Repository navigation
Add syncing settings to a GitHub Gist - #4950
xianghongai wants to merge 1 commit into
Conversation
|
Here's what the new section looks like at the bottom of the options page, under Backup and Restore (the Gist ID is a placeholder): Setting it up from scratch:
The new controls follow the layout of the existing settings rows, and none of them affect anything unless the user fills them in. |
The options page can now sync settings with a vimium-options.json file in a secret gist, using the same format as the backup file: - Upload to the gist (overwrites the remote file), and restore from it. - Optionally upload automatically whenever settings change. - Create a secret gist from the options page, or paste an existing one. - A link to GitHub's token form, pre-filled with the "gist" scope. - List the gist's 10 most recent revisions and restore any of them. The GitHub token and gist ID are kept in chrome.storage.local so they're never included in the settings, backups, or the gist itself. Also fix the chrome.storage test stub's get() when given an array of keys.
|
Hi @xianghongai, could you update the README file on this PR to include the steps needed to utilize it? It might also be helpful to include links/screenshots on how to generate the gist token. |
Thanks for the suggestion and for taking a look! I’d actually lean against adding this to the main
The comment and screenshots I left on the PR were mainly to provide context for the maintainers to evaluate the implementation. Really appreciate your feedback and input, though! |

Description
This adds optional syncing of Vimium's settings to a GitHub Gist, revisiting #4084 (closed as not planned). I know that issue raised two concerns, so I've tried to address both directly in the design below, and to keep the feature entirely opt-in and isolated from the existing settings path.
Why a Gist?
chrome.storage.synconly syncs within one browser vendor and one account. Many Vimium users run several browsers (Chrome + Firefox), several profiles (work / personal), or machines where browser sync is disabled by policy. Today they keep their key mappings in step by hand with the backup/restore file. A Gist is a natural home for that file: it's versioned, private when secret, and already familiar to the people who write custom key mappings. #2719 asked for essentially the same thing.Addressing the concerns in #4084
1. "Pasting a GitHub token is clunky UX." Vimium's audience already edits key mappings, writes CSS for link hints and configures search engines by URL template, so creating a token is well within reach. The options page also makes it a two-click flow:
github.com/settings/tokens/new?description=Vimium%20Gist%20Sync&scopes=gist. GitHub's form opens with the note filled in and only thegistscope ticked. The hint next to the field tells the user to set Expiration to "No expiration" (GitHub doesn't support pre-filling that), then click Generate token and paste it.2. "Persistence would have to handle network failures." It doesn't need to, because the Gist is never the source of truth. Settings are still saved to
chrome.storage.syncexactly as today, andSettingsis not modified. Gist sync is a separate layer on top:Design
flowchart LR subgraph Browser O["Options page<br/>(pages/options.js)"] S[("chrome.storage.sync<br/>Vimium settings")] L[("chrome.storage.local<br/>token, gist ID,<br/>auto-upload flag, status")] B["Background page<br/>(main.js)"] G["gist_sync.js"] end GH[("GitHub Gist<br/>vimium-options.json<br/>+ revision history")] O -- "Save (unchanged)" --> S S -- "Settings 'change' event" --> B B -- "debounced auto-upload<br/>(opt-in, skipped if unchanged)" --> G O -- "Upload / Restore /<br/>Create gist / History" --> G G -- "reads config" --> L G -- "PATCH /gists/:id<br/>(overwrite file)" --> GH GH -- "GET /gists/:id<br/>GET /gists/:id/:sha" --> G G -- "Settings.setSettings()<br/>(existing migration path)" --> Svimium-options.jsonproduced by the same serializer as Download backup.prepareBackupSettings()now calls the sharedserializeSettings(), so a gist file and a backup file are interchangeable. Other files in the gist are left untouched.Settings.setSettings(), just like Restore from a backup file does, so older settings files go through the normal migrations.chrome.storage.local. They're not inchrome.storage.sync, so they are never in backups, never uploaded to the gist, and never synced by the browser. The options page fields are kept out of the settings form, so typing in them doesn't enable Save changes.<all_urls>already allows requests toapi.github.com, somanifest.jsonis unchanged and this works on Chrome and Firefox alike.Changes
background_scripts/gist_sync.jsserializeSettings,upload,download,createGist,testConnection,listRevisions,restoreRevision, debounced auto-uploadbackground_scripts/main.jsSettings"change" eventpages/options.{html,js,css}tests/unit_tests/gist_sync_test.jsfetchstubbedtests/unit_tests/test_chrome_stubs.jsget()when given an array of keys (for (key of …)referenced an undeclared variable)Testing
./make.js test-unit: 232/232 pass../make.js checkis clean.Size
I'm aware this is well over the ~50 LOC guideline. About 170 of the lines are tests, and the feature is self-contained: it doesn't change any existing behavior unless a user opts in. If you'd prefer a smaller first step, it could be split into (1) manual upload/restore and (2) auto-upload plus history. I'm happy to rework it, or to keep it in my fork if it's out of scope for mainline Vimium.
Refs #4084, #2719.