privacysandbox / privacy-sandbox-dev-support

Discuss your Privacy Sandbox developer questions with the Chrome team.
Apache License 2.0
179 stars 74 forks source link

Errors on shared storage API #159

Open fhoering opened 11 months ago

fhoering commented 11 months ago

We the ramp-up of Chrome traffic we started getting client complaints at Criteo about an error produced by shared storage:

Uncaught (in promise) DOMException: sharedStorage.worklet.addModule is disabled because either sharedStorage is disabled or both > sharedStorage.selectURL and privateAggregation are disabled

It seems unexpected as PS API should just silently fail if activated or not be activated at all.

It can be reproduced by:

Note that clients also have this behavior sometimes when "Block third-party cookies" is not checked. But it seems to be a good way to reproduce this error.

Can you have a look ?

image

pythagoraskitty commented 11 months ago

If third-party cookies are blocked, then it is expected that shared storage (and hence sharedStorage.worklet.addModule()) will be blocked.

In the cases where third-party cookies are not blocked, then this error can still happen, as sharedStorage.worklet.addModule() needs both sharedStorage and at least one of sharedStorage.selectURL() or privateAggregation to be enabled. Clients can disable these separately from cookies.

Also, you should ensure that your site is enrolled and attested if you haven't already.

My advice is that you wrap your code in a try...catch block so that you can process in the cases where shared storage is enabled.

Let me know if you have more questions about this.

fhoering commented 11 months ago

If third-party cookies are blocked, then it is expected that shared storage (and hence sharedStorage.worklet.addModule()) will be blocked.

If shared storage is supposed to be an alternative to 3rd party cookies it should not be blocked at all, right ?

In the cases where third-party cookies are not blocked, then this error can still happen, as sharedStorage.worklet.addModule() needs both sharedStorage and at least one of sharedStorage.selectURL() or privateAggregation to be enabled. Clients can disable these separately from cookies.

How can this happen with the latest user consent mechanism as I can only opt in to PA, Topics and Measurement ? As a user I can never choose sharedStorage or privateAggregation (see screenshot). I didn't activate any Chrome flags and this error has been seen by real users that certainly don't change chrome://flags

image

My advice is that you wrap your code in a try...catch block so that you can process in the cases where shared storage is enabled.

The code already contains checks if the APIs are activated. Just adding try/catch because we don't know what happens seems not like the right approach to me.

Can you please investigate this error ?

async function measureAudienceSize() {
  // Measuring audience size
  // Register worklet
  if((!window?.sharedStorage?.worklet?.addModule) \|\| (!window?.sharedStorage?.run)){
    return;
  }
  await window.sharedStorage.worklet.addModule('/Tagging/scripts/asw.js');
   
  // Run audience size measurement operation
  await window.sharedStorage.run('audience-size-measurement', {
     data: { bucketKey: BigInt('187300'), contributionValue: 8192}
  });
 }
fhoering commented 11 months ago

Also, you should ensure that your site is enrolled and attested if you haven't already.

Thanks for the reminder. At one point in time we had issues with the attestation on some of our subdomains like measurement-api.criteo.com. But it seems fixed now on Chrome Canary or at least I don't see it anymore. Did you see any error somewhere or was this just a general comment ?

pythagoraskitty commented 11 months ago

Uncaught (in promise) DOMException: sharedStorage.worklet.addModule is disabled because either sharedStorage is disabled or both > sharedStorage.selectURL and privateAggregation are disabled

The ways of hitting this error are if:

  1. The site calling shared storage is not properly enrolled and attested.
  2. Third-party cookies are blocked by the user.
  3. sharedStorage is disabled by the user.
  4. Both sharedStorage.selectURL() and privateAggregation are disabled by the user.

I don't have any specific reason to believe that (1) is at issue here, but I mentioned it to double check that you have completed the enrollment/attestation process. If you have more questions about that, I will get someone from that team to chime in.

To comment on (2), we are blocking shared storage when a user blocks all third-party cookies because we made the privacy design decision that it was likely that the average user who elects to block third-party cookies would reasonably expect other technologies collecting cross-site data to be blocked as well. I realize that this may be counterintuitive, and we are open to feedback. Note that in the long term, of course, third-party cookies will be deprecated in any case.

As for (3) and (4), you are correct in surfacing that the UX toggles are somewhat confusing in terms of how they correlate with enabling/disabling sharedStorage, sharedStorage.selectURL(), and privateAggregation. The toggles which accomplish this are not currently listed under those same names in the UX.

All of the following explanation assumes that "Privacy Sandbox Settings V4" and "Privacy Sandbox Ads APIs" are enabled in chrome://flags. Otherwise the settings discussed may not appear in the menu.

Screenshot of chrome://flags

sharedStorage can be enabled/disabled at chrome://settings/content/siteData.

Screenshot of chrome://settings/content/siteData with toggle on

Screenshot of chrome://settings/content/siteData with toggle off

sharedStorage.selectURL() can be enabled/disabled at chrome://settings/adPrivacy/sites.

Screenshot of chrome://settings/adPrivacy/sites with toggle on

Screenshot of chrome://settings/adPrivacy/sites with toggle off

privateAggregation can be enabled/disabled at chrome://settings/adPrivacy/measurement

Screenshot of chrome://settings/adPrivacy/measurement with toggle on

Screenshot of chrome://settings/adPrivacy/measurement with toggle off

Let me know if this makes sense.

My guess is that what's causing the error here is (4), since you are already checking whether sharedStorage is enabled, which should account for (1), (2), and (3). Since you aren't going to be able to assume that all users have sharedStorage.selectURL() and/or privateAggregation enabled, however, you will need to also check for the availability of at least one of those.

Can you add a check for those and see if it resolves the problem?

jkarlin commented 11 months ago

Hi Fabian - appreciate you reaching out. A couple of thoughts here. The first is that disabling third-party cookies blocked the Privacy Sandbox Ads APIs during the Origin Trial experiment process, as the UX wasn’t yet completed. With general availability of the APIS and UX, disabling third-party cookies no longer disables the APIs. It’s possible to still have the old UX if you’ve enabled some custom flags (e.g., PrivacySandboxAdsAPIs).

Second, I hear your request for feature detection to be more capable here. The team is thinking about this (e.g., disabling the API surface if the user has opted out of it). Will get back to you on it. If you have any other suggestions, we are open to feedback.

fhoering commented 11 months ago

The first is that disabling third-party cookies blocked the Privacy Sandbox Ads APIs during the Origin Trial experiment process, as the UX wasn’t yet completed. With general availability of the APIS and UX, disabling third-party cookies no longer disables the APIs. It’s possible to still have the old UX if you’ve enabled some custom flags (e.g., PrivacySandboxAdsAPIs).

OK. Thanks for the replies. I didn't mention this but on my local machine I very likely still had the flags PrivacySandboxAdsAPIs enabled. So I hear the error will disappear with global rollout of all APIs.

Ideally all intermediate behaviors/flags should be cleaned up. Like only have the new consent popups everywhere and some necessary override flags like "Privacy Sandbox Enrollment Overrides" for testing domains, for example. The blocked 3rd party cookies mode will be used to simulate 3rd party cookie deprecation behavior. So it is pretty important also that all new APIs are available and that this simulates the real new cookie deprecation behavior.

FIGHTING-TOP commented 7 months ago

image I get a similar problem, I have enable Privacy Sandbox Ads APIs & third-party-cookie

pythagoraskitty commented 7 months ago

Hello @FIGHTING-TOP. Thank you so much for testing our new APIs!

It looks the site where you are trying to use shared storage is not enrolled and/or attested, or else somehow is not being recognized as such. (See https://github.com/privacysandbox/attestation/blob/main/how-to-enroll.md.)

You can override this locally at chrome://flags/#privacy-sandbox-enrollment-overrides.

Please let me know if you need more help.

fhoering commented 1 week ago

@jkarlin we stopped using shared storage for some time and now started using it again at scale. The error is still there and we are getting complaints from our customers for error messages in their console. If you don't know why this happens in some cases can you at least donwgrade the error to a warning ?

pythagoraskitty commented 1 week ago

Hello @fhoering ,

Have you confirmed that the site trying to use shared storage is attested? An attestation error is the most likely thing happening here.

If you want a more verbose debug message displayed in the DevTools console for why shared storage is disabled on a given machine, you can enable this feature via command line (--enable-features=SharedStorageAPI:ExposeDebugMessageForSettingsStatus/true. (Note that this verbose message can only be set locally.)

fhoering commented 1 week ago

@pythagoraskitty It is definitely not an attestation issue as we get client complaints and it works in most cases and shared storage is called from Criteo iframe.

@jkarlin @pythagoraskitty Can you please have a look or forward this issue to other Chrome engineers ? As I said the best would be to fix it. If you have no resources to investigate this please at least downgrade this to a warning.

fhoering commented 1 week ago

@pythagoraskitty @jkarlin We made some more tests with Chrome stable 128.

The issue actually happens when the user has deactivated chrome://settings/adPrivacy/sites which means it is linked to sharedStorage.selectURL enabling/disabling as per comment from above:

sharedStorage.selectURL() can be enabled/disabled at chrome://settings/adPrivacy/sites.

Then there are two different behaviors:

  1. When in addition to that chrome://settings/adPrivacy/measurement in off the error is:

    Uncaught (in promise) OperationError: sharedStorage.worklet.addModule is disabled because either sharedStorage is disabled or both sharedStorage.selectURL and privateAggregation are disabled

  2. When in addition to that chrome://settings/adPrivacy/measurement in on the error is:

    Uncaught (in promise) OperationError: sharedStorage.selectURL is disabled

Our code is here:

  async function run() {
        if (!window?.sharedStorage?.selectURL) {
            return;
        }

        await window.sharedStorage.worklet.addModule('https://myurl//worklet');

        window.sharedStorage.set('key', '1', { ignoreIfPresent: true });

        const urls = [];
        urls.push({ url: `https://myurl..` });

        const urn = await window.sharedStorage.selectURL('select-abt-url', urls, {resolveToConfig: false});
        dropIFrame(urn);    
    }
run()

For 1. the call to window.sharedStorage.worklet.addModule fails For 2. the call to window.sharedStorage.selectURLfails

In both cases we should never reach this code because we are checking the availability of !window?.sharedStorage?.selectURL

So it seems like the unchecking chrome://settings/adPrivacy/sites doesn't really remove the availability of window.sharedStorage.selectURL API.

Normally all PSB APIs can be checked for availability according to this doc https://github.com/WICG/turtledove/blob/main/PA_Feature_Detecting.md (doc on sharedStorage is missing however)

Is the explanation clear ? It clearly looks like a bug to me. Can you please fix the behavior ?

jkarlin commented 1 week ago

Hi @fhoering

addModule and selectURL can both throw exceptions, for reasons such as lack of attestation, or the user has disabled the API, and more. It's therefore important to wrap your shared storage operations in try/catch if you're using async/await.

There are several other web APIs that have this behavior of throwing when they're not going to work, e.,g., some newer APIs that are gated by permission policy such as payments.

I know you'd prefer for the API to not even exist if it's not going to work, so that you can feature detect. That's not really how platform APIs work however. You can always try a single operation with a try/catch and condition based on that as a form of feature detection I suppose. I don't recommend that though.

fhoering commented 6 days ago

OK. thanks @jkarlin for the additional information. As as workaround that is what we are going to do. It is good news already that the issue seems clearer.

addModule and selectURL can both throw exceptions, for reasons such as lack of attestation, or the user has disabled the API, and more. It's therefore important to wrap your shared storage operations in try/catch if you're using async/await.

I think you should add the try/catch part or some note to the documentation samples. It is currently not mentioned: https://github.com/WICG/shared-storage?tab=readme-ov-file#simple-example-consistent-ab-experiments-across-sites It looks documented in the payment API for example.

There are several other web APIs that have this behavior of throwing when they're not going to work, e.,g., some newer APIs that are gated by permission policy such as payments.

I don't really see why shared storage is closer to the payment API rather then to the other PSB APIs. And they are all new and have feature detection. So, it looks consistent to me to also be able to feature detect this API as part of all PSB APIs. However I agree that a consistent behavior across all web apis looks impossible. So maybe just some additional documentation is enough.