Skip to content

Commit 33206a1

Browse files
authored
Merge pull request #16 from tomayac/no-description
Remove `description`
2 parents 636c21d + 350030a commit 33206a1

File tree

6 files changed

+64
-102
lines changed

6 files changed

+64
-102
lines changed

README.md

Lines changed: 48 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<img src="https://raw.githubusercontent.com/tomayac/cross-origin-storage/refs/heads/main/logo-cos.svg" alt="Cross-Origin Storage (COS) logo, consisting of a folder icon with a crossing person." width="100">
44

5-
This proposal outlines the design of the **Cross-Origin Storage (COS)** API, which allows web applications to store and retrieve files across different origins with explicit user consent. Using concepts introduced in **File System Living Standard** defined by the WHATWG, the COS API facilitates secure cross-origin file storage and retrieval for large files, such as AI models, SQLite databases, offline storage archives, and WebAssembly (Wasm) modules. Taking inspiration from **Cache Digests for HTTP/2**, the API uses file hashes for integrity, while human-readable descriptions allow for permission management.
5+
This proposal outlines the design of the **Cross-Origin Storage (COS)** API, which allows web applications to store and retrieve files across different origins with explicit user consent. Using concepts introduced in **File System Living Standard** defined by the WHATWG, the COS API facilitates secure cross-origin file storage and retrieval for large files, such as AI models, SQLite databases, offline storage archives, and WebAssembly (Wasm) modules. Taking inspiration from **Cache Digests for HTTP/2**, the API uses file hashes for integrity.
66

77
This proposal is an early design sketch by Chrome Developer Relations to describe the problem below and solicit feedback on the proposed solution. It has not been approved to ship in Chrome.
88

@@ -19,28 +19,25 @@ This proposal is an early design sketch by Chrome Developer Relations to describ
1919

2020
## Introduction
2121

22-
The **Cross-Origin Storage (COS)** API provides a cross-origin file storage and retrieval mechanism for web applications. It allows applications to store and access large files, such as AI models, SQLite databases, offline storage archives, and Wasm modules across different origins securely and with user consent. Taking inspiration from **Cache Digests for HTTP/2**, files are identified by their hashes to ensure integrity, and human-readable descriptions need to be assigned to files for permission management. The API uses concepts like `FileSystemFileHandle` from the **File System Living Standard** with a focus on cross-origin usage. Here is an example that shows the basic flow for retrieving a file from COS:
22+
The **Cross-Origin Storage (COS)** API provides a cross-origin file storage and retrieval mechanism for web applications. It allows applications to store and access large files, such as AI models, SQLite databases, offline storage archives, and Wasm modules across different origins securely and with user consent. Taking inspiration from **Cache Digests for HTTP/2**, files are identified by their hashes to ensure integrity. The API uses concepts like `FileSystemFileHandle` from the **File System Living Standard** with a focus on cross-origin usage. Here is an example that shows the basic flow for retrieving a file from COS:
2323

2424
```js
2525
// The hash of the file we want to access.
2626
const hash = {
2727
algorithm: 'SHA-256',
2828
value: '8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4',
2929
};
30-
// The human-readable file description.
31-
const description = 'Large AI Model';
32-
3330
// This triggers a permission prompt:
34-
// example.com wants to check if the file "Large AI Model" is stored by your browser.
31+
// example.com wants to check if your browser already has a file it needs,
32+
// possibly saved from another site. If found, it will use the file without
33+
// changing it.
3534
// [Allow this time] [Allow on every visit] [Don't allow]
3635
try {
37-
const handle = await navigator.crossOriginStorage.requestFileHandle(hash, {
38-
description,
39-
});
36+
const handle = await navigator.crossOriginStorage.requestFileHandle(hash);
4037
// The file exists in Cross-Origin Storage.
4138
const fileBlob = await handle.getFile();
4239
// Do something with the blob.
43-
console.log('Retrieved', description, fileBlob);
40+
console.log('Retrieved', fileBlob);
4441
} catch (err) {
4542
if (err.name === 'NotAllowedError') {
4643
console.log('The user did not grant permission to access the file.');
@@ -62,8 +59,7 @@ COS aims to:
6259

6360
- Provide a cross-origin storage mechanism for web applications to store and retrieve large files like AI models, SQLite databases, offline storage archives (for example, complete website archives at the scale of Wikipedia), and Wasm modules.
6461
- Ensure security and user control with explicit consent before accessing or storing files.
65-
- Use SHA-256 hashes (see [Appendix B](#appendix-b-blob-hash-with-the-web-crypto-api)) for file identification, guaranteeing data integrity and consistency.
66-
- Require developers to assign human-readable descriptions to files for permission management.
62+
- Use SHA-256 hashes (see [Appendix&nbsp;B](#appendix-b-blob-hash-with-the-web-crypto-api)) for file identification, guaranteeing data integrity and consistency.
6763

6864
## Non-goals
6965

@@ -111,14 +107,14 @@ Web applications that utilize large Wasm modules can store these modules using C
111107

112108
### File Storage Process
113109

114-
The **COS** API will be available through the `navigator.crossOriginStorage` interface. Files will be stored and retrieved using their hashes, ensuring that each file is uniquely identified. A human-readable description needs to be provided for permission management of files.
110+
The **COS** API will be available through the `navigator.crossOriginStorage` interface. Files will be stored and retrieved using their hashes, ensuring that each file is uniquely identified.
115111

116112
#### Storing a file
117113

118-
1. Hash the contents of the file using SHA-256 (or an equivalent secure algorithm, see [Appendix B](#appendix-b-blob-hash-with-the-web-crypto-api)). The used hash algorithm is communicated as a valid [`HashAlgorithmIdentifier`](https://w3c.github.io/webcrypto/#dom-hashalgorithmidentifier).
119-
1. Request a `FileSystemFileHandle` for the file, specifying the file's hash and a human-readable description. This will trigger a permission prompt if it's okay for the origin to check if the file is stored by the browser.
120-
1. If a file with the hash already exists, return.
121-
1. Else, store the file in the browser.
114+
1. Hash the contents of the file using SHA-256 (or an equivalent secure algorithm, see [Appendix&nbsp;B](#appendix-b-blob-hash-with-the-web-crypto-api)). The used hash algorithm is communicated as a valid [`HashAlgorithmIdentifier`](https://w3c.github.io/webcrypto/#dom-hashalgorithmidentifier).
115+
1. Request a `FileSystemFileHandle` for the file, specifying the file's hash.
116+
1. The resulting `FileSystemFileHandle` can only be used for writing. Trying to read would fail with a `NotAllowed` `DOMException`.
117+
1. Store the file in the browser.
122118

123119
```js
124120
/**
@@ -130,16 +126,14 @@ const hash = {
130126
algorithm: 'SHA-256',
131127
value: '8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4',
132128
};
133-
// The human-readable file description.
134-
const description = 'Large AI model';
135129

136130
// This triggers a permission prompt:
137-
// example.com wants to check if the file "Large AI Model" is stored by your browser.
131+
// example.com wants to check if your browser already has a file it needs,
132+
// possibly saved from another site. If found, it will use the file without
133+
// changing it.
138134
// [Allow this time] [Allow on every visit] [Don't allow]
139135
try {
140-
const handle = await navigator.crossOriginStorage.requestFileHandle(hash, {
141-
description,
142-
});
136+
const handle = await navigator.crossOriginStorage.requestFileHandle(hash);
143137
} catch (err) {
144138
if (err.name === 'NotFoundError') {
145139
// Load the file from the network.
@@ -166,7 +160,7 @@ try {
166160

167161
#### Retrieving a file
168162

169-
1. Request a file handle using the file's hash and a human-readable description. This will trigger a permission prompt if it's okay for the origin to check if the file is stored by the browser.
163+
1. Request a file handle using the file's hash. This will trigger a permission prompt if it's okay for the origin to check if the file is stored by the browser.
170164
1. Retrieve the file after the user has granted access.
171165

172166
```js
@@ -179,19 +173,17 @@ const hash = {
179173
algorithm: 'SHA-256',
180174
value: '8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4',
181175
};
182-
// The human-readable file description.
183-
const description = 'Large AI model';
184176

185177
// This triggers a permission prompt:
186-
// example.com wants to check if the file "Large AI Model" is stored by your browser.
178+
// example.com wants to check if your browser already has a file it needs,
179+
// possibly saved from another site. If found, it will use the file without
180+
// changing it.
187181
// [Allow this time] [Allow on every visit] [Don't allow]
188182
try {
189-
const handle = await navigator.crossOriginStorage.requestFileHandle(hash, {
190-
description,
191-
});
183+
const handle = await navigator.crossOriginStorage.requestFileHandle(hash);
192184
// The file exists in COS.
193185
const fileBlob = await handle.getFile();
194-
console.log(`Retrieved file: ${description}`);
186+
console.log('Retrieved file', fileBlob);
195187
// Return the file as a Blob.
196188
console.log(fileBlob);
197189
} catch (err) {
@@ -209,28 +201,26 @@ try {
209201

210202
#### Storing and retrieving a file across unrelated sites
211203

212-
To illustrate the capabilities of the COS API, consider the following example where two unrelated sites want to interact with the same large language model. The first site stores the model in COS, while the second site retrieves it, each using different human-readable descriptions, one in English and one in Spanish.
204+
To illustrate the capabilities of the COS API, consider the following example where two unrelated sites want to interact with the same large language model. The first site stores the model in COS, while the second site retrieves it.
213205

214-
##### Site A: Storing a large language model with an English description
206+
##### Site A: Storing a large language model
215207

216-
On Site A, a web application stores a large language model in COS with a human-readable English description, "Large AI Model."
208+
On Site A, a web application stores a large language model in COS.
217209

218210
```js
219211
// The hash of the file we want to access.
220212
const hash = {
221213
algorithm: 'SHA-256',
222214
value: '8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4',
223215
};
224-
// The human-readable file description.
225-
const description = 'Large AI model';
226216

227217
// This triggers a permission prompt:
228-
// site-a.example.com wants to check if the file "Large AI Model" is stored by your browser.
218+
// site-a.example.com wants to check if your browser already has a file it
219+
// needs, possibly saved from another site. If found, it will use the file
220+
// without changing it.”
229221
// [Allow this time] [Allow on every visit] [Don't allow]
230222
try {
231-
const handle = await navigator.crossOriginStorage.requestFileHandle(hash, {
232-
description,
233-
});
223+
const handle = await navigator.crossOriginStorage.requestFileHandle(hash);
234224

235225
// Use the file and return.
236226
//
@@ -258,7 +248,7 @@ try {
258248
await writableStream.write(fileBlob);
259249
await writableStream.close();
260250

261-
console.log(`File stored: ${description}`);
251+
console.log('File stored.');
262252
} catch (err) {
263253
// The `write()` failed.
264254
}
@@ -269,29 +259,26 @@ try {
269259
}
270260
```
271261

272-
##### Site B: Retrieving the same model with a Spanish description
262+
##### Site B: Retrieving the same model
273263

274-
On Site B, entirely unrelated to Site A, a different web application happens to retrieve the same model from COS, but refers to it with a human-readable Spanish description, "Modelo de IA Grande."
264+
On Site B, entirely unrelated to Site A, a different web application happens to retrieve the same model from COS.
275265

276266
```js
277267
// The hash of the file we want to access.
278268
const hash = {
279269
algorithm: 'SHA-256',
280270
value: '8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4',
281271
};
282-
// The human-readable file description.
283-
const description = 'Modelo de IA Grande';
284272

285273
// This triggers a permission prompt:
286-
// site-b.example.com wants to check if the file "Modelo de IA Grande" is stored by your browser.
274+
// site-b.example.com wants to check if your browser already has a file it
275+
// needs, possibly saved from another site. If found, it will use the file
276+
// without changing it.
287277
// [Allow this time] [Allow on every visit] [Don't allow]
288278
try {
289-
const handle = await navigator.crossOriginStorage.requestFileHandle(hash, {
290-
description,
291-
});
279+
const handle = await navigator.crossOriginStorage.requestFileHandle(hash);
292280
const fileBlob = await handle.getFile();
293-
// This now logs the Spanish description, even if the file was stored with an English description by site A.
294-
console.log(`File retrieved with description: ${description}`);
281+
console.log('File retrieved', fileBlob);
295282
// Use the fileBlob as needed.
296283
} catch (err) {
297284
if (err.name === 'NotFoundError') {
@@ -307,35 +294,28 @@ try {
307294
##### Key points
308295

309296
- **Unrelated sites:** The two sites belong to different origins and do not share any context, ensuring the example demonstrates cross-origin capabilities.
310-
- **Human-readable descriptions:** Each site assigns its own human-readable description, localized to the user's context. The description isn't shared across origins.
311-
- **Cross-origin sharing:** Despite the different descriptions and origins, the file is securely identified by its hash, demonstrating the API's ability to facilitate cross-origin file storage and retrieval.
297+
- **Cross-origin sharing:** Despite the different origins, the file is securely identified by its hash, demonstrating the API's ability to facilitate cross-origin file storage and retrieval.
312298

313299
## Detailed design discussion
314300

315301
### User consent and permissions
316302

317-
The permission prompt must clearly display the file's description to ensure users understand what file they are being asked to store or retrieve. The goal is to strike a balance between providing sufficient technical details and maintaining user-friendly simplicity.
303+
The permission prompt must clearly convey that the user agent is granting access to a shared file. The goal is to strike a balance between providing sufficient technical details and maintaining user-friendly simplicity.
318304

319-
An **access permission** will be shown every time the `navigator.crossOriginStorage.requestFileHandle(hash, { description })` method is called _without_ the `create` option set to `true`, which can happen to check for existence of the file and to obtain the handle to then get the actual file.
305+
An **access permission** will be shown every time the `navigator.crossOriginStorage.requestFileHandle(hash)` method is called _without_ the `create` option set to `true`, which can happen to check for existence of the file and to obtain the handle to then get the actual file.
320306

321307
The resulting `FileSystemFileHandle` that the developer obtains when `create` is set to `true` can only be used for writing. Trying to call `FileSystemFileHandle.getFile()` would fail with a `NotAllowed` `DOMException`.
322308

323-
The `description` will be part of the permission text. User agents can decide to allow this on every visit, or to explicitly ask upon each access attempt.
309+
User agents can decide to allow access on every visit, or to explicitly ask upon each access attempt.
324310

325-
If the origin has stored the file before, the user agent can decide to not show a prompt.
311+
If an origin itself has stored the file before, the user agent can decide to not show a prompt if the origin requests access to the file again.
326312

327313
If the user agent knows that the file exists, it can customize the permission prompt to differentiate the existence check and the access prompt:
328314

329315
- If the file doesn't exist:
330-
```
331-
example.com wants to check if the file "large file" is stored by your browser.
332-
[Allow this time] [Allow on every visit] [Don't allow]
333-
```
316+
![example.com wants to check if your browser already has a file it needs, possibly saved from another site. If found, it will use the file without changing it. (Allow this time) (Allow on every visit) (Don't allow)](./permission-1.png)
334317
- If the file does exist:
335-
```
336-
example.com wants to access the file "large file" stored by your browser.
337-
[Allow this time] [Allow on every visit] [Don't allow]
338-
```
318+
![example.com wants to access a file it needs that was already saved from another site. If you allow this, it will use the file without changing it. (Allow this time) (Allow on every visit) (Don't allow)](./permission-2.png)
339319

340320
> [!IMPORTANT]
341321
> The permission could mention other recent origins that have accessed the same file, but this may be misinterpreted by the user as information the current site may learn, which is never the case. Instead, the vision is that user agents would make information about origins that have (recently) accessed a file stored in COS available in special browser settings UI, as outlined in [Handling of eviction](#handling-of-eviction).
@@ -357,10 +337,6 @@ const hash = {
357337

358338
The current hashing algorithm is [SHA-256](https://w3c.github.io/webcrypto/#alg-sha-256), implemented by the **Web Crypto API**. If hashing best practices should change, COS will reflect the [implementers' recommendation](https://w3c.github.io/webcrypto/#algorithm-recommendations-implementers) in the Web Crypto API.
359339

360-
### Human-readable descriptions
361-
362-
A valid human-readable description is a string that is not an empty string and that doesn't contain linebreaks or control characters.
363-
364340
## Open questions
365341

366342
### Concurrency
@@ -431,7 +407,7 @@ Many thanks for valuable inspiration or ideas from:
431407

432408
## Appendices
433409

434-
### Appendix A: Full IDL
410+
### Appendix&nbsp;A: Full IDL
435411

436412
```webidl
437413
interface mixin NavigatorCrossOriginStorage {
@@ -453,12 +429,11 @@ dictionary CrossOriginStorageRequestFileHandleHash {
453429
}
454430
455431
dictionary CrossOriginStorageRequestFileHandleOptions {
456-
DOMString description;
457432
optional boolean create = false;
458433
}
459434
```
460435

461-
### Appendix B: Blob hash with the Web Crypto API
436+
### Appendix&nbsp;B: Blob hash with the Web Crypto API
462437

463438
```js
464439
async function getBlobHash(blob) {
@@ -494,7 +469,7 @@ getBlobHash(fileBlob).then((hash) => {
494469
});
495470
```
496471

497-
### Appendix C: FAQ
472+
### Appendix&nbsp;C: Frequently asked questions (FAQ)
498473

499474
<details>
500475
<summary>

permission-1.png

89.5 KB
Loading

permission-2.png

87 KB
Loading

0 commit comments

Comments
 (0)