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

Report user-error from 3p iframe #11002

Merged
merged 44 commits into from Aug 31, 2017
Merged

Report user-error from 3p iframe #11002

merged 44 commits into from Aug 31, 2017

Conversation

tiendt
Copy link
Contributor

@tiendt tiendt commented Aug 19, 2017

For #10892

@tiendt tiendt requested review from lannka and zhouyx August 19, 2017 05:45
@tiendt tiendt self-assigned this Aug 19, 2017
lannka
lannka previously requested changes Aug 20, 2017
@@ -208,7 +209,8 @@
type="a9"
data-aax_size="300x250"
data-aax_pubname="test123"
data-aax_src="302">
data-aax_src="302"
Copy link
Contributor

Choose a reason for hiding this comment

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

pls have a separate example page

<script type="application/json">
{
"requests": {
"user-error": "http://localhost:8000/ampadtest"
Copy link
Contributor

Choose a reason for hiding this comment

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

include error type and message in the request

3p/ampcontext.js Outdated
*/
errorReport() {
this.win_.addEventListener('error', event => {
if (!!event.error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Unnecessary !!

@@ -0,0 +1,1436 @@
<!doctype html>
Copy link
Contributor

Choose a reason for hiding this comment

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

why is this file?
for a testing example, you can put in analytics-user-error.amp.html once that PR is merged

Copy link
Contributor

Choose a reason for hiding this comment

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

+1

@lannka
Copy link
Contributor

lannka commented Aug 24, 2017

@zhouyx I will leave the rest to you

@lannka lannka dismissed their stale review August 24, 2017 17:45

@zhouyx I will leave the rest to you

@@ -206,6 +207,11 @@ export class AmpAdXOriginIframeHandler {
this.sendEmbedInfo_(this.baseInstance_.isInViewport());
}));

this.unlisteners_.push(listenFor(this.iframe, 'user-error',
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Use MessageType.USER_ERROR.

this.unlisteners_.push(listenFor(this.iframe, 'user-error',
data => {
this.userErrorForAnalytics(data['error'], data['message']);
}, true, true));
Copy link
Contributor

Choose a reason for hiding this comment

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

opt_includingNestedWindows set to true if a messages from nested frames should also be accepted.

I don't think you want to include messages from nested frames?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you mean and why so?

Copy link
Contributor

Choose a reason for hiding this comment

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

* @param {!Error} error
* @param {string} message
*/
userErrorForAnalytics(error, message) {
Copy link
Contributor

Choose a reason for hiding this comment

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

who is calling this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

in the listenFor('user-error), line 212

Copy link
Contributor

Choose a reason for hiding this comment

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

should be private function

3p/ampcontext.js Outdated
if (!!event.error) {
this.client_.sendMessage(MessageType.USER_ERROR, dict({
'error': event.error,
'message': event.error.message,
Copy link
Contributor

Choose a reason for hiding this comment

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

is event the ErrorEvent? if so should it be event.message here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was thinking event.error returns error so I can get message from that error

Copy link
Contributor

Choose a reason for hiding this comment

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

I honestly don't know. Can you make sure?

3p/ampcontext.js Outdated
@@ -104,6 +104,7 @@ export class AbstractAmpContext {
this.client_ = new IframeMessagingClient(win);
this.client_.setHostWindow(this.getHostWindow_());
this.client_.setSentinel(dev().assertString(this.sentinel));
this.errorReport();
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: reportError()?

3p/ampcontext.js Outdated
report3pError_() {
this.win_.onerror = function(message) {
if (message) {
this.client_.sendMessage(MessageType.USER_ERROR, dict({
Copy link
Contributor

Choose a reason for hiding this comment

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

the code here won't work. this changes in function. You can either use () => {} or bind this to the function.

Copy link
Contributor

@zhouyx zhouyx left a comment

Choose a reason for hiding this comment

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

Looks good in general. Few more comments : )

<amp-youtube width="480" height="270"
data-param-autoplay
data-videoid="dQw4w9WgXcQ">
</amp-youtube>

<amp-analytics type="googleanalytics">
<h1>These create 3P error</h1>
<h2>A9 fake 3p error</h2>
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer throw fake error in our fake ping ad. But I am ok with using these two, if they return use error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah these return user error. I can add more errors if needed?

Copy link
Contributor

Choose a reason for hiding this comment

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

I am ok with this

* @private
*/
userErrorForAnalytics_(message) {
const e = new Error();
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 check message is a string here. Just want to be safe.
Then do e = new Error(message);

};
windowMessageHandler(message);

window.onerror = function(message, source, lineno, colno, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I see we use describe here, so please do not rewrite window function. This can potentially break other unrelated tests that depend on window.onerror.
You can mock it in win, like what we did for addEventListener.
Also this test here simply fake everything that we want to test. Can we use the try/catch we have before?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because for testing onerror, it will need to manually call the handler instead of how we dealt with addEventListener(). cc @cramforce

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. I am however still opposing overwriting window.onerror here, it would super hard to debug later. We can 1) rewrite the test to use describes or 2) make the onerror function a method and test that method instead.

expect(message).to.equal('message');
context.report3pError_();
expect(windowPostMessageSpy).to.be.called;
expect(windowPostMessageSpy).to.be.calledWith(
Copy link
Contributor

Choose a reason for hiding this comment

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

please use .jsonObject as we agreed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just took a look at the code, postMessage would call to serializeMessage which will JSON.stringify(message). Therefore I think checking the value as string here is expected.

Copy link
Contributor

Choose a reason for hiding this comment

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

you can use deserializeMessage before testing. I know the test works fine, but it would be really hard for people to fix, if it fails for any reason.

@@ -51,6 +51,9 @@ export const MessageType = {
// For amp-analytics' iframe-transport
SEND_IFRAME_TRANSPORT_EVENTS: 'send-iframe-transport-events',
IFRAME_TRANSPORT_EVENTS: 'iframe-transport-events',

// For user-error
USER_ERROR: 'user-error',
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 rename this to USER_ERROR_IN_IFRAME? I find that to be more clear. Thanks

this.unlisteners_.push(listenFor(this.iframe, MessageType.USER_ERROR,
data => {
this.userErrorForAnalytics_(data['message']);
}, true, true));
Copy link
Contributor

Choose a reason for hiding this comment

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

please see my previous comments. I really don't think we should listen to message from nested iframe here. Also i don't think nested iframe will send us error message.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought when we talked offline you said you'd prefer to send message around instead of error. What's your suggestion to improve this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Please see. #11002 (comment)
Let me know if there's any question

3p/ampcontext.js Outdated
this.win_.onerror = message => {
if (message) {
this.client_.sendMessage(MessageType.USER_ERROR_IN_IRAME, dict({
'message': message,
Copy link
Member

Choose a reason for hiding this comment

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

Don't you want the stack?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I only need the message to be passed through

Copy link
Contributor

Choose a reason for hiding this comment

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

Curious how can we get the stack here?

Copy link
Member

Choose a reason for hiding this comment

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

The 4th argument (I think) of onerror is the Error object or undefined.

So you can do 'stack': error && error.stack

throw e;
} catch (err) {
win.onerror = function(message, source, lineno, colno, error) {
expect(error).to.equal(err);
Copy link
Member

Choose a reason for hiding this comment

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

Does this actually run? How?

@@ -523,6 +529,18 @@ export class AmpAdXOriginIframeHandler {
this.intersectionObserver_.fire();
}
}

/**
* @param {!string} message
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: {string}

@@ -51,6 +51,9 @@ export const MessageType = {
// For amp-analytics' iframe-transport
SEND_IFRAME_TRANSPORT_EVENTS: 'send-iframe-transport-events',
IFRAME_TRANSPORT_EVENTS: 'iframe-transport-events',

// For user-error
USER_ERROR_IN_IRAME: 'user-error',
Copy link
Contributor

Choose a reason for hiding this comment

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

nit : USER_ERROR_IN_IFRAME: 'user-error-in-iframe',

3p/ampcontext.js Outdated
'message': message,
}));
}
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

just curious, do we have to return false here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if we don't return false then it would be undefined, which is false. But i think we should explicitly return false to make it readable

Copy link
Contributor

Choose a reason for hiding this comment

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

sounds good

3p/ampcontext.js Outdated
this.win_.onerror = message => {
if (message) {
this.client_.sendMessage(MessageType.USER_ERROR_IN_IRAME, dict({
'message': message,
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious how can we get the stack here?

3p/ampcontext.js Outdated
'message': message,
}));
}
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

sounds good

<amp-youtube width="480" height="270"
data-param-autoplay
data-videoid="dQw4w9WgXcQ">
</amp-youtube>

<amp-analytics type="googleanalytics">
<h1>These create 3P error</h1>
<h2>A9 fake 3p error</h2>
Copy link
Contributor

Choose a reason for hiding this comment

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

I am ok with this

@@ -51,6 +51,9 @@ export const MessageType = {
// For amp-analytics' iframe-transport
SEND_IFRAME_TRANSPORT_EVENTS: 'send-iframe-transport-events',
IFRAME_TRANSPORT_EVENTS: 'iframe-transport-events',

// For user-error-in-iframe
USER_ERROR_IN_IRAME: 'user-error-in-iframe',
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: USER_ERROR_IN_IFRAME

Copy link
Contributor

@zhouyx zhouyx left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -32,8 +32,6 @@ describe('3p ampcontext.js', () => {
windowPostMessageSpy = sandbox.spy();
win = {
addEventListener: (eventType, handlerFn) => {
expect(eventType).to.equal('message');
Copy link
Contributor

Choose a reason for hiding this comment

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

don't think you should remove Alan's test here though.

win.name = generateSerializedAttributes();
const context = new AmpContext(win);
expect(context).to.be.ok;
context.report3pError_();
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question again, the constructor already called report3pError_() why we need to call it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i needed it to test addEventListener call before, but forgot to remove. Will change now.

@@ -61,6 +59,24 @@ describe('3p ampcontext.js', () => {
windowMessageHandler = undefined;
});

it('should send message when report3pError_()', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: 'should send error message with report3pError_'

Copy link
Member

@cramforce cramforce left a comment

Choose a reason for hiding this comment

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

LGTM
See comments about stack traces (if appliacable).

@cramforce cramforce merged commit dbd6399 into ampproject:master Aug 31, 2017
@tiendt tiendt mentioned this pull request Sep 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants