Import Cobalt 9.89162
diff --git a/src/cobalt/browser/stack_size_constants.h b/src/cobalt/browser/stack_size_constants.h
index d6b33fc..3d7d7d2 100644
--- a/src/cobalt/browser/stack_size_constants.h
+++ b/src/cobalt/browser/stack_size_constants.h
@@ -21,12 +21,12 @@
namespace browser {
#if defined(COBALT_BUILD_TYPE_DEBUG)
// Non-optimized builds require a bigger stack size.
- const size_t kBaseStackSize = 2 * 1024 * 1024;
+ const size_t kBaseStackSize = 3 * 1024 * 1024;
#elif defined(COBALT_BUILD_TYPE_DEVEL)
// Devel builds require a slightly bigger stack size.
- const size_t kBaseStackSize = 448 * 1024;
+ const size_t kBaseStackSize = 832 * 1024;
#else
- const size_t kBaseStackSize = 384 * 1024;
+ const size_t kBaseStackSize = 768 * 1024;
#endif
const size_t kWebModuleStackSize =
kBaseStackSize + base::kAsanAdditionalStackSize;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 7b38425..1bb91e9 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-76656
\ No newline at end of file
+89162
\ No newline at end of file
diff --git a/src/cobalt/css_parser/grammar.y b/src/cobalt/css_parser/grammar.y
index 86a9ca0..063c59c 100644
--- a/src/cobalt/css_parser/grammar.y
+++ b/src/cobalt/css_parser/grammar.y
@@ -6257,7 +6257,6 @@
std::string property_name = $1.ToString();
DCHECK_GT(property_name.size(), 0U);
-#ifdef __LB_SHELL__FORCE_LOGGING__
// Do not warn about non-standard or non-WebKit properties.
if (property_name[0] != '-') {
base::AutoLock lock(non_trivial_static_fields.Get().lock);
@@ -6270,7 +6269,6 @@
parser_impl->LogWarning(@1, "unsupported property " + property_name);
}
}
-#endif // __LB_SHELL__FORCE_LOGGING__
$$ = NULL;
}
diff --git a/src/cobalt/css_parser/parser.cc b/src/cobalt/css_parser/parser.cc
index 7be1525..086782c 100644
--- a/src/cobalt/css_parser/parser.cc
+++ b/src/cobalt/css_parser/parser.cc
@@ -229,7 +229,6 @@
};
// TODO: Stop deduplicating warnings.
-#ifdef __LB_SHELL__FORCE_LOGGING__
namespace {
struct NonTrivialStaticFields {
@@ -242,7 +241,6 @@
LAZY_INSTANCE_INITIALIZER;
} // namespace
-#endif // __LB_SHELL__FORCE_LOGGING__
ParserImpl::ParserImpl(const std::string& input,
const base::SourceLocation& input_location,
diff --git a/src/cobalt/debug/debug_web_server.cc b/src/cobalt/debug/debug_web_server.cc
index 76b371f..6ffd152 100644
--- a/src/cobalt/debug/debug_web_server.cc
+++ b/src/cobalt/debug/debug_web_server.cc
@@ -80,21 +80,11 @@
return base::nullopt;
}
-std::string GetLocalIpAddress() {
+base::optional<std::string> GetLocalIpAddress() {
net::IPEndPoint ip_addr;
-#if defined(__LB_SHELL__)
- struct sockaddr_in addr = {0};
- addr.sin_family = AF_INET;
- lb_get_local_ip_address(&addr.sin_addr);
- bool result =
- ip_addr.FromSockAddr(reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
- DCHECK(result);
-#elif defined(OS_STARBOARD)
-
-#if SB_API_VERSION >= 4
SbSocketAddress local_ip;
- SbMemorySet(&(local_ip.address), 0, sizeof(local_ip.address));
-
+ SbMemorySet(&local_ip, 0, sizeof(local_ip));
+#if SB_API_VERSION >= 4
bool result = false;
// Prefer IPv4 addresses, as they're easier to type for debugging.
@@ -115,17 +105,24 @@
}
}
- DCHECK(result);
+ if (!result) {
+ DLOG(WARNING) << "Unable to get a local interface address.";
+ return base::nullopt;
+ }
#else
- SbSocketAddress sb_address;
- bool result = SbSocketGetLocalInterfaceAddress(&sb_address);
- DCHECK(result);
- result = ip_addr.FromSbSocketAddress(&sb_address);
+ bool result = SbSocketGetLocalInterfaceAddress(&local_ip);
+ if (!result) {
+ DLOG(WARNING) << "Unable to get a local interface address.";
+ return base::nullopt;
+ }
+
+ result = ip_addr.FromSbSocketAddress(&local_ip);
+ if (!result) {
+ LOG(WARNING) << "Got invalid local interface address.";
+ return base::nullopt;
+ }
#endif // SB_API_VERSION >= 4
-#else
-#error "Not Implemented."
-#endif
return ip_addr.ToStringWithoutPort();
}
@@ -339,8 +336,13 @@
DCHECK(thread_checker_.CalledOnValidThread());
// Create http server
- const std::string ip_addr = GetLocalIpAddress();
- factory_.reset(new net::TCPListenSocketFactory(ip_addr, port));
+ const base::optional<std::string> ip_addr = GetLocalIpAddress();
+ if (!ip_addr) {
+ DLOG(WARNING)
+ << "Could not get a local IP address for the debug web server.";
+ return;
+ }
+ factory_.reset(new net::TCPListenSocketFactory(*ip_addr, port));
server_ = new net::HttpServer(*factory_, this);
std::string address;
diff --git a/src/cobalt/loader/image/animated_webp_image.cc b/src/cobalt/loader/image/animated_webp_image.cc
index eef28b9..123d945 100644
--- a/src/cobalt/loader/image/animated_webp_image.cc
+++ b/src/cobalt/loader/image/animated_webp_image.cc
@@ -51,7 +51,6 @@
frame_count_(0),
loop_count_(kLoopInfinite),
current_frame_index_(0),
- next_frame_index_(0),
should_dispose_previous_frame_to_background_(false),
resource_provider_(resource_provider),
frame_provider_(new FrameProvider()) {
@@ -59,7 +58,7 @@
"AnimatedWebPImage::AnimatedWebPImage()");
}
-scoped_refptr<const AnimatedImage::FrameProvider>
+scoped_refptr<AnimatedImage::FrameProvider>
AnimatedWebPImage::GetFrameProvider() {
TRACE_EVENT0("cobalt::loader::image",
"AnimatedWebPImage::GetFrameProvider()");
@@ -178,25 +177,25 @@
base::Bind(&AnimatedWebPImage::DecodeFrames, base::Unretained(this)));
}
- UpdateTimelineInfo();
-
- // Decode the frames from current frame to next frame and blend the results.
- for (int frame_index = current_frame_index_ + 1;
- frame_index <= next_frame_index_; ++frame_index) {
- if (!DecodeOneFrame(frame_index)) {
- break;
- }
+ if (AdvanceFrame()) {
+ // Decode the frames from current frame to next frame and blend the results.
+ DecodeOneFrame(current_frame_index_);
}
- current_frame_index_ = next_frame_index_;
// Set up the next time to call the decode callback.
if (is_playing_) {
- base::TimeDelta delay = next_frame_time_ - base::TimeTicks::Now();
const base::TimeDelta min_delay =
base::TimeDelta::FromMilliseconds(kMinimumDelayInMilliseconds);
- if (delay < min_delay) {
+ base::TimeDelta delay;
+ if (next_frame_time_) {
+ delay = *next_frame_time_ - base::TimeTicks::Now();
+ if (delay < min_delay) {
+ delay = min_delay;
+ }
+ } else {
delay = min_delay;
}
+
message_loop_->PostDelayedTask(FROM_HERE, decode_closure_.callback(),
delay);
}
@@ -294,44 +293,78 @@
return true;
}
-void AnimatedWebPImage::UpdateTimelineInfo() {
- TRACE_EVENT0("cobalt::loader::image",
- "AnimatedWebPImage::UpdateTimelineInfo()");
+bool AnimatedWebPImage::AdvanceFrame() {
+ TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::AdvanceFrame()");
TRACK_MEMORY_SCOPE("Rendering");
DCHECK(message_loop_->BelongsToCurrentThread());
lock_.AssertAcquired();
base::TimeTicks current_time = base::TimeTicks::Now();
- next_frame_index_ = current_frame_index_ ? current_frame_index_ : 1;
- while (true) {
- // Decode frames, until a frame such that the duration covers the current
- // time, i.e. the next frame should be displayed in the future.
- WebPIterator webp_iterator;
- WebPDemuxGetFrame(demux_, next_frame_index_, &webp_iterator);
- next_frame_time_ = current_frame_time_ + base::TimeDelta::FromMilliseconds(
- webp_iterator.duration);
- WebPDemuxReleaseIterator(&webp_iterator);
- if (current_time < next_frame_time_) {
- break;
+
+ // If the WebP image hasn't been fully fetched, then stop on the current
+ // frame.
+ if (demux_state_ == WEBP_DEMUX_PARSED_HEADER) {
+ return false;
+ }
+
+ // If we're done playing the animation, do nothing.
+ if (LoopingFinished()) {
+ return false;
+ }
+
+ // If it's still not time to advance to the next frame, do nothing.
+ if (next_frame_time_ && current_time < *next_frame_time_) {
+ return false;
+ }
+
+ // Always wait for a consumer to consume the previous frame before moving
+ // forward with decoding the next frame.
+ if (!frame_provider_->FrameConsumed()) {
+ return false;
+ }
+
+ if (next_frame_time_) {
+ current_frame_time_ = *next_frame_time_;
+ } else {
+ current_frame_time_ = current_time;
+ }
+
+ ++current_frame_index_;
+ if (current_frame_index_ == frame_count_) {
+ // Check if we have finished looping, and if so return indicating that there
+ // is no additional frame available.
+ if (LoopingFinished()) {
+ next_frame_time_ = base::nullopt;
+ return false;
}
- current_frame_time_ = next_frame_time_;
- if (next_frame_index_ < frame_count_) {
- next_frame_index_++;
- } else {
- DCHECK_EQ(next_frame_index_, frame_count_);
- // If the WebP image hasn't been fully fetched, or we've reached the end
- // of the last loop, then stop on the current frame.
- if (demux_state_ == WEBP_DEMUX_PARSED_HEADER || loop_count_ == 1) {
- break;
- }
- next_frame_index_ = 1;
- current_frame_index_ = 0;
- if (loop_count_ != kLoopInfinite) {
- loop_count_--;
- }
+ // Loop around to the beginning
+ current_frame_index_ = 0;
+ if (loop_count_ != kLoopInfinite) {
+ loop_count_--;
}
}
+
+ // Update the time in the future at which point we should switch to the
+ // frame after the new current frame.
+ next_frame_time_ =
+ current_frame_time_ + GetFrameDuration(current_frame_index_);
+ if (next_frame_time_ < current_time) {
+ // Don't let the animation fall back for more than a frame.
+ next_frame_time_ = current_time;
+ }
+
+ return true;
+}
+
+base::TimeDelta AnimatedWebPImage::GetFrameDuration(int frame_index) {
+ lock_.AssertAcquired();
+ WebPIterator webp_iterator;
+ WebPDemuxGetFrame(demux_, frame_index, &webp_iterator);
+ base::TimeDelta frame_duration =
+ base::TimeDelta::FromMilliseconds(webp_iterator.duration);
+ WebPDemuxReleaseIterator(&webp_iterator);
+ return frame_duration;
}
scoped_ptr<render_tree::ImageData> AnimatedWebPImage::AllocateImageData(
@@ -346,6 +379,10 @@
return image_data.Pass();
}
+bool AnimatedWebPImage::LoopingFinished() const {
+ return loop_count_ == 1 && current_frame_index_ == frame_count_;
+}
+
} // namespace image
} // namespace loader
} // namespace cobalt
diff --git a/src/cobalt/loader/image/animated_webp_image.h b/src/cobalt/loader/image/animated_webp_image.h
index 179d42e..8714c46 100644
--- a/src/cobalt/loader/image/animated_webp_image.h
+++ b/src/cobalt/loader/image/animated_webp_image.h
@@ -45,18 +45,21 @@
const math::Size& GetSize() const OVERRIDE { return size_; }
uint32 GetEstimatedSizeInBytes() const OVERRIDE {
- return static_cast<uint32>(data_buffer_.size());
+ // Return the size of 2 frames of images, since we can have two frames in
+ // memory at a time (the previous decode image passed to the frame provider
+ // and the next frame that is composed from the previous frame).
+ return size_.GetArea() * 4 * 2 + static_cast<uint32>(data_buffer_.size());
}
bool IsOpaque() const OVERRIDE { return is_opaque_; }
- scoped_refptr<const FrameProvider> GetFrameProvider() OVERRIDE;
+ scoped_refptr<FrameProvider> GetFrameProvider() OVERRIDE;
void Play(const scoped_refptr<base::MessageLoopProxy>& message_loop) OVERRIDE;
void Stop() OVERRIDE;
- void AppendChunk(const uint8* data, size_t size);
+ void AppendChunk(const uint8* data, size_t input_byte);
private:
~AnimatedWebPImage() OVERRIDE;
@@ -72,11 +75,17 @@
// Decodes the frame with the given index, returns if it succeeded.
bool DecodeOneFrame(int frame_index);
- // Updates the index and time info of the current and next frames.
- void UpdateTimelineInfo();
-
scoped_ptr<render_tree::ImageData> AllocateImageData(const math::Size& size);
+ // If the time is right, updates the index and time info of the current frame.
+ bool AdvanceFrame();
+
+ // Returns the duration of the given frame index.
+ base::TimeDelta GetFrameDuration(int frame_index);
+
+ // Returns true if the animation loop is finished.
+ bool LoopingFinished() const;
+
const math::Size size_;
const bool is_opaque_;
const render_tree::PixelFormat pixel_format_;
@@ -89,7 +98,6 @@
// looping infinitely.
int loop_count_;
int current_frame_index_;
- int next_frame_index_;
bool should_dispose_previous_frame_to_background_;
render_tree::ResourceProvider* resource_provider_;
scoped_refptr<base::MessageLoopProxy> message_loop_;
@@ -98,7 +106,7 @@
math::RectF previous_frame_rect_;
base::CancelableClosure decode_closure_;
base::TimeTicks current_frame_time_;
- base::TimeTicks next_frame_time_;
+ base::optional<base::TimeTicks> next_frame_time_;
// The original encoded data.
std::vector<uint8> data_buffer_;
scoped_refptr<render_tree::Image> current_canvas_;
diff --git a/src/cobalt/loader/image/image.h b/src/cobalt/loader/image/image.h
index fe77dac..2b72010 100644
--- a/src/cobalt/loader/image/image.h
+++ b/src/cobalt/loader/image/image.h
@@ -88,13 +88,22 @@
// that was in there.
class FrameProvider : public base::RefCountedThreadSafe<FrameProvider> {
public:
+ FrameProvider() : frame_consumed_(true) {}
+
void SetFrame(const scoped_refptr<render_tree::Image>& frame) {
base::AutoLock lock(mutex_);
frame_ = frame;
+ frame_consumed_ = false;
}
- scoped_refptr<render_tree::Image> GetFrame() const {
+ bool FrameConsumed() const {
base::AutoLock lock(mutex_);
+ return frame_consumed_;
+ }
+
+ scoped_refptr<render_tree::Image> GetFrame() {
+ base::AutoLock lock(mutex_);
+ frame_consumed_ = true;
return frame_;
}
@@ -103,6 +112,9 @@
friend class base::RefCountedThreadSafe<FrameProvider>;
mutable base::Lock mutex_;
+ // True if a call to FrameConsumed() has been made after the last call to
+ // SetFrame().
+ bool frame_consumed_;
scoped_refptr<render_tree::Image> frame_;
};
@@ -121,11 +133,11 @@
// Returns a FrameProvider object from which frames can be pulled out of.
// The AnimatedImage object is expected to push frames into the FrameProvider
// as it generates them.
- virtual scoped_refptr<const FrameProvider> GetFrameProvider() = 0;
+ virtual scoped_refptr<FrameProvider> GetFrameProvider() = 0;
// This callback is intended to be used in a render_tree::AnimateNode.
static void AnimateCallback(
- scoped_refptr<const FrameProvider> frame_provider,
+ scoped_refptr<FrameProvider> frame_provider,
const math::RectF& destination_rect,
const math::Matrix3F& local_transform,
render_tree::ImageNode::Builder* image_node_builder,
diff --git a/src/cobalt/loader/image/image_data_decoder.cc b/src/cobalt/loader/image/image_data_decoder.cc
index af95b3b..a7a1920 100644
--- a/src/cobalt/loader/image/image_data_decoder.cc
+++ b/src/cobalt/loader/image/image_data_decoder.cc
@@ -67,8 +67,13 @@
}
size_t decoded_size = DecodeChunkInternal(input_bytes, input_size);
- size_t undecoded_size = input_size - decoded_size;
+ if (decoded_size == 0 && offset < size) {
+ LOG(ERROR) << "Unable to make progress decoding image.";
+ state_ = kError;
+ return;
+ }
+ size_t undecoded_size = input_size - decoded_size;
if (undecoded_size == 0) {
// Remove all elements from the data_buffer.
data_buffer_.clear();
diff --git a/src/cobalt/loader/image/image_decoder_test.cc b/src/cobalt/loader/image/image_decoder_test.cc
index 7f995fc..fda87ed 100644
--- a/src/cobalt/loader/image/image_decoder_test.cc
+++ b/src/cobalt/loader/image/image_decoder_test.cc
@@ -674,7 +674,7 @@
thread.Stop();
// The image should contain the whole undecoded data from the file.
- EXPECT_EQ(3224674u, animated_webp_image->GetEstimatedSizeInBytes());
+ EXPECT_EQ(4261474u, animated_webp_image->GetEstimatedSizeInBytes());
EXPECT_EQ(math::Size(480, 270), animated_webp_image->GetSize());
EXPECT_TRUE(animated_webp_image->IsOpaque());
@@ -705,7 +705,7 @@
thread.Stop();
// The image should contain the whole undecoded data from the file.
- EXPECT_EQ(3224674u, animated_webp_image->GetEstimatedSizeInBytes());
+ EXPECT_EQ(4261474u, animated_webp_image->GetEstimatedSizeInBytes());
EXPECT_EQ(math::Size(480, 270), animated_webp_image->GetSize());
EXPECT_TRUE(animated_webp_image->IsOpaque());
diff --git a/src/cobalt/loader/image/webp_image_decoder.cc b/src/cobalt/loader/image/webp_image_decoder.cc
index d587e79..5c803bc 100644
--- a/src/cobalt/loader/image/webp_image_decoder.cc
+++ b/src/cobalt/loader/image/webp_image_decoder.cc
@@ -87,8 +87,20 @@
if (status == VP8_STATUS_OK) {
DCHECK(image_data());
DCHECK(config_.output.u.RGBA.rgba);
- SbMemoryCopy(image_data()->GetMemory(), config_.output.u.RGBA.rgba,
- config_.output.u.RGBA.size);
+
+ // Copy the image data over line by line. We copy line by line instead
+ // of all at once so that we can adjust for differences in pitch between
+ // source and destination buffers.
+ uint8* cur_src = config_.output.u.RGBA.rgba;
+ uint8* cur_dest = image_data()->GetMemory();
+ int height = image_data()->GetDescriptor().size.height();
+ int num_pixel_bytes = image_data()->GetDescriptor().size.width() * 4;
+ for (int i = 0; i < height; ++i) {
+ SbMemoryCopy(cur_dest, cur_src, num_pixel_bytes);
+ cur_src += config_.output.u.RGBA.stride;
+ cur_dest += image_data()->GetDescriptor().pitch_in_bytes;
+ }
+
set_state(kDone);
} else if (status != VP8_STATUS_SUSPENDED) {
DLOG(ERROR) << "WebPIAppend error, status code: " << status;
@@ -135,10 +147,6 @@
config_.output.colorspace = pixel_format() == render_tree::kPixelFormatRGBA8
? (has_alpha ? MODE_rgbA : MODE_RGBA)
: (has_alpha ? MODE_bgrA : MODE_BGRA);
- config_.output.u.RGBA.stride = image_data()->GetDescriptor().pitch_in_bytes;
- config_.output.u.RGBA.size =
- static_cast<size_t>(config_.output.u.RGBA.stride *
- image_data()->GetDescriptor().size.height());
// We don't use image buffer as the decoding buffer because libwebp will read
// from it while we assume that our image buffer is write only.
config_.output.is_external_memory = 0;
diff --git a/src/cobalt/network/network_module.cc b/src/cobalt/network/network_module.cc
index bb4e074..f9fb043 100644
--- a/src/cobalt/network/network_module.cc
+++ b/src/cobalt/network/network_module.cc
@@ -122,6 +122,7 @@
base::Thread::Options thread_options;
thread_options.message_loop_type = MessageLoop::TYPE_IO;
thread_options.stack_size = 256 * 1024;
+ thread_options.priority = base::kThreadPriority_High;
thread_->StartWithOptions(thread_options);
base::WaitableEvent creation_event(true, false);
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.cc b/src/cobalt/renderer/backend/egl/graphics_context.cc
index 5564bcd..6255fc7 100644
--- a/src/cobalt/renderer/backend/egl/graphics_context.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_context.cc
@@ -274,8 +274,13 @@
// with eglMakeCurrent to avoid polluting the previous EGLSurface target.
DCHECK_NE(surface->GetPlatformHandle(), 0);
- egl_surface = null_surface_->GetSurface();
- EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
+ // Since we don't care about what surface is backing the default
+ // framebuffer, don't change draw surfaces unless we simply don't have one
+ // already.
+ if (!IsCurrent()) {
+ egl_surface = null_surface_->GetSurface();
+ EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
+ }
GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, surface->GetPlatformHandle()));
}
@@ -289,7 +294,12 @@
}
void GraphicsContextEGL::MakeCurrent() {
- MakeCurrentWithSurface(null_surface_);
+ // Some GL drivers do *not* handle switching contexts in the middle of a
+ // frame very well, so with this change we avoid making a new surface
+ // current if we don't actually care about what surface is current.
+ if (!IsCurrent()) {
+ MakeCurrentWithSurface(null_surface_);
+ }
}
void GraphicsContextEGL::ReleaseCurrentContext() {
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.h b/src/cobalt/renderer/backend/egl/graphics_context.h
index 49e7c60..ef88e66 100644
--- a/src/cobalt/renderer/backend/egl/graphics_context.h
+++ b/src/cobalt/renderer/backend/egl/graphics_context.h
@@ -113,6 +113,9 @@
void Blit(GLuint texture, int x, int y, int width, int height);
+ // Returns if this graphics context is current on the calling thread or not.
+ bool IsCurrent() const { return is_current_; }
+
private:
// Performs a test to determine if the pixel data returned by glReadPixels
// needs to be vertically flipped or not. This test is expensive, so it
diff --git a/src/cobalt/renderer/rasterizer/blitter/image.cc b/src/cobalt/renderer/rasterizer/blitter/image.cc
index f51569e..21a6b1c 100644
--- a/src/cobalt/renderer/rasterizer/blitter/image.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/image.cc
@@ -96,7 +96,8 @@
SubmitOffscreenCallback submit_offscreen_callback, SbBlitterDevice device)
: size_(static_cast<int>(root->GetBounds().right()),
static_cast<int>(root->GetBounds().bottom())),
- is_opaque_(false) {
+ is_opaque_(false),
+ surface_(kSbBlitterInvalidSurface) {
initialize_image_ = base::Bind(
&SinglePlaneImage::InitializeImageFromRenderTree, base::Unretained(this),
root, submit_offscreen_callback, device);
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
index 4a95847..3defd2e 100644
--- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
@@ -190,6 +190,11 @@
void RenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) {
TRACE_EVENT0_IF_ENABLED("Visit(ImageNode)");
+ // The image_node may contain nothing. For example, when it represents a video
+ // or other kind of animated image element before any frame is decoded.
+ if (!image_node->data().source) {
+ return;
+ }
// All Blitter API images derive from skia::Image (so that they can be
// compatible with the Skia software renderer), so we start here by casting
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc
index fb95695..192010c 100644
--- a/src/cobalt/renderer/rasterizer/pixel_test.cc
+++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -3405,6 +3405,12 @@
#endif // defined(ENABLE_MAP_TO_MESH)
+TEST_F(PixelTest, DrawNullImage) {
+ // An ImageNode with no source is legal, though it should result in nothing
+ // being drawn.
+ TestTree(new ImageNode(NULL, math::RectF(output_surface_size())));
+}
+
} // namespace rasterizer
} // namespace renderer
} // namespace cobalt
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
index 5eafdd2..6332261 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
@@ -320,9 +320,16 @@
backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context) {
DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current());
+ backend::GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(
+ cobalt_context);
+
scoped_refptr<backend::FramebufferRenderTargetEGL> render_target(
new backend::FramebufferRenderTargetEGL(cobalt_context, size_));
+ // The above call to FramebufferRenderTargetEGL() may have dirtied graphics
+ // state, so tell Skia to reset its context.
+ gr_context->resetContext(kRenderTarget_GrGLBackendState |
+ kTextureBinding_GrGLBackendState);
submit_offscreen_callback.Run(root, render_target);
scoped_ptr<backend::TextureEGL> texture(
@@ -330,6 +337,11 @@
backend_image_.reset(new HardwareBackendImage(texture.Pass()));
backend_image_->CommonInitialize(gr_context);
+
+ // Tell Skia that the graphics state is unknown because we issued custom
+ // GL commands above.
+ gr_context->resetContext(kRenderTarget_GrGLBackendState |
+ kTextureBinding_GrGLBackendState);
}
HardwareMultiPlaneImage::HardwareMultiPlaneImage(
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
index 471f5cd..1af8965 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
@@ -560,6 +560,17 @@
const scoped_refptr<backend::RenderTarget>& render_target) {
DCHECK(thread_checker_.CalledOnValidThread());
+ scoped_refptr<backend::RenderTargetEGL> render_target_egl(
+ base::polymorphic_downcast<backend::RenderTargetEGL*>(
+ render_target.get()));
+
+ if (render_target_egl->is_surface_bad()) {
+ return;
+ }
+
+ backend::GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(
+ graphics_context_, render_target_egl);
+
// Create a canvas from the render target.
GrBackendRenderTargetDesc skia_desc =
CobaltRenderTargetToSkiaBackendRenderTargetDesc(render_target.get());
diff --git a/src/cobalt/renderer/rasterizer/testdata/DrawNullImage-expected.png b/src/cobalt/renderer/rasterizer/testdata/DrawNullImage-expected.png
new file mode 100644
index 0000000..7f0bfcf
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/DrawNullImage-expected.png
Binary files differ
diff --git a/src/cobalt/webdriver_benchmarks/README.md b/src/cobalt/webdriver_benchmarks/README.md
deleted file mode 100644
index da77083..0000000
--- a/src/cobalt/webdriver_benchmarks/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-Framework for webdriver-driven benchmarks.
-
-Please see tests/README.md
diff --git a/src/cobalt/webdriver_benchmarks/__init__.py b/src/cobalt/webdriver_benchmarks/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/cobalt/webdriver_benchmarks/__init__.py
+++ /dev/null
diff --git a/src/cobalt/webdriver_benchmarks/c_val_names.py b/src/cobalt/webdriver_benchmarks/c_val_names.py
deleted file mode 100644
index 6ce4f4d..0000000
--- a/src/cobalt/webdriver_benchmarks/c_val_names.py
+++ /dev/null
@@ -1,89 +0,0 @@
-"""Provides cval names needed by the webdriver benchmarks."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-def count_dom_active_java_script_events():
- return "Count.DOM.ActiveJavaScriptEvents"
-
-
-def count_dom_html_elements_document():
- return "Count.MainWebModule.DOM.HtmlElement.Document"
-
-
-def count_dom_html_elements_total():
- return "Count.MainWebModule.DOM.HtmlElement.Total"
-
-
-def count_dom_html_script_element_execute():
- return "Count.MainWebModule.DOM.HtmlScriptElement.Execute"
-
-
-def count_layout_boxes():
- return "Count.MainWebModule.Layout.Box"
-
-
-def count_image_cache_loading_resources():
- return "Count.MainWebModule.ImageCache.LoadingResources"
-
-
-def count_image_cache_requested_resources():
- return "Count.MainWebModule.ImageCache.RequestedResources"
-
-
-def count_rasterize_new_render_tree():
- return "Count.Renderer.Rasterize.NewRenderTree"
-
-
-def event_duration_dom_video_start_delay():
- return "Event.Duration.MainWebModule.DOM.VideoStartDelay"
-
-
-def event_is_processing():
- return "Event.MainWebModule.IsProcessing"
-
-
-def event_value_dictionary(event_type):
- return "Event.MainWebModule.{}.ValueDictionary".format(event_type)
-
-
-def layout_is_dirty():
- return "MainWebModule.Layout.IsDirty"
-
-
-def rasterize_animations_entry_list():
- return "Renderer.Rasterize.Animations.EntryList"
-
-
-def renderer_has_active_animations():
- return "Renderer.HasActiveAnimations"
-
-
-def time_browser_navigate():
- return "Time.Browser.Navigate"
-
-
-def time_browser_on_load_event():
- return "Time.Browser.OnLoadEvent"
-
-
-def time_cobalt_start():
- return "Time.Cobalt.Start"
-
-
-def time_dom_html_script_element_execute():
- return "Time.MainWebModule.DOM.HtmlScriptElement.Execute"
-
-
-def time_rasterize_animations_start():
- return "Time.Renderer.Rasterize.Animations.Start"
-
-
-def time_rasterize_animations_end():
- return "Time.Renderer.Rasterize.Animations.End"
-
-
-def time_rasterize_new_render_tree():
- return "Time.Renderer.Rasterize.NewRenderTree"
diff --git a/src/cobalt/webdriver_benchmarks/container_util.py b/src/cobalt/webdriver_benchmarks/container_util.py
deleted file mode 100644
index 56e948a..0000000
--- a/src/cobalt/webdriver_benchmarks/container_util.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""Base class for WebDriver tests."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import math
-
-
-def mean(list_values):
- """Returns the mean of a list of numeric values.
-
- Args:
- list_values: A list of numeric values.
- Returns:
- Appropriate value.
- """
- if not list_values:
- return None
-
- return sum(list_values) / len(list_values)
-
-
-def percentile(list_values, target_percentile):
- """Returns the percentile of a list.
-
- This method interpolates between two numbers if the percentile lands between
- two data points.
-
- Args:
- list_values: A sortable list of values
- target_percentile: A number ranging from 0-100.
- Returns:
- Appropriate value.
- Raises:
- RuntimeError: Raised on invalid args.
- """
- if not list_values:
- return None
- if target_percentile > 100 or target_percentile < 0:
- raise RuntimeError("target_percentile must be 0-100")
- sorted_values = sorted(list_values)
-
- if target_percentile == 100:
- return sorted_values[-1]
- fractional, index = math.modf(
- (len(sorted_values) - 1) * (target_percentile * 0.01))
- index = int(index)
-
- if len(sorted_values) == index + 1:
- return sorted_values[index]
-
- return sorted_values[index] * (
- 1 - fractional) + sorted_values[index + 1] * fractional
diff --git a/src/cobalt/webdriver_benchmarks/container_util_test.py b/src/cobalt/webdriver_benchmarks/container_util_test.py
deleted file mode 100755
index 8c29bb4..0000000
--- a/src/cobalt/webdriver_benchmarks/container_util_test.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/python2
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Unit tests for tv_testcase.py."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import sys
-import unittest
-
-# This directory is a package
-sys.path.insert(0, os.path.abspath('.'))
-# pylint: disable=C6203,C6203
-# pylint: disable=g-import-not-at-top
-import container_util
-
-
-class MeanTest(unittest.TestCase):
-
- def test_empty_case(self):
- self.assertEqual(container_util.mean([]), None)
-
- def test_one_item(self):
- self.assertEqual(container_util.mean([1]), 1)
-
- def test_two_items(self):
- self.assertAlmostEqual(container_util.mean([4, 1]), 2.5)
-
- def test_three_items(self):
- self.assertAlmostEqual(container_util.mean([4, -4, 9]), 3)
-
- def test_four_items(self):
- self.assertAlmostEqual(container_util.mean([6, 0, 1, -2]), 1.25)
-
-
-class MedianPercentileTest(unittest.TestCase):
-
- def test_empty_case(self):
- self.assertEqual(container_util.percentile([], 50), None)
-
- def test_one_item(self):
- self.assertEqual(container_util.percentile([1], 50), 1)
-
- def test_two_items(self):
- self.assertAlmostEqual(container_util.percentile([4, 1], 50), 2.5)
-
- def test_three_items(self):
- self.assertAlmostEqual(container_util.percentile([4, -4, -2], 50), -2)
-
- def test_four_items(self):
- self.assertAlmostEqual(container_util.percentile([4, 0, 1, -2], 50), 0.5)
-
-
-class PercentileTest(unittest.TestCase):
-
- def test_one_item(self):
- self.assertEqual(container_util.percentile([1], 10), 1)
- self.assertEqual(container_util.percentile([2], 50), 2)
- self.assertEqual(container_util.percentile([3], 90), 3)
-
- def test_two_items(self):
- self.assertEqual(container_util.percentile([2, 1], 10), 1.1)
- self.assertEqual(container_util.percentile([2, 3], 50), 2.5)
- self.assertEqual(container_util.percentile([3, 4], 90), 3.9)
- self.assertEqual(container_util.percentile([3, 4], 100), 4)
-
- def test_five_items(self):
- self.assertEqual(container_util.percentile([2, 1, 3, 4, 5], 10), 1.4)
- self.assertEqual(container_util.percentile([2, 1, 3, 4, 5], 50), 3)
- self.assertEqual(container_util.percentile([2, 1, 3, 4, 5], 90), 4.6)
- self.assertEqual(container_util.percentile([2, 1, 3, 4, 5], 100), 5)
-
-
-if __name__ == '__main__':
- sys.exit(unittest.main())
diff --git a/src/cobalt/webdriver_benchmarks/default_query_param_constants.py b/src/cobalt/webdriver_benchmarks/default_query_param_constants.py
deleted file mode 100644
index c2347f2..0000000
--- a/src/cobalt/webdriver_benchmarks/default_query_param_constants.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""Default query params to use when loading URLs."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-BASE_QUERY_PARAMS = {}
-
-INIT_QUERY_PARAMS = {}
-INIT_QUERY_PARAMS_TRIGGER_RELOAD = False
diff --git a/src/cobalt/webdriver_benchmarks/tests/README.md b/src/cobalt/webdriver_benchmarks/tests/README.md
deleted file mode 100644
index 81fde36..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/README.md
+++ /dev/null
@@ -1,292 +0,0 @@
-# Cobalt Webdriver-driven Benchmarks
-
-This directory contains a set of webdriver-driven benchmarks
-for Cobalt.
-
-Each file should contain a set of tests in Python "unittest" format.
-
-All tests included within [performance.py](performance.py) will be run on the
-build system. Results can be recorded in the build results database.
-
-## Running the tests
-
-In most cases, you will want to run all performance tests, and you can do so by
-executing the script [performance.py](performance.py). You can call
-`python performance.py --help` to see a list of commandline parameters to call
-it with. For example, to run tests on the raspi-2 QA build, you should run the
-following command:
-
-```
-python performance.py -p raspi-2 -c qa -d $RASPI_ADDR
-```
-
-Where `RASPI_ADDR` is set to the IP of the target Raspberry Pi device.
-
-To run individual tests, simply execute the script directly. For all tests,
-platform configuration will be inferred from the environment if set. Otherwise,
-it must be specified via commandline parameters.
-
-## Creating a new test
-
- 1. If appropriate, create a new file borrowing the boilerplate from
- an existing simple file, such as
- [browse_horizontal.py](performance/non_video/browse_horizontal.py).
-
- 2. Add the file name to the tests added within
- [performance.py](performance.py), causing it run when
- [performance](performance.py) is run.
-
- 3. If this file contains internal names or details, consider adding it
- to the "EXCLUDE.FILES" list.
-
- 4. Use the `record_test_result*` methods in `tv_testcase_util` where
- appropriate.
-
- 5. Results must be added to the build results database schema. See
- the internal
- [README-Updating-Result-Schema.md](README-Updating-Result-Schema.md) file.
-
-## Testing against specific loaders/labels
-
-To run the benchmarks against any desired loader, a --url command line parameter
-can be provided. This will be the url that the tests will run against.
-
-It should have the following format:
-
-```
-python performance.py -p raspi-2 -c qa -d $RASPI_ADDR --url https://www.youtube.com/tv?loader=nllive
-```
-
-## Benchmark Results
-
-The results will be printed to stdout. You should redirect output to a file
-if you would like to store the results. Each line of the benchmark output
-prefixed with `webdriver_benchmark TEST_RESULT:` provides the result of one
-measurment. Those lines have the following format:
-
-```
-webdriver_benchmark TEST_RESULT: result_name result_value
-```
-
-where `result_name` is the name of the result and `result_value` is a number
-providing the measured result for that metric. For example,
-
-```
-webdriver_benchmark TEST RESULT: wbBrowseHorizontalDurLayoutBoxTreeUpdateUsedSizesUsPct50 3061.5
-```
-
-gives the 50th percentile of the duration Cobalt took to update the box tree's
-used sizes, on a horizontal scroll event, in microseconds.
-
-Note that most time-based measurements are in microseconds.
-
-### Interesting Timing-Related Benchmarks
-Some particularly interesting timing-related benchmark results are:
-
-#### Startup
- - `wbStartupDurLaunchToBrowseUs`: Measures the time it takes to launch Cobalt
- and load the desired URL. The measurement ends when all images finish loading
- and the final render tree is produced. This is only run once so it will be
- noiser than other values but provides the most accurate measurement of the
- requirement startup time.
- - `wbStartupDurLaunchToUsableUs`: Measures the time it takes to launch Cobalt,
- and fully load the desired URL, including loading all scripts. The
- measurement ends when the Player JavaScript code finishes loading on the
- Browse page, which is the point when Cobalt is fully usable. This is only run
- once so it will be noiser than other values but provides the most accurate
- measurement of the time when Cobalt is usable.
- - `wbStartupDurNavigateToBrowseUs*`: Measures the time it takes to navigate to
- the desired URL when Cobalt is already loaded. The measurement ends when all
- images finish loading and the final render tree is produced. This is run
- multiple times, so it will be less noisy than `wbStartupDurLaunchToBrowseUs`,
- but it does not include Cobalt initialization so it is not as accurate of a
- measurement.
- - `wbStartupDurNavigateToUsableUs`: Measures the time it takes to navigate to
- the desired URL when Cobalt is already loaded, including loading all scripts.
- The measurement ends when the Player JavaScript code finishes loading on the
- Browse page, which is the point when Cobalt is fully usable. This is run
- multiple times, so it will be less noisy than `wbStartupDurLaunchToUsableUs`,
- but it does not include Cobalt initialization so it is not as accurate of a
- measurement.
-
-#### Browse Horizontal Scroll Events
- - `wbBrowseHorizontalDurTotalUs*`: Measures the latency (i.e. JavaScript
- execution time + layout time) during horizontal scroll events from keypress
- until the render tree is submitted to the rasterize thread. It does not
- include the time taken to rasterize the render tree so it will be smaller
- than the observed latency.
- - `wbBrowseHorizontalDurAnimationsStartDelayUs*`: Measures the input latency
- during horizontal scroll events from the keypress until the animation starts.
- This is the most accurate measure of input latency.
- - `wbBrowseHorizontalDurAnimationsEndDelayUs*`: Measures the latency during
- horizontal scroll events from the keypress until the animation ends.
- - `wbBrowseHorizontalDurFinalRenderTreeDelayUs*`: Measures the latency during
- horizontal scroll events from the keypress until the final render tree is
- rendered and processing stops.
- - `wbBrowseHorizontalDurRasterizeAnimationsUs*`: Measures the time it takes to
- render each frame of the animation triggered by a horizontal scroll event.
- The inverse of this number is the framerate.
-
-#### Browse Vertical Scroll Events
- - `wbBrowseVerticalDurTotalUs*`: Measures the latency (i.e. JavaScript
- execution time + layout time) during vertical scroll events from keypress
- until the render tree is submitted to the rasterize thread. It does not
- include the time taken to rasterize the render tree so it will be smaller
- than the observed latency.
- - `wbBrowseVerticalDurAnimationsStartDelayUs*`: Measures the input latency
- during vertical scroll events from the keypress until the animation starts.
- This is the most accurate measure of input latency.
- - `wbBrowseVerticalDurAnimationsEndDelayUs*`: Measures the latency during
- vertical scroll events from the keypress until the animation ends.
- - `wbBrowseVerticalDurFinalRenderTreeDelayUs*`: Measures the latency during
- vertical scroll events from the keypress until the final render tree is
- rendered and processing stops.
- - `wbBrowseVerticalDurRasterizeAnimationsUs*`: Measures the time it takes to
- render each frame of the animation triggered by a vertical scroll event.
- The inverse of this number is the framerate.
-
-#### Browse-to-Watch
- - `wbBrowseToWatchDurVideoStartDelay*`: Measures the browse-to-watch time.
-
-In each case above, the `*` symbol can be one of either `Mean`, `Pct25`,
-`Pct50`, `Pct75` or `Pct95`. For example, `wbStartupDurBlankToBrowseUsMean` or
-`wbStartupDurBlankToBrowseUsPct95` are both valid measurements. The webdriver
-benchmarks runs its tests many times in order to obtain multiple samples, so you
-can drill into the data by exploring either the mean, or the various
-percentiles.
-
-### Interesting Count-Related Benchmarks
-Some particularly interesting count-related benchmark results are:
-
-#### Startup
- - `wbStartupCntDomHtmlElements*`: Lists the number of HTML elements in
- existence after startup completes. This includes HTML elements that are no
- longer in the DOM but have not been garbage collected yet.
- - `wbStartupCntDocumentDomHtmlElements*`: Lists the number of HTML
- elements within the DOM tree after startup completes.
- - `wbStartupCntLayoutBoxes*`: Lists the number of layout boxes within
- the layout tree after startup completes.
- - `wbStartupCntRenderTrees*`: Lists the number of render trees that were
- generated during startup.
- - `wbStartupCntRequestedImages*`: Lists the number of images that were
- requested during startup.
-
-#### Browse Horizontal Scroll Events
- - `wbBrowseHorizontalCntDomHtmlElements*`: Lists the number of HTML elements in
- existence after the event. This includes HTML elements that are no longer in
- the DOM but have not been garbage collected yet.
- - `wbBrowseHorizontalCntDocumentDomHtmlElements*`: Lists the number of HTML
- elements within the DOM tree after the event.
- - `wbBrowseHorizontalCntLayoutBoxes*`: Lists the number of layout boxes within
- the layout tree after the event.
- - `wbBrowseHorizontalCntLayoutBoxesCreated*`: Lists the number of new layout
- boxes that were created during the event.
- - `wbBrowseHorizontalCntRenderTrees*`: Lists the number of render trees that
- were generated by the event.
- - `wbBrowseHorizontalCntRequestedImages*`: Lists the number of images that were
- requested as a result of the event.
-
-#### Browse Vertical Scroll Events
- - `wbBrowseVerticalCntDomHtmlElements*`: Lists the number of HTML elements in
- existence after the event. This includes HTML elements that are no longer in
- the DOM but have not been garbage collected yet.
- - `wbBrowseVerticalCntDocumentDomHtmlElements*`: Lists the number of HTML
- elements within the DOM tree after the event.
- - `wbBrowseVerticalCntLayoutBoxes*`: Lists the number of layout boxes within
- the layout tree after the event.
- - `wbBrowseVerticalCntLayoutBoxesCreated*`: Lists the number of new layout
- boxes that were created during the event.
- - `wbBrowseVerticalCntRenderTrees*`: Lists the number of render trees that
- were generated by the event.
- - `wbBrowseVerticalCntRequestedImages*`: Lists the number of images that were
- requested as a result of the event.
-
-In each case above, the `*` symbol can be one of either `Max`, `Median`, or
-`Mean`. For example, `wbBrowseVerticalCntDomHtmlElementsMax` or
-`wbBrowseVerticalCntDomHtmlElementsMedian` are both valid measurements. The
-webdriver benchmarks runs its tests many times in order to obtain multiple
-samples, so you can drill into the data by exploring either the max, median, or
-mean.
-
-### Filtering results
-
-The webdriver benchmarks output many metrics, but you may only be interested
-in a few. You will have to manually filter only the metrics that you are
-interested in. You can do so with `grep`, for example:
-
-```
-python performance.py -p raspi-2 -c qa -d $RASPI_ADDR > results.txt
-echo "" > filtered_results.txt
-printf "=================================TIMING-RELATED=================================\n" >> filtered_results.txt
-printf "\nSTARTUP\n" >> filtered_results.txt
-grep -o "wbStartupDurLaunchToBrowseUs.*$" results.txt >> filtered_results.txt
-grep -o "wbStartupDurLaunchToUsableUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbStartupDurNavigateToBrowseUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbStartupDurNavigateToUsableUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-printf "\nBROWSE HORIZONTAL SCROLL EVENTS\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalDurTotalUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalDurAnimationsStartDelayUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalDurAnimationsEndDelayUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalDurFinalRenderTreeDelayUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalDurRasterizeAnimationsUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-printf "\nBROWSE VERTICAL SCROLL EVENTS\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalDurTotalUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalDurAnimationsStartDelayUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalDurAnimationsEndDelayUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalDurFinalRenderTreeDelayUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalDurRasterizeAnimationsUs.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-printf "\nBROWSE TO WATCH\n" >> filtered_results.txt
-grep -o "wbBrowseToWatchDurVideoStartDelay.*$" results.txt >> filtered_results.txt
-printf "\n\n=================================COUNT-RELATED==================================\n" >> filtered_results.txt
-printf "\nSTARTUP\n" >> filtered_results.txt
-grep -o "wbStartupCntDomHtmlElements.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbStartupCntDomDocumentHtmlElements.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbStartupCntLayoutBoxes.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbStartupCntRenderTrees.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbStartupCntRequestedImages.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-printf "\nBROWSE HORIZONTAL SCROLL EVENTS\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalCntDomHtmlElementsM.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalCntDomDocumentHtmlElements.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalCntLayoutBoxesM.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalCntLayoutBoxesCreated.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalCntRenderTrees.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseHorizontalCntRequestedImages.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-printf "\nBROWSE VERTICAL SCROLL EVENTS\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalCntDomHtmlElementsM.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalCntDomDocumentHtmlElements.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalCntLayoutBoxesM.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalCntLayoutBoxesCreated.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalCntRenderTrees.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-grep -o "wbBrowseVerticalCntRequestedImages.*$" results.txt >> filtered_results.txt
-printf "\n" >> filtered_results.txt
-cat filtered_results.txt
-```
diff --git a/src/cobalt/webdriver_benchmarks/tests/__init__.py b/src/cobalt/webdriver_benchmarks/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/__init__.py
+++ /dev/null
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance.py b/src/cobalt/webdriver_benchmarks/tests/performance.py
deleted file mode 100644
index 8495f71..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python2
-"""Target for running all performance test cases."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import importlib
-import os
-import sys
-import unittest
-
-# The parent directory is a module
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
-
-# pylint: disable=C6204,C6203
-import tv_testcase
-
-
-def _add_test(test_suite, dir_path, test_name):
- if os.path.isfile(os.path.join(dir_path, test_name + ".py")):
- print("Adding test: {}".format(test_name))
- test_suite.addTest(unittest.TestLoader().loadTestsFromModule(
- importlib.import_module("tests." + test_name)))
-
-
-# pylint: disable=unused-argument
-def load_tests(loader, tests, pattern):
- """This is a Python unittest "load_tests protocol method."""
- test_suite = unittest.TestSuite()
- dir_path = os.path.dirname(__file__)
-
- _add_test(test_suite, dir_path, "performance_non_video")
- _add_test(test_suite, dir_path, "performance_video")
-
- return test_suite
-
-
-if __name__ == "__main__":
- tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/__init__.py b/src/cobalt/webdriver_benchmarks/tests/performance/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance/__init__.py
+++ /dev/null
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/__init__.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/__init__.py
+++ /dev/null
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_horizontal.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_horizontal.py
deleted file mode 100755
index 2da83c6..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_horizontal.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python2
-"""Simple benchmark of horizontally navigating shelves during browse."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import sys
-
-# Add the base webdriver_benchmarks path
-sys.path.insert(0,
- os.path.dirname(
- os.path.dirname((os.path.dirname(
- os.path.dirname(os.path.realpath(__file__)))))))
-
-# pylint: disable=C6204,C6203
-import tv_testcase
-import tv_testcase_event_recorder
-import tv_testcase_util
-
-# selenium imports
-keys = tv_testcase_util.import_selenium_module("webdriver.common.keys")
-
-NUM_LOAD_TV_CALLS = 5
-NUM_ITERATIONS_PER_LOAD_TV_CALL = 20
-
-BROWSE_HORIZONTAL_EVENT_NAME = "wbBrowseHorizontal"
-BROWSE_HORIZONTAL_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_DOWN
-
-
-class BrowseHorizontalTest(tv_testcase.TvTestCase):
-
- def test_simple(self):
- recorder_options = tv_testcase_event_recorder.EventRecorderOptions(
- self, BROWSE_HORIZONTAL_EVENT_NAME, BROWSE_HORIZONTAL_EVENT_TYPE)
- recorder = tv_testcase_event_recorder.EventRecorder(recorder_options)
-
- for _ in xrange(NUM_LOAD_TV_CALLS):
- self.load_tv()
- self.send_keys(keys.Keys.ARROW_RIGHT)
- self.wait_for_processing_complete_after_focused_shelf()
-
- for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL):
- recorder.on_start_event()
- self.send_keys(keys.Keys.ARROW_RIGHT)
- self.wait_for_processing_complete_after_focused_shelf()
- recorder.on_end_event()
-
- recorder.on_end_test()
-
-
-if __name__ == "__main__":
- tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_guide.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_guide.py
deleted file mode 100755
index 7e5230f..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_guide.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/python2
-"""Simple benchmark for going from browse to guide and back."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import sys
-
-# Add the base webdriver_benchmarks path
-sys.path.insert(0,
- os.path.dirname(
- os.path.dirname((os.path.dirname(
- os.path.dirname(os.path.realpath(__file__)))))))
-
-# pylint: disable=C6204,C6203
-import tv
-import tv_testcase
-import tv_testcase_event_recorder
-import tv_testcase_util
-
-# selenium imports
-keys = tv_testcase_util.import_selenium_module("webdriver.common.keys")
-
-NUM_LOAD_TV_CALLS = 1
-NUM_ITERATIONS_PER_LOAD_TV_CALL = 20
-
-BROWSE_TO_GUIDE_EVENT_NAME = "wbBrowseToGuide"
-BROWSE_TO_GUIDE_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_DOWN
-
-GUIDE_TO_BROWSE_EVENT_NAME = "wbGuideToBrowse"
-GUIDE_TO_BROWSE_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_DOWN
-
-
-class BrowseToGuideTest(tv_testcase.TvTestCase):
-
- def test_simple(self):
- recorder_options = tv_testcase_event_recorder.EventRecorderOptions(
- self, BROWSE_TO_GUIDE_EVENT_NAME, BROWSE_TO_GUIDE_EVENT_TYPE)
- browse_to_guide_recorder = tv_testcase_event_recorder.EventRecorder(
- recorder_options)
-
- recorder_options = tv_testcase_event_recorder.EventRecorderOptions(
- self, GUIDE_TO_BROWSE_EVENT_NAME, GUIDE_TO_BROWSE_EVENT_TYPE)
- guide_to_browse_recorder = tv_testcase_event_recorder.EventRecorder(
- recorder_options)
-
- for _ in xrange(NUM_LOAD_TV_CALLS):
- self.load_tv()
-
- for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL):
- browse_to_guide_recorder.on_start_event()
- self.send_keys(keys.Keys.ARROW_LEFT)
- self.wait_for_processing_complete()
- self.assert_displayed(tv.FOCUSED_GUIDE)
- browse_to_guide_recorder.on_end_event()
-
- guide_to_browse_recorder.on_start_event()
- self.send_keys(keys.Keys.ARROW_RIGHT)
- self.wait_for_processing_complete_after_focused_shelf()
- guide_to_browse_recorder.on_end_event()
-
- browse_to_guide_recorder.on_end_test()
- guide_to_browse_recorder.on_end_test()
-
-
-if __name__ == "__main__":
- tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_search.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_search.py
deleted file mode 100755
index a2d82de..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_search.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/python2
-"""Simple benchmark for going from browse to search and back."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import sys
-
-# Add the base webdriver_benchmarks path
-sys.path.insert(0,
- os.path.dirname(
- os.path.dirname((os.path.dirname(
- os.path.dirname(os.path.realpath(__file__)))))))
-
-# pylint: disable=C6204,C6203
-import tv
-import tv_testcase
-import tv_testcase_event_recorder
-import tv_testcase_util
-
-# selenium imports
-keys = tv_testcase_util.import_selenium_module("webdriver.common.keys")
-
-NUM_LOAD_TV_CALLS = 1
-NUM_ITERATIONS_PER_LOAD_TV_CALL = 20
-
-BROWSE_TO_SEARCH_EVENT_NAME = "wbBrowseToSearch"
-BROWSE_TO_SEARCH_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_UP
-
-SEARCH_TO_BROWSE_EVENT_NAME = "wbSearchToBrowse"
-SEARCH_TO_BROWSE_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_UP
-
-
-class BrowseToSearchTest(tv_testcase.TvTestCase):
-
- def test_simple(self):
- recorder_options = tv_testcase_event_recorder.EventRecorderOptions(
- self, BROWSE_TO_SEARCH_EVENT_NAME, BROWSE_TO_SEARCH_EVENT_TYPE)
- recorder_options.record_animations = False
- browse_to_search_recorder = tv_testcase_event_recorder.EventRecorder(
- recorder_options)
-
- recorder_options = tv_testcase_event_recorder.EventRecorderOptions(
- self, SEARCH_TO_BROWSE_EVENT_NAME, SEARCH_TO_BROWSE_EVENT_TYPE)
- recorder_options.record_animations = False
- search_to_browse_recorder = tv_testcase_event_recorder.EventRecorder(
- recorder_options)
-
- for _ in xrange(NUM_LOAD_TV_CALLS):
- self.load_tv()
-
- for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL):
- browse_to_search_recorder.on_start_event()
- self.send_keys("s")
- self.wait_for_processing_complete(False)
- self.assert_displayed(tv.FOCUSED_SEARCH)
- browse_to_search_recorder.on_end_event()
-
- search_to_browse_recorder.on_start_event()
- self.send_keys(keys.Keys.ESCAPE)
- self.wait_for_processing_complete_after_focused_shelf()
- search_to_browse_recorder.on_end_event()
-
- browse_to_search_recorder.on_end_test()
- search_to_browse_recorder.on_end_test()
-
-
-if __name__ == "__main__":
- tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_vertical.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_vertical.py
deleted file mode 100755
index 08a687e..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_vertical.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python2
-"""Simple benchmark of vertically navigating shelves during browse."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import sys
-
-# Add the base webdriver_benchmarks path
-sys.path.insert(0,
- os.path.dirname(
- os.path.dirname((os.path.dirname(
- os.path.dirname(os.path.realpath(__file__)))))))
-
-# pylint: disable=C6204,C6203
-import tv_testcase
-import tv_testcase_event_recorder
-import tv_testcase_util
-
-# selenium imports
-keys = tv_testcase_util.import_selenium_module("webdriver.common.keys")
-
-NUM_LOAD_TV_CALLS = 4
-NUM_ITERATIONS_PER_LOAD_TV_CALL = 25
-
-BROWSE_VERTICAL_EVENT_NAME = "wbBrowseVertical"
-BROWSE_VERTICAL_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_DOWN
-
-
-class BrowseVerticalTest(tv_testcase.TvTestCase):
-
- def test_simple(self):
- recorder_options = tv_testcase_event_recorder.EventRecorderOptions(
- self, BROWSE_VERTICAL_EVENT_NAME, BROWSE_VERTICAL_EVENT_TYPE)
- recorder = tv_testcase_event_recorder.EventRecorder(recorder_options)
-
- for _ in xrange(NUM_LOAD_TV_CALLS):
- self.load_tv()
- self.send_keys(keys.Keys.ARROW_DOWN)
- self.wait_for_processing_complete_after_focused_shelf()
-
- for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL):
- recorder.on_start_event()
- self.send_keys(keys.Keys.ARROW_DOWN)
- self.wait_for_processing_complete_after_focused_shelf()
- recorder.on_end_event()
-
- recorder.on_end_test()
-
-
-if __name__ == "__main__":
- tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/startup.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/startup.py
deleted file mode 100755
index c37008e..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/startup.py
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/python2
-"""Simple benchmark for measuring startup time."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import sys
-
-# Add the base webdriver_benchmarks path
-sys.path.insert(0,
- os.path.dirname(
- os.path.dirname((os.path.dirname(
- os.path.dirname(os.path.realpath(__file__)))))))
-
-# pylint: disable=C6204,C6203
-import c_val_names
-import tv_testcase
-import tv_testcase_util
-
-NUM_LOAD_TV_ITERATIONS = 20
-
-STARTUP_RECORD_NAME = "wbStartup"
-
-
-class StartupTest(tv_testcase.TvTestCase):
-
- def setUp(self):
- # Override TvTestCase's setUp() so that blank startup can first be measured.
- pass
-
- def test_simple(self):
- """This test tries to measure the startup time for the YouTube TV page."""
- self.wait_for_processing_complete()
- self.wait_for_html_script_element_execute_count(2)
-
- # Measure durations for the intial launch.
- launch_time = self.get_cval(c_val_names.time_cobalt_start())
- navigate_time = self.get_cval(c_val_names.time_browser_navigate())
- on_load_event_time = self.get_cval(c_val_names.time_browser_on_load_event())
- browse_time = self.get_cval(c_val_names.time_rasterize_new_render_tree())
- usable_time = self.get_cval(
- c_val_names.time_dom_html_script_element_execute())
-
- dur_launch_to_navigate_us = navigate_time - launch_time
- dur_launch_to_on_load_event_us = on_load_event_time - launch_time
- dur_launch_to_browse_us = browse_time - launch_time
- dur_launch_to_usable_us = usable_time - launch_time
-
- # Call TvTestCase's setUp() now that the launch times have been measured.
- super(StartupTest, self).setUp()
-
- # Count record strategies
- count_record_strategies = []
- count_record_strategies.append(tv_testcase_util.RecordStrategyMean())
- count_record_strategies.append(tv_testcase_util.RecordStrategyMin())
- count_record_strategies.append(tv_testcase_util.RecordStrategyMedian())
- count_record_strategies.append(tv_testcase_util.RecordStrategyMax())
-
- # Duration record strategies
- duration_record_strategies = []
- duration_record_strategies.append(tv_testcase_util.RecordStrategyMean())
- duration_record_strategies.append(tv_testcase_util.RecordStrategyMin())
- duration_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(25))
- duration_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(50))
- duration_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(75))
- duration_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(95))
- duration_record_strategies.append(tv_testcase_util.RecordStrategyMax())
-
- # Count recorders
- count_total_html_element_recorder = tv_testcase_util.ResultsRecorder(
- STARTUP_RECORD_NAME + "CntDomHtmlElements", count_record_strategies)
- count_document_html_element_recorder = tv_testcase_util.ResultsRecorder(
- STARTUP_RECORD_NAME + "CntDomDocumentHtmlElements",
- count_record_strategies)
- count_layout_box_recorder = tv_testcase_util.ResultsRecorder(
- STARTUP_RECORD_NAME + "CntLayoutBoxes", count_record_strategies)
- count_render_trees_recorder = tv_testcase_util.ResultsRecorder(
- STARTUP_RECORD_NAME + "CntRenderTrees", count_record_strategies)
- count_requested_images_recorder = tv_testcase_util.ResultsRecorder(
- STARTUP_RECORD_NAME + "CntRequestedImages", count_record_strategies)
-
- # Duration recorders
- duration_navigate_to_on_load_recorder = tv_testcase_util.ResultsRecorder(
- STARTUP_RECORD_NAME + "DurNavigateToOnLoadUs",
- duration_record_strategies)
- duration_navigate_to_browse_recorder = tv_testcase_util.ResultsRecorder(
- STARTUP_RECORD_NAME + "DurNavigateToBrowseUs",
- duration_record_strategies)
- duration_navigate_to_usable_recorder = tv_testcase_util.ResultsRecorder(
- STARTUP_RECORD_NAME + "DurNavigateToUsableUs",
- duration_record_strategies)
-
- # Now measure counts and durations from reloading the URL.
- for _ in range(NUM_LOAD_TV_ITERATIONS):
- count_render_trees_start = self.get_cval(
- c_val_names.count_rasterize_new_render_tree())
-
- self.load_tv()
-
- count_render_trees_end = self.get_cval(
- c_val_names.count_rasterize_new_render_tree())
-
- count_total_html_elements = self.get_cval(
- c_val_names.count_dom_html_elements_total())
- count_document_html_elements = self.get_cval(
- c_val_names.count_dom_html_elements_document())
- count_layout_boxes = self.get_cval(c_val_names.count_layout_boxes())
- count_requested_images = self.get_cval(
- c_val_names.count_image_cache_requested_resources())
-
- navigate_time = self.get_cval(c_val_names.time_browser_navigate())
- on_load_event_time = self.get_cval(
- c_val_names.time_browser_on_load_event())
- browse_time = self.get_cval(c_val_names.time_rasterize_new_render_tree())
- usable_time = self.get_cval(
- c_val_names.time_dom_html_script_element_execute())
-
- count_total_html_element_recorder.collect_value(count_total_html_elements)
- count_document_html_element_recorder.collect_value(
- count_document_html_elements)
- count_layout_box_recorder.collect_value(count_layout_boxes)
- count_render_trees_recorder.collect_value(count_render_trees_end -
- count_render_trees_start)
- count_requested_images_recorder.collect_value(count_requested_images)
-
- duration_navigate_to_on_load_recorder.collect_value(
- on_load_event_time - navigate_time)
- duration_navigate_to_browse_recorder.collect_value(
- browse_time - navigate_time)
- duration_navigate_to_usable_recorder.collect_value(
- usable_time - navigate_time)
-
- # Record the counts
- count_total_html_element_recorder.on_end_test()
- count_document_html_element_recorder.on_end_test()
- count_layout_box_recorder.on_end_test()
- count_render_trees_recorder.on_end_test()
- count_requested_images_recorder.on_end_test()
-
- # Record the durations
- tv_testcase_util.record_test_result(
- STARTUP_RECORD_NAME + "DurLaunchToNavigateUs",
- dur_launch_to_navigate_us)
- tv_testcase_util.record_test_result(
- STARTUP_RECORD_NAME + "DurLaunchToOnLoadUs",
- dur_launch_to_on_load_event_us)
- tv_testcase_util.record_test_result(
- STARTUP_RECORD_NAME + "DurLaunchToBrowseUs", dur_launch_to_browse_us)
- tv_testcase_util.record_test_result(
- STARTUP_RECORD_NAME + "DurLaunchToUsableUs", dur_launch_to_usable_us)
-
- duration_navigate_to_on_load_recorder.on_end_test()
- duration_navigate_to_browse_recorder.on_end_test()
- duration_navigate_to_usable_recorder.on_end_test()
-
-
-if __name__ == "__main__":
- tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/video/__init__.py b/src/cobalt/webdriver_benchmarks/tests/performance/video/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance/video/__init__.py
+++ /dev/null
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/video/browse_to_watch.py b/src/cobalt/webdriver_benchmarks/tests/performance/video/browse_to_watch.py
deleted file mode 100755
index 248e73c..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance/video/browse_to_watch.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/python2
-"""Simple benchmark for starting a video from browse."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import sys
-
-# Add the base webdriver_benchmarks path
-sys.path.insert(0,
- os.path.dirname(
- os.path.dirname((os.path.dirname(
- os.path.dirname(os.path.realpath(__file__)))))))
-
-# pylint: disable=C6204,C6203
-import tv_testcase
-import tv_testcase_event_recorder
-import tv_testcase_util
-
-# selenium imports
-keys = tv_testcase_util.import_selenium_module("webdriver.common.keys")
-
-MAX_VIDEO_FAILURE_COUNT = 10
-MAX_SKIPPABLE_AD_COUNT = 8
-
-NUM_LOAD_TV_CALLS = 4
-NUM_ITERATIONS_PER_LOAD_TV_CALL = 25
-
-BROWSE_TO_WATCH_EVENT_NAME = "wbBrowseToWatch"
-BROWSE_TO_WATCH_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_UP
-
-WATCH_TO_BROWSE_EVENT_NAME = "wbWatchToBrowse"
-WATCH_TO_BROWSE_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_UP
-
-
-class BrowseToWatchTest(tv_testcase.TvTestCase):
-
- class VideoFailureException(BaseException):
- """Exception thrown when MAX_VIDEO_FAILURE_COUNT is exceeded."""
-
- class AdvertisementFailureException(BaseException):
- """Exception thrown when MAX_SKIPPABLE_AD_COUNT is exceeded."""
-
- def test_simple(self):
- recorder_options = tv_testcase_event_recorder.EventRecorderOptions(
- self, BROWSE_TO_WATCH_EVENT_NAME, BROWSE_TO_WATCH_EVENT_TYPE)
- recorder_options.record_animations = False
- recorder_options.record_video = True
- browse_to_watch_recorder = tv_testcase_event_recorder.EventRecorder(
- recorder_options)
-
- recorder_options = tv_testcase_event_recorder.EventRecorderOptions(
- self, WATCH_TO_BROWSE_EVENT_NAME, WATCH_TO_BROWSE_EVENT_TYPE)
- recorder_options.record_animations = False
- watch_to_browse_recorder = tv_testcase_event_recorder.EventRecorder(
- recorder_options)
-
- failure_count = 0
- skippable_ad_count = 0
-
- for _ in xrange(NUM_LOAD_TV_CALLS):
- self.load_tv()
-
- for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL):
- self.send_keys(keys.Keys.ARROW_DOWN)
- self.wait_for_processing_complete_after_focused_shelf()
-
- browse_to_watch_recorder.on_start_event()
- self.send_keys(keys.Keys.ENTER)
-
- if not self.wait_for_media_element_playing():
- failure_count += 1
- print("Video failed to play! {} events failed.".format(failure_count))
- if failure_count > MAX_VIDEO_FAILURE_COUNT:
- raise BrowseToWatchTest.VideoFailureException()
-
- self.send_keys(keys.Keys.ESCAPE)
- self.wait_for_processing_complete_after_focused_shelf()
- continue
-
- if self.skip_advertisement_if_playing():
- skippable_ad_count += 1
- print(
- "Encountered skippable ad! {} total.".format(skippable_ad_count))
- if skippable_ad_count > MAX_SKIPPABLE_AD_COUNT:
- raise BrowseToWatchTest.AdvertisementFailureException()
-
- self.wait_for_title_card_hidden()
- self.send_keys(keys.Keys.ESCAPE)
- self.wait_for_processing_complete_after_focused_shelf()
- continue
-
- browse_to_watch_recorder.on_end_event()
-
- # Wait for the title card hidden before sending the escape. Otherwise,
- # two escapes are required to exit the video.
- self.wait_for_title_card_hidden()
-
- watch_to_browse_recorder.on_start_event()
- self.send_keys(keys.Keys.ESCAPE)
- self.wait_for_processing_complete_after_focused_shelf()
- watch_to_browse_recorder.on_end_event()
-
- browse_to_watch_recorder.on_end_test()
- watch_to_browse_recorder.on_end_test()
-
-
-if __name__ == "__main__":
- tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance_non_video.py b/src/cobalt/webdriver_benchmarks/tests/performance_non_video.py
deleted file mode 100644
index f71a433..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance_non_video.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/python2
-"""Target for running non-video performance test cases."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import importlib
-import os
-import sys
-import unittest
-
-# The parent directory is a module
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
-
-# pylint: disable=C6204,C6203
-import tv_testcase
-
-
-def _add_test(test_suite, dir_path, test_name):
- if os.path.isfile(
- os.path.join(dir_path, "performance", "non_video", test_name + ".py")):
- print("Adding test: {}".format(test_name))
- test_suite.addTest(unittest.TestLoader().loadTestsFromModule(
- importlib.import_module("tests.performance.non_video." + test_name)))
-
-
-# pylint: disable=unused-argument
-def load_tests(loader, tests, pattern):
- """This is a Python unittest "load_tests protocol method."""
- test_suite = unittest.TestSuite()
- dir_path = os.path.dirname(__file__)
-
- # "startup" must be the first test added. The timings that it
- # records require it to run first.
- _add_test(test_suite, dir_path, "startup")
- _add_test(test_suite, dir_path, "browse_horizontal")
- _add_test(test_suite, dir_path, "browse_vertical")
- _add_test(test_suite, dir_path, "browse_to_guide")
- _add_test(test_suite, dir_path, "browse_to_search")
-
- return test_suite
-
-
-if __name__ == "__main__":
- tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance_video.py b/src/cobalt/webdriver_benchmarks/tests/performance_video.py
deleted file mode 100755
index 3784cc2..0000000
--- a/src/cobalt/webdriver_benchmarks/tests/performance_video.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python2
-"""Target for running video performance test cases."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import importlib
-import os
-import sys
-import unittest
-
-# The parent directory is a module
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
-
-# pylint: disable=C6204,C6203
-import tv_testcase
-
-
-def _add_test(test_suite, dir_path, test_name):
- if os.path.isfile(
- os.path.join(dir_path, "performance", "video", test_name + ".py")):
- print("Adding test: {}".format(test_name))
- test_suite.addTest(unittest.TestLoader().loadTestsFromModule(
- importlib.import_module("tests.performance.video." + test_name)))
-
-
-# pylint: disable=unused-argument
-def load_tests(loader, tests, pattern):
- """This is a Python unittest "load_tests protocol method."""
- test_suite = unittest.TestSuite()
- dir_path = os.path.dirname(__file__)
-
- _add_test(test_suite, dir_path, "browse_to_watch")
-
- return test_suite
-
-
-if __name__ == "__main__":
- tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tv.py b/src/cobalt/webdriver_benchmarks/tv.py
deleted file mode 100644
index 332b3c9..0000000
--- a/src/cobalt/webdriver_benchmarks/tv.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""CSS Constants."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-FOCUSED_GUIDE = '.focused.guide'
-FOCUSED_SEARCH = '.focused.search'
-FOCUSED_SHELF = '.focused.selected.shelf'
-FOCUSED_SHELF_TITLE = '.focused.selected.shelf .shelf-header-title .main'
-SKIP_AD_BUTTON_CAN_SKIP = '.skip-ad-button.canskip'
-SKIP_AD_BUTTON_HIDDEN = '.skip-ad-button.hidden'
-TITLE_CARD_HIDDEN = '.title-card.hidden'
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase.py b/src/cobalt/webdriver_benchmarks/tv_testcase.py
deleted file mode 100644
index dc49278..0000000
--- a/src/cobalt/webdriver_benchmarks/tv_testcase.py
+++ /dev/null
@@ -1,343 +0,0 @@
-"""Base class for WebDriver tests."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import json
-import logging
-import os
-import sys
-import time
-import unittest
-
-# This directory is a package
-sys.path.insert(0, os.path.abspath("."))
-# pylint: disable=C6204,C6203
-import c_val_names
-import tv
-import tv_testcase_runner
-import tv_testcase_util
-
-try:
- import custom_query_param_constants as query_param_constants
-except ImportError:
- import default_query_param_constants as query_param_constants
-
-# selenium imports
-# pylint: disable=C0103
-ActionChains = tv_testcase_util.import_selenium_module(
- submodule="webdriver.common.action_chains").ActionChains
-keys = tv_testcase_util.import_selenium_module("webdriver.common.keys")
-
-WINDOWDRIVER_CREATED_TIMEOUT_SECONDS = 30
-WEBMODULE_LOADED_TIMEOUT_SECONDS = 30
-PAGE_LOAD_WAIT_SECONDS = 30
-PROCESSING_TIMEOUT_SECONDS = 60
-HTML_SCRIPT_ELEMENT_EXECUTE_TIMEOUT_SECONDS = 30
-MEDIA_TIMEOUT_SECONDS = 30
-SKIP_AD_TIMEOUT_SECONDS = 30
-TITLE_CARD_HIDDEN_TIMEOUT_SECONDS = 30
-
-_is_initialized = False
-
-
-class TvTestCase(unittest.TestCase):
- """Base class for WebDriver tests.
-
- Style note: snake_case is used for function names here so as to match
- with an internal class with the same name.
- """
-
- class WindowDriverCreatedTimeoutException(BaseException):
- """Exception thrown when WindowDriver was not created in time."""
-
- class WebModuleLoadedTimeoutException(BaseException):
- """Exception thrown when WebModule was not loaded in time."""
-
- class ProcessingTimeoutException(BaseException):
- """Exception thrown when processing did not complete in time."""
-
- class HtmlScriptElementExecuteTimeoutException(BaseException):
- """Exception thrown when processing did not complete in time."""
-
- class TitleCardHiddenTimeoutException(BaseException):
- """Exception thrown when title card did not disappear in time."""
-
- @classmethod
- def setUpClass(cls):
- print("Running " + cls.__name__)
-
- @classmethod
- def tearDownClass(cls):
- print("Done " + cls.__name__)
-
- def setUp(self):
- global _is_initialized
- if not _is_initialized:
- # Initialize the tests.
- query_params = query_param_constants.INIT_QUERY_PARAMS
- triggers_reload = query_param_constants.INIT_QUERY_PARAMS_TRIGGER_RELOAD
- self.load_tv(query_params, triggers_reload)
- _is_initialized = True
-
- def get_webdriver(self):
- return tv_testcase_runner.GetWebDriver()
-
- def get_default_url(self):
- return tv_testcase_runner.GetDefaultUrl()
-
- def get_cval(self, cval_name):
- """Returns the Python object represented by a JSON cval string.
-
- Args:
- cval_name: Name of the cval.
- Returns:
- Python object represented by the JSON cval string
- """
- javascript_code = "return h5vcc.cVal.getValue('{}')".format(cval_name)
- json_result = self.get_webdriver().execute_script(javascript_code)
- if json_result is None:
- return None
- else:
- return json.loads(json_result)
-
- def load_blank(self):
- """Loads about:blank and waits for it to finish.
-
- Raises:
- Underlying WebDriver exceptions
- """
- self.clear_url_loaded_events()
- self.get_webdriver().get("about:blank")
- self.wait_for_url_loaded_events()
-
- def load_tv(self, query_params=None, triggers_reload=False):
- """Loads the main TV page and waits for it to display.
-
- Args:
- query_params: A dict containing additional query parameters.
- triggers_reload: Whether or not the navigation will trigger a reload.
- Raises:
- Underlying WebDriver exceptions
- """
- self.get_webdriver().execute_script("h5vcc.storage.clearCookies()")
- self.clear_url_loaded_events()
- self.get_webdriver().get(
- tv_testcase_util.generate_url(self.get_default_url(), query_params))
- self.wait_for_url_loaded_events()
- if triggers_reload:
- self.clear_url_loaded_events()
- self.wait_for_url_loaded_events()
- # Note that the internal tests use "expect_transition" which is
- # a mechanism that sets a maximum timeout for a "@with_retries"
- # decorator-driven success retry loop for subsequent webdriver requests.
- #
- # We'll skip that sophistication here.
- self.wait_for_processing_complete_after_focused_shelf()
-
- def poll_until_found(self, css_selector):
- """Polls until an element is found.
-
- Args:
- css_selector: A CSS selector
- Raises:
- Underlying WebDriver exceptions
- """
- start_time = time.time()
- while ((not self.find_elements(css_selector)) and
- (time.time() - start_time < PAGE_LOAD_WAIT_SECONDS)):
- time.sleep(1)
- self.assert_displayed(css_selector)
-
- def unique_find(self, unique_selector):
- """Finds and returns a uniquely selected element.
-
- Args:
- unique_selector: A CSS selector that will select only one element
- Raises:
- Underlying WebDriver exceptions
- AssertError: the element isn't unique
- Returns:
- Element
- """
- return self.find_elements(unique_selector, expected_num=1)[0]
-
- def assert_displayed(self, css_selector):
- """Asserts that an element is displayed.
-
- Args:
- css_selector: A CSS selector
- Raises:
- Underlying WebDriver exceptions
- AssertError: the element isn't found
- """
- # TODO does not actually assert that it's visible, like webdriver.py
- # probably does.
- self.assertTrue(self.unique_find(css_selector))
-
- def find_elements(self, css_selector, expected_num=None):
- """Finds elements based on a selector.
-
- Args:
- css_selector: A CSS selector
- expected_num: Expected number of matching elements
- Raises:
- Underlying WebDriver exceptions
- AssertError: expected_num isn't met
- Returns:
- Array of selected elements
- """
- elements = self.get_webdriver().find_elements_by_css_selector(css_selector)
- if expected_num is not None:
- self.assertEqual(len(elements), expected_num)
- return elements
-
- def send_keys(self, key_events):
- """Sends keys to whichever element currently has focus.
-
- Args:
- key_events: key events
-
- Raises:
- Underlying WebDriver exceptions
- """
- ActionChains(self.get_webdriver()).send_keys(key_events).perform()
-
- def clear_url_loaded_events(self):
- """Clear the events that indicate that Cobalt finished loading a URL."""
- tv_testcase_runner.GetWindowDriverCreated().clear()
- tv_testcase_runner.GetWebModuleLoaded().clear()
-
- def wait_for_url_loaded_events(self):
- """Wait for the events indicating that Cobalt finished loading a URL."""
- windowdriver_created = tv_testcase_runner.GetWindowDriverCreated()
- if not windowdriver_created.wait(WINDOWDRIVER_CREATED_TIMEOUT_SECONDS):
- raise TvTestCase.WindowDriverCreatedTimeoutException()
-
- webmodule_loaded = tv_testcase_runner.GetWebModuleLoaded()
- if not webmodule_loaded.wait(WEBMODULE_LOADED_TIMEOUT_SECONDS):
- raise TvTestCase.WebModuleLoadedTimeoutException()
-
- def wait_for_processing_complete_after_focused_shelf(self):
- """Waits for Cobalt to focus on a shelf and complete pending layouts."""
- self.poll_until_found(tv.FOCUSED_SHELF)
- self.assert_displayed(tv.FOCUSED_SHELF_TITLE)
- self.wait_for_processing_complete()
-
- def wait_for_processing_complete(self, check_animations=True):
- """Waits for Cobalt to complete processing.
-
- This method requires two consecutive iterations through its loop where
- Cobalt is not processing before treating processing as complete. This
- protects against a brief window between two different processing sections
- being mistaken as completed processing.
-
- Args:
- check_animations: Whether or not animations should be checked when
- determining if processing is complete.
-
- Raises:
- ProcessingTimeoutException: Processing is not complete within the
- required time.
- """
- start_time = time.time()
-
- # First simply check for whether or not the event is still processing.
- # There's no need to check anything else while the event is still going on.
- # Once it is done processing, it won't get re-set, so there's no need to
- # re-check it.
- while self.get_cval(c_val_names.event_is_processing()):
- if time.time() - start_time > PROCESSING_TIMEOUT_SECONDS:
- raise TvTestCase.ProcessingTimeoutException()
-
- time.sleep(0.1)
-
- # Now wait for all processing to complete in Cobalt.
- count = 0
- while count < 2:
- if self.is_processing(check_animations):
- count = 0
- else:
- count += 1
-
- if time.time() - start_time > PROCESSING_TIMEOUT_SECONDS:
- raise TvTestCase.ProcessingTimeoutException()
-
- time.sleep(0.1)
-
- def is_processing(self, check_animations):
- """Checks to see if Cobalt is currently processing."""
- return (self.get_cval(c_val_names.count_dom_active_java_script_events()) or
- self.get_cval(c_val_names.layout_is_dirty()) or
- (check_animations and
- self.get_cval(c_val_names.renderer_has_active_animations())) or
- self.get_cval(c_val_names.count_image_cache_loading_resources()))
-
- def wait_for_html_script_element_execute_count(self, required_count):
- """Waits for specified number of html script element Execute() calls.
-
- Args:
- required_count: the number of executions that must occur
-
- Raises:
- HtmlScriptElementExecuteTimeoutException: The required html script element
- executions did not occur within the required time.
- """
- start_time = time.time()
- while self.get_cval(
- c_val_names.count_dom_html_script_element_execute()) < required_count:
- if time.time() - start_time > HTML_SCRIPT_ELEMENT_EXECUTE_TIMEOUT_SECONDS:
- raise TvTestCase.HtmlScriptElementExecuteTimeoutException()
- time.sleep(0.1)
-
- def wait_for_media_element_playing(self):
- """Waits for a video to begin playing.
-
- Returns:
- Whether or not the video started.
- """
- start_time = time.time()
- while self.get_cval(
- c_val_names.event_duration_dom_video_start_delay()) == 0:
- if time.time() - start_time > MEDIA_TIMEOUT_SECONDS:
- return False
- time.sleep(0.1)
-
- return True
-
- def skip_advertisement_if_playing(self):
- """Waits to skip an ad if it is encountered.
-
- Returns:
- True if a skippable advertisement was encountered
- """
- start_time = time.time()
- if not self.find_elements(tv.SKIP_AD_BUTTON_HIDDEN):
- while not self.find_elements(tv.SKIP_AD_BUTTON_CAN_SKIP):
- if time.time() - start_time > SKIP_AD_TIMEOUT_SECONDS:
- return True
- time.sleep(0.1)
- self.send_keys(keys.Keys.ENTER)
- self.wait_for_processing_complete(False)
- return True
-
- return False
-
- def wait_for_title_card_hidden(self):
- """Waits for the title to disappear while a video is playing.
-
- Raises:
- TitleCardHiddenTimeoutException: The title card did not become hidden in
- the required time.
- """
- start_time = time.time()
- while not self.find_elements(tv.TITLE_CARD_HIDDEN):
- if time.time() - start_time > TITLE_CARD_HIDDEN_TIMEOUT_SECONDS:
- raise TvTestCase.TitleCardHiddenTimeoutException()
- time.sleep(1)
-
-
-def main():
- logging.basicConfig(level=logging.DEBUG)
- tv_testcase_runner.main()
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py b/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py
deleted file mode 100644
index 5905e84..0000000
--- a/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py
+++ /dev/null
@@ -1,262 +0,0 @@
-#!/usr/bin/python2
-"""Records stats on an event injected by a benchmark test."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import c_val_names
-import tv_testcase_util
-
-
-class EventRecorderOptions(object):
- """Contains all of the parameters needed by EventRecorder."""
-
- def __init__(self, test, event_name, event_type):
- """Initializes the event recorder options.
-
- Args:
- test: specific benchmark test being run
- event_name: name of the event being recorded
- event_type: type of event being recorded (tv_testcase_util.py)
- """
- self.test = test
- self.event_name = event_name
- self.event_type = event_type
-
- self.record_animations = True
- self.record_video = False
-
-
-class EventRecorder(object):
- """Records stats on an event injected by a benchmark test.
-
- Handles collecting event data over all of the instances of a specific event
- injected by a benchmark test and records statistics on the data when the test
- ends. The specific event types that can be injected are listed within
- tv_testcase_util.py.
-
- Both rasterize animations and video start delay data can potentially be
- recorded, depending on the |record_animations| and |record_video| option
- flags.
- """
-
- def __init__(self, options):
- """Initializes the event recorder.
-
- Handles setting up this event recorder, including creating all of its
- recorders, based upon the passed in options.
-
- Args:
- options: the settings to use in creating this event recorder
- """
- self.test = options.test
- self.event_name = options.event_name
- self.event_type = options.event_type
-
- self.render_tree_failure_count = 0
-
- # Each entry in the list contains a tuple with a key and value recorder.
- self.value_dictionary_recorders = []
-
- # Optional animations recorders
- self.animations_recorder = None
- self.animations_start_delay_recorder = None
- self.animations_end_delay_recorder = None
-
- # Optional video recorders
- self.video_delay_recorder = None
-
- # Count record strategies
- count_record_strategies = []
- count_record_strategies.append(tv_testcase_util.RecordStrategyMean())
- count_record_strategies.append(tv_testcase_util.RecordStrategyMedian())
- count_record_strategies.append(tv_testcase_util.RecordStrategyMax())
-
- # Duration record strategies
- duration_record_strategies = []
- duration_record_strategies.append(tv_testcase_util.RecordStrategyMean())
- duration_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(25))
- duration_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(50))
- duration_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(75))
- duration_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(95))
-
- # Video delay record strategies
- video_delay_record_strategies = []
- video_delay_record_strategies.append(tv_testcase_util.RecordStrategyMean())
- video_delay_record_strategies.append(tv_testcase_util.RecordStrategyMin())
- video_delay_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(25))
- video_delay_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(50))
- video_delay_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(75))
- video_delay_record_strategies.append(
- tv_testcase_util.RecordStrategyPercentile(95))
- video_delay_record_strategies.append(tv_testcase_util.RecordStrategyMax())
-
- # Dictionary count recorders
- self._add_value_dictionary_recorder("CntDomEventListeners",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntDomNodes", count_record_strategies)
- self._add_value_dictionary_recorder("CntDomHtmlElements",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntDomDocumentHtmlElements",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntDomHtmlElementsCreated",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntDomUpdateMatchingRules",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntDomUpdateComputedStyle",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntDomGenerateHtmlComputedStyle",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntDomGeneratePseudoComputedStyle",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntLayoutBoxes",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntLayoutBoxesCreated",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntLayoutUpdateSize",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntLayoutRenderAndAnimate",
- count_record_strategies)
- self._add_value_dictionary_recorder("CntLayoutUpdateCrossReferences",
- count_record_strategies)
-
- # Dictionary duration recorders
- self._add_value_dictionary_recorder("DurTotalUs",
- duration_record_strategies)
- self._add_value_dictionary_recorder("DurDomInjectEventUs",
- duration_record_strategies)
- self._add_value_dictionary_recorder("DurDomRunAnimationFrameCallbacksUs",
- duration_record_strategies)
- self._add_value_dictionary_recorder("DurDomUpdateComputedStyleUs",
- duration_record_strategies)
- self._add_value_dictionary_recorder("DurLayoutBoxTreeUs",
- duration_record_strategies)
- self._add_value_dictionary_recorder("DurLayoutBoxTreeBoxGenerationUs",
- duration_record_strategies)
- self._add_value_dictionary_recorder("DurLayoutBoxTreeUpdateUsedSizesUs",
- duration_record_strategies)
- self._add_value_dictionary_recorder("DurLayoutRenderAndAnimateUs",
- duration_record_strategies)
-
- self.count_render_trees_recorder = tv_testcase_util.ResultsRecorder(
- self.event_name + "CntRenderTrees", count_record_strategies)
- self.count_requested_images_recorder = tv_testcase_util.ResultsRecorder(
- self.event_name + "CntRequestedImages", count_record_strategies)
-
- # Optional animations recorder
- if options.record_animations:
- self.animations_recorder = tv_testcase_util.ResultsRecorder(
- self.event_name + "DurRasterizeAnimationsUs",
- duration_record_strategies)
- self.animations_start_delay_recorder = tv_testcase_util.ResultsRecorder(
- self.event_name + "DurAnimationsStartDelayUs",
- duration_record_strategies)
- self.animations_end_delay_recorder = tv_testcase_util.ResultsRecorder(
- self.event_name + "DurAnimationsEndDelayUs",
- duration_record_strategies)
-
- self.final_render_tree_delay_recorder = tv_testcase_util.ResultsRecorder(
- self.event_name + "DurFinalRenderTreeDelayUs",
- duration_record_strategies)
-
- # Optional video recorder
- if options.record_video:
- self.video_delay_recorder = tv_testcase_util.ResultsRecorder(
- self.event_name + "DurVideoStartDelayUs",
- video_delay_record_strategies)
-
- def _add_value_dictionary_recorder(self, key, record_strategies):
- recorder = tv_testcase_util.ResultsRecorder(self.event_name + key,
- record_strategies)
- self.value_dictionary_recorders.append((key, recorder))
-
- def on_start_event(self):
- """Handles logic related to the start of the event instance."""
- self.count_render_trees_start = self.test.get_cval(
- c_val_names.count_rasterize_new_render_tree())
- self.count_requested_images_start = self.test.get_cval(
- c_val_names.count_image_cache_requested_resources())
-
- def on_end_event(self):
- """Handles logic related to the end of the event instance."""
-
- value_dictionary = self.test.get_cval(
- c_val_names.event_value_dictionary(self.event_type))
-
- # If the event failed to produce a render tree, then its data is not
- # collected. Log the failure and return.
- if not value_dictionary or not value_dictionary.get("ProducedRenderTree"):
- self.render_tree_failure_count += 1
- print("{} event failed to produce render tree! {} events failed.".format(
- self.event_name, self.render_tree_failure_count))
- return
-
- event_start_time = value_dictionary.get("StartTime")
-
- # Record all of the values from the event.
- for value_dictionary_recorder in self.value_dictionary_recorders:
- value = value_dictionary.get(value_dictionary_recorder[0])
- if value is not None:
- value_dictionary_recorder[1].collect_value(value)
-
- self.count_render_trees_end = self.test.get_cval(
- c_val_names.count_rasterize_new_render_tree())
- self.count_render_trees_recorder.collect_value(
- self.count_render_trees_end - self.count_render_trees_start)
-
- self.count_requested_images_end = self.test.get_cval(
- c_val_names.count_image_cache_requested_resources())
- self.count_requested_images_recorder.collect_value(
- self.count_requested_images_end - self.count_requested_images_start)
-
- if self.animations_recorder:
- animation_entries = self.test.get_cval(
- c_val_names.rasterize_animations_entry_list())
- for value in animation_entries:
- self.animations_recorder.collect_value(value)
-
- animations_start_time = self.test.get_cval(
- c_val_names.time_rasterize_animations_start())
- self.animations_start_delay_recorder.collect_value(
- animations_start_time - event_start_time)
- animations_end_time = self.test.get_cval(
- c_val_names.time_rasterize_animations_end())
- self.animations_end_delay_recorder.collect_value(animations_end_time -
- event_start_time)
-
- final_render_tree_time = self.test.get_cval(
- c_val_names.time_rasterize_new_render_tree())
- self.final_render_tree_delay_recorder.collect_value(final_render_tree_time -
- event_start_time)
-
- if self.video_delay_recorder:
- self.video_delay_recorder.collect_value(
- self.test.get_cval(
- c_val_names.event_duration_dom_video_start_delay()))
-
- def on_end_test(self):
- """Handles logic related to the end of the test."""
-
- for value_dictionary_recorder in self.value_dictionary_recorders:
- value_dictionary_recorder[1].on_end_test()
-
- self.count_render_trees_recorder.on_end_test()
- self.count_requested_images_recorder.on_end_test()
-
- if self.animations_recorder:
- self.animations_recorder.on_end_test()
- self.animations_start_delay_recorder.on_end_test()
- self.animations_end_delay_recorder.on_end_test()
-
- self.final_render_tree_delay_recorder.on_end_test()
-
- if self.video_delay_recorder:
- self.video_delay_recorder.on_end_test()
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py b/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py
deleted file mode 100755
index 45c8556..0000000
--- a/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py
+++ /dev/null
@@ -1,297 +0,0 @@
-#!/usr/bin/python2
-"""Runs webdriver-based Cobalt benchmark tests."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import argparse
-import importlib
-import inspect
-import os
-import re
-import sys
-import thread
-import threading
-import unittest
-
-import tv_testcase_util
-
-arg_parser = argparse.ArgumentParser(
- description="Runs Webdriver-based Cobalt benchmark tests")
-arg_parser.add_argument(
- "-p",
- "--platform",
- help="Cobalt platform, eg 'linux-x64x11'."
- "Fetched from environment if absent.")
-arg_parser.add_argument(
- "-e",
- "--executable",
- help="Path to Cobalt executable. "
- "Auto-derived if absent.")
-arg_parser.add_argument(
- "-c",
- "--config",
- choices=["debug", "devel", "qa", "gold"],
- help="Build config (eg, 'qa' or 'devel'). Not used if "
- "--executable is specified. Fetched from environment "
- "if needed and absent.")
-arg_parser.add_argument(
- "-d",
- "--devkit_name",
- help="Devkit or IP address for app_launcher."
- "Current hostname used if absent.")
-arg_parser.add_argument(
- "--command_line",
- nargs="*",
- help="Command line arguments to pass to the Cobalt executable.")
-arg_parser.add_argument(
- "--url", help="Specifies the URL to run the tests against.")
-arg_parser.add_argument(
- "-o", "--log_file", help="Logfile pathname. stdout if absent.")
-
-# Pattern to match Cobalt log line for when the WebDriver port has been
-# opened.
-RE_WEBDRIVER_LISTEN = re.compile(r"Starting WebDriver server on port (\d+)")
-# Pattern to match Cobalt log line for when a WindowDriver has been created.
-RE_WINDOWDRIVER_CREATED = re.compile(
- r"^\[\d+/\d+:INFO:browser_module\.cc\(\d+\)\] Created WindowDriver: ID=\S+")
-# Pattern to match Cobalt log line for when a WebModule is has been loaded.
-RE_WEBMODULE_LOADED = re.compile(
- r"^\[\d+/\d+:INFO:browser_module\.cc\(\d+\)\] Loaded WebModule")
-
-DEFAULT_STARTUP_TIMEOUT_SECONDS = 2 * 60
-WEBDRIVER_HTTP_TIMEOUT_SECONDS = 2 * 60
-COBALT_EXIT_TIMEOUT_SECONDS = 5
-
-COBALT_WEBDRIVER_CAPABILITIES = {
- "browserName": "cobalt",
- "javascriptEnabled": True,
- "platform": "LINUX"
-}
-
-_webdriver = None
-_windowdriver_created = threading.Event()
-_webmodule_loaded = threading.Event()
-_default_url = "https://www.youtube.com/tv"
-
-
-def GetWebDriver():
- """Returns the active connect WebDriver instance."""
- return _webdriver
-
-
-def GetWindowDriverCreated():
- """Returns the WindowDriver created instance."""
- return _windowdriver_created
-
-
-def GetWebModuleLoaded():
- """Returns the WebModule loaded instance."""
- return _webmodule_loaded
-
-
-def GetDefaultUrl():
- """Returns the default url to use with tests."""
- return _default_url
-
-
-class TimeoutException(Exception):
- pass
-
-
-class CobaltRunner(object):
- """Runs a Cobalt browser w/ a WebDriver client attached."""
- test_script_started = threading.Event()
- selenium_webdriver_module = None
- webdriver = None
- launcher = None
- log_file_path = None
- thread = None
- failed = False
- should_exit = threading.Event()
-
- def __init__(self, platform, executable, devkit_name, command_line_args,
- default_url, log_file_path):
- global _default_url
- if default_url is not None:
- _default_url = default_url
-
- self.selenium_webdriver_module = tv_testcase_util.import_selenium_module(
- "webdriver")
-
- script_path = os.path.realpath(inspect.getsourcefile(lambda: 0))
- app_launcher_path = os.path.realpath(
- os.path.join(
- os.path.dirname(script_path), "..", "..", "tools", "lbshell"))
- sys.path.append(app_launcher_path)
- app_launcher = importlib.import_module("app_launcher")
- self.launcher = app_launcher.CreateLauncher(
- platform, executable, devkit_name=devkit_name, close_output_file=False)
-
- args = []
- if command_line_args is not None:
- for command_line_arg in command_line_args:
- args.append("--" + command_line_arg)
- args.append("--enable_webdriver")
- args.append("--debug_console=off")
- args.append("--disable_image_animations")
- args.append("--null_savegame")
- args.append("--url=" + _default_url)
-
- self.launcher.SetArgs(args)
- self.launcher.SetOutputCallback(self._HandleLine)
- self.log_file_path = log_file_path
- self.log_file = None
-
- def __enter__(self):
- self.thread = threading.Thread(target=self.Run)
- self.thread.start()
- try:
- self.WaitForStart()
- except KeyboardInterrupt:
- # potentially from thread.interrupt_main(). We will treat as
- # a timeout regardless
- self.SetShouldExit(failed=True)
- raise TimeoutException
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- # The unittest module terminates with a SystemExit
- # If this is a successful exit, then this is a successful run
- success = exc_type is None or (exc_type is SystemExit and
- not exc_value.code)
- self.SetShouldExit(failed=not success)
- self.thread.join(COBALT_EXIT_TIMEOUT_SECONDS)
-
- def _HandleLine(self, line):
- """Internal log line callback."""
-
- if RE_WINDOWDRIVER_CREATED.search(line):
- _windowdriver_created.set()
- return
-
- if RE_WEBMODULE_LOADED.search(line):
- _webmodule_loaded.set()
- return
-
- # Wait for WebDriver port here then connect
- if self.test_script_started.is_set():
- return
-
- match = RE_WEBDRIVER_LISTEN.search(line)
- if not match:
- return
-
- port = match.group(1)
- print("WebDriver port opened:" + port + "\n", file=self.log_file)
- self._StartWebdriver(port)
-
- def SetShouldExit(self, failed=False):
- """Indicates cobalt process should exit."""
- self.failed = failed
- self.should_exit.set()
- self.launcher.SendKill()
-
- def _GetProcessIPAddress(self):
- return self.launcher.GetProcessIPAddress()
-
- def _StartWebdriver(self, port):
- global _webdriver
- url = "http://{}:{}/".format(self._GetProcessIPAddress(), port)
- self.webdriver = self.selenium_webdriver_module.Remote(
- url, COBALT_WEBDRIVER_CAPABILITIES)
- self.webdriver.command_executor.set_timeout(WEBDRIVER_HTTP_TIMEOUT_SECONDS)
- print("Selenium Connected\n", file=self.log_file)
- _webdriver = self.webdriver
- self.test_script_started.set()
-
- def WaitForStart(self):
- """Waits for the webdriver client to attach to Cobalt."""
- startup_timeout_seconds = self.launcher.GetStartupTimeout()
- if not startup_timeout_seconds:
- startup_timeout_seconds = DEFAULT_STARTUP_TIMEOUT_SECONDS
-
- if not self.test_script_started.wait(startup_timeout_seconds):
- self.SetShouldExit(failed=True)
- raise TimeoutException
- print("Cobalt started", file=self.log_file)
-
- def Run(self):
- """Thread run routine."""
-
- # Use stdout if log_file_path is unspecified
- # If log_file_path is specified, make sure to close it
- to_close = None
- try:
- if self.log_file_path:
- self.log_file = open(self.log_file_path, "w")
- to_close = self.log_file
- else:
- self.log_file = sys.stdout
-
- self.launcher.SetOutputFile(self.log_file)
- print("Running launcher", file=self.log_file)
- self.launcher.Run()
- print(
- "Cobalt terminated. failed: " + str(self.failed), file=self.log_file)
- # This is watched for in webdriver_benchmark_test.py
- if not self.failed:
- print("{}\n".format(tv_testcase_util.TEST_COMPLETE))
- # pylint: disable=broad-except
- except Exception as ex:
- print("Exception running Cobalt " + str(ex), file=sys.stderr)
- finally:
- if to_close:
- to_close.close()
- if not self.should_exit.is_set():
- # If the main thread is not expecting us to exit,
- # we must interrupt it.
- thread.interrupt_main()
- return 0
-
-
-def GetCobaltExecutablePath(platform, config):
- """Auto-derives a path to a cobalt executable."""
- if config is None:
- try:
- config = os.environ["BUILD_TYPE"]
- except KeyError:
- sys.stderr.write("Must specify --config or --executable\n")
- sys.exit(1)
- script_path = os.path.realpath(inspect.getsourcefile(lambda: 0))
- script_dir = os.path.dirname(script_path)
- out_dir = os.path.join(script_dir, "..", "..", "out")
- executable_directory = os.path.join(out_dir, "{}_{}".format(platform, config))
- return os.path.join(executable_directory, "cobalt")
-
-
-def main():
- args = arg_parser.parse_args()
- # Keep unittest module from seeing these args
- sys.argv = sys.argv[:1]
-
- platform = args.platform
- if platform is None:
- try:
- platform = os.environ["BUILD_PLATFORM"]
- except KeyError:
- sys.stderr.write("Must specify --platform\n")
- sys.exit(1)
-
- executable = args.executable
- if executable is None:
- executable = GetCobaltExecutablePath(platform, args.config)
-
- try:
- with CobaltRunner(platform, executable, args.devkit_name, args.command_line,
- args.url, args.log_file) as runner:
- unittest.main(testRunner=unittest.TextTestRunner(
- verbosity=0, stream=runner.log_file))
- except TimeoutException:
- print("Timeout waiting for Cobalt to start", file=sys.stderr)
- sys.exit(1)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase_util.py b/src/cobalt/webdriver_benchmarks/tv_testcase_util.py
deleted file mode 100644
index 6cb9a52..0000000
--- a/src/cobalt/webdriver_benchmarks/tv_testcase_util.py
+++ /dev/null
@@ -1,200 +0,0 @@
-"""Provides constants and functions needed by tv_testcase classes."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import importlib
-import json
-import sys
-
-# pylint: disable=C6204
-from urllib import urlencode
-import urlparse
-
-import container_util
-
-try:
- import custom_query_param_constants as query_param_constants
-except ImportError:
- import default_query_param_constants as query_param_constants
-
-# These are watched for in webdriver_benchmark_test.py
-TEST_RESULT = "webdriver_benchmark TEST RESULT"
-TEST_COMPLETE = "webdriver_benchmark TEST COMPLETE"
-
-# These are event types that can be injected
-EVENT_TYPE_KEY_DOWN = "KeyDown"
-EVENT_TYPE_KEY_UP = "KeyUp"
-
-
-def import_selenium_module(submodule=None):
- """Dynamically imports a selenium.webdriver submodule.
-
- This is done because selenium 3.0 is not commonly pre-installed
- on workstations, and we want to have a friendly error message for that
- case.
-
- Args:
- submodule: module subpath underneath "selenium.webdriver"
- Returns:
- appropriate module
- """
- if submodule:
- module_path = ".".join(("selenium", submodule))
- else:
- module_path = "selenium"
- # As of this writing, Google uses selenium 3.0.0b2 internally, so
- # thats what we will target here as well.
- try:
- module = importlib.import_module(module_path)
- if submodule is None:
- # Only the top-level module has __version__
- if not module.__version__.startswith("3.0"):
- raise ImportError("Not version 3.0.x")
- except ImportError:
- sys.stderr.write("Could not import {}\n"
- "Please install selenium >= 3.0.0b2.\n"
- "Commonly: \"sudo pip install 'selenium>=3.0.0b2'\"\n"
- .format(module_path))
- sys.exit(1)
- return module
-
-
-def generate_url(default_url, query_params_override=None):
- """Returns the URL indicated by the path and query parameters.
-
- Args:
- default_url: the default url to use; its query params may be overridden
- query_params_override: optional query params that override the ones
- contained within the default URL
- Returns:
- the url generated from the parameters
- """
- parsed_url = list(urlparse.urlparse(default_url))
-
- query_params = query_param_constants.BASE_QUERY_PARAMS
- if query_params_override:
- query_params.update(query_params_override)
- else:
- query_params.update(urlparse.parse_qsl(parsed_url[4]))
-
- parsed_url[4] = urlencode(query_params, doseq=True)
- return urlparse.urlunparse(parsed_url)
-
-
-def record_test_result(name, result):
- """Records an individual scalar result of a benchmark test.
-
- Args:
- name: string name of test case
- result: Test result. Must be JSON encodable scalar.
- """
- value_to_record = result
-
- string_value_to_record = json.JSONEncoder().encode(value_to_record)
- print("{}: {} {}\n".format(TEST_RESULT, name, string_value_to_record))
- sys.stdout.flush()
-
-
-class RecordStrategyMax(object):
- """"Records the max of an array of values."""
-
- def run(self, name, values):
- """Records the max of an array of values.
-
- Args:
- name: string name of test case
- values: must be array of JSON encodable scalar
- """
- record_test_result("{}Max".format(name), max(values))
-
-
-class RecordStrategyMin(object):
- """"Records the min of an array of values."""
-
- def run(self, name, values):
- """Records the min of an array of values.
-
- Args:
- name: string name of test case
- values: must be array of JSON encodable scalar
- """
- record_test_result("{}Min".format(name), min(values))
-
-
-class RecordStrategyMean(object):
- """"Records the mean of an array of values."""
-
- def run(self, name, values):
- """Records the mean of an array of values.
-
- Args:
- name: string name of test case
- values: must be array of JSON encodable scalar
- """
- record_test_result("{}Mean".format(name), container_util.mean(values))
-
-
-class RecordStrategyMedian(object):
- """"Records the median of an array of test results."""
-
- def run(self, name, values):
- """Records the median of an array of values.
-
- Args:
- name: string name of test case
- values: must be array of JSON encodable scalar
- """
- record_test_result("{}Median".format(name),
- container_util.percentile(values, 50))
-
-
-class RecordStrategyPercentile(object):
- """"Records the specified percentile of an array of test results."""
-
- def __init__(self, percentile):
- """Initializes the record strategy.
-
- Args:
- percentile: the percentile to record
- """
- self.percentile = percentile
-
- def run(self, name, values):
- """Records the percentile of an array of values.
-
- Args:
- name: string name of test case
- values: must be array of JSON encodable scalar
- Raises:
- RuntimeError: Raised on invalid args.
- """
- record_test_result("{}Pct{}".format(name, self.percentile),
- container_util.percentile(values, self.percentile))
-
-
-class ResultsRecorder(object):
- """"Collects values and records results after a benchmark test ends."""
-
- def __init__(self, name, record_strategies):
- """Initializes the value recorder.
-
- Args:
- name: the name to use when recording test results
- record_strategies: the strategies to use when the test ends
- """
- self.name = name
- self.record_strategies = record_strategies
- self.values = []
-
- def collect_value(self, value):
- self.values.append(value)
-
- def on_end_test(self):
- """Handles logic related to the end of the benchmark test."""
-
- # Only run the strategies if values have been collected.
- if self.values:
- for record_strategy in self.record_strategies:
- record_strategy.run(self.name, self.values)
diff --git a/src/net/url_request/url_request_job_manager.cc b/src/net/url_request/url_request_job_manager.cc
index 1ab6814..ed0f5db 100644
--- a/src/net/url_request/url_request_job_manager.cc
+++ b/src/net/url_request/url_request_job_manager.cc
@@ -39,9 +39,7 @@
static const SchemeToFactory kBuiltinFactories[] = {
{"https", URLRequestHttpJob::Factory},
{"data", URLRequestDataJob::Factory},
-#if !defined(COBALT_FORCE_HTTPS)
{ "http", URLRequestHttpJob::Factory },
-#endif
#if defined(COBALT_ENABLE_FILE_SCHEME)
{ "file", URLRequestFileJob::Factory },
#endif
diff --git a/src/starboard/client_porting/eztime/eztime.cc b/src/starboard/client_porting/eztime/eztime.cc
index 10c86f4..aa4f737 100644
--- a/src/starboard/client_porting/eztime/eztime.cc
+++ b/src/starboard/client_porting/eztime/eztime.cc
@@ -115,8 +115,17 @@
SB_DCHECK(value);
SB_DCHECK(out_exploded);
UErrorCode status = U_ZERO_ERROR;
+
+ // Always query the time using a gregorian calendar. This is
+ // implied in opengroup documentation for tm struct, even though it is not
+ // specified. E.g. in gmtime's documentation, it states that UTC time is
+ // used, and in tm struct's documentation it is specified that year should
+ // be an offset from 1900.
+
+ // See:
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/gmtime.html
UCalendar* calendar = ucal_open(GetTimeZoneId(timezone), -1,
- uloc_getDefault(), UCAL_DEFAULT, &status);
+ uloc_getDefault(), UCAL_GREGORIAN, &status);
if (!calendar) {
return false;
}
@@ -157,8 +166,17 @@
EzTimeZone timezone) {
SB_DCHECK(exploded);
UErrorCode status = U_ZERO_ERROR;
+
+ // Always query the time using a gregorian calendar. This is
+ // implied in opengroup documentation for tm struct, even though it is not
+ // specified. E.g. in gmtime's documentation, it states that UTC time is
+ // used, and in tm struct's documentation it is specified that year should
+ // be an offset from 1900.
+
+ // See:
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/gmtime.html
UCalendar* calendar = ucal_open(GetTimeZoneId(timezone), -1,
- uloc_getDefault(), UCAL_DEFAULT, &status);
+ uloc_getDefault(), UCAL_GREGORIAN, &status);
if (!calendar) {
EzTimeValue zero_time = {};
return zero_time;
diff --git a/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc b/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc
index 0a96110..bdf679d 100644
--- a/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc
+++ b/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc
@@ -257,6 +257,14 @@
}
}
+ std::string cryptoblockformat =
+ mime_type.GetParamStringValue("cryptoblockformat", "");
+ if (!cryptoblockformat.empty()) {
+ if (mime_type.subtype() != "webm" || cryptoblockformat != "subsample") {
+ return kSbMediaSupportTypeNotSupported;
+ }
+ }
+
int width = 0;
int height = 0;
int fps = 0;