99import qz .common .Constants ;
1010import qz .installer .Installer ;
1111import qz .installer .apps .ChromiumPolicyInstaller ;
12+ import qz .installer .apps .locator .AppAlias ;
13+ import qz .installer .apps .locator .AppInfo ;
14+ import qz .installer .apps .locator .AppLocator ;
1215import qz .utils .FileUtilities ;
1316
1417import java .io .BufferedWriter ;
1720import java .io .IOException ;
1821import java .nio .charset .StandardCharsets ;
1922import java .nio .file .Files ;
23+ import java .nio .file .Path ;
2024import java .nio .file .Paths ;
25+ import java .util .HashSet ;
26+ import java .util .Locale ;
2127
2228public class LinuxChromiumPolicyInstaller extends ChromiumPolicyInstaller {
2329 private static final Logger log = LogManager .getLogger (LinuxChromiumPolicyInstaller .class );
2430
25- private static final String [] MANAGED_POLICY_PATH_PATTERNS = {
26- "/etc/chromium/policies/managed/%s.json" ,
27- "/etc/opt/chrome/policies/managed/%s.json" ,
28- "/etc/opt/edge/policies/managed/%s.json"
29- };
31+ private static final String MANAGED_POLICY_PATH_PATTERN = "%s/policies/managed/%s.json" ;
32+
33+ public static void main (String ... args ) {
34+ LinuxChromiumPolicyInstaller installer = new LinuxChromiumPolicyInstaller ();
35+ installer .install (Installer .PrivilegeLevel .SYSTEM , "SafeBrowsingEnabled" , "true" );
36+ installer .uninstall (Installer .PrivilegeLevel .SYSTEM , "SafeBrowsingEnabled" , "true" );
37+ }
38+
39+ // TODO:
40+ // 1. Decide whether we loop over all apps or all found apps
41+ // 2. Decide if we should use a symlink to a JSON file in /opt/qz-tray or if we should
42+ // write each file individually
43+ // 3. JSON should support boolean/int/string and maybe array
3044
3145 @ Override
3246 public boolean install (Installer .PrivilegeLevel scope , String policyName , String ... values ) {
3347 if (scope != Installer .PrivilegeLevel .SYSTEM ) {
48+ // TODO: Remove this if Linux user-level policies can be confirmed
3449 log .info ("Skipping installation of Chromium policy {}, not supported as PrivilegeLevel {}" , policyName , scope );
3550 return false ;
3651 }
37- for (String pattern : MANAGED_POLICY_PATH_PATTERNS ) {
38- // Chromium policy, e.g. /etc/chromium/policies/managed/qz-tray.json
39- File location = Paths .get (String .format (pattern , Constants .PROPS_FILE )).toFile ();
40- log .info ("Installing Chromium policy {} {}..." , policyName , location );
41-
42-
43- // Build JSON array (e.g. { "URLAllowlist": [ "qz://*"] } )
44- JSONObject jsonPolicy = new JSONObject ();
45- JSONArray jsonArray = new JSONArray ();
46-
47- try {
48- // Ensure parent is writable
49- FileUtilities .setPermissionsParentally (Files .createDirectories (location .getParentFile ().toPath ()), false );
50-
51- // Populate object
52- if (location .exists ()) {
53- jsonPolicy = new JSONObject (FileUtils .readFileToString (location , StandardCharsets .UTF_8 ));
54- JSONArray found = jsonPolicy .optJSONArray (policyName );
55- if (found == null ) {
56- log .info ("Chromium policy found {} but without entry for {}, we'll add it" , location , policyName );
57- } else {
58- jsonArray = found ;
59- }
52+ boolean success = true ;
53+ for (AppInfo appInfo : AppLocator .getInstance ().locate (AppAlias .CHROMIUM )) {
54+ if (!writeJson (calculatePolicyFile (scope , appInfo ), policyName , values )) {
55+ success = false ;
56+ }
57+ }
58+ return success ;
59+ }
60+
61+ private static File calculatePolicyFile (Installer .PrivilegeLevel scope , AppInfo appInfo ) {
62+ Path prefix ;
63+ switch (scope ) {
64+ case SYSTEM :
65+ prefix = Paths .get ("/" );
66+ switch (appInfo .getName (true )) {
67+ case "chromium" :
68+ // OS-provided are stored in /etc/<name>
69+ prefix = prefix .resolve ("etc" );
70+ break ;
71+ default :
72+ // 3rd-party provided are stored in /etc/opt/<name>
73+ prefix = prefix .resolve ("etc" ).resolve ("opt" );
6074 }
75+ break ;
76+ case USER :
77+ // ~/.config
78+ prefix = Paths .get (System .getProperty ("user.home" )).resolve (".config" );
79+ break ;
80+ default :
81+ throw new UnsupportedOperationException (String .format ("Scope %s is not yet supported" , scope ));
82+ }
83+ prefix = prefix .resolve (appInfo .getName (true ).toLowerCase (Locale .ENGLISH ));
84+ String policyFile = String .format (MANAGED_POLICY_PATH_PATTERN , prefix , Constants .PROPS_FILE );
85+ return new File (policyFile );
86+ }
87+
88+ private static boolean writeJson (File location , String policyName , String ... values ) {
89+ // Chromium policy, e.g. /etc/chromium/policies/managed/qz-tray.json
90+ ///File location = Paths.get(String.format(pattern, Constants.PROPS_FILE)).toFile();
91+ log .info ("Installing Chromium policy {} {}..." , policyName , location );
6192
62- value :
63- for (String value : values ) {
64- for (int i = 0 ; i < jsonArray .length (); i ++) {
65- if (jsonArray .optString (i , "" ).equals (value )) {
66- log .info ("Chromium policy {} '{}' already exists at location {}, skipping" , policyName , value , location );
67- continue value ;
68- }
93+
94+ // Build JSON array (e.g. { "URLAllowlist": [ "qz://*"] } )
95+ JSONObject jsonPolicy = new JSONObject ();
96+ JSONArray jsonArray = new JSONArray ();
97+
98+ try {
99+ // Ensure parent is writable
100+ FileUtilities .setPermissionsParentally (Files .createDirectories (location .getParentFile ().toPath ()), false );
101+
102+ // Populate object
103+ if (location .exists ()) {
104+ jsonPolicy = new JSONObject (FileUtils .readFileToString (location , StandardCharsets .UTF_8 ));
105+ JSONArray found = jsonPolicy .optJSONArray (policyName );
106+ if (found == null ) {
107+ log .info ("Chromium policy found {} but without entry for {}, we'll add it" , location , policyName );
108+ } else {
109+ jsonArray = found ;
110+ }
111+ }
112+
113+ value :
114+ for (String value : values ) {
115+ for (int i = 0 ; i < jsonArray .length (); i ++) {
116+ if (jsonArray .optString (i , "" ).equals (value )) {
117+ log .info ("Chromium policy {} '{}' already exists at location {}, skipping" , policyName , value , location );
118+ continue value ;
69119 }
70- jsonArray .put (value );
71120 }
121+ jsonArray .put (value );
122+ }
72123
73- // Insert array into object
74- jsonPolicy .put (policyName , jsonArray );
124+ // Insert array into object
125+ jsonPolicy .put (policyName , jsonArray );
75126
76- // Write contents, ensuring policy file is world readable
77- try (BufferedWriter writer = new BufferedWriter (new FileWriter (location ))) {
78- writer .write (jsonPolicy .toString ());
79- if (!location .setReadable (true , false )) {
80- throw new IOException ("Unable to set readable: " + location );
81- }
127+ // Write contents, ensuring policy file is world readable
128+ try (BufferedWriter writer = new BufferedWriter (new FileWriter (location ))) {
129+ writer .write (jsonPolicy .toString ());
130+ if (!location .setReadable (true , false )) {
131+ throw new IOException ("Unable to set readable: " + location );
82132 }
83- } catch (IOException | JSONException e ) {
84- log .warn ("An error occurred while writing the new policy file {}" , location , e );
85133 }
134+ } catch (IOException | JSONException e ) {
135+ log .warn ("An error occurred while writing the new policy file {}" , location , e );
136+ return false ;
86137 }
87138 return true ;
88139 }
@@ -93,9 +144,9 @@ public boolean uninstall(Installer.PrivilegeLevel scope, String policyName, Stri
93144 log .info ("Skipping removal of Chromium policy {}, not supported as PrivilegeLevel {}" , policyName , scope );
94145 return false ;
95146 }
96- for (String pattern : MANAGED_POLICY_PATH_PATTERNS ) {
147+ for (AppInfo appInfo : AppLocator . getInstance (). locate ( AppAlias . CHROMIUM ) ) {
97148 // Chromium policy, e.g. /etc/chromium/policies/managed/qz-tray.json
98- File location = Paths . get ( String . format ( pattern , Constants . PROPS_FILE )). toFile ( );
149+ File location = calculatePolicyFile ( scope , appInfo );
99150 log .info ("Removing Chromium policy {} {}..." , policyName , location );
100151
101152 if (location .exists ()) {
0 commit comments