diff --git a/i2pbrowser/main.go b/i2pbrowser/main.go index 92f1f24..90bba18 100644 --- a/i2pbrowser/main.go +++ b/i2pbrowser/main.go @@ -11,6 +11,7 @@ import ( var ( u = flag.Bool("usability", false, "Launch in usability mode") + a = flag.Bool("application", false, "Launch in app mode") d = flag.String("directory", defaultDir(), "Directory to store profiles in") ) @@ -36,6 +37,11 @@ func main() { if len(flag.Args()) > 0 { url = flag.Arg(0) } + application := *a + if application { + goi2pbrowser.BrowseApp(*d, url) + return + } usability := *u switch usability { case true: diff --git a/run.go b/run.go index e67c3c0..ce5f71a 100644 --- a/run.go +++ b/run.go @@ -47,3 +47,22 @@ func BrowseUsability(profileDir, url string) { defer FIREFOX.Close() <-FIREFOX.Done() } + +// BrowseApp launches a Firefox browser configured to use I2P and waits for it to exit. +// The profile is in "Usability" mode +func BrowseApp(profileDir, url string) { + var profilePath string + var err error + profilePath, err = UnpackApp(profileDir) + if err != nil { + log.Println(err) + return + } + FIREFOX, ERROR := fcw.BasicFirefox(profilePath, false, url) + if ERROR != nil { + log.Println(ERROR) + return + } + defer FIREFOX.Close() + <-FIREFOX.Done() +} diff --git a/unembed.go b/unembed.go index 1094019..06194bf 100644 --- a/unembed.go +++ b/unembed.go @@ -5,6 +5,7 @@ import ( "log" "os" "path/filepath" + "strings" "github.com/artdarek/go-unzip/pkg/unzip" ) @@ -20,10 +21,7 @@ func existsAlready(profileDir string) bool { // path to the profile and possibly, an error if something goes wrong. If everything // works, the error will be nil func UnpackBase(profileDir string) (string, error) { - if existsAlready(profileDir) { - log.Println(profileDir, "exists already") - return filepath.Join(profileDir, "i2p.firefox.base.profile"), nil - } + log.Println(profileDir, "exists already") os.MkdirAll(filepath.Dir(profileDir), 0755) zipFile := filepath.Join(filepath.Dir(profileDir), "i2p.firefox.base.profile.zip") err := ioutil.WriteFile(zipFile, BaseProfile, 0644) @@ -42,10 +40,7 @@ func UnpackBase(profileDir string) (string, error) { // path to the profile and possibly, an error if something goes wrong. If everything // works, the error will be nil func UnpackUsability(profileDir string) (string, error) { - if existsAlready(profileDir) { - log.Println(profileDir, "exists already") - return filepath.Join(profileDir, "i2p.firefox.usability.profile"), nil - } + log.Println(profileDir, "exists already") os.MkdirAll(filepath.Dir(profileDir), 0755) zipFile := filepath.Join(filepath.Dir(profileDir), "i2p.firefox.usability.profile.zip") err := ioutil.WriteFile(zipFile, UsabilityProfile, 0644) @@ -59,3 +54,116 @@ func UnpackUsability(profileDir string) (string, error) { } return filepath.Join(profileDir, "i2p.firefox.usability.profile"), nil } + +// UnpackApp unpacks a "App" mode profile into the "profileDir" and returns the +// path to the profile and possibly, an error if something goes wrong. If everything +// works, the error will be nil +func UnpackApp(profileDir string) (string, error) { + log.Println(profileDir, "exists already") + os.MkdirAll(filepath.Dir(profileDir), 0755) + zipFile := filepath.Join(filepath.Dir(profileDir), "i2p.firefox.usability.profile.zip") + err := ioutil.WriteFile(zipFile, UsabilityProfile, 0644) + if err != nil { + return filepath.Join(profileDir, "i2p.firefox.app.profile"), err + } + uz := unzip.New() + _, err = uz.Extract(zipFile, profileDir) + unzippedFiles := strings.Replace(filepath.Join(profileDir, "i2p.firefox.usability.profile.zip"), ".zip", "", 1) + if !existsAlready(filepath.Join(profileDir, "i2p.firefox.app.profile")) { + if err = os.Rename(unzippedFiles, filepath.Join(profileDir, "i2p.firefox.app.profile")); err != nil { + return filepath.Join(profileDir, "i2p.firefox.app.profile"), err + } + } + if err := os.MkdirAll(filepath.Join(profileDir, "i2p.firefox.app.profile", "chrome"), 0755); err != nil { + return filepath.Join(profileDir, "i2p.firefox.app.profile"), err + } + if err := ForceUserChromeCSS(filepath.Join(profileDir, "i2p.firefox.app.profile", "chrome", "userChrome.css")); err != nil { + return filepath.Join(profileDir, "i2p.firefox.app.profile"), err + } + if err := AppifyUserJS(filepath.Join(profileDir, "i2p.firefox.app.profile", "user-overrides.js")); err != nil { + return filepath.Join(profileDir, "i2p.firefox.app.profile"), err + } + if err := AppifyUserJS(filepath.Join(profileDir, "i2p.firefox.app.profile", "user.js")); err != nil { + return filepath.Join(profileDir, "i2p.firefox.app.profile"), err + } + if err := AppifyUserJS(filepath.Join(profileDir, "i2p.firefox.app.profile", "prefs.js")); err != nil { + return filepath.Join(profileDir, "i2p.firefox.app.profile"), err + } + return filepath.Join(profileDir, "i2p.firefox.app.profile"), nil +} + +func AppifyUserJS(profile string) error { + content, err := ioutil.ReadFile(profile) + if err != nil { + return err + } + lines := strings.Split(string(content), "\n") + for i, line := range lines { + if strings.Contains(line, "toolkit.legacyUserProfileCustomizations.stylesheets\"") { + if strings.Contains(line, "true") { + return nil + } else { + line = strings.Replace(line, "false", "true", 1) + } + } + lines[i] = line + } + out := strings.Join(lines, "\n") + if err := ioutil.WriteFile(profile, []byte(out), 0644); err != nil { + return err + } + return nil +} + +func ForceUserChromeCSS(profile string) error { + var userChrome = `@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); + +/* only needed once */ + +@namespace html url("http://www.w3.org/1999/xhtml"); +#PersonalToolbar, +#PanelUI-Button, +#PanelUI-menu-button, +#star-button, +#forward-button, +#home-button, +#bookmarks-toolbar-button, +#library-button, +#sidebar-button, +#pocket-button, +#fxa-toolbar-menu-button, +#reader-mode-button, +#identity-icon { + visibility: collapse; +} + +#urlbar-background { + background-color: black !important; +} + + +/* Remove back button circle */ + +#back-button:not(:hover), +#back-button:not(:hover)>.toolbarbutton-icon { + background: transparent !important; + border: none !important; + box-shadow: none !important; +} + +#back-button:hover, +#back-button:hover>.toolbarbutton-icon { + border: none !important; + border-radius: 2px !important; +} + +#urlbar-container, +#nav-bar { + visibility: collapse !important +} +` + if err := ioutil.WriteFile(profile, []byte(userChrome), 0644); err != nil { + return err + } + return nil +}