blob: 921779c4ca4d671024d93319334218add85bf898 [file] [log] [blame]
// 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/testapp/vr_test_context.h"
#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/i18n/icu_util.h"
#include "base/numerics/ranges.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/version.h"
#include "chrome/browser/vr/assets_load_status.h"
#include "chrome/browser/vr/gl_texture_location.h"
#include "chrome/browser/vr/graphics_delegate.h"
#include "chrome/browser/vr/model/assets.h"
#include "chrome/browser/vr/model/location_bar_state.h"
#include "chrome/browser/vr/model/model.h"
#include "chrome/browser/vr/model/omnibox_suggestions.h"
#include "chrome/browser/vr/render_info.h"
#include "chrome/browser/vr/speech_recognizer.h"
#include "chrome/browser/vr/test/constants.h"
#include "chrome/browser/vr/testapp/assets_component_version.h"
#include "chrome/browser/vr/testapp/test_keyboard_delegate.h"
#include "chrome/browser/vr/text_input_delegate.h"
#include "chrome/browser/vr/ui.h"
#include "chrome/browser/vr/ui_element_renderer.h"
#include "chrome/browser/vr/ui_input_manager.h"
#include "chrome/browser/vr/ui_renderer.h"
#include "chrome/browser/vr/ui_scene.h"
#include "chrome/browser/vr/ui_unsupported_mode.h"
#include "chrome/grit/vr_testapp_resources.h"
#include "components/omnibox/browser/vector_icons.h"
#include "components/security_state/core/security_state.h"
#include "components/vector_icons/vector_icons.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/angle_conversions.h"
namespace vr {
namespace {
// Constants related to scaling of the UI for zooming, to let us look at
// elements up close. The adjustment factor determines how much the zoom changes
// at each adjustment step.
constexpr float kDefaultViewScaleFactor = 1.2f;
constexpr float kMinViewScaleFactor = 0.5f;
constexpr float kMaxViewScaleFactor = 5.0f;
constexpr float kViewScaleAdjustmentFactor = 0.2f;
constexpr float kPageLoadTimeMilliseconds = 1000;
constexpr gfx::Point3F kDefaultLaserOrigin = {0.5f, -0.5f, 0.f};
constexpr gfx::Vector3dF kLaserLocalOffset = {0.f, -0.0075f, -0.05f};
constexpr float kControllerScaleFactor = 1.5f;
constexpr float kTouchpadPositionDelta = 0.05f;
const float kVerticalScrollScaleFactor =
8.0f / ui::MouseWheelEvent::kWheelDelta;
const float kHorizontalScrollScaleFactor =
100.0f / ui::MouseWheelEvent::kWheelDelta;
constexpr gfx::PointF kInitialTouchPosition = {0.5f, 0.5f};
void RotateToward(const gfx::Vector3dF& fwd, gfx::Transform* transform) {
gfx::Quaternion quat(kForwardVector, fwd);
transform->PreconcatTransform(gfx::Transform(quat));
}
bool LoadPng(int resource_id, std::unique_ptr<SkBitmap>* out_image) {
base::StringPiece data =
ui::ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id);
*out_image = std::make_unique<SkBitmap>();
return gfx::PNGCodec::Decode(
reinterpret_cast<const unsigned char*>(data.data()), data.size(),
out_image->get());
}
InputEventList CreateScrollGestureEventList(InputEvent::Type type) {
std::unique_ptr<InputEvent> gesture = std::make_unique<InputEvent>(type);
InputEventList list;
list.push_back(std::move(gesture));
return list;
}
InputEventList CreateScrollGestureEventList(InputEvent::Type type,
const gfx::Vector2dF& delta) {
auto list = CreateScrollGestureEventList(type);
InputEvent* event = static_cast<InputEvent*>(list.front().get());
event->scroll_data.delta_x = delta.x();
event->scroll_data.delta_y = delta.y();
return list;
}
} // namespace
VrTestContext::VrTestContext(GraphicsDelegate* graphics_delegate)
: view_scale_factor_(kDefaultViewScaleFactor),
graphics_delegate_(graphics_delegate) {
base::FilePath pak_path;
base::PathService::Get(base::DIR_MODULE, &pak_path);
ui::ResourceBundle::InitSharedInstanceWithPakPath(
pak_path.AppendASCII("vr_testapp.pak"));
base::i18n::InitializeICU();
auto text_input_delegate = std::make_unique<TextInputDelegate>();
auto keyboard_delegate = std::make_unique<TestKeyboardDelegate>();
keyboard_delegate_ = keyboard_delegate.get();
text_input_delegate->SetUpdateInputCallback(
base::BindRepeating(&TestKeyboardDelegate::UpdateInput,
base::Unretained(keyboard_delegate.get())));
UiInitialState ui_initial_state;
ui_instance_ = std::make_unique<Ui>(
this, nullptr, std::move(keyboard_delegate),
std::move(text_input_delegate), nullptr, ui_initial_state);
ui_ = ui_instance_.get();
LoadAssets();
touchpad_touch_position_ = kInitialTouchPosition;
model_ = ui_instance_->model_for_test();
CycleOrigin();
auto browser_ui = ui_->GetBrowserUiWeakPtr();
browser_ui->SetHistoryButtonsEnabled(true, true);
browser_ui->SetLoading(true);
browser_ui->SetLoadProgress(0.4);
CapturingStateModel active_capturing;
CapturingStateModel background_capturing;
CapturingStateModel potential_capturing;
potential_capturing.video_capture_enabled = true;
background_capturing.screen_capture_enabled = true;
active_capturing.bluetooth_connected = true;
active_capturing.location_access_enabled = true;
browser_ui->SetCapturingState(active_capturing, background_capturing,
potential_capturing);
ui_instance_->input_manager()->set_hit_test_strategy(
UiInputManager::PROJECT_TO_LASER_ORIGIN_FOR_TEST);
InitializeGl();
}
VrTestContext::~VrTestContext() = default;
void VrTestContext::InitializeGl() {
unsigned int content_texture_id = CreateTexture(0xFF000080);
unsigned int ui_texture_id = CreateTexture(0xFF008000);
ui_->OnGlInitialized(kGlTextureLocationLocal, content_texture_id,
content_texture_id, ui_texture_id);
keyboard_delegate_->Initialize(
ui_instance_->scene()->SurfaceProviderForTesting(),
ui_instance_->ui_element_renderer());
}
void VrTestContext::DrawFrame() {
base::TimeTicks current_time = base::TimeTicks::Now();
RenderInfo render_info = GetRenderInfo();
// Update the render position of all UI elements (including desktop).
ui_->OnBeginFrame(current_time, head_pose_);
ui_->OnProjMatrixChanged(render_info.left_eye_model.proj_matrix);
UpdateController(render_info, current_time);
graphics_delegate_->RunInSkiaContext(
base::BindOnce(&UiInterface::UpdateSceneTextures, base::Unretained(ui_)));
auto load_progress = (current_time - page_load_start_).InMilliseconds() /
kPageLoadTimeMilliseconds;
auto browser_ui = ui_->GetBrowserUiWeakPtr();
browser_ui->SetLoading(load_progress < 1.0f);
browser_ui->SetLoadProgress(std::min(load_progress, 1.0f));
if (web_vr_mode_ && model_->web_vr.state == kWebVrPresenting &&
webvr_frames_received_) {
ui_->DrawWebVrOverlayForeground(render_info);
} else {
ui_->Draw(render_info);
}
}
void VrTestContext::HandleInput(ui::Event* event) {
auto browser_ui = ui_->GetBrowserUiWeakPtr();
if (event->IsKeyEvent()) {
if (event->type() != ui::ET_KEY_PRESSED) {
return;
}
if (event->AsKeyEvent()->key_code() == ui::VKEY_CONTROL) {
return;
}
if (!event->IsControlDown() && keyboard_delegate_->HandleInput(event)) {
return;
}
switch (event->AsKeyEvent()->code()) {
case ui::DomCode::ESCAPE:
view_scale_factor_ = kDefaultViewScaleFactor;
head_angle_x_degrees_ = 0;
head_angle_y_degrees_ = 0;
head_pose_ = gfx::Transform();
break;
case ui::DomCode::US_F:
fullscreen_ = !fullscreen_;
browser_ui->SetFullscreen(fullscreen_);
break;
case ui::DomCode::US_A:
if (model_->platform_toast) {
browser_ui->CancelPlatformToast();
} else {
browser_ui->ShowPlatformToast(base::UTF8ToUTF16("Downloading"));
}
break;
case ui::DomCode::US_H:
handedness_ = handedness_ == ControllerModel::kRightHanded
? ControllerModel::kLeftHanded
: ControllerModel::kRightHanded;
break;
case ui::DomCode::US_I:
incognito_ = !incognito_;
browser_ui->SetIncognito(incognito_);
break;
case ui::DomCode::US_C:
CycleIndicators();
break;
case ui::DomCode::US_D:
ui_instance_->Dump(false);
break;
case ui::DomCode::US_B:
ui_instance_->Dump(true);
break;
case ui::DomCode::US_V:
CreateFakeVoiceSearchResult();
break;
case ui::DomCode::US_W:
CycleWebVrModes();
break;
case ui::DomCode::US_S:
ToggleSplashScreen();
break;
case ui::DomCode::US_R: {
webvr_frames_received_ = true;
CapturingStateModel active_capturing;
CapturingStateModel background_capturing;
CapturingStateModel potential_capturing;
active_capturing.bluetooth_connected = true;
active_capturing.location_access_enabled = true;
browser_ui->SetCapturingState(active_capturing, background_capturing,
potential_capturing);
ui_->GetSchedulerUiPtr()->OnWebXrFrameAvailable();
break;
}
case ui::DomCode::US_O:
CycleOrigin();
model_->can_navigate_back = !model_->can_navigate_back;
break;
case ui::DomCode::US_P:
model_->toggle_mode(kModeRepositionWindow);
break;
case ui::DomCode::US_G:
recentered_ = true;
break;
case ui::DomCode::US_T:
touching_touchpad_ = !touching_touchpad_;
break;
case ui::DomCode::US_Q: {
auto mode = model_->active_modal_prompt_type;
model_->active_modal_prompt_type =
static_cast<ModalPromptType>((mode + 1) % kNumModalPromptTypes);
model_->push_mode(kModeModalPrompt);
break;
}
case ui::DomCode::US_L:
model_->standalone_vr_device = !model_->standalone_vr_device;
break;
case ui::DomCode::US_N:
if (hosted_ui_enabled_) {
CloseHostedDialog();
} else {
ui_->SetAlertDialogEnabled(true, nullptr, 100, 50);
hosted_ui_enabled_ = true;
}
break;
default:
break;
}
return;
}
if (event->IsMouseWheelEvent()) {
int direction =
base::ClampToRange(event->AsMouseWheelEvent()->y_offset(), -1, 1);
if (event->IsControlDown()) {
view_scale_factor_ *= (1 + direction * kViewScaleAdjustmentFactor);
view_scale_factor_ = base::ClampToRange(
view_scale_factor_, kMinViewScaleFactor, kMaxViewScaleFactor);
} else if (model_->reposition_window_enabled()) {
touchpad_touch_position_.set_y(base::ClampToRange(
touchpad_touch_position_.y() + kTouchpadPositionDelta * direction,
0.0f, 1.0f));
} else {
input_event_lists_.push(
CreateScrollGestureEventList(InputEvent::kScrollBegin));
auto offset = gfx::Vector2dF(event->AsMouseWheelEvent()->offset());
if (event->IsShiftDown()) {
offset.Scale(kHorizontalScrollScaleFactor);
offset = gfx::Vector2dF(offset.y(), offset.x());
} else {
offset.Scale(kVerticalScrollScaleFactor);
}
input_event_lists_.push(
CreateScrollGestureEventList(InputEvent::kScrollUpdate, offset));
input_event_lists_.push(
CreateScrollGestureEventList(InputEvent::kScrollEnd));
}
return;
}
if (!event->IsMouseEvent()) {
return;
}
const ui::MouseEvent* mouse_event = event->AsMouseEvent();
if (mouse_event->IsMiddleMouseButton() &&
mouse_event->type() == ui::ET_MOUSE_RELEASED) {
InputEventList list;
list.push_back(
std::make_unique<InputEvent>(InputEvent::kMenuButtonClicked));
input_event_lists_.push(std::move(list));
}
// TODO(cjgrant): Figure out why, quite regularly, mouse click events do not
// make it into this method and are missed.
if (mouse_event->IsLeftMouseButton()) {
if (mouse_event->type() == ui::ET_MOUSE_PRESSED) {
touchpad_pressed_ = true;
} else if (mouse_event->type() == ui::ET_MOUSE_RELEASED) {
touchpad_pressed_ = false;
}
}
// Move the head pose if needed.
if (mouse_event->IsRightMouseButton()) {
if (last_drag_x_pixels_ != 0 || last_drag_y_pixels_ != 0) {
float angle_y = 180.f *
((mouse_event->x() - last_drag_x_pixels_) - 0.5f) /
window_size_.width();
float angle_x = 180.f *
((mouse_event->y() - last_drag_y_pixels_) - 0.5f) /
window_size_.height();
head_angle_x_degrees_ += angle_x;
head_angle_y_degrees_ += angle_y;
head_angle_x_degrees_ =
base::ClampToRange(head_angle_x_degrees_, -90.f, 90.f);
}
last_drag_x_pixels_ = mouse_event->x();
last_drag_y_pixels_ = mouse_event->y();
} else {
last_drag_x_pixels_ = 0;
last_drag_y_pixels_ = 0;
}
head_pose_ = gfx::Transform();
head_pose_.RotateAboutXAxis(-head_angle_x_degrees_);
head_pose_.RotateAboutYAxis(-head_angle_y_degrees_);
last_mouse_point_ = gfx::Point(mouse_event->x(), mouse_event->y());
}
ControllerModel VrTestContext::UpdateController(const RenderInfo& render_info,
base::TimeTicks current_time) {
// We could map mouse position to controller position, and skip this logic,
// but it will make targeting elements with a mouse feel strange and not
// mouse-like. Instead, we make the reticle track the mouse position linearly
// by working from reticle position backwards to compute controller position.
// We also don't apply the elbow model (the controller pivots around its
// centroid), so do not expect the positioning of the controller in the test
// app to exactly match what will happen in production.
//
// We first set up a controller model that simulates firing the laser directly
// through a screen pixel. We do this by computing two points behind the mouse
// position in normalized device coordinates. The z components are arbitrary.
gfx::Point3F mouse_point_far(
2.0 * last_mouse_point_.x() / window_size_.width() - 1.0,
-2.0 * last_mouse_point_.y() / window_size_.height() + 1.0, 0.8);
gfx::Point3F mouse_point_near = mouse_point_far;
mouse_point_near.set_z(-0.8);
// We then convert these points into world space via the inverse view proj
// matrix. These points are then used to construct a temporary controller
// model that pretends to be shooting through the pixel at the mouse position.
gfx::Transform inv_view_proj;
CHECK(ViewProjectionMatrix().GetInverse(&inv_view_proj));
inv_view_proj.TransformPoint(&mouse_point_near);
inv_view_proj.TransformPoint(&mouse_point_far);
ControllerModel controller_model;
controller_model.touchpad_button_state =
touchpad_pressed_ ? ControllerModel::ButtonState::kDown
: ControllerModel::ButtonState::kUp;
controller_model.touchpad_touch_position = touchpad_touch_position_;
controller_model.touching_touchpad = touching_touchpad_;
controller_model.recentered = recentered_;
recentered_ = false;
controller_model.laser_origin = mouse_point_near;
controller_model.laser_direction = mouse_point_far - mouse_point_near;
CHECK(controller_model.laser_direction.GetNormalized(
&controller_model.laser_direction));
gfx::Point3F laser_origin = LaserOrigin();
controller_model.transform.Translate3d(laser_origin.x(), laser_origin.y(),
laser_origin.z());
controller_model.transform.Scale3d(
kControllerScaleFactor, kControllerScaleFactor, kControllerScaleFactor);
RotateToward(controller_model.laser_direction, &controller_model.transform);
// Hit testing is done in terms of this synthesized controller model.
if (input_event_lists_.empty()) {
input_event_lists_.push(InputEventList());
}
ReticleModel reticle_model;
ui_->HandleInput(current_time, render_info, controller_model, &reticle_model,
&input_event_lists_.front());
input_event_lists_.pop();
// Now that we have accurate hit information, we use this to construct a
// controller model for display.
controller_model.laser_direction = reticle_model.target_point - laser_origin;
controller_model.transform.MakeIdentity();
controller_model.transform.Translate3d(laser_origin.x(), laser_origin.y(),
laser_origin.z());
controller_model.transform.Scale3d(
kControllerScaleFactor, kControllerScaleFactor, kControllerScaleFactor);
RotateToward(controller_model.laser_direction, &controller_model.transform);
gfx::Vector3dF local_offset = kLaserLocalOffset;
controller_model.transform.TransformVector(&local_offset);
controller_model.laser_origin = laser_origin + local_offset;
controller_model.handedness = handedness_;
std::vector<ControllerModel> controllers;
controllers.push_back(controller_model);
ui_->OnControllersUpdated(controllers, reticle_model);
return controller_model;
}
unsigned int VrTestContext::CreateTexture(SkColor color) {
sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(1, 1);
SkCanvas* canvas = surface->getCanvas();
canvas->clear(color);
SkPixmap pixmap;
CHECK(surface->peekPixels(&pixmap));
SkColorType type = pixmap.colorType();
DCHECK(type == kRGBA_8888_SkColorType || type == kBGRA_8888_SkColorType);
GLint format = (type == kRGBA_8888_SkColorType ? GL_RGBA : GL_BGRA);
unsigned int texture_id;
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, format, pixmap.width(), pixmap.height(), 0,
format, GL_UNSIGNED_BYTE, pixmap.addr());
return texture_id;
}
void VrTestContext::CreateFakeVoiceSearchResult() {
if (!model_->voice_search_active())
return;
auto browser_ui = ui_->GetBrowserUiWeakPtr();
browser_ui->SetRecognitionResult(
base::UTF8ToUTF16("I would like to see cat videos, please."));
browser_ui->SetSpeechRecognitionEnabled(false);
}
void VrTestContext::CycleWebVrModes() {
auto browser_ui = ui_->GetBrowserUiWeakPtr();
switch (model_->web_vr.state) {
case kWebVrNoTimeoutPending: {
web_vr_mode_ = true;
webvr_frames_received_ = false;
browser_ui->SetWebVrMode(true);
break;
}
case kWebVrAwaitingFirstFrame:
ui_->GetSchedulerUiPtr()->OnWebXrTimeoutImminent();
break;
case kWebVrTimeoutImminent:
ui_->GetSchedulerUiPtr()->OnWebXrTimedOut();
break;
case kWebVrTimedOut:
browser_ui->SetWebVrMode(false);
web_vr_mode_ = false;
break;
case kWebVrPresenting:
browser_ui->SetWebVrMode(false);
web_vr_mode_ = false;
break;
default:
break;
}
}
void VrTestContext::ToggleSplashScreen() {
if (!show_web_vr_splash_screen_) {
web_vr_mode_ = true;
webvr_frames_received_ = false;
UiInitialState state;
state.in_web_vr = true;
ui_instance_->ReinitializeForTest(state);
} else {
ui_instance_->ReinitializeForTest(UiInitialState());
}
show_web_vr_splash_screen_ = !show_web_vr_splash_screen_;
}
gfx::Transform VrTestContext::ProjectionMatrix() const {
gfx::Transform transform(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0.5);
if (window_size_.height() > 0) {
transform.Scale(
view_scale_factor_,
view_scale_factor_ * window_size_.width() / window_size_.height());
}
return transform;
}
gfx::Transform VrTestContext::ViewProjectionMatrix() const {
return ProjectionMatrix() * head_pose_;
}
void VrTestContext::SetVoiceSearchActive(bool active) {
if (!voice_search_enabled_) {
OnUnsupportedMode(
UiUnsupportedMode::kVoiceSearchNeedsRecordAudioOsPermission);
return;
}
auto browser_ui = ui_->GetBrowserUiWeakPtr();
browser_ui->SetSpeechRecognitionEnabled(active);
if (active)
browser_ui->OnSpeechRecognitionStateChanged(SPEECH_RECOGNITION_RECOGNIZING);
}
void VrTestContext::ExitPresent() {
web_vr_mode_ = false;
ui_->GetBrowserUiWeakPtr()->SetWebVrMode(false);
}
void VrTestContext::ExitFullscreen() {
fullscreen_ = false;
ui_->GetBrowserUiWeakPtr()->SetFullscreen(false);
}
void VrTestContext::Navigate(GURL gurl, NavigationMethod method) {
LocationBarState state(gurl, security_state::SecurityLevel::WARNING,
&omnibox::kHttpIcon, true, false);
ui_->GetBrowserUiWeakPtr()->SetLocationBarState(state);
page_load_start_ = base::TimeTicks::Now();
}
void VrTestContext::NavigateBack() {
page_load_start_ = base::TimeTicks::Now();
model_->can_navigate_back = false;
model_->can_navigate_forward = true;
}
void VrTestContext::NavigateForward() {
page_load_start_ = base::TimeTicks::Now();
model_->can_navigate_back = true;
model_->can_navigate_forward = false;
}
void VrTestContext::ReloadTab() {
page_load_start_ = base::TimeTicks::Now();
}
void VrTestContext::OpenNewTab(bool incognito) {
incognito_ = incognito;
auto browser_ui = ui_->GetBrowserUiWeakPtr();
browser_ui->SetIncognito(incognito);
model_->incognito_tabs_open = model_->incognito_tabs_open || incognito;
}
void VrTestContext::OpenBookmarks() {}
void VrTestContext::OpenRecentTabs() {}
void VrTestContext::OpenHistory() {}
void VrTestContext::OpenDownloads() {}
void VrTestContext::OpenShare() {}
void VrTestContext::OpenSettings() {}
void VrTestContext::CloseAllIncognitoTabs() {
incognito_ = false;
ui_->GetBrowserUiWeakPtr()->SetIncognito(false);
model_->incognito_tabs_open = false;
}
void VrTestContext::OpenFeedback() {}
void VrTestContext::OnUnsupportedMode(vr::UiUnsupportedMode mode) {
if (mode == UiUnsupportedMode::kVoiceSearchNeedsRecordAudioOsPermission) {
ui_->GetBrowserUiWeakPtr()->ShowExitVrPrompt(mode);
}
}
void VrTestContext::CloseHostedDialog() {
ui_->SetAlertDialogEnabled(false, nullptr, 0, 0);
hosted_ui_enabled_ = false;
}
void VrTestContext::OnExitVrPromptResult(vr::ExitVrPromptChoice choice,
vr::UiUnsupportedMode reason) {
DCHECK_NE(reason, UiUnsupportedMode::kCount);
if (reason == UiUnsupportedMode::kVoiceSearchNeedsRecordAudioOsPermission &&
choice == CHOICE_EXIT) {
voice_search_enabled_ = true;
}
}
void VrTestContext::OnContentScreenBoundsChanged(const gfx::SizeF& bounds) {}
void VrTestContext::StartAutocomplete(const AutocompleteRequest& request) {
std::vector<OmniboxSuggestion> result;
auto browser_ui = ui_->GetBrowserUiWeakPtr();
if (request.text.empty()) {
browser_ui->SetOmniboxSuggestions(std::move(result));
return;
}
// Supply an in-line match if the input matches a canned URL.
base::string16 full_string = base::UTF8ToUTF16("wikipedia.org");
if (!request.prevent_inline_autocomplete && request.text.size() >= 2 &&
full_string.find(request.text) == 0) {
result.emplace_back(full_string, base::string16(), ACMatchClassifications(),
ACMatchClassifications(), &vector_icons::kSearchIcon,
GURL(), request.text,
full_string.substr(request.text.size()));
}
// Supply a verbatim search match.
result.emplace_back(request.text, base::string16(), ACMatchClassifications(),
ACMatchClassifications(), &vector_icons::kSearchIcon,
GURL(), base::string16(), base::string16());
// Add a suggestion to exercise classification text styling.
result.emplace_back(
base::UTF8ToUTF16("Suggestion with classification"),
base::UTF8ToUTF16("none url match dim"), ACMatchClassifications(),
ACMatchClassifications{
ACMatchClassification(0, ACMatchClassification::NONE),
ACMatchClassification(5, ACMatchClassification::URL),
ACMatchClassification(9, ACMatchClassification::MATCH),
ACMatchClassification(15, ACMatchClassification::DIM),
},
&vector_icons::kSearchIcon, GURL("http://www.test.com/"),
base::string16(), base::string16());
while (result.size() < 4) {
result.emplace_back(
base::UTF8ToUTF16("Suggestion"),
base::UTF8ToUTF16(
"Very lengthy description of the suggestion that would wrap "
"if not truncated through some other means."),
ACMatchClassifications(), ACMatchClassifications(),
&vector_icons::kSearchIcon, GURL("http://www.test.com/"),
base::string16(), base::string16());
}
browser_ui->SetOmniboxSuggestions(std::move(result));
}
void VrTestContext::StopAutocomplete() {
ui_->GetBrowserUiWeakPtr()->SetOmniboxSuggestions(
std::vector<OmniboxSuggestion>{});
}
void VrTestContext::ShowPageInfo() {
ui_->GetBrowserUiWeakPtr()->ShowExitVrPrompt(
UiUnsupportedMode::kUnhandledPageInfo);
}
void VrTestContext::CycleIndicators() {
static size_t state = 0;
const std::vector<CapturingStateModelMemberPtr> signals = {
&CapturingStateModel::location_access_enabled,
&CapturingStateModel::audio_capture_enabled,
&CapturingStateModel::video_capture_enabled,
&CapturingStateModel::bluetooth_connected,
&CapturingStateModel::screen_capture_enabled};
state = (state + 1) % (1 << (signals.size() + 1));
for (size_t i = 0; i < signals.size(); ++i) {
model_->active_capturing.*signals[i] = state & (1 << i);
}
}
void VrTestContext::CycleOrigin() {
const std::vector<LocationBarState> states = {
{GURL("http://domain.com"), security_state::SecurityLevel::WARNING,
&omnibox::kHttpIcon, true, false},
{GURL("https://www.domain.com/path/segment/directory/file.html"),
security_state::SecurityLevel::SECURE, &omnibox::kHttpsValidIcon, true,
false},
{GURL("https://www.domain.com/path/segment/directory/file.html"),
security_state::SecurityLevel::DANGEROUS,
&omnibox::kNotSecureWarningIcon, true, false},
// Do not show URL
{GURL(), security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon,
false, false},
{GURL(), security_state::SecurityLevel::SECURE, &omnibox::kHttpsValidIcon,
true, false},
{GURL("file://very-very-very-long-file-hostname/path/path/path/path"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
{GURL("file:///path/path/path/path/path/path/path/path/path"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
// Elision-related cases.
{GURL("http://domaaaaaaaaaaain.com"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
{GURL("http://domaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaain.com"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
{GURL("http://domain.com/a/"), security_state::SecurityLevel::WARNING,
&omnibox::kHttpIcon, true, false},
{GURL("http://domain.com/aaaaaaa/"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
{GURL("http://domain.com/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
{GURL("http://domaaaaaaaaaaaaaaaaain.com/aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
{GURL("http://domaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaain.com/aaaaaaaaaa/"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
{GURL("http://www.domain.com/path/segment/directory/file.html"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
{GURL("http://subdomain.domain.com/"),
security_state::SecurityLevel::WARNING, &omnibox::kHttpIcon, true,
false},
{GURL("http://中央大学.ಠ_ಠ.tw/"), security_state::SecurityLevel::WARNING,
&omnibox::kHttpIcon, true, false},
};
static int state = 0;
ui_->GetBrowserUiWeakPtr()->SetLocationBarState(states[state]);
state = (state + 1) % states.size();
}
RenderInfo VrTestContext::GetRenderInfo() const {
RenderInfo render_info;
render_info.head_pose = head_pose_;
render_info.left_eye_model.viewport = gfx::Rect(window_size_);
render_info.left_eye_model.view_matrix = head_pose_;
render_info.left_eye_model.proj_matrix = ProjectionMatrix();
render_info.left_eye_model.view_proj_matrix = ViewProjectionMatrix();
render_info.right_eye_model = render_info.left_eye_model;
return render_info;
}
gfx::Point3F VrTestContext::LaserOrigin() const {
gfx::Point3F origin = kDefaultLaserOrigin;
if (handedness_ == ControllerModel::kLeftHanded) {
origin.set_x(-origin.x());
}
return origin;
}
void VrTestContext::LoadAssets() {
base::Version assets_component_version(VR_ASSETS_COMPONENT_VERSION);
auto assets = std::make_unique<Assets>();
if (!(LoadPng(IDR_VR_BACKGROUND_IMAGE, &assets->background) &&
LoadPng(IDR_VR_NORMAL_GRADIENT_IMAGE, &assets->normal_gradient) &&
LoadPng(IDR_VR_INCOGNITO_GRADIENT_IMAGE, &assets->incognito_gradient) &&
LoadPng(IDR_VR_FULLSCREEN_GRADIENT_IMAGE,
&assets->fullscreen_gradient))) {
ui_->GetBrowserUiWeakPtr()->OnAssetsLoaded(
AssetsLoadStatus::kInvalidContent, nullptr, assets_component_version);
return;
}
ui_->GetBrowserUiWeakPtr()->OnAssetsLoaded(
AssetsLoadStatus::kSuccess, std::move(assets), assets_component_version);
}
} // namespace vr