Files
Jonathan Kamens 3b4d10d2d0 Disable user-created dynamic scheduling functions in ATN version
The moderators of ATN want me to get rid of "unsafe-eval", which I use
for dynamic scheduling functions. I've elected to abide by their
wishes by disabling user-created dynamic scheduling functions in the
ATN version of the add-on, while allowing them to continue working in
the beta version of the add-on. This seems like the best trade-off of
usability vs. following ATN's rules.

Here's a high-level summary of what I did to implement this change:

* The "unsafe-eval" script policy is removed from the content security
  policy of the add-on by default, but added back when building the
  beta XPI.
* A warning pop-up is displayed when the version of the add-on without
  unsafe-eval is in use, in the following contexts:

    * on startup, when there are any user-created dynamic functions;
    * when the user attempts to assign a user-created dynamic function
      to a shortcut or accelerator;
    * when the user starts writing a new user-created dynamic
      function; and
    * whenever the add-on attempts to evaluate a user-created dynamic
      function, e.g., because it's attempting to reschedule a
      recurring message with dynamic scheduling that was created
      before the add-on was modified as described here.

* The actual code for the built-in dynamic functions, BusinessHours,
  DaysInARow, and Delay, is now hard-coded in the extension so that it
  can be executed without unsafe-eval permissions.
* To distinguish between built-in and user-created dynamic function
  execution, the telemetry event for evaluating dynamic functions now
  includes the function name of it's a built-in or "<private>"
  otherwise.
2025-06-28 21:27:42 -04:00

145 lines
5.9 KiB
Makefile

SHELL=/bin/bash
VERSION=$(shell jq -r .version < manifest.json)
MEDITOR=$(if $(EDITOR),$(EDITOR),$(VISUAL))
# https://stackoverflow.com/a/17055840/937306
define n
endef
RELEASE_PATTERNS=$(subst $n, ,$(file <dev/include-manifest))
RELEASE_FILES=$(filter-out %~,$(wildcard $(RELEASE_PATTERNS)))
# The line in the HTML that we're matching here looks like this:
# <li>Versions: <code>0.3, 0.4, ....lots of versions..., 119.*, *</code></li>
# We can't currently use "*" as max version, so we need the second-to-last
# version number on the line.
# We cache this so we don't have to fetch it every time.
VERSIONS_URL=https://addons.thunderbird.net/en-US/thunderbird/pages/appversions/
MAX_GECKO_VERSION=$(shell \
if (($$(date +%s) - $$(stat -c %Y .max_gecko_version) < 60 * 60 * 24)); then \
cat .max_gecko_version; \
else \
curl --silent "$(VERSIONS_URL)" | \
sed -n -e 's/.*Versions: <code>.*, \([^,]*\),.*/\1/p' | \
head -1 >| .max_gecko_version; \
if [ ! -s .max_gecko_version ]; then \
open "$(VERSIONS_URL)"; \
echo -n "Enter max gecko version: " 1>&2; \
read max_gecko_version; \
echo $$max_gecko_version >| .max_gecko_version; \
fi; \
cat .max_gecko_version; \
fi)
BETA_JSON=beta-channel.json
.PHONY: release
all: send_later.xpi send_later_beta.xpi send_later_atn.xpi
clean:: ; -rm -f send_later.xpi
send_later.xpi: dev/include-manifest $(RELEASE_FILES)
rm -f "$@" "$@".tmp
zip -q -r "$@".tmp $(RELEASE_FILES)
mv "$@".tmp "$@"
# Makes sure release tag is on origin.
# Makes sure our checked-out files are what's supposed to be in the release.
# Creates XPI files.
# Prompts for title and for user to edit release notes.
# Creates GitHub release as prerelease, uploading release notes and XPI files.
# Regenerates and commits beta-channel.json.
# Rebuilds github pages to deploy new beta XPI download link in user guide.
# Pushes new beta-channel.json to GitHub.
TITLE_FILE=/tmp/send-later-github-release-title.$(VERSION)
NOTES_FILE=/tmp/send-later-github-release-notes.$(VERSION).md
FULL_NOTES_FILE=/tmp/send-later-github-release-notes-full.$(VERSION).md
ASSETS=dist/send_later_$(VERSION).xpi dist/send_later_$(VERSION)_beta.xpi
gh_release: $(ASSETS)
# No releases that aren't pushed to main
git merge-base --is-ancestor v$(VERSION) origin/main
# No changes to release files in our checked-out tree
@set -e; for file in $(RELEASE_FILES); do \
git diff --exit-code v$(VERSION) $$file; \
done
@title=$$(cat $(TITLE_FILE) 2>/dev/null); \
[ -n "$$title" ] || title=$(VERSION); \
echo -n "Enter release title [$$title]: "; \
read newtitle; if [ -n "$$newtitle" ]; then title="$$newtitle"; fi; \
echo "$$title" > $(TITLE_FILE)
touch $(NOTES_FILE)
$(MEDITOR) $(NOTES_FILE)
cat $(NOTES_FILE) >| $(FULL_NOTES_FILE)
echo -e '\n\n**Note:** Downloading and installing `send_later_beta.xpi` will subscribe you to future beta releases. We love beta-testers! The advantage is that if there'\''s a bug that affects your workflow you'\''ll help find it and get it fixed quickly. The disadvantage is that bugs are a bit more likely in beta releases. You can unsubscribe from beta releases at any time by downloading and installing `send_later.xpi` or installing from [addons.thunderbird.net](https://addons.thunderbird.net/thunderbird/addon/send-later-3/).' >> $(FULL_NOTES_FILE)
@echo -n "Hit Enter to proceed or ctrl-C to abort: "; read response
# N.B. This uses $$(cat instead of $(file to read the title file because the
# contents of the file change while the rule is running but Make expands the
# rule earlier.
@set -x; gh release create v$(VERSION) --prerelease \
--title "$$(cat $(TITLE_FILE))" --notes-file $(FULL_NOTES_FILE) \
--verify-tag $(ASSETS)
set -e; \
gh_user=$$(yq -r '."github.com".user' ~/.config/gh/hosts.yml); \
pat=$$(jq -r .pages_pat secrets.json); \
curl -u $$gh_user:$$pat -X POST https://api.github.com/repos/Extended-Thunder/send-later/pages/builds
$(MAKE) update_beta_channel
.PHONY: gh_release
dist/send_later_$(VERSION)%xpi: send_later%xpi
mkdir -p dist
cp $^ $@.tmp
mv $@.tmp $@
update_beta_channel:
pipenv run dev/beta-channel-generator.py $(BETA_JSON) > $(BETA_JSON).tmp
mv $(BETA_JSON).tmp $(BETA_JSON)
@if git diff --exit-code $(BETA_JSON); then \
echo "$(BETA_JSON) unchanged" 1>&2; exit 1; \
else \
git commit -m "Update beta channel from GitHub" $(BETA_JSON); \
git push; \
fi
.PHONY: update_beta_channel
beta: send_later_beta.xpi
clean:: ; rm -fr send_later_beta.xpi tmp
.PHONY: beta
send_later_beta.xpi: send_later.xpi
rm -rf tmp $@.tmp
mkdir tmp
cd tmp && unzip -q ../send_later.xpi
cd tmp && jq '.applications.gecko.update_url="https://raw.githubusercontent.com/Extended-Thunder/send-later/main/beta-channel.json"|.content_security_policy|=sub("script-src '\''self'\''";"script-src '\''self'\'' '\''unsafe-eval'\''")' manifest.json > manifest.json.tmp
cd tmp && mv manifest.json.tmp manifest.json
cd tmp && zip -q -r ../$@.tmp *
mv $@.tmp $@
clean:: ; rm -fr send_later_beta.xpi tmp
send_later_atn.xpi: send_later.xpi
[ -n "$(MAX_GECKO_VERSION)" ]
rm -rf $@.tmp tmp
mkdir tmp
cd tmp && unzip -q ../send_later.xpi
cd tmp && jq '.applications.gecko.strict_max_version="$(MAX_GECKO_VERSION)"' manifest.json > manifest.json.tmp
cd tmp && mv manifest.json.tmp manifest.json
cd tmp && zip -q -r ../$@.tmp *
mv $@.tmp $@
## Requires the Node 'addons-linter' package is installed
## npm install -g addons-linter
## Note: this will produce a lot of "MANIFEST_PERMISSIONS"
## warnings because the addons-linter assumes vanilla firefox target.
lint:
addons-linter .
unit_test: $(RELEASE_FILES)
@node test/run_tests.js 2>&1 \
| sed -e '/^+ TEST'/s//"`printf '\033[32m+ TEST\033[0m'`"'/' \
| sed -e '/^- TEST'/s//"`printf '\033[31m- TEST\033[0m'`"'/' \
| sed -e 's/All \([0-9]*\) tests are passing!'/"`printf '\033[1m\033[32m'`"'All \1 tests are passing!'"`printf '\033[0m'`"/ \
| sed -e 's/\([0-9]*\/[0-9]*\) tests failed.'/"`printf '\033[1m\033[31m'`"'\1 tests failed.'"`printf '\033[0m'`"/
test: lint unit_test