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

Remove redundant windowproxy transplanting #23967

Merged
merged 1 commit into from Aug 14, 2019

Conversation

gterzian
Copy link
Member

@gterzian gterzian commented Aug 14, 2019


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • These changes fix #___ (GitHub issue number if applicable)
  • There are tests for these changes OR
  • These changes do not require tests because ___

This change is Reviewable

@highfive
Copy link

Heads up! This PR modifies the following files:

  • @asajeffrey: components/script/script_thread.rs, components/script/dom/window.rs
  • @KiChjang: components/script/script_thread.rs, components/script/dom/window.rs

@highfive highfive added the S-awaiting-review There is new code that needs to be reviewed. label Aug 14, 2019
@highfive
Copy link

warning Warning warning

  • These commits modify script code, but no tests are modified. Please consider adding a test!

@gterzian
Copy link
Member Author

gterzian commented Aug 14, 2019

@asajeffrey The call to self.window_proxy().set_currently_active(self); inside window.resume seems redundant in two cases:

  1. When a new page is loaded, and we create a new windowproxy. See
    window.resume();
  2. When a new page is loaded, and we re-use a windowproxy, since we will already do the transplant at
    window_proxy.set_currently_active(&*window);

So I think the call is only necessary when we set the activity of a document to full-active, and there is no in progress load for that document(essentially I guess that's when re re-use a doc in the bfcache, and just set it to fully active).

In that case, the call is done inside document.set_activity, via a call to window.resume. I think it's probably clearer to do it as I've changed it here, and to remove the call inside window.resume, since most cases when we resume a window we do not need to transplant the windowproxy.

@asajeffrey
Copy link
Member

This seems like a dangerous way to fix the issue, calling resume should make the document active. I'm concerned that with this change, we'd get weird race conditions about things like nested documents A with iframe B with iframe C, if C is resumed then B is resumed, since this should result in C being fully active but I'm not sure it will with this revision.

Is the case you're worried about one where we're transplanting a window proxy even though it's already in the right realm? If so, can we deal with this by adding a check to set_window to exit early if the proxy is already in the same realm as the window?

@asajeffrey asajeffrey added S-awaiting-answer Someone asked a question that requires an answer. and removed S-awaiting-review There is new code that needs to be reviewed. labels Aug 14, 2019
@gterzian
Copy link
Member Author

gterzian commented Aug 14, 2019

Is the case you're worried about one where we're transplanting a window proxy even though it's already in the right realm?

What I've noticed is that when we load a new url in an existing browsing-context, we hit the branch at

window_proxy.set_currently_active(&*window);

Then later we hit it again at

self.window_proxy().set_currently_active(self);

So we simply do the transplant twice, as far as I can tell.

In the other cases, we do the transplant only once as part of window.resume, and I still wonder whether it's not redundant, since in those other cases we actually create a windowproxy using the window, as in WindowProxy::new(&window, ..). Do we then still need to do a set_window after that?


The only other place in the code I could find that uses window.resume is at

self.window().resume();
,

which is called from

document.set_activity(activity);

That case seems necessary, since it deals with an existing window that becomes fully-active inside an existing browsing context.

So essentially that's the only place I added an explicit call to set_currently_active, as it seems necessary, as opposed to doing it in each call to resume, in which case it's often redundant.


can we deal with this by adding a check to set_window to exit early if the proxy is already in the same realm as the window?

Could we catch the redundancies inside

pub fn set_currently_active(&self, window: &Window) {

by checking the pipeline id of the window against self.currently_active? Yes we could because in those cases they're already the same, and then I assume the call to set_window is redundant?

It might still be better to only call set_currently_active when it's necessary, as opposed to making it idempotent?


I'm concerned that with this change, we'd get weird race conditions about things like nested documents A with iframe B with iframe C, if C is resumed then B is resumed, since this should result in C being fully active but I'm not sure it will with this revision.

There might be something I'm missing, and from reading the code it seems the above mentioned cases provide an exhaustive list of when set_window is called, so if the redundancies are correctly identified it seems we should not get weird side-effects.

Iframes are dealt as part of

let iframe = parent_info.and_then(|parent_id| {

and it seems that they get their own newly created windowproxy each time, hence the subsequent call to set_window that happens as part of window.resume would seem redundant.

@asajeffrey
Copy link
Member

I guess I'm worried that this change removes the transplanting from resume but not suspend, so they're not inverses. I see what you mean though, it is odd that local_window_proxy has a side-effect of setting the active document.

@gterzian
Copy link
Member Author

gterzian commented Aug 14, 2019

Ok, should I simply check the pipeline of the window against the currently active one, and return early, inside

pub fn set_currently_active(&self, window: &Window) {

That way we keep the current structure, and we just make "redundant" calls idempotent?

If self.currently_active is already the same as the pipeline id of the window passed as an argument, we never have to actually call set_window, or is there something else going on at the JS level?

@gterzian
Copy link
Member Author

By the way, I was also surprised to see that a call to suspend always sets a DissimilarOriginWindow as the current window on the proxy...

See

let window = DissimilarOriginWindow::new(&*globalscope, self);

@asajeffrey
Copy link
Member

Yeah, that is odd. I think it's because if the replacement window is similar-origin, then the constellation will send another message activating it. But it does mean there's a transient state where it appears to be a dissimilar-origin window, possibly resulting in spurious security errors.

@highfive highfive added the S-awaiting-review There is new code that needs to be reviewed. label Aug 14, 2019
@gterzian
Copy link
Member Author

Ok, the latest commit provides a fix that doesn't change the overall code stucture, ready for another review @asajeffrey

Copy link
Member

@asajeffrey asajeffrey left a comment

Choose a reason for hiding this comment

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

A possible niggle about log levels, but otherwise LGTM.

let dest_pipeline_id = globalscope.pipeline_id();
if let Some(pipeline_id) = self.currently_active() {
if pipeline_id == dest_pipeline_id {
return warn!(
Copy link
Member

Choose a reason for hiding this comment

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

Make this a debug! rather than a warn!?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, done.

@asajeffrey
Copy link
Member

@bors-servo r+

@bors-servo
Copy link
Contributor

📌 Commit 9acf3f6 has been approved by asajeffrey

@highfive highfive removed S-awaiting-review There is new code that needs to be reviewed. S-awaiting-answer Someone asked a question that requires an answer. labels Aug 14, 2019
@highfive highfive added the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Aug 14, 2019
@bors-servo
Copy link
Contributor

⌛ Testing commit 9acf3f6 with merge 91469aa...

bors-servo pushed a commit that referenced this pull request Aug 14, 2019
Remove redundant windowproxy transplanting

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [ ] `./mach build -d` does not report any errors
- [ ] `./mach test-tidy` does not report any errors
- [ ] These changes fix #___ (GitHub issue number if applicable)

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23967)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

☀️ Test successful - linux-rel-css, linux-rel-wpt, status-taskcluster
Approved by: asajeffrey
Pushing 91469aa to master...

@bors-servo bors-servo merged commit 9acf3f6 into servo:master Aug 14, 2019
@highfive highfive removed the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Aug 14, 2019
@gterzian gterzian deleted the fix_double_transplant branch August 15, 2019 05:59
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

4 participants