Skip to content

Commit

Permalink
Remove consent storage limit for viewer (#34054)
Browse files Browse the repository at this point in the history
  • Loading branch information
Micajuine Ho authored May 6, 2021
1 parent 5245f96 commit a81915a
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 106 deletions.
40 changes: 2 additions & 38 deletions extensions/amp-consent/0.1/consent-state-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,12 @@ import {
import {Deferred} from '../../../src/core/data-structures/promise';
import {Services} from '../../../src/services';
import {assertHttpsUrl} from '../../../src/url';
import {dev, devAssert, user} from '../../../src/log';
import {dict, hasOwn} from '../../../src/core/types/object';
import {dev, devAssert} from '../../../src/log';
import {expandConsentEndpointUrl, getConsentCID} from './consent-config';
import {hasOwn} from '../../../src/core/types/object';

const TAG = 'CONSENT-STATE-MANAGER';

/** @visibleForTesting */
export const CONSENT_STORAGE_MAX = 1200;

export class ConsentStateManager {
/**
* Creates an instance of ConsentStateManager.
Expand Down Expand Up @@ -447,39 +444,6 @@ export class ConsentInstance {
return;
}

// Check size
const size = JSON.stringify(
dict({
[this.storageKey_]: value,
})
).length;

if (size > CONSENT_STORAGE_MAX) {
// Size restriction only applies to documents servered from a viewer
// that implements the storage API.
const usesViewerStorage = storage.isViewerStorage();
if (usesViewerStorage) {
// 1200 * 4/3 (base64) = 1600 bytes
user().error(
TAG,
'Cannot store consent information which length exceeds %s. ' +
'Previous stored consentInfo will be cleared',
CONSENT_STORAGE_MAX
);
// If new consentInfo value cannot be stored, need to remove previous
// value
storage.remove(this.storageKey_);
// TODO: Good to have a way to inform CMP service in this case
return;
}
user().info(
TAG,
'Current consent information length exceeds %s ' +
'and will not be stored when the page is served ' +
'from a viewer that supports the Local Storage API.',
CONSENT_STORAGE_MAX
);
}
this.savedConsentInfo_ = consentInfo;
storage.setNonBoolean(this.storageKey_, value);
this.sendUpdateHrefRequest_(consentInfo);
Expand Down
67 changes: 1 addition & 66 deletions extensions/amp-consent/0.1/test/test-consent-state-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,8 @@ import {
constructConsentInfo,
constructMetadata,
} from '../consent-info';
import {
CONSENT_STORAGE_MAX,
ConsentInstance,
ConsentStateManager,
} from '../consent-state-manager';
import {CONSENT_STRING_TYPE} from '../../../../src/core/constants/consent-state';
import {ConsentInstance, ConsentStateManager} from '../consent-state-manager';
import {Services} from '../../../../src/services';
import {dev} from '../../../../src/log';
import {macroTask} from '../../../../testing/yield';
Expand Down Expand Up @@ -194,35 +190,6 @@ describes.realWin('ConsentStateManager', {amp: 1}, (env) => {
)
);
});

it('update consent string that exceeds max size', async () => {
expectAsyncConsoleError(/Cannot store consent information/);
manager.registerConsentInstance('test', {});
let testStr = 'a';
// Reserve 26 chars to metadata size `"m":{"cst":1,"ac":"12345"}`
// Reserve 36 chars to the storage key, `''` and `{}`
// Leaves CONSENT_STORAGE_MAX - 62 chars to consent string
for (let i = 0; i < CONSENT_STORAGE_MAX - 62; i++) {
testStr += 'a';
}
manager.updateConsentInstancePurposes({
'purpose-abc': PURPOSE_CONSENT_STATE.ACCEPTED,
});
manager.updateConsentInstanceState(
CONSENT_ITEM_STATE.ACCEPTED,
testStr,
constructMetadata(CONSENT_STRING_TYPE.TCF_V1, '12345')
);
const value = await manager.getConsentInstanceInfo();
expect(value).to.deep.equal(
constructConsentInfo(
CONSENT_ITEM_STATE.ACCEPTED,
testStr,
constructMetadata(CONSENT_STRING_TYPE.TCF_V1, '12345'),
{'purpose-abc': PURPOSE_CONSENT_STATE.ACCEPTED}
)
);
});
});

describe('onConsentStateChange', () => {
Expand Down Expand Up @@ -497,38 +464,6 @@ describes.realWin('ConsentStateManager', {amp: 1}, (env) => {
expect(storageSetSpy).to.not.be.called;
expect(storageRemoveSpy).to.be.calledOnce;
});

it('remove consentInfo when consentStr length exceeds', function* () {
expectAsyncConsoleError(/Cannot store consent information/);
let testStr = 'a';
// Reserve 26 chars to metadata size `"m":{"cst":1,"ac":"12345"}`
// Reserve 36 chars to the storage key, `''` and `{}`
// Leaves CONSENT_STORAGE_MAX - 62 chars to consent string
for (let i = 0; i < CONSENT_STORAGE_MAX - 62; i++) {
testStr += 'a';
}
instance.update(
CONSENT_ITEM_STATE.ACCEPTED,
testStr,
undefined,
constructMetadata(CONSENT_STRING_TYPE.TCF_V1, '12345')
);
yield macroTask();
expect(storageSetSpy).to.not.be.called;
expect(storageRemoveSpy).to.be.calledOnce;
});

it('allows large consentInfo when not using viewer storage API', async () => {
usesViewer = false;
let testStr = 'a';
for (let i = 0; i < CONSENT_STORAGE_MAX - 62; i++) {
testStr += 'a';
}
instance.update(CONSENT_ITEM_STATE.ACCEPTED, testStr);
await macroTask();
expect(storageSetSpy).to.be.calledOnce;
expect(storageRemoveSpy).to.not.be.called;
});
});

describe('should override stored value correctly', () => {
Expand Down
2 changes: 0 additions & 2 deletions extensions/amp-consent/integrating-consent.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ To add your consent management service to AMP runtime, it is expected that you:
- Meet the restrictions that the AMP runtime applies to ensure a good user experience. These includes
- Enforce the size of the consent prompt. The only two allowed sizes are the initial size (`width: 100vw`, `height: 30vh`), and the full screen size (`width: 100vw`, `height: 100%`) after user interactions.
- A default placeholder will be displayed before the consent prompt iframe is ready.
- Enforce the size of the stored consent information, when the page is served from a cache that supports the [Storage API](./../../spec/amp-localstorage.md#Storage-API). 1200 character length including storage key, consent string and additional metadata is the limit. Please [file an issue](https://github.com/ampproject/amphtml/issues/new) if you find that not sufficient.
- NOTE: You can detect if the page is being served from the origin from the `checkConsentHref` request header or via `window.location.ancestorOrigin` within the iframe. Additionally, if the page is served from the cache, there is no guarantee that the LocalStorage API is supported by the viewer, and the consent information might not be persisted.
- Understand that including `<amp-consent type='yourName'></amp-consent>` on the page won't block any components by default. **Please make sure to inform your service users to block AMP components either by the `<meta name="amp-consent-blocking">` metaTag, or the `data-block-on-consent` attribute.**
- Understand that AMP Consent doesn't attempt to interpret the consent info string from the CMP. Vendors can access the consent info string from CMPs via [provided APIs](https://github.com/ampproject/amphtml/blob/main/ads/README.md#amp-consent-integration). It's up to the CMP and service provider vendors to agree on the format of the consent info string.
- Create an [Intent-To-Implement issue](../../CONTRIBUTING.md#contributing-features) stating that you'll be adding support to your CMP service to AMP. A great start point is to follow the `_ping_` CMP service implementation that the AMP team creates for testing purpose.
Expand Down

0 comments on commit a81915a

Please sign in to comment.