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;