Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moves closure sha384 into a new extension amp-crypto-polyfill for lazy load #7006

Merged
merged 6 commits into from
Jan 13, 2017

Conversation

lannka
Copy link
Contributor

@lannka lannka commented Jan 12, 2017

This PR introduces our first "lib-like" extension amp-crypto-polyfill.
Part of #4898

/cc @keithwrightbos This should unblock your refactoring in #6837

dev().error(TAG, FALLBACK_MSG, e);
}
return this.loadPolyfill_()
.then(polyfill => polyfill.sha384(input));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call this.sha384(input) instead? The correct polyfill method is already codified above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that will not work. we need to call loadPolyfill here otherwise this.polyfillPromise_ is null forever

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yah, but the then block doesn't need to know about polyfill#sha384.

return this.loadPolyfill_().then(this.sha384(input));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, done.

});
} catch (e) {
dev().error(TAG, FALLBACK_MSG, e);
return this.loadPolyfill_().then(polyfill => polyfill.sha384(input));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

if (this.polyfillPromise_) {
return this.polyfillPromise_;
}
return this.polyfillPromise_ = extensionsFor(this.win_)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add the polyfillPromise_ property in the constructor, regardless of subtle_.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -70,9 +83,7 @@ export class Crypto {
* @throws {!Error} when input string contains chars out of range [0,255]
*/
sha384Base64(input) {
return this.sha384(input).then(buffer => {
return lib.base64(buffer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please drop the base64 stuff from the library?! 😋

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh ye, will do

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. but no size change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really? Does sha384 internally depend on it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, i've updated it already. did you see anything else i can strip off?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh perfect, not sure how I missed that.

import * as lib from '../../../third_party/closure-library/sha384-generated';

// Register doc-service factory.
AMP.registerServiceForDoc(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just do window-singleton service instead? It really always window-scoped, right? Just as WebCrypto itself...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small correction:
installCryptoPolyfill(window);

->

installCryptoPolyfill(AMP.win);

}
// polyfill is (being) loaded,
// means native Crypto API is not available or failed before.
if (this.polyfillPromise_) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This var should be defined in the constructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -28,6 +30,13 @@ export class Crypto {
constructor(win) {
/** @private @const {?webCrypto.SubtleCrypto} */
this.subtle_ = getSubtle(win);

/** @private {!Window} */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move on top.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -28,6 +30,13 @@ export class Crypto {
constructor(win) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jsdoc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

import {fromClass} from '../../../src/service';
import {dev} from '../../../src/log';
import {getExistingServiceForWindow} from '../../../src/service';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this module now just needs to go to the src/, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, please add tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@keithwrightbos has a pending PR to do that. Tests updated.

}
try {
return this.subtle_.digest({name: 'SHA-384'},
input instanceof Uint8Array ? input : stringToBytes(input))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be the other way: if (typeof input == 'string') ? stringToBytes(input) : input?

try {
return this.subtle_.digest({name: 'SHA-384'},
input instanceof Uint8Array ? input : stringToBytes(input))
// [].slice.call(Unit8Array) is a shim for Array.from(Unit8Array)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
return this.polyfillPromise_ = extensionsFor(this.win_)
.loadExtension('amp-crypto-polyfill')
.then(() => getExistingServiceForWindow(this.win_, 'crypto-polyfill'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already lookup window-scoped service, so it should definitely be window-scoped in the polyfill itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


/**
* Loads Crypto polyfill library.
* @returns {!Promise}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be !Promise<????> since you are using response of this promise everywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not seeing changes here. Did you push?

Also, it should be @return (no "s")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obviously i lied. done now.

Copy link
Contributor Author

@lannka lannka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments addressed. PTAL

import {fromClass} from '../../../src/service';
import {dev} from '../../../src/log';
import {getExistingServiceForWindow} from '../../../src/service';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@keithwrightbos has a pending PR to do that. Tests updated.

@@ -28,6 +30,13 @@ export class Crypto {
constructor(win) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -28,6 +30,13 @@ export class Crypto {
constructor(win) {
/** @private @const {?webCrypto.SubtleCrypto} */
this.subtle_ = getSubtle(win);

/** @private {!Window} */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
// polyfill is (being) loaded,
// means native Crypto API is not available or failed before.
if (this.polyfillPromise_) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

try {
return this.subtle_.digest({name: 'SHA-384'},
input instanceof Uint8Array ? input : stringToBytes(input))
// [].slice.call(Unit8Array) is a shim for Array.from(Unit8Array)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


/**
* Loads Crypto polyfill library.
* @returns {!Promise}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

if (this.polyfillPromise_) {
return this.polyfillPromise_;
}
return this.polyfillPromise_ = extensionsFor(this.win_)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
return this.polyfillPromise_ = extensionsFor(this.win_)
.loadExtension('amp-crypto-polyfill')
.then(() => getExistingServiceForWindow(this.win_, 'crypto-polyfill'));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

import * as lib from '../../../third_party/closure-library/sha384-generated';

// Register doc-service factory.
AMP.registerServiceForDoc(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@lannka lannka removed the WIP label Jan 13, 2017
}

/**
* Returns the SHA-384 hash of the input string in a number array.
* Input string cannot contain chars out of range [0,255].
* @param {string|!Uint8Array} input
* @returns {!Promise<!Array<number>>}
* @returns {!Promise<!Uint8Array>}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@return

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

} catch (e) {
dev().error(TAG, FALLBACK_MSG, e);
}
if (!(input instanceof Uint8Array)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are usually careful with instanceof b/c of different window contexts. E.g. window.UInt8Array vs embedWin.UInt8Array. Is this not a concern here?

/cc @jridgewell

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Friendly Frames are the only thing that can violate that, right? We can do a !input.buffer check instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Only friendly iframes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi gentlemen, what is this?
Uint8Array can be different across windows in same browser?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each window has its own instance of the generic classes, take String for instance. Now, when we create an iframe, it gets its own window and its own String. If we compare, they are not equivalent:

window.String === iframe.contentWindow.String; // => false

Since instanceof looks for object equality in the prototype chain, this also breaks across iframe boundaries:

iframe.contentWindow.uint8instance instanceof Uint8Array; // => false
uint8instance instanceof iframe.contentWindow.Uint8Array; // => false

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow. thanks!
will change to typeof input === "string"

@dvoytenko
Copy link
Contributor

@lannka Couple more comments, but otherwise LGTM.

@lannka lannka merged commit 17136cf into ampproject:master Jan 13, 2017
@lannka lannka deleted the crypto-polyfill branch January 13, 2017 21:49
rpominov pushed a commit to yandex-pcode/amphtml that referenced this pull request Jan 20, 2017
* master: (310 commits)
  Update csa.md to remove non-required parameters (ampproject#6902)
  Add notes about requesting ads ATF and link to demo (ampproject#7037)
  Remove whitelist for lightbox scrollable validator (ampproject#7034)
  Delegate submit events until amp-form is loaded  (ampproject#6929)
  Moves closure sha384 into a new extension amp-crypto-polyfill for lazy load (ampproject#7006)
  Refactor observables in viewer-impl into a map object (ampproject#7004)
  resizing of margins (ampproject#6824)
  Use URL replacer from embed for pixel (ampproject#7029)
  adds support for Gemius analytics (ampproject#6558)
  Avoid duplicating server-layout (ampproject#7021)
  Laterpay validator config (ampproject#6974)
  Validator rollup (ampproject#7023)
  skeleton for amp-tabs (ampproject#7003)
  Upgrade post-css and related packages to latest (ampproject#7020)
  handle unload (ampproject#7001)
  viewer-integr.js -> amp-viewer-integration (ampproject#6989)
  dev().info()->dev().fine() (ampproject#7017)
  Turned on experiment flag (ampproject#6774)
  Unlaunch ios-embed-wrapper for iOS8 to avoid scroll freezing issues (ampproject#7018)
  Add some A4A ad request parameters (ampproject#6643)
  ...
jridgewell pushed a commit to jridgewell/amphtml that referenced this pull request Jan 31, 2017
…y load (ampproject#7006)

* Moves closure sha384 into a new extension amp-crypto-polyfill for lazy load.

* fix

* Update tests. Remove base64 polyfill from lib.

* Fix presubmit

* Address comments

* Fix test.
mrjoro pushed a commit to mrjoro/amphtml that referenced this pull request Apr 28, 2017
…y load (ampproject#7006)

* Moves closure sha384 into a new extension amp-crypto-polyfill for lazy load.

* fix

* Update tests. Remove base64 polyfill from lib.

* Fix presubmit

* Address comments

* Fix test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants