From 786f1531c9fa3562f66b9446f98df7210c4f0a23 Mon Sep 17 00:00:00 2001 From: George Carlson Date: Sun, 5 Jun 2022 12:20:35 -0500 Subject: [PATCH 1/3] Seperate Chromium and Edge UI's Seperate the chromium and EDGE UI's into lorca.NewChromium and lorca.NewEdge so that the user can choose to use Edge instead of chrome when they have booth installed. Also, do not automatically add in all the default arguments. Instead make these public through AdditionalEdgeArgs and AdditionalChromiumArgs so that the user is not forced to use all the default arguments. --- locate_chromium.go | 62 ++++++++++++++++++++++++++++++++++++++++ locate_edge.go | 49 ++++++++++++++++++++++++++++++++ ui_chromium.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++ ui_edge.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 locate_chromium.go create mode 100644 locate_edge.go create mode 100644 ui_chromium.go create mode 100644 ui_edge.go diff --git a/locate_chromium.go b/locate_chromium.go new file mode 100644 index 0000000..b0dcafb --- /dev/null +++ b/locate_chromium.go @@ -0,0 +1,62 @@ +package lorca + +import ( + "os" + "runtime" +) + +// ChromeExecutable returns a string which points to the preferred Chromium +// executable file. +var ChromiumExecutable = LocateChromium + +// LocateChromium returns a path to the Chromium binary, or an empty string if +// Chromium installation is not found. +func LocateChromium() string { + + // If env variable "LORCACHROME" specified and it exists + if path, ok := os.LookupEnv("LORCACHROMIUM"); ok { + if _, err := os.Stat(path); err == nil { + return path + } + } + + var paths []string + switch runtime.GOOS { + case "darwin": + paths = []string{ + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary", + "/Applications/Chromium.app/Contents/MacOS/Chromium", + "/usr/bin/google-chrome-stable", + "/usr/bin/google-chrome", + "/usr/bin/chromium", + "/usr/bin/chromium-browser", + } + case "windows": + paths = []string{ + os.Getenv("LocalAppData") + "/Google/Chrome/Application/chrome.exe", + os.Getenv("ProgramFiles") + "/Google/Chrome/Application/chrome.exe", + os.Getenv("ProgramFiles(x86)") + "/Google/Chrome/Application/chrome.exe", + os.Getenv("LocalAppData") + "/Chromium/Application/chrome.exe", + os.Getenv("ProgramFiles") + "/Chromium/Application/chrome.exe", + os.Getenv("ProgramFiles(x86)") + "/Chromium/Application/chrome.exe", + } + default: + paths = []string{ + "/usr/bin/google-chrome-stable", + "/usr/bin/google-chrome", + "/usr/bin/chromium", + "/usr/bin/chromium-browser", + "/snap/bin/chromium", + } + } + + for _, path := range paths { + if _, err := os.Stat(path); os.IsNotExist(err) { + continue + } + return path + } + return "" +} + diff --git a/locate_edge.go b/locate_edge.go new file mode 100644 index 0000000..fda19d9 --- /dev/null +++ b/locate_edge.go @@ -0,0 +1,49 @@ +package lorca + +import ( + "os" + "runtime" +) + +// EdgeExecutable returns a string which points to the preferred Edge +// executable file. +var EdgeExecutable = LocateEdge + +// LocateEdge returns a path to the Edge binary, or an empty string if +// Edge installation is not found. +func LocateEdge() string { + + // If env variable "LORCACHROME" specified and it exists + if path, ok := os.LookupEnv("LORCAEDGE"); ok { + if _, err := os.Stat(path); err == nil { + return path + } + } + + var paths []string + switch runtime.GOOS { + case "darwin": + paths = []string{ + "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge", + } + case "windows": + paths = []string{ + os.Getenv("ProgramFiles") + "/Microsoft/Edge/Application/msedge.exe", + os.Getenv("ProgramFiles(x86)") + "/Microsoft/Edge/Application/msedge.exe", + } + default: + paths = []string{ + "/usr/bin/microsoft-edge-stable", + "/usr/bin/microsoft-edge", + } + } + + for _, path := range paths { + if _, err := os.Stat(path); os.IsNotExist(err) { + continue + } + return path + } + return "" +} + diff --git a/ui_chromium.go b/ui_chromium.go new file mode 100644 index 0000000..97f0b8e --- /dev/null +++ b/ui_chromium.go @@ -0,0 +1,70 @@ +package lorca + +import ( + "fmt" + "io/ioutil" +) + +var AdditionalChromiumArgs = []string{ + "--disable-background-networking", + "--disable-background-timer-throttling", + "--disable-backgrounding-occluded-windows", + "--disable-breakpad", + "--disable-client-side-phishing-detection", + "--disable-default-apps", + "--disable-dev-shm-usage", + "--disable-extensions", + "--disable-features=site-per-process", + "--disable-hang-monitor", + "--disable-ipc-flooding-protection", + "--disable-popup-blocking", + "--disable-prompt-on-repost", + "--disable-renderer-backgrounding", + "--disable-sync", + "--disable-translate", + "--disable-windows10-custom-titlebar", + "--metrics-recording-only", + "--no-first-run", + "--no-default-browser-check", + "--safebrowsing-disable-auto-update", + "--password-store=basic", + "--use-mock-keychain", +} + +// New returns a new HTML5 UI for the given URL, user profile directory, window +// size and other options passed to the browser engine. If URL is an empty +// string - a blank page is displayed. If user profile directory is an empty +// string - a temporary directory is created and it will be removed on +// ui.Close(). You might want to use "--headless" custom CLI argument to test +// your UI code. +func NewChromium(url, dir string, width, height int, additionalArgs ...string) (UI, error) { + if url == "" { + url = "data:text/html," + } + tmpDir := "" + if dir == "" { + name, err := ioutil.TempDir("", "lorca") + if err != nil { + return nil, err + } + dir, tmpDir = name, name + } + args := append([]string{}, fmt.Sprintf("--app=%s", url)) + args = append(args, fmt.Sprintf("--user-data-dir=%s", dir)) + args = append(args, fmt.Sprintf("--window-size=%d,%d", width, height)) + args = append(args, additionalArgs...) + args = append(args, "--remote-debugging-port=0") + + chrome, err := newChromeWithArgs(ChromiumExecutable(), args...) + done := make(chan struct{}) + if err != nil { + return nil, err + } + + go func() { + chrome.cmd.Wait() + close(done) + }() + return &ui{chrome: chrome, done: done, tmpDir: tmpDir}, nil +} + diff --git a/ui_edge.go b/ui_edge.go new file mode 100644 index 0000000..271b6aa --- /dev/null +++ b/ui_edge.go @@ -0,0 +1,70 @@ +package lorca + +import ( + "fmt" + "io/ioutil" +) + +var AdditionalEdgeArgs = []string{ + "--disable-background-networking", + "--disable-background-timer-throttling", + "--disable-backgrounding-occluded-windows", + "--disable-breakpad", + "--disable-client-side-phishing-detection", + "--disable-default-apps", + "--disable-dev-shm-usage", + "--disable-extensions", + "--disable-features=site-per-process", + "--disable-hang-monitor", + "--disable-ipc-flooding-protection", + "--disable-popup-blocking", + "--disable-prompt-on-repost", + "--disable-renderer-backgrounding", + "--disable-sync", + "--disable-translate", + "--disable-windows10-custom-titlebar", + "--metrics-recording-only", + "--no-first-run", + "--no-default-browser-check", + "--safebrowsing-disable-auto-update", + "--password-store=basic", + "--use-mock-keychain", +} + +// New returns a new HTML5 UI for the given URL, user profile directory, window +// size and other options passed to the browser engine. If URL is an empty +// string - a blank page is displayed. If user profile directory is an empty +// string - a temporary directory is created and it will be removed on +// ui.Close(). You might want to use "--headless" custom CLI argument to test +// your UI code. +func NewEdge(url, dir string, width, height int, additionalArgs ...string) (UI, error) { + if url == "" { + url = "data:text/html," + } + tmpDir := "" + if dir == "" { + name, err := ioutil.TempDir("", "lorca") + if err != nil { + return nil, err + } + dir, tmpDir = name, name + } + args := append([]string{}, fmt.Sprintf("--app=%s", url)) + args = append(args, fmt.Sprintf("--user-data-dir=%s", dir)) + args = append(args, fmt.Sprintf("--window-size=%d,%d", width, height)) + args = append(args, additionalArgs...) + args = append(args, "--remote-debugging-port=0") + + chrome, err := newChromeWithArgs(EdgeExecutable(), args...) + done := make(chan struct{}) + if err != nil { + return nil, err + } + + go func() { + chrome.cmd.Wait() + close(done) + }() + return &ui{chrome: chrome, done: done, tmpDir: tmpDir}, nil +} + From 6a82ef7d9c6ab23711b643133123893809aaaf62 Mon Sep 17 00:00:00 2001 From: George Carlson Date: Sun, 5 Jun 2022 23:52:43 -0500 Subject: [PATCH 2/3] Split Chromium and Google Chrome Split Chromium and Google Chrome because we may want to use them indepedetly. --- locate_chromium.go | 11 +----- locate_google_chrome.go | 52 +++++++++++++++++++++++++ ui_chromium.go | 70 ---------------------------------- ui_edge.go | 70 ---------------------------------- ui_html5.go | 84 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 150 deletions(-) create mode 100644 locate_google_chrome.go delete mode 100644 ui_chromium.go delete mode 100644 ui_edge.go create mode 100644 ui_html5.go diff --git a/locate_chromium.go b/locate_chromium.go index b0dcafb..93f6562 100644 --- a/locate_chromium.go +++ b/locate_chromium.go @@ -10,7 +10,7 @@ import ( var ChromiumExecutable = LocateChromium // LocateChromium returns a path to the Chromium binary, or an empty string if -// Chromium installation is not found. +// the Chromium installation is not found. func LocateChromium() string { // If env variable "LORCACHROME" specified and it exists @@ -24,27 +24,18 @@ func LocateChromium() string { switch runtime.GOOS { case "darwin": paths = []string{ - "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", - "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary", "/Applications/Chromium.app/Contents/MacOS/Chromium", - "/usr/bin/google-chrome-stable", - "/usr/bin/google-chrome", "/usr/bin/chromium", "/usr/bin/chromium-browser", } case "windows": paths = []string{ - os.Getenv("LocalAppData") + "/Google/Chrome/Application/chrome.exe", - os.Getenv("ProgramFiles") + "/Google/Chrome/Application/chrome.exe", - os.Getenv("ProgramFiles(x86)") + "/Google/Chrome/Application/chrome.exe", os.Getenv("LocalAppData") + "/Chromium/Application/chrome.exe", os.Getenv("ProgramFiles") + "/Chromium/Application/chrome.exe", os.Getenv("ProgramFiles(x86)") + "/Chromium/Application/chrome.exe", } default: paths = []string{ - "/usr/bin/google-chrome-stable", - "/usr/bin/google-chrome", "/usr/bin/chromium", "/usr/bin/chromium-browser", "/snap/bin/chromium", diff --git a/locate_google_chrome.go b/locate_google_chrome.go new file mode 100644 index 0000000..abcc29e --- /dev/null +++ b/locate_google_chrome.go @@ -0,0 +1,52 @@ +package lorca + +import ( + "os" + "runtime" +) + +// GoogleChromeExecutable returns a string which points to the preferred +// Google Chrome executable file. +var GoogleChromeExecutable = LocateGoogleChrome + +// LocateGoogleChrome returns a path to the Google Chrome binary, or an empty +// string if the Google Chrome installation is not found. +func LocateGoogleChrome() string { + + // If env variable "LORCACHROME" specified and it exists + if path, ok := os.LookupEnv("LORCAGOOGLECHROME"); ok { + if _, err := os.Stat(path); err == nil { + return path + } + } + + var paths []string + switch runtime.GOOS { + case "darwin": + paths = []string{ + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary", + "/usr/bin/google-chrome-stable", + "/usr/bin/google-chrome", + } + case "windows": + paths = []string{ + os.Getenv("LocalAppData") + "/Google/Chrome/Application/chrome.exe", + os.Getenv("ProgramFiles") + "/Google/Chrome/Application/chrome.exe", + os.Getenv("ProgramFiles(x86)") + "/Google/Chrome/Application/chrome.exe", + } + default: + paths = []string{ + "/usr/bin/google-chrome-stable", + "/usr/bin/google-chrome", + } + } + + for _, path := range paths { + if _, err := os.Stat(path); os.IsNotExist(err) { + continue + } + return path + } + return "" +} diff --git a/ui_chromium.go b/ui_chromium.go deleted file mode 100644 index 97f0b8e..0000000 --- a/ui_chromium.go +++ /dev/null @@ -1,70 +0,0 @@ -package lorca - -import ( - "fmt" - "io/ioutil" -) - -var AdditionalChromiumArgs = []string{ - "--disable-background-networking", - "--disable-background-timer-throttling", - "--disable-backgrounding-occluded-windows", - "--disable-breakpad", - "--disable-client-side-phishing-detection", - "--disable-default-apps", - "--disable-dev-shm-usage", - "--disable-extensions", - "--disable-features=site-per-process", - "--disable-hang-monitor", - "--disable-ipc-flooding-protection", - "--disable-popup-blocking", - "--disable-prompt-on-repost", - "--disable-renderer-backgrounding", - "--disable-sync", - "--disable-translate", - "--disable-windows10-custom-titlebar", - "--metrics-recording-only", - "--no-first-run", - "--no-default-browser-check", - "--safebrowsing-disable-auto-update", - "--password-store=basic", - "--use-mock-keychain", -} - -// New returns a new HTML5 UI for the given URL, user profile directory, window -// size and other options passed to the browser engine. If URL is an empty -// string - a blank page is displayed. If user profile directory is an empty -// string - a temporary directory is created and it will be removed on -// ui.Close(). You might want to use "--headless" custom CLI argument to test -// your UI code. -func NewChromium(url, dir string, width, height int, additionalArgs ...string) (UI, error) { - if url == "" { - url = "data:text/html," - } - tmpDir := "" - if dir == "" { - name, err := ioutil.TempDir("", "lorca") - if err != nil { - return nil, err - } - dir, tmpDir = name, name - } - args := append([]string{}, fmt.Sprintf("--app=%s", url)) - args = append(args, fmt.Sprintf("--user-data-dir=%s", dir)) - args = append(args, fmt.Sprintf("--window-size=%d,%d", width, height)) - args = append(args, additionalArgs...) - args = append(args, "--remote-debugging-port=0") - - chrome, err := newChromeWithArgs(ChromiumExecutable(), args...) - done := make(chan struct{}) - if err != nil { - return nil, err - } - - go func() { - chrome.cmd.Wait() - close(done) - }() - return &ui{chrome: chrome, done: done, tmpDir: tmpDir}, nil -} - diff --git a/ui_edge.go b/ui_edge.go deleted file mode 100644 index 271b6aa..0000000 --- a/ui_edge.go +++ /dev/null @@ -1,70 +0,0 @@ -package lorca - -import ( - "fmt" - "io/ioutil" -) - -var AdditionalEdgeArgs = []string{ - "--disable-background-networking", - "--disable-background-timer-throttling", - "--disable-backgrounding-occluded-windows", - "--disable-breakpad", - "--disable-client-side-phishing-detection", - "--disable-default-apps", - "--disable-dev-shm-usage", - "--disable-extensions", - "--disable-features=site-per-process", - "--disable-hang-monitor", - "--disable-ipc-flooding-protection", - "--disable-popup-blocking", - "--disable-prompt-on-repost", - "--disable-renderer-backgrounding", - "--disable-sync", - "--disable-translate", - "--disable-windows10-custom-titlebar", - "--metrics-recording-only", - "--no-first-run", - "--no-default-browser-check", - "--safebrowsing-disable-auto-update", - "--password-store=basic", - "--use-mock-keychain", -} - -// New returns a new HTML5 UI for the given URL, user profile directory, window -// size and other options passed to the browser engine. If URL is an empty -// string - a blank page is displayed. If user profile directory is an empty -// string - a temporary directory is created and it will be removed on -// ui.Close(). You might want to use "--headless" custom CLI argument to test -// your UI code. -func NewEdge(url, dir string, width, height int, additionalArgs ...string) (UI, error) { - if url == "" { - url = "data:text/html," - } - tmpDir := "" - if dir == "" { - name, err := ioutil.TempDir("", "lorca") - if err != nil { - return nil, err - } - dir, tmpDir = name, name - } - args := append([]string{}, fmt.Sprintf("--app=%s", url)) - args = append(args, fmt.Sprintf("--user-data-dir=%s", dir)) - args = append(args, fmt.Sprintf("--window-size=%d,%d", width, height)) - args = append(args, additionalArgs...) - args = append(args, "--remote-debugging-port=0") - - chrome, err := newChromeWithArgs(EdgeExecutable(), args...) - done := make(chan struct{}) - if err != nil { - return nil, err - } - - go func() { - chrome.cmd.Wait() - close(done) - }() - return &ui{chrome: chrome, done: done, tmpDir: tmpDir}, nil -} - diff --git a/ui_html5.go b/ui_html5.go new file mode 100644 index 0000000..b83aec7 --- /dev/null +++ b/ui_html5.go @@ -0,0 +1,84 @@ +package lorca + +import ( + "fmt" + "io/ioutil" +) + +var AdditionalChromiumArgs = []string{ + "--disable-background-networking", + "--disable-background-timer-throttling", + "--disable-backgrounding-occluded-windows", + "--disable-breakpad", + "--disable-client-side-phishing-detection", + "--disable-default-apps", + "--disable-dev-shm-usage", + "--disable-extensions", + "--disable-features=site-per-process", + "--disable-hang-monitor", + "--disable-ipc-flooding-protection", + "--disable-popup-blocking", + "--disable-prompt-on-repost", + "--disable-renderer-backgrounding", + "--disable-sync", + "--disable-translate", + "--disable-windows10-custom-titlebar", + "--metrics-recording-only", + "--no-first-run", + "--no-default-browser-check", + "--safebrowsing-disable-auto-update", + "--password-store=basic", + "--use-mock-keychain", +} + +// NewHtml5 returns a new HTML5 UI for the given executable URL, user profile +// directory, window size and other options passed to the browser engine. If +// URL is an empty string - a blank page is displayed. If user profile directory +// is an empty string - a temporary directory is created and it will be removed on +// ui.Close(). You might want to use "--headless" custom CLI argument to test +// your UI code. +func NewHtml5(executable, url, dir string, width, height int, additionalArgs ...string) (UI, error) { + if url == "" { + url = "data:text/html," + } + tmpDir := "" + if dir == "" { + name, err := ioutil.TempDir("", "lorca") + if err != nil { + return nil, err + } + dir, tmpDir = name, name + } + args := append([]string{}, fmt.Sprintf("--app=%s", url)) + args = append(args, fmt.Sprintf("--user-data-dir=%s", dir)) + args = append(args, fmt.Sprintf("--window-size=%d,%d", width, height)) + args = append(args, additionalArgs...) + args = append(args, "--remote-debugging-port=0") + + chrome, err := newChromeWithArgs(ChromiumExecutable(), args...) + done := make(chan struct{}) + if err != nil { + return nil, err + } + + go func() { + chrome.cmd.Wait() + close(done) + }() + return &ui{chrome: chrome, done: done, tmpDir: tmpDir}, nil +} + +// NewChromium returns a new Chromium HTML5 UI. +func NewChromium(url, dir string, width, height int, additionalArgs ...string) (UI, error) { + return NewHtml5(ChromiumExecutable(), url, dir, width, height, additionalArgs...) +} + +// NewEdge returns a new Edge HTML5 UI. +func NewEdge(url, dir string, width, height int, additionalArgs ...string) (UI, error) { + return NewHtml5(EdgeExecutable(), url, dir, width, height, additionalArgs...) +} + +// NewGoogleChrome returns a new Google Chrome HTML5 UI. +func NewGoogleChrome(url, dir string, width, height int, additionalArgs ...string) (UI, error) { + return NewHtml5(GoogleChromeExecutable(), url, dir, width, height, additionalArgs...) +} From 7fd3fefe5af0bd5665d4899106289b48fdce7bb3 Mon Sep 17 00:00:00 2001 From: George Carlson Date: Sun, 5 Jun 2022 23:57:27 -0500 Subject: [PATCH 3/3] Fix UI HTML5 Constructor Fix the UI HTML5 constructor. It was supposed to leverage the executable parameter instead of being hardcoded to be the chromium executable. --- ui_html5.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui_html5.go b/ui_html5.go index b83aec7..ac5a5ce 100644 --- a/ui_html5.go +++ b/ui_html5.go @@ -55,7 +55,7 @@ func NewHtml5(executable, url, dir string, width, height int, additionalArgs ... args = append(args, additionalArgs...) args = append(args, "--remote-debugging-port=0") - chrome, err := newChromeWithArgs(ChromiumExecutable(), args...) + chrome, err := newChromeWithArgs(executable, args...) done := make(chan struct{}) if err != nil { return nil, err