blob: 0305a8645ea4c0d18df0436d3d324e381e5f4e62 [file] [log] [blame]
# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import time
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.video import method_logger
class VideoPlayer(object):
"""
Provides interface to interact with and control video playback via js.
"""
@method_logger.log
def __init__(self, tab, full_url, video_src_path, video_id,
time_out_for_events_s, time_btwn_polling_s):
"""
@param tab: object, tab to interact with the tab in the browser.
@param full_url: string, full url pointing to html file to load.
@param video_src_path: path, complete path to video used for test.
@param video_id: string, name of the video_id element in the html file.
@param time_out_for_events_s: integer, how long to wait for an event
before timing out
@param time_btwn_polling_s: integer, how long to wait between one call
to check a condition and the next.
"""
self.tab = tab
self.full_url = full_url
self.video_source_path = video_src_path
self.video_id = video_id
self.time_out_for_events_s = time_out_for_events_s
self.time_btwn_polling_s = time_btwn_polling_s
@method_logger.log
def load_video(self):
"""
Loads video and waits for video to be ready to play.
"""
self.tab.Navigate(self.full_url)
self._wait_for_page_to_load()
# Set video source to desired path in the html file.
self.tab.ExecuteJavaScript(
'loadVideoSource("%s")' % self.video_source_path)
self._wait_for_canplay_event()
@method_logger.log
def seek_video_to_timestamp(self, timestamp):
"""
Uses javascript to set currentTime property of video to desired time.
@param timestamp: timedelta, instance of time to navigate video to.
"""
cmd = "%s.currentTime=%.3f" % (
self.video_id, timestamp.total_seconds())
self.tab.ExecuteJavaScript(cmd)
@method_logger.log
def wait_for_video_to_seek(self):
"""
Waits for the javascript 'seeked' event.
"""
def has_video_finished_seeking():
"""
Helper function to get video seeking status via javascript.
"""
return self.tab.EvaluateJavaScript('finishedSeeking()')
exception_msg = 'Video did not complete seeking in time.'
self._wait_for_event(has_video_finished_seeking, exception_msg)
# TODO: Fix this.
# There is a lag between assigning a value to the currentTimeElement
# and the new assigned value being displayed.
# TODO: Wait for 100ms once crosbug.com/p/32518 is fixed
time.sleep(1.5)
@method_logger.log
def _wait_for_page_to_load(self):
"""
Waits for javascript objects to be defined.
When we a valid video object we say the page is ready to accept more
commands.
"""
def has_page_loaded():
"""
Uses javascript to check if page objects have been defined.
If objects are defined then we know we are able to execute further
commands in the page.
"""
result = self.tab.EvaluateJavaScript('(typeof %s)' % self.video_id)
return result != 'undefined'
exception_msg = 'HTML page did not load at url : %s' % self.full_url
self._wait_for_event(has_page_loaded, exception_msg)
@method_logger.log
def _wait_for_canplay_event(self):
"""
Waits for the javascript 'canplay' event.
"""
def can_play_video():
"""
Uses javascript to check if the 'canplay' event was raised.
Executing the javascript 'canplay()' function we return the value of
a bool variable set to true when the canplay event is raised.
"""
return self.tab.EvaluateJavaScript('canplay()')
exception_msg = 'canplay event was not received in time'
self._wait_for_event(can_play_video, exception_msg)
@method_logger.log
def _wait_for_event(self, predicate_function, exception_msg):
"""
Helper method to wait for a desired condition.
@param predicate_function: object, function which returns true when
desired condition is achieved.
@param exception_msg: string, an exception message to show when desired
condition is not achieved in allowed time.
"""
fullmsg = exception_msg + ' Waited for %ss' % self.time_out_for_events_s
utils.poll_for_condition(predicate_function,
error.TestError(fullmsg),
self.time_out_for_events_s,
self.time_btwn_polling_s)