Microsoft Edge Canary on macOS

May 23, 2019    Article    905 words    5 mins read

Microsoft launched the new Microsoft Edge browser for macOS (for now just a Chromium re-skin with some telemetry sprinkled in) so if you want to run it on your Mac you must either use the built-in installer (and get all the benefits of seeing telemetry data being sent to the cloud) or extract the package and copy the .app to /Applications.

Download the latest version from the Microsoft Edge Insider website.

$ pkgutil --expand-full MicrosoftEdgeCanary-76.0.167.0.pkg ~/Downloads/MicrosoftEdgeCanary/

If you have a different version, adjust the command line accordingly.

Browse into the newly created directory and copy the .app file.

$ mv "~/Downloads/MicrosoftEdgeCanary/MicrosoftEdgeCanaryUpdate-76.0.167.0.pkg/Payload/Microsoft Edge Canary.app" /Applications/
$ open /Applications/Microsoft Edge Canary.app

There are some scripts that are sending telemetry data to Microsoft and a send_event binary that sends data to https://self.events.data.microsoft.com/OneCollector/1.0/ using sudo. Also the installer uses sudo to register the app to get updates from Microsoft Auto Update.

Below are the preinstall and postinstall scripts for the .pkg, found inside the MicrosoftEdgeCanaryUpdate-76.0.167.0.pkg/Scripts directory.

MicrosoftEdgeCanaryUpdate-76.0.167.0.pkg/Scripts/preinstall

#!/bin/bash
# Copyright (C) Microsoft Corporation. All rights reserved.

LOGPATH="/Library/Logs/Microsoft"
LOGFILE="${LOGPATH}/edgeinstall.log"

mkdir ${LOGPATH}

edge_log()
{
	local message="$1"
	local timestamp="$(/bin/date +%Y-%m-%d' '%T)"
	/bin/echo "${timestamp} [Apple Installer - preinstall] <Info> ${message}" >> "${LOGFILE}"
}

edge_log "Edge Preinstall Script Start"

# kMDItemWhereFroms metadata in extended attributes of the package includes consent value and installation session identifier.
whereFrom=$(xattr -lp com.apple.metadata:kMDItemWhereFroms "${PACKAGE_PATH}")
# metadata will be in binary format - this regex is to just get the text between the |
combinedString=$(echo $whereFrom | perl -e 'local $/; $_=<>; s/[^|]*\|([^|]{16})\|/$1/g; print $_;')
# this regex will parse the consent value.
consentValue=$(echo $combinedString | sed "s/.*Consent=\([^]]*\)&.*/\1/g")
# this regex will parse the installation session identifier as a GUID.
iid=$(echo $combinedString | sed "s/.*IID=\([[:xdigit:]]\{8\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{12\}\).*/\1/g")
if [[ "${iid}" == "${combinedString}" ]]; then
  iid=""
fi

# Send telemetry
send_event="./send_event"
if [[ -f "${send_event}" ]]; then
  edge_log "Sending event."
  PkgName="$(basename "${PACKAGE_PATH}")"
  if [[ "${PkgName}" == *"Dev"* ]]; then
	Channel=2
  elif [[ "${PkgName}" == *"Canary"*  ]]; then
	Channel=1
  elif [[ "${PkgName}" == *"Beta"* ]]; then
	Channel=3
  else
	# Stable
	Channel=4
  fi
  edge_log "Channel ${Channel}"
  if [[ -z $COMMAND_LINE_INSTALL || $COMMAND_LINE_INSTALL == 0 ]]; then
	IsInstaller=1
  else
	IsInstaller=0
  fi
  if [[ ${Channel} != 4 || ! -z ${consentValue} && ${consentValue} == "1" ]]; then
	/usr/bin/sudo -b ${send_event} --event "Preinstall" --channel ${Channel} --installer ${IsInstaller} --iid "${iid}"
  fi
fi

edge_log "Edge Preinstall Script End"

exit 0

MicrosoftEdgeCanaryUpdate-76.0.167.0.pkg/Scripts/postinstall

#!/bin/bash
# Copyright (C) Microsoft Corporation. All rights reserved.

LOGPATH="/Library/Logs/Microsoft"
LOGFILE="${LOGPATH}/edgeinstall.log"

mkdir ${LOGPATH}

edge_log()
{
	local message="$1"
	local timestamp="$(/bin/date +%Y-%m-%d' '%T)"
	/bin/echo "${timestamp} [Apple Installer - postinstall] <Info> ${message}" >> "${LOGFILE}"
}

should_reopen_edge()
{
	# COMMAND_LINE_INSTALL is set by apple installer 
	if [[ -z $COMMAND_LINE_INSTALL || $COMMAND_LINE_INSTALL == 0 ]]
	then 
		edge_log "apple gui installer"
		return 0
	else
	return 1
  fi
}

edge_log "Edge Postinstall Script Start"

PkgName="$(basename "${PACKAGE_PATH}")"
# Previous methods of getting current logged in user is not accurate.
# We could also use $USER or whoami, but those aren't necessarily reliable either.
# Getting the owner of /dev/console should be reliable.
UserName="$(/usr/bin/stat -f '%Su' /dev/console)"
LCID="0409"
MAUPlistName="com.microsoft.autoupdate2"

if [[ "${PkgName}" == *"Dev"* ]]; then
  edge_log "We are installing Dev Channel"
  EdgeAppPath="/Applications/Microsoft Edge Dev.app"
  EdgeAppName="Microsoft Edge Dev"
  Channel=2
elif [[ "${PkgName}" == *"Canary"*  ]]; then
  edge_log "We are installing Canary Channel"
  EdgeAppPath="/Applications/Microsoft Edge Canary.app"
  EdgeAppName="Microsoft Edge Canary"
  Channel=1
elif [[ "${PkgName}" == *"Beta"* ]]; then
  edge_log "We are installing Beta Channel"
  EdgeAppPath="/Applications/Microsoft Edge Beta.app"
  EdgeAppName="Microsoft Edge Beta"
  Channel=3
else
  edge_log "We are installing Stable Channel"
  EdgeAppPath="/Applications/Microsoft Edge.app"
  EdgeAppName="Microsoft Edge"
  Channel=4
fi

PlistPath="${EdgeAppPath}/Contents/Info.plist"

# Get the App Code and Bundle Suffix from App's plist, which is neceesary for
# creating the ApplicationID needed to register Edge with MAU.
AppCode="$(/usr/bin/defaults read "${PlistPath}" CFBundleSignature)"
BundleSuffix="$(/usr/bin/defaults read "${PlistPath}" MSEUBundleSuffx)"

ApplicationID="${AppCode}${BundleSuffix}"

# Register app to get Updates from MAU
/usr/bin/sudo -u ${UserName} /usr/bin/defaults write MAUPlistName Applications -dict-add '{'\""${EdgeAppPath}"\"' = { "Application ID" = '\""${ApplicationID}"\"'; LCID = '"${LCID}"'; }; }'

# Only open if it was invoked by GUI
if should_reopen_edge; then
  parent_dir=`/usr/bin/dirname "$0"`
  chain_clu="$parent_dir/chain_app"

  # Find the PID of the installer process
  installer_pid=$(/bin/ps -o pid,command -ax | /usr/bin/grep "Installer\.app/Contents/MacOS/Installer" | /usr/bin/awk '{print $1}')

  # Open the newly installed app
  /usr/bin/sudo -u ${UserName} "$chain_clu" -p "$installer_pid" -a "${EdgeAppPath}" &
fi

# Perform consent related tasks here
whereFrom=$(xattr -lp com.apple.metadata:kMDItemWhereFroms "${PACKAGE_PATH}")
# metadata will be in binary format - this regex is to just get the text between the |
combinedString=$(echo $whereFrom | perl -e 'local $/; $_=<>; s/[^|]*\|([^|]{16})\|/$1/g; print $_;')
# this regex will parse the consent value.
consentValue=$(echo $combinedString | sed "s/.*Consent=\([^]]*\)&.*/\1/g")
# this regex will parse the installation session identifier as a GUID.
iid=$(echo $combinedString | sed "s/.*IID=\([[:xdigit:]]\{8\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{12\}\).*/\1/g")
if [[ "${iid}" == "${combinedString}" ]]; then
  iid=""
fi

if [[ ! -z ${consentValue} && ${consentValue} == "1" ]]; then
  edge_log "Adding Consent Value Here."
  # Create the folder we want
  mkdir -p "${HOME}/Library/Application Support/${EdgeAppName}"
  # Change ownership of local folder
  chown ${UserName} -R "${HOME}/Library/Application Support/${EdgeAppName}"
  # Create the consent files
  touch "${HOME}/Library/Application Support/${EdgeAppName}/Consent To Send Stats"
  touch "${HOME}/Library/Application Support/${EdgeAppName}/Consent To Send Urls"
fi

# Send telemetry
send_event="./send_event"
if [[ -f "${send_event}" ]]; then
  edge_log "Sending event."
  Version="$(/usr/bin/defaults read "${PlistPath}" CFBundleShortVersionString)"
  Identifier="$(/usr/bin/defaults read "${PlistPath}" CFBundleIdentifier)"
  Executable="$(/usr/bin/defaults read "${PlistPath}" CFBundleExecutable)"
  edge_log "${Version}"
  edge_log "${Identifier}"
  edge_log "${Executable}"
  edge_log "Channel ${Channel}"
  if [[ -z $COMMAND_LINE_INSTALL || $COMMAND_LINE_INSTALL == 0 ]]; then
	IsInstaller=1
  else
	IsInstaller=0
  fi
  if [[ ${Channel} != 4 || ! -z ${consentValue} && ${consentValue} == "1" ]]; then
	/usr/bin/sudo -b ${send_event} --event "Postinstall" --channel ${Channel} --version "${Version}" --id "${Identifier}" --exe "${Executable}" --installer ${IsInstaller} --iid "${iid}"
  fi
fi

edge_log "Edge Postinstall Script End"

exit 0