# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from telemetry import story
from telemetry import page
from contrib.vr_benchmarks import (shared_vr_page_state as vr_state)
from contrib.vr_benchmarks.vr_story_set import VrStorySet
class WebVrWprPage(page.Page):
"""Class for running a story on a WebVR WPR page."""
def __init__(self, page_set, url, name, interaction_function,
extra_browser_args=None):
"""
Args:
page_set: The StorySet the WebVrWprPage is being added to
url: The URL to navigate to for the story
name: The name of the story
interaction_function: A pointer to a function that takes an ActionRunner
and boolean indicating whether a WPR archive is being recorded. Meant
to handle webpage-specific VR entry
extra_browser_args: Extra browser args that are simply forwarded to
page.Page
"""
super(WebVrWprPage, self).__init__(
url=url,
page_set=page_set,
name=name,
extra_browser_args=extra_browser_args,
shared_page_state_class=vr_state.SharedVrPageStateFactory)
self._shared_page_state = None
self._interaction_function = interaction_function
def RunPageInteractions(self, action_runner):
if self._interaction_function:
self._interaction_function(action_runner, self.recording_wpr)
action_runner.MeasureMemory(True)
if self._shared_page_state.ShouldNavigateToBlankPageBeforeFinishing():
action_runner.Navigate("about:blank")
def Run(self, shared_state):
self._shared_page_state = shared_state
super(WebVrWprPage, self).Run(shared_state)
@property
def platform(self):
return self._shared_page_state.platform
@property
def recording_wpr(self):
return self._shared_page_state.recording_wpr
class WebVrWprPageSet(VrStorySet):
"""A page set using live WebVR sites recorded using WPR."""
def __init__(self, use_fake_pose_tracker=True):
super(WebVrWprPageSet, self).__init__(
archive_data_file='data/webvr_wpr.json',
cloud_storage_bucket=story.PARTNER_BUCKET,
use_fake_pose_tracker=use_fake_pose_tracker)
# View the Pirates: Dock model on Sketchfab
def SketchfabInteraction(action_runner, _):
action_runner.WaitForNetworkQuiescence(timeout_in_seconds=20)
action_runner.WaitForElement(selector='a[data-tooltip="View in VR"]')
action_runner.TapElement(selector='a[data-tooltip="View in VR"]')
self.AddStory(WebVrWprPage(
self,
'https://sketchfab.com/models/uFqGJrS9ZjVr9Myk9kg4fubPNPz',
'sketchfab_pirates_dock',
SketchfabInteraction))
# Watch part of the Invasion Episode 1 video on With.in
def WithinInvasionInteraction(action_runner, recording_wpr):
action_runner.WaitForNetworkQuiescence()
action_runner.TapElement(selector='div.play-button')
action_runner.TapElement(selector='div.right.stereo')
# Make sure we get enough streaming video during WPR recording to not run
# into issues when actually running the benchmark
if recording_wpr:
action_runner.Wait(30)
self.AddStory(WebVrWprPage(
self,
# Access the video directly to more easily set resolution and avoid
# iframe weirdness
'https://player.with.in/embed/?id=272&resolution=2880&forced=false&'
'autoplay=true&t=0&internal=true',
'within_invasion_ep_1',
WithinInvasionInteraction))
# Watch a girl running through a giant forest (I think) in Under Neon Lights
# Note that this is semi-broken in that it doesn't move away from the
# opening when you enter VR, but we're still viewing a relatively complex
# WebGL scene, so it's still useful for perf testing
def UnderNeonLightsInteraction(action_runner, _):
action_runner.WaitForNetworkQuiescence(timeout_in_seconds=30)
# The VR button doesn't have any unique ID or anything, so instead select
# based on the unique text in a child div
action_runner.WaitForElement(text='Start in VR')
action_runner.TapElement(text='Start in VR')
self.AddStory(WebVrWprPage(
self,
# Access the content directly to avoid iframe weirdness
'https://player.with.in/embed/?id=541&resolution=1920&forced=false&'
'autoplay=true&t=0&internal=true',
'under_neon_lights',
UnderNeonLightsInteraction))
class WebVrLivePageSet(WebVrWprPageSet):
"""A superset of the WPR page set.
Also contains sites that we would like to run with WPR, but that interact
badly when replayed. So, access the live version instead.
"""
def __init__(self, use_fake_pose_tracker=True):
super(WebVrLivePageSet, self).__init__(
use_fake_pose_tracker=use_fake_pose_tracker)
# Look at "randomly" generated (constant seed) geometry in Mass Migrations
# Not usable via WPR due to it often not submitting frames while using WPR
def MassMigrationsInteraction(action_runner, _):
action_runner.WaitForNetworkQuiescence()
# All DOM elements seem to be present on the page from the start, so
# instead wait until the button is actually visible
action_runner.WaitForJavaScriptCondition(
condition='document.querySelector(\'div[id="footer"]\').style.display'
'== "block"')
action_runner.TapElement(selector='a[id="vr"]')
self.AddStory(WebVrWprPage(
self,
# The /iaped is necessary to keep the geometry constant, as it acts as
# the seed for the generator - just visiting the site randomly generates
# geometry
'https://massmigrations.com/iaped',
'mass_migrations',
MassMigrationsInteraction))
# Watch dancing polyhedrons in Dance Tonite
# Not usable via WPR due to weird rendering issues (incorrect colors,
# missing geometry, etc.) that are present when using WPR
def DanceToniteInteraction(action_runner, _):
action_runner.WaitForNetworkQuiescence()
action_runner.WaitForElement(selector='div.button-play')
action_runner.TapElement(selector='div.button-play')
action_runner.WaitForNetworkQuiescence()
# The VR entry button has no unique text, ID, etc. but does have a child
# SVG with a child path with a unique "d" attribute. It's super long, so
# only match against one part of it
action_runner.WaitForElement(selector='path[d~="M52.6"]')
action_runner.TapElement(selector='path[d~="M52.6"]')
self.AddStory(WebVrWprPage(
self,
'https://tonite.dance',
'dance_tonite',
DanceToniteInteraction))