return delegate_ ? delegate_->EnterPictureInPicture(this)this is subtle. this has side-effects such as notifying the picture in picture window manager that pip has started. there can only be one pip window at a time, and since immersive is built on pip, i suspect that's the same limitation. i don't know for sure which of these things we want to trigger in immersive, but i'd not be surprised if 'all of them' were reasonable.
i'm really not sure though. just that it's subtle and needs some thought.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
return delegate_ ? delegate_->EnterPictureInPicture(this)this is subtle. this has side-effects such as notifying the picture in picture window manager that pip has started. there can only be one pip window at a time, and since immersive is built on pip, i suspect that's the same limitation. i don't know for sure which of these things we want to trigger in immersive, but i'd not be surprised if 'all of them' were reasonable.
i'm really not sure though. just that it's subtle and needs some thought.
This is where I finally implement it [1]. It will call the same `PictureInPictureWindowManager::GetInstance()->EnterVideoPictureInPicture(web_contents)` as the `EnterPictureInPicture`. The only difference is that it will check for the `IsImmersivePlaybackEnabled` before proceeding. In this case the PiP can stay disabled (or unsupported) and Immersive can still be enabled.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
void RequestImmersivePlayback(RequestImmersivePlaybackCallback) final;Oleh Desiatyrikov (xWF)this feels like it's simply an implementation convenience. it could be moved to another xr-specific service if there is one available. this is especially true once the xr options it returns are handed back to `StartSession()`.
it's also okay to keep it here, since it's convenient and doesn't really hurt anything. but, in case you already have such a service where it would fit better, the `StartSession()` changes now decouple it entirely from the pip service if you want.
Done
void SetIsImmersive(bool is_immersive) override;Oleh Desiatyrikov (xWF)i don;t follow why this isn't a parameter to StartSession(). doesn't the renderer know at that point if it's requesting immersive or not?
Frank LiberatoI was trying to be as less intrusive as possible only adding the necessary things and not changing the existing interface. If you suggest moving this to the constructor - I have no objections. I'm also fine with using
`bool IsImmersive() const { return immersive_options.has_value(); }`.
Please let me know which way you prefer.
Oleh Desiatyrikov (xWF)`StartSession()` should get the parameters. otherwise, one could end up in the position where the immersive flags are set, but nobody ever calls StartSession for whatever reason. this will break something, possibly the next call to StartSession().
to be honest, there is a lot of information in the window controller that should be in the session - existing stuff, i mean, not just these new xr flags. but conceptually, the session is roughly "this instance of the pip window" while the controller is... i'm not sure what.
storing the xr flags on the window controller is right (or at least consistent with what we're already, incorrectly, doing), to be clear.
Done
is_immersive_ = false;
immersive_stereo_mode_ = blink::mojom::ImmersiveStereoMode::kMono;
immersive_projection_type_ = blink::mojom::ImmersiveEntityShape::kQuad;Oleh Desiatyrikov (xWF)if these have to be held here, i suggest something like:
```
using ImmersiveOptions =- struct {mode, type};
std::optional<ImmersiveOptions> immersive_options_;
bool IsImmersive() const { return immersive_options.has_value(); }
```
Oleh Desiatyrikov (xWF)Okay, no problem.
Done
RequestImmersivePlayback() => (ImmersivePlaybackResult result);Oleh Desiatyrikov (xWF)unsure if this needs to be here. seems only tangentially related.
Oleh Desiatyrikov (xWF)I was also thinking about moving this to a separate interface. I decided to keep it here for now and ask you opinion.
If it's okay to keep it here for now, I'd prefer to leave it as is. Currently, there is no AndroidXR related service where I could place it.
Oleh Desiatyrikov (xWF)I see a bunch of failed targets. Working to resolve them.
Done
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
return delegate_ ? delegate_->EnterPictureInPicture(this)Oleh Desiatyrikov (xWF)this is subtle. this has side-effects such as notifying the picture in picture window manager that pip has started. there can only be one pip window at a time, and since immersive is built on pip, i suspect that's the same limitation. i don't know for sure which of these things we want to trigger in immersive, but i'd not be surprised if 'all of them' were reasonable.
i'm really not sure though. just that it's subtle and needs some thought.
This is where I finally implement it [1]. It will call the same `PictureInPictureWindowManager::GetInstance()->EnterVideoPictureInPicture(web_contents)` as the `EnterPictureInPicture`. The only difference is that it will check for the `IsImmersivePlaybackEnabled` before proceeding. In this case the PiP can stay disabled (or unsupported) and Immersive can still be enabled.
not sure i understand what you mean - i think i'm not getting why picture in picture has to be any different at this level than immersive mode. other than having some extra ImmersiveMode options that the controller knows about and instantiating a different overlay window type, what's the difference?
RequestImmersivePlayback() => (ImmersivePlaybackResult result);Oleh Desiatyrikov (xWF)unsure if this needs to be here. seems only tangentially related.
Oleh Desiatyrikov (xWF)I was also thinking about moving this to a separate interface. I decided to keep it here for now and ask you opinion.
If it's okay to keep it here for now, I'd prefer to leave it as is. Currently, there is no AndroidXR related service where I could place it.
sure just add a comment to that effect. else future me will wonder why it's here.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
return delegate_ ? delegate_->EnterPictureInPicture(this)Oleh Desiatyrikov (xWF)this is subtle. this has side-effects such as notifying the picture in picture window manager that pip has started. there can only be one pip window at a time, and since immersive is built on pip, i suspect that's the same limitation. i don't know for sure which of these things we want to trigger in immersive, but i'd not be surprised if 'all of them' were reasonable.
i'm really not sure though. just that it's subtle and needs some thought.
Frank LiberatoThis is where I finally implement it [1]. It will call the same `PictureInPictureWindowManager::GetInstance()->EnterVideoPictureInPicture(web_contents)` as the `EnterPictureInPicture`. The only difference is that it will check for the `IsImmersivePlaybackEnabled` before proceeding. In this case the PiP can stay disabled (or unsupported) and Immersive can still be enabled.
not sure i understand what you mean - i think i'm not getting why picture in picture has to be any different at this level than immersive mode. other than having some extra ImmersiveMode options that the controller knows about and instantiating a different overlay window type, what's the difference?
When `WebContentsImpl::EnterPictureInPicture` calls `delegate_->EnterPictureInPicture(this)` we are handling this call at `TabWebContentsDelegateAndroid::EnterPictureInPicture`. There we check for `IsPictureInPictureEnabled()` [1].
In our case, `IsPictureInPictureEnabled()` returns false since PiP is disabled on Android XR. So, to be able to proceed with immersive XR session even though the PiP is disabled, I've introduced a separate `EnterImmersivePlayback/IsImmersivePlaybackEnabled` methods.
Otherwise, I could keep the same `EnterPictureInPicture` method and add `bool is_immersive` as a parameter.
RequestImmersivePlayback() => (ImmersivePlaybackResult result);Oleh Desiatyrikov (xWF)unsure if this needs to be here. seems only tangentially related.
Oleh Desiatyrikov (xWF)I was also thinking about moving this to a separate interface. I decided to keep it here for now and ask you opinion.
Frank LiberatoIf it's okay to keep it here for now, I'd prefer to leave it as is. Currently, there is no AndroidXR related service where I could place it.
sure just add a comment to that effect. else future me will wonder why it's here.
Done
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
void VideoPictureInPictureWindowControllerImpl::RequestImmersivePlayback(Oleh Desiatyrikov (xWF)i'm confused about the overall flow. is this the thing that asks the user for permission?
Oleh Desiatyrikov (xWF)Yes, correct. We need to ask user confirmation for immersive playback. Here is a [document](go/chromxr-immersive-playback-pip) with all the details.
Done
+cc:steimel@ for opinions.
thanks
-fl
return delegate_ ? delegate_->EnterPictureInPicture(this)Oleh Desiatyrikov (xWF)this is subtle. this has side-effects such as notifying the picture in picture window manager that pip has started. there can only be one pip window at a time, and since immersive is built on pip, i suspect that's the same limitation. i don't know for sure which of these things we want to trigger in immersive, but i'd not be surprised if 'all of them' were reasonable.
i'm really not sure though. just that it's subtle and needs some thought.
Frank LiberatoThis is where I finally implement it [1]. It will call the same `PictureInPictureWindowManager::GetInstance()->EnterVideoPictureInPicture(web_contents)` as the `EnterPictureInPicture`. The only difference is that it will check for the `IsImmersivePlaybackEnabled` before proceeding. In this case the PiP can stay disabled (or unsupported) and Immersive can still be enabled.
Oleh Desiatyrikov (xWF)not sure i understand what you mean - i think i'm not getting why picture in picture has to be any different at this level than immersive mode. other than having some extra ImmersiveMode options that the controller knows about and instantiating a different overlay window type, what's the difference?
When `WebContentsImpl::EnterPictureInPicture` calls `delegate_->EnterPictureInPicture(this)` we are handling this call at `TabWebContentsDelegateAndroid::EnterPictureInPicture`. There we check for `IsPictureInPictureEnabled()` [1].
In our case, `IsPictureInPictureEnabled()` returns false since PiP is disabled on Android XR. So, to be able to proceed with immersive XR session even though the PiP is disabled, I've introduced a separate `EnterImmersivePlayback/IsImmersivePlaybackEnabled` methods.
Otherwise, I could keep the same `EnterPictureInPicture` method and add `bool is_immersive` as a parameter.
ah i see. definitely trying to merge the code paths a bit i think is a good idea. i'm picturing "immersive mode" as another type of pip - it's basically "pip with a different window type" but still, for practical purposes, just pip.
i'm not a big fan of `WebContentsImpl::EnterPictureInPicture(bool is_immersive)` though. maybe we should send in an VideoPictureInPictureSessionOptions struct into StartSession and also just pass that along to EnterPictureInPicture? that might be a lot cleaner. @ste...@chromium.org - WDYT?
TL;DR: PipService::StartSession => WebContentsImpl::Enter(Video)PictureInPicture(void) => WebContentsDelegate::EnterPictureInPIcture needs to know a boolean.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
return delegate_ ? delegate_->EnterPictureInPicture(this)Oleh Desiatyrikov (xWF)this is subtle. this has side-effects such as notifying the picture in picture window manager that pip has started. there can only be one pip window at a time, and since immersive is built on pip, i suspect that's the same limitation. i don't know for sure which of these things we want to trigger in immersive, but i'd not be surprised if 'all of them' were reasonable.
i'm really not sure though. just that it's subtle and needs some thought.
Frank LiberatoThis is where I finally implement it [1]. It will call the same `PictureInPictureWindowManager::GetInstance()->EnterVideoPictureInPicture(web_contents)` as the `EnterPictureInPicture`. The only difference is that it will check for the `IsImmersivePlaybackEnabled` before proceeding. In this case the PiP can stay disabled (or unsupported) and Immersive can still be enabled.
Oleh Desiatyrikov (xWF)not sure i understand what you mean - i think i'm not getting why picture in picture has to be any different at this level than immersive mode. other than having some extra ImmersiveMode options that the controller knows about and instantiating a different overlay window type, what's the difference?
Frank LiberatoWhen `WebContentsImpl::EnterPictureInPicture` calls `delegate_->EnterPictureInPicture(this)` we are handling this call at `TabWebContentsDelegateAndroid::EnterPictureInPicture`. There we check for `IsPictureInPictureEnabled()` [1].
In our case, `IsPictureInPictureEnabled()` returns false since PiP is disabled on Android XR. So, to be able to proceed with immersive XR session even though the PiP is disabled, I've introduced a separate `EnterImmersivePlayback/IsImmersivePlaybackEnabled` methods.
Otherwise, I could keep the same `EnterPictureInPicture` method and add `bool is_immersive` as a parameter.
ah i see. definitely trying to merge the code paths a bit i think is a good idea. i'm picturing "immersive mode" as another type of pip - it's basically "pip with a different window type" but still, for practical purposes, just pip.
i'm not a big fan of `WebContentsImpl::EnterPictureInPicture(bool is_immersive)` though. maybe we should send in an VideoPictureInPictureSessionOptions struct into StartSession and also just pass that along to EnterPictureInPicture? that might be a lot cleaner. @ste...@chromium.org - WDYT?
TL;DR: PipService::StartSession => WebContentsImpl::Enter(Video)PictureInPicture(void) => WebContentsDelegate::EnterPictureInPIcture needs to know a boolean.
How about we check for `IsPictureInPictureEnabled/IsImmersivePlaybackEnabled` in `VideoPictureInPictureWindowControllerImpl` instead of checking it in `TabWebContentsDelegateAndroid`. This will make the code neater and will remove the `EnterImmersivePlayback` path entirely.
```
PictureInPictureResult result = PictureInPictureResult::kNotSupported;
WebContentsDelegate* delegate = web_contents()->GetDelegate();
if (delegate && (IsImmersive() ? delegate->IsImmersivePlaybackEnabled()
: delegate->IsPictureInPictureEnabled())) {
result = GetWebContentsImpl()->EnterPictureInPicture();
}
```
The check was added to the `TabWebContentsDelegateAndroid` just recently.
[1] https://chromium-review.googlesource.com/c/chromium/src/+/7565223
result = GetWebContentsImpl()->EnterImmersivePlayback();Does this need to do any sort of check that we've gone through the `RequestImmersivePlaybackConfirmation()` process?
if (!window_) {IIUC this probably needs to also create a new window if the current `window_` is of the other type (i.e. we're going from pip to immersive or vice versa)
if (!window_) {IIUC this probably needs to also create a new window if the current `window_` is of the other type (i.e. we're going from pip to immersive or vice versa)
that's a very good point.
result = GetWebContentsImpl()->EnterImmersivePlayback();Does this need to do any sort of check that we've gone through the `RequestImmersivePlaybackConfirmation()` process?
Not necessary. We might convert it to the WebAPI afterwards to let websites to control it.
if (!window_) {Frank LiberatoIIUC this probably needs to also create a new window if the current `window_` is of the other type (i.e. we're going from pip to immersive or vice versa)
that's a very good point.
This path is currently unreachable. If it's okay, I would prefer to add a TODO and address it once everything else is done.
return delegate_ ? delegate_->EnterPictureInPicture(this)| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
if (!window_) {Frank LiberatoIIUC this probably needs to also create a new window if the current `window_` is of the other type (i.e. we're going from pip to immersive or vice versa)
Oleh Desiatyrikov (xWF)that's a very good point.
This path is currently unreachable. If it's okay, I would prefer to add a TODO and address it once everything else is done.
is it unreachable via any combination of pip and immersive? if so, please convert this to a CHECK. i didn't think this was unreachable though.
@libe...@chromium.org is there anything else should I look at?
if (!window_) {Frank LiberatoIIUC this probably needs to also create a new window if the current `window_` is of the other type (i.e. we're going from pip to immersive or vice versa)
Oleh Desiatyrikov (xWF)that's a very good point.
Frank LiberatoThis path is currently unreachable. If it's okay, I would prefer to add a TODO and address it once everything else is done.
is it unreachable via any combination of pip and immersive? if so, please convert this to a CHECK. i didn't think this was unreachable though.
Immersive mode is currently only supported on Android XR, where Picture-in-Picture is disabled.
Added a CHECK with a comment.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
some other minor nits. please also add some comments around the immersive checks, since likely the folks who maintain this code have no idea what immersive mode is or why it's mixed in with pip.
-fl
blink::mojom::ImmersiveOptionsPtr options) {}NOTREACHED
window_->SetImmersiveVideoOptions(immersive_options_.Clone());not sure if you need to clone this or not.
virtual bool IsImmersivePlaybackEnabled();const?
virtual bool IsPictureInPictureEnabled();const?
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
blink::mojom::ImmersiveOptionsPtr options) {}Oleh Desiatyrikov (xWF)NOTREACHED
Done
window_->SetImmersiveVideoOptions(immersive_options_.Clone());not sure if you need to clone this or not.
It was required since I was storing the immersive options locally to do the `IsImmersive` check. However, this can be easily simplified by storing the `is_immersive_` bool instead.
virtual bool IsImmersivePlaybackEnabled();Oleh Desiatyrikov (xWF)const?
Done
virtual bool IsPictureInPictureEnabled();Oleh Desiatyrikov (xWF)const?
Done
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Looks good in general % test question
#define MAYBE_EnterImmersivePlayback DISABLED_EnterImmersivePlaybackIt doesn't seem good that this new test is disabled on the only platform we care about it on. Is there something about Android test infra that prevents this from working properly?
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
#define MAYBE_EnterImmersivePlayback DISABLED_EnterImmersivePlaybackIt doesn't seem good that this new test is disabled on the only platform we care about it on. Is there something about Android test infra that prevents this from working properly?
Yes, I agree. I didn't spend much time trying to figure out the actual reason why the PiP is flaky on Android. My reasoning is that it is a unit test that tests the APIs and not the platform specific implementation, so it should be sufficient to run it at least on one platform. I'll try to see why the PiP test is failing on Android in a first place but this can be done as a separate task.
#define MAYBE_EnterImmersivePlayback DISABLED_EnterImmersivePlaybackOleh Desiatyrikov (xWF)It doesn't seem good that this new test is disabled on the only platform we care about it on. Is there something about Android test infra that prevents this from working properly?
Yes, I agree. I didn't spend much time trying to figure out the actual reason why the PiP is flaky on Android. My reasoning is that it is a unit test that tests the APIs and not the platform specific implementation, so it should be sufficient to run it at least on one platform. I'll try to see why the PiP test is failing on Android in a first place but this can be done as a separate task.
Furthermore, I do not have access to the https://crbug.com/970866.
#define MAYBE_EnterImmersivePlayback DISABLED_EnterImmersivePlaybackOleh Desiatyrikov (xWF)It doesn't seem good that this new test is disabled on the only platform we care about it on. Is there something about Android test infra that prevents this from working properly?
Oleh Desiatyrikov (xWF)Yes, I agree. I didn't spend much time trying to figure out the actual reason why the PiP is flaky on Android. My reasoning is that it is a unit test that tests the APIs and not the platform specific implementation, so it should be sufficient to run it at least on one platform. I'll try to see why the PiP test is failing on Android in a first place but this can be done as a separate task.
Furthermore, I do not have access to the https://crbug.com/970866.
i cc'd you on it, so you should have access now. TL;DR: it was from 2019 on kitkat, which was old in 2019. it's entirely possible these tests work now.
#define MAYBE_EnterImmersivePlayback DISABLED_EnterImmersivePlaybackOleh Desiatyrikov (xWF)It doesn't seem good that this new test is disabled on the only platform we care about it on. Is there something about Android test infra that prevents this from working properly?
Oleh Desiatyrikov (xWF)Yes, I agree. I didn't spend much time trying to figure out the actual reason why the PiP is flaky on Android. My reasoning is that it is a unit test that tests the APIs and not the platform specific implementation, so it should be sufficient to run it at least on one platform. I'll try to see why the PiP test is failing on Android in a first place but this can be done as a separate task.
Frank LiberatoFurthermore, I do not have access to the https://crbug.com/970866.
i cc'd you on it, so you should have access now. TL;DR: it was from 2019 on kitkat, which was old in 2019. it's entirely possible these tests work now.
It looks you are right. I run both PiP and Immersive tests locally on my Android device for 20 times in a row and they all passed. I also run a few android try bots and they all passed too. Let's assume these are not flaky anymore.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +1 |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |