From 8d042b20bed670144339940553f3c90dbfb8f05c Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Thu, 6 Jun 2019 22:37:44 +0200 Subject: [PATCH] Extensions break on path change (Issue portapps/firefox-portable#2) --- go.mod | 3 +++ go.sum | 4 +++ main.go | 62 ++++++++++++++++++++++++++++++++++++++++++ mozlz4.go | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+) create mode 100644 mozlz4.go diff --git a/go.mod b/go.mod index f035d4c..1dc8d27 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,9 @@ module github.com/portapps/waterfox-portable go 1.12 require ( + github.com/Jeffail/gabs v1.4.0 github.com/kevinburke/go-bindata v3.13.0+incompatible + github.com/pierrec/lz4 v2.0.5+incompatible + github.com/pkg/errors v0.8.1 github.com/portapps/portapps v1.24.1 ) diff --git a/go.sum b/go.sum index 46575df..468d85d 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= +github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= @@ -10,6 +12,8 @@ github.com/kevinburke/go-bindata v3.13.0+incompatible h1:hThDhUBH4KjTyhfXfOgacEP github.com/kevinburke/go-bindata v3.13.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/portapps/portapps v1.24.1 h1:IImx122R3hlxS3NO4+jv1Bl5Lwx6tfSJHON9V3lBirU= diff --git a/main.go b/main.go index c60916c..ab033b7 100644 --- a/main.go +++ b/main.go @@ -7,12 +7,15 @@ package main import ( "fmt" "io/ioutil" + "net/url" "os" "path" "strconv" "strings" + "github.com/Jeffail/gabs" _ "github.com/kevinburke/go-bindata" + "github.com/pkg/errors" . "github.com/portapps/portapps" "github.com/portapps/portapps/pkg/dialog" "github.com/portapps/portapps/pkg/mutex" @@ -107,6 +110,11 @@ lockPref("toolkit.crashreporter.enabled", false); Log.Fatal().Err(err).Msg("Cannot write portapps.cfg") } + // Fix extensions path + if err := updateAddonStartup(profileFolder); err != nil { + Log.Error().Err(err).Msg("Cannot fix extensions path") + } + // Set env vars crashreporterFolder := utl.CreateFolder(app.DataPath, "crashreporter") pluginsFolder := utl.CreateFolder(app.DataPath, "plugins") @@ -168,3 +176,57 @@ lockPref("toolkit.crashreporter.enabled", false); app.Launch(os.Args[1:]) } + +func updateAddonStartup(profileFolder string) error { + asLz4 := path.Join(profileFolder, "addonStartup.json.lz4") + if !utl.Exists(asLz4) { + return nil + } + + decAsLz4, err := mozLz4Decompress(asLz4) + if err != nil { + return err + } + + jsonAs, err := gabs.ParseJSON(decAsLz4) + if err != nil { + return err + } + + if err := updateAddons("app-global", utl.PathJoin(profileFolder, "extensions"), jsonAs); err != nil { + return err + } + if err := updateAddons("app-profile", utl.PathJoin(profileFolder, "extensions"), jsonAs); err != nil { + return err + } + if err := updateAddons("app-system-defaults", utl.PathJoin(app.AppPath, "browser", "features"), jsonAs); err != nil { + return err + } + Log.Debug().Msgf("Updated addonStartup.json: %s", jsonAs.String()) + + encAsLz4, err := mozLz4Compress(jsonAs.Bytes()) + if err != nil { + return err + } + + return ioutil.WriteFile(asLz4, encAsLz4, 0644) +} + +func updateAddons(field string, basePath string, container *gabs.Container) error { + if _, ok := container.Search(field, "path").Data().(string); !ok { + return nil + } + if _, err := container.Set(basePath, field, "path"); err != nil { + return errors.Wrap(err, fmt.Sprintf("couldn't set %s.path", field)) + } + + addons, _ := container.S(field, "addons").ChildrenMap() + for key, addon := range addons { + _, err := addon.Set(fmt.Sprintf("jar:file:///%s/%s.xpi!/", utl.FormatUnixPath(basePath), url.PathEscape(key)), "rootURI") + if err != nil { + return errors.Wrap(err, fmt.Sprintf("couldn't set %s %s.rootURI", field, key)) + } + } + + return nil +} diff --git a/mozlz4.go b/mozlz4.go new file mode 100644 index 0000000..ffa57ef --- /dev/null +++ b/mozlz4.go @@ -0,0 +1,81 @@ +package main + +import ( + "bytes" + "encoding/binary" + "io/ioutil" + "os" + + "github.com/pierrec/lz4" + "github.com/pkg/errors" +) + +const ( + mozLz4Header = "mozLz40\x00" + mozLz4DecompSize = 4 +) + +func mozLz4Decompress(filename string) ([]byte, error) { + file, err := os.Open(filename) + if err != nil { + return nil, err + } + + header := make([]byte, len(mozLz4Header)) + _, err = file.Read(header) + if err != nil { + return nil, errors.Wrap(err, "couldn't read header") + } + if string(header) != mozLz4Header { + return nil, errors.New("no mozLz4 header") + } + + var size uint32 + err = binary.Read(file, binary.LittleEndian, &size) + if err != nil { + return nil, errors.Wrap(err, "couldn't read size") + } + + src, err := ioutil.ReadAll(file) + if err != nil { + return nil, errors.Wrap(err, "couldn't read compressed data") + } + + out := make([]byte, size) + _, err = lz4.UncompressBlock(src, out) + if err != nil { + return nil, errors.Wrap(err, "couldn't decompress data") + } + + return out, nil +} + +func mozLz4Compress(src []byte) ([]byte, error) { + out := new(bytes.Buffer) + + _, err := out.Write([]byte(mozLz4Header)) + if err != nil { + return nil, errors.Wrap(err, "couldn't write header") + } + + err = binary.Write(out, binary.LittleEndian, uint32(len(src))) + if err != nil { + return nil, errors.Wrap(err, "couldn't encode length") + } + + buf := make([]byte, 10*len(src)) + sz, err := lz4.CompressBlockHC(src, buf, -1) + if err != nil { + return nil, errors.Wrap(err, "couldn't compress data") + } + if sz == 0 { + return nil, errors.New("data incompressible") + } + + _, err = out.Write(buf[:sz]) + if err != nil { + return nil, errors.Wrap(err, "couldn't write compressed data") + } + + return out.Bytes(), nil +}