fix(extension): don't offer a Web Store install for an extension that's already here - #86
Merged
Merged
Conversation
…'s already here Opening the MarkSyncr listing on chromewebstore.google.com and clicking "Add to TronBrowser" hung: the install dialog sat there spinning, never installed, and would not dismiss. MarkSyncr is bundled. build-release.sh fetches its CRX and stages it into extensions/marksyncr, and the launcher loads every extension subdir with --load-extension. The CRX's manifest carries a `key`, so the bundled copy claims the same extension id as the store listing (hjcjjcpialiakkalcgadnfnoomdaegjg). Clicking Add therefore asked Chromium to install a downloaded CRX over an extension it already had from a command-line (unpacked) location, which a CRX cannot replace. The prompt had nothing to complete and no failure to report, so it never resolved. install-helper.js offered that button unconditionally — it never asked whether the extension was already installed. It does now, and the rule is general rather than a special case for the one listing that exposed it: any already-installed extension has the same problem. The service worker looks the id up with chrome.management (content scripts don't get the API) and the button shows what can actually succeed — nothing when it is installed and enabled, Enable when it is installed and switched off, and an install only when it is genuinely absent. The lookup is bounded at 3s and every failure path resolves null, so an unknown answer falls back to the plain CRX install this button already did. A stalled registry must not be what decides whether the button works. Adds the `management` permission, which is what the lookup and the enable both need. The decision is pure and lives in install-state.js with 15 tests, including the MarkSyncr case that started this. Full desktop suite: 89 passing, eslint clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XbNfTZM5a6sH1A54dsf7ns
| : { action: 'none', label: '✗ Could not enable', title: 'Enabling failed. Turn it on from chrome://extensions.' }); | ||
| return; | ||
| } | ||
| window.location.href = target.url; |
ThreatCrush Security Scan55 finding(s) HIGH/CRITICAL: 7 | MEDIUM: 24 | LOW: 24
…and 5 more. Full results in the Security tab. Snippets are redacted; ThreatCrush never prints matched credential material. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Opening the MarkSyncr listing and clicking Add to TronBrowser hung: the install dialog sat spinning, never installed, and would not dismiss.
Why
MarkSyncr is bundled.
build-release.shfetches its CRX and stages it intoextensions/marksyncr, and the launcher loads every extension subdir with--load-extension. The CRX's manifest carries akey, so the bundled copy claims the same extension id as the store listing (hjcjjcpialiakkalcgadnfnoomdaegjg).Clicking Add therefore asked Chromium to install a downloaded CRX over an extension it already had from a command-line (unpacked) location — which a CRX cannot replace. The prompt had nothing to complete and no failure to report, so it never resolved.
install-helper.jsoffered that button unconditionally; it never asked whether the extension was already installed.What changed
The rule is general rather than a special case for the one listing that exposed it — any already-installed extension has the same problem. The service worker looks the id up with
chrome.management(content scripts don't get the API) and the button shows what can actually succeed:✓ Bundled with TronBrowser(inert)✓ Already in TronBrowser(inert)⏻ Enable in TronBrowser— installing again could not have fixed that either⬇ Add from TronBrowser Store⬇ Add to TronBrowser(CWS CRX)The lookup is bounded at 3s and every failure path resolves
null, so an unknown answer falls back to the plain CRX install this button already did. A stalled registry must not decide whether the button works.Adds the
managementpermission, which both the lookup and the enable need.Note for maintainers
A bundled extension can never be updated or reinstalled from the Web Store — a
--load-extensioncopy outranks a downloaded CRX. MarkSyncr updates have to ship through the bundle. Documented in the extension README.Verification
install-state.jsholds the decision as a pure function with 15 new tests, including the MarkSyncr case.🤖 Generated with Claude Code
https://claude.ai/code/session_01XbNfTZM5a6sH1A54dsf7ns