Skip to content

Commit

Permalink
update size limit (#28917)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhouyx authored Jun 17, 2020
1 parent 0a0269a commit e667e50
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 25 deletions.
36 changes: 20 additions & 16 deletions extensions/amp-consent/0.1/consent-state-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ import {Deferred} from '../../../src/utils/promise';
import {Services} from '../../../src/services';
import {assertHttpsUrl} from '../../../src/url';
import {dev, devAssert, user} from '../../../src/log';
import {dict} from '../../../src/utils/object';
import {expandConsentEndpointUrl, getConsentCID} from './consent-config';

const TAG = 'CONSENT-STATE-MANAGER';

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

export class ConsentStateManager {
/**
Expand Down Expand Up @@ -364,31 +365,34 @@ export class ConsentInstance {
return;
}

const consentStr = consentInfo['consentString'];
if (consentStr && consentStr.length > CONSENT_STRING_MAX_LENGTH) {
// Verify the length of consentString.
// 1024 * 4/3 (base64) = 1336 bytes.
const value = composeStoreValue(consentInfo);
if (value == null) {
// Value can be false, do not use !value check
// Nothing to store to localStorage
return;
}

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

if (size > CONSENT_STORAGE_MAX) {
// 1200 * 4/3 (base64) = 1600 bytes
user().error(
TAG,
'Cannot store consentString which length exceeds %s. ' +
'Cannot store consent information which length exceeds %s. ' +
'Previous stored consentInfo will be cleared',
CONSENT_STRING_MAX_LENGTH
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;
}

// TODO: enforce metadata limits here (if any)

const value = composeStoreValue(consentInfo);
if (value == null) {
// Value can be false, do not use !value check
// Nothing to store to localStorage
return;
}
this.savedConsentInfo_ = consentInfo;
storage.setNonBoolean(this.storageKey_, value);
this.sendUpdateHrefRequest_(consentInfo);
Expand Down
26 changes: 18 additions & 8 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,7 +20,7 @@ import {
constructMetadata,
} from '../consent-info';
import {
CONSENT_STRING_MAX_LENGTH,
CONSENT_STORAGE_MAX,
ConsentInstance,
ConsentStateManager,
} from '../consent-state-manager';
Expand Down Expand Up @@ -175,16 +175,19 @@ describes.realWin('ConsentStateManager', {amp: 1}, (env) => {
});

it('update consent string that exceeds max size', function* () {
expectAsyncConsoleError(/Cannot store consentString/);
expectAsyncConsoleError(/Cannot store consent information/);
manager.registerConsentInstance('test', {});
let testStr = 'a';
for (let i = 0; i < CONSENT_STRING_MAX_LENGTH; i++) {
// 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.updateConsentInstanceState(
CONSENT_ITEM_STATE.ACCEPTED,
testStr,
constructMetadata()
constructMetadata(CONSENT_STRING_TYPE.TCF_V1, '12345')
);
let value;
const p = manager.getConsentInstanceInfo().then((v) => (value = v));
Expand All @@ -193,7 +196,7 @@ describes.realWin('ConsentStateManager', {amp: 1}, (env) => {
constructConsentInfo(
CONSENT_ITEM_STATE.ACCEPTED,
testStr,
constructMetadata()
constructMetadata(CONSENT_STRING_TYPE.TCF_V1, '12345')
)
);
});
Expand Down Expand Up @@ -356,12 +359,19 @@ describes.realWin('ConsentStateManager', {amp: 1}, (env) => {
});

it('remove consentInfo when consentStr length exceeds', function* () {
expectAsyncConsoleError(/Cannot store consentString/);
expectAsyncConsoleError(/Cannot store consent information/);
let testStr = 'a';
for (let i = 0; i < CONSENT_STRING_MAX_LENGTH; i++) {
// 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);
instance.update(
CONSENT_ITEM_STATE.ACCEPTED,
testStr,
constructMetadata(CONSENT_STRING_TYPE.TCF_V1, '12345')
);
yield macroTask();
expect(storageSetSpy).to.not.be.called;
expect(storageRemoveSpy).to.be.calledOnce;
Expand Down
2 changes: 1 addition & 1 deletion extensions/amp-consent/integrating-consent.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ 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. 1024 character length is the limit. Please [file an issue](https://github.com/ampproject/amphtml/issues/new) if you find that not sufficient.
- Enforce the size of the stored consent information. 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.
- 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/master/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 e667e50

Please sign in to comment.