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 when XHR are issued before viewer is visible #9350
Conversation
src/service/xhr-impl.js
Outdated
this.ampdoc_ = ampdocServiceFor(win).getAmpDoc(); | ||
} catch (e) { | ||
this.ampdoc_ = null; | ||
dev().error('XHR', e, 'XHR service failed to find ampdoc'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The probability of failure in PWA case here is about 100% :).
I think we just need to restrict this reporting/warning to single-doc mode. The real issue is only in this mode anyway. See AmpDocService.isSingleDoc()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I was thinking. Though I don't agree that it's only needed in single-doc mode. Is there a way to get the parent amp-doc while in PWA?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only way to pull the parent ampdoc is by passing around the context node (element). The reason why I think PWA mode is less relevant b/c this is a privacy feature, since iframes can pull documents from different origins. PWA on the other hand is built to serve "own" same-origin documents. If PWA decides to request cross-origin docs, it still needs to support CORS, etc - which essentially nullify our protection here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation, done!
src/service/xhr-impl.js
Outdated
input); | ||
} | ||
} else { | ||
dev().error('XHR', 'attempted to fetch %s without knowing if viewer is' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above
src/service/xhr-impl.js
Outdated
// TODO(@jridgewell, #9048): We can alternatively _always_ wait on | ||
// #whenFirstVisible. | ||
if (!viewerForDoc(this.ampdoc_).hasBeenVisible()) { | ||
dev().error('XHR', 'attempted to fetch %s before viewer was visible', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To start with, we should sample it at 1% and then go higher. Otherwise we take a risk of over-spamming our pantheon which is quota-limited. Once confirmed low volume - we can go to 100%.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this already sampled by the error reporting server?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, we don't want to overwhelm that service either. But basically, error transformer can only sample randomly regardless of error. So if we think this could have too big a rate, we should do it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/service/xhr-impl.js
Outdated
@@ -94,6 +96,11 @@ export class Xhr { | |||
constructor(win) { | |||
/** @const {!Window} */ | |||
this.win = win; | |||
|
|||
const ampdocService = ampdocServiceFor(win); | |||
this.ampdoc_ = ampdocService.isSingleDoc() ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: ampdocSingle_
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 and jsdoc
src/service/xhr-impl.js
Outdated
if (this.ampdoc_) { | ||
// TODO(@jridgewell, #9048): We can alternatively _always_ wait on | ||
// #whenFirstVisible. | ||
if (Math.random() < .01 && !viewerForDoc(this.ampdoc_).hasBeenVisible()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this will also trigger for legitimate pre-render XHRs, e.g. same-origin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's intended for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the purpose of reporting those? Won't it just muddy the signal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To follow up on this from above. I definitely agree with @choumx - this signal will get super noisy and even with 1% error rate it would be overwhelming. Sorry for missing it at first. We can already define which requests are "good" or "bad" . The only requests we need to report here are URLs with url.origin != window.location.origin
. Same-origin requests are explicitly allowed and have 0 risk of any kind associated with them since we just pulled the document itself from that origin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eventually, I believe, we'll use this condition and throw an actual error ==
deny the request in prerender with different origin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/service/xhr-impl.js
Outdated
@@ -106,6 +113,15 @@ export class Xhr { | |||
* @private | |||
*/ | |||
fetch_(input, init) { | |||
if (this.ampdoc_) { | |||
// TODO(@jridgewell, #9048): We can alternatively _always_ wait on | |||
// #whenFirstVisible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be nice as a conservative mitigation technique. As is, this PR won't prevent the next privacy issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, just reports it. I think once we understand all the valid use cases, we can move to this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We definitely can't always wait on first-visible, not w/o additional rules. We can try to define these rules right now - it's generally possible. But starting with reporting is likely better. I'll make a comment below.
d8fddf2
to
9b89509
Compare
src/service/xhr-impl.js
Outdated
@@ -154,7 +171,7 @@ export class Xhr { | |||
} | |||
// For some same origin requests, add AMP-Same-Origin: true header to allow | |||
// publishers to validate that this request came from their own origin. | |||
const currentOrigin = parseUrl(this.win.location.href).origin; | |||
const currentOrigin = this.win.location.origin; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Safe to use? MDN is unclear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WTF.
0164f2a
to
bf2d429
Compare
Ping. |
src/service/xhr-impl.js
Outdated
return false; | ||
}, | ||
}; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks weird. Can we do without?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'll complain that it can't find the service.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hidden side effect would cause subsequent ampdoc registrations to silently fail. Perhaps we can either allow injection of the ampdoc instance or just don't call that code in test mode.
The rest LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to resolve this. I'm ok with not calling this code in the test code as well. Otherwise this will be asking for a trouble.
Ditto: otherwise LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we have to, we can even test for the presence of the service and if
it out if not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/service/xhr-impl.js
Outdated
return false; | ||
}, | ||
}; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hidden side effect would cause subsequent ampdoc registrations to silently fail. Perhaps we can either allow injection of the ampdoc instance or just don't call that code in test mode.
The rest LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but one quick confirmation: this won't have any issues with our workers, will it?
Workers? |
01e978b
to
d227ba0
Compare
Web workers or service workers? Do we reuse xhr-impl for any of those? |
d227ba0
to
370f95c
Compare
Oh no, they don't use any of this. |
Well, the web worker is fetched via |
Fixes #9048.