diff --git a/files/en-us/web/api/shared_storage_api/index.md b/files/en-us/web/api/shared_storage_api/index.md new file mode 100644 index 000000000000000..6d61c56516020c5 --- /dev/null +++ b/files/en-us/web/api/shared_storage_api/index.md @@ -0,0 +1,267 @@ +--- +title: Shared Storage API +slug: Web/API/Shared_Storage_API +page-type: web-api-overview +status: + - experimental +browser-compat: api.SharedStorage +--- + +{{SeeCompatTable}}{{DefaultAPISidebar("Shared Storage API")}} + +The **Shared Storage API** is a client-side storage mechanism that enables unpartitioned, cross-site data access in a privacy-preserving manner for specific use cases that require it. + +## Concepts and usage + +One major source of [privacy](/en-US/docs/Web/Privacy) and [security](/en-US/docs/Web/Security) problems on the web is third-party cookies set on content embedded in {{htmlelement("iframe")}} elements, which can be used to share information and track users across sites. + +To prevent cross-site tracking, browsers are working towards partitioning all forms of storage — this includes [Cookies](/en-US/docs/Web/HTTP/Cookies), [Web Storage](/en-US/docs/Web/API/Web_Storage_API), [IndexedDB](/en-US/docs/Web/API/IndexedDB_API), [Cache API](/en-US/docs/Web/API/Cache), etc. However, a major barrier to achieving this is several legitimate use cases that rely on sharing information across sites. For example, advertisers wish to measure the reach of their ads across sites and generate reports, and site owners wish to customize user experiences based on what group they are in, or what content they've already seen on other properties. + +The Shared Storage API provides a flexible solution to fulfill such use cases — aiming to provide the required data storage, processing, and sharing — but without sharing user data with parties that shouldn't have access to it. + +Like other storage APIs, you can write to shared storage at any time. However, you can only read shared storage data from inside a {{domxref("SharedStorageWorklet", "worklet", "", "nocode")}}. Worklets provide a secure environment inside which you can process shared storage data and return useful results, but you can't directly share the data with the associated browsing context. + +To extract useful results from a shared storage worklet, you need to use an **output gate**. Output gates are mechanisms that fulfill a specific type of use case, for example selecting a URL from a provided list to display to the user based on shared storage data. Any results to be displayed to the user will be shown securely inside a [fenced frame](/en-US/docs/Web/API/Fenced_Frame_API) where they can't be accessed from the embedding page. + +### Use cases + +The Shared Storage API's currently available output gates are discussed in the sections below. In each section, we list typical use cases for each one, and link to guides that provide more information and code examples. + +> **Note:** More output gates will likely be added in the future, to support additional use cases. + +#### URL Selection + +The **URL Selection** output gate (via the {{domxref("WindowSharedStorage.selectURL", "selectURL()")}} method) is used to select a URL from a provided list to display to the user, based on shared storage data. This can be used for the following purposes: + +- [**Creative rotation**](https://developer.chrome.com/docs/privacy-sandbox/shared-storage/creative-rotation/): Store data such as creative IDs, view counts, and user interaction, to determine which creative users see across different sites. This allows you to balance views and avoid oversaturation of certain content, which can help you avoid a negative user experience. +- [**A/B testing**](https://developer.chrome.com/docs/privacy-sandbox/shared-storage/ab-testing/): Assign a user to an experiment group, then store group details in shared storage to be accessed cross-site. +- [**Custom user experiences**](https://developer.chrome.com/docs/privacy-sandbox/shared-storage/known-customer/): Share custom content and calls-to-action based on a user's registration status or other user states. + +#### Run + +The **Run** output gate (via the {{domxref("WindowSharedStorage.run", "run()")}} method) is intended as a generic way to process some shared storage data. + +The [Private Aggregation API](https://developer.chrome.com/docs/privacy-sandbox/private-aggregation/) can use the Run output gate to process shared storage data and generate aggregated reports. These can be used for the following use cases: + +- [**Unique reach reporting**](https://developer.chrome.com/docs/privacy-sandbox/shared-storage/unique-reach/): Content producers and advertisers often want to know how many unique people saw their content. You can use shared storage to report on the first time a user saw your ad or embedded publication, and prevent duplicative counting of that same user on a different site, giving you an aggregated noisy report of your approximate unique reach. +- [**User demographic reporting**](https://developer.chrome.com/docs/privacy-sandbox/shared-storage/user-demographics/): Content producers often want to understand the demographics of their audience. You can use shared storage to record user demographic data on your main site, and use aggregated reporting to report on it across other sites, in embedded contexts. +- [**K+ frequency measurement**](https://developer.chrome.com/docs/privacy-sandbox/shared-storage/k-freq-reach/): Sometimes described as "effective frequency", K+ frequency refers to the minimum number of views before a user will recognize or recall certain content (often used in the context of ad views). You can use shared storage to build reports of unique users that have seen a piece of content at least K times. + +## How does shared storage work? + +There are two parts to using the Shared Storage API — writing data to storage and reading/processing it. To give you an idea of how these parts are handled, we'll walk you through the basic [A/B testing](https://developer.chrome.com/docs/privacy-sandbox/shared-storage/ab-testing/) example from developer.chrome.com. This example assigns a user to an experiment group, stores the group details in shared storage, and then allows other sites to use that data when choosing a URL to display in a [fenced frame](/en-US/docs/Web/API/Fenced_Frame_API). + +### Writing to shared storage + +Writing the data is simple — you use methods defined on the {{domxref("SharedStorage")}} interface to {{domxref("SharedStorage.set", "set", "", "nocode")}}, {{domxref("SharedStorage.append", "append", "", "nocode")}}, or {{domxref("SharedStorage.delete", "delete", "", "nocode")}}/{{domxref("SharedStorage.clear", "clear", "", "nocode")}} data. + +This functionality is available in two different contexts: + +- In the main browsing context that your site or app is running in, on {{domxref("WindowSharedStorage")}}, which is available via `window.sharedStorage`. +- In the context of your shared storage worklet, on {{domxref("WorkletSharedStorage")}}, which is available via `this.sharedStorage`. + +In our A/B testing example, we define a function in our app context that generates a random number — 0 or 1 — to represent an experiment group to assign the current user to, and then run the {{domxref("SharedStorage.set", "window.sharedStorage.set()")}} function to assign the user to a group and save the result in shared storage: + +```js +// Randomly assigns a user to a group 0 or 1 +function getExperimentGroup() { + return Math.round(Math.random()); +} + +async function injectContent() { + // Assign user to a random group (0 or 1) and store it in shared storage + window.sharedStorage.set("ab-testing-group", getExperimentGroup(), { + ignoreIfPresent: true, + }); +} +``` + +> _Note:_ The `ignoreIfPresent: true` option causes the `set()` function to abort if the shared storage already contains a data item with the specified key. + +### Reading and processing data from shared storage + +As mentioned above, to extract useful results from a shared storage worklet you need to use an **output gate**. In this example, we'll use the URL Selection output gate to read the user's experiment group and then load a URL in a fenced frame based on their group. + +To use the output gate, you need to: + +- Define an operation in a worklet module script to handle choosing the URL, and register it. +- Add the module to your shared storage worklet. +- Choose the URL using the worklet operation and load it in a fenced frame. + +Below we'll look at these steps one by one. + +#### Define an operation in a worklet + +The URL will be chosen based on the experiment group stored in shared storage. To retrieve this value and choose a URL based on it, we need to define an operation in a {{domxref("SharedStorageWorklet")}} context — it must be inside a worklet to keep the raw data hidden from other contexts and therefore preserve privacy. + +The URL Selection operation takes the form of a JavaScript class. It can be written in any way you like, as long as it follows certain rules (some of the rules for each output gate differ, depending on what kind of use case they fulfill): + +- The actual functionality must be contained inside an asynchronous `run()` method, which must have an array of objects containing URLs as its first paramater, and a data object as its second parameter (when called, the data argument is optional). +- The `run()` method must return a number, which will equate to the number of the URL chosen. + +> **Note:** Each output gate has a corresponding interface that defines the required structure of its class and `run()` method. For URL Selection, see {{domxref("SharedStorageSelectURLOperation")}}. + +Once the operation is defined, it needs to be registered using {{domxref("SharedStorageWorkletGlobalScope.register()")}}. + +```js +// ab-testing-worklet.js +class SelectURLOperation { + async run(urls, data) { + // Read the user's experiment group from shared storage + const experimentGroup = await this.sharedStorage.get("ab-testing-group"); + + // Return the group number + return experimentGroup; + } +} + +register("ab-testing", SelectURLOperation); +``` + +Note how the value set in our main app context is retrieved using {{domxref("WorkletSharedStorage.get()")}}. To reiterate, to preserve privacy and mitigate data leakage you can only read values back out of shared storage inside a worklet. + +> **Note:** It is possible to define and register multiple operations in the same shared storage worklet module script with different names; see {{domxref("SharedStorageOperation")}} for an example. + +#### Add the worklet + +To use the operation defined in the worklet module, it needs to be added to the shared storage worklet using {{domxref("Worklet.addModule", "window.sharedStorage.worklet.addModule()")}}. This is done in our main app context, before we set the experiment group value, so that it is ready to use when needed: + +```js +async function injectContent() { + // Add the module to the shared storage worklet + await window.sharedStorage.worklet.addModule("ab-testing-worklet.js"); + + // Assign user to a random group (0 or 1) and store it in shared storage + window.sharedStorage.set("ab-testing-group", getExperimentGroup(), { + ignoreIfPresent: true, + }); +} +``` + +#### Choose a URL and load it in a fenced frame + +To run the operation defined in the worklet, we call {{domxref("WindowSharedStorage.selectURL()")}} — this acts as a proxy to our worklet operation, accessing it securely and returning the result without leaking any data. `selectURL()` is the correct method to call our user-defined worklet operation because it was defined with the appropriate class structure for a URL Selection operation, as discussed above. + +`selectURL()` expects an array of objects containing URLs to choose from, an optional options object, and for the underlying operation to return an integer that it can use to choose a URL. + +```js +// Run the URL selection operation +const fencedFrameConfig = await window.sharedStorage.selectURL( + "ab-testing", + [ + { url: `https://your-server.example/content/default-content.html` }, + { url: `https://your-server.example/content/experiment-content-a.html` }, + ], + { + resolveToConfig: true, + }, +); +``` + +Because the options object contains `resolveToConfig: true`, the returned {{jsxref("Promise")}} will resolve with a {{domxref("FencedFrameConfig")}} object, which can be set as the value of the {{domxref("HTMLFencedFrameElement.config")}} property, resulting in the chosen URL being displayed in the associated {{htmlelement("fencedframe")}} element: + +```js +document.getElementById("content-slot").config = fencedFrameConfig; +``` + +The full app script looks like so: + +```js +// Randomly assigns a user to a group 0 or 1 +function getExperimentGroup() { + return Math.round(Math.random()); +} + +async function injectContent() { + // Add the module to the shared storage worklet + await window.sharedStorage.worklet.addModule("ab-testing-worklet.js"); + + // Assign user to a random group (0 or 1) and store it in shared storage + window.sharedStorage.set("ab-testing-group", getExperimentGroup(), { + ignoreIfPresent: true, + }); + + // Run the URL selection operation + const fencedFrameConfig = await window.sharedStorage.selectURL( + "ab-testing", + [ + { url: `https://your-server.example/content/default-content.html` }, + { url: `https://your-server.example/content/experiment-content-a.html` }, + ], + { + resolveToConfig: true, + }, + ); + + // Render the chosen URL into a fenced frame + document.getElementById("content-slot").config = fencedFrameConfig; +} + +injectContent(); +``` + +## How does shared storage differ from web storage? + +The key difference is that shared storage is intended for use with cross-origin data once storage has been partitioned. + +- If you are a publisher and you want to store first-party data that is accessible to you only, use the [`localStorage`](/en-US/docs/Web/API/Window/localStorage) version of [web storage](/en-US/docs/Web/API/Web_Storage_API). +- If you want that data to persist only for that browser session, use [`sessionStorage`](/en-US/docs/Web/API/Window/sessionStorage). +- If you are operating as a third-party on another site, and you want to record data from that site for you to access later on another site, use shared storage. + +Another important difference between shared storage and web storage is that reading from shared storage is guarded (writing to storage behaves similarly). With `localStorage` and `sessionStorage`, you can read freely. With shared storage, reading can only happen inside a shared storage worklet, and the origin used for reading in the worklet is the same as the browsing context that created it. + +Also, you cannot extract shared storage data to the outside of a shared storage worklet (for tracking protection). You must use one of the output gates provided if you want to work with your data in shared storage. + +Last, data in `localStorage` persists until manually cleared (`sessionStorage` is cleared at the end of a browsing session). Shared storage data is cleared 30 days after the last write call. + +## Interfaces + +- {{domxref("SharedStorage")}} + - : Represents the shared storage for a particular origin. It defines methods to write data to the shared storage. +- {{domxref("WindowSharedStorage")}} + - : Represents the shared storage for a particular origin, as it is exposed to a standard browsing context. Among other things, it defines methods to use the available output gates, which act as proxies for the operations defined in the worklet. +- {{domxref("WorkletSharedStorage")}} + - : Represents the shared storage for a particular origin, as it is exposed to a worklet context. Among other things, it defines methods to read the shared storage data. +- {{domxref("SharedStorageWorklet")}} + - : Represents the current origin's shared storage worklet. Contains the {{domxref("Worklet.addModule", "addModule()")}} method used to add a module to it. Unlike a regular {{domxref("Worklet")}}, `SharedStorageWorklet` can only have a single module added to it, for privacy reasons. +- {{domxref("SharedStorageWorkletGlobalScope")}} + - : Represents the global scope of a {{domxref("SharedStorageWorklet")}} module. Contains functionality to {{domxref("SharedStorageWorkletGlobalScope.register", "register", "", "nocode")}} a defined operation, and {{domxref("SharedStorageWorkletGlobalScope.sharedStorage", "access the shared storage", "", "nocode")}}. + +### Output gate operation signature definitions + +- {{domxref("SharedStorageOperation")}} + - : Represents the base class for all different output gate operation types. +- {{domxref("SharedStorageRunOperation")}} + - : Represents a Run output gate operation. +- {{domxref("SharedStorageSelectURLOperation")}} + - : Represents a URL Selection output gate operation. + +### Extensions to other interfaces + +- {{domxref("Window.sharedStorage")}} + - : Returns the {{domxref("WindowSharedStorage")}} object for the current origin. + +## Enrollment and local testing + +To use the Shared Storage API in your sites, you must specify it in the [privacy sandbox enrollment process](/en-US/docs/Web/Privacy/Privacy_sandbox/Enrollment). If you don't do this, none of the methods of the Shared Storage API will run successfully. + +You can still test your Shared Storage API code locally without enrollment. To allow local testing, enable the following Chrome developer flag: + +`chrome://flags/#privacy-sandbox-enrollment-overrides` + +## Examples + +For extensive demos, see [Shared Storage API demo site](https://shared-storage-demo.web.app/) (which also includes some Private Aggregation API examples). + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage](https://developer.chrome.com/docs/privacy-sandbox/shared-storage/) on developer.chrome.com +- [The Privacy Sandbox](https://developer.chrome.com/docs/privacy-sandbox/) on developer.chrome.com diff --git a/files/en-us/web/api/sharedstorage/append/index.md b/files/en-us/web/api/sharedstorage/append/index.md new file mode 100644 index 000000000000000..7348ea7e716ec09 --- /dev/null +++ b/files/en-us/web/api/sharedstorage/append/index.md @@ -0,0 +1,63 @@ +--- +title: "SharedStorage: append() method" +short-title: append() +slug: Web/API/SharedStorage/append +page-type: web-api-instance-method +status: + - experimental +browser-compat: api.SharedStorage.append +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`append()`** method of the +{{domxref("SharedStorage")}} interface appends a string to the value of an existing key/value pair in the current origin's shared storage. + +## Syntax + +```js-nolint +append(key, value) +``` + +### Parameters + +- `key` + - : A string representing the key of the key/value pair you want to append a string to. +- `value` + - : A string that you want to append to the existing value. + +> **Note:** If the specified `key` isn't found in shared storage, the `append()` operation is equivalent to {{domxref("SharedStorage.set", "set()")}}, i.e. a new key/value pair is added to storage with the specified `key`. + +### Return value + +A {{jsxref("Promise")}} that fulfills with `undefined`. + +### Exceptions + +- In the case of {{domxref("WorkletSharedStorage")}}, the `Promise` rejects with a {{jsxref("TypeError")}} if the worklet module has not been added with {{domxref("Worklet.addModule", "SharedStorageWorklet.addModule()")}}. +- In both cases, the `Promise` rejects with a {{jsxref("TypeError")}} if: + - The appended entry was not successfully stored in the database due to shared storage not being available (for example it is disabled using a browser setting). + - `key` and/or `value` exceed the browser-defined maximum length. + - The calling site does not have the Shared Storage API included in a successful [privacy sandbox enrollment process](/en-US/docs/Web/Privacy/Privacy_sandbox/Enrollment). + +> **Note:** In the case of {{domxref("WindowSharedStorage")}}, if the `append()` operation doesn't successfully write to the database for a reason other than shared storage not being available, no error is thrown — the operation still fulfills with `undefined`. + +## Examples + +```js +window.sharedStorage + .append("integer-list", ",9") + .then(console.log("Value appended to integer list")); +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorage/clear/index.md b/files/en-us/web/api/sharedstorage/clear/index.md new file mode 100644 index 000000000000000..a99b15da8a24e9a --- /dev/null +++ b/files/en-us/web/api/sharedstorage/clear/index.md @@ -0,0 +1,55 @@ +--- +title: "SharedStorage: clear() method" +short-title: clear() +slug: Web/API/SharedStorage/clear +page-type: web-api-instance-method +status: + - experimental +browser-compat: api.SharedStorage.clear +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`clear()`** method of the +{{domxref("SharedStorage")}} interface clears the current origin's shared storage, removing all data from it. + +## Syntax + +```js-nolint +clear() +``` + +### Parameters + +None. + +### Return value + +A {{jsxref("Promise")}} that fulfills with `undefined`. + +### Exceptions + +- In the case of {{domxref("WorkletSharedStorage")}}, the `Promise` rejects with a {{jsxref("TypeError")}} if the worklet module has not been added with {{domxref("Worklet.addModule", "SharedStorageWorklet.addModule()")}}. +- In both cases, the `Promise` rejects with a {{jsxref("TypeError")}} if: + - The database was not cleared successfully due to shared storage not being available (for example it is disabled using a browser setting). + - The calling site does not have the Shared Storage API included in a successful [privacy sandbox enrollment process](/en-US/docs/Web/Privacy/Privacy_sandbox/Enrollment). + +> **Note:** In the case of {{domxref("WindowSharedStorage")}}, if the `clear()` operation doesn't successfully write to the database for a reason other than shared storage not being available, no error is thrown — the operation still fulfills with `undefined`. + +## Examples + +```js +window.sharedStorage.clear().then(console.log("Shared storage cleared")); +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorage/delete/index.md b/files/en-us/web/api/sharedstorage/delete/index.md new file mode 100644 index 000000000000000..6cf1bed00d338d3 --- /dev/null +++ b/files/en-us/web/api/sharedstorage/delete/index.md @@ -0,0 +1,62 @@ +--- +title: "SharedStorage: delete() method" +short-title: delete() +slug: Web/API/SharedStorage/delete +page-type: web-api-instance-method +status: + - experimental +browser-compat: api.SharedStorage.delete +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`delete()`** method of the +{{domxref("SharedStorage")}} interface deletes an existing key/value pair from the current origin's shared storage. + +## Syntax + +```js-nolint +delete(key) +``` + +### Parameters + +- `key` + - : A string representing the key of the key/value pair you want to delete. + +### Return value + +A {{jsxref("Promise")}} that fulfills with `undefined`. + +### Exceptions + +- In the case of {{domxref("WorkletSharedStorage")}}, the `Promise` rejects with a {{jsxref("TypeError")}} if: + - The worklet module has not been added with {{domxref("Worklet.addModule", "SharedStorageWorklet.addModule()")}}. +- In both cases, the `Promise` rejects with a {{jsxref("TypeError")}} if: + - The database was not cleared successfully due to shared storage not being available (for example it is disabled using a browser setting). + - `key` exceeds the browser-defined maximum length. + - The calling site does not have the Shared Storage API included in a successful [privacy sandbox enrollment process](/en-US/docs/Web/Privacy/Privacy_sandbox/Enrollment). + +> **Note:** If the key/value pair doesn't exist in the shared storage, no error is thrown — the operation still fulfills with `undefined`. + +> **Note:** In the case of {{domxref("WindowSharedStorage")}}, if the `delete()` operation doesn't successfully write to the database for a reason other than shared storage not being available, no error is thrown — the operation still fulfills with `undefined`. + +## Examples + +```js +window.sharedStorage + .delete("ab-testing-group") + .then(console.log("Value deleted")); +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorage/index.md b/files/en-us/web/api/sharedstorage/index.md new file mode 100644 index 000000000000000..7896dd69fbdc932 --- /dev/null +++ b/files/en-us/web/api/sharedstorage/index.md @@ -0,0 +1,51 @@ +--- +title: SharedStorage +slug: Web/API/SharedStorage +page-type: web-api-interface +status: + - experimental +browser-compat: api.SharedStorage +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`SharedStorage`** interface of the {{domxref("Shared Storage API", "Shared Storage API", "", "nocode")}} represents the shared storage for a particular origin, defining methods to write data to the shared storage. + +`SharedStorage` is the base class for: + +- {{domxref("WindowSharedStorage")}}, accessed via {{domxref("Window.sharedStorage")}}. +- {{domxref("WorkletSharedStorage")}}, accessed via {{domxref("SharedStorageWorkletGlobalScope.sharedStorage")}}. + +{{InheritanceDiagram}} + +## Instance methods + +- {{domxref("SharedStorage.append", "append()")}} {{Experimental_Inline}} + - : Appends a string to the value of an existing key/value pair in the current origin's shared storage. +- {{domxref("SharedStorage.clear", "clear()")}} {{Experimental_Inline}} + - : Clears the current origin's shared storage, removing all data from it. +- {{domxref("SharedStorage.delete", "delete()")}} {{Experimental_Inline}} + - : Deletes an existing key/value pair from the current origin's shared storage. +- {{domxref("SharedStorage.set", "set()")}} {{Experimental_Inline}} + - : Stores a new key/value pair in the current origin's shared storage or updates an existing one. + +## Examples + +```js +window.sharedStorage + .set("ab-testing-group", "0") + .then(console.log("Value saved to shared storage")); +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- {{domxref("WindowSharedStorage")}} +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorage/set/index.md b/files/en-us/web/api/sharedstorage/set/index.md new file mode 100644 index 000000000000000..d51da1984548780 --- /dev/null +++ b/files/en-us/web/api/sharedstorage/set/index.md @@ -0,0 +1,68 @@ +--- +title: "SharedStorage: set() method" +short-title: set() +slug: Web/API/SharedStorage/set +page-type: web-api-instance-method +status: + - experimental +browser-compat: api.SharedStorage.set +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`set()`** method of the +{{domxref("SharedStorage")}} interface stores a new key/value pair in the current origin's shared storage or updates an existing one. + +## Syntax + +```js-nolint +set(key, value) +set(key, value, options) +``` + +### Parameters + +- `key` + - : A string representing the key of the key/value pair you want to add or update. +- `value` + - : A string representing the value you want to add or update. +- `options` {{optional_inline}} + - : An options object containing the following properties: + - `ignoreIfPresent` + - : A boolean value that, if set to `true`, will cause the set operation to abort if a key/value pair with the specified `key` already exists. The default value, `false`, will cause the set operation to go ahead and overwrite the previous value, in such cases. + +### Return value + +A {{jsxref("Promise")}} that fulfills with `undefined`. + +### Exceptions + +- In the case of {{domxref("WorkletSharedStorage")}}, the `Promise` rejects with a {{jsxref("TypeError")}} if the worklet module has not been added with {{domxref("Worklet.addModule", "SharedStorageWorklet.addModule()")}}. +- In both cases, the `Promise` rejects with a {{jsxref("TypeError")}} if: + - The created entry was not successfully stored in the database due to shared storage not being available (for example it is disabled using a browser setting). + - `key` and/or `value` exceed the browser-defined maximum length. + - The calling site does not have the Shared Storage API included in a successful [privacy sandbox enrollment process](/en-US/docs/Web/Privacy/Privacy_sandbox/Enrollment). + +> **Note:** In the case of {{domxref("WindowSharedStorage")}}, if the `set()` operation doesn't successfully write to the database for a reason other than shared storage not being available, no error is thrown — the operation still fulfills with `undefined`. + +## Examples + +```js +window.sharedStorage + .set("ab-testing-group", "0", { + ignoreIfPresent: true, + }) + .then(console.log("Set operation completed")); +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorageoperation/index.md b/files/en-us/web/api/sharedstorageoperation/index.md new file mode 100644 index 000000000000000..2e8a64bc88ff692 --- /dev/null +++ b/files/en-us/web/api/sharedstorageoperation/index.md @@ -0,0 +1,172 @@ +--- +title: SharedStorageOperation +slug: Web/API/SharedStorageOperation +page-type: web-api-interface +status: + - experimental +browser-compat: api.SharedStorageOperation +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`SharedStorageOperation`** interface of the {{domxref("Shared Storage API", "Shared Storage API", "", "nocode")}} represents the base class for all different output gate operation types. + +{{InheritanceDiagram}} + +The different output gate types are detailed below: + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionDefined byInvoked by
URL SelectionUsed to select a URL from a provided list to display to the user, based on shared storage data.{{domxref("SharedStorageSelectURLOperation")}}{{domxref("WindowSharedStorage.selectURL()", "selectURL()")}}
RunA generic way to process some shared storage data. Used, for example, by the Private Aggregation API to process shared storage data and generate aggregated reports. {{domxref("SharedStorageRunOperation")}}{{domxref("WindowSharedStorage.run()", "run()")}}
+ +## Examples + +## Defining individual operations + +Many shared storage worklet module scripts only define and register a single operation; you can see examples on the {{domxref("SharedStorageSelectURLOperation")}} and {{domxref("SharedStorageRunOperation")}} pages. + +## Defining multiple operations + +It is however perfectly possible, in more advanced cases, to define and register multiple operations in the same shared storage worklet module script with different names. In the following worklet module script, we define a URL Selection operation called `SelectURLOperation` that selects a URL for A/B testing, and a Run operation called `ExperimentGroupReportingOperation`, which runs a histogram report based on the user's A/B testing group: + +```js +// ab-testing-worklet.js + +class SelectURLOperation { + async run(urls, data) { + // Read the user's group from shared storage + const experimentGroup = await sharedStorage.get("ab-testing-group"); + + // Log to console for the demo + console.log(`urls = ${JSON.stringify(urls)}`); + console.log(`data = ${JSON.stringify(data)}`); + console.log(`ab-testing-group in shared storage is ${experimentGroup}`); + + // Return the index of the group + return data.indexOf(experimentGroup); + } +} + +function getBucketForTestingGroup(testingGroup) { + switch (testingGroup) { + case "control": + return 0; + case "experiment-a": + return 1; + case "experiment-b": + return 2; + } +} + +class ExperimentGroupReportingOperation { + async run() { + const experimentGroup = await sharedStorage.get("ab-testing-group"); + + const bucket = BigInt(getBucketForTestingGroup(experimentGroup)); + privateAggregation.contributeToHistogram({ bucket, value: 1 }); + } +} + +// Register the operations +register("ab-testing", SelectURLOperation); +register("experiment-group-reporting", ExperimentGroupReportingOperation); +``` + +In the main browsing context, these operations are invoked by {{domxref("WindowSharedStorage.selectURL()", "selectURL()")}} and {{domxref("WindowSharedStorage.run()", "run()")}} respectively. The operations to invoke via these methods are selected using the names they were registered with, and they are also required to conform to the structures defined by the {{domxref("SharedStorageSelectURLOperation")}} and {{domxref("SharedStorageRunOperation")}} classes, and their `run()` methods. + +```js +// For demo purposes. The hostname is used to determine the usage of +// development localhost URL vs production URL +const contentProducerUrl = window.location.host; + +// Map the experiment groups to the URLs +const EXPERIMENT_MAP = [ + { + group: "control", + url: `https://${contentProducerUrl}/ads/default-ad.html`, + }, + { + group: "experiment-a", + url: `https://${contentProducerUrl}/ads/experiment-ad-a.html`, + }, + { + group: "experiment-b", + url: `https://${contentProducerUrl}/ads/experiment-ad-b.html`, + }, +]; + +// Choose a random group for the initial experiment +function getRandomExperiment() { + const randomIndex = Math.floor(Math.random() * EXPERIMENT_MAP.length); + return EXPERIMENT_MAP[randomIndex].group; +} + +async function injectAd() { + // Load the worklet module + await window.sharedStorage.worklet.addModule("ab-testing-worklet.js"); + + // Set the initial value in the storage to a random experiment group + window.sharedStorage.set("ab-testing-group", getRandomExperiment(), { + ignoreIfPresent: true, + }); + + const urls = EXPERIMENT_MAP.map(({ url }) => ({ url })); + const groups = EXPERIMENT_MAP.map(({ group }) => group); + + // Resolve the selectURL call to a fenced frame config only when it exists on the page + const resolveToConfig = typeof window.FencedFrameConfig !== "undefined"; + + // Run the URL selection operation to select an ad based on the experiment group in shared storage + const selectedUrl = await window.sharedStorage.selectURL("ab-testing", urls, { + data: groups, + resolveToConfig, + keepAlive: true, + }); + + const adSlot = document.getElementById("ad-slot"); + + if (resolveToConfig && selectedUrl instanceof FencedFrameConfig) { + adSlot.config = selectedUrl; + } else { + adSlot.src = selectedUrl; + } + + // Run the reporting operation + await window.sharedStorage.run("experiment-group-reporting"); +} + +injectAd(); +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstoragerunoperation/index.md b/files/en-us/web/api/sharedstoragerunoperation/index.md new file mode 100644 index 000000000000000..52700bcd5766248 --- /dev/null +++ b/files/en-us/web/api/sharedstoragerunoperation/index.md @@ -0,0 +1,92 @@ +--- +title: SharedStorageRunOperation +slug: Web/API/SharedStorageRunOperation +page-type: web-api-interface +status: + - experimental +browser-compat: api.SharedStorageRunOperation +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`SharedStorageRunOperation`** interface of the {{domxref("Shared Storage API", "Shared Storage API", "", "nocode")}} represents a run output gate operation. + +{{InheritanceDiagram}} + +## Instance methods + +- {{domxref("SharedStorageRunOperation.run", "run()")}} {{Experimental_Inline}} + - : Defines the structure that the `run()` method defined inside a run output gate operation should conform to. + +## Examples + +In a worklet, a class called `ReachMeasurementOperation` is defined and registered using {{domxref("SharedStorageWorkletGlobalScope.register()")}} with a name of `reach-measurement`. `SharedStorageRunOperation` defines the structure this class needs to conform to, which in real terms means the parameters the `run()` method is required to have. Apart from that, the functionality of the class is flexible in terms of how it is defined. + +```js +// reach-measurement-worklet.js +const SCALE_FACTOR = 65536; + +function convertContentIdToBucket(contentId) { + return BigInt(contentId); +} + +class ReachMeasurementOperation { + async run(data) { + const { contentId } = data; + + // Read from Shared Storage + const key = "has-reported-content"; + const hasReportedContent = (await this.sharedStorage.get(key)) === "true"; + + // Do not report if a report has been sent already + if (hasReportedContent) { + return; + } + + // Generate the aggregation key and the aggregatable value + const bucket = convertContentIdToBucket(contentId); + const value = 1 * SCALE_FACTOR; + + // Send an aggregatable report via the Private Aggregation API + privateAggregation.sendHistogramReport({ bucket, value }); + + // Set the report submission status flag + await this.sharedStorage.set(key, true); + } +} + +// Register the operation +register("reach-measurement", ReachMeasurementOperation); +``` + +> **Note:** It is possible to define and register multiple operations in the same shared storage worklet module script with different names; see {{domxref("SharedStorageOperation")}} for an example. + +In the main browsing context, the `reach-measurement` operation is invoked using the {{domxref("WindowSharedStorage.run()")}} method: + +```js +async function measureUniqueReach() { + // Load the Shared Storage worklet + await window.sharedStorage.worklet.addModule("reach-measurement-worklet.js"); + + // Run the reach measurement operation + await window.sharedStorage.run("reach-measurement", { + data: { contentId: "1234" }, + }); +} + +measureUniqueReach(); +``` + +See [Unique reach measurement](https://developer.chrome.com/docs/privacy-sandbox/shared-storage/unique-reach/) for more details of this example, and [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) for more examples. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstoragerunoperation/run/index.md b/files/en-us/web/api/sharedstoragerunoperation/run/index.md new file mode 100644 index 000000000000000..688084e88de5e0e --- /dev/null +++ b/files/en-us/web/api/sharedstoragerunoperation/run/index.md @@ -0,0 +1,45 @@ +--- +title: "SharedStorageRunOperation: run() method" +short-title: run() +slug: Web/API/SharedStorageRunOperation/run +page-type: web-api-instance-method +status: + - experimental +browser-compat: api.SharedStorageRunOperation.run +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`run()`** method of the +{{domxref("SharedStorageRunOperation")}} interface defines the structure that the `run()` method defined inside a run output gate operation should conform to. + +## Syntax + +```js-nolint +run(data) +``` + +### Parameters + +- `data` + - : An object representing any data required for executing the operation. + +### Return value + +A {{jsxref("Promise")}} that fulfills with `undefined`. + +## Examples + +See the main {{domxref("SharedStorageRunOperation")}} page for an example. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorageselecturloperation/index.md b/files/en-us/web/api/sharedstorageselecturloperation/index.md new file mode 100644 index 000000000000000..6fd8efbd2afedac --- /dev/null +++ b/files/en-us/web/api/sharedstorageselecturloperation/index.md @@ -0,0 +1,91 @@ +--- +title: SharedStorageSelectURLOperation +slug: Web/API/SharedStorageSelectURLOperation +page-type: web-api-interface +status: + - experimental +browser-compat: api.SharedStorageSelectURLOperation +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`SharedStorageSelectURLOperation`** interface of the {{domxref("Shared Storage API", "Shared Storage API", "", "nocode")}} represents a URL Selection output gate operation. + +{{InheritanceDiagram}} + +## Instance methods + +- {{domxref("SharedStorageSelectURLOperation.run", "run()")}} {{Experimental_Inline}} + - : Defines the structure that the `run()` method defined inside a URL Selection output gate operation should conform to. + +## Examples + +In a worklet, a class called `SelectURLOperation` is defined and registered using {{domxref("SharedStorageWorkletGlobalScope.register()")}} with a name of `ab-testing`. `SharedStorageSelectURLOperation` defines the structure this class needs to conform to, which in real terms means the parameters and return value the `run()` method is required to have. Apart from that, the functionality of the class is flexible in terms of how it is defined. + +```js +// ab-testing-worklet.js +class SelectURLOperation { + async run(urls, data) { + // Read the user's experiment group from Shared Storage + const experimentGroup = await this.sharedStorage.get("ab-testing-group"); + + // Return the group number + return experimentGroup; + } +} + +// Register the operation +register("ab-testing", SelectURLOperation); +``` + +> **Note:** It is possible to define and register multiple operations in the same shared storage worklet module script with different names; see {{domxref("SharedStorageOperation")}} for an example. + +In the main browsing context, the `ab-testing` operation is invoked using the {{domxref("WindowSharedStorage.selectURL()")}} method: + +```js +// Randomly assigns a user to a group 0 or 1 +function getExperimentGroup() { + return Math.round(Math.random()); +} + +async function injectContent() { + // Register the Shared Storage worklet + await window.sharedStorage.worklet.addModule("ab-testing-worklet.js"); + + // Assign user to a random group (0 or 1) and store it in Shared Storage + window.sharedStorage.set("ab-testing-group", getExperimentGroup(), { + ignoreIfPresent: true, + }); + + // Run the URL selection operation + const fencedFrameConfig = await window.sharedStorage.selectURL( + "ab-testing", + [ + { url: `https://your-server.example/content/default-content.html` }, + { url: `https://your-server.example/content/experiment-content-a.html` }, + ], + { + resolveToConfig: true, + }, + ); + + // Render the chosen URL into a fenced frame + document.getElementById("content-slot").config = fencedFrameConfig; +} + +injectContent(); +``` + +See the [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) landing page for more information about this example, and links to other examples. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorageselecturloperation/run/index.md b/files/en-us/web/api/sharedstorageselecturloperation/run/index.md new file mode 100644 index 000000000000000..a71f99dfd477fd8 --- /dev/null +++ b/files/en-us/web/api/sharedstorageselecturloperation/run/index.md @@ -0,0 +1,51 @@ +--- +title: "SharedStorageSelectURLOperation: run() method" +short-title: run() +slug: Web/API/SharedStorageSelectURLOperation/run +page-type: web-api-instance-method +status: + - experimental +browser-compat: api.SharedStorageSelectURLOperation.run +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`run()`** method of the +{{domxref("SharedStorageSelectURLOperation")}} interface defines the structure that the `run()` method defined inside a URL Selection output gate operation should conform to. + +## Syntax + +```js-nolint +run(urls, data) +``` + +### Parameters + +- `urls` + - : An array of objects representing the URLs to be chosen between by the URL Selection operation. Each object contains two properties: + - `url` + - : A string representing the URL. + - `reportingMetadata` {{optional_inline}} + - : An object containing properties with names equal to event types, and values equal to URLs where reporting destinations are located, for example, `"click" : "my-reports/report1.html"`. These act as destinations for reports submitted with a destination type of `"shared-storage-select-url"`, for example via a {{domxref("Fence.reportEvent()")}} or {{domxref("Fence.setReportEventDataForAutomaticBeacons()")}} method call. +- `data` + - : An object representing any data required for executing the operation. + +### Return value + +A {{jsxref("Promise")}} that fulfills with a number defining the array index of the URL selected by the operation. + +## Examples + +See the main {{domxref("SharedStorageSelectURLOperation")}} page for an example. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorageworklet/index.md b/files/en-us/web/api/sharedstorageworklet/index.md new file mode 100644 index 000000000000000..9749acdebc95024 --- /dev/null +++ b/files/en-us/web/api/sharedstorageworklet/index.md @@ -0,0 +1,73 @@ +--- +title: SharedStorageWorklet +slug: Web/API/SharedStorageWorklet +page-type: web-api-interface +status: + - experimental +browser-compat: api.SharedStorageWorklet +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`SharedStorageWorklet`** interface of the {{domxref("Shared Storage API", "Shared Storage API", "", "nocode")}} represents the current origin's shared storage worklet. + +`SharedStorageWorklet` has no properties or methods directly defined on it; it inherits the {{domxref("Worklet.addModule", "addModule()")}} method from the {{domxref("Worklet")}} interface, which is used to add a module to it. Unlike a regular {{domxref("Worklet")}}. + +Note that: + +- If the calling site does not have the Shared Storage API included in a successful [privacy sandbox enrollment process](/en-US/docs/Web/Privacy/Privacy_sandbox/Enrollment), calls to `addModule()` will reject. +- `SharedStorageWorklet` can only have a single module added to it, for privacy reasons. Even with a successful enrollment, repeated calls to `addModule()` on the same shared storage worklet will reject. + +`SharedStorageWorklet` is accessed via {{domxref("WindowSharedStorage.worklet")}}. + +{{InheritanceDiagram}} + +## Examples + +```js +// Randomly assigns a user to a group 0 or 1 +function getExperimentGroup() { + return Math.round(Math.random()); +} + +async function injectContent() { + // Add the module to the shared storage worklet + await window.sharedStorage.worklet.addModule("ab-testing-worklet.js"); + + // Assign user to a random group (0 or 1) and store it in shared storage + window.sharedStorage.set("ab-testing-group", getExperimentGroup(), { + ignoreIfPresent: true, + }); + + // Run the URL selection operation + const fencedFrameConfig = await window.sharedStorage.selectURL( + "ab-testing", + [ + { url: `https://your-server.example/content/default-content.html` }, + { url: `https://your-server.example/content/experiment-content-a.html` }, + ], + { + resolveToConfig: true, + }, + ); + + // Render the chosen URL into a fenced frame + document.getElementById("content-slot").config = fencedFrameConfig; +} + +injectContent(); +``` + +See the [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) landing page for a walkthrough of this example, and links to other examples. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorageworkletglobalscope/index.md b/files/en-us/web/api/sharedstorageworkletglobalscope/index.md new file mode 100644 index 000000000000000..b2a3776ab6e20fd --- /dev/null +++ b/files/en-us/web/api/sharedstorageworkletglobalscope/index.md @@ -0,0 +1,55 @@ +--- +title: SharedStorageWorkletGlobalScope +slug: Web/API/SharedStorageWorkletGlobalScope +page-type: web-api-interface +status: + - experimental +browser-compat: api.SharedStorageWorkletGlobalScope +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`SharedStorageWorkletGlobalScope`** interface of the {{domxref("Shared Storage API", "Shared Storage API", "", "nocode")}} represents the global scope of a {{domxref("SharedStorageWorklet")}} module. + +{{InheritanceDiagram}} + +## Instance properties + +- {{domxref("SharedStorageWorkletGlobalScope.sharedStorage", "sharedStorage")}} {{Experimental_Inline}} + - : Contains a {{domxref("WorkletSharedStorage")}} object instance representing the shared storage for a particular origin, as it is exposed to a worklet context. + +## Instance methods + +- {{domxref("SharedStorageWorkletGlobalScope.register", "register()")}} {{Experimental_Inline}} + - : Registers an {{domxref("SharedStorageOperation", "operation", "", "nocode")}} defined inside the current worklet module. + +## Examples + +```js +// ab-testing-worklet.js +class SelectURLOperation { + async run(urls, data) { + // Read the user's experiment group from shared storage + const experimentGroup = await this.sharedStorage.get("ab-testing-group"); + + // Return the group number + return experimentGroup; + } +} + +register("ab-testing", SelectURLOperation); +``` + +See the [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) landing page for a walkthrough of this example, and links to other examples. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorageworkletglobalscope/register/index.md b/files/en-us/web/api/sharedstorageworkletglobalscope/register/index.md new file mode 100644 index 000000000000000..ad7bff18b10c501 --- /dev/null +++ b/files/en-us/web/api/sharedstorageworkletglobalscope/register/index.md @@ -0,0 +1,73 @@ +--- +title: "SharedStorageWorkletGlobalScope: register() method" +short-title: register() +slug: Web/API/SharedStorageWorkletGlobalScope/register +page-type: web-api-instance-method +status: + - experimental +browser-compat: api.SharedStorageWorkletGlobalScope.register +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`register()`** method of the +{{domxref("SharedStorageWorkletGlobalScope")}} interface registers an {{domxref("SharedStorageOperation", "operation", "", "nocode")}} defined inside the current worklet module. + +## Syntax + +```js-nolint +register(name, operationCtor) +``` + +### Parameters + +- `name` + - : A string representing the name you want to register the operation with. When the operation is invoked (for example via {{domxref("WindowSharedStorage.run()")}} or {{domxref("WindowSharedStorage.selectURL()")}}), the name is used to identify the operation you want to run. +- `operationCtor` + - : The class name of the operation to be registered. In real terms, this is the class constructor, which is invoked behind the scenes when the operation is run. + +### Return value + +None (`undefined`). + +### Exceptions + +- {{jsxref("TypeError")}} + - : Thrown if: + - An operation has already been registered with the specified name. + - The `operationCtor` is not a valid constructor. + - The class does not contain a valid `run()` method. + - The worklet module has not been added with {{domxref("Worklet.addModule", "SharedStorageWorklet.addModule()")}}. + +## Examples + +```js +// ab-testing-worklet.js +class SelectURLOperation { + async run(urls, data) { + // Read the user's experiment group from shared storage + const experimentGroup = await this.sharedStorage.get("ab-testing-group"); + + // Return the group number + return experimentGroup; + } +} + +register("ab-testing", SelectURLOperation); +``` + +See the [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) landing page for a walkthrough of this example, and links to other examples. + +> **Note:** It is possible to define and register multiple operations in the same shared storage worklet module script with different names; see {{domxref("SharedStorageOperation")}} for an example. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/sharedstorageworkletglobalscope/sharedstorage/index.md b/files/en-us/web/api/sharedstorageworkletglobalscope/sharedstorage/index.md new file mode 100644 index 000000000000000..8f646faa69c13f9 --- /dev/null +++ b/files/en-us/web/api/sharedstorageworkletglobalscope/sharedstorage/index.md @@ -0,0 +1,47 @@ +--- +title: "SharedStorageWorkletGlobalScope: sharedStorage property" +short-title: sharedStorage +slug: Web/API/SharedStorageWorkletGlobalScope/sharedStorage +page-type: web-api-instance-property +status: + - experimental +browser-compat: api.SharedStorageWorkletGlobalScope.sharedStorage +--- + +{{APIRef("Shared Storage API")}}{{SeeCompatTable}} + +The **`context`** read-only property of the +{{domxref("SharedStorageWorkletGlobalScope")}} interface contains a {{domxref("WorkletSharedStorage")}} object instance representing the shared storage for a particular origin, as it is exposed to a worklet context. + +## Value + +A {{domxref("WorkletSharedStorage")}} object instance. + +## Examples + +```js +// ab-testing-worklet.js +class SelectURLOperation { + async run(urls, data) { + // Read the user's experiment group from shared storage + const experimentGroup = await this.sharedStorage.get("ab-testing-group"); + + // Return the group number + return experimentGroup; + } +} + +register("ab-testing", SelectURLOperation); +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Shared Storage API](/en-US/docs/Web/API/Shared_storage_API) diff --git a/files/en-us/web/api/web_storage_api/embedded-content.png b/files/en-us/web/api/web_storage_api/embedded-content.png new file mode 100644 index 000000000000000..88a8ad6094a1a20 Binary files /dev/null and b/files/en-us/web/api/web_storage_api/embedded-content.png differ diff --git a/files/en-us/web/api/web_storage_api/index.md b/files/en-us/web/api/web_storage_api/index.md index 9a205e8b3ba078c..96687f7790ce520 100644 --- a/files/en-us/web/api/web_storage_api/index.md +++ b/files/en-us/web/api/web_storage_api/index.md @@ -32,6 +32,17 @@ These mechanisms are available via the {{domxref("Window.sessionStorage")}} and > **Note:** Access to Web Storage from third-party IFrames is denied if the user has [disabled third-party cookies](https://support.mozilla.org/en-US/kb/third-party-cookies-firefox-tracking-protection). +## Determining storage access by a third-party + +Each origin has its own storage (this is the same for web storage and [shared storage](/en-US/docs/Web/API/Shared_Storage_API)), but what about third-party (i.e. embedded) code access to shared storage? The [browsing context](/en-US/docs/Glossary/Browsing_context) of where the third-party code from another origin is executed determines whose storage that third-party code can access. + +![A box diagram showing a top-level browsing context called publisher.com, with third-party content embedded in it](embedded-content.png) + +Third-party code can be added to another site by injecting it with a {{htmlelement("script")}} element, or navigating an {{htmlelement("iframe")}} to a site that contains it. If you are a third-party from another origin, how you are added to another site determines the browsing context of your code. + +- If your third-party code is added to another site with a `