@@ -13,10 +13,11 @@ const PolicyPath = "/etc/chromium/policies/managed/policy.json"
1313type Policy struct {
1414 mu sync.Mutex
1515
16- PasswordManagerEnabled bool `json:"PasswordManagerEnabled"`
17- AutofillCreditCardEnabled bool `json:"AutofillCreditCardEnabled"`
18- TranslateEnabled bool `json:"TranslateEnabled"`
19- ExtensionSettings map [string ]ExtensionSetting `json:"ExtensionSettings"`
16+ PasswordManagerEnabled bool `json:"PasswordManagerEnabled"`
17+ AutofillCreditCardEnabled bool `json:"AutofillCreditCardEnabled"`
18+ TranslateEnabled bool `json:"TranslateEnabled"`
19+ DefaultNotificationsSetting int `json:"DefaultNotificationsSetting"`
20+ ExtensionSettings map [string ]ExtensionSetting `json:"ExtensionSettings"`
2021}
2122
2223// ExtensionSetting represents settings for a specific extension
@@ -29,23 +30,19 @@ type ExtensionSetting struct {
2930 RuntimeAllowedHosts []string `json:"runtime_allowed_hosts,omitempty"`
3031}
3132
32- var (
33- )
34-
35- // ReadPolicy reads the current enterprise policy from disk
36- func (p * Policy ) ReadPolicy () (* Policy , error ) {
37- p .mu .Lock ()
38- defer p .mu .Unlock ()
39-
33+ // readPolicyUnlocked reads the current enterprise policy from disk without locking
34+ // This is an internal helper for use within already-locked operations
35+ func (p * Policy ) readPolicyUnlocked () (* Policy , error ) {
4036 data , err := os .ReadFile (PolicyPath )
4137 if err != nil {
4238 if os .IsNotExist (err ) {
4339 // Return default policy if file doesn't exist
4440 return & Policy {
45- PasswordManagerEnabled : false ,
46- AutofillCreditCardEnabled : false ,
47- TranslateEnabled : false ,
48- ExtensionSettings : make (map [string ]ExtensionSetting ),
41+ PasswordManagerEnabled : false ,
42+ AutofillCreditCardEnabled : false ,
43+ TranslateEnabled : false ,
44+ DefaultNotificationsSetting : 2 ,
45+ ExtensionSettings : make (map [string ]ExtensionSetting ),
4946 }, nil
5047 }
5148 return nil , fmt .Errorf ("failed to read policy file: %w" , err )
@@ -56,14 +53,25 @@ func (p *Policy) ReadPolicy() (*Policy, error) {
5653 return nil , fmt .Errorf ("failed to parse policy file: %w" , err )
5754 }
5855
56+ // Initialize ExtensionSettings map if it's nil to prevent panic on write
57+ if policy .ExtensionSettings == nil {
58+ policy .ExtensionSettings = make (map [string ]ExtensionSetting )
59+ }
60+
5961 return & policy , nil
6062}
6163
62- // WritePolicy writes the policy to disk
63- func (p * Policy ) WritePolicy ( policy * Policy ) error {
64+ // ReadPolicy reads the current enterprise policy from disk
65+ func (p * Policy ) ReadPolicy () ( * Policy , error ) {
6466 p .mu .Lock ()
6567 defer p .mu .Unlock ()
6668
69+ return p .readPolicyUnlocked ()
70+ }
71+
72+ // writePolicyUnlocked writes the policy to disk without locking
73+ // This is an internal helper for use within already-locked operations
74+ func (p * Policy ) writePolicyUnlocked (policy * Policy ) error {
6775 data , err := json .MarshalIndent (policy , "" , " " )
6876 if err != nil {
6977 return fmt .Errorf ("failed to marshal policy: %w" , err )
@@ -76,10 +84,22 @@ func (p *Policy) WritePolicy(policy *Policy) error {
7684 return nil
7785}
7886
87+ // WritePolicy writes the policy to disk
88+ func (p * Policy ) WritePolicy (policy * Policy ) error {
89+ p .mu .Lock ()
90+ defer p .mu .Unlock ()
91+
92+ return p .writePolicyUnlocked (policy )
93+ }
94+
7995// AddExtension adds or updates an extension in the policy
8096// extensionID should be a stable identifier (can be derived from extension path)
81- func (p * Policy ) AddExtension (extensionID , extensionPath string , requiresEnterprisePolicy bool ) error {
82- policy , err := p .ReadPolicy ()
97+ func (p * Policy ) AddExtension (extensionID , extensionPath string , requiresEnterprisePolicy bool ) error {
98+ // Lock for the entire read-modify-write cycle to prevent race conditions
99+ p .mu .Lock ()
100+ defer p .mu .Unlock ()
101+
102+ policy , err := p .readPolicyUnlocked ()
83103 if err != nil {
84104 return err
85105 }
@@ -109,7 +129,7 @@ func (p *Policy) AddExtension(extensionID, extensionPath string, requiresEnterpr
109129
110130 policy .ExtensionSettings [extensionID ] = setting
111131
112- return p .WritePolicy (policy )
132+ return p .writePolicyUnlocked (policy )
113133}
114134
115135// GenerateExtensionID returns a stable identifier for the extension policy.
0 commit comments