Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upNotify embedder when history changes #15794
Conversation
highfive
commented
Mar 2, 2017
|
Heads up! This PR modifies the following files:
|
highfive
commented
Mar 2, 2017
|
@emilio review ping |
|
Looks sensible, but I wouldn't think |
| @@ -105,7 +103,7 @@ pub enum Msg { | |||
| /// A favicon was detected | |||
| NewFavicon(ServoUrl), | |||
| /// <head> tag finished parsing | |||
This comment has been minimized.
This comment has been minimized.
|
We want the final URL, after all the redirections, and once the pipeline is not pending anymore. |
|
Doc added. |
|
@asajeffrey r? |
|
Do we want the embedder to be notified about intermediate URLs when doing redirection? Or just the final URL? |
That's a good question. Naively I would say no. Just the final URL. This will be used to update the urlbar in the user interface. How does it work in Firefox? Does the urlbar get updated for each redirection? |
| // FIXME(https://github.com/rust-lang/rust/issues/23338) | ||
| let mut frame_url = servoframe.url.borrow_mut(); | ||
| *frame_url = url.into_string(); | ||
| let utf16_chars: Vec<u16> = frame_url.encode_utf16().collect(); |
This comment has been minimized.
This comment has been minimized.
| let frame = browser.get_main_frame(); | ||
| let servoframe = frame.downcast(); | ||
| // FIXME(https://github.com/rust-lang/rust/issues/23338) | ||
| let mut frame_url = servoframe.url.borrow_mut(); |
This comment has been minimized.
This comment has been minimized.
|
I think most browsers just report the final URL, but I can certainly imagine some embedders wanting to display the intermediates. If we give them all the URLs, they can choose whether or not to display them. |
|
Ok. I can report all the urls. The embedder can assume the latest received url when getting HeadParsed is the final url. |
|
Sounds good. |
|
I think gecko and others don't report intermediates partly because they all have some protection against endless redirects and that would not make much sense to notify of all the changes. |
Not sure it would hurt to report the url anyway? |
|
I've been thinking a bit more about this. The reason why I need the url is to update the urlbar. All of that doesn't make much sense because the history can change without load events (it actually change after load_start and before load_end) and url can change without head_parsed. So I would rather have this:
With: struct HistoryEntries {
current: u32,
entries: Vec<HistoryEntry>,
}
struct HistoryEntry {
url: ServoUrl,
title: Option<String>,
favicon_url: Option<ServoUrl>
}I don't see any benefit of being notified every time the pipeline resolve urls. And also, while it's resolving urls, the pipeline is still pending, so there is nothing the embedder can do with this information. What would be more appropriate is to do what other engines do and have a way to be notified of any HTTP activity. Something like this: https://developer.chrome.com/extensions/webRequest |
|
I'll go ahead and implement this proposal. @asajeffrey @fabricedesre let me know if any of this doesn't make sense to you. |
25a5372
to
aac02df
|
@asajeffrey I've updated the PR. I'd appreciate some feedback. |
| /// The load of a page has completed | ||
| LoadComplete, | ||
| /// The history of a top level browser has changed. | ||
| HistoryChanged(HistoryEntries), |
This comment has been minimized.
This comment has been minimized.
asajeffrey
Mar 20, 2017
Member
Is this sending the joint session history?
Sending the whole history every time seems a bit wasteful, most of it won't have changed.
| @@ -2141,6 +2135,35 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> | |||
| } | |||
| } | |||
|
|
|||
| fn notify_history_changed(&self, frame_id: FrameId) { | |||
| if let Some(frame) = self.frames.get(&frame_id) { | |||
This comment has been minimized.
This comment has been minimized.
asajeffrey
Mar 20, 2017
Member
Can we not use one of the existing iterators for this? This appears to be only sending the session history for the frame that traversed, not the joint session history.
|
|
||
| let current = history.current; | ||
| let can_go_back = current > 0; | ||
| let can_go_forward = current < history.entries.len() - 1; |
This comment has been minimized.
This comment has been minimized.
asajeffrey
Mar 20, 2017
Member
These are the forward/back settings for the session history of the frame that just navigated, not the joint session history.
|
I've updated the PR and now send the whole joint session.
It's easier for the embedder though as we don't have to maintain a state and duplicate the navigation logic. |
|
|
|
@paulrouget should we merge this as-is, or are there any more changes you're wanting to implement? |
I need to do some further testing. Your previous comment made me realize that I might have not correctly exposed the flatten history. I think this approach will show the load_data of an iframe when the embedder need the load_data of its parent. Scenario:
The history is:
We want an array of If I'm not mistaken, my PR will include the load_data of the iframe. I'll test that later today. |
|
In the example, shouldn't the session history include the frame id, so it would be:
child frames can traverse independently from their parent, e.g going forward from 1.html will traverse the child, but not the parent. cc @cbrewster |
|
I believe you would end up with something like:
Its important to note that the current entry is actually a group of current entries. Each frame has its own current entry, so for the child 2.html is the current entry which means it will not be present with this implementation. I am not sure whether the embedder would care about that or not. |
|
The event and its payload are used to update the current url, to know if the user can go back/forward, and to display a list of entries where he can jump to (long press on the back button in Firefox). So we need to have an array of LoadData with an index of the current position in the history. When the user navigates within iframes, the user can click back and the iframe will go back. But the LoadData we want are not the LoadData of the iframe being navigated, but of the parent document. Back to the above scenario:
When the user long press the back button, we want to show:
We don't want to show 2.html or 1.html in the drop down menu. Does it make sense? The current PR is wrong because it collects the LoadData of the inner documents. After getting joint_session_past and joint_session_furture, I don't know how to get the LoadData of the parent. Can you help? |
|
I think you're wanting the frame id, and the frame tree, so you can present the url, etc. for the top-level frame, not the child frame. |
|
I've updated the PR.
We can't go "up" the frame tree to get the proper FrameState in this case. Reaching the parent pipeline and then getting the frame_id won't work as it will give me a frame when I need a framestate. Instead, when the FrameState is for an iframe, I use the previous FrameState in the history to find the relevant LoadData. See the comment in the PR. I've tested this locally, and it appears to work as expected. |
|
Back from vacation, sorry about the delay. Mostly this looks fine, just a few niggles. |
| }; | ||
|
|
||
| let mut entries: Vec<LoadData> = self.joint_session_past(top_level_frame_id) | ||
| .map(&keep_load_data_if_top_frame) |
This comment has been minimized.
This comment has been minimized.
asajeffrey
Apr 17, 2017
Member
Do we need this &? It makes the function call a dynamic rather than static dispatch.
This comment has been minimized.
This comment has been minimized.
paulrouget
Apr 17, 2017
Author
Contributor
This callback is called twice. Moved in the first map. How can I use it twice then?
Also, in general, I'd be interested to understand why it's bad to use &.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Apr 17, 2017
Member
Oh, perhaps you're okay in this case, since it's a pointer to a closure, so Rust will probably generate a new type for it. In the case of a declared fn foo, .map(&foo) will perform dynamic dispatch, since &foo has type &fn(S) -> T, which blocks other code optimizations.
| entries.push(current_load_data.clone()); | ||
|
|
||
| let mut future_entries = self.joint_session_future(top_level_frame_id) | ||
| .map(&keep_load_data_if_top_frame) |
This comment has been minimized.
This comment has been minimized.
| .scan(current_load_data.clone(), &resolve_load_data) | ||
| .collect(); | ||
|
|
||
| entries.append(&mut future_entries); |
This comment has been minimized.
This comment has been minimized.
asajeffrey
Apr 17, 2017
Member
Do we need to collect then append? Wouldn't it be easier to chain the iterators, then do one collect?
This comment has been minimized.
This comment has been minimized.
paulrouget
Apr 17, 2017
Author
Contributor
Maybe. How do I append the current entry (using chain(once())?) and also get the size of the past entries (to get the current index)?
This comment has been minimized.
This comment has been minimized.
asajeffrey
Apr 17, 2017
Member
Oh rats, you need the length of the session past? Oops, forgot about that. You can still avold doing the unnecessary collect by using entries.extend with an iterator.
|
Updated the PR. I didn't change I used |
|
@bors-servo r+ |
|
|
Notify embedder when history changes `WindowMethods::set_page_url` is only called when the embedder set the URL. It is not called when the page url is updated. I believe that instead we should just pass the URL to `head_parsed`. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #15439 #15643 and #15642 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because I'm not sure how to test that <!-- 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/15794) <!-- Reviewable:end -->
|
|
paulrouget commentedMar 2, 2017
•
edited
WindowMethods::set_page_urlis only called when the embedder set the URL. It is not called when the page url is updated. I believe that instead we should just pass the URL tohead_parsed../mach build -ddoes not report any errors./mach test-tidydoes not report any errorsThis change is