Report when XHR are issued before viewer is visible#9350
Report when XHR are issued before viewer is visible#9350jridgewell merged 9 commits intoampproject:masterfrom
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.
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.
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.
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.
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' + |
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.
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.
Isn't this already sampled by the error reporting server?
There was a problem hiding this comment.
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.
src/service/xhr-impl.js
Outdated
| this.win = win; | ||
|
|
||
| const ampdocService = ampdocServiceFor(win); | ||
| this.ampdoc_ = ampdocService.isSingleDoc() ? |
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.
Seems like this will also trigger for legitimate pre-render XHRs, e.g. same-origin.
There was a problem hiding this comment.
That's intended for now.
There was a problem hiding this comment.
What's the purpose of reporting those? Won't it just muddy the signal?
There was a problem hiding this comment.
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.
Eventually, I believe, we'll use this condition and throw an actual error == deny the request in prerender with different origin.
src/service/xhr-impl.js
Outdated
| fetch_(input, init) { | ||
| if (this.ampdoc_) { | ||
| // TODO(@jridgewell, #9048): We can alternatively _always_ wait on | ||
| // #whenFirstVisible. |
There was a problem hiding this comment.
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.
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.
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
| // 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; |
0164f2a to
bf2d429
Compare
|
Ping. |
src/service/xhr-impl.js
Outdated
| return false; | ||
| }, | ||
| }; | ||
| }); |
There was a problem hiding this comment.
This looks weird. Can we do without?
There was a problem hiding this comment.
It'll complain that it can't find the service.
There was a problem hiding this comment.
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.
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.
If we have to, we can even test for the presence of the service and if it out if not.
src/service/xhr-impl.js
Outdated
| return false; | ||
| }, | ||
| }; | ||
| }); |
There was a problem hiding this comment.
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.
dvoytenko
left a comment
There was a problem hiding this comment.
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.