codex-overleaf-link 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -23
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/runtime-manifest.json +5 -71
- package/extension/src/background.js +53 -69
- package/extension/src/backgroundUpdateCoordinator.js +128 -66
- package/extension/src/content/applyResultFormatters.js +2 -3
- package/extension/src/content/contentRuntime.js +650 -1449
- package/extension/src/content/contextTray.js +4 -6
- package/extension/src/content/diagnosticsController.js +1 -2
- package/extension/src/content/diffReviewPanel.js +14 -13
- package/extension/src/content/generated/content.bundle.js +41370 -0
- package/extension/src/content/generated/content.bundle.meta.json +102 -0
- package/extension/src/content/legacyGlobalRegistry.js +129 -0
- package/extension/src/content/markdownText.js +5 -7
- package/extension/src/content/modelPicker.js +1 -1
- package/extension/src/content/modelPickerSupport.js +10 -5
- package/extension/src/content/moduleRegistryKernel.js +125 -0
- package/extension/src/content/nativeCompatibilityController.js +313 -0
- package/extension/src/content/otWarmMirror.js +7 -5
- package/extension/src/content/pageBridgeClient.js +224 -0
- package/extension/src/content/panelMaintenance.js +8 -3
- package/extension/src/content/postNavigationSettlementPersistence.js +100 -0
- package/extension/src/content/projectProviderSelection.js +4 -12
- package/extension/src/content/projectSessionCleanup.js +3 -3
- package/extension/src/content/providerSettingsCoordinator.js +59 -26
- package/extension/src/content/providerSettingsDialog.js +30 -18
- package/extension/src/content/recentProjects.js +15 -23
- package/extension/src/content/runGuidanceController.js +1 -1
- package/extension/src/content/runQueueScheduler.js +129 -29
- package/extension/src/content/runSettlementPersistence.js +51 -0
- package/extension/src/content/runTimelineView.js +11 -8
- package/extension/src/content/scopedPersistenceCoordinator.js +100 -0
- package/extension/src/content/scopedPersistenceDetachedCommit.js +47 -0
- package/extension/src/content/scopedPersistencePanelState.js +111 -0
- package/extension/src/content/sessionManager.js +15 -12
- package/extension/src/content/sessionPersistence.js +67 -8
- package/extension/src/content/updateNotice.js +10 -4
- package/extension/src/content/writebackOrchestrator.js +91 -23
- package/extension/src/contentScript.js +5 -1
- package/extension/src/page/trackedChangesLifecycle.js +6 -1
- package/extension/src/pageBridge.js +47 -98
- package/extension/src/shared/agentTranscript.js +8 -5
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/governanceRules.js +1 -1
- package/extension/src/shared/managedUpdateProjection.js +337 -0
- package/extension/src/shared/nativeRequestIdentity.js +60 -0
- package/extension/src/shared/otText.js +0 -19
- package/extension/src/shared/pageRpcContract.js +136 -0
- package/extension/src/shared/runExecutionSnapshot.js +177 -0
- package/extension/src/shared/runExecutionSnapshotCodec.js +168 -0
- package/extension/src/shared/runInputQueue.js +81 -34
- package/extension/src/shared/scopedPersistenceBrowserAdapter.js +79 -0
- package/extension/src/shared/scopedPersistenceQueuePolicy.js +181 -0
- package/extension/src/shared/scopedPersistenceTransaction.js +238 -0
- package/extension/src/shared/sessionState.js +64 -48
- package/extension/src/shared/settlementFacts.js +351 -0
- package/extension/src/shared/storageDb.js +19 -5
- package/extension/src/shared/storageMigration.js +275 -61
- package/extension/src/shared/storageSessionClaims.js +60 -0
- package/extension/src/shared/updateConsent.js +4 -0
- package/extension/src/shared/updateRevocationIntent.js +109 -0
- package/extension/src/shared/writebackEvidenceProjection.js +150 -0
- package/extension/src/shared/writebackOperationEvidence.js +143 -0
- package/extension/src/shared/writebackSettlement.js +705 -0
- package/native-host/src/codexRuntimeIdentity.js +1 -1
- package/native-host/src/codexSessionRunner.js +7 -13
- package/native-host/src/index.js +3 -69
- package/native-host/src/managedInstall.js +50 -8
- package/native-host/src/nativeTransportEnvelope.js +148 -0
- package/native-host/src/taskRunnerRuntime.js +3 -3
- package/package.json +13 -5
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
(function initStorageMigration(root, factory) {
|
|
2
2
|
if (typeof module === 'object' && module.exports) {
|
|
3
|
-
module.exports = factory();
|
|
3
|
+
module.exports = factory(require('./storageDb'));
|
|
4
4
|
} else {
|
|
5
|
-
root.
|
|
5
|
+
root.CodexOverleafModuleRegistry.define('StorageMigration', ['StorageDb'], factory);
|
|
6
6
|
}
|
|
7
|
-
})(typeof globalThis !== 'undefined' ? globalThis : window, function storageMigrationFactory() {
|
|
7
|
+
})(typeof globalThis !== 'undefined' ? globalThis : window, function storageMigrationFactory(StorageDb) {
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
10
|
var PREFS_KEY = 'codexOverleafPrefs';
|
|
@@ -13,74 +13,249 @@
|
|
|
13
13
|
var MAX_DELETED_SESSION_IDS_PER_PROJECT = 100;
|
|
14
14
|
var CUSTOM_INSTRUCTIONS_MAX_CHARS = 12000;
|
|
15
15
|
var PROJECT_PREF_KEY_MAX_CHARS = 160;
|
|
16
|
+
var PROJECT_SCOPED_PREF_MAPS = [
|
|
17
|
+
'activeSessionByProject',
|
|
18
|
+
'experimentalOtByProject',
|
|
19
|
+
'customInstructionsByProject',
|
|
20
|
+
'governanceRulesByProject',
|
|
21
|
+
'selectedLocalSkillIdsByProject'
|
|
22
|
+
];
|
|
23
|
+
var projectPreferenceLockTails = {};
|
|
16
24
|
|
|
17
|
-
function
|
|
18
|
-
var
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
function buildScopedProjectPreferenceKey(accountScopeId, projectId) {
|
|
26
|
+
var account = compactScopePart(accountScopeId);
|
|
27
|
+
var project = compactScopePart(projectId);
|
|
28
|
+
return account && project ? 'account:' + account + ':project:' + project : '';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function compactScopePart(value) {
|
|
32
|
+
var text = normalizeTextField(value, PROJECT_PREF_KEY_MAX_CHARS);
|
|
33
|
+
if (!text) {
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
var encoded = encodeURIComponent(text);
|
|
37
|
+
if (encoded.length <= 64) {
|
|
38
|
+
return encoded;
|
|
39
|
+
}
|
|
40
|
+
return encoded.slice(0, 48) + '-' + hashText(encoded);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function hashText(value) {
|
|
44
|
+
var hash = 2166136261;
|
|
45
|
+
for (var i = 0; i < value.length; i++) {
|
|
46
|
+
hash ^= value.charCodeAt(i);
|
|
47
|
+
hash = Math.imul(hash, 16777619);
|
|
48
|
+
}
|
|
49
|
+
return (hash >>> 0).toString(36);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function withProjectPreferenceLock(projectId, work) {
|
|
53
|
+
var lockName = 'codex-overleaf-project-prefs:' + compactScopePart(projectId);
|
|
54
|
+
var lockManager = typeof navigator !== 'undefined' && navigator && navigator.locks;
|
|
55
|
+
if (lockManager && typeof lockManager.request === 'function') {
|
|
56
|
+
return lockManager.request(lockName, work);
|
|
57
|
+
}
|
|
58
|
+
var previous = projectPreferenceLockTails[lockName] || Promise.resolve();
|
|
59
|
+
var current = previous.then(work, work);
|
|
60
|
+
projectPreferenceLockTails[lockName] = current;
|
|
61
|
+
return current.finally(function () {
|
|
62
|
+
if (projectPreferenceLockTails[lockName] === current) {
|
|
63
|
+
delete projectPreferenceLockTails[lockName];
|
|
36
64
|
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
37
67
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
68
|
+
function copyPreferenceValue(value) {
|
|
69
|
+
if (!value || typeof value !== 'object') {
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
return JSON.parse(JSON.stringify(value));
|
|
74
|
+
} catch (_error) {
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function claimLegacyProjectPreferences(prefs, accountScopeId, projectId) {
|
|
80
|
+
var scopedKey = buildScopedProjectPreferenceKey(accountScopeId, projectId);
|
|
81
|
+
var next = normalizePrefs(prefs);
|
|
82
|
+
var changed = false;
|
|
83
|
+
PROJECT_SCOPED_PREF_MAPS.forEach(function (mapName) {
|
|
84
|
+
var source = next[mapName] && typeof next[mapName] === 'object'
|
|
85
|
+
? Object.assign({}, next[mapName])
|
|
86
|
+
: {};
|
|
87
|
+
if (Object.prototype.hasOwnProperty.call(source, projectId)) {
|
|
88
|
+
if (!Object.prototype.hasOwnProperty.call(source, scopedKey)) {
|
|
89
|
+
source[scopedKey] = copyPreferenceValue(source[projectId]);
|
|
90
|
+
}
|
|
91
|
+
delete source[projectId];
|
|
92
|
+
changed = true;
|
|
93
|
+
}
|
|
94
|
+
next[mapName] = source;
|
|
95
|
+
});
|
|
96
|
+
return { prefs: next, changed: changed };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function buildProjectPreferenceView(prefs, accountScopeId, projectId) {
|
|
100
|
+
var source = normalizePrefs(prefs);
|
|
101
|
+
var scopedKey = buildScopedProjectPreferenceKey(accountScopeId, projectId);
|
|
102
|
+
var view = Object.assign({}, source);
|
|
103
|
+
PROJECT_SCOPED_PREF_MAPS.forEach(function (mapName) {
|
|
104
|
+
var sourceMap = source[mapName] && typeof source[mapName] === 'object'
|
|
105
|
+
? source[mapName]
|
|
106
|
+
: {};
|
|
107
|
+
var projectMap = {};
|
|
108
|
+
if (Object.prototype.hasOwnProperty.call(sourceMap, scopedKey)) {
|
|
109
|
+
projectMap[projectId] = copyPreferenceValue(sourceMap[scopedKey]);
|
|
51
110
|
}
|
|
111
|
+
view[mapName] = projectMap;
|
|
112
|
+
});
|
|
113
|
+
return normalizePrefs(view);
|
|
114
|
+
}
|
|
52
115
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
116
|
+
function mergeScopedProjectPreferences(existingPrefs, incomingPrefs, accountScopeId, projectId) {
|
|
117
|
+
var existing = normalizePrefs(existingPrefs);
|
|
118
|
+
var incoming = normalizePrefs(incomingPrefs);
|
|
119
|
+
var scopedKey = buildScopedProjectPreferenceKey(accountScopeId, projectId);
|
|
120
|
+
var next = Object.assign({}, existing, incoming);
|
|
121
|
+
PROJECT_SCOPED_PREF_MAPS.forEach(function (mapName) {
|
|
122
|
+
var storedMap = existing[mapName] && typeof existing[mapName] === 'object'
|
|
123
|
+
? Object.assign({}, existing[mapName])
|
|
124
|
+
: {};
|
|
125
|
+
var incomingMap = incoming[mapName] && typeof incoming[mapName] === 'object'
|
|
126
|
+
? incoming[mapName]
|
|
127
|
+
: {};
|
|
128
|
+
if (Object.prototype.hasOwnProperty.call(incomingMap, projectId)) {
|
|
129
|
+
storedMap[scopedKey] = copyPreferenceValue(incomingMap[projectId]);
|
|
130
|
+
}
|
|
131
|
+
delete storedMap[projectId];
|
|
132
|
+
next[mapName] = storedMap;
|
|
133
|
+
});
|
|
134
|
+
return normalizePrefs(next);
|
|
135
|
+
}
|
|
56
136
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
137
|
+
function runMigrationIfNeeded(projectId, legacyStorageKey, accountScopeId) {
|
|
138
|
+
projectId = normalizeProjectPrefKey(projectId);
|
|
139
|
+
var normalizedAccountScopeId = normalizeTextField(accountScopeId, PROJECT_PREF_KEY_MAX_CHARS);
|
|
140
|
+
if (!normalizedAccountScopeId || !projectId) {
|
|
141
|
+
return Promise.resolve({
|
|
142
|
+
prefs: normalizePrefs({}),
|
|
143
|
+
sessions: [],
|
|
144
|
+
activeSessionId: '',
|
|
145
|
+
migrated: false,
|
|
146
|
+
reason: 'account_scope_unavailable'
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return withProjectPreferenceLock(projectId, function () {
|
|
150
|
+
return chrome.storage.local.get(null).then(function (stored) {
|
|
151
|
+
var claimed = claimLegacyProjectPreferences(
|
|
152
|
+
stored[PREFS_KEY] || {},
|
|
153
|
+
normalizedAccountScopeId,
|
|
154
|
+
projectId
|
|
63
155
|
);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
156
|
+
var storedPrefs = claimed.prefs;
|
|
157
|
+
var persistClaim = claimed.changed
|
|
158
|
+
? chrome.storage.local.set({ [PREFS_KEY]: storedPrefs })
|
|
159
|
+
: Promise.resolve();
|
|
160
|
+
return persistClaim.then(function () {
|
|
161
|
+
var prefs = buildProjectPreferenceView(
|
|
162
|
+
storedPrefs,
|
|
163
|
+
normalizedAccountScopeId,
|
|
164
|
+
projectId
|
|
165
|
+
);
|
|
166
|
+
var tombstones = collectSessionTombstones(stored);
|
|
167
|
+
var deletedSessionIds = getDeletedSessionIds(tombstones, projectId);
|
|
168
|
+
var schemaVersion = prefs.storageSchemaVersion || 0;
|
|
169
|
+
|
|
170
|
+
if (schemaVersion >= StorageDb.TARGET_SCHEMA_VERSION) {
|
|
171
|
+
var activeSessionByProject = prefs.activeSessionByProject || {};
|
|
172
|
+
var activeSessionId = activeSessionByProject[projectId] || '';
|
|
173
|
+
if (typeof StorageDb.claimSessionsForAccount !== 'function') {
|
|
174
|
+
return Promise.reject(Object.assign(
|
|
175
|
+
new Error('Atomic legacy-session claiming is unavailable.'),
|
|
176
|
+
{ code: 'scoped_claim_unavailable' }
|
|
177
|
+
));
|
|
178
|
+
}
|
|
179
|
+
return StorageDb.claimSessionsForAccount(
|
|
180
|
+
projectId,
|
|
181
|
+
normalizedAccountScopeId,
|
|
182
|
+
deletedSessionIds
|
|
183
|
+
).then(function (visibleSessions) {
|
|
184
|
+
var visibleActiveSessionId = visibleSessions.some(function (session) {
|
|
185
|
+
return session && session.id === activeSessionId;
|
|
186
|
+
})
|
|
187
|
+
? activeSessionId
|
|
188
|
+
: visibleSessions.length
|
|
189
|
+
? visibleSessions[visibleSessions.length - 1].id
|
|
190
|
+
: '';
|
|
191
|
+
return {
|
|
192
|
+
prefs: prefs,
|
|
193
|
+
sessions: visibleSessions,
|
|
194
|
+
activeSessionId: visibleActiveSessionId,
|
|
195
|
+
migrated: false
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Migration v0 → v1
|
|
201
|
+
var legacyBlob = stored[legacyStorageKey] || {};
|
|
202
|
+
var legacySessions = Array.isArray(legacyBlob.sessions) ? legacyBlob.sessions : [];
|
|
203
|
+
var migratedSessions = [];
|
|
204
|
+
|
|
205
|
+
for (var i = 0; i < legacySessions.length; i++) {
|
|
206
|
+
var legacy = legacySessions[i];
|
|
207
|
+
if (!legacy || !legacy.id) { continue; }
|
|
208
|
+
if (deletedSessionIds.indexOf(legacy.id) !== -1) { continue; }
|
|
209
|
+
var record = StorageDb.buildSessionRecord(
|
|
210
|
+
buildLegacySessionRecordInput(projectId, legacyBlob, legacy, normalizedAccountScopeId)
|
|
211
|
+
);
|
|
212
|
+
migratedSessions.push(record);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
var putPromise = migratedSessions.length
|
|
216
|
+
? StorageDb.putRecords('sessions', migratedSessions)
|
|
217
|
+
: Promise.resolve([]);
|
|
218
|
+
|
|
219
|
+
return putPromise.then(function () {
|
|
220
|
+
var newPrefs = StorageDb.extractLightweightPrefs(legacyBlob, projectId);
|
|
221
|
+
newPrefs.activeSessionByProject = StorageDb.buildActiveSessionByProject(
|
|
222
|
+
{},
|
|
223
|
+
projectId,
|
|
224
|
+
legacyBlob.activeSessionId || (migratedSessions.length ? migratedSessions[migratedSessions.length - 1].id : '')
|
|
225
|
+
);
|
|
226
|
+
var mergedPrefs = mergeScopedProjectPreferences(
|
|
227
|
+
storedPrefs,
|
|
228
|
+
newPrefs,
|
|
229
|
+
normalizedAccountScopeId,
|
|
230
|
+
projectId
|
|
231
|
+
);
|
|
232
|
+
var prefsView = buildProjectPreferenceView(
|
|
233
|
+
mergedPrefs,
|
|
234
|
+
normalizedAccountScopeId,
|
|
235
|
+
projectId
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
return chrome.storage.local.set({ [PREFS_KEY]: mergedPrefs }).then(function () {
|
|
239
|
+
return chrome.storage.local.remove(legacyStorageKey).catch(function () {});
|
|
240
|
+
}).then(function () {
|
|
241
|
+
return {
|
|
242
|
+
prefs: prefsView,
|
|
243
|
+
sessions: migratedSessions,
|
|
244
|
+
activeSessionId: prefsView.activeSessionByProject[projectId] || '',
|
|
245
|
+
migrated: true
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
});
|
|
75
249
|
});
|
|
76
250
|
});
|
|
77
251
|
});
|
|
78
252
|
}
|
|
79
253
|
|
|
80
|
-
function buildLegacySessionRecordInput(projectId, legacyBlob, legacy) {
|
|
254
|
+
function buildLegacySessionRecordInput(projectId, legacyBlob, legacy, accountScopeId) {
|
|
81
255
|
return {
|
|
82
256
|
id: legacy.id,
|
|
83
257
|
projectId: projectId,
|
|
258
|
+
accountScopeId: accountScopeId,
|
|
84
259
|
title: legacy.title || '',
|
|
85
260
|
titleSource: legacy.titleSource === 'manual' ? 'manual' : 'auto',
|
|
86
261
|
codexThreadId: '',
|
|
@@ -100,13 +275,51 @@
|
|
|
100
275
|
};
|
|
101
276
|
}
|
|
102
277
|
|
|
103
|
-
function savePrefs(prefs) {
|
|
104
|
-
|
|
278
|
+
function savePrefs(prefs, accountScopeId, projectId) {
|
|
279
|
+
var account = normalizeTextField(accountScopeId, PROJECT_PREF_KEY_MAX_CHARS);
|
|
280
|
+
var project = normalizeProjectPrefKey(projectId);
|
|
281
|
+
if (!account && !project) {
|
|
282
|
+
return chrome.storage.local.set({ [PREFS_KEY]: normalizePrefs(prefs) });
|
|
283
|
+
}
|
|
284
|
+
if (!account || !project) {
|
|
285
|
+
return Promise.reject(Object.assign(
|
|
286
|
+
new Error('Scoped project preferences require account and project identity.'),
|
|
287
|
+
{ code: 'account_scope_unavailable' }
|
|
288
|
+
));
|
|
289
|
+
}
|
|
290
|
+
return withProjectPreferenceLock(project, function () {
|
|
291
|
+
return chrome.storage.local.get([PREFS_KEY]).then(function (stored) {
|
|
292
|
+
var claimed = claimLegacyProjectPreferences(stored[PREFS_KEY] || {}, account, project);
|
|
293
|
+
var next = mergeScopedProjectPreferences(claimed.prefs, prefs, account, project);
|
|
294
|
+
return chrome.storage.local.set({ [PREFS_KEY]: next });
|
|
295
|
+
});
|
|
296
|
+
});
|
|
105
297
|
}
|
|
106
298
|
|
|
107
|
-
function loadPrefs() {
|
|
108
|
-
|
|
109
|
-
|
|
299
|
+
function loadPrefs(accountScopeId, projectId) {
|
|
300
|
+
var account = normalizeTextField(accountScopeId, PROJECT_PREF_KEY_MAX_CHARS);
|
|
301
|
+
var project = normalizeProjectPrefKey(projectId);
|
|
302
|
+
if (!account && !project) {
|
|
303
|
+
return chrome.storage.local.get([PREFS_KEY]).then(function (stored) {
|
|
304
|
+
return normalizePrefs(stored[PREFS_KEY] || {});
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
if (!account || !project) {
|
|
308
|
+
return Promise.reject(Object.assign(
|
|
309
|
+
new Error('Scoped project preferences require account and project identity.'),
|
|
310
|
+
{ code: 'account_scope_unavailable' }
|
|
311
|
+
));
|
|
312
|
+
}
|
|
313
|
+
return withProjectPreferenceLock(project, function () {
|
|
314
|
+
return chrome.storage.local.get([PREFS_KEY]).then(function (stored) {
|
|
315
|
+
var claimed = claimLegacyProjectPreferences(stored[PREFS_KEY] || {}, account, project);
|
|
316
|
+
var persisted = claimed.changed
|
|
317
|
+
? chrome.storage.local.set({ [PREFS_KEY]: claimed.prefs })
|
|
318
|
+
: Promise.resolve();
|
|
319
|
+
return persisted.then(function () {
|
|
320
|
+
return buildProjectPreferenceView(claimed.prefs, account, project);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
110
323
|
});
|
|
111
324
|
}
|
|
112
325
|
|
|
@@ -278,6 +491,7 @@
|
|
|
278
491
|
return {
|
|
279
492
|
PREFS_KEY: PREFS_KEY,
|
|
280
493
|
SESSION_TOMBSTONES_KEY: SESSION_TOMBSTONES_KEY,
|
|
494
|
+
buildScopedProjectPreferenceKey: buildScopedProjectPreferenceKey,
|
|
281
495
|
runMigrationIfNeeded: runMigrationIfNeeded,
|
|
282
496
|
savePrefs: savePrefs,
|
|
283
497
|
loadPrefs: loadPrefs,
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
(function initStorageSessionClaims(root, factory) {
|
|
2
|
+
var api = factory();
|
|
3
|
+
if (typeof module === 'object' && module.exports) module.exports = api;
|
|
4
|
+
if (root) root.CodexOverleafStorageSessionClaims = api;
|
|
5
|
+
})(typeof globalThis !== 'undefined' ? globalThis : this, function storageSessionClaimsFactory() {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
function createSessionClaimer(openDb, getKeyRange) {
|
|
9
|
+
return function claimSessionsForAccount(projectId, accountScopeId, deletedSessionIds) {
|
|
10
|
+
var normalizedProjectId = typeof projectId === 'string' ? projectId.trim() : '';
|
|
11
|
+
var normalizedAccountScopeId = typeof accountScopeId === 'string' ? accountScopeId.trim() : '';
|
|
12
|
+
if (!normalizedProjectId || !normalizedAccountScopeId) {
|
|
13
|
+
return Promise.reject(Object.assign(
|
|
14
|
+
new Error('A project and account scope are required to claim legacy sessions.'),
|
|
15
|
+
{ code: !normalizedAccountScopeId ? 'account_scope_unavailable' : 'project_scope_unavailable' }
|
|
16
|
+
));
|
|
17
|
+
}
|
|
18
|
+
var deleted = {};
|
|
19
|
+
(Array.isArray(deletedSessionIds) ? deletedSessionIds : []).forEach(function (id) {
|
|
20
|
+
if (typeof id === 'string' && id) deleted[id] = true;
|
|
21
|
+
});
|
|
22
|
+
return openDb().then(function (db) {
|
|
23
|
+
return new Promise(function (resolve, reject) {
|
|
24
|
+
var visible = [];
|
|
25
|
+
var tx = db.transaction('sessions', 'readwrite');
|
|
26
|
+
var store = tx.objectStore('sessions');
|
|
27
|
+
var index = store.index('projectId');
|
|
28
|
+
var request = index.openCursor(getKeyRange().only(normalizedProjectId));
|
|
29
|
+
request.onsuccess = function (event) {
|
|
30
|
+
var cursor = event.target.result;
|
|
31
|
+
if (!cursor) return;
|
|
32
|
+
var record = cursor.value;
|
|
33
|
+
if (record && !deleted[record.id]) {
|
|
34
|
+
var recordScopeId = typeof record.accountScopeId === 'string'
|
|
35
|
+
? record.accountScopeId.trim()
|
|
36
|
+
: '';
|
|
37
|
+
if (recordScopeId === normalizedAccountScopeId) {
|
|
38
|
+
visible.push(record);
|
|
39
|
+
} else if (!recordScopeId) {
|
|
40
|
+
var claimed = Object.assign({}, record, {
|
|
41
|
+
accountScopeId: normalizedAccountScopeId,
|
|
42
|
+
accountScopeUnavailable: false
|
|
43
|
+
});
|
|
44
|
+
cursor.update(claimed);
|
|
45
|
+
visible.push(claimed);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
cursor.continue();
|
|
49
|
+
};
|
|
50
|
+
request.onerror = function (event) { reject(event.target.error); };
|
|
51
|
+
tx.oncomplete = function () { resolve(visible); };
|
|
52
|
+
tx.onerror = function (event) { reject(event.target.error || tx.error); };
|
|
53
|
+
tx.onabort = function (event) { reject(event.target.error || tx.error); };
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return Object.freeze({ createSessionClaimer: createSessionClaimer });
|
|
60
|
+
});
|
|
@@ -87,6 +87,10 @@
|
|
|
87
87
|
authorizedVersion: safeVersion(value.authorizedVersion),
|
|
88
88
|
authorizationId: safeId(value.authorizationId),
|
|
89
89
|
authorizedAt: finiteNumber(value.authorizedAt),
|
|
90
|
+
revokingAuthorizationId: safeId(value.revokingAuthorizationId),
|
|
91
|
+
revokingVersion: safeVersion(value.revokingVersion),
|
|
92
|
+
revokingTransactionId: safeId(value.revokingTransactionId),
|
|
93
|
+
revokingAt: finiteNumber(value.revokingAt),
|
|
90
94
|
lastPromptedVersion: safeVersion(value.lastPromptedVersion),
|
|
91
95
|
lastPromptedAt: finiteNumber(value.lastPromptedAt)
|
|
92
96
|
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
(function initUpdateRevocationIntent(root, factory) {
|
|
2
|
+
const api = factory();
|
|
3
|
+
if (typeof module === "object" && module.exports) {
|
|
4
|
+
module.exports = api;
|
|
5
|
+
}
|
|
6
|
+
if (root) {
|
|
7
|
+
root.CodexOverleafUpdateRevocation = api;
|
|
8
|
+
}
|
|
9
|
+
})(typeof globalThis !== "undefined" ? globalThis : this, function createUpdateRevocationIntent() {
|
|
10
|
+
"use strict";
|
|
11
|
+
|
|
12
|
+
function safeString(value) {
|
|
13
|
+
return typeof value === "string" ? value.trim() : "";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function safeTime(value, fallback = 0) {
|
|
17
|
+
return Number.isFinite(value) && value >= 0 ? value : fallback;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function begin(consentState, updateState, now = Date.now()) {
|
|
21
|
+
const consent = consentState && typeof consentState === "object" ? consentState : {};
|
|
22
|
+
const update = updateState && typeof updateState === "object" ? updateState : {};
|
|
23
|
+
return {
|
|
24
|
+
...consent,
|
|
25
|
+
revokingAuthorizationId: safeString(consent.authorizationId),
|
|
26
|
+
revokingVersion:
|
|
27
|
+
safeString(consent.authorizedVersion) || safeString(update.latestVersion),
|
|
28
|
+
revokingTransactionId: safeString(update.transactionId),
|
|
29
|
+
revokingAt: safeTime(now)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function prepareAuthorization(consentState, authorizationId, targetVersion, now = Date.now()) {
|
|
34
|
+
const consent = consentState && typeof consentState === "object" ? consentState : {};
|
|
35
|
+
return {
|
|
36
|
+
...consent,
|
|
37
|
+
revokingAuthorizationId: safeString(authorizationId),
|
|
38
|
+
revokingVersion: safeString(targetVersion),
|
|
39
|
+
revokingTransactionId: "",
|
|
40
|
+
revokingAt: safeTime(now)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function hasPending(consentState) {
|
|
45
|
+
const consent = consentState && typeof consentState === "object" ? consentState : {};
|
|
46
|
+
return Boolean(
|
|
47
|
+
safeString(consent.revokingAuthorizationId) &&
|
|
48
|
+
safeString(consent.revokingVersion)
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function clear(consentState) {
|
|
53
|
+
const consent = consentState && typeof consentState === "object" ? consentState : {};
|
|
54
|
+
return {
|
|
55
|
+
...consent,
|
|
56
|
+
revokingAuthorizationId: "",
|
|
57
|
+
revokingVersion: "",
|
|
58
|
+
revokingTransactionId: "",
|
|
59
|
+
revokingAt: 0
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function complete(updateState, consentState, options = {}) {
|
|
64
|
+
const update = updateState && typeof updateState === "object" ? updateState : {};
|
|
65
|
+
const consent = consentState && typeof consentState === "object" ? consentState : {};
|
|
66
|
+
const now = safeTime(options.now, Date.now());
|
|
67
|
+
const snoozeMs = safeTime(options.snoozeMs);
|
|
68
|
+
const version =
|
|
69
|
+
safeString(consent.revokingVersion) ||
|
|
70
|
+
safeString(consent.authorizedVersion) ||
|
|
71
|
+
safeString(update.latestVersion);
|
|
72
|
+
return {
|
|
73
|
+
updateState: {
|
|
74
|
+
...update,
|
|
75
|
+
state: "update_available",
|
|
76
|
+
transactionId: "",
|
|
77
|
+
stagedPath: "",
|
|
78
|
+
stagedAt: 0,
|
|
79
|
+
applyingAt: 0,
|
|
80
|
+
awaitingHealthAt: 0,
|
|
81
|
+
blocker: "",
|
|
82
|
+
blockers: [],
|
|
83
|
+
blockingReason: "",
|
|
84
|
+
code: "",
|
|
85
|
+
message: "",
|
|
86
|
+
error: null,
|
|
87
|
+
postponeUntil: safeTime(options.postponeUntil),
|
|
88
|
+
postponeGuardVersion: version
|
|
89
|
+
},
|
|
90
|
+
consentState: clear({
|
|
91
|
+
...consent,
|
|
92
|
+
mode: "snoozed",
|
|
93
|
+
snoozedVersion: version,
|
|
94
|
+
snoozedUntil: now + snoozeMs,
|
|
95
|
+
authorizedVersion: "",
|
|
96
|
+
authorizationId: "",
|
|
97
|
+
authorizedAt: 0
|
|
98
|
+
})
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return Object.freeze({
|
|
103
|
+
begin,
|
|
104
|
+
prepareAuthorization,
|
|
105
|
+
hasPending,
|
|
106
|
+
clear,
|
|
107
|
+
complete
|
|
108
|
+
});
|
|
109
|
+
});
|