Skip to main content
Question

Packaging Google Chrome breaks auto-updates

  • August 11, 2015
  • 18 replies
  • 42 views

Forum|alt.badge.img+6

Hi Everyone,

I've recently packaged Google Chrome as a .pkg, and it deploys and works perfectly except that the automatic updates seem to fail. When I go to Chrome -> About Google Chrome , I get the "Updating Google Chrome" message for a moment then "Update failed (error: 12)". Following Google's instructions for resolving this error produces no results. The only thing that seems to fix it is a clean download and install off the .dmg direct from Google. Has anyone else experienced this before?

Thanks,

-Mike

18 replies

mpermann
Forum|alt.badge.img+22
  • Valued Contributor
  • 690 replies
  • August 11, 2015

What are the permissions on the Google Chrome.app that you packaged?


Forum|alt.badge.img+6
  • Author
  • Contributor
  • 27 replies
  • August 11, 2015

Actually, I got frustrated using Composer so I used pkgbuild following these instructions:

https://wiki.afp548.com/index.php/Guidelines_for_Mac_software_packaging#Google_Chrome


Forum|alt.badge.img+17
  • Contributor
  • 881 replies
  • August 11, 2015

I see that same error with pkgbuild and Chrome, for what it's worth. I wasn't able to figure it out, even with permissions modifications after installing.


Forum|alt.badge.img+31
  • Hall of Fame
  • 920 replies
  • August 11, 2015

I'm going to put in an obligatory plug for AutoPkg, as it can handle building a working Chrome installer package for you:

http://autopkg.github.io/autopkg/

Other approaches for packaging drag-and-drop applications like Chrome include using Packages:

https://derflounder.wordpress.com/2014/05/02/building-simple-packages-with-packages/

I've also built a tool for creating installer packages from drag-and-drop applications:

https://github.com/rtrouton/Simple-Package-Creator


Forum|alt.badge.img+16
  • Valued Contributor
  • 277 replies
  • August 13, 2015

I fixed an issue with Chrome not updating by deploying a package along with the app that contains:

/Library/Google/Google Chrome Brand.plist
/Library/Google/GoogleSoftwareUpdate/*
/Library/LaunchAgents/com.google.keystone.agent.plist
/Library/LaunchDaemons/com.google.keystone.daemon.plist

I honestly don't recall what error I was seeing, but it may be worth making sure those files exist on your test machine when you try to update.


RobertHammen
Forum|alt.badge.img+28
  • Esteemed Contributor
  • 1027 replies
  • August 13, 2015

@rtrouton I'm even seeing the same thing with packages built with AutoPkg, so... #ymmv


apizz
Forum|alt.badge.img+15
  • Honored Contributor
  • 395 replies
  • August 15, 2015

I just did Normal Snapshot with Composer before installing Chrome, install Chrome, configure settings and set auto-update, set bookmarks, etc. and then take after snapshot. Worked like a charm.

Alternatively, I also tried installing Chrome, configure the settings, auto update, etc. and using the preinstalled software option in Composer and that worked as well.

My 2 cents ...


Forum|alt.badge.img+10
  • New Contributor
  • 343 replies
  • August 15, 2015

Depending on your POV disabling autoupdates for Chrome might be considered a feature and not a bug.

But what's happening here is that when a pkg installs Chrome it's being written to the /Applications folder with root as the owner of the application bundle. When a normal (non-root) user runs the app, they don't have the rights to modify it.

There are ways to install the Google Updater as root also so it can update Chrome if you want to, but I'd think you'd want your software management system (Casper) to manage your software and its updates...


Forum|alt.badge.img+19
  • Contributor
  • 437 replies
  • December 16, 2015

from the chrome installer script, I believe this is what Greg was referring to . . .

FixChromePerms () {
    if [ -e "/Applications/Google Chrome.app" ]; then
        chgrp -Rh admin /Applications/Google Chrome.app
        chmod -R "a+rX,ug+w,o-w" /Applications/Google Chrome.app
        find /Applications/Google Chrome.app -type l -exec chmod -h "a+rX,ug+w,o-w" {} +
        OS_VERSION=$(sw_vers -productVersion)
        OS_MAJOR=$(sed -Ene 's/^([0-9]+).*/1/p' <<< ${OS_VERSION})
        OS_MINOR=$(sed -Ene 's/^([0-9]+).([0-9]+).*/2/p' <<< ${OS_VERSION})
        QUARANTINE_ATTR=com.apple.quarantine
        if [ ${OS_MAJOR} -gt 10 ] ||
           ([ ${OS_MAJOR} -eq 10 ] && [ ${OS_MINOR} -ge 6 ]) ; then
          # On 10.6, xattr supports -r for recursive operation.
          xattr -d -r "${QUARANTINE_ATTR}" "${DEST}" >& /dev/null
        else
          # On earlier systems, xattr doesn't support -r, so run xattr via find.
          find "${DEST}" -exec xattr -d "${QUARANTINE_ATTR}" {} + >& /dev/null
        fi
    fi
}

Chris_Hafner
Forum|alt.badge.img+25
  • Jamf Heroes
  • 1754 replies
  • December 18, 2015

Here's +1 for @rtrouton posted methods. For what it's worth, I use composer and distribute as a .dmg.


Forum|alt.badge.img+23
  • Valued Contributor
  • 512 replies
  • March 8, 2016

Hey all,

I used autopkg to create my initial Chrome installer package. I have since used @hjuutilainen 's script to enable Chrome to automatically update.

After running the script, Chrome stopped offering to "set up updates for all users", and was able to successfully run an update check for a time.

Today, I encountered Chrome offering to "set up updates for all users" again. When I loaded the About page in Chrome, it was unable to check for updates, returning error 12. After trying the permissions fix @nkalister quoted above, the update check proceeded, but then returned error 11.

After clicking the button to "set up updates for all users" and authenticating, Chrome was able to update.

So, the question is, what happens when you let Chrome "set up updates for all users"? I captured changes during the process and I'm slogging through the list of changes. I'm wondering if anyone listening has already discovered the answer.


donmontalvo
Forum|alt.badge.img+36
  • Hall of Fame
  • 4293 replies
  • March 16, 2016

+1 to @milesleacy's position.

Chrome has an embedded copy of Flash, and as everyone knows, Flash is updated every time you sneeze.

So disabling automatic updates to Flash might sound like a good idea.

But the truth is, when your company has it's next security audit and they (hopefully) raise a flag, you're going some 'splaining to do, Lucy.

Diaper policy...enable Chrome updates and keep it enabled. If your company/client tells you to disable, teach them why that's a terrible idea (and not recommended or supported by Google).

Don


Forum|alt.badge.img+23
  • Valued Contributor
  • 512 replies
  • March 17, 2016

@donmontalvo I have Chrome automatically updating.

Adobe Flash Installer is a restricted software item - kill, delete, message "Flash Player is a security and performance risk. If you need to view Flash content, you may use Google Chrome."


Chris_Hafner
Forum|alt.badge.img+25
  • Jamf Heroes
  • 1754 replies
  • March 17, 2016

@milesleacy What an interesting concept. Something tells me that I won't be able to pull that one off but...


Forum|alt.badge.img+9
  • Employee
  • 35 replies
  • April 14, 2016

See Ben Toms latest MacMule post on Google Chrome v50 - some significant OS version requirement changes

GOOGLE CHROME 50 OS REQUIREMENT CHANGES


Forum|alt.badge.img+17
  • Valued Contributor
  • 178 replies
  • June 22, 2016

Looks like there still isn't a solid answer for this? I've got a "normal" package (just places the chrome .app in /Applications) that we push out and it fails to update with error 12. I've ran both of the scripts mentioned here - the first doesn't change anything and hjuutilainen's makes the errors go away, but now chrome reports as being up to date but it isn't. (My package is a few months old so is installing version 45). Any ideas? Testing on 10.11.5 currently, so it's not the v50 OS requirements.

Thanks!

p.s. Anybody found anything like Joe Farage's FirefoxInstall.sh? LOVE that - no packaging, always get the latest version. :)


apizz
Forum|alt.badge.img+15
  • Honored Contributor
  • 395 replies
  • June 22, 2016

@mbezzo We ran into this issue, but only when for when we initially packaged Chrome and User preferences into a DMG and set the file to Fill User Templates.

We're getting our 10.11.5 image ready and I've been able to deploy the latest version of Chrome (just the app) to /Applications and then run a one-time startup Python script to enable Auto Updates for all users without issue.

I can't seem to find where I acquired the script originally, but I've included it below.

#!/usr/bin/python
# encoding: utf-8
"""
chrome-enable-autoupdates.py

This script enables system wide automatic updates for Google Chrome.
It should work for Chrome versions 18 and later. No configuration needed
as this is originally intended as a munki postinstall script.

Created by Hannes Juutilainen, hjuutilainen@mac.com

History:

2015-09-25, Niklas Blomdalen - Modifications to include old KeystoneRegistration installation (python version) 2014-11-20, Hannes Juutilainen - Modifications for Chrome 39 2012-08-31, Hannes Juutilainen - Added --force flag to keystoneInstall as suggested by Riley Shott 2012-05-29, Hannes Juutilainen - Added more error checking 2012-05-25, Hannes Juutilainen - Added some error checking in main 2012-05-24, Hannes Juutilainen - First version """ import sys import os import getopt import subprocess import plistlib chromePath = "/Applications/Google Chrome.app" infoPlistPath = os.path.realpath(os.path.join(chromePath, 'Contents/Info.plist')) brandPath = "/Library/Google/Google Chrome Brand.plist" brandKey = "KSBrandID" tagPath = infoPlistPath tagKey = "KSChannelID" versionPath = infoPlistPath versionKey = "KSVersion" class Usage(Exception): def __init__(self, msg): self.msg = msg def chromeIsInstalled(): """Check if Chrome is installed""" if os.path.exists(chromePath): return True else: return False def chromeVersion(): """Returns Chrome version""" infoPlist = plistlib.readPlist(infoPlistPath) bundleShortVersion = infoPlist["CFBundleShortVersionString"] return bundleShortVersion def chromeKSUpdateURL(): """Returns KSUpdateURL from Chrome Info.plist""" infoPlist = plistlib.readPlist(infoPlistPath) KSUpdateURL = infoPlist["KSUpdateURL"] return KSUpdateURL def chromeKSProductID(): """Returns KSProductID from Chrome Info.plist""" infoPlist = plistlib.readPlist(infoPlistPath) KSProductID = infoPlist["KSProductID"] return KSProductID def keystoneRegistrationFrameworkPath(): """Returns KeystoneRegistration.framework path""" keystoneRegistration = os.path.join(chromePath, 'Contents/Versions') keystoneRegistration = os.path.join(keystoneRegistration, chromeVersion()) keystoneRegistration = os.path.join(keystoneRegistration, 'Google Chrome Framework.framework') keystoneRegistration = os.path.join(keystoneRegistration, 'Frameworks/KeystoneRegistration.framework') return keystoneRegistration def keystoneInstall(): """Install the current Keystone""" installScript = os.path.join(keystoneRegistrationFrameworkPath(), 'Resources/ksinstall') if not os.path.exists(installScript): installScript = os.path.join(keystoneRegistrationFrameworkPath(), 'Resources/install.py') keystonePayload = os.path.join(keystoneRegistrationFrameworkPath(), 'Resources/Keystone.tbz') if os.path.exists(installScript) and os.path.exists(keystonePayload): retcode = subprocess.call([installScript, '--install', keystonePayload, '--force']) if retcode == 0: return True else: return False else: print >> sys.stderr, "Error: KeystoneRegistration.framework not found" return False def removeChromeFromKeystone(): """Removes Chrome from Keystone""" ksadmin = "/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin" ksadminProcess = [ ksadmin, '--delete', '--productid', chromeKSProductID()] retcode = subprocess.call(ksadminProcess) if retcode == 0: return True else: return False def registerChromeWithKeystone(): """Registers Chrome with Keystone""" ksadmin = "/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin" if os.path.exists(ksadmin): ksadminProcess = [ksadmin, '--register', '--preserve-tttoken', '--productid', chromeKSProductID(), '--version', chromeVersion(), '--xcpath', chromePath, '--url', chromeKSUpdateURL(), '--tag-path', tagPath, '--tag-key', tagKey, '--brand-path', brandPath, '--brand-key', brandKey, '--version-path', versionPath, '--version-key', versionKey] retcode = subprocess.call(ksadminProcess) if retcode == 0: return True else: return False else: print >> sys.stderr, "Error: %s doesn't exist" % ksadmin return False def main(argv=None): if argv is None: argv = sys.argv try: # Check for root if os.geteuid() != 0: print >> sys.stderr, "This script must be run as root" return 1 if not chromeIsInstalled(): print >> sys.stderr, "Error: Chrome is not installed on this computer" return 1 if keystoneInstall(): print "Keystone installed" else: print >> sys.stderr, "Error: Keystone install failed" return 1 if registerChromeWithKeystone(): print "Registered Chrome with Keystone" return 0 else: print >> sys.stderr, "Error: Failed to register Chrome with Keystone" return 1 except Usage, err: print >>sys.stderr, err.msg print >>sys.stderr, "for help use --help" return 2 if __name__ == "__main__": sys.exit(main())

Forum|alt.badge.img+17
  • Valued Contributor
  • 178 replies
  • June 22, 2016

Thanks @aporlebeke That's the script I'm using where I'm seeing the "Chrome is up to date" when it isn't. So, it fixed one issue but presents another! This is such a pain to test too, because if I create a new package, or say use autopkg, the newly packaged version is completely updated, so can't actually test to see if it does properly update! :)

Thanks,
Matt