Safari
With the release of Safari 10, it looks like Apple no longer allows for MCX-style management of Safari's preferences. In previous versions, you could easily set a homepage using the following command (ran as the current user):
defaults write com.apple.Safari HomePage "http://HOMEPAGE_URL"
MCX preference settings are still supported through configuration profiles. We can create a custom profile with the following attributes:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>PayloadIdentifier</key> <string>com.laurenceschool.profile.safari.20161111</string> <key>PayloadRemovalDisallowed</key> <true/> <key>PayloadScope</key> <string>System</string> <key>PayloadType</key> <string>Configuration</string> <key>PayloadUUID</key> <string>69F2AD5C-A85E-11E6-80F5-76304DEC7EB7</string> <key>PayloadOrganization</key> <string>Laurence School</string> <key>PayloadVersion</key> <integer>1</integer> <key>PayloadDisplayName</key> <string>Safari Home Page</string> <key>PayloadContent</key> <array> <dict> <key>PayloadType</key> <string>com.apple.ManagedClient.preferences</string> <key>PayloadVersion</key> <integer>1</integer> <key>PayloadIdentifier</key> <string>com.laurenceschool.profile.safari.20161113</string> <key>PayloadUUID</key> <string>E276A24C-A85E-11E6-80F5-76304DEC7EB7</string> <key>PayloadEnabled</key> <true/> <key>PayloadDisplayName</key> <string>Sets the Safari HomePage attribute and locks it in place.</string> <key>PayloadContent</key> <dict> <key>com.apple.Safari</key> <dict> <key>Forced</key> <array> <dict> <key>mcx_preference_settings</key> <dict> <key>AlwaysRestoreSessionAtLaunch</key> <false/> <key>NewWindowBehavior</key> <integer>0</integer> <key>NewTabBehavior</key> <integer>0</integer> <key>HomePage</key> <string>http://HOMEPAGE_URL</string> </dict> </dict> </array> </dict> </dict> </dict> </array> </dict> </plist>
The profile can then be installed for a specific user through a script:
/usr/bin/profiles -I -F /path/to/profile.mobileconfig -U $USER
Google Chrome
The same concept applies for Google Chrome:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadIdentifier</key>
<string>com.laurenceschool.profile.chrome.20161113</string>
<key>PayloadRemovalDisallowed</key>
<true/>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>6A53E33E-A9E8-11E6-80F5-76304DEC7EB7</string>
<key>PayloadOrganization</key>
<string>Laurence School</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadDisplayName</key>
<string>Google Chrome Homepage</string>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadType</key>
<string>com.apple.ManagedClient.preferences</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadIdentifier</key>
<string>com.laurenceschool.profile.chrome.20161113</string>
<key>PayloadUUID</key>
<string>BC8C5630-A9E9-11E6-80F5-76304DEC7EB7</string>
<key>PayloadEnabled</key>
<true/>
<key>PayloadDisplayName</key>
<string>Sets the Chrome HomePage attribute and locks it in place.</string>
<key>PayloadContent</key>
<dict>
<key>com.google.Chrome</key>
<dict>
<key>Forced</key>
<array>
<dict>
<key>mcx_preference_settings</key>
<dict>
<key>AutoFillEnabled</key>
<false/>
<key>DefaultBrowserSettingEnabled</key>
<false/>
<key>BookmarkBarEnabled</key>
<true/>
<key>HideWebStorePromo</key>
<true/>
<key>HomepageIsNewTabPage</key>
<false/>
<key>HomepageLocation</key>
<string>http://HOMEPAGE_URL</string>
<key>PasswordManagerEnabled</key>
<false/>
<key>RestoreOnStartup</key>
<integer>4</integer>
<key>RestoreOnStartupURLs</key>
<array>
<string>http://HOMEPAGE_URL</string>
</array>
<key>ShowHomeButton</key>
<true/>
<key>SyncDisabled</key>
<false/>
<key>DefaultNotificationsSetting</key>
<integer>2</integer>
<key>ImportAutofillFormData</key>
<false/>
<key>ImportBookmarks</key>
<false/>
<key>ImportHistory</key>
<false/>
<key>ImportHomepage</key>
<false/>
<key>ImportSearchEngine</key>
<false/>
<key>ImportSavedPasswords</key>
<false/>
</dict>
</dict>
</array>
</dict>
</dict>
</dict>
</array>
</dict>
</plist>
Firefox
Firefox, however, does not support MCX or Configuration Profile management. There is a third party extension that allows customizing preferences and then exporting them as an add-on package. For our purposes, we will create an override autoconfig.js file inside the app directory itself. The JS file will initially point to a CFG file. This allows us to lock the settings using javascript:
// This file is saved to
// Firefox.app/Contents/Resources/defaults/pref/autoconfig.js
pref("general.config.filename", "firefox.cfg");
pref("general.config.obscure_value", 0);
// This file is saved to
// Firefox.app/Contents/Resources/firefox.cfg
// Disable updater
lockPref("app.update.enabled", false);
// make absolutely sure it is really off
lockPref("app.update.auto", false);
lockPref("app.update.mode", 0);
lockPref("app.update.service.enabled", false);
// Disable Add-ons compatibility checking
clearPref("extensions.lastAppVersion");
// Don't show 'know your rights' on first run
pref("browser.rights.3.shown", true);
// Don't show WhatsNew on first run after every update
pref("browser.startup.homepage_override.mstone", "ignore");
// Set default homepage
lockPref("browser.startup.homepage","http://HOMEPAGE_URL");
// Disable the internal PDF viewer
pref("pdfjs.disabled", true);
// Disable the flash to javascript converter
pref("shumway.disabled", true);
// Don't ask to install the Flash plugin
pref("plugins.notifyMissingFlash", false);
// Plugin checking
lockPref("plugins.hide_infobar_for_outdated_plugin", true);
clearPref("plugins.update.url");
// Health reporter
lockPref("datareporting.healthreport.service.enabled", false);
// Telemetry and FHR
lockPref("datareporting.policy.dataSubmissionEnabled", false);
// Crash reporter
lockPref("toolkit.crashreporter.enabled", false);
Components.classes["@mozilla.org/toolkit/crash-reporter;1"].getService(Components.interfaces.nsICrashReporter).submitReports = false;
// Popup blocker
lockPref("dom.disable_open_during_load", true);
// Popup whitelist
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
Services.perms.add(NetUtil.newURI("http://ALLOWED_URL"), "popup", Services.perms.ALLOW_ACTION);
// Set default search engine
Components.utils.import("resource://gre/modules/Services.jsm");
var searchService = Services.search;
var engine = searchService.getEngineByName("Google");
searchService.currentEngine = engine;
Note: This configuration will reset with each update to the app since Munki will override the actual executable. This deployment should be included as an 'update-to' package to ensure that it is continuously applied after each app update.
Signing Configuration Profiles
Custom profiles, or profiles created outside of Profile Manager/Apple Configurator, are not signed. We can sign them manually with a trusted certificate from the Apple Developer program.
Sign in to the Developer portal and download a Mac Developer Application cert. After it's installed to the keychain, verify that it's available as a code signing identity:
/usr/bin/security find-identity -p codesigning -v
Then use it to sign a profile:
/usr/bin/security cms -S -N "3rd Party Mac Developer Application: Laurence School Apps (4MESE8N7WN)" -i /path/to/profile.mobileconfig -o /path/to/signedprofile.mobileconfig
The resulting profile will now appear verified to the user.