Skip to content

fix: Arc space names on unsynced machines, and Chrome false 'not installed' - #9

Merged
tarikbc merged 3 commits into
mainfrom
worktree-arc-space-names
Sep 14, 2026
Merged

tarikbc merged 3 commits into
mainfrom
worktree-arc-space-names

Conversation

@tarikbc

@tarikbc tarikbc commented Sep 14, 2026 •

Copy link
Copy Markdown
Owner

Fixes two detection bugs reported on Reddit, plus the space-name failure seen in person on a second machine.

1. Arc space names, icons and colors were lost

arc_pinned_tab_extractor read space metadata only from firebaseSyncState.syncData.spaceModels. Arc writes that blob once the profile has synced to its cloud, so a machine that never signed into Arc has no titles there at all, and every space imported as Space <uuid> with no icon and no color.

The local sidebar.containers[1].spaces array carries the same fields (title, customInfo.iconType.emoji_v2, customInfo.windowTheme, profile), is always present, and stays current across renames. The lookup is now built from the local sidebar with the sync blob filling gaps field by field.

This also fixes the "Default Space imports empty" report. Arc gives the default space sentinel ids (thebrowser.company.defaultPersonalSpace*). When that space was missing from the sync blob it got no key in pinned_tabs_by_space, so whenever _get_space_display_order came back empty the code fell through to an empty list and produced a named-but-empty space. Reproduced against a real StorableSidebar.json:

default space name pinned folders
before Space thebrowser.company.defaultPersonalSpaceID 0 0
after Personal 241 37

Unsynced machines also used to drop every Essential tab, because the profile lookup table was empty. That works now too.

Ordering note. _extract_essential_tabs_distributed maps profile → space and keeps the last space for a given profile, so the iteration order of this dict decides where a user's Essential tabs land. The sync blob's ordering is deliberately kept ahead of local-only spaces so the fix cannot silently move anyone's Essential tabs. Verified byte-identical output against a real six-space sidebar: same spaces, same names, same 443 pinned tabs, same placement.

2. Chrome reported "not installed" when it was installed

ChromiumExtractor.is_installed required a profile directory holding a Bookmarks file. Chromium writes that file only after the first bookmark change, so a profile that has been browsed and never bookmarked has History, Cookies, Favicons and Preferences and no Bookmarks.

Confirmed by launching Chrome against a throwaway --user-data-dir:

--- Bookmarks present? ---  NO
--- Preferences present? --- YES
--- History present? ---    YES

profile_paths already accepted Bookmarks or History, so the two disagreed. is_installed now delegates to profile_paths and cannot drift from it again.

Root selection keeps the anti-shadowing behaviour it was protecting. _root_has_profile becomes _root_profile_rank: a root with bookmarks outranks one with only history, which outranks an empty leftover install dir. Both existing Brave-Origin regression tests still pass — a launched-once-then-abandoned Brave-Browser still loses to a live Brave-Origin, and an empty install dir still reports not installed.

Tests

Four new tests, each confirmed failing before the fix:

  • test_arc_space_name_survives_missing_sync_state
  • test_arc_space_name_prefers_local_sidebar_over_stale_sync
  • test_chrome_detected_without_a_bookmarks_file
  • test_chrome_not_detected_when_no_profile_data

Full suite: 82 passed, 1 skipped. ruff check src tests app clean.

Not addressed here

  • Helium support (Reddit request). Helium is a Chromium fork, so it is likely a small ChromiumExtractor subclass, but its User Data path and Keychain service name need verifying on a real install rather than guessing.
  • Essential tabs land in an arbitrary space. Pre-existing and untouched: profile_to_space maps one profile to one space, so when several spaces share a profile (the normal case) the last one wins and all Essential tabs go there. Worth a separate issue.
  • _assign_essential_tab_to_space still hard-codes the space names remoterlabs, gavelmatch.com and willowtree. Also pre-existing, also worth its own issue.

Space names, icons and colors were parsed exclusively from
`firebaseSyncState.syncData.spaceModels`. Arc only writes that blob
once the profile has synced to its cloud, so a machine that had never
signed into Arc imported every space as `Space <uuid>` with no icon and
no color. The local `sidebar.containers[1].spaces` array carries the
same fields, is always present, and stays current across renames.

Build the space lookup from the local sidebar and fall back to the sync
blob field by field. Keeping the sync blob's key ordering first matters:
`_extract_essential_tabs_distributed` collapses several spaces onto one
profile key and keeps the last one, so re-ordering the dict would move a
user's Essential tabs to a different space. Verified byte-identical
output against a real six-space StorableSidebar.json.

Also fixes Essential tabs being dropped entirely on unsynced machines,
where the profile lookup table was previously empty.
`is_installed` required a profile directory holding a `Bookmarks` file,
but Chromium writes that file only after the first bookmark change. A
profile that has been browsed and never bookmarked has History, Cookies,
Favicons and Preferences and no Bookmarks, so a real, working Chrome
install reported as "not installed" (Reddit report: "It's showing that I
don't have Google Chrome installed, but I do"). Verified by launching
Chrome against a throwaway --user-data-dir: the fresh profile has
History and Preferences and no Bookmarks.

`profile_paths` already accepted `Bookmarks` or `History`, so the two
disagreed. `is_installed` now delegates to `profile_paths` and cannot
drift from it again.

Root selection keeps the anti-shadowing behaviour it was protecting.
`_root_has_profile` becomes `_root_profile_rank`: a root with bookmarks
outranks one with only history, which outranks an empty leftover install
dir. A launched-once-then-abandoned Brave-Browser still loses to a live
Brave-Origin, and an empty install dir still reports not installed.
@tarikbc
tarikbc marked this pull request as ready for review September 14, 2026 22:07
@tarikbc
tarikbc merged commit 5bcc98c into main Sep 14, 2026
2 checks passed
@tarikbc
tarikbc deleted the worktree-arc-space-names branch September 14, 2026 22:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant