Commit d1389bea authored by Ian Vollick's avatar Ian Vollick Committed by Commit Bot

[vr] Fade out 2d browsing elements when showing modal dialogs

With this CL, I change how the visibility of modal dialogs and the
related visibility of 2d browsing scene elements are managed.

I have also added two elements in the ancestor chain for the
audio permission prompt: a shadow and a full screen hit target
(similar to the exit prompt backplane).

Bug: 768512
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Ia5dcbe865fb8d92e90538039d9dfaa4679573dac
Reviewed-on: https://chromium-review.googlesource.com/774908
Commit-Queue: Ian Vollick <vollick@chromium.org>
Reviewed-by: default avatarYash Malik <ymalik@chromium.org>
Reviewed-by: default avatarBiao She <bshe@chromium.org>
Reviewed-by: default avatarAmirhossein Simjour <asimjour@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517298}
parent 5097c6d9
......@@ -116,6 +116,8 @@ static_library("vr_common") {
"gltf_parser.h",
"macros.h",
"model/controller_model.h",
"model/modal_prompt_type.cc",
"model/modal_prompt_type.h",
"model/model.cc",
"model/model.h",
"model/omnibox_suggestions.cc",
......@@ -250,6 +252,7 @@ test("vr_common_unittests") {
"ui_renderer_unittest.cc",
"ui_scene_manager_unittest.cc",
"ui_scene_unittest.cc",
"ui_unittest.cc",
"vr_gl_util_unittest.cc",
]
......
......@@ -24,6 +24,7 @@ namespace vr {
class ContentInputForwarder {
public:
virtual ~ContentInputForwarder() {}
virtual void ForwardEvent(std::unique_ptr<blink::WebInputEvent> event,
int content_id) = 0;
};
......
......@@ -10,8 +10,8 @@
namespace vr {
ExitPrompt::ExitPrompt(int preferred_width,
const base::Callback<void()>& primary_button_callback,
const base::Callback<void()>& secondary_buttton_callback)
const ExitPrompt::Callback& primary_button_callback,
const ExitPrompt::Callback& secondary_buttton_callback)
: TexturedElement(preferred_width),
texture_(base::MakeUnique<ExitPromptTexture>()),
primary_button_callback_(primary_button_callback),
......@@ -50,9 +50,9 @@ void ExitPrompt::OnButtonDown(const gfx::PointF& position) {
void ExitPrompt::OnButtonUp(const gfx::PointF& position) {
if (primary_down_ && texture_->HitsPrimaryButton(position))
primary_button_callback_.Run();
primary_button_callback_.Run(reason_);
else if (secondary_down_ && texture_->HitsSecondaryButton(position))
secondary_buttton_callback_.Run();
secondary_buttton_callback_.Run(reason_);
primary_down_ = false;
secondary_down_ = false;
......
......@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "chrome/browser/vr/elements/textured_element.h"
#include "chrome/browser/vr/ui_unsupported_mode.h"
namespace vr {
......@@ -17,15 +18,18 @@ class ExitPromptTexture;
class ExitPrompt : public TexturedElement {
public:
typedef typename base::Callback<void(UiUnsupportedMode)> Callback;
ExitPrompt(int preferred_width,
const base::Callback<void()>& primary_button_callback,
const base::Callback<void()>& secondary_buttton_callback);
const Callback& primary_button_callback,
const Callback& secondary_buttton_callback);
~ExitPrompt() override;
void SetContentMessageId(int message_id);
void SetTextureForTesting(ExitPromptTexture* texture);
void set_reason(UiUnsupportedMode reason) { reason_ = reason; }
void OnHoverEnter(const gfx::PointF& position) override;
void OnHoverLeave() override;
void OnMove(const gfx::PointF& position) override;
......@@ -39,11 +43,12 @@ class ExitPrompt : public TexturedElement {
bool primary_down_ = false;
bool secondary_down_ = false;
UiUnsupportedMode reason_ = UiUnsupportedMode::kCount;
std::unique_ptr<ExitPromptTexture> texture_;
base::Callback<void()> primary_button_callback_;
base::Callback<void()> secondary_buttton_callback_;
Callback primary_button_callback_;
Callback secondary_buttton_callback_;
DISALLOW_COPY_AND_ASSIGN(ExitPrompt);
};
......
......@@ -45,8 +45,12 @@ class TestExitPrompt : public ExitPrompt {
bool secondary_button_pressed() const { return secondary_button_pressed_; }
private:
void OnPrimaryButtonPressed() { primary_button_pressed_ = true; }
void OnSecondaryButtonPressed() { secondary_button_pressed_ = true; }
void OnPrimaryButtonPressed(UiUnsupportedMode reason) {
primary_button_pressed_ = true;
}
void OnSecondaryButtonPressed(UiUnsupportedMode reason) {
secondary_button_pressed_ = true;
}
bool primary_button_pressed_ = false;
bool secondary_button_pressed_ = false;
......
......@@ -43,8 +43,10 @@ static const char* g_ui_element_name_strings[] = {
"kScreenDimmer",
"kExitWarning",
"kExitPrompt",
"kAudioPermissionPrompt",
"kExitPromptBackplane",
"kAudioPermissionPrompt",
"kAudioPermissionPromptShadow",
"kAudioPermissionPromptBackplane",
"kWebVrUrlToastTransientParent",
"kWebVrUrlToast",
"kExclusiveScreenToastTransientParent",
......
......@@ -43,8 +43,10 @@ enum UiElementName {
kScreenDimmer,
kExitWarning,
kExitPrompt,
kAudioPermissionPrompt,
kExitPromptBackplane,
kAudioPermissionPrompt,
kAudioPermissionPromptShadow,
kAudioPermissionPromptBackplane,
kWebVrUrlToastTransientParent,
kWebVrUrlToast,
kExclusiveScreenToastTransientParent,
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/vr/model/modal_prompt_type.h"
#include "base/logging.h"
namespace vr {
UiUnsupportedMode GetReasonForPrompt(ModalPromptType prompt) {
switch (prompt) {
case kModalPromptTypeExitVRForSiteInfo:
return UiUnsupportedMode::kUnhandledPageInfo;
case kModalPromptTypeExitVRForAudioPermission:
return UiUnsupportedMode::kAndroidPermissionNeeded;
case kModalPromptTypeNone:
return UiUnsupportedMode::kCount;
}
NOTREACHED();
return UiUnsupportedMode::kCount;
}
} // namespace vr
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_VR_MODEL_MODAL_PROMPT_TYPE_H_
#define CHROME_BROWSER_VR_MODEL_MODAL_PROMPT_TYPE_H_
#include "chrome/browser/vr/ui_unsupported_mode.h"
namespace vr {
enum ModalPromptType {
kModalPromptTypeNone,
kModalPromptTypeExitVRForSiteInfo,
kModalPromptTypeExitVRForAudioPermission,
};
UiUnsupportedMode GetReasonForPrompt(ModalPromptType prompt);
} // namespace vr
#endif // CHROME_BROWSER_VR_MODEL_MODAL_PROMPT_TYPE_H_
......@@ -6,6 +6,7 @@
#define CHROME_BROWSER_VR_MODEL_MODEL_H_
#include "chrome/browser/vr/model/controller_model.h"
#include "chrome/browser/vr/model/modal_prompt_type.h"
#include "chrome/browser/vr/model/omnibox_suggestions.h"
#include "chrome/browser/vr/model/reticle_model.h"
#include "chrome/browser/vr/model/speech_recognition_model.h"
......@@ -30,6 +31,8 @@ struct Model {
bool experimental_features_enabled = false;
bool incognito = false;
ModalPromptType active_modal_prompt_type = kModalPromptTypeNone;
std::vector<OmniboxSuggestion> omnibox_suggestions;
};
......
......@@ -66,4 +66,17 @@ void FakeUiElementRenderer::DrawReticle(
called_ = true;
}
void FakeUiElementRenderer::DrawShadow(
const gfx::Transform& model_view_proj_matrix,
const gfx::SizeF& element_size,
float x_padding,
float y_padding,
float y_offset,
SkColor color,
float opacity,
float corner_radius) {
// We do not verify the opacity used by shadows -- they adjust this at the
// last moment before calling into the UiElementRenderer.
}
} // namespace vr
......@@ -50,6 +50,15 @@ class FakeUiElementRenderer : public UiElementRenderer {
void DrawReticle(float opacity,
const gfx::Transform& view_proj_matrix) override;
void DrawShadow(const gfx::Transform& model_view_proj_matrix,
const gfx::SizeF& element_size,
float x_padding,
float y_padding,
float y_offset,
SkColor color,
float opacity,
float corner_radius) override;
private:
float opacity_ = -1.f;
float called_ = false;
......
......@@ -302,14 +302,18 @@ gfx::Transform VrTestContext::ViewProjectionMatrix() const {
return ProjectionMatrix() * head_pose_;
}
void VrTestContext::SetVoiceSearchActive(bool active) {}
void VrTestContext::SetVoiceSearchActive(bool active) {
OnUnsupportedMode(UiUnsupportedMode::kAndroidPermissionNeeded);
}
void VrTestContext::ExitPresent() {}
void VrTestContext::ExitFullscreen() {}
void VrTestContext::NavigateBack() {}
void VrTestContext::ExitCct() {}
void VrTestContext::OnUnsupportedMode(vr::UiUnsupportedMode mode) {
if (mode == UiUnsupportedMode::kUnhandledPageInfo)
if (mode == UiUnsupportedMode::kUnhandledPageInfo ||
mode == UiUnsupportedMode::kAndroidPermissionNeeded) {
ui_->SetExitVrPromptEnabled(true, mode);
}
}
void VrTestContext::OnExitVrPromptResult(vr::UiUnsupportedMode reason,
vr::ExitVrPromptChoice choice) {
......
......@@ -13,6 +13,7 @@
#include "chrome/browser/vr/model/model.h"
#include "chrome/browser/vr/model/omnibox_suggestions.h"
#include "chrome/browser/vr/speech_recognizer.h"
#include "chrome/browser/vr/ui_browser_interface.h"
#include "chrome/browser/vr/ui_element_renderer.h"
#include "chrome/browser/vr/ui_input_manager.h"
#include "chrome/browser/vr/ui_renderer.h"
......@@ -25,7 +26,8 @@ namespace vr {
Ui::Ui(UiBrowserInterface* browser,
ContentInputForwarder* content_input_forwarder,
const UiInitialState& ui_initial_state)
: scene_(base::MakeUnique<UiScene>()),
: browser_(browser),
scene_(base::MakeUnique<UiScene>()),
model_(base::MakeUnique<Model>()),
content_input_delegate_(
base::MakeUnique<ContentInputDelegate>(content_input_forwarder)),
......@@ -105,7 +107,28 @@ void Ui::SetLocationAccessIndicator(bool enabled) {
}
void Ui::SetExitVrPromptEnabled(bool enabled, UiUnsupportedMode reason) {
scene_manager_->SetExitVrPromptEnabled(enabled, reason);
if (!enabled) {
model_->active_modal_prompt_type = kModalPromptTypeNone;
return;
}
if (model_->active_modal_prompt_type != kModalPromptTypeNone) {
browser_->OnExitVrPromptResult(
GetReasonForPrompt(model_->active_modal_prompt_type),
ExitVrPromptChoice::CHOICE_NONE);
}
switch (reason) {
case UiUnsupportedMode::kUnhandledPageInfo:
model_->active_modal_prompt_type = kModalPromptTypeExitVRForSiteInfo;
break;
case UiUnsupportedMode::kAndroidPermissionNeeded:
model_->active_modal_prompt_type =
kModalPromptTypeExitVRForAudioPermission;
break;
default:
NOTREACHED();
}
}
void Ui::SetSpeechRecognitionEnabled(bool enabled) {
......
......@@ -95,6 +95,8 @@ class Ui : public BrowserUiInterface {
void SetOmniboxSuggestions(std::unique_ptr<OmniboxSuggestions> suggestions);
private:
UiBrowserInterface* browser_;
// This state may be further abstracted into a SkiaUi object.
std::unique_ptr<vr::UiScene> scene_;
std::unique_ptr<vr::Model> model_;
......
......@@ -266,7 +266,7 @@ TEST_F(UiInputManagerContentTest, NoMouseMovesDuringClick) {
}
TEST_F(UiInputManagerContentTest, ExitPromptHitTesting) {
manager_->SetExitVrPromptEnabled(true, UiUnsupportedMode::kUnhandledPageInfo);
model_->active_modal_prompt_type = kModalPromptTypeExitVRForSiteInfo;
EXPECT_TRUE(AnimateBy(MsToDelta(500)));
UiElement* exit_prompt =
......
......@@ -147,9 +147,6 @@ TestParams params[] = {
kScreenCaptureIndicator,
kBluetoothConnectedIndicator,
kLocationAccessIndicator,
kExitPromptBackplane,
kExitPrompt,
kAudioPermissionPrompt,
kUrlBar,
kLoadingIndicator,
kLoadingIndicatorForeground,
......@@ -157,6 +154,11 @@ TestParams params[] = {
kVoiceSearchButton,
kCloseButton,
kExclusiveScreenToast,
kExitPromptBackplane,
kExitPrompt,
kAudioPermissionPromptBackplane,
kAudioPermissionPromptShadow,
kAudioPermissionPrompt,
kSpeechRecognitionResultText,
kSpeechRecognitionResultCircle,
kSpeechRecognitionResultMicrophoneIcon,
......
......@@ -53,6 +53,7 @@ static constexpr float kUrlBarRotationRad = -0.175f;
static constexpr float kAudioPermissionPromptWidth = 0.63f * kUrlBarDistance;
static constexpr float kAudioPermissionPromptHeight = 0.218f * kUrlBarDistance;
static constexpr float kAudionPermisionPromptDepth = 0.11f;
static constexpr float kIndicatorHeight = 0.08f;
static constexpr float kIndicatorGap = 0.05f;
......@@ -207,6 +208,8 @@ static constexpr float kSpeechRecognitionResultTextYOffset = 0.5f;
static constexpr int kSpeechRecognitionResultTimeoutSeconds = 2;
static constexpr int kSpeechRecognitionOpacityAnimationDurationMs = 200;
static constexpr float kModalPromptFadeOpacity = 0.5f;
} // namespace vr
#endif // CHROME_BROWSER_VR_UI_SCENE_CONSTANTS_H_
......@@ -164,8 +164,8 @@ UiSceneManager::UiSceneManager(UiBrowserInterface* browser,
CreateBackground();
CreateViewportAwareRoot();
CreateContentQuad(content_input_delegate);
CreateExitPrompt();
CreateAudioPermissionPrompt();
CreateExitPrompt(model);
CreateAudioPermissionPrompt(model);
CreateWebVRExitWarning();
CreateSystemIndicators();
CreateUrlBar(model);
......@@ -197,13 +197,35 @@ void UiSceneManager::Create2dBrowsingSubtreeRoots(Model* model) {
element->set_hit_testable(false);
scene_->AddUiElement(k2dBrowsingRoot, std::move(element));
auto browsing_mode_toggle = base::MakeUnique<UiElement>();
browsing_mode_toggle->set_hit_testable(false);
browsing_mode_toggle->AddBinding(
VR_BIND_FUNC(bool, UiSceneManager, this, browsing_mode(), UiElement,
browsing_mode_toggle.get(), SetVisible));
element = base::MakeUnique<UiElement>();
element->set_name(k2dBrowsingForeground);
element->set_hit_testable(false);
element->SetTransitionedProperties({OPACITY});
element->SetTransitionDuration(base::TimeDelta::FromMilliseconds(
kSpeechRecognitionOpacityAnimationDurationMs));
scene_->AddUiElement(k2dBrowsingRoot, std::move(element));
element->AddBinding(base::MakeUnique<Binding<ModalPromptType>>(
base::Bind([](Model* m) { return m->active_modal_prompt_type; },
base::Unretained(model)),
base::Bind(
[](UiElement* e, const ModalPromptType& t) {
if (t == kModalPromptTypeExitVRForSiteInfo) {
e->SetVisibleImmediately(false);
} else if (t == kModalPromptTypeExitVRForAudioPermission) {
e->SetOpacity(kModalPromptFadeOpacity);
} else {
e->SetVisible(true);
}
},
base::Unretained(element.get()))));
browsing_mode_toggle->AddChild(std::move(element));
scene_->AddUiElement(k2dBrowsingRoot, std::move(browsing_mode_toggle));
element = base::MakeUnique<UiElement>();
element->set_name(k2dBrowsingContentGroup);
......@@ -211,9 +233,6 @@ void UiSceneManager::Create2dBrowsingSubtreeRoots(Model* model) {
element->SetSize(kContentWidth, kContentHeight);
element->set_hit_testable(false);
element->SetTransitionedProperties({TRANSFORM});
element->AddBinding(VR_BIND(bool, UiSceneManager, this,
browsing_mode() && !model->prompting_to_exit(),
UiElement, element.get(), SetVisible(value)));
scene_->AddUiElement(k2dBrowsingForeground, std::move(element));
}
......@@ -826,10 +845,8 @@ void UiSceneManager::CreateUrlBar(Model* model) {
url_bar->SetTranslate(0, kUrlBarVerticalOffset, -kUrlBarDistance);
url_bar->SetRotate(1, 0, 0, kUrlBarRotationRad);
url_bar->SetSize(kUrlBarWidth, kUrlBarHeight);
url_bar->AddBinding(VR_BIND_FUNC(
bool, UiSceneManager, this,
browsing_mode() && !model->prompting_to_exit() && !model->fullscreen(),
UiElement, url_bar.get(), SetVisible));
url_bar->AddBinding(VR_BIND(bool, UiSceneManager, this, fullscreen(),
UiElement, url_bar.get(), SetVisible(!value)));
url_bar_ = url_bar.get();
scene_->AddUiElement(k2dBrowsingForeground, std::move(url_bar));
......@@ -941,28 +958,31 @@ void UiSceneManager::CreateCloseButton() {
scene_->AddUiElement(k2dBrowsingForeground, std::move(element));
}
void UiSceneManager::CreateExitPrompt() {
void UiSceneManager::CreateExitPrompt(Model* model) {
std::unique_ptr<UiElement> element;
// Place an invisible but hittable plane behind the exit prompt, to keep the
// reticle roughly planar with the content if near content.
auto backplane = base::MakeUnique<InvisibleHitTarget>();
exit_prompt_backplane_ = backplane.get();
element = std::move(backplane);
element->set_name(kExitPromptBackplane);
element->set_draw_phase(kPhaseForeground);
element->SetVisible(false);
element->SetSize(kPromptBackplaneSize, kPromptBackplaneSize);
element->SetTranslate(0.0, kContentVerticalOffset + kExitPromptVerticalOffset,
kTextureOffset - kContentDistance);
backplane->set_name(kExitPromptBackplane);
backplane->set_draw_phase(kPhaseForeground);
backplane->SetSize(kPromptBackplaneSize, kPromptBackplaneSize);
backplane->SetTranslate(0.0,
kContentVerticalOffset + kExitPromptVerticalOffset,
kTextureOffset - kContentDistance);
EventHandlers event_handlers;
event_handlers.button_up = base::Bind(
&UiSceneManager::OnExitPromptBackplaneClicked, base::Unretained(this));
element->set_event_handlers(event_handlers);
element->AddBinding(VR_BIND_FUNC(
bool, UiSceneManager, this, browsing_mode() && model->prompting_to_exit(),
UiElement, element.get(), SetVisible));
scene_->AddUiElement(k2dBrowsingForeground, std::move(element));
[](UiSceneManager* manager, Model* m) {
manager->OnExitPromptBackplaneClicked(
GetReasonForPrompt(m->active_modal_prompt_type));
},
base::Unretained(this), base::Unretained(model));
backplane->set_event_handlers(event_handlers);
backplane->AddBinding(VR_BIND_FUNC(
bool, Model, model,
active_modal_prompt_type == kModalPromptTypeExitVRForSiteInfo, UiElement,
backplane.get(), SetVisible));
scene_->AddUiElement(k2dBrowsingRoot, std::move(backplane));
std::unique_ptr<ExitPrompt> exit_prompt = base::MakeUnique<ExitPrompt>(
512,
......@@ -970,37 +990,79 @@ void UiSceneManager::CreateExitPrompt() {
false),
base::Bind(&UiSceneManager::OnExitPromptChoice, base::Unretained(this),
true));
exit_prompt_ = exit_prompt.get();
element = std::move(exit_prompt);
element->set_name(kExitPrompt);
element->set_draw_phase(kPhaseForeground);
element->SetVisible(true);
element->SetSize(kExitPromptWidth, kExitPromptHeight);
element->SetTranslate(0.0, 0.0, kTextureOffset);
scene_->AddUiElement(kExitPromptBackplane, std::move(element));
exit_prompt->set_name(kExitPrompt);
exit_prompt->set_draw_phase(kPhaseForeground);
exit_prompt->SetVisible(true);
exit_prompt->SetSize(kExitPromptWidth, kExitPromptHeight);
exit_prompt->SetTranslate(0.0, 0.0, kTextureOffset);
exit_prompt->AddBinding(base::MakeUnique<Binding<ModalPromptType>>(
base::Bind([](Model* m) { return m->active_modal_prompt_type; },
base::Unretained(model)),
base::Bind(
[](ExitPrompt* e, const ModalPromptType& p) {
e->set_reason(GetReasonForPrompt(p));
switch (p) {
case kModalPromptTypeExitVRForSiteInfo:
e->SetContentMessageId(
IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION_SITE_INFO);
break;
default:
e->SetContentMessageId(IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION);
break;
}
},
base::Unretained(exit_prompt.get()))));
scene_->AddUiElement(kExitPromptBackplane, std::move(exit_prompt));
}
void UiSceneManager::CreateAudioPermissionPrompt() {
void UiSceneManager::CreateAudioPermissionPrompt(Model* model) {
std::unique_ptr<UiElement> element;
std::unique_ptr<AudioPermissionPrompt> audio_permission_prompt =
// Place an invisible but hittable plane behind the exit prompt, to keep the
// reticle roughly planar with the content if near content.
auto backplane = base::MakeUnique<InvisibleHitTarget>();
backplane->set_draw_phase(kPhaseForeground);
backplane->set_name(kAudioPermissionPromptBackplane);
backplane->SetSize(kPromptBackplaneSize, kPromptBackplaneSize);
backplane->SetTranslate(0.0,
kContentVerticalOffset + kExitPromptVerticalOffset,
kTextureOffset - kContentDistance);
EventHandlers event_handlers;
event_handlers.button_up = base::Bind(
[](UiSceneManager* manager, Model* m) {
manager->OnExitPromptBackplaneClicked(
GetReasonForPrompt(m->active_modal_prompt_type));
},
base::Unretained(this), base::Unretained(model));
backplane->set_event_handlers(event_handlers);
backplane->SetVisible(false);
backplane->SetTransitionedProperties({OPACITY});
backplane->AddBinding(VR_BIND_FUNC(
bool, Model, model,
active_modal_prompt_type == kModalPromptTypeExitVRForAudioPermission,
UiElement, backplane.get(), SetVisible));
std::unique_ptr<Shadow> shadow = base::MakeUnique<Shadow>();
shadow->set_draw_phase(kPhaseForeground);
shadow->set_name(kAudioPermissionPromptShadow);
shadow->set_corner_radius(kContentCornerRadius);
std::unique_ptr<AudioPermissionPrompt> prompt =
base::MakeUnique<AudioPermissionPrompt>(
1024,
base::Bind(&UiSceneManager::OnExitPromptChoice,
base::Unretained(this), true),
base::Unretained(this), true,
UiUnsupportedMode::kAndroidPermissionNeeded),
base::Bind(&UiSceneManager::OnExitPromptChoice,
base::Unretained(this), false));
audio_permission_prompt_ = audio_permission_prompt.get();
element = std::move(audio_permission_prompt);
element->set_name(kAudioPermissionPrompt);
element->set_draw_phase(kPhaseForeground);
element->SetSize(kAudioPermissionPromptWidth, kAudioPermissionPromptHeight);
element->SetTranslate(0.0, kContentVerticalOffset, -kUrlBarDistance);
element->AddBinding(
VR_BIND(bool, UiSceneManager, this,
browsing_mode() && model->prompting_to_audio_permission(),
UiElement, element.get(), SetVisible(value)));
scene_->AddUiElement(k2dBrowsingForeground, std::move(element));
base::Unretained(this), false,
UiUnsupportedMode::kAndroidPermissionNeeded));
prompt->set_name(kAudioPermissionPrompt);
prompt->set_draw_phase(kPhaseForeground);
prompt->SetSize(kAudioPermissionPromptWidth, kAudioPermissionPromptHeight);
prompt->SetTranslate(0.0, 0.0f, kAudionPermisionPromptDepth);
shadow->AddChild(std::move(prompt));
backplane->AddChild(std::move(shadow));
scene_->AddUiElement(k2dBrowsingRoot, std::move(backplane));
}
void UiSceneManager::CreateToasts(Model* model) {
......@@ -1325,34 +1387,6 @@ void UiSceneManager::SetFullscreen(bool fullscreen) {
ConfigureScene();
}
void UiSceneManager::SetExitVrPromptEnabled(bool enabled,
UiUnsupportedMode reason) {
DCHECK(enabled || reason == UiUnsupportedMode::kCount);
if (!enabled) {
prompting_to_exit_ = enabled;
prompting_to_audio_permission_ = enabled;
ConfigureScene();
return;
}
if ((prompting_to_exit_ || prompting_to_audio_permission_) && enabled) {
browser_->OnExitVrPromptResult(exit_vr_prompt_reason_,
ExitVrPromptChoice::CHOICE_NONE);
}
if (reason == UiUnsupportedMode::kUnhandledPageInfo) {
exit_prompt_->SetContentMessageId(
IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION_SITE_INFO);
prompting_to_exit_ = enabled;
} else if (reason == UiUnsupportedMode::kAndroidPermissionNeeded) {
prompting_to_audio_permission_ = enabled;
} else {
exit_prompt_->SetContentMessageId(IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION);
prompting_to_exit_ = enabled;
}
exit_vr_prompt_reason_ = reason;
ConfigureScene();
}
void UiSceneManager::OnBackButtonClicked() {
browser_->NavigateBack();
}
......@@ -1361,27 +1395,28 @@ void UiSceneManager::OnSecurityIconClickedForTesting() {
OnSecurityIconClicked();
}
void UiSceneManager::OnExitPromptChoiceForTesting(bool chose_exit) {
OnExitPromptChoice(chose_exit);
void UiSceneManager::OnExitPromptChoiceForTesting(bool chose_exit,
UiUnsupportedMode reason) {
OnExitPromptChoice(chose_exit, reason);
}
void UiSceneManager::OnSecurityIconClicked() {
browser_->OnUnsupportedMode(UiUnsupportedMode::kUnhandledPageInfo);
}
void UiSceneManager::OnExitPromptBackplaneClicked() {
browser_->OnExitVrPromptResult(exit_vr_prompt_reason_,
ExitVrPromptChoice::CHOICE_NONE);
void UiSceneManager::OnExitPromptBackplaneClicked(UiUnsupportedMode reason) {
browser_->OnExitVrPromptResult(reason, ExitVrPromptChoice::CHOICE_NONE);
}
void UiSceneManager::OnExitRecognizingSpeechClicked() {
browser_->SetVoiceSearchActive(false);
}
void UiSceneManager::OnExitPromptChoice(bool chose_exit) {
browser_->OnExitVrPromptResult(exit_vr_prompt_reason_,
chose_exit ? ExitVrPromptChoice::CHOICE_EXIT
: ExitVrPromptChoice::CHOICE_STAY);
void UiSceneManager::OnExitPromptChoice(bool chose_exit,
UiUnsupportedMode reason) {
browser_->OnExitVrPromptResult(reason, chose_exit
? ExitVrPromptChoice::CHOICE_EXIT
: ExitVrPromptChoice::CHOICE_STAY);
}
void UiSceneManager::SetToolbarState(const ToolbarState& state) {
......
......@@ -27,8 +27,6 @@ class UiBrowserInterface;
class UiElement;
class UiScene;
class UrlBar;
class ExitPrompt;
class AudioPermissionPrompt;
struct Model;
struct UiInitialState;
......@@ -57,6 +55,10 @@ struct UiInitialState;
// kBluetoothConnectedIndicator
// kExitPromptBackplane
// kExitPrompt
// (unnamed) a toggle element for hiding out of browser mode.
// kAudioPermissionPromptBackplane
// kAudioPermissounPromptShadow
// kAudioPermissionPrompt
// kExclusiveScreenToastTransientParent
// kExclusiveScreenToast
// kCloseButton
......@@ -131,7 +133,6 @@ class UiSceneManager {
void SetLocationAccessIndicator(bool enabled);
void SetBluetoothConnectedIndicator(bool enabled);
void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward);
void SetExitVrPromptEnabled(bool enabled, UiUnsupportedMode reason);
bool ShouldRenderWebVr();
void OnGlInitialized(unsigned int content_texture_id,
......@@ -146,7 +147,7 @@ class UiSceneManager {
void OnSplashScreenHidden(TransientElementHideReason);
void OnSecurityIconClickedForTesting();
void OnExitPromptChoiceForTesting(bool chose_exit);
void OnExitPromptChoiceForTesting(bool chose_exit, UiUnsupportedMode reason);
// TODO(vollick): these should move to the model.
const ColorScheme& color_scheme() const;
......@@ -158,10 +159,6 @@ class UiSceneManager {
bool browsing_mode() const {
return !web_vr_mode_ && !showing_web_vr_splash_screen_;
}
bool prompting_to_exit() const { return prompting_to_exit_; }
bool prompting_to_audio_permission() const {
return prompting_to_audio_permission_;
}
bool fullscreen() const { return fullscreen_; }
private:
......@@ -179,8 +176,8 @@ class UiSceneManager {
void CreateSuggestionList(Model* model);
void CreateWebVrUrlToast();
void CreateCloseButton();
void CreateExitPrompt();
void CreateAudioPermissionPrompt();
void CreateExitPrompt(Model* model);
void CreateAudioPermissionPrompt(Model* model);
void CreateToasts(Model* model);
void CreateVoiceSearchUiGroup(Model* model);
void CreateController(Model* model);
......@@ -190,8 +187,8 @@ class UiSceneManager {
void ConfigureBackgroundColor();
void OnBackButtonClicked();
void OnSecurityIconClicked();
void OnExitPromptChoice(bool chose_exit);
void OnExitPromptBackplaneClicked();
void OnExitPromptChoice(bool chose_exit, UiUnsupportedMode reason);
void OnExitPromptBackplaneClicked(UiUnsupportedMode reason);
void OnExitRecognizingSpeechClicked();
void OnCloseButtonClicked();
void OnUnsupportedMode(UiUnsupportedMode mode);
......@@ -211,9 +208,6 @@ class UiSceneManager {
TransientElement* exclusive_screen_toast_viewport_aware_transient_parent_ =
nullptr;
ShowUntilSignalTransientElement* splash_screen_transient_parent_ = nullptr;
ExitPrompt* exit_prompt_ = nullptr;
AudioPermissionPrompt* audio_permission_prompt_ = nullptr;
UiElement* exit_prompt_backplane_ = nullptr;
UiElement* speech_recognition_prompt_backplane_ = nullptr;
UiElement* exit_warning_ = nullptr;
ContentElement* main_content_ = nullptr;
......@@ -240,8 +234,6 @@ class UiSceneManager {
// before we hide the splash screen. This is used in the case of WebVR
// auto-presentation.
bool showing_web_vr_splash_screen_ = false;
bool prompting_to_exit_ = false;
bool prompting_to_audio_permission_ = false;
bool exiting_ = false;
bool browsing_disabled_ = false;
bool configuring_scene_ = false;
......@@ -253,7 +245,6 @@ class UiSceneManager {
bool screen_capturing_ = false;
bool location_access_ = false;
bool bluetooth_connected_ = false;
UiUnsupportedMode exit_vr_prompt_reason_ = UiUnsupportedMode::kCount;
std::vector<Rect*> background_panels_;
......
......@@ -55,6 +55,7 @@ const std::set<UiElementName> kHitTestableElements = {
kExitPrompt,
kExitPromptBackplane,
kAudioPermissionPrompt,
kAudioPermissionPromptBackplane,
kUrlBar,
kLoadingIndicator,
kWebVrTimeoutSpinner,
......@@ -390,7 +391,7 @@ TEST_F(UiSceneManagerTest, UiUpdatesForShowingExitPrompt) {
VerifyElementsVisible("Initial", kElementsVisibleInBrowsing);
// Showing exit VR prompt should make prompt visible.
manager_->SetExitVrPromptEnabled(true, UiUnsupportedMode::kUnhandledPageInfo);
model_->active_modal_prompt_type = kModalPromptTypeExitVRForSiteInfo;
VerifyElementsVisible("Prompt visible", kElementsVisibleWithExitPrompt);
}
......@@ -398,11 +399,12 @@ TEST_F(UiSceneManagerTest, UiUpdatesForHidingExitPrompt) {
MakeManager(kNotInCct, kNotInWebVr);
// Initial state.
manager_->SetExitVrPromptEnabled(true, UiUnsupportedMode::kUnhandledPageInfo);
model_->active_modal_prompt_type = kModalPromptTypeExitVRForSiteInfo;
VerifyElementsVisible("Initial", kElementsVisibleWithExitPrompt);
// Hiding exit VR prompt should make prompt invisible.
manager_->SetExitVrPromptEnabled(false, UiUnsupportedMode::kCount);
model_->active_modal_prompt_type = kModalPromptTypeNone;
EXPECT_TRUE(AnimateBy(MsToDelta(1000)));
VerifyElementsVisible("Prompt invisible", kElementsVisibleInBrowsing);
}
......@@ -411,7 +413,7 @@ TEST_F(UiSceneManagerTest, BackplaneClickTriggersOnExitPrompt) {
// Initial state.
VerifyElementsVisible("Initial", kElementsVisibleInBrowsing);
manager_->SetExitVrPromptEnabled(true, UiUnsupportedMode::kUnhandledPageInfo);
model_->active_modal_prompt_type = kModalPromptTypeExitVRForSiteInfo;
// Click on backplane should trigger UI browser interface but not close
// prompt.
......@@ -427,13 +429,14 @@ TEST_F(UiSceneManagerTest, PrimaryButtonClickTriggersOnExitPrompt) {
// Initial state.
VerifyElementsVisible("Initial", kElementsVisibleInBrowsing);
manager_->SetExitVrPromptEnabled(true, UiUnsupportedMode::kUnhandledPageInfo);
model_->active_modal_prompt_type = kModalPromptTypeExitVRForSiteInfo;
// Click on 'OK' should trigger UI browser interface but not close prompt.
EXPECT_CALL(*browser_,
OnExitVrPromptResult(UiUnsupportedMode::kUnhandledPageInfo,
ExitVrPromptChoice::CHOICE_STAY));
manager_->OnExitPromptChoiceForTesting(false);
manager_->OnExitPromptChoiceForTesting(false,
UiUnsupportedMode::kUnhandledPageInfo);
VerifyElementsVisible("Prompt still visible", kElementsVisibleWithExitPrompt);
}
......@@ -442,31 +445,15 @@ TEST_F(UiSceneManagerTest, SecondaryButtonClickTriggersOnExitPrompt) {
// Initial state.
VerifyElementsVisible("Initial", kElementsVisibleInBrowsing);
manager_->SetExitVrPromptEnabled(true, UiUnsupportedMode::kUnhandledPageInfo);
model_->active_modal_prompt_type = kModalPromptTypeExitVRForSiteInfo;
// Click on 'Exit VR' should trigger UI browser interface but not close
// prompt.
EXPECT_CALL(*browser_,
OnExitVrPromptResult(UiUnsupportedMode::kUnhandledPageInfo,
ExitVrPromptChoice::CHOICE_EXIT));
manager_->OnExitPromptChoiceForTesting(true);
VerifyElementsVisible("Prompt still visible", kElementsVisibleWithExitPrompt);
}
TEST_F(UiSceneManagerTest, SecondExitPromptTriggersOnExitPrompt) {
MakeManager(kNotInCct, kNotInWebVr);
// Initial state.
VerifyElementsVisible("Initial", kElementsVisibleInBrowsing);
manager_->SetExitVrPromptEnabled(true, UiUnsupportedMode::kUnhandledPageInfo);
// Click on 'Exit VR' should trigger UI browser interface but not close
// prompt.
EXPECT_CALL(*browser_,
OnExitVrPromptResult(UiUnsupportedMode::kUnhandledPageInfo,
ExitVrPromptChoice::CHOICE_NONE));
manager_->SetExitVrPromptEnabled(true,
UiUnsupportedMode::kUnhandledCodePoint);
manager_->OnExitPromptChoiceForTesting(true,
UiUnsupportedMode::kUnhandledPageInfo);
VerifyElementsVisible("Prompt still visible", kElementsVisibleWithExitPrompt);
}
......@@ -536,6 +523,7 @@ TEST_F(UiSceneManagerTest, CaptureIndicatorsVisibility) {
manager_->SetFullscreen(false);
// Back to browser, make sure the indicators reappear.
EXPECT_TRUE(AnimateBy(MsToDelta(500)));
EXPECT_TRUE(VerifyVisibility(indicators, true));
EXPECT_TRUE(VerifyRequiresLayout(indicators, true));
......@@ -648,7 +636,7 @@ TEST_F(UiSceneManagerTest, EnforceSceneHierarchyForProjMatrixChanges) {
UiElement* browsing_root = scene_->GetUiElementByName(k2dBrowsingRoot);
UiElement* root = scene_->GetUiElementByName(kRoot);
EXPECT_EQ(browsing_content_group->parent(), browsing_foreground);
EXPECT_EQ(browsing_foreground->parent(), browsing_root);
EXPECT_EQ(browsing_foreground->parent()->parent(), browsing_root);
EXPECT_EQ(browsing_root->parent(), root);
EXPECT_EQ(root->parent(), nullptr);
// Parents of k2dBrowsingContentGroup should not animate transform. Note that
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/vr/ui.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/vr/content_input_delegate.h"
#include "chrome/browser/vr/test/mock_browser_interface.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace vr {
class FakeContentInputForwarder : public ContentInputForwarder {
public:
FakeContentInputForwarder() {}
~FakeContentInputForwarder() override {}
void ForwardEvent(std::unique_ptr<blink::WebInputEvent> event,
int content_id) override {}
};
class UiTest : public testing::Test {
public:
UiTest() {}
~UiTest() override {}
void SetUp() override {
UiInitialState initial_state;
forwarder_ = base::MakeUnique<FakeContentInputForwarder>();
browser_ = base::MakeUnique<testing::NiceMock<MockBrowserInterface>>();
ui_ = base::MakeUnique<Ui>(browser_.get(), forwarder_.get(), initial_state);
}
protected:
std::unique_ptr<FakeContentInputForwarder> forwarder_;
std::unique_ptr<MockBrowserInterface> browser_;
std::unique_ptr<Ui> ui_;
};
TEST_F(UiTest, SecondExitPromptTriggersOnExitPrompt) {
ui_->SetExitVrPromptEnabled(true, UiUnsupportedMode::kUnhandledPageInfo);
// Initiating another exit VR prompt while a previous one was in flight should
// result in a call to the UiBrowserInterface.
EXPECT_CALL(*browser_,
OnExitVrPromptResult(UiUnsupportedMode::kUnhandledPageInfo,
ExitVrPromptChoice::CHOICE_NONE));
ui_->SetExitVrPromptEnabled(true,
UiUnsupportedMode::kAndroidPermissionNeeded);
}
} // namespace vr
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment