diff --git a/DEPS b/DEPS
index d4d41eb..40a49997 100644
--- a/DEPS
+++ b/DEPS
@@ -39,7 +39,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '262a71b7f95ce98ff3dd8dba845afbd724470903',
+  'skia_revision': '776d49b41bb2aaa77f1d02a06963ff4266b502be',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index 7e39d1cd..484259b 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -220,7 +220,7 @@
       network_session_params;
   ApplyCmdlineOverridesToNetworkSessionParams(&network_session_params);
   builder.set_http_network_session_params(network_session_params);
-  builder.SetSpdyAndQuicEnabled(true, true);
+  builder.SetSpdyAndQuicEnabled(true, false);
 
   scoped_ptr<net::MappedHostResolver> host_resolver(new net::MappedHostResolver(
       net::HostResolver::CreateDefaultResolver(nullptr)));
diff --git a/base/command_line.cc b/base/command_line.cc
index c2ce33d..e2dde1cd 100644
--- a/base/command_line.cc
+++ b/base/command_line.cc
@@ -75,7 +75,11 @@
   bool parse_switches = true;
   for (size_t i = 1; i < argv.size(); ++i) {
     CommandLine::StringType arg = argv[i];
+#if defined(OS_WIN)
     TrimWhitespace(arg, TRIM_ALL, &arg);
+#else
+    TrimWhitespaceASCII(arg, TRIM_ALL, &arg);
+#endif
 
     CommandLine::StringType switch_string;
     CommandLine::StringType switch_value;
@@ -263,7 +267,11 @@
 }
 
 void CommandLine::SetProgram(const FilePath& program) {
+#if defined(OS_WIN)
   TrimWhitespace(program.value(), TRIM_ALL, &argv_[0]);
+#else
+  TrimWhitespaceASCII(program.value(), TRIM_ALL, &argv_[0]);
+#endif
 }
 
 bool CommandLine::HasSwitch(const base::StringPiece& switch_string) const {
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index 731a77d..72b85006 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -403,14 +403,6 @@
   return TrimStringPieceT(input, StringPiece(kWhitespaceASCII), positions);
 }
 
-// This function is only for backward-compatibility.
-// To be removed when all callers are updated.
-TrimPositions TrimWhitespace(const std::string& input,
-                             TrimPositions positions,
-                             std::string* output) {
-  return TrimWhitespaceASCII(input, positions, output);
-}
-
 template<typename STR>
 STR CollapseWhitespaceT(const STR& text,
                         bool trim_sequences_with_line_breaks) {
diff --git a/base/strings/string_util.h b/base/strings/string_util.h
index 3976111..af7b6e6ae9 100644
--- a/base/strings/string_util.h
+++ b/base/strings/string_util.h
@@ -243,12 +243,6 @@
 BASE_EXPORT StringPiece TrimWhitespaceASCII(StringPiece input,
                                             TrimPositions positions);
 
-// Deprecated. This function is only for backward compatibility and calls
-// TrimWhitespaceASCII().
-BASE_EXPORT TrimPositions TrimWhitespace(const std::string& input,
-                                         TrimPositions positions,
-                                         std::string* output);
-
 // Searches  for CR or LF characters.  Removes all contiguous whitespace
 // strings that contain them.  This is useful when trying to deal with text
 // copied from terminals.
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc
index 765ba83..1db7746 100644
--- a/base/strings/string_util_unittest.cc
+++ b/base/strings/string_util_unittest.cc
@@ -250,7 +250,7 @@
   for (size_t i = 0; i < arraysize(trim_cases_ascii); ++i) {
     const trim_case_ascii& value = trim_cases_ascii[i];
     EXPECT_EQ(value.return_value,
-              TrimWhitespace(value.input, value.positions, &output_ascii));
+              TrimWhitespaceASCII(value.input, value.positions, &output_ascii));
     EXPECT_EQ(value.output, output_ascii);
   }
 }
diff --git a/cc/base/switches.cc b/cc/base/switches.cc
index 13a9735..af836e3f 100644
--- a/cc/base/switches.cc
+++ b/cc/base/switches.cc
@@ -56,10 +56,10 @@
 // Enables the GPU benchmarking extension
 const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking";
 
-// Enables the use of property trees rather than CalcDrawProps for computing
+// Disables the use of property trees rather than CalcDrawProps for computing
 // draw properties.
-const char kEnableCompositorPropertyTrees[] =
-    "enable-compositor-property-trees";
+const char kDisableCompositorPropertyTrees[] =
+    "disable-compositor-property-trees";
 
 // Renders a border around compositor layers to help debug and study
 // layer compositing.
diff --git a/cc/base/switches.h b/cc/base/switches.h
index bd5b2eb..3465eaf9 100644
--- a/cc/base/switches.h
+++ b/cc/base/switches.h
@@ -30,7 +30,7 @@
 // Switches for both the renderer and ui compositors.
 CC_EXPORT extern const char kEnableBeginFrameScheduling[];
 CC_EXPORT extern const char kEnableGpuBenchmarking[];
-CC_EXPORT extern const char kEnableCompositorPropertyTrees[];
+CC_EXPORT extern const char kDisableCompositorPropertyTrees[];
 
 // Debug visualizations.
 CC_EXPORT extern const char kShowCompositedLayerBorders[];
diff --git a/cc/surfaces/BUILD.gn b/cc/surfaces/BUILD.gn
index 6dd7240..cfb42b7 100644
--- a/cc/surfaces/BUILD.gn
+++ b/cc/surfaces/BUILD.gn
@@ -33,6 +33,7 @@
     "surface_factory_client.h",
     "surface_hittest.cc",
     "surface_hittest.h",
+    "surface_hittest_delegate.h",
     "surface_id_allocator.cc",
     "surface_id_allocator.h",
     "surface_manager.cc",
diff --git a/cc/surfaces/surface_hittest.cc b/cc/surfaces/surface_hittest.cc
index b7414de..1f443d6 100644
--- a/cc/surfaces/surface_hittest.cc
+++ b/cc/surfaces/surface_hittest.cc
@@ -10,15 +10,16 @@
 #include "cc/quads/render_pass_draw_quad.h"
 #include "cc/quads/surface_draw_quad.h"
 #include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_hittest_delegate.h"
 #include "cc/surfaces/surface_manager.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/transform.h"
 
 namespace cc {
-namespace {
-}
 
-SurfaceHittest::SurfaceHittest(SurfaceManager* manager) : manager_(manager) {}
+SurfaceHittest::SurfaceHittest(SurfaceHittestDelegate* delegate,
+                               SurfaceManager* manager)
+    : delegate_(delegate), manager_(manager) {}
 
 SurfaceHittest::~SurfaceHittest() {}
 
@@ -95,6 +96,11 @@
       // Surface.
       const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
 
+      if (delegate_ &&
+          delegate_->RejectHitTarget(surface_quad, point_in_quad_space)) {
+        continue;
+      }
+
       gfx::Transform transform_to_child_space;
       if (GetTargetSurfaceAtPointInternal(
               surface_quad->surface_id, RenderPassId(), point_in_quad_space,
diff --git a/cc/surfaces/surface_hittest.h b/cc/surfaces/surface_hittest.h
index 60fa8937..ce45a90f 100644
--- a/cc/surfaces/surface_hittest.h
+++ b/cc/surfaces/surface_hittest.h
@@ -16,16 +16,18 @@
 }
 
 namespace cc {
+
 class DrawQuad;
 class QuadList;
 class RenderPass;
 class RenderPassId;
+class SurfaceHittestDelegate;
 class SurfaceManager;
 
 // Performs a hittest in surface quads.
 class CC_SURFACES_EXPORT SurfaceHittest {
  public:
-  explicit SurfaceHittest(SurfaceManager* manager);
+  SurfaceHittest(SurfaceHittestDelegate* delegate, SurfaceManager* manager);
   ~SurfaceHittest();
 
   // Returns the target surface that falls underneath the provided |point|.
@@ -67,6 +69,7 @@
                    gfx::Transform* target_to_quad_transform,
                    gfx::Point* point_in_quad_space);
 
+  SurfaceHittestDelegate* const delegate_;
   SurfaceManager* const manager_;
 };
 }  // namespace cc
diff --git a/cc/surfaces/surface_hittest_delegate.h b/cc/surfaces/surface_hittest_delegate.h
new file mode 100644
index 0000000..1f0fbf9
--- /dev/null
+++ b/cc/surfaces/surface_hittest_delegate.h
@@ -0,0 +1,24 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_
+#define CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_
+
+namespace cc {
+
+class SurfaceDrawQuad;
+
+// Clients of SurfaceHittest can provide a SurfaceHittestDelegate implementation
+// to override the hit target based on metadata outside of the Surfaces system.
+class SurfaceHittestDelegate {
+ public:
+  // Return true if this delegate rejects this |surface_quad| as a candidate hit
+  // target.
+  virtual bool RejectHitTarget(const SurfaceDrawQuad* surface_quad,
+                               const gfx::Point& point_in_quad_space) = 0;
+};
+
+}  // namespace cc
+
+#endif  // CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_
diff --git a/cc/surfaces/surface_hittest_unittest.cc b/cc/surfaces/surface_hittest_unittest.cc
index 2b59f0a..144d0d6e 100644
--- a/cc/surfaces/surface_hittest_unittest.cc
+++ b/cc/surfaces/surface_hittest_unittest.cc
@@ -25,8 +25,11 @@
   gfx::Point expected_output_point;
 };
 
-void RunTests(SurfaceManager* manager, TestCase* tests, size_t test_count) {
-  SurfaceHittest hittest(manager);
+void RunTests(SurfaceHittestDelegate* delegate,
+              SurfaceManager* manager,
+              TestCase* tests,
+              size_t test_count) {
+  SurfaceHittest hittest(delegate, manager);
   for (size_t i = 0; i < test_count; ++i) {
     const TestCase& test = tests[i];
     gfx::Point point(test.input_point);
@@ -83,7 +86,7 @@
                                 SurfaceFactory::DrawCallback());
 
   {
-    SurfaceHittest hittest(&manager);
+    SurfaceHittest hittest(nullptr, &manager);
     // It is expected this test will complete without crashes.
     gfx::Transform transform;
     EXPECT_EQ(root_surface_id,
@@ -120,7 +123,7 @@
     },
   };
 
-  RunTests(&manager, tests, arraysize(tests));
+  RunTests(nullptr, &manager, tests, arraysize(tests));
 
   factory.Destroy(root_surface_id);
 }
@@ -215,7 +218,7 @@
     }
   };
 
-  RunTests(&manager, tests, arraysize(tests));
+  RunTests(nullptr, &manager, tests, arraysize(tests));
 
   // Submit another root frame, with a slightly perturbed child Surface.
   root_frame = CreateCompositorFrame(root_rect, &root_pass);
@@ -233,7 +236,7 @@
   // Verify that point (100, 100) no longer falls on the child surface.
   // Verify that the transform to the child surface's space has also shifted.
   {
-    SurfaceHittest hittest(&manager);
+    SurfaceHittest hittest(nullptr, &manager);
 
     gfx::Point point(100, 100);
     gfx::Transform transform;
@@ -355,7 +358,7 @@
     }
   };
 
-  RunTests(&manager, tests, arraysize(tests));
+  RunTests(nullptr, &manager, tests, arraysize(tests));
 
   factory.Destroy(root_surface_id);
   factory.Destroy(child_surface_id);
@@ -459,7 +462,131 @@
     }
   };
 
-  RunTests(&manager, tests, arraysize(tests));
+  RunTests(nullptr, &manager, tests, arraysize(tests));
+
+  factory.Destroy(root_surface_id);
+}
+
+TEST(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) {
+  SurfaceManager manager;
+  EmptySurfaceFactoryClient client;
+  SurfaceFactory factory(&manager, &client);
+
+  // Creates a root surface.
+  gfx::Rect root_rect(300, 300);
+  RenderPass* root_pass = nullptr;
+  scoped_ptr<CompositorFrame> root_frame =
+      CreateCompositorFrame(root_rect, &root_pass);
+
+  // Add a reference to the child surface on the root surface.
+  SurfaceIdAllocator child_allocator(3);
+  SurfaceId child_surface_id = child_allocator.GenerateId();
+  gfx::Rect child_rect(200, 200);
+  CreateSurfaceDrawQuad(
+      root_pass,
+      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f,
+                     0.0f, 1.0f, 0.0f, 50.0f,
+                     0.0f, 0.0f, 1.0f, 0.0f,
+                     0.0f, 0.0f, 0.0f, 1.0f),
+      root_rect, child_rect, child_surface_id);
+
+  // Submit the root frame.
+  SurfaceIdAllocator root_allocator(2);
+  SurfaceId root_surface_id = root_allocator.GenerateId();
+  factory.Create(root_surface_id);
+  factory.SubmitCompositorFrame(root_surface_id, std::move(root_frame),
+                                SurfaceFactory::DrawCallback());
+
+  // Creates a child surface.
+  RenderPass* child_pass = nullptr;
+  scoped_ptr<CompositorFrame> child_frame =
+      CreateCompositorFrame(child_rect, &child_pass);
+
+  // Add a solid quad in the child surface.
+  gfx::Rect child_solid_quad_rect(200, 200);
+  CreateSolidColorDrawQuad(
+      child_pass,
+      gfx::Transform(),
+      root_rect, child_solid_quad_rect);
+
+  // Submit the frame.
+  factory.Create(child_surface_id);
+  factory.SubmitCompositorFrame(child_surface_id, std::move(child_frame),
+                                SurfaceFactory::DrawCallback());
+
+  TestCase test_expectations_without_insets[] = {
+    {
+      root_surface_id,
+      gfx::Point(50, 50),
+      child_surface_id,
+      gfx::Point(0, 0)
+    },
+    {
+      root_surface_id,
+      gfx::Point(60, 60),
+      child_surface_id,
+      gfx::Point(10, 10)
+    },
+    {
+      root_surface_id,
+      gfx::Point(239, 239),
+      child_surface_id,
+      gfx::Point(189, 189)
+    },
+    {
+      root_surface_id,
+      gfx::Point(249, 249),
+      child_surface_id,
+      gfx::Point(199, 199)
+    },
+  };
+
+  TestSurfaceHittestDelegate delegate;
+  RunTests(&delegate, &manager, test_expectations_without_insets,
+           arraysize(test_expectations_without_insets));
+
+  // Verify that insets have NOT affected hit targeting.
+  EXPECT_EQ(0, delegate.target_overrides());
+
+  delegate.AddInsetsForSurface(child_surface_id, gfx::Insets(10, 10, 10, 10));
+
+  TestCase test_expectations_with_insets[] = {
+    // Point (50, 50) falls outside the child surface due to the insets
+    // introduced above.
+    {
+      root_surface_id,
+      gfx::Point(50, 50),
+      root_surface_id,
+      gfx::Point(50, 50)
+    },
+    // These two points still fall within the child surface.
+    {
+      root_surface_id,
+      gfx::Point(60, 60),
+      child_surface_id,
+      gfx::Point(10, 10)
+    },
+    {
+      root_surface_id,
+      gfx::Point(239, 239),
+      child_surface_id,
+      gfx::Point(189, 189)
+    },
+    // Point (249, 249) falls outside the child surface due to the insets
+    // introduced above.
+    {
+      root_surface_id,
+      gfx::Point(249, 249),
+      root_surface_id,
+      gfx::Point(249, 249)
+    },
+  };
+
+  RunTests(&delegate, &manager, test_expectations_with_insets,
+           arraysize(test_expectations_with_insets));
+
+  // Verify that insets have affected hit targeting.
+  EXPECT_EQ(2, delegate.target_overrides());
 
   factory.Destroy(root_surface_id);
 }
diff --git a/cc/test/data/background_filter_on_scaled_layer_gl.png b/cc/test/data/background_filter_on_scaled_layer_gl.png
index 83cb2c5..fc5c8f9c 100644
--- a/cc/test/data/background_filter_on_scaled_layer_gl.png
+++ b/cc/test/data/background_filter_on_scaled_layer_gl.png
Binary files differ
diff --git a/cc/test/surface_hittest_test_helpers.cc b/cc/test/surface_hittest_test_helpers.cc
index 8c579597..b83d6d4b 100644
--- a/cc/test/surface_hittest_test_helpers.cc
+++ b/cc/test/surface_hittest_test_helpers.cc
@@ -92,5 +92,32 @@
   return root_frame;
 }
 
+TestSurfaceHittestDelegate::TestSurfaceHittestDelegate()
+    : target_overrides_(0) {}
+
+TestSurfaceHittestDelegate::~TestSurfaceHittestDelegate() {}
+
+void TestSurfaceHittestDelegate::AddInsetsForSurface(
+    const SurfaceId& surface_id,
+    const gfx::Insets& inset) {
+  insets_for_surface_.insert(std::make_pair(surface_id, inset));
+}
+
+bool TestSurfaceHittestDelegate::RejectHitTarget(
+    const SurfaceDrawQuad* surface_quad,
+    const gfx::Point& point_in_quad_space) {
+  if (!insets_for_surface_.count(surface_quad->surface_id))
+    return false;
+  gfx::Rect bounds(surface_quad->rect);
+  bounds.Inset(insets_for_surface_[surface_quad->surface_id]);
+  // If the point provided falls outside the inset, then we skip this surface.
+  if (!bounds.Contains(point_in_quad_space)) {
+    if (surface_quad->rect.Contains(point_in_quad_space))
+      ++target_overrides_;
+    return true;
+  }
+  return false;
+}
+
 }  // namespace test
 }  // namespace cc
diff --git a/cc/test/surface_hittest_test_helpers.h b/cc/test/surface_hittest_test_helpers.h
index be4ad2e..4a276592 100644
--- a/cc/test/surface_hittest_test_helpers.h
+++ b/cc/test/surface_hittest_test_helpers.h
@@ -5,9 +5,14 @@
 #ifndef CC_TEST_SURFACE_HITTEST_TEST_HELPERS_H_
 #define CC_TEST_SURFACE_HITTEST_TEST_HELPERS_H_
 
+#include <map>
+
+#include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "cc/quads/render_pass.h"
 #include "cc/surfaces/surface_factory_client.h"
+#include "cc/surfaces/surface_hittest_delegate.h"
+#include "ui/gfx/geometry/insets.h"
 
 namespace gfx {
 class Transform;
@@ -60,6 +65,27 @@
 scoped_ptr<CompositorFrame> CreateCompositorFrame(const gfx::Rect& root_rect,
                                                   RenderPass** render_pass);
 
+class TestSurfaceHittestDelegate : public SurfaceHittestDelegate {
+ public:
+  TestSurfaceHittestDelegate();
+  ~TestSurfaceHittestDelegate();
+
+  int target_overrides() const { return target_overrides_; }
+
+  void AddInsetsForSurface(const SurfaceId& surface_id,
+                           const gfx::Insets& inset);
+
+  // SurfaceHittestDelegate implementation.
+  bool RejectHitTarget(const SurfaceDrawQuad* surface_quad,
+                       const gfx::Point& point_in_quad_space) override;
+
+ private:
+  int target_overrides_;
+  std::map<SurfaceId, gfx::Insets> insets_for_surface_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestSurfaceHittestDelegate);
+};
+
 }  // namespace test
 }  // namespace cc
 
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index 9ab91f03..b155373 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -128,7 +128,7 @@
                               true,
                               false,
                               true,
-                              false,
+                              true,
                               render_surface_layer_list,
                               current_render_surface_layer_list_id,
                               GetPropertyTrees(root_layer)) {
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index 7ff78b3..1a978fb 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -59,7 +59,7 @@
       scheduled_raster_task_limit(32),
       use_occlusion_for_tile_prioritization(false),
       verify_property_trees(false),
-      use_property_trees(false),
+      use_property_trees(true),
       image_decode_tasks_enabled(false),
       use_compositor_animation_timelines(false),
       wait_for_beginframe_interval(true),
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 627ee4b..e2a1584f 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -189,10 +189,10 @@
     // content/browser/renderer_host/render_process_host_impl.cc.
     cc::switches::kDisableCachedPictureRaster,
     cc::switches::kDisableCompositedAntialiasing,
+    cc::switches::kDisableCompositorPropertyTrees,
     cc::switches::kDisableMainFrameBeforeActivation,
     cc::switches::kDisableThreadedAnimation,
     cc::switches::kEnableBeginFrameScheduling,
-    cc::switches::kEnableCompositorPropertyTrees,
     cc::switches::kEnableGpuBenchmarking,
     cc::switches::kEnablePropertyTreeVerification,
     cc::switches::kEnableMainFrameBeforeActivation,
diff --git a/chrome/browser/chromeos/power/cpu_data_collector.cc b/chrome/browser/chromeos/power/cpu_data_collector.cc
index 3166c60..21c65fa4 100644
--- a/chrome/browser/chromeos/power/cpu_data_collector.cc
+++ b/chrome/browser/chromeos/power/cpu_data_collector.cc
@@ -94,7 +94,8 @@
   std::string cpu_online_string;
   if (base::ReadFileToString(base::FilePath(cpu_online_file),
                              &cpu_online_string)) {
-    base::TrimWhitespace(cpu_online_string, base::TRIM_ALL, &cpu_online_string);
+    base::TrimWhitespaceASCII(cpu_online_string, base::TRIM_ALL,
+                              &cpu_online_string);
     if (base::StringToInt(cpu_online_string, &online))
       return online == kCpuOnlineStatus;
   }
@@ -159,9 +160,9 @@
           return;
         }
 
-        base::TrimWhitespace(state_name, base::TRIM_ALL, &state_name);
-        base::TrimWhitespace(
-            occupancy_time_string, base::TRIM_ALL, &occupancy_time_string);
+        base::TrimWhitespaceASCII(state_name, base::TRIM_ALL, &state_name);
+        base::TrimWhitespaceASCII(occupancy_time_string, base::TRIM_ALL,
+                                  &occupancy_time_string);
         if (base::StringToInt64(occupancy_time_string, &occupancy_time_usec)) {
           // idle state occupancy time in sysfs is recorded in microseconds.
           int64 time_in_state_ms = occupancy_time_usec / 1000;
@@ -324,7 +325,8 @@
         int max_cpu;
         // The possible CPUs are listed in the format "0-N". Hence, N is present
         // in the substring starting at offset 2.
-        base::TrimWhitespace(possible_string, base::TRIM_ALL, &possible_string);
+        base::TrimWhitespaceASCII(possible_string, base::TRIM_ALL,
+                                  &possible_string);
         if (possible_string.find("-") != std::string::npos &&
             possible_string.length() > 2 &&
             base::StringToInt(possible_string.substr(2), &max_cpu)) {
diff --git a/chrome/browser/devtools/device/android_device_manager.cc b/chrome/browser/devtools/device/android_device_manager.cc
index 3426726d..e7c58b6 100644
--- a/chrome/browser/devtools/device/android_device_manager.cc
+++ b/chrome/browser/devtools/device/android_device_manager.cc
@@ -223,7 +223,7 @@
 
     std::string value = response_.substr(
         start_pos + header.length(), endline_pos - start_pos - header.length());
-    base::TrimWhitespace(value, base::TRIM_ALL, &value);
+    base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value);
     return value;
   }
 
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc b/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
index 68f1b2f..ec28633 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
@@ -8,7 +8,9 @@
 #include "chrome/browser/extensions/api/developer_private/developer_private_api.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
+#include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/common/chrome_paths.h"
+#include "content/public/browser/render_frame_host.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
 
@@ -81,4 +83,52 @@
       (*app_windows.begin())->web_contents()));
 }
 
+IN_PROC_BROWSER_TEST_F(DeveloperPrivateApiTest, InspectEmbeddedOptionsPage) {
+  base::FilePath dir;
+  PathService::Get(chrome::DIR_TEST_DATA, &dir);
+  // Load an extension that only has an embedded options_ui page.
+  const Extension* extension = LoadExtension(dir.AppendASCII("extensions")
+                                                 .AppendASCII("delayed_install")
+                                                 .AppendASCII("v1"));
+  ASSERT_TRUE(extension);
+
+  // Open the embedded options page.
+  ASSERT_TRUE(ExtensionTabUtil::OpenOptionsPage(extension, browser()));
+  WaitForExtensionNotIdle(extension->id());
+
+  // Get the info about the extension, including the inspectable views.
+  scoped_refptr<UIThreadExtensionFunction> function(
+      new api::DeveloperPrivateGetExtensionInfoFunction());
+  scoped_ptr<base::Value> result(
+      extension_function_test_utils::RunFunctionAndReturnSingleResult(
+          function.get(),
+          base::StringPrintf("[\"%s\"]", extension->id().c_str()), browser()));
+  ASSERT_TRUE(result);
+  scoped_ptr<api::developer_private::ExtensionInfo> info =
+      api::developer_private::ExtensionInfo::FromValue(*result);
+  ASSERT_TRUE(info);
+
+  // The embedded options page should show up.
+  ASSERT_EQ(1u, info->views.size());
+  api::developer_private::ExtensionView* view = info->views[0].get();
+  ASSERT_TRUE(view);
+  ASSERT_EQ(api::developer_private::VIEW_TYPE_EXTENSION_GUEST, view->type);
+
+  // Inspect the embedded options page.
+  function = new api::DeveloperPrivateOpenDevToolsFunction();
+  extension_function_test_utils::RunFunction(
+      function.get(),
+      base::StringPrintf("[{\"renderViewId\": %d, \"renderProcessId\": %d}]",
+                         view->render_view_id, view->render_process_id),
+      browser(), extension_function_test_utils::NONE);
+
+  // Verify that dev tools opened.
+  content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
+      view->render_process_id, view->render_view_id);
+  ASSERT_TRUE(rfh);
+  content::WebContents* wc = content::WebContents::FromRenderFrameHost(rfh);
+  ASSERT_TRUE(wc);
+  EXPECT_TRUE(DevToolsWindow::GetInstanceForInspectedWebContents(wc));
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
index 93d90f4..e588caf 100644
--- a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
+++ b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
@@ -60,6 +60,9 @@
     case VIEW_TYPE_EXTENSION_DIALOG:
       view->type = api::developer_private::VIEW_TYPE_EXTENSION_DIALOG;
       break;
+    case VIEW_TYPE_EXTENSION_GUEST:
+      view->type = api::developer_private::VIEW_TYPE_EXTENSION_GUEST;
+      break;
     case VIEW_TYPE_EXTENSION_POPUP:
       view->type = api::developer_private::VIEW_TYPE_EXTENSION_POPUP;
       break;
@@ -148,8 +151,10 @@
     content::WebContents* web_contents =
         content::WebContents::FromRenderFrameHost(host);
     ViewType host_type = GetViewType(web_contents);
-    if (host_type == VIEW_TYPE_EXTENSION_POPUP ||
-        host_type == VIEW_TYPE_EXTENSION_DIALOG) {
+    if (host_type == VIEW_TYPE_INVALID ||
+        host_type == VIEW_TYPE_EXTENSION_POPUP ||
+        host_type == VIEW_TYPE_EXTENSION_DIALOG ||
+        host_type == VIEW_TYPE_APP_WINDOW) {
       continue;
     }
 
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc
index abae1f8..14999a8 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_client.cc
+++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -366,10 +366,12 @@
       return;
 
     case VIEW_TYPE_BACKGROUND_CONTENTS:
+    case VIEW_TYPE_EXTENSION_GUEST:
     case VIEW_TYPE_PANEL:
     case VIEW_TYPE_TAB_CONTENTS:
       // Those types are tracked by other tags:
       // BACKGROUND_CONTENTS --> task_management::BackgroundContentsTag.
+      // GUEST --> extensions::ChromeGuestViewManagerDelegate.
       // PANEL --> task_management::PanelTag.
       // TAB_CONTENTS --> task_management::TabContentsTag.
       // These tags are created and attached to the web_contents in other
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index 9419781..54c44fe 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -123,6 +123,14 @@
   ASSERT_TRUE(RunExtensionTest("messaging/connect_external")) << message_;
 }
 
+// Tests that a content script can exchange messages with a tab even if there is
+// no background page.
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingNoBackground) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(RunExtensionSubtest("messaging/connect_nobackground",
+                                  "page_in_main_frame.html")) << message_;
+}
+
 // Tests that messages with event_urls are only passed to extensions with
 // appropriate permissions.
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingEventURL) {
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc
index 3596cbc..d1e3013 100644
--- a/chrome/browser/extensions/process_manager_browsertest.cc
+++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -4,23 +4,182 @@
 
 #include "extensions/browser/process_manager.h"
 
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
 #include "chrome/browser/extensions/browser_action_test_util.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/test_extension_dir.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/extensions/extension_process_policy.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
+#include "extensions/common/value_builder.h"
+#include "extensions/test/background_page_watcher.h"
+#include "extensions/test/extension_test_message_listener.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
 namespace extensions {
 
+namespace {
+
+void AddFrameToSet(std::set<content::RenderFrameHost*>* frames,
+                   content::RenderFrameHost* rfh) {
+  if (rfh->IsRenderFrameLive())
+    frames->insert(rfh);
+}
+
+}  // namespace
+
+// Takes a snapshot of all frames upon construction. When Wait() is called, a
+// MessageLoop is created and Quit when all previously recorded frames are
+// either present in the tab, or deleted. If a navigation happens between the
+// construction and the Wait() call, then this logic ensures that all obsolete
+// RenderFrameHosts have been destructed when Wait() returns.
+// See also the comment at ProcessManagerBrowserTest::NavigateToURL.
+class NavigationCompletedObserver : public content::WebContentsObserver {
+ public:
+  explicit NavigationCompletedObserver(content::WebContents* web_contents)
+      : content::WebContentsObserver(web_contents),
+        message_loop_runner_(new content::MessageLoopRunner) {
+    web_contents->ForEachFrame(
+        base::Bind(&AddFrameToSet, base::Unretained(&frames_)));
+  }
+
+  void Wait() {
+    if (!AreAllFramesInTab())
+      message_loop_runner_->Run();
+  }
+
+  void RenderFrameDeleted(content::RenderFrameHost* rfh) override {
+    if (frames_.erase(rfh) != 0 && message_loop_runner_->loop_running() &&
+        AreAllFramesInTab())
+      message_loop_runner_->Quit();
+  }
+
+ private:
+  // Check whether all frames that were recorded at the construction of this
+  // class are still part of the tab.
+  bool AreAllFramesInTab() {
+    std::set<content::RenderFrameHost*> current_frames;
+    web_contents()->ForEachFrame(
+        base::Bind(&AddFrameToSet, base::Unretained(&current_frames)));
+    for (content::RenderFrameHost* frame : frames_) {
+      if (current_frames.find(frame) == current_frames.end())
+        return false;
+    }
+    return true;
+  }
+
+  std::set<content::RenderFrameHost*> frames_;
+  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(NavigationCompletedObserver);
+};
+
 // Exists as a browser test because ExtensionHosts are hard to create without
 // a real browser.
-typedef ExtensionBrowserTest ProcessManagerBrowserTest;
+class ProcessManagerBrowserTest : public ExtensionBrowserTest {
+ public:
+  // Create an extension with web-accessible frames and an optional background
+  // page.
+  const Extension* CreateExtension(const std::string& name,
+                                   bool has_background_process) {
+    scoped_ptr<TestExtensionDir> dir(new TestExtensionDir());
+
+    DictionaryBuilder manifest;
+    manifest.Set("name", name)
+        .Set("version", "1")
+        .Set("manifest_version", 2)
+        // To allow ExecuteScript* to work.
+        .Set("content_security_policy",
+             "script-src 'self' 'unsafe-eval'; object-src 'self'")
+        .Set("sandbox", DictionaryBuilder().Set(
+                            "pages", ListBuilder().Append("sandboxed.html")))
+        .Set("web_accessible_resources", ListBuilder().Append("*"));
+
+    if (has_background_process) {
+      manifest.Set("background", DictionaryBuilder().Set("page", "bg.html"));
+      dir->WriteFile(FILE_PATH_LITERAL("bg.html"),
+                     "<iframe id='bgframe' src='empty.html'></iframe>");
+    }
+
+    dir->WriteFile(FILE_PATH_LITERAL("blank_iframe.html"),
+                   "<iframe id='frame0' src='about:blank'></iframe>");
+
+    dir->WriteFile(FILE_PATH_LITERAL("srcdoc_iframe.html"),
+                   "<iframe id='frame0' srcdoc='Hello world'></iframe>");
+
+    dir->WriteFile(FILE_PATH_LITERAL("two_iframes.html"),
+                   "<iframe id='frame1' src='empty.html'></iframe>"
+                   "<iframe id='frame2' src='empty.html'></iframe>");
+
+    dir->WriteFile(FILE_PATH_LITERAL("sandboxed.html"), "Some sandboxed page");
+
+    dir->WriteFile(FILE_PATH_LITERAL("empty.html"), "");
+
+    dir->WriteManifest(manifest.ToJSON());
+
+    const Extension* extension = LoadExtension(dir->unpacked_path());
+    EXPECT_TRUE(extension);
+    temp_dirs_.push_back(dir.Pass());
+    return extension;
+  }
+
+  // ui_test_utils::NavigateToURL sometimes returns too early: It returns as
+  // soon as the StopLoading notification has been triggered. This does not
+  // imply that RenderFrameDeleted was called, so the test may continue too
+  // early and fail when ProcessManager::GetAllFrames() returns too many frames
+  // (namely frames that are in the process of being deleted). To work around
+  // this problem, we also wait until all previous frames have been deleted.
+  void NavigateToURL(const GURL& url) {
+    NavigationCompletedObserver observer(
+        browser()->tab_strip_model()->GetActiveWebContents());
+
+    ui_test_utils::NavigateToURL(browser(), url);
+
+    // Wait until the last RenderFrameHosts are deleted. This wait doesn't take
+    // long.
+    observer.Wait();
+  }
+
+  void NavigateIframeToURLAndWait(content::WebContents* web_contents,
+                                  const std::string iframe_id,
+                                  const GURL& url) {
+    // This is an improved version of content::NavigateIframeToURL. Unlike the
+    // other method, this does actually wait until the load of all child frames
+    // completes.
+    std::string script = base::StringPrintf(
+        "var frame = document.getElementById('%s');"
+        "frame.onload = frame.onerror = function(event) {"
+        "  frame.onload = frame.onerror = null;"
+        "  domAutomationController.send(event.type === 'load');"
+        "};"
+        "frame.src = '%s';",
+        iframe_id.c_str(), url.spec().c_str());
+    bool is_loaded = false;
+    EXPECT_TRUE(ExecuteScriptAndExtractBool(web_contents, script, &is_loaded));
+    EXPECT_TRUE(is_loaded);
+  }
+
+  size_t IfExtensionsIsolated(size_t if_enabled, size_t if_disabled) {
+    return content::AreAllSitesIsolatedForTesting() ||
+                   IsIsolateExtensionsEnabled()
+               ? if_enabled
+               : if_disabled;
+  }
+
+ private:
+  std::vector<scoped_ptr<TestExtensionDir>> temp_dirs_;
+};
 
 // Test that basic extension loading creates the appropriate ExtensionHosts
 // and background pages.
@@ -157,6 +316,193 @@
   EXPECT_TRUE(pm->GetBackgroundHostForExtension(extension->id()));
 }
 
+IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, NoBackgroundPage) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  ProcessManager* pm = ProcessManager::Get(profile());
+  const Extension* extension =
+      LoadExtension(test_data_dir_.AppendASCII("api_test")
+                        .AppendASCII("messaging")
+                        .AppendASCII("connect_nobackground"));
+  ASSERT_TRUE(extension);
+
+  // The extension has no background page.
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
+
+  // Start in a non-extension process, then navigate to an extension process.
+  NavigateToURL(embedded_test_server()->GetURL("/empty.html"));
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
+
+  const GURL extension_url = extension->url().Resolve("manifest.json");
+  NavigateToURL(extension_url);
+  EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
+
+  NavigateToURL(GURL("about:blank"));
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
+
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), extension_url, NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+  EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
+}
+
+// Tests whether frames are correctly classified. Non-extension frames should
+// never appear in the list. Top-level extension frames should always appear.
+// Child extension frames should only appear if it is hosted in an extension
+// process (i.e. if the top-level frame is an extension page, or if OOP frames
+// are enabled for extensions).
+IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, FrameClassification) {
+  const Extension* extension1 = CreateExtension("Extension 1", false);
+  const Extension* extension2 = CreateExtension("Extension 2", true);
+  embedded_test_server()->ServeFilesFromDirectory(extension1->path());
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  const GURL kExt1TwoFramesUrl(extension1->url().Resolve("two_iframes.html"));
+  const GURL kExt1EmptyUrl(extension1->url().Resolve("empty.html"));
+  const GURL kExt2TwoFramesUrl(extension2->url().Resolve("two_iframes.html"));
+  const GURL kExt2EmptyUrl(extension2->url().Resolve("empty.html"));
+
+  ProcessManager* pm = ProcessManager::Get(profile());
+
+  // 1 background page + 1 frame in background page from Extension 2.
+  BackgroundPageWatcher(pm, extension2).WaitForOpen();
+  EXPECT_EQ(2u, pm->GetAllFrames().size());
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+  EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  ExecuteScriptInBackgroundPageNoWait(extension2->id(),
+                                      "setTimeout(window.close, 0)");
+  BackgroundPageWatcher(pm, extension2).WaitForClose();
+  EXPECT_EQ(0u, pm->GetAllFrames().size());
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html"));
+  EXPECT_EQ(0u, pm->GetAllFrames().size());
+
+  content::WebContents* tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Tests extension frames in non-extension page.
+  NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl);
+  EXPECT_EQ(IfExtensionsIsolated(1, 0),
+            pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+  EXPECT_EQ(IfExtensionsIsolated(1, 0), pm->GetAllFrames().size());
+
+  NavigateIframeToURLAndWait(tab, "frame2", kExt2EmptyUrl);
+  EXPECT_EQ(IfExtensionsIsolated(1, 0),
+            pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+  EXPECT_EQ(IfExtensionsIsolated(2, 0), pm->GetAllFrames().size());
+
+  // Tests non-extension page in extension frame.
+  NavigateToURL(kExt1TwoFramesUrl);
+  // 1 top-level + 2 child frames from Extension 1.
+  EXPECT_EQ(3u, pm->GetAllFrames().size());
+  EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  NavigateIframeToURLAndWait(tab, "frame1",
+                             embedded_test_server()->GetURL("/empty.html"));
+  // 1 top-level + 1 child frame from Extension 1.
+  EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+  EXPECT_EQ(2u, pm->GetAllFrames().size());
+
+  NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl);
+  // 1 top-level + 2 child frames from Extension 1.
+  EXPECT_EQ(3u, pm->GetAllFrames().size());
+  EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+
+  // Load a frame from another extension.
+  NavigateIframeToURLAndWait(tab, "frame1", kExt2EmptyUrl);
+  // 1 top-level + 1 child frame from Extension 1,
+  // 1 child frame from Extension 2.
+  EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size());
+  EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+  EXPECT_EQ(IfExtensionsIsolated(1, 0),
+            pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  // Destroy all existing frames by navigating to another extension.
+  NavigateToURL(extension2->url().Resolve("empty.html"));
+  EXPECT_EQ(1u, pm->GetAllFrames().size());
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+  EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  // Test about:blank and about:srcdoc child frames.
+  NavigateToURL(extension2->url().Resolve("srcdoc_iframe.html"));
+  // 1 top-level frame + 1 child frame from Extension 2.
+  EXPECT_EQ(2u, pm->GetAllFrames().size());
+  EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  NavigateToURL(extension2->url().Resolve("blank_iframe.html"));
+  // 1 top-level frame + 1 child frame from Extension 2.
+  EXPECT_EQ(2u, pm->GetAllFrames().size());
+  EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  // Sandboxed frames are not viewed as extension frames.
+  NavigateIframeToURLAndWait(tab, "frame0",
+                             extension2->url().Resolve("sandboxed.html"));
+  // 1 top-level frame from Extension 2.
+  EXPECT_EQ(1u, pm->GetAllFrames().size());
+  EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  NavigateToURL(extension2->url().Resolve("sandboxed.html"));
+  EXPECT_EQ(0u, pm->GetAllFrames().size());
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  // Test nested frames (same extension).
+  NavigateToURL(kExt2TwoFramesUrl);
+  // 1 top-level + 2 child frames from Extension 2.
+  EXPECT_EQ(3u, pm->GetAllFrames().size());
+  EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  NavigateIframeToURLAndWait(tab, "frame1", kExt2TwoFramesUrl);
+  // 1 top-level + 2 child frames from Extension 1,
+  // 2 child frames in frame1 from Extension 2.
+  EXPECT_EQ(5u, pm->GetAllFrames().size());
+  EXPECT_EQ(5u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  // The extension frame from the other extension should not be classified as an
+  // extension (unless out-of-process frames are enabled).
+  NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl);
+  // 1 top-level + 1 child frames from Extension 2,
+  // 1 child frame from Extension 1.
+  EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size());
+  EXPECT_EQ(IfExtensionsIsolated(1, 0),
+            pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+  EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  NavigateIframeToURLAndWait(tab, "frame2", kExt1TwoFramesUrl);
+  // 1 top-level + 1 child frames from Extension 2,
+  // 1 child frame + 2 child frames in frame2 from Extension 1.
+  EXPECT_EQ(IfExtensionsIsolated(5, 1), pm->GetAllFrames().size());
+  EXPECT_EQ(IfExtensionsIsolated(4, 0),
+            pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+  EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  // Crash tab where the top-level frame is an extension frame.
+  content::CrashTab(tab);
+  EXPECT_EQ(0u, pm->GetAllFrames().size());
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
+
+  // Now load an extension page and a non-extension page...
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), kExt1EmptyUrl, NEW_BACKGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+  NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html"));
+  EXPECT_EQ(1u, pm->GetAllFrames().size());
+
+  // ... load an extension frame in the non-extension process
+  NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl);
+  EXPECT_EQ(IfExtensionsIsolated(2, 1),
+            pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+
+  // ... and take down the tab. The extension process is not part of the tab,
+  // so it should be kept alive (minus the frames that died).
+  content::CrashTab(tab);
+  EXPECT_EQ(1u, pm->GetAllFrames().size());
+  EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
+}
+
 // Verify correct keepalive count behavior on network request events.
 // Regression test for http://crbug.com/535716.
 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, KeepaliveOnNetworkRequest) {
diff --git a/chrome/browser/google/google_brand_chromeos.cc b/chrome/browser/google/google_brand_chromeos.cc
index 8ccec25a..ddde682e 100644
--- a/chrome/browser/google/google_brand_chromeos.cc
+++ b/chrome/browser/google/google_brand_chromeos.cc
@@ -31,7 +31,7 @@
   base::FilePath brand_file_path(kRLZBrandFilePath);
   if (!base::ReadFileToString(brand_file_path, &brand))
     LOG(WARNING) << "Brand code file missing: " << brand_file_path.value();
-  base::TrimWhitespace(brand, base::TRIM_ALL, &brand);
+  base::TrimWhitespaceASCII(brand, base::TRIM_ALL, &brand);
   return brand;
 }
 
diff --git a/chrome/browser/net/firefox_proxy_settings.cc b/chrome/browser/net/firefox_proxy_settings.cc
index 203d9557..16b3618 100644
--- a/chrome/browser/net/firefox_proxy_settings.cc
+++ b/chrome/browser/net/firefox_proxy_settings.cc
@@ -102,7 +102,7 @@
     }
     std::string value = line.substr(start_value + 1,
                                     stop_value - start_value - 1);
-    base::TrimWhitespace(value, base::TRIM_ALL, &value);
+    base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value);
     // Value could be a boolean.
     bool is_value_true = base::LowerCaseEqualsASCII(value, "true");
     if (is_value_true || base::LowerCaseEqualsASCII(value, "false")) {
diff --git a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc
index 99b336ef..a9099abf 100644
--- a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc
+++ b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc
@@ -423,6 +423,7 @@
       view_type == extensions::VIEW_TYPE_APP_WINDOW ||
       view_type == extensions::VIEW_TYPE_LAUNCHER_PAGE ||
       view_type == extensions::VIEW_TYPE_VIRTUAL_KEYBOARD ||
+      view_type == extensions::VIEW_TYPE_EXTENSION_POPUP ||
       view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
     // If it is a tab, we can check for permission. For apps, this means
     // manifest would be checked for permission.
diff --git a/chrome/browser/ui/search_engines/edit_search_engine_controller.cc b/chrome/browser/ui/search_engines/edit_search_engine_controller.cc
index b81e9cb..837c8ea 100644
--- a/chrome/browser/ui/search_engines/edit_search_engine_controller.cc
+++ b/chrome/browser/ui/search_engines/edit_search_engine_controller.cc
@@ -127,9 +127,9 @@
 std::string EditSearchEngineController::GetFixedUpURL(
     const std::string& url_input) const {
   std::string url;
-  base::TrimWhitespace(TemplateURLRef::DisplayURLToURLRef(
-                           base::UTF8ToUTF16(url_input)),
-                       base::TRIM_ALL, &url);
+  base::TrimWhitespaceASCII(
+      TemplateURLRef::DisplayURLToURLRef(base::UTF8ToUTF16(url_input)),
+      base::TRIM_ALL, &url);
   if (url.empty())
     return url;
 
diff --git a/chrome/common/extensions/api/developer_private.idl b/chrome/common/extensions/api/developer_private.idl
index 15e7dc0..882c7db 100644
--- a/chrome/common/extensions/api/developer_private.idl
+++ b/chrome/common/extensions/api/developer_private.idl
@@ -64,6 +64,7 @@
     BACKGROUND_CONTENTS,
     EXTENSION_BACKGROUND_PAGE,
     EXTENSION_DIALOG,
+    EXTENSION_GUEST,
     EXTENSION_POPUP,
     LAUNCHER_PAGE,
     PANEL,
diff --git a/chrome/test/chromedriver/net/adb_client_socket.cc b/chrome/test/chromedriver/net/adb_client_socket.cc
index 14a10ba..752dde2 100644
--- a/chrome/test/chromedriver/net/adb_client_socket.cc
+++ b/chrome/test/chromedriver/net/adb_client_socket.cc
@@ -185,7 +185,7 @@
         if (endline_pos != std::string::npos) {
           std::string len = response_.substr(content_pos + 15,
                                              endline_pos - content_pos - 15);
-          base::TrimWhitespace(len, base::TRIM_ALL, &len);
+          base::TrimWhitespaceASCII(len, base::TRIM_ALL, &len);
           if (!base::StringToInt(len, &expected_length)) {
             CheckNetResultOrDie(net::ERR_FAILED);
             return;
diff --git a/chrome/test/data/extensions/api_test/messaging/connect_nobackground/contentscript.js b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/contentscript.js
new file mode 100644
index 0000000..ed5955a7
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/contentscript.js
@@ -0,0 +1,12 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
+  chrome.test.assertEq('msg from tab', message);
+  sendResponse('Reply here');
+});
+
+var port = chrome.runtime.connect();
+port.postMessage('Hello from content script');
+port.disconnect();
diff --git a/chrome/test/data/extensions/api_test/messaging/connect_nobackground/manifest.json b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/manifest.json
new file mode 100644
index 0000000..55df682
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/manifest.json
@@ -0,0 +1,10 @@
+{
+  "name": "connect_nobackground",
+  "version": "1.0",
+  "manifest_version": 2,
+  "description": "Tests that a content script can notify an extension in a tab.",
+  "content_scripts": [{
+    "matches": ["*://*/*?will_test_connect_and_sendMessage"],
+    "js": ["contentscript.js"]
+  }]
+}
diff --git a/chrome/test/data/extensions/api_test/messaging/connect_nobackground/page_in_main_frame.html b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/page_in_main_frame.html
new file mode 100644
index 0000000..3fb274a
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/page_in_main_frame.html
@@ -0,0 +1,6 @@
+<!--
+ * Copyright 2015 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+-->
+<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/messaging/connect_nobackground/test.js b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/test.js
new file mode 100644
index 0000000..af1732f
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/test.js
@@ -0,0 +1,35 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.runtime.onConnect.addListener(function(port) {
+  var succeed1 = chrome.test.callbackAdded();
+  var succeed2 = chrome.test.callbackAdded();
+  var succeed3 = chrome.test.callbackAdded();
+
+  port.onMessage.addListener(function(msg) {
+    chrome.test.log('port.onMessage was triggered.');
+    chrome.test.assertEq('Hello from content script', msg);
+    succeed1();
+  });
+
+  port.onDisconnect.addListener(function() {
+    chrome.test.log('port.onDisconnect was triggered.');
+    succeed2();
+  });
+
+  chrome.tabs.sendMessage(port.sender.tab.id, 'msg from tab', function(reply) {
+    chrome.test.log('tab.sendMessage\'s response callback was invoked');
+    chrome.test.assertEq('Reply here', reply);
+    succeed3();
+  });
+});
+
+chrome.test.getConfig(function(config) {
+  var url = 'http://localhost:' + config.testServer.port +
+      '/extensions/test_file.html?will_test_connect_and_sendMessage';
+  // Content script will try to connect and trigger onConnect.
+  chrome.tabs.create({
+    url: url
+  });
+});
diff --git a/chrome/tools/convert_dict/hunspell_reader.cc b/chrome/tools/convert_dict/hunspell_reader.cc
index 6555fb7be..5232443 100644
--- a/chrome/tools/convert_dict/hunspell_reader.cc
+++ b/chrome/tools/convert_dict/hunspell_reader.cc
@@ -23,7 +23,7 @@
   // Treat this text as an ASCII text and trim whitespace characters as
   // hunspell does. The returned text is to be converted into UTF-8 text with
   // the encoding defined in an affix file.
-  base::TrimWhitespace(*line, base::TRIM_ALL, line);
+  base::TrimWhitespaceASCII(*line, base::TRIM_ALL, line);
 }
 
 std::string ReadLine(FILE* file) {
diff --git a/chromeos/dbus/power_policy_controller.cc b/chromeos/dbus/power_policy_controller.cc
index 336b72e..49c76c2 100644
--- a/chromeos/dbus/power_policy_controller.cc
+++ b/chromeos/dbus/power_policy_controller.cc
@@ -152,7 +152,7 @@
   }
   if (policy.has_reason())
     str += base::StringPrintf("reason=\"%s\" ", policy.reason().c_str());
-  base::TrimWhitespace(str, base::TRIM_TRAILING, &str);
+  base::TrimWhitespaceASCII(str, base::TRIM_TRAILING, &str);
   return str;
 }
 
diff --git a/components/cdm/browser/cdm_message_filter_android.cc b/components/cdm/browser/cdm_message_filter_android.cc
index e9399f6..14043e1 100644
--- a/components/cdm/browser/cdm_message_filter_android.cc
+++ b/components/cdm/browser/cdm_message_filter_android.cc
@@ -9,11 +9,10 @@
 
 #include "components/cdm/common/cdm_messages_android.h"
 #include "ipc/ipc_message_macros.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_codec_util.h"
 #include "media/base/android/media_drm_bridge.h"
 
 using content::BrowserThread;
-using media::MediaCodecBridge;
 using media::MediaDrmBridge;
 using media::SupportedCodecs;
 
@@ -59,7 +58,7 @@
     if ((request.codecs & info.codec) &&
         MediaDrmBridge::IsKeySystemSupportedWithType(
             key_system, info.container_mime_type) &&
-        MediaCodecBridge::CanDecode(info.codec_name, is_secure)) {
+        media::MediaCodecUtil::CanDecode(info.codec_name, is_secure)) {
       supported_codecs |= info.codec;
     }
   }
diff --git a/components/google/core/browser/google_url_tracker.cc b/components/google/core/browser/google_url_tracker.cc
index fa0d140..f503265e 100644
--- a/components/google/core/browser/google_url_tracker.cc
+++ b/components/google/core/browser/google_url_tracker.cc
@@ -97,7 +97,7 @@
   // See if the response data was valid.  It should be ".google.<TLD>".
   std::string url_str;
   source->GetResponseAsString(&url_str);
-  base::TrimWhitespace(url_str, base::TRIM_ALL, &url_str);
+  base::TrimWhitespaceASCII(url_str, base::TRIM_ALL, &url_str);
   if (!base::StartsWith(url_str, ".google.",
                         base::CompareCase::INSENSITIVE_ASCII))
     return;
diff --git a/components/mus/surfaces/surfaces_state.cc b/components/mus/surfaces/surfaces_state.cc
index ea203ba6..51b7358 100644
--- a/components/mus/surfaces/surfaces_state.cc
+++ b/components/mus/surfaces/surfaces_state.cc
@@ -7,9 +7,7 @@
 namespace mus {
 
 SurfacesState::SurfacesState()
-    : next_id_namespace_(1u),
-      hit_tester_(&manager_) {
-}
+    : next_id_namespace_(1u), hit_tester_(nullptr, &manager_) {}
 
 SurfacesState::~SurfacesState() {}
 
diff --git a/components/nacl/BUILD.gn b/components/nacl/BUILD.gn
index ad200c93..7e20ecc0 100644
--- a/components/nacl/BUILD.gn
+++ b/components/nacl/BUILD.gn
@@ -144,6 +144,7 @@
     deps = [
       ":nacl_common",
       ":nacl_switches",
+      "renderer/plugin:nacl_trusted_plugin",
       "//base",
       "//content/public/common",
       "//content/public/renderer",
@@ -153,7 +154,6 @@
       "//ppapi/proxy:ipc",
       "//ppapi/shared_impl",
       "//third_party/WebKit/public:blink",
-      "renderer/plugin:nacl_trusted_plugin",
     ]
   }
 
diff --git a/components/plugins/renderer/plugin_placeholder.cc b/components/plugins/renderer/plugin_placeholder.cc
index bfb3ef15..96fb0bb 100644
--- a/components/plugins/renderer/plugin_placeholder.cc
+++ b/components/plugins/renderer/plugin_placeholder.cc
@@ -81,7 +81,7 @@
     if (base::EndsWith(width_str, "px", base::CompareCase::INSENSITIVE_ASCII)) {
       width_str = width_str.substr(0, width_str.length() - 2);
     }
-    base::TrimWhitespace(width_str, base::TRIM_TRAILING, &width_str);
+    base::TrimWhitespaceASCII(width_str, base::TRIM_TRAILING, &width_str);
     width_str += "[\\s]*px";
     std::string height_str("height:[\\s]*");
     height_str += element.getAttribute("height").utf8().data();
@@ -89,7 +89,7 @@
                        base::CompareCase::INSENSITIVE_ASCII)) {
       height_str = height_str.substr(0, height_str.length() - 2);
     }
-    base::TrimWhitespace(height_str, base::TRIM_TRAILING, &height_str);
+    base::TrimWhitespaceASCII(height_str, base::TRIM_TRAILING, &height_str);
     height_str += "[\\s]*px";
     blink::WebNode parent = element;
     while (!parent.parentNode().isNull()) {
diff --git a/components/safe_browsing_db/prefix_set_unittest.cc b/components/safe_browsing_db/prefix_set_unittest.cc
index 181efc7..d1de0db4 100644
--- a/components/safe_browsing_db/prefix_set_unittest.cc
+++ b/components/safe_browsing_db/prefix_set_unittest.cc
@@ -199,7 +199,7 @@
     while (fgets(buf, sizeof(buf), file.get())) {
       std::string trimmed;
       if (base::TRIM_TRAILING !=
-          base::TrimWhitespace(buf, base::TRIM_ALL, &trimmed))
+          base::TrimWhitespaceASCII(buf, base::TRIM_ALL, &trimmed))
         return false;
       unsigned prefix;
       if (!base::StringToUint(trimmed, &prefix))
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn
index 3f9c7c7d..a65148a 100644
--- a/components/variations/BUILD.gn
+++ b/components/variations/BUILD.gn
@@ -62,6 +62,7 @@
   }
 
   deps = [
+    "proto",
     "//base",
     "//base:prefs",
     "//components/compression",
@@ -69,7 +70,6 @@
     "//crypto",
     "//third_party/mt19937ar",
     "//third_party/protobuf:protobuf_lite",
-    "proto",
   ]
 
   if (is_android) {
@@ -111,11 +111,11 @@
 
   deps = [
     ":variations",
+    "net",
+    "proto",
     "//base:prefs_test_support",
     "//base/test:test_support",
     "//components/compression",
     "//testing/gtest",
-    "net",
-    "proto",
   ]
 }
diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc
index 2650a76..bf39969 100644
--- a/content/browser/compositor/delegated_frame_host.cc
+++ b/content/browser/compositor/delegated_frame_host.cc
@@ -211,7 +211,7 @@
     gfx::Point* transformed_point) {
   if (surface_id_.is_null())
     return surface_id_;
-  cc::SurfaceHittest hittest(GetSurfaceManager());
+  cc::SurfaceHittest hittest(nullptr, GetSurfaceManager());
   gfx::Transform target_transform;
   cc::SurfaceId target_surface_id =
       hittest.GetTargetSurfaceAtPoint(surface_id_, point, &target_transform);
@@ -230,7 +230,7 @@
     return;
 
   gfx::Transform transform;
-  cc::SurfaceHittest hittest(GetSurfaceManager());
+  cc::SurfaceHittest hittest(nullptr, GetSurfaceManager());
   if (hittest.GetTransformToTargetSurface(surface_id_, original_surface,
                                           &transform) &&
       transform.GetInverse(&transform)) {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 789c5ea3..70646c1 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -444,8 +444,8 @@
       command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
   settings.initial_debug_state.show_fps_counter =
       command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
-  settings.use_property_trees =
-      command_line->HasSwitch(cc::switches::kEnableCompositorPropertyTrees);
+  if (command_line->HasSwitch(cc::switches::kDisableCompositorPropertyTrees))
+    settings.use_property_trees = false;
   // TODO(enne): Update this this compositor to use the scheduler.
   settings.single_thread_proxy_scheduler = false;
 
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 60b94257..c695f6f 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1445,10 +1445,10 @@
     // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
     cc::switches::kDisableCachedPictureRaster,
     cc::switches::kDisableCompositedAntialiasing,
+    cc::switches::kDisableCompositorPropertyTrees,
     cc::switches::kDisableMainFrameBeforeActivation,
     cc::switches::kDisableThreadedAnimation,
     cc::switches::kEnableBeginFrameScheduling,
-    cc::switches::kEnableCompositorPropertyTrees,
     cc::switches::kEnableGpuBenchmarking,
     cc::switches::kEnableMainFrameBeforeActivation,
     cc::switches::kShowCompositedLayerBorders,
diff --git a/content/child/npapi/plugin_host.cc b/content/child/npapi/plugin_host.cc
index 4f3006e0..7f03896c 100644
--- a/content/child/npapi/plugin_host.cc
+++ b/content/child/npapi/plugin_host.cc
@@ -259,7 +259,7 @@
         case GETNAME:
           // Got a value.
           value = std::string(start, ptr - start);
-          base::TrimWhitespace(value, base::TRIM_ALL, &value);
+          base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value);
           // If the name field is empty, we'll skip this header
           // but we won't error out.
           if (!name.empty() && name != "content-length") {
@@ -271,7 +271,7 @@
         case GETVALUE:
           // Got a header.
           name = base::ToLowerASCII(base::StringPiece(start, ptr - start));
-          base::TrimWhitespace(name, base::TRIM_ALL, &name);
+          base::TrimWhitespaceASCII(name, base::TRIM_ALL, &name);
           start = ptr + 1;
           break;
         case GETDATA: {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index be71402..691b8b9 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -19,7 +19,7 @@
 #include <cpu-features.h>
 #include "base/android/build_info.h"
 #include "base/metrics/field_trial.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_codec_util.h"
 #elif defined(OS_WIN)
 #include "base/win/windows_version.h"
 #endif
@@ -34,7 +34,7 @@
 
 #if defined(OS_ANDROID)
   // MSE/EME implementation needs Android MediaCodec API.
-  if (!media::MediaCodecBridge::IsAvailable()) {
+  if (!media::MediaCodecUtil::IsMediaCodecAvailable()) {
     WebRuntimeFeatures::enableMediaSource(false);
     WebRuntimeFeatures::enablePrefixedEncryptedMedia(false);
     WebRuntimeFeatures::enableEncryptedMedia(false);
@@ -43,7 +43,7 @@
   // is available.
   AndroidCpuFamily cpu_family = android_getCpuFamily();
   WebRuntimeFeatures::enableWebAudio(
-      media::MediaCodecBridge::IsAvailable() &&
+      media::MediaCodecUtil::IsMediaCodecAvailable() &&
       ((cpu_family == ANDROID_CPU_FAMILY_ARM) ||
        (cpu_family == ANDROID_CPU_FAMILY_ARM64) ||
        (cpu_family == ANDROID_CPU_FAMILY_X86) ||
@@ -121,7 +121,7 @@
   // API is available.
   WebRuntimeFeatures::enableWebAudio(
       !command_line.HasSwitch(switches::kDisableWebAudio) &&
-      media::MediaCodecBridge::IsAvailable());
+      media::MediaCodecUtil::IsMediaCodecAvailable());
 #else
   if (command_line.HasSwitch(switches::kDisableWebAudio))
     WebRuntimeFeatures::enableWebAudio(false);
diff --git a/content/common/gpu/media/android_video_decode_accelerator.h b/content/common/gpu/media/android_video_decode_accelerator.h
index 2e8058af..945a4d0a 100644
--- a/content/common/gpu/media/android_video_decode_accelerator.h
+++ b/content/common/gpu/media/android_video_decode_accelerator.h
@@ -17,7 +17,7 @@
 #include "content/common/content_export.h"
 #include "content/common/gpu/media/avda_state_provider.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/video/video_decode_accelerator.h"
 
 namespace gfx {
diff --git a/content/common/gpu/media/android_video_decode_accelerator_unittest.cc b/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
index 2e0e7ac2..c1e91f12 100644
--- a/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
+++ b/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
@@ -12,7 +12,7 @@
 #include "content/common/gpu/media/android_copying_backing_strategy.h"
 #include "content/common/gpu/media/android_video_decode_accelerator.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_codec_util.h"
 #include "media/base/android/media_jni_registrar.h"
 #include "media/video/picture.h"
 #include "media/video/video_decode_accelerator.h"
@@ -92,7 +92,7 @@
 }
 
 TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureSupportedCodec) {
-  if (!media::MediaCodecBridge::IsAvailable())
+  if (!media::MediaCodecUtil::IsMediaCodecAvailable())
     return;
   EXPECT_TRUE(Configure(media::kCodecVP8));
 }
diff --git a/content/common/gpu/media/android_video_encode_accelerator.cc b/content/common/gpu/media/android_video_encode_accelerator.cc
index 1cb6e549..e439203 100644
--- a/content/common/gpu/media/android_video_encode_accelerator.cc
+++ b/content/common/gpu/media/android_video_encode_accelerator.cc
@@ -14,7 +14,7 @@
 #include "content/common/gpu/gpu_channel.h"
 #include "content/public/common/content_switches.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_codec_util.h"
 #include "media/base/bitstream_buffer.h"
 #include "media/base/limits.h"
 #include "media/video/picture.h"
@@ -22,7 +22,6 @@
 #include "ui/gl/android/scoped_java_surface.h"
 #include "ui/gl/gl_bindings.h"
 
-using media::MediaCodecBridge;
 using media::VideoCodecBridge;
 using media::VideoFrame;
 
@@ -83,7 +82,7 @@
   if (mime.empty())
     return false;
 
-  std::set<int> formats = MediaCodecBridge::GetEncoderColorFormats(mime);
+  std::set<int> formats = media::MediaCodecUtil::GetEncoderColorFormats(mime);
   if (formats.count(COLOR_FORMAT_YUV420_SEMIPLANAR) > 0)
     *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR;
   else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0)
@@ -157,8 +156,8 @@
 
   client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
 
-  if (!(media::MediaCodecBridge::SupportsSetParameters() &&
-        format == media::PIXEL_FORMAT_I420)) {
+  if (!(media::MediaCodecUtil::SupportsSetParameters() &&
+      format == media::PIXEL_FORMAT_I420)) {
     DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile;
     return false;
   }
diff --git a/content/common/gpu/media/android_video_encode_accelerator.h b/content/common/gpu/media/android_video_encode_accelerator.h
index 98fa3c2b9..367ecf88 100644
--- a/content/common/gpu/media/android_video_encode_accelerator.h
+++ b/content/common/gpu/media/android_video_encode_accelerator.h
@@ -14,7 +14,7 @@
 #include "base/timer/timer.h"
 #include "base/tuple.h"
 #include "content/common/content_export.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/video/video_encode_accelerator.h"
 
 namespace media {
diff --git a/content/common/gpu/media/avda_shared_state.h b/content/common/gpu/media/avda_shared_state.h
index a64bf3a..474037d 100644
--- a/content/common/gpu/media/avda_shared_state.h
+++ b/content/common/gpu/media/avda_shared_state.h
@@ -6,7 +6,7 @@
 #define CONTENT_COMMON_GPU_AVDA_SHARED_STATE_H_
 
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "ui/gl/gl_image.h"
 
 namespace gfx {
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 15dbc68..83093288 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -331,8 +331,8 @@
 
   settings.verify_property_trees =
       cmd->HasSwitch(cc::switches::kEnablePropertyTreeVerification);
-  settings.use_property_trees =
-      cmd->HasSwitch(cc::switches::kEnableCompositorPropertyTrees);
+  if (cmd->HasSwitch(cc::switches::kDisableCompositorPropertyTrees))
+    settings.use_property_trees = false;
   settings.renderer_settings.allow_antialiasing &=
       !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
   // The means the renderer compositor has 2 possible modes:
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 4d20f5e..869a4a5 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -62,7 +62,7 @@
 #include "third_party/webrtc/base/ssladapter.h"
 
 #if defined(OS_ANDROID)
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_codec_util.h"
 #endif
 
 namespace content {
@@ -415,7 +415,7 @@
   }
 
 #if defined(OS_ANDROID)
-  if (!media::MediaCodecBridge::SupportsSetParameters())
+  if (!media::MediaCodecUtil::SupportsSetParameters())
     encoder_factory.reset();
 #endif
 
diff --git a/content/renderer/npapi/webplugin_impl_unittest.cc b/content/renderer/npapi/webplugin_impl_unittest.cc
index 4576ea4..760c874 100644
--- a/content/renderer/npapi/webplugin_impl_unittest.cc
+++ b/content/renderer/npapi/webplugin_impl_unittest.cc
@@ -19,7 +19,7 @@
 
 std::string GetHeader(const WebURLRequest& request, const char* name) {
   std::string result;
-  base::TrimWhitespace(
+  base::TrimWhitespaceASCII(
       request.httpHeaderField(WebString::fromUTF8(name)).utf8(),
       base::TRIM_ALL,
       &result);
diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc
index 665fc08..ea1104a 100644
--- a/extensions/browser/extension_web_contents_observer.cc
+++ b/extensions/browser/extension_web_contents_observer.cc
@@ -5,6 +5,7 @@
 #include "extensions/browser/extension_web_contents_observer.h"
 
 #include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/navigation_details.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -50,18 +51,25 @@
   DCHECK(render_frame_host);
   DCHECK(render_frame_host->IsRenderFrameLive());
 
+  // At the initialization of the render frame, the last committed URL is not
+  // reliable, so do not take it into account in determining whether it is an
+  // extension frame.
+  const Extension* frame_extension =
+      GetExtensionFromFrame(render_frame_host, false);
+  // This observer is attached to every WebContents, so we are also notified of
+  // frames that are not in an extension process.
+  if (!frame_extension)
+    return;
+
   // Notify the render frame of the view type.
   render_frame_host->Send(new ExtensionMsg_NotifyRenderViewType(
       render_frame_host->GetRoutingID(), GetViewType(web_contents())));
 
-  const Extension* frame_extension = GetExtensionFromFrame(render_frame_host);
-  if (frame_extension) {
-    ExtensionsBrowserClient::Get()->RegisterMojoServices(render_frame_host,
-                                                         frame_extension);
-    ProcessManager::Get(browser_context_)
-        ->RegisterRenderFrameHost(web_contents(), render_frame_host,
-                                  frame_extension);
-  }
+  ExtensionsBrowserClient::Get()->RegisterMojoServices(render_frame_host,
+                                                       frame_extension);
+  ProcessManager::Get(browser_context_)
+      ->RegisterRenderFrameHost(web_contents(), render_frame_host,
+                                frame_extension);
 }
 
 content::WebContents* ExtensionWebContentsObserver::GetAssociatedWebContents()
@@ -110,6 +118,49 @@
       ->UnregisterRenderFrameHost(render_frame_host);
 }
 
+void ExtensionWebContentsObserver::DidCommitProvisionalLoadForFrame(
+    content::RenderFrameHost* render_frame_host,
+    const GURL& url,
+    ui::PageTransition transition_type) {
+  ProcessManager* pm = ProcessManager::Get(browser_context_);
+
+  if (pm->IsRenderFrameHostRegistered(render_frame_host)) {
+    const Extension* frame_extension =
+        GetExtensionFromFrame(render_frame_host, true);
+
+    if (!frame_extension)
+      pm->UnregisterRenderFrameHost(render_frame_host);
+  }
+}
+
+void ExtensionWebContentsObserver::DidNavigateAnyFrame(
+    content::RenderFrameHost* render_frame_host,
+    const content::LoadCommittedDetails& details,
+    const content::FrameNavigateParams& params) {
+  if (details.is_in_page)
+    return;
+
+  const Extension* frame_extension =
+      GetExtensionFromFrame(render_frame_host, true);
+  ProcessManager* pm = ProcessManager::Get(browser_context_);
+
+  if (!frame_extension) {
+    // Should have been unregistered by DidCommitProvisionalLoadForFrame.
+    DCHECK(!pm->IsRenderFrameHostRegistered(render_frame_host));
+    return;
+  }
+
+  if (pm->IsRenderFrameHostRegistered(render_frame_host)) {
+    // Notify ProcessManager, because some clients do not just want to know
+    // whether the frame is in an extension process, but also whether the frame
+    // was navigated.
+    pm->DidNavigateRenderFrameHost(render_frame_host);
+  } else {
+    pm->RegisterRenderFrameHost(web_contents(), render_frame_host,
+                                frame_extension);
+  }
+}
+
 bool ExtensionWebContentsObserver::OnMessageReceived(
     const IPC::Message& message,
     content::RenderFrameHost* render_frame_host) {
@@ -146,24 +197,38 @@
 
 std::string ExtensionWebContentsObserver::GetExtensionIdFromFrame(
     content::RenderFrameHost* render_frame_host) const {
-  content::SiteInstance* site_instance = render_frame_host->GetSiteInstance();
-  GURL url = render_frame_host->GetLastCommittedURL();
-  if (!url.is_empty()) {
-    if (site_instance->GetSiteURL().GetOrigin() != url.GetOrigin())
-      return std::string();
-  } else {
-    url = site_instance->GetSiteURL();
-  }
-
-  return url.SchemeIs(kExtensionScheme) ? url.host() : std::string();
+  const Extension* extension = GetExtensionFromFrame(render_frame_host, true);
+  return extension ? extension->id() : std::string();
 }
 
 const Extension* ExtensionWebContentsObserver::GetExtensionFromFrame(
-    content::RenderFrameHost* render_frame_host) const {
-  return ExtensionRegistry::Get(
-             render_frame_host->GetProcess()->GetBrowserContext())
-      ->enabled_extensions()
-      .GetByID(GetExtensionIdFromFrame(render_frame_host));
+    content::RenderFrameHost* render_frame_host,
+    bool verify_url) const {
+  const GURL site_url(render_frame_host->GetSiteInstance()->GetSiteURL());
+  if (!site_url.SchemeIs(kExtensionScheme))
+    return nullptr;
+
+  const std::string& extension_id = site_url.host();
+  content::BrowserContext* browser_context =
+      render_frame_host->GetProcess()->GetBrowserContext();
+  const Extension* extension = ExtensionRegistry::Get(browser_context)
+                                   ->enabled_extensions()
+                                   .GetByID(extension_id);
+  if (!extension)
+    return nullptr;
+
+  if (verify_url) {
+    const url::Origin& origin(render_frame_host->GetLastCommittedOrigin());
+    // Without site isolation, this check is needed to eliminate non-extension
+    // schemes. With site isolation, this is still needed to exclude sandboxed
+    // extension frames with a unique origin.
+    if (origin.unique() ||
+        site_url != content::SiteInstance::GetSiteForURL(
+                        browser_context, GURL(origin.Serialize())))
+      return nullptr;
+  }
+
+  return extension;
 }
 
 const Extension* ExtensionWebContentsObserver::GetExtension(
diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h
index c92ad9c..5b86dc0 100644
--- a/extensions/browser/extension_web_contents_observer.h
+++ b/extensions/browser/extension_web_contents_observer.h
@@ -29,6 +29,23 @@
 // WebContents. It must be a subclass so that creating an instance via
 // content::WebContentsUserData::CreateForWebContents() provides an object of
 // the correct type. For an example, see ChromeExtensionWebContentsObserver.
+//
+// This class is responsible for maintaining the registrations of extension
+// frames with the ProcessManager. Only frames in an extension process are
+// registered. If out-of-process frames are enabled, every frame hosts a
+// chrome-extension: page. Otherwise non-extension frames may erroneously be
+// registered, but only briefly until they are correctly classified. This is
+// achieved using the following notifications:
+// 1. RenderFrameCreated - registers all new frames in extension processes.
+// 2. DidCommitProvisionalLoadForFrame - unregisters non-extension frames.
+// 3. DidNavigateAnyFrame - registers extension frames if they had been
+//    unregistered.
+//
+// Without OOPIF, non-extension frames created by the Chrome extension are also
+// registered at RenderFrameCreated. When the non-extension page is committed,
+// we detect that the unexpected URL and unregister the frame.
+// With OOPIF only the first notification is sufficient in most cases, except
+// for sandboxed frames with a unique origin.
 class ExtensionWebContentsObserver
     : public content::WebContentsObserver,
       public ExtensionFunctionDispatcher::Delegate {
@@ -60,6 +77,13 @@
 
   void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
   void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+  void DidCommitProvisionalLoadForFrame(
+      content::RenderFrameHost* render_frame_host,
+      const GURL& url,
+      ui::PageTransition transition_type) override;
+  void DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host,
+                           const content::LoadCommittedDetails& details,
+                           const content::FrameNavigateParams& params) override;
 
   // Subclasses should call this first before doing their own message handling.
   bool OnMessageReceived(const IPC::Message& message,
@@ -77,8 +101,12 @@
 
   // Returns the extension associated with the given |render_frame_host|, or
   // null if there is none.
+  // If |verify_url| is false, only the SiteInstance is taken into account.
+  // If |verify_url| is true, the frame's last committed URL is also used to
+  // improve the classification of the frame.
   const Extension* GetExtensionFromFrame(
-      content::RenderFrameHost* render_frame_host) const;
+      content::RenderFrameHost* render_frame_host,
+      bool verify_url) const;
 
   // TODO(devlin): Remove these once callers are updated to use the FromFrame
   // equivalents.
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.cc b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
index 6a34aa0..5806540 100644
--- a/extensions/browser/guest_view/extension_options/extension_options_guest.cc
+++ b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
@@ -19,6 +19,7 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/guest_view/extension_options/extension_options_constants.h"
 #include "extensions/browser/guest_view/extension_options/extension_options_guest_delegate.h"
+#include "extensions/browser/view_type_utils.h"
 #include "extensions/common/api/extension_options_internal.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
@@ -108,7 +109,9 @@
       content::SiteInstance::CreateForURL(browser_context(), extension_url);
   WebContents::CreateParams params(browser_context(), options_site_instance);
   params.guest_delegate = this;
-  callback.Run(WebContents::Create(params));
+  WebContents* wc = WebContents::Create(params);
+  SetViewType(wc, VIEW_TYPE_EXTENSION_GUEST);
+  callback.Run(wc);
 }
 
 void ExtensionOptionsGuest::DidInitialize(
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index 8b2b4b534..581219b6 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -166,6 +166,7 @@
       case VIEW_TYPE_APP_WINDOW:
       case VIEW_TYPE_BACKGROUND_CONTENTS:
       case VIEW_TYPE_EXTENSION_DIALOG:
+      case VIEW_TYPE_EXTENSION_GUEST:
       case VIEW_TYPE_EXTENSION_POPUP:
       case VIEW_TYPE_LAUNCHER_PAGE:
       case VIEW_TYPE_PANEL:
@@ -309,6 +310,21 @@
   }
 }
 
+void ProcessManager::DidNavigateRenderFrameHost(
+    content::RenderFrameHost* render_frame_host) {
+  ExtensionRenderFrames::iterator frame =
+      all_extension_frames_.find(render_frame_host);
+
+  if (frame != all_extension_frames_.end()) {
+    std::string extension_id = GetExtensionID(render_frame_host);
+
+    FOR_EACH_OBSERVER(ProcessManagerObserver,
+                      observer_list_,
+                      OnExtensionFrameNavigated(extension_id,
+                                                render_frame_host));
+  }
+}
+
 scoped_refptr<content::SiteInstance> ProcessManager::GetSiteInstanceForURL(
     const GURL& url) {
   return make_scoped_refptr(site_instance_->GetRelatedSiteInstance(url));
@@ -324,20 +340,19 @@
 ProcessManager::FrameSet ProcessManager::GetRenderFrameHostsForExtension(
     const std::string& extension_id) {
   FrameSet result;
-  scoped_refptr<content::SiteInstance> site_instance(GetSiteInstanceForURL(
-      Extension::GetBaseURLFromExtensionId(extension_id)));
-  if (!site_instance.get())
-    return result;
-
-  // Gather up all the frames for that site.
   for (const auto& key_value : all_extension_frames_) {
-    if (key_value.first->GetSiteInstance() == site_instance)
+    if (GetExtensionID(key_value.first) == extension_id)
       result.insert(key_value.first);
   }
-
   return result;
 }
 
+bool ProcessManager::IsRenderFrameHostRegistered(
+    content::RenderFrameHost* render_frame_host) {
+  return all_extension_frames_.find(render_frame_host) !=
+         all_extension_frames_.end();
+}
+
 void ProcessManager::AddObserver(ProcessManagerObserver* observer) {
   observer_list_.AddObserver(observer);
 }
diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h
index 9d44453..c93bd80 100644
--- a/extensions/browser/process_manager.h
+++ b/extensions/browser/process_manager.h
@@ -56,6 +56,7 @@
                                content::RenderFrameHost* render_frame_host,
                                const Extension* extension);
   void UnregisterRenderFrameHost(content::RenderFrameHost* render_frame_host);
+  void DidNavigateRenderFrameHost(content::RenderFrameHost* render_frame_host);
 
   // Returns the SiteInstance that the given URL belongs to.
   // TODO(aa): This only returns correct results for extensions and packaged
@@ -71,6 +72,8 @@
   ProcessManager::FrameSet GetRenderFrameHostsForExtension(
       const std::string& extension_id);
 
+  bool IsRenderFrameHostRegistered(content::RenderFrameHost* render_frame_host);
+
   void AddObserver(ProcessManagerObserver* observer);
   void RemoveObserver(ProcessManagerObserver* observer);
 
diff --git a/extensions/browser/process_manager_observer.h b/extensions/browser/process_manager_observer.h
index 668b3df..47883ef 100644
--- a/extensions/browser/process_manager_observer.h
+++ b/extensions/browser/process_manager_observer.h
@@ -30,13 +30,21 @@
   // Called immediately after the extension background host is destroyed.
   virtual void OnBackgroundHostClose(const std::string& extension_id) {}
 
+  // Called when a RenderFrameHost has been registered in an extension process.
   virtual void OnExtensionFrameRegistered(
       const std::string& extension_id,
       content::RenderFrameHost* render_frame_host) {}
 
+  // Called when a RenderFrameHost is no longer part of an extension process.
   virtual void OnExtensionFrameUnregistered(
       const std::string& extension_id,
       content::RenderFrameHost* render_frame_host) {}
+
+  // Called when a RenderFrameHost was navigated to another page within the
+  // extension process.
+  virtual void OnExtensionFrameNavigated(
+      const std::string& extension_id,
+      content::RenderFrameHost* render_frame_host) {}
 };
 
 }  // namespace extensions
diff --git a/extensions/common/view_type.h b/extensions/common/view_type.h
index 82c906b5..bbe498d 100644
--- a/extensions/common/view_type.h
+++ b/extensions/common/view_type.h
@@ -18,6 +18,7 @@
   VIEW_TYPE_BACKGROUND_CONTENTS,
   VIEW_TYPE_EXTENSION_BACKGROUND_PAGE,
   VIEW_TYPE_EXTENSION_DIALOG,
+  VIEW_TYPE_EXTENSION_GUEST,
   VIEW_TYPE_EXTENSION_POPUP,
   VIEW_TYPE_LAUNCHER_PAGE,
   VIEW_TYPE_PANEL,
diff --git a/extensions/renderer/extension_frame_helper.cc b/extensions/renderer/extension_frame_helper.cc
index fe581c33..c063f84a 100644
--- a/extensions/renderer/extension_frame_helper.cc
+++ b/extensions/renderer/extension_frame_helper.cc
@@ -4,6 +4,7 @@
 
 #include "extensions/renderer/extension_frame_helper.h"
 
+#include "base/strings/string_util.h"
 #include "content/public/renderer/render_frame.h"
 #include "extensions/common/api/messaging/message.h"
 #include "extensions/common/constants.h"
@@ -14,6 +15,7 @@
 #include "extensions/renderer/dispatcher.h"
 #include "extensions/renderer/messaging_bindings.h"
 #include "extensions/renderer/script_context.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
@@ -34,11 +36,22 @@
   if (match_view_type != VIEW_TYPE_INVALID &&
       frame_helper->view_type() != match_view_type)
     return false;
-  GURL url = frame_helper->render_frame()->GetWebFrame()->document().url();
-  if (!url.SchemeIs(kExtensionScheme))
+
+  // Not all frames have a valid ViewType, e.g. devtools, most GuestViews, and
+  // unclassified detached WebContents.
+  if (frame_helper->view_type() == VIEW_TYPE_INVALID)
     return false;
-  if (url.host() != match_extension_id)
+
+  // This logic matches ExtensionWebContentsObserver::GetExtensionFromFrame.
+  blink::WebSecurityOrigin origin =
+      frame_helper->render_frame()->GetWebFrame()->securityOrigin();
+  if (origin.isUnique() ||
+      !base::EqualsASCII(base::StringPiece16(origin.protocol()),
+                         kExtensionScheme) ||
+      !base::EqualsASCII(base::StringPiece16(origin.host()),
+                         match_extension_id.c_str()))
     return false;
+
   if (match_window_id != extension_misc::kUnknownWindowId &&
       frame_helper->browser_window_id() != match_window_id)
     return false;
diff --git a/mandoline/ui/desktop_ui/BUILD.gn b/mandoline/ui/desktop_ui/BUILD.gn
index f5aa86bf..e84c565 100644
--- a/mandoline/ui/desktop_ui/BUILD.gn
+++ b/mandoline/ui/desktop_ui/BUILD.gn
@@ -35,6 +35,7 @@
   ]
 
   deps = [
+    "public/interfaces",
     "//base",
     "//components/web_view/public/cpp",
     "//components/web_view/public/interfaces",
@@ -51,7 +52,6 @@
     "//ui/views",
     "//ui/views/mus:for_mojo_application",
     "//url",
-    "public/interfaces",
   ]
 }
 
diff --git a/media/BUILD.gn b/media/BUILD.gn
index 4d7e198..d53cb64 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -395,6 +395,16 @@
       "//media/base/android:media_jni_headers",
       "//media/base/android:video_capture_jni_headers",
     ]
+
+    # Only 64 bit builds are using android-21 NDK library, check common.gypi
+    if (current_cpu == "arm64" || current_cpu == "x64" ||
+        current_cpu == "mips64el") {
+      sources += [
+        "base/android/ndk_media_codec_bridge.cc",
+        "base/android/ndk_media_codec_bridge.h",
+      ]
+      libs += [ "-lmediandk" ]
+    }
     allow_circular_includes_from = [ "//media/base/android" ]
   }
 
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn
index c51ee6b..75c6717c 100644
--- a/media/base/android/BUILD.gn
+++ b/media/base/android/BUILD.gn
@@ -31,6 +31,8 @@
     "media_codec_decoder.h",
     "media_codec_player.cc",
     "media_codec_player.h",
+    "media_codec_util.cc",
+    "media_codec_util.h",
     "media_codec_video_decoder.cc",
     "media_codec_video_decoder.h",
     "media_decoder_job.cc",
@@ -58,6 +60,8 @@
     "media_task_runner.h",
     "media_url_interceptor.h",
     "provision_fetcher.h",
+    "sdk_media_codec_bridge.cc",
+    "sdk_media_codec_bridge.h",
     "video_decoder_job.cc",
     "video_decoder_job.h",
     "webaudio_media_codec_bridge.cc",
@@ -81,12 +85,12 @@
   testonly = true
   sources = [
     "access_unit_queue_unittest.cc",
-    "media_codec_bridge_unittest.cc",
     "media_codec_decoder_unittest.cc",
     "media_codec_player_unittest.cc",
     "media_drm_bridge_unittest.cc",
     "media_player_bridge_unittest.cc",
     "media_source_player_unittest.cc",
+    "sdk_media_codec_bridge_unittest.cc",
     "test_data_factory.cc",
     "test_data_factory.h",
     "test_statistics.h",
@@ -106,6 +110,7 @@
     "java/src/org/chromium/media/AudioManagerAndroid.java",
     "java/src/org/chromium/media/AudioRecordInput.java",
     "java/src/org/chromium/media/MediaCodecBridge.java",
+    "java/src/org/chromium/media/MediaCodecUtil.java",
     "java/src/org/chromium/media/MediaDrmBridge.java",
     "java/src/org/chromium/media/MediaPlayerBridge.java",
     "java/src/org/chromium/media/MediaPlayerListener.java",
diff --git a/media/base/android/audio_decoder_job.cc b/media/base/android/audio_decoder_job.cc
index 4ef622a..06f728a2 100644
--- a/media/base/android/audio_decoder_job.cc
+++ b/media/base/android/audio_decoder_job.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/lazy_instance.h"
 #include "base/threading/thread.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/audio_timestamp_helper.h"
 #include "media/base/timestamp_constants.h"
 
@@ -161,10 +161,12 @@
   if (!media_codec_bridge_)
     return STATUS_FAILURE;
 
-  if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))->Start(
-      audio_codec_, config_sampling_rate_, num_channels_, &audio_extra_data_[0],
-      audio_extra_data_.size(), audio_codec_delay_ns_, audio_seek_preroll_ns_,
-      true, GetMediaCrypto().obj())) {
+  if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
+           ->ConfigureAndStart(audio_codec_, config_sampling_rate_,
+                               num_channels_, &audio_extra_data_[0],
+                               audio_extra_data_.size(), audio_codec_delay_ns_,
+                               audio_seek_preroll_ns_, true,
+                               GetMediaCrypto().obj())) {
     media_codec_bridge_.reset();
     return STATUS_FAILURE;
   }
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
index 72c3964..3a62582 100644
--- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
+++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
@@ -22,9 +22,6 @@
 import org.chromium.base.annotations.JNINamespace;
 
 import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * A wrapper of the MediaCodec class to facilitate exception capturing and
@@ -47,10 +44,6 @@
     private static final int MEDIA_CODEC_ABORT = 8;
     private static final int MEDIA_CODEC_ERROR = 9;
 
-    // Codec direction.  Keep this in sync with media_codec_bridge.h.
-    private static final int MEDIA_CODEC_DECODER = 0;
-    private static final int MEDIA_CODEC_ENCODER = 1;
-
     // Max adaptive playback size to be supplied to the decoder.
     private static final int MAX_ADAPTIVE_PLAYBACK_WIDTH = 1920;
     private static final int MAX_ADAPTIVE_PLAYBACK_HEIGHT = 1080;
@@ -100,37 +93,6 @@
         }
     }
 
-    /**
-     * This class represents supported android codec information.
-     */
-    private static class CodecInfo {
-        private final String mCodecType;  // e.g. "video/x-vnd.on2.vp8".
-        private final String mCodecName;  // e.g. "OMX.google.vp8.decoder".
-        private final int mDirection;
-
-        private CodecInfo(String codecType, String codecName,
-                          int direction) {
-            mCodecType = codecType;
-            mCodecName = codecName;
-            mDirection = direction;
-        }
-
-        @CalledByNative("CodecInfo")
-        private String codecType() {
-            return mCodecType;
-        }
-
-        @CalledByNative("CodecInfo")
-        private String codecName() {
-            return mCodecName;
-        }
-
-        @CalledByNative("CodecInfo")
-        private int direction() {
-            return mDirection;
-        }
-    }
-
     private static class DequeueOutputResult {
         private final int mStatus;
         private final int mIndex;
@@ -180,105 +142,6 @@
         }
     }
 
-    /**
-     * Get a list of supported android codec mimes.
-     */
-    @SuppressWarnings("deprecation")
-    @CalledByNative
-    private static CodecInfo[] getCodecsInfo() {
-        // Return the first (highest-priority) codec for each MIME type.
-        Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>();
-        Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>();
-        int count = MediaCodecList.getCodecCount();
-        for (int i = 0; i < count; ++i) {
-            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
-            int direction =
-                    info.isEncoder() ? MEDIA_CODEC_ENCODER : MEDIA_CODEC_DECODER;
-            String codecString = info.getName();
-            String[] supportedTypes = info.getSupportedTypes();
-            for (int j = 0; j < supportedTypes.length; ++j) {
-                Map<String, CodecInfo> map = info.isEncoder() ? encoderInfoMap : decoderInfoMap;
-                if (!map.containsKey(supportedTypes[j])) {
-                    map.put(supportedTypes[j], new CodecInfo(
-                            supportedTypes[j], codecString, direction));
-                }
-            }
-        }
-        ArrayList<CodecInfo> codecInfos = new ArrayList<CodecInfo>(
-                decoderInfoMap.size() + encoderInfoMap.size());
-        codecInfos.addAll(encoderInfoMap.values());
-        codecInfos.addAll(decoderInfoMap.values());
-        return codecInfos.toArray(new CodecInfo[codecInfos.size()]);
-    }
-
-    /**
-     * Get a name of default android codec.
-     */
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
-    @SuppressWarnings("deprecation")
-    @CalledByNative
-    private static String getDefaultCodecName(String mime, int direction) {
-        String codecName = "";
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
-            try {
-                MediaCodec mediaCodec = null;
-                if (direction == MEDIA_CODEC_ENCODER) {
-                    mediaCodec = MediaCodec.createEncoderByType(mime);
-                } else {
-                    mediaCodec = MediaCodec.createDecoderByType(mime);
-                }
-                codecName = mediaCodec.getName();
-                mediaCodec.release();
-            } catch (Exception e) {
-                Log.w(TAG, "getDefaultCodecName: Failed to create MediaCodec: %s, direction: %d",
-                        mime, direction, e);
-            }
-        }
-        return codecName;
-    }
-
-    /**
-     * Get a list of encoder supported color formats for specified mime type.
-     */
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    @SuppressWarnings("deprecation")
-    @CalledByNative
-    private static int[] getEncoderColorFormatsForMime(String mime) {
-        MediaCodecInfo[] codecs = null;
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
-            codecs = mediaCodecList.getCodecInfos();
-        } else {
-            int count = MediaCodecList.getCodecCount();
-            if (count <= 0) {
-                return null;
-            }
-            codecs = new MediaCodecInfo[count];
-            for (int i = 0; i < count; ++i) {
-                MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
-                codecs[i] = info;
-            }
-        }
-
-        for (int i = 0; i < codecs.length; i++) {
-            if (!codecs[i].isEncoder()) {
-                continue;
-            }
-
-            String[] supportedTypes = codecs[i].getSupportedTypes();
-            for (int j = 0; j < supportedTypes.length; ++j) {
-                if (!supportedTypes[j].equalsIgnoreCase(mime)) {
-                    continue;
-                }
-
-                MediaCodecInfo.CodecCapabilities capabilities =
-                        codecs[i].getCapabilitiesForType(mime);
-                return capabilities.colorFormats;
-            }
-        }
-        return null;
-    }
-
     @SuppressWarnings("deprecation")
     private static String getDecoderNameForMime(String mime) {
         int count = MediaCodecList.getCodecCount();
@@ -321,8 +184,9 @@
         boolean adaptivePlaybackSupported = false;
         try {
             // |isSecure| only applies to video decoders.
-            if (mime.startsWith("video") && isSecure && direction == MEDIA_CODEC_DECODER) {
-                String decoderName = getDecoderNameForMime(mime);
+            if (mime.startsWith("video") && isSecure
+                    && direction == MediaCodecUtil.MEDIA_CODEC_DECODER) {
+                String decoderName = MediaCodecUtil.getDecoderNameForMime(mime);
                 if (decoderName == null) {
                     return null;
                 }
@@ -336,7 +200,7 @@
                 }
                 mediaCodec = MediaCodec.createByCodecName(decoderName + ".secure");
             } else {
-                if (direction == MEDIA_CODEC_ENCODER) {
+                if (direction == MediaCodecUtil.MEDIA_CODEC_ENCODER) {
                     mediaCodec = MediaCodec.createEncoderByType(mime);
                 } else {
                     mediaCodec = MediaCodec.createDecoderByType(mime);
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java b/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java
new file mode 100644
index 0000000..b498b29
--- /dev/null
+++ b/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java
@@ -0,0 +1,231 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.media;
+
+import android.annotation.TargetApi;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.os.Build;
+
+import org.chromium.base.Log;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A collection of MediaCodec utility functions.
+ */
+@JNINamespace("media")
+class MediaCodecUtil {
+    private static final String TAG = "MediaCodecUtil";
+
+    // Codec direction.  Keep this in sync with media_codec_bridge.h.
+    static final int MEDIA_CODEC_DECODER = 0;
+    static final int MEDIA_CODEC_ENCODER = 1;
+
+    /**
+     * This class represents supported android codec information.
+     */
+    private static class CodecInfo {
+        private final String mCodecType; // e.g. "video/x-vnd.on2.vp8".
+        private final String mCodecName; // e.g. "OMX.google.vp8.decoder".
+        private final int mDirection;
+
+        private CodecInfo(String codecType, String codecName, int direction) {
+            mCodecType = codecType;
+            mCodecName = codecName;
+            mDirection = direction;
+        }
+
+        @CalledByNative("CodecInfo")
+        private String codecType() {
+            return mCodecType;
+        }
+
+        @CalledByNative("CodecInfo")
+        private String codecName() {
+            return mCodecName;
+        }
+
+        @CalledByNative("CodecInfo")
+        private int direction() {
+            return mDirection;
+        }
+    }
+
+    /**
+     * @return a list of supported android codec information.
+     */
+    @SuppressWarnings("deprecation")
+    @CalledByNative
+    private static CodecInfo[] getCodecsInfo() {
+        // Return the first (highest-priority) codec for each MIME type.
+        Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>();
+        Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>();
+        int count = MediaCodecList.getCodecCount();
+        for (int i = 0; i < count; ++i) {
+            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+            int direction = info.isEncoder() ? MEDIA_CODEC_ENCODER : MEDIA_CODEC_DECODER;
+            String codecString = info.getName();
+            String[] supportedTypes = info.getSupportedTypes();
+            for (int j = 0; j < supportedTypes.length; ++j) {
+                Map<String, CodecInfo> map = info.isEncoder() ? encoderInfoMap : decoderInfoMap;
+                if (!map.containsKey(supportedTypes[j])) {
+                    map.put(supportedTypes[j],
+                            new CodecInfo(supportedTypes[j], codecString, direction));
+                }
+            }
+        }
+        ArrayList<CodecInfo> codecInfos =
+                new ArrayList<CodecInfo>(decoderInfoMap.size() + encoderInfoMap.size());
+        codecInfos.addAll(encoderInfoMap.values());
+        codecInfos.addAll(decoderInfoMap.values());
+        return codecInfos.toArray(new CodecInfo[codecInfos.size()]);
+    }
+
+    /**
+     * Get a name of default android codec.
+     * @param mime MIME type of the media.
+     * @param direction Whether this is encoder or decoder.
+     * @return name of the codec.
+     */
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
+    @SuppressWarnings("deprecation")
+    @CalledByNative
+    private static String getDefaultCodecName(String mime, int direction) {
+        String codecName = "";
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+            try {
+                MediaCodec mediaCodec = null;
+                if (direction == MEDIA_CODEC_ENCODER) {
+                    mediaCodec = MediaCodec.createEncoderByType(mime);
+                } else {
+                    mediaCodec = MediaCodec.createDecoderByType(mime);
+                }
+                codecName = mediaCodec.getName();
+                mediaCodec.release();
+            } catch (Exception e) {
+                Log.w(TAG, "getDefaultCodecName: Failed to create MediaCodec: %s, direction: %d",
+                        mime, direction, e);
+            }
+        }
+        return codecName;
+    }
+
+    /**
+     * Get a list of encoder supported color formats for specified MIME type.
+     * @param mime MIME type of the media format.
+     * @return a list of encoder supported color formats.
+     */
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    @SuppressWarnings("deprecation")
+    @CalledByNative
+    private static int[] getEncoderColorFormatsForMime(String mime) {
+        MediaCodecInfo[] codecs = null;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
+            codecs = mediaCodecList.getCodecInfos();
+        } else {
+            int count = MediaCodecList.getCodecCount();
+            if (count <= 0) {
+                return null;
+            }
+            codecs = new MediaCodecInfo[count];
+            for (int i = 0; i < count; ++i) {
+                MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+                codecs[i] = info;
+            }
+        }
+
+        for (int i = 0; i < codecs.length; i++) {
+            if (!codecs[i].isEncoder()) {
+                continue;
+            }
+
+            String[] supportedTypes = codecs[i].getSupportedTypes();
+            for (int j = 0; j < supportedTypes.length; ++j) {
+                if (!supportedTypes[j].equalsIgnoreCase(mime)) {
+                    continue;
+                }
+
+                MediaCodecInfo.CodecCapabilities capabilities =
+                        codecs[i].getCapabilitiesForType(mime);
+                return capabilities.colorFormats;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get decoder name for the input MIME type.
+     * @param mime MIME type of the media.
+     * @return name of the decoder.
+     */
+    @SuppressWarnings("deprecation")
+    protected static String getDecoderNameForMime(String mime) {
+        int count = MediaCodecList.getCodecCount();
+        for (int i = 0; i < count; ++i) {
+            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+            if (info.isEncoder()) {
+                continue;
+            }
+
+            String[] supportedTypes = info.getSupportedTypes();
+            for (int j = 0; j < supportedTypes.length; ++j) {
+                if (supportedTypes[j].equalsIgnoreCase(mime)) {
+                    return info.getName();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Check if a given MIME type can be decoded.
+     * @param mime MIME type of the media.
+     * @param secure Whether secure decoder is required.
+     * @return true if system is able to decode, or false otherwise.
+     */
+    @CalledByNative
+    private static boolean canDecode(String mime, boolean isSecure) {
+        // Creation of ".secure" codecs sometimes crash instead of throwing exceptions
+        // on pre-JBMR2 devices.
+        if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
+            return false;
+        }
+        MediaCodec mediaCodec = null;
+        try {
+            // |isSecure| only applies to video decoders.
+            if (mime.startsWith("video") && isSecure) {
+                String decoderName = getDecoderNameForMime(mime);
+                if (decoderName == null) return false;
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+                    // To work around an issue that we cannot get the codec info from the secure
+                    // decoder, create an insecure decoder first so that we can query its codec
+                    // info. http://b/15587335.
+                    MediaCodec insecureCodec = MediaCodec.createByCodecName(decoderName);
+                    insecureCodec.release();
+                }
+                mediaCodec = MediaCodec.createByCodecName(decoderName + ".secure");
+            } else {
+                mediaCodec = MediaCodec.createDecoderByType(mime);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to create MediaCodec: %s, isSecure: %s", mime, isSecure, e);
+        }
+
+        if (mediaCodec == null) return false;
+        try {
+            mediaCodec.release();
+        } catch (IllegalStateException e) {
+            Log.e(TAG, "Cannot release media codec", e);
+        }
+        return true;
+    }
+}
diff --git a/media/base/android/media_codec_audio_decoder.cc b/media/base/android/media_codec_audio_decoder.cc
index 4b8a076..f68a07e 100644
--- a/media/base/android/media_codec_audio_decoder.cc
+++ b/media/base/android/media_codec_audio_decoder.cc
@@ -6,8 +6,8 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_statistics.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/audio_timestamp_helper.h"
 #include "media/base/demuxer_stream.h"
 
@@ -144,16 +144,11 @@
     return kConfigFailure;
 
   if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
-           ->Start(
-               configs_.audio_codec,
-               configs_.audio_sampling_rate,
-               configs_.audio_channels,
-               &configs_.audio_extra_data[0],
-               configs_.audio_extra_data.size(),
-               configs_.audio_codec_delay_ns,
-               configs_.audio_seek_preroll_ns,
-               true,
-               media_crypto)) {
+           ->ConfigureAndStart(
+               configs_.audio_codec, configs_.audio_sampling_rate,
+               configs_.audio_channels, &configs_.audio_extra_data[0],
+               configs_.audio_extra_data.size(), configs_.audio_codec_delay_ns,
+               configs_.audio_seek_preroll_ns, true, media_crypto)) {
     DVLOG(0) << class_name() << "::" << __FUNCTION__
              << " failed: cannot start audio codec";
 
diff --git a/media/base/android/media_codec_bridge.cc b/media/base/android/media_codec_bridge.cc
index 9bae69edd..c242dba3 100644
--- a/media/base/android/media_codec_bridge.cc
+++ b/media/base/android/media_codec_bridge.cc
@@ -11,13 +11,8 @@
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "base/basictypes.h"
-#include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/numerics/safe_conversions.h"
 #include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "jni/MediaCodecBridge_jni.h"
-#include "media/base/bit_reader.h"
 #include "media/base/decrypt_config.h"
 
 using base::android::AttachCurrentThread;
@@ -26,320 +21,11 @@
 using base::android::JavaIntArrayToIntVector;
 using base::android::ScopedJavaLocalRef;
 
-#define RETURN_ON_ERROR(condition)                          \
-  do {                                                           \
-    if (!(condition)) {                                          \
-      LOG(ERROR) << "Unable to parse AAC header: " #condition; \
-      return false;                                              \
-    }                                                            \
-  } while (0)
-
 namespace media {
 
-enum {
-  kBufferFlagSyncFrame = 1,    // BUFFER_FLAG_SYNC_FRAME
-  kBufferFlagEndOfStream = 4,  // BUFFER_FLAG_END_OF_STREAM
-  kConfigureFlagEncode = 1,    // CONFIGURE_FLAG_ENCODE
-};
+MediaCodecBridge::MediaCodecBridge() {}
 
-static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
-  switch (codec) {
-    case kCodecMP3:
-      return "audio/mpeg";
-    case kCodecVorbis:
-      return "audio/vorbis";
-    case kCodecOpus:
-      return "audio/opus";
-    case kCodecAAC:
-      return "audio/mp4a-latm";
-    default:
-      return std::string();
-  }
-}
-
-static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
-  switch (codec) {
-    case kCodecH264:
-      return "video/avc";
-    case kCodecHEVC:
-      return "video/hevc";
-    case kCodecVP8:
-      return "video/x-vnd.on2.vp8";
-    case kCodecVP9:
-      return "video/x-vnd.on2.vp9";
-    default:
-      return std::string();
-  }
-}
-
-static const std::string CodecTypeToAndroidMimeType(const std::string& codec) {
-  // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"?
-  if (codec == "avc1")
-    return "video/avc";
-  if (codec == "hvc1")
-    return "video/hevc";
-  if (codec == "mp4a")
-    return "audio/mp4a-latm";
-  if (codec == "vp8" || codec == "vp8.0")
-    return "video/x-vnd.on2.vp8";
-  if (codec == "vp9" || codec == "vp9.0")
-    return "video/x-vnd.on2.vp9";
-  if (codec == "vorbis")
-    return "audio/vorbis";
-  if (codec == "opus")
-    return "audio/opus";
-  return std::string();
-}
-
-// TODO(qinmin): using a map to help all the conversions in this class.
-static const std::string AndroidMimeTypeToCodecType(const std::string& mime) {
-  if (mime == "video/mp4v-es")
-    return "mp4v";
-  if (mime == "video/avc")
-    return "avc1";
-  if (mime == "video/hevc")
-    return "hvc1";
-  if (mime == "video/x-vnd.on2.vp8")
-    return "vp8";
-  if (mime == "video/x-vnd.on2.vp9")
-    return "vp9";
-  if (mime == "audio/mp4a-latm")
-    return "mp4a";
-  if (mime == "audio/mpeg")
-    return "mp3";
-  if (mime == "audio/vorbis")
-    return "vorbis";
-  if (mime == "audio/opus")
-    return "opus";
-  return std::string();
-}
-
-static ScopedJavaLocalRef<jintArray>
-ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) {
-  ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
-  env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
-  return j_array;
-}
-
-// static
-bool MediaCodecBridge::IsAvailable() {
-  // MediaCodec is only available on JB and greater.
-  if (base::android::BuildInfo::GetInstance()->sdk_int() < 16)
-    return false;
-  // Blacklist some devices on Jellybean as for MediaCodec support is buggy.
-  // http://crbug.com/365494.
-  if (base::android::BuildInfo::GetInstance()->sdk_int() == 16) {
-    std::string model(base::android::BuildInfo::GetInstance()->model());
-    return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000";
-  }
-  return true;
-}
-
-// static
-bool MediaCodecBridge::SupportsSetParameters() {
-  // MediaCodec.setParameters() is only available starting with K.
-  return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
-}
-
-// static
-bool MediaCodecBridge::SupportsGetName() {
-  // MediaCodec.getName() is only available on JB MR2 and greater.
-  return base::android::BuildInfo::GetInstance()->sdk_int() >= 18;
-}
-
-// static
-std::vector<MediaCodecBridge::CodecsInfo> MediaCodecBridge::GetCodecsInfo() {
-  std::vector<CodecsInfo> codecs_info;
-  if (!IsAvailable())
-    return codecs_info;
-
-  JNIEnv* env = AttachCurrentThread();
-  std::string mime_type;
-  ScopedJavaLocalRef<jobjectArray> j_codec_info_array =
-      Java_MediaCodecBridge_getCodecsInfo(env);
-  jsize len = env->GetArrayLength(j_codec_info_array.obj());
-  for (jsize i = 0; i < len; ++i) {
-    ScopedJavaLocalRef<jobject> j_info(
-        env, env->GetObjectArrayElement(j_codec_info_array.obj(), i));
-    ScopedJavaLocalRef<jstring> j_codec_type =
-        Java_CodecInfo_codecType(env, j_info.obj());
-    ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type);
-    ScopedJavaLocalRef<jstring> j_codec_name =
-        Java_CodecInfo_codecName(env, j_info.obj());
-    CodecsInfo info;
-    info.codecs = AndroidMimeTypeToCodecType(mime_type);
-    ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name);
-    info.direction = static_cast<MediaCodecDirection>(
-        Java_CodecInfo_direction(env, j_info.obj()));
-    codecs_info.push_back(info);
-  }
-  return codecs_info;
-}
-
-// static
-std::string MediaCodecBridge::GetDefaultCodecName(
-    const std::string& mime_type,
-    MediaCodecDirection direction) {
-  if (!IsAvailable())
-    return std::string();
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
-  ScopedJavaLocalRef<jstring> j_codec_name =
-      Java_MediaCodecBridge_getDefaultCodecName(env, j_mime.obj(), direction);
-  return ConvertJavaStringToUTF8(env, j_codec_name.obj());
-}
-
-// static
-std::set<int> MediaCodecBridge::GetEncoderColorFormats(
-    const std::string& mime_type) {
-  std::set<int> color_formats;
-  if (!IsAvailable())
-    return color_formats;
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
-  ScopedJavaLocalRef<jintArray> j_color_format_array =
-      Java_MediaCodecBridge_getEncoderColorFormatsForMime(env, j_mime.obj());
-
-  if (j_color_format_array.obj()) {
-    std::vector<int> formats;
-    JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats);
-    color_formats = std::set<int>(formats.begin(), formats.end());
-  }
-
-  return color_formats;
-}
-
-// static
-bool MediaCodecBridge::CanDecode(const std::string& codec, bool is_secure) {
-  if (!IsAvailable())
-    return false;
-
-  JNIEnv* env = AttachCurrentThread();
-  std::string mime = CodecTypeToAndroidMimeType(codec);
-  if (mime.empty())
-    return false;
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
-  ScopedJavaLocalRef<jobject> j_media_codec_bridge =
-      Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, false);
-  if (!j_media_codec_bridge.is_null()) {
-    Java_MediaCodecBridge_release(env, j_media_codec_bridge.obj());
-    return true;
-  }
-  return false;
-}
-
-// static
-bool MediaCodecBridge::IsKnownUnaccelerated(const std::string& mime_type,
-                                            MediaCodecDirection direction) {
-  if (!IsAvailable())
-    return true;
-
-  std::string codec_name;
-  if (SupportsGetName()) {
-    codec_name = GetDefaultCodecName(mime_type, direction);
-  } else {
-    std::string codec_type = AndroidMimeTypeToCodecType(mime_type);
-    std::vector<media::MediaCodecBridge::CodecsInfo> codecs_info =
-        MediaCodecBridge::GetCodecsInfo();
-    for (size_t i = 0; i < codecs_info.size(); ++i) {
-      if (codecs_info[i].codecs == codec_type &&
-          codecs_info[i].direction == direction) {
-        codec_name = codecs_info[i].name;
-        break;
-      }
-    }
-  }
-  DVLOG(1) << __PRETTY_FUNCTION__ << "Default codec for " << mime_type <<
-      " : " << codec_name;
-  // It would be nice if MediaCodecInfo externalized some notion of
-  // HW-acceleration but it doesn't. Android Media guidance is that the
-  // "OMX.google" prefix is always used for SW decoders, so that's what we
-  // use. "OMX.SEC.*" codec is Samsung software implementation - report it
-  // as unaccelerated as well. Also temporary blacklist Exynos and MediaTek
-  // devices while HW decoder video freezes and distortions are
-  // investigated - http://crbug.com/446974.
-  if (codec_name.length() > 0) {
-    return (base::StartsWith(codec_name, "OMX.google.",
-                             base::CompareCase::SENSITIVE) ||
-            base::StartsWith(codec_name, "OMX.SEC.",
-                             base::CompareCase::SENSITIVE) ||
-            base::StartsWith(codec_name, "OMX.MTK.",
-                             base::CompareCase::SENSITIVE) ||
-            base::StartsWith(codec_name, "OMX.Exynos.",
-                             base::CompareCase::SENSITIVE));
-  }
-  return true;
-}
-
-MediaCodecBridge::MediaCodecBridge(const std::string& mime,
-                                   bool is_secure,
-                                   MediaCodecDirection direction) {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-  DCHECK(!mime.empty());
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
-  j_media_codec_.Reset(
-      Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction));
-}
-
-MediaCodecBridge::~MediaCodecBridge() {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-  if (j_media_codec_.obj())
-    Java_MediaCodecBridge_release(env, j_media_codec_.obj());
-}
-
-bool MediaCodecBridge::StartInternal() {
-  JNIEnv* env = AttachCurrentThread();
-  return Java_MediaCodecBridge_start(env, j_media_codec_.obj());
-}
-
-MediaCodecStatus MediaCodecBridge::Reset() {
-  JNIEnv* env = AttachCurrentThread();
-  return static_cast<MediaCodecStatus>(
-      Java_MediaCodecBridge_flush(env, j_media_codec_.obj()));
-}
-
-void MediaCodecBridge::Stop() {
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_stop(env, j_media_codec_.obj());
-}
-
-void MediaCodecBridge::GetOutputFormat(int* width, int* height) {
-  JNIEnv* env = AttachCurrentThread();
-
-  *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj());
-  *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj());
-}
-
-int MediaCodecBridge::GetOutputSamplingRate() {
-  JNIEnv* env = AttachCurrentThread();
-
-  return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj());
-}
-
-MediaCodecStatus MediaCodecBridge::QueueInputBuffer(
-    int index,
-    const uint8* data,
-    size_t data_size,
-    const base::TimeDelta& presentation_time) {
-  DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
-  if (data_size > base::checked_cast<size_t>(kint32max))
-    return MEDIA_CODEC_ERROR;
-  if (data && !FillInputBuffer(index, data, data_size))
-    return MEDIA_CODEC_ERROR;
-  JNIEnv* env = AttachCurrentThread();
-  return static_cast<MediaCodecStatus>(
-      Java_MediaCodecBridge_queueInputBuffer(env,
-                                             j_media_codec_.obj(),
-                                             index,
-                                             0,
-                                             data_size,
-                                             presentation_time.InMicroseconds(),
-                                             0));
-}
+MediaCodecBridge::~MediaCodecBridge() {}
 
 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer(
     int index,
@@ -349,204 +35,25 @@
     const std::string& iv,
     const std::vector<SubsampleEntry>& subsamples,
     const base::TimeDelta& presentation_time) {
-  return QueueSecureInputBuffer(
-      index, data, data_size, reinterpret_cast<const uint8_t*>(key_id.data()),
-      key_id.size(), reinterpret_cast<const uint8_t*>(iv.data()), iv.size(),
-      subsamples.empty() ? nullptr : &subsamples[0], subsamples.size(),
-      presentation_time);
-}
-
-// TODO(timav): Combine this and above methods together keeping only the first
-// interface after we switch to Spitzer pipeline.
-MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer(
-    int index,
-    const uint8* data,
-    size_t data_size,
-    const uint8* key_id,
-    int key_id_size,
-    const uint8* iv,
-    int iv_size,
-    const SubsampleEntry* subsamples,
-    int subsamples_size,
-    const base::TimeDelta& presentation_time) {
-  DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
-  if (data_size > base::checked_cast<size_t>(kint32max))
-    return MEDIA_CODEC_ERROR;
-  if (data && !FillInputBuffer(index, data, data_size))
-    return MEDIA_CODEC_ERROR;
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jbyteArray> j_key_id =
-      base::android::ToJavaByteArray(env, key_id, key_id_size);
-  ScopedJavaLocalRef<jbyteArray> j_iv =
-      base::android::ToJavaByteArray(env, iv, iv_size);
-
-  // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array|
-  // to indicate that all data is encrypted. But it doesn't specify what
-  // |cypher_array| and |subsamples_size| should be in that case. Passing
-  // one subsample here just to be on the safe side.
-  int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
-
-  scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]);
-  scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]);
-
-  if (subsamples_size == 0) {
-    DCHECK(!subsamples);
-    native_clear_array[0] = 0;
-    native_cypher_array[0] = data_size;
-  } else {
-    DCHECK_GT(subsamples_size, 0);
-    DCHECK(subsamples);
-    for (int i = 0; i < subsamples_size; ++i) {
-      DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max());
-      if (subsamples[i].cypher_bytes >
-          static_cast<uint32>(std::numeric_limits<jint>::max())) {
-        return MEDIA_CODEC_ERROR;
-      }
-
-      native_clear_array[i] = subsamples[i].clear_bytes;
-      native_cypher_array[i] = subsamples[i].cypher_bytes;
-    }
-  }
-
-  ScopedJavaLocalRef<jintArray> clear_array =
-      ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size);
-  ScopedJavaLocalRef<jintArray> cypher_array =
-      ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size);
-
-  return static_cast<MediaCodecStatus>(
-      Java_MediaCodecBridge_queueSecureInputBuffer(
-          env,
-          j_media_codec_.obj(),
-          index,
-          0,
-          j_iv.obj(),
-          j_key_id.obj(),
-          clear_array.obj(),
-          cypher_array.obj(),
-          new_subsamples_size,
-          presentation_time.InMicroseconds()));
-}
-
-void MediaCodecBridge::QueueEOS(int input_buffer_index) {
-  DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index;
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_queueInputBuffer(env,
-                                         j_media_codec_.obj(),
-                                         input_buffer_index,
-                                         0,
-                                         0,
-                                         0,
-                                         kBufferFlagEndOfStream);
-}
-
-MediaCodecStatus MediaCodecBridge::DequeueInputBuffer(
-    const base::TimeDelta& timeout,
-    int* index) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer(
-      env, j_media_codec_.obj(), timeout.InMicroseconds());
-  *index = Java_DequeueInputResult_index(env, result.obj());
-  MediaCodecStatus status = static_cast<MediaCodecStatus>(
-      Java_DequeueInputResult_status(env, result.obj()));
-  DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
-           << ", index: " << *index;
-  return status;
-}
-
-MediaCodecStatus MediaCodecBridge::DequeueOutputBuffer(
-    const base::TimeDelta& timeout,
-    int* index,
-    size_t* offset,
-    size_t* size,
-    base::TimeDelta* presentation_time,
-    bool* end_of_stream,
-    bool* key_frame) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> result =
-      Java_MediaCodecBridge_dequeueOutputBuffer(
-          env, j_media_codec_.obj(), timeout.InMicroseconds());
-  *index = Java_DequeueOutputResult_index(env, result.obj());
-  *offset = base::checked_cast<size_t>(
-      Java_DequeueOutputResult_offset(env, result.obj()));
-  *size = base::checked_cast<size_t>(
-      Java_DequeueOutputResult_numBytes(env, result.obj()));
-  if (presentation_time) {
-    *presentation_time = base::TimeDelta::FromMicroseconds(
-        Java_DequeueOutputResult_presentationTimeMicroseconds(env,
-                                                              result.obj()));
-  }
-  int flags = Java_DequeueOutputResult_flags(env, result.obj());
-  if (end_of_stream)
-    *end_of_stream = flags & kBufferFlagEndOfStream;
-  if (key_frame)
-    *key_frame = flags & kBufferFlagSyncFrame;
-  MediaCodecStatus status = static_cast<MediaCodecStatus>(
-      Java_DequeueOutputResult_status(env, result.obj()));
-  DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
-           << ", index: " << *index << ", offset: " << *offset
-           << ", size: " << *size << ", flags: " << flags;
-  return status;
-}
-
-void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
-  DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index;
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-
-  Java_MediaCodecBridge_releaseOutputBuffer(
-      env, j_media_codec_.obj(), index, render);
+  const std::vector<char> key_vec(key_id.begin(), key_id.end());
+  const std::vector<char> iv_vec(iv.begin(), iv.end());
+  return QueueSecureInputBuffer(index, data, data_size, key_vec, iv_vec,
+                                subsamples.empty() ? nullptr : &subsamples[0],
+                                subsamples.size(), presentation_time);
 }
 
 int MediaCodecBridge::GetOutputBuffersCount() {
-  JNIEnv* env = AttachCurrentThread();
-  return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj());
+  return 0;
 }
 
 size_t MediaCodecBridge::GetOutputBuffersCapacity() {
-  JNIEnv* env = AttachCurrentThread();
-  return Java_MediaCodecBridge_getOutputBuffersCapacity(env,
-                                                        j_media_codec_.obj());
-}
-
-void MediaCodecBridge::GetInputBuffer(int input_buffer_index,
-                                      uint8** data,
-                                      size_t* capacity) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer(
-      env, j_media_codec_.obj(), input_buffer_index));
-  *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
-  *capacity = base::checked_cast<size_t>(
-      env->GetDirectBufferCapacity(j_buffer.obj()));
-}
-
-bool MediaCodecBridge::CopyFromOutputBuffer(int index,
-                                            size_t offset,
-                                            void* dst,
-                                            int dst_size) {
-  void* src_data = nullptr;
-  int src_capacity = GetOutputBufferAddress(index, offset, &src_data);
-  if (src_capacity < dst_size)
-    return false;
-  memcpy(dst, src_data, dst_size);
-  return true;
-}
-
-int MediaCodecBridge::GetOutputBufferAddress(int index,
-                                             size_t offset,
-                                             void** addr) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> j_buffer(
-      Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index));
-  *addr = reinterpret_cast<uint8*>(
-      env->GetDirectBufferAddress(j_buffer.obj())) + offset;
-  return env->GetDirectBufferCapacity(j_buffer.obj()) - offset;
+  return 0;
 }
 
 bool MediaCodecBridge::FillInputBuffer(int index,
                                        const uint8* data,
                                        size_t size) {
-  uint8* dst = NULL;
+  uint8* dst = nullptr;
   size_t capacity = 0;
   GetInputBuffer(index, &dst, &capacity);
   CHECK(dst);
@@ -561,334 +68,4 @@
   return true;
 }
 
-AudioCodecBridge::AudioCodecBridge(const std::string& mime)
-    // Audio codec doesn't care about security level and there is no need for
-    // audio encoding yet.
-    : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {}
-
-bool AudioCodecBridge::Start(const AudioCodec& codec,
-                             int sample_rate,
-                             int channel_count,
-                             const uint8* extra_data,
-                             size_t extra_data_size,
-                             int64 codec_delay_ns,
-                             int64 seek_preroll_ns,
-                             bool play_audio,
-                             jobject media_crypto) {
-  JNIEnv* env = AttachCurrentThread();
-
-  if (!media_codec())
-    return false;
-
-  std::string codec_string = AudioCodecToAndroidMimeType(codec);
-  if (codec_string.empty())
-    return false;
-
-  ScopedJavaLocalRef<jstring> j_mime =
-      ConvertUTF8ToJavaString(env, codec_string);
-  ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat(
-      env, j_mime.obj(), sample_rate, channel_count));
-  DCHECK(!j_format.is_null());
-
-  if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size,
-                            codec_delay_ns, seek_preroll_ns)) {
-    return false;
-  }
-
-  if (!Java_MediaCodecBridge_configureAudio(
-           env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) {
-    return false;
-  }
-
-  return StartInternal();
-}
-
-bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
-                                            const AudioCodec& codec,
-                                            const uint8* extra_data,
-                                            size_t extra_data_size,
-                                            int64 codec_delay_ns,
-                                            int64 seek_preroll_ns) {
-  if (extra_data_size == 0 && codec != kCodecOpus)
-    return true;
-
-  JNIEnv* env = AttachCurrentThread();
-  switch (codec) {
-    case kCodecVorbis: {
-      if (extra_data[0] != 2) {
-        LOG(ERROR) << "Invalid number of vorbis headers before the codec "
-                   << "header: " << extra_data[0];
-        return false;
-      }
-
-      size_t header_length[2];
-      // |total_length| keeps track of the total number of bytes before the last
-      // header.
-      size_t total_length = 1;
-      const uint8* current_pos = extra_data;
-      // Calculate the length of the first 2 headers.
-      for (int i = 0; i < 2; ++i) {
-        header_length[i] = 0;
-        while (total_length < extra_data_size) {
-          size_t size = *(++current_pos);
-          total_length += 1 + size;
-          if (total_length > 0x80000000) {
-            LOG(ERROR) << "Vorbis header size too large";
-            return false;
-          }
-          header_length[i] += size;
-          if (size < 0xFF)
-            break;
-        }
-        if (total_length >= extra_data_size) {
-          LOG(ERROR) << "Invalid vorbis header size in the extra data";
-          return false;
-        }
-      }
-      current_pos++;
-      // The first header is identification header.
-      ScopedJavaLocalRef<jbyteArray> first_header =
-          base::android::ToJavaByteArray(env, current_pos, header_length[0]);
-      Java_MediaCodecBridge_setCodecSpecificData(
-          env, j_format, 0, first_header.obj());
-      // The last header is codec header.
-      ScopedJavaLocalRef<jbyteArray> last_header =
-          base::android::ToJavaByteArray(
-              env, extra_data + total_length, extra_data_size - total_length);
-      Java_MediaCodecBridge_setCodecSpecificData(
-          env, j_format, 1, last_header.obj());
-      break;
-    }
-    case kCodecAAC: {
-      media::BitReader reader(extra_data, extra_data_size);
-
-      // The following code is copied from aac.cc
-      // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
-      uint8 profile = 0;
-      uint8 frequency_index = 0;
-      uint8 channel_config = 0;
-      RETURN_ON_ERROR(reader.ReadBits(5, &profile));
-      RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
-
-      if (0xf == frequency_index)
-        RETURN_ON_ERROR(reader.SkipBits(24));
-      RETURN_ON_ERROR(reader.ReadBits(4, &channel_config));
-
-      if (profile == 5 || profile == 29) {
-        // Read extension config.
-        RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
-        if (frequency_index == 0xf)
-          RETURN_ON_ERROR(reader.SkipBits(24));
-        RETURN_ON_ERROR(reader.ReadBits(5, &profile));
-      }
-
-      if (profile < 1 || profile > 4 || frequency_index == 0xf ||
-          channel_config > 7) {
-        LOG(ERROR) << "Invalid AAC header";
-        return false;
-      }
-      const size_t kCsdLength = 2;
-      uint8 csd[kCsdLength];
-      csd[0] = profile << 3 | frequency_index >> 1;
-      csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3;
-      ScopedJavaLocalRef<jbyteArray> byte_array =
-          base::android::ToJavaByteArray(env, csd, kCsdLength);
-      Java_MediaCodecBridge_setCodecSpecificData(
-          env, j_format, 0, byte_array.obj());
-
-      // TODO(qinmin): pass an extra variable to this function to determine
-      // whether we need to call this.
-      Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format);
-      break;
-    }
-    case kCodecOpus: {
-      if (!extra_data || extra_data_size == 0 ||
-          codec_delay_ns < 0 || seek_preroll_ns < 0) {
-        LOG(ERROR) << "Invalid Opus Header";
-        return false;
-      }
-
-      // csd0 - Opus Header
-      ScopedJavaLocalRef<jbyteArray> csd0 =
-          base::android::ToJavaByteArray(env, extra_data, extra_data_size);
-      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj());
-
-      // csd1 - Codec Delay
-      ScopedJavaLocalRef<jbyteArray> csd1 =
-          base::android::ToJavaByteArray(
-              env, reinterpret_cast<const uint8*>(&codec_delay_ns),
-              sizeof(int64_t));
-      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj());
-
-      // csd2 - Seek Preroll
-      ScopedJavaLocalRef<jbyteArray> csd2 =
-          base::android::ToJavaByteArray(
-              env, reinterpret_cast<const uint8*>(&seek_preroll_ns),
-              sizeof(int64_t));
-      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj());
-      break;
-    }
-    default:
-      LOG(ERROR) << "Invalid header encountered for codec: "
-                 << AudioCodecToAndroidMimeType(codec);
-      return false;
-  }
-  return true;
-}
-
-int64 AudioCodecBridge::PlayOutputBuffer(int index,
-                                         size_t size,
-                                         size_t offset,
-                                         bool postpone) {
-  DCHECK_LE(0, index);
-  int numBytes = base::checked_cast<int>(size);
-
-  void* buffer = nullptr;
-  int capacity = GetOutputBufferAddress(index, offset, &buffer);
-  numBytes = std::min(capacity, numBytes);
-  CHECK_GE(numBytes, 0);
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray(
-          env, static_cast<uint8*>(buffer), numBytes);
-  return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(),
-                                                byte_array.obj(), postpone);
-}
-
-void AudioCodecBridge::SetVolume(double volume) {
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_setVolume(env, media_codec(), volume);
-}
-
-// static
-AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) {
-  if (!MediaCodecBridge::IsAvailable())
-    return NULL;
-
-  const std::string mime = AudioCodecToAndroidMimeType(codec);
-  return mime.empty() ? NULL : new AudioCodecBridge(mime);
-}
-
-// static
-bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) {
-  return MediaCodecBridge::IsKnownUnaccelerated(
-      AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER);
-}
-
-// static
-bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec,
-                                            MediaCodecDirection direction) {
-  return MediaCodecBridge::IsKnownUnaccelerated(
-      VideoCodecToAndroidMimeType(codec), direction);
-}
-
-// static
-VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec,
-                                                  bool is_secure,
-                                                  const gfx::Size& size,
-                                                  jobject surface,
-                                                  jobject media_crypto) {
-  if (!MediaCodecBridge::IsAvailable())
-    return NULL;
-
-  const std::string mime = VideoCodecToAndroidMimeType(codec);
-  if (mime.empty())
-    return NULL;
-
-  scoped_ptr<VideoCodecBridge> bridge(
-      new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER));
-  if (!bridge->media_codec())
-    return NULL;
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
-  ScopedJavaLocalRef<jobject> j_format(
-      Java_MediaCodecBridge_createVideoDecoderFormat(
-          env, j_mime.obj(), size.width(), size.height()));
-  DCHECK(!j_format.is_null());
-  if (!Java_MediaCodecBridge_configureVideo(env,
-                                            bridge->media_codec(),
-                                            j_format.obj(),
-                                            surface,
-                                            media_crypto,
-                                            0)) {
-    return NULL;
-  }
-
-  return bridge->StartInternal() ? bridge.release() : NULL;
-}
-
-// static
-VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec,
-                                                  const gfx::Size& size,
-                                                  int bit_rate,
-                                                  int frame_rate,
-                                                  int i_frame_interval,
-                                                  int color_format) {
-  if (!MediaCodecBridge::IsAvailable())
-    return NULL;
-
-  const std::string mime = VideoCodecToAndroidMimeType(codec);
-  if (mime.empty())
-    return NULL;
-
-  scoped_ptr<VideoCodecBridge> bridge(
-      new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER));
-  if (!bridge->media_codec())
-    return NULL;
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
-  ScopedJavaLocalRef<jobject> j_format(
-      Java_MediaCodecBridge_createVideoEncoderFormat(env,
-                                                     j_mime.obj(),
-                                                     size.width(),
-                                                     size.height(),
-                                                     bit_rate,
-                                                     frame_rate,
-                                                     i_frame_interval,
-                                                     color_format));
-  DCHECK(!j_format.is_null());
-  if (!Java_MediaCodecBridge_configureVideo(env,
-                                            bridge->media_codec(),
-                                            j_format.obj(),
-                                            NULL,
-                                            NULL,
-                                            kConfigureFlagEncode)) {
-    return NULL;
-  }
-
-  return bridge->StartInternal() ? bridge.release() : NULL;
-}
-
-VideoCodecBridge::VideoCodecBridge(const std::string& mime,
-                                   bool is_secure,
-                                   MediaCodecDirection direction)
-    : MediaCodecBridge(mime, is_secure, direction),
-      adaptive_playback_supported_for_testing_(-1) {}
-
-void VideoCodecBridge::SetVideoBitrate(int bps) {
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps);
-}
-
-void VideoCodecBridge::RequestKeyFrameSoon() {
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec());
-}
-
-bool VideoCodecBridge::IsAdaptivePlaybackSupported(int width, int height) {
-  if (adaptive_playback_supported_for_testing_ == 0)
-    return false;
-  else if (adaptive_playback_supported_for_testing_ > 0)
-    return true;
-  JNIEnv* env = AttachCurrentThread();
-  return Java_MediaCodecBridge_isAdaptivePlaybackSupported(
-      env, media_codec(), width, height);
-}
-
-bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) {
-  return RegisterNativesImpl(env);
-}
-
 }  // namespace media
diff --git a/media/base/android/media_codec_bridge.h b/media/base/android/media_codec_bridge.h
index 73f070d..0719448f3 100644
--- a/media/base/android/media_codec_bridge.h
+++ b/media/base/android/media_codec_bridge.h
@@ -5,15 +5,14 @@
 #ifndef MEDIA_BASE_ANDROID_MEDIA_CODEC_BRIDGE_H_
 #define MEDIA_BASE_ANDROID_MEDIA_CODEC_BRIDGE_H_
 
-#include <jni.h>
 #include <set>
 #include <string>
+#include <vector>
 
-#include "base/android/scoped_java_ref.h"
+#include "base/compiler_specific.h"
 #include "base/time/time.h"
-#include "media/base/audio_decoder_config.h"
-#include "media/base/video_decoder_config.h"
-#include "ui/gfx/geometry/size.h"
+#include "media/base/android/media_codec_util.h"
+#include "media/base/media_export.h"
 
 namespace media {
 
@@ -34,59 +33,12 @@
   MEDIA_CODEC_ERROR
 };
 
-// Codec direction.  Keep this in sync with MediaCodecBridge.java.
-enum MediaCodecDirection {
-  MEDIA_CODEC_DECODER,
-  MEDIA_CODEC_ENCODER,
-};
-
-// This class serves as a bridge for native code to call java functions inside
-// Android MediaCodec class. For more information on Android MediaCodec, check
+// Interface for wrapping different Android MediaCodec implementations. For
+// more information on Android MediaCodec, check
 // http://developer.android.com/reference/android/media/MediaCodec.html
 // Note: MediaCodec is only available on JB and greater.
-// Use AudioCodecBridge or VideoCodecBridge to create an instance of this
-// object.
-//
-// TODO(fischman,xhwang): replace this (and the enums that go with it) with
-// chromium's JNI auto-generation hotness.
 class MEDIA_EXPORT MediaCodecBridge {
  public:
-  // Returns true if MediaCodec is available on the device.
-  // All other static methods check IsAvailable() internally. There's no need
-  // to check IsAvailable() explicitly before calling them.
-  static bool IsAvailable();
-
-  // Returns true if MediaCodec.setParameters() is available on the device.
-  static bool SupportsSetParameters();
-
-  // Returns true if MediaCodec.getName() is available on the device.
-  static bool SupportsGetName();
-
-  // Returns whether MediaCodecBridge has a decoder that |is_secure| and can
-  // decode |codec| type.
-  static bool CanDecode(const std::string& codec, bool is_secure);
-
-  // Represents supported codecs on android.
-  // TODO(qinmin): Currently the codecs string only contains one codec. Do we
-  // need to support codecs separated by comma. (e.g. "vp8" -> "vp8, vp8.0")?
-  struct CodecsInfo {
-    std::string codecs;  // E.g. "vp8" or "avc1".
-    std::string name;    // E.g. "OMX.google.vp8.decoder".
-    MediaCodecDirection direction;
-  };
-
-  // Get a list of supported codecs.
-  static std::vector<CodecsInfo> GetCodecsInfo();
-
-  // Get default codec name for |mime_type|.
-  static std::string GetDefaultCodecName(const std::string& mime_type,
-                                         MediaCodecDirection direction);
-
-  // Get a list of encoder supported color formats for |mime_type|.
-  // The mapping of color format name and its value refers to
-  // MediaCodecInfo.CodecCapabilities.
-  static std::set<int> GetEncoderColorFormats(const std::string& mime_type);
-
   virtual ~MediaCodecBridge();
 
   // Resets both input and output, all indices previously returned in calls to
@@ -95,31 +47,36 @@
   // words, there will be no outputs until new input is provided.
   // Returns MEDIA_CODEC_ERROR if an unexpected error happens, or Media_CODEC_OK
   // otherwise.
-  MediaCodecStatus Reset();
+  virtual MediaCodecStatus Reset() = 0;
+
+  // Calls start() against the media codec instance. Returns whether media
+  // codec was successfully started.
+  virtual bool Start() = 0;
 
   // Finishes the decode/encode session. The instance remains active
   // and ready to be StartAudio/Video()ed again. HOWEVER, due to the buggy
   // vendor's implementation , b/8125974, Stop() -> StartAudio/Video() may not
   // work on some devices. For reliability, Stop() -> delete and recreate new
   // instance -> StartAudio/Video() is recommended.
-  void Stop();
+  virtual void Stop() = 0;
 
   // Used for getting output format. This is valid after DequeueInputBuffer()
   // returns a format change by returning INFO_OUTPUT_FORMAT_CHANGED
-  void GetOutputFormat(int* width, int* height);
+  virtual void GetOutputFormat(int* width, int* height) = 0;
 
   // Used for checking for new sampling rate after DequeueInputBuffer() returns
   // INFO_OUTPUT_FORMAT_CHANGED
-  int GetOutputSamplingRate();
+  virtual int GetOutputSamplingRate() = 0;
 
   // Submits a byte array to the given input buffer. Call this after getting an
-  // available buffer from DequeueInputBuffer().  If |data| is NULL, assume the
+  // available buffer from DequeueInputBuffer(). If |data| is NULL, assume the
   // input buffer has already been populated (but still obey |size|).
   // |data_size| must be less than kint32max (because Java).
-  MediaCodecStatus QueueInputBuffer(int index,
-                                    const uint8* data,
-                                    size_t data_size,
-                                    const base::TimeDelta& presentation_time);
+  virtual MediaCodecStatus QueueInputBuffer(
+      int index,
+      const uint8* data,
+      size_t data_size,
+      const base::TimeDelta& presentation_time) = 0;
 
   // Similar to the above call, but submits a buffer that is encrypted.  Note:
   // NULL |subsamples| indicates the whole buffer is encrypted.  If |data| is
@@ -138,20 +95,18 @@
   // and MediaCodecPlayer.
   // TODO(timav): remove this method and keep only the one above after we
   // switch to the Spitzer pipeline.
-  MediaCodecStatus QueueSecureInputBuffer(
+  virtual MediaCodecStatus QueueSecureInputBuffer(
       int index,
       const uint8* data,
       size_t data_size,
-      const uint8* key_id,
-      int key_id_size,
-      const uint8* iv,
-      int iv_size,
+      const std::vector<char>& key_id,
+      const std::vector<char>& iv,
       const SubsampleEntry* subsamples,
       int subsamples_size,
-      const base::TimeDelta& presentation_time);
+      const base::TimeDelta& presentation_time) = 0;
 
   // Submits an empty buffer with a EOS (END OF STREAM) flag.
-  void QueueEOS(int input_buffer_index);
+  virtual void QueueEOS(int input_buffer_index) = 0;
 
   // Returns:
   // MEDIA_CODEC_OK if an input buffer is ready to be filled with valid data,
@@ -159,8 +114,8 @@
   // MEDIA_CODEC_ERROR if unexpected error happens.
   // Note: Never use infinite timeout as this would block the decoder thread and
   // prevent the decoder job from being released.
-  MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout,
-                                      int* index);
+  virtual MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout,
+                                              int* index) = 0;
 
   // Dequeues an output buffer, block at most timeout_us microseconds.
   // Returns the status of this operation. If OK is returned, the output
@@ -171,159 +126,51 @@
   // prevent the decoder job from being released.
   // TODO(xhwang): Can we drop |end_of_stream| and return
   // MEDIA_CODEC_OUTPUT_END_OF_STREAM?
-  MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout,
-                                       int* index,
-                                       size_t* offset,
-                                       size_t* size,
-                                       base::TimeDelta* presentation_time,
-                                       bool* end_of_stream,
-                                       bool* key_frame);
+  virtual MediaCodecStatus DequeueOutputBuffer(
+      const base::TimeDelta& timeout,
+      int* index,
+      size_t* offset,
+      size_t* size,
+      base::TimeDelta* presentation_time,
+      bool* end_of_stream,
+      bool* key_frame) = 0;
 
   // Returns the buffer to the codec. If you previously specified a surface when
   // configuring this video decoder you can optionally render the buffer.
-  void ReleaseOutputBuffer(int index, bool render);
+  virtual void ReleaseOutputBuffer(int index, bool render) = 0;
 
   // Returns the number of output buffers used by the codec.
   // TODO(qinmin): this call is deprecated in Lollipop.
-  int GetOutputBuffersCount();
+  virtual int GetOutputBuffersCount();
 
   // Returns the capacity of each output buffer used by the codec.
   // TODO(qinmin): this call is deprecated in Lollipop.
-  size_t GetOutputBuffersCapacity();
+  virtual size_t GetOutputBuffersCapacity();
 
   // Returns an input buffer's base pointer and capacity.
-  void GetInputBuffer(int input_buffer_index, uint8** data, size_t* capacity);
+  virtual void GetInputBuffer(int input_buffer_index,
+                              uint8** data,
+                              size_t* capacity) = 0;
 
   // Copy |dst_size| bytes from output buffer |index|'s |offset| onwards into
   // |*dst|.
-  bool CopyFromOutputBuffer(int index, size_t offset, void* dst, int dst_size);
-
-  static bool RegisterMediaCodecBridge(JNIEnv* env);
+  virtual bool CopyFromOutputBuffer(int index,
+                                    size_t offset,
+                                    void* dst,
+                                    int dst_size) = 0;
 
  protected:
-  // Returns true if |mime_type| is known to be unaccelerated (i.e. backed by a
-  // software codec instead of a hardware one).
-  static bool IsKnownUnaccelerated(const std::string& mime_type,
-                                   MediaCodecDirection direction);
+  MediaCodecBridge();
 
-  MediaCodecBridge(const std::string& mime,
-                   bool is_secure,
-                   MediaCodecDirection direction);
-
-  // Calls start() against the media codec instance. Used in StartXXX() after
-  // configuring media codec. Returns whether media codec was successfully
-  // started.
-  bool StartInternal() WARN_UNUSED_RESULT;
-
-  // Called to get the buffer address given the output buffer index and offset.
-  // This function returns the size of the output and |addr| is the pointer to
-  // the address to read.
-  int GetOutputBufferAddress(int index, size_t offset, void** addr);
-
-  jobject media_codec() { return j_media_codec_.obj(); }
-  MediaCodecDirection direction_;
-
- private:
   // Fills a particular input buffer; returns false if |data_size| exceeds the
   // input buffer's capacity (and doesn't touch the input buffer in that case).
   bool FillInputBuffer(int index,
                        const uint8* data,
                        size_t data_size) WARN_UNUSED_RESULT;
 
-  // Java MediaCodec instance.
-  base::android::ScopedJavaGlobalRef<jobject> j_media_codec_;
-
   DISALLOW_COPY_AND_ASSIGN(MediaCodecBridge);
 };
 
-class AudioCodecBridge : public MediaCodecBridge {
- public:
-  // Returns an AudioCodecBridge instance if |codec| is supported, or a NULL
-  // pointer otherwise.
-  static AudioCodecBridge* Create(const AudioCodec& codec);
-
-  // See MediaCodecBridge::IsKnownUnaccelerated().
-  static bool IsKnownUnaccelerated(const AudioCodec& codec);
-
-  // Start the audio codec bridge.
-  bool Start(const AudioCodec& codec, int sample_rate, int channel_count,
-             const uint8* extra_data, size_t extra_data_size,
-             int64 codec_delay_ns, int64 seek_preroll_ns,
-             bool play_audio, jobject media_crypto) WARN_UNUSED_RESULT;
-
-  // Plays the output buffer right away or save for later playback if |postpone|
-  // is set to true. This call must be called after DequeueOutputBuffer() and
-  // before ReleaseOutputBuffer. The data is extracted from the output buffers
-  // using |index|, |size| and |offset|. Returns the playback head position
-  // expressed in frames.
-  // When |postpone| is set to true, the next PlayOutputBuffer() should have
-  // postpone == false, and it will play two buffers: the postponed one and
-  // the one identified by |index|.
-  int64 PlayOutputBuffer(int index,
-                         size_t size,
-                         size_t offset,
-                         bool postpone = false);
-
-  // Set the volume of the audio output.
-  void SetVolume(double volume);
-
- private:
-  explicit AudioCodecBridge(const std::string& mime);
-
-  // Configure the java MediaFormat object with the extra codec data passed in.
-  bool ConfigureMediaFormat(jobject j_format, const AudioCodec& codec,
-                            const uint8* extra_data, size_t extra_data_size,
-                            int64 codec_delay_ns, int64 seek_preroll_ns);
-};
-
-class MEDIA_EXPORT VideoCodecBridge : public MediaCodecBridge {
- public:
-  // See MediaCodecBridge::IsKnownUnaccelerated().
-  static bool IsKnownUnaccelerated(const VideoCodec& codec,
-                                   MediaCodecDirection direction);
-
-  // Create, start, and return a VideoCodecBridge decoder or NULL on failure.
-  static VideoCodecBridge* CreateDecoder(
-      const VideoCodec& codec,  // e.g. media::kCodecVP8
-      bool is_secure,
-      const gfx::Size& size,  // Output frame size.
-      jobject surface,        // Output surface, optional.
-      jobject media_crypto);  // MediaCrypto object, optional.
-
-  // Create, start, and return a VideoCodecBridge encoder or NULL on failure.
-  static VideoCodecBridge* CreateEncoder(
-      const VideoCodec& codec,  // e.g. media::kCodecVP8
-      const gfx::Size& size,    // input frame size
-      int bit_rate,             // bits/second
-      int frame_rate,           // frames/second
-      int i_frame_interval,     // count
-      int color_format);        // MediaCodecInfo.CodecCapabilities.
-
-  void SetVideoBitrate(int bps);
-  void RequestKeyFrameSoon();
-
-  // Returns whether adaptive playback is supported for this object given
-  // the new size.
-  bool IsAdaptivePlaybackSupported(int width, int height);
-
-  // Test-only method to set the return value of IsAdaptivePlaybackSupported().
-  // Without this function, the return value of that function will be device
-  // dependent. If |adaptive_playback_supported| is equal to 0, the return value
-  // will be false. If |adaptive_playback_supported| is larger than 0, the
-  // return value will be true.
-  void set_adaptive_playback_supported_for_testing(
-      int adaptive_playback_supported) {
-    adaptive_playback_supported_for_testing_ = adaptive_playback_supported;
-  }
-
- private:
-  VideoCodecBridge(const std::string& mime,
-                   bool is_secure,
-                   MediaCodecDirection direction);
-
-  int adaptive_playback_supported_for_testing_;
-};
-
 }  // namespace media
 
 #endif  // MEDIA_BASE_ANDROID_MEDIA_CODEC_BRIDGE_H_
diff --git a/media/base/android/media_codec_bridge_unittest.cc b/media/base/android/media_codec_bridge_unittest.cc
deleted file mode 100644
index f1c04711..0000000
--- a/media/base/android/media_codec_bridge_unittest.cc
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "media/base/android/media_codec_bridge.h"
-#include "media/base/decoder_buffer.h"
-#include "media/base/test_data_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace {
-
-// The first frame of
-// http://www.html5rocks.com/en/tutorials/audio/quick/test.mp3
-unsigned char test_mp3[] = {
-  0xff, 0xfb, 0xd2, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x05, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x7e, 0x40,
-  0xc0, 0x19, 0x4a, 0x80, 0x0d, 0x60, 0x48, 0x1b, 0x40, 0xf7, 0xbd, 0xb9,
-  0xd9, 0x40, 0x6f, 0x82, 0x01, 0x8b, 0x17, 0xa0, 0x80, 0xc5, 0x01, 0xad,
-  0x9a, 0xd3, 0x00, 0x12, 0xc0, 0x72, 0x93, 0x67, 0xd0, 0x03, 0x6f, 0xa4,
-  0xc0, 0xc3, 0x23, 0xee, 0x9b, 0xc0, 0xcc, 0x02, 0xa0, 0xa1, 0x30, 0x0c,
-  0x52, 0x2d, 0xfd, 0x6e, 0x08, 0x83, 0x60, 0x40, 0x46, 0x06, 0x4b, 0x20,
-  0x82, 0x82, 0x7f, 0xd4, 0x81, 0xe7, 0x00, 0x64, 0x20, 0x18, 0xec, 0xc2,
-  0x06, 0x57, 0x0f, 0x81, 0x93, 0x0b, 0x00, 0x66, 0xe3, 0xb7, 0xe8, 0x32,
-  0x6e, 0xf0, 0x32, 0xb0, 0x58, 0x0c, 0x7c, 0x3a, 0x03, 0x22, 0x14, 0x80,
-  0xc9, 0x01, 0x80, 0x30, 0x20, 0x14, 0x0c, 0x96, 0x73, 0xfe, 0x9f, 0x6c,
-  0x0c, 0xd2, 0x25, 0x0f, 0xdc, 0x0c, 0x32, 0x43, 0x03, 0x27, 0x87, 0xc0,
-  0xc2, 0xc0, 0x20, 0xfc, 0x42, 0xc5, 0xff, 0xff, 0xd4, 0x80, 0x01, 0x01,
-  0x80, 0xc3, 0x81, 0x01, 0x95, 0x03, 0x28, 0x82, 0xc0, 0xc3, 0x01, 0xa1,
-  0x06, 0x81, 0x87, 0xc2, 0x40, 0x64, 0xc1, 0xf0, 0x12, 0x02, 0xff, 0xf6,
-  0x5b, 0x9f, 0x44, 0xdc, 0xdd, 0x0b, 0x38, 0x59, 0xe0, 0x31, 0x71, 0x60,
-  0x0c, 0xb4, 0x22, 0x03, 0x3b, 0x96, 0x40, 0xc8, 0x63, 0x90, 0x0a, 0x23,
-  0x81, 0x9e, 0x4c, 0x20, 0x65, 0xb3, 0x18, 0x19, 0x6c, 0x42, 0x06, 0x36,
-  0x1d, 0x01, 0x90, 0x87, 0xdf, 0xff, 0xd0, 0x65, 0xa6, 0xea, 0x66, 0xfd,
-  0x40, 0x0c, 0x48, 0x03, 0x1a, 0x09, 0x01, 0x21, 0x98, 0x19, 0x2c, 0x36,
-  0x06, 0x43, 0x21, 0x81, 0x92, 0xca, 0x60, 0x64, 0x70, 0xb8, 0x19, 0x20,
-  0x6c, 0x02, 0x83, 0x80, 0xcb, 0x60, 0x65, 0x32, 0x28, 0x18, 0x64, 0x24,
-  0x06, 0x3a, 0x0c, 0x00, 0xe1, 0x00, 0x18, 0xd0, 0x35, 0xff, 0xff, 0xff,
-  0xe8, 0x32, 0xef, 0xb2, 0x90, 0x65, 0xbb, 0xdd, 0x94, 0x82, 0x0b, 0x4c,
-  0xfa, 0x25, 0xf3, 0x74, 0x13, 0x0f, 0xf8, 0x19, 0x28, 0x84, 0x06, 0x36,
-  0x11, 0x01, 0x20, 0x80, 0x18, 0xb4, 0x52, 0x0e, 0x15, 0x00, 0x30, 0x50,
-  0x0c, 0x84, 0x32, 0x03, 0x11, 0x04, 0x03, 0x48, 0x04, 0x00, 0x00, 0x31,
-  0x21, 0x00, 0x0c, 0x84, 0x18, 0x03, 0x07, 0x85, 0x40, 0xc6, 0xa5, 0x70,
-  0x32, 0xb8, 0x7c, 0x0c, 0x54, 0x04, 0x00, 0xd0, 0x08, 0x59, 0x58, 0x18,
-  0x20, 0x14, 0x06, 0x30, 0x30, 0x01, 0x9b, 0x86, 0x00, 0x6b, 0x54, 0xa8,
-  0x19, 0x8c, 0x2a, 0x06, 0x16, 0x09, 0x01, 0xa0, 0xd0, 0xa0, 0x69, 0x74,
-  0xb8, 0x19, 0xc4, 0x4a, 0xa3, 0xda, 0x9d, 0x1e, 0x4f, 0x05, 0xc0, 0x5b,
-  0x0b, 0x03, 0xc2, 0x76, 0xa3, 0x4f, 0xb9, 0x16, 0xc2, 0x70, 0x41, 0x07,
-  0xa0, 0x84, 0x16, 0x38, 0x4a, 0xc8, 0xaf, 0xee, 0x7f, 0x93, 0xb5, 0x5c,
-  0x39, 0x1e, 0x29, 0xd9, 0x8c, 0x80, 0xb5, 0x80, 0xe6, 0x85, 0xb2, 0x99,
-  0x68, 0x85, 0x46, 0x91, 0x60, 0xdb, 0x06, 0xfa, 0x38, 0x7a, 0xc7, 0xac,
-  0x85, 0xa8, 0xd3, 0xe6, 0x99, 0x3b, 0x66, 0x43, 0x23, 0x1f, 0x84, 0xe1,
-  0x65, 0x5e, 0xbc, 0x84, 0x18, 0x62, 0xe6, 0x42, 0x0b, 0x82, 0xe4, 0xd3,
-  0x42, 0xd2, 0x05, 0x81, 0x4e, 0xe4, 0x9f, 0x8c, 0xc8, 0x7f, 0xa3, 0xe0,
-  0x8d, 0xf1, 0x0f, 0x38, 0xe5, 0x3f, 0xc4, 0x2c, 0x24, 0x65, 0x8d, 0xb9,
-  0x58, 0xac, 0x39, 0x0e, 0x37, 0x99, 0x2e, 0x85, 0xe0, 0xb7, 0x98, 0x41,
-  0x20, 0x38, 0x1b, 0x95, 0x07, 0xfa, 0xa8, 0x9c, 0x21, 0x0f, 0x13, 0x8c,
-  0xa5, 0xc1, 0x76, 0xae, 0x0b, 0xc1, 0x30, 0x27, 0x08, 0xc1, 0xf6, 0x4d,
-  0xce, 0xb4, 0x41, 0x38, 0x1e, 0x82, 0x10, 0x74, 0x45, 0x91, 0x90, 0xff,
-  0x41, 0x8b, 0x62, 0x1a, 0x71, 0xb6, 0x45, 0x63, 0x8c, 0xce, 0xb8, 0x54,
-  0x1b, 0xe8, 0x5d, 0x9e, 0x35, 0x9d, 0x6c, 0xac, 0xe8, 0x83, 0xa1, 0xe9,
-  0x3f, 0x13, 0x74, 0x11, 0x04, 0x10, 0xf1, 0x37, 0x38, 0xc6, 0x00, 0x60,
-  0x27, 0x48, 0x38, 0x85, 0x92, 0x76, 0xb7, 0xf3, 0xa7, 0x1c, 0x4b, 0xf9,
-  0x3b, 0x5a, 0x88, 0xac, 0x60, 0x1b, 0x85, 0x81, 0x16, 0xab, 0x44, 0x17,
-  0x08, 0x2e, 0x0f, 0xd4, 0xe2, 0xde, 0x49, 0xc9, 0xe1, 0xc0, 0xc0, 0xa0,
-  0x7e, 0x73, 0xa1, 0x67, 0xf8, 0xf5, 0x9f, 0xc4, 0x21, 0x50, 0x4f, 0x05,
-  0x2c, 0xfc, 0x5c, 0xaa, 0x85, 0xb0, 0xfa, 0x67, 0x80, 0x7e, 0x0f, 0xfd,
-  0x92, 0x30, 0xd5, 0xa0, 0xd4, 0x05, 0xdd, 0x06, 0x68, 0x1d, 0x6e, 0x4e,
-  0x8b, 0x79, 0xd6, 0xfc, 0xff, 0x2e, 0x6e, 0x7c, 0xba, 0x03, 0x90, 0xd4,
-  0x25, 0x65, 0x8e, 0xe7, 0x3a, 0xd1, 0xd6, 0xdc, 0xf0, 0xbe, 0x12, 0xc4,
-  0x31, 0x08, 0x16, 0x70, 0x31, 0x85, 0x61, 0x38, 0x27, 0x0a, 0x91, 0x5f,
-  0x03, 0x38, 0xeb, 0x37, 0x13, 0x48, 0x41, 0xbe, 0x7f, 0x04, 0x70, 0x62,
-  0x2b, 0x15, 0x91, 0x67, 0x63, 0x4f, 0xad, 0xa7, 0x1d, 0x3f, 0x44, 0x17,
-  0x02, 0x08, 0x0d, 0xf2, 0xfc, 0x03, 0xa0, 0x74, 0x21, 0x8b, 0x07, 0x3a,
-  0x8d, 0x0f, 0x54, 0x58, 0x94, 0x12, 0xc5, 0x62, 0x18, 0xb9, 0x42, 0xf0,
-  0x6c, 0x73, 0xa0, 0x92, 0xad, 0x27, 0x1c, 0x20, 0x0f, 0xc1, 0xca, 0x44,
-  0x87, 0x47, 0xc5, 0x43, 0x23, 0x01, 0xda, 0x23, 0xe2, 0x89, 0x38, 0x9f,
-  0x1f, 0x8d, 0x8c, 0xc6, 0x95, 0xa3, 0x34, 0x21, 0x21, 0x2d, 0x49, 0xea,
-  0x4b, 0x05, 0x85, 0xf5, 0x58, 0x25, 0x13, 0xcd, 0x51, 0x19, 0x1a, 0x88,
-  0xa6, 0x83, 0xd6, 0xd0, 0xbc, 0x25, 0x19, 0x1c, 0x92, 0x12, 0x44, 0x5d,
-  0x1c, 0x04, 0xf1, 0x99, 0xdf, 0x92, 0x8e, 0x09, 0x85, 0xf3, 0x88, 0x82,
-  0x4c, 0x22, 0x17, 0xc5, 0x25, 0x23, 0xed, 0x78, 0xf5, 0x41, 0xd1, 0xe9,
-  0x8a, 0xb3, 0x52, 0xd1, 0x3d, 0x79, 0x81, 0x4d, 0x31, 0x24, 0xf9, 0x38,
-  0x96, 0xbc, 0xf4, 0x8c, 0x25, 0xe9, 0xf2, 0x73, 0x94, 0x85, 0xc2, 0x61,
-  0x6a, 0x34, 0x68, 0x65, 0x78, 0x87, 0xa6, 0x4f
-};
-
-}  // namespace
-
-namespace media {
-
-// Helper macro to skip the test if MediaCodecBridge isn't available.
-#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
-  do {                                                            \
-    if (!MediaCodecBridge::IsAvailable()) {                       \
-      VLOG(0) << "Could not run test - not supported on device."; \
-      return;                                                     \
-    }                                                             \
-  } while (0)
-
-static const int kPresentationTimeBase = 100;
-
-static inline const base::TimeDelta InfiniteTimeOut() {
-  return base::TimeDelta::FromMicroseconds(-1);
-}
-
-void DecodeMediaFrame(
-    VideoCodecBridge* media_codec, const uint8* data, size_t data_size,
-    const base::TimeDelta input_presentation_timestamp,
-    const base::TimeDelta initial_timestamp_lower_bound) {
-  base::TimeDelta input_pts = input_presentation_timestamp;
-  base::TimeDelta timestamp = initial_timestamp_lower_bound;
-  base::TimeDelta new_timestamp;
-  for (int i = 0; i < 10; ++i) {
-    int input_buf_index = -1;
-    MediaCodecStatus status =
-        media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
-    ASSERT_EQ(MEDIA_CODEC_OK, status);
-
-    media_codec->QueueInputBuffer(
-        input_buf_index, data, data_size, input_presentation_timestamp);
-
-    size_t unused_offset = 0;
-    size_t size = 0;
-    bool eos = false;
-    int output_buf_index = -1;
-    status = media_codec->DequeueOutputBuffer(InfiniteTimeOut(),
-                                              &output_buf_index,
-                                              &unused_offset,
-                                              &size,
-                                              &new_timestamp,
-                                              &eos,
-                                              NULL);
-
-    if (status == MEDIA_CODEC_OK && output_buf_index > 0) {
-      media_codec->ReleaseOutputBuffer(output_buf_index, false);
-    }
-    // Output time stamp should not be smaller than old timestamp.
-    ASSERT_TRUE(new_timestamp >= timestamp);
-    input_pts += base::TimeDelta::FromMicroseconds(33000);
-    timestamp = new_timestamp;
-  }
-}
-
-TEST(MediaCodecBridgeTest, Initialize) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<media::MediaCodecBridge> media_codec;
-  media_codec.reset(VideoCodecBridge::CreateDecoder(
-      kCodecH264, false, gfx::Size(640, 480), NULL, NULL));
-}
-
-TEST(MediaCodecBridgeTest, DoNormal) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<media::AudioCodecBridge> media_codec;
-  media_codec.reset(AudioCodecBridge::Create(kCodecMP3));
-
-  ASSERT_TRUE(media_codec->Start(
-      kCodecMP3, 44100, 2, NULL, 0, 0, 0, false, NULL));
-
-  int input_buf_index = -1;
-  MediaCodecStatus status =
-      media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
-  ASSERT_EQ(MEDIA_CODEC_OK, status);
-  ASSERT_GE(input_buf_index, 0);
-
-  int64 input_pts = kPresentationTimeBase;
-  media_codec->QueueInputBuffer(input_buf_index,
-                                test_mp3,
-                                sizeof(test_mp3),
-                                base::TimeDelta::FromMicroseconds(++input_pts));
-
-  status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
-  media_codec->QueueInputBuffer(
-      input_buf_index, test_mp3, sizeof(test_mp3),
-      base::TimeDelta::FromMicroseconds(++input_pts));
-
-  status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
-  media_codec->QueueEOS(input_buf_index);
-
-  input_pts = kPresentationTimeBase;
-  bool eos = false;
-  while (!eos) {
-    size_t unused_offset = 0;
-    size_t size = 0;
-    base::TimeDelta timestamp;
-    int output_buf_index = -1;
-    status = media_codec->DequeueOutputBuffer(InfiniteTimeOut(),
-                                              &output_buf_index,
-                                              &unused_offset,
-                                              &size,
-                                              &timestamp,
-                                              &eos,
-                                              NULL);
-    switch (status) {
-      case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
-        FAIL();
-        return;
-
-      case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
-        continue;
-
-      case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
-        continue;
-
-      default:
-        break;
-    }
-    ASSERT_GE(output_buf_index, 0);
-    EXPECT_LE(1u, size);
-    if (!eos)
-      EXPECT_EQ(++input_pts, timestamp.InMicroseconds());
-    ASSERT_LE(input_pts, kPresentationTimeBase + 2);
-  }
-  ASSERT_EQ(input_pts, kPresentationTimeBase + 2);
-}
-
-TEST(MediaCodecBridgeTest, InvalidVorbisHeader) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<media::AudioCodecBridge> media_codec;
-  media_codec.reset(AudioCodecBridge::Create(kCodecVorbis));
-
-  // The first byte of the header is not 0x02.
-  uint8 invalid_first_byte[] = { 0x00, 0xff, 0xff, 0xff, 0xff };
-  EXPECT_FALSE(media_codec->Start(
-      kCodecVorbis, 44100, 2, invalid_first_byte, sizeof(invalid_first_byte),
-      0, 0, false, NULL));
-
-  // Size of the header does not match with the data we passed in.
-  uint8 invalid_size[] = { 0x02, 0x01, 0xff, 0x01, 0xff };
-  EXPECT_FALSE(media_codec->Start(
-      kCodecVorbis, 44100, 2, invalid_size, sizeof(invalid_size),
-      0, 0, false, NULL));
-
-  // Size of the header is too large.
-  size_t large_size = 8 * 1024 * 1024 + 2;
-  uint8* very_large_header = new uint8[large_size];
-  very_large_header[0] = 0x02;
-  for (size_t i = 1; i < large_size - 1; ++i)
-    very_large_header[i] = 0xff;
-  very_large_header[large_size - 1] = 0xfe;
-  EXPECT_FALSE(media_codec->Start(
-      kCodecVorbis, 44100, 2, very_large_header, 0x80000000,
-      0, 0, false, NULL));
-  delete[] very_large_header;
-}
-
-TEST(MediaCodecBridgeTest, InvalidOpusHeader) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<media::AudioCodecBridge> media_codec;
-  media_codec.reset(AudioCodecBridge::Create(kCodecOpus));
-  uint8 dummy_extra_data[] = { 0, 0 };
-
-  // Extra Data is NULL.
-  EXPECT_FALSE(media_codec->Start(
-      kCodecOpus, 48000, 2, NULL, 0, -1, 0, false, NULL));
-
-  // Codec Delay is < 0.
-  EXPECT_FALSE(media_codec->Start(
-      kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data),
-      -1, 0, false, NULL));
-
-  // Seek Preroll is < 0.
-  EXPECT_FALSE(media_codec->Start(
-      kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data),
-      0, -1, false, NULL));
-}
-
-TEST(MediaCodecBridgeTest, PresentationTimestampsDoNotDecrease) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<VideoCodecBridge> media_codec(VideoCodecBridge::CreateDecoder(
-      kCodecVP8, false, gfx::Size(320, 240), NULL, NULL));
-  EXPECT_TRUE(media_codec.get());
-  scoped_refptr<DecoderBuffer> buffer =
-      ReadTestDataFile("vp8-I-frame-320x240");
-  DecodeMediaFrame(media_codec.get(),
-                   buffer->data(),
-                   buffer->data_size(),
-                   base::TimeDelta(),
-                   base::TimeDelta());
-
-  // Simulate a seek to 10 seconds, and each chunk has 2 I-frames.
-  std::vector<uint8> chunk(buffer->data(),
-                           buffer->data() + buffer->data_size());
-  chunk.insert(chunk.end(), buffer->data(),
-               buffer->data() + buffer->data_size());
-  media_codec->Reset();
-  DecodeMediaFrame(media_codec.get(),
-                   &chunk[0],
-                   chunk.size(),
-                   base::TimeDelta::FromMicroseconds(10000000),
-                   base::TimeDelta::FromMicroseconds(9900000));
-
-  // Simulate a seek to 5 seconds.
-  media_codec->Reset();
-  DecodeMediaFrame(media_codec.get(),
-                   &chunk[0],
-                   chunk.size(),
-                   base::TimeDelta::FromMicroseconds(5000000),
-                   base::TimeDelta::FromMicroseconds(4900000));
-}
-
-TEST(MediaCodecBridgeTest, CreateUnsupportedCodec) {
-  EXPECT_EQ(NULL, AudioCodecBridge::Create(kUnknownAudioCodec));
-  EXPECT_EQ(
-      NULL,
-      VideoCodecBridge::CreateDecoder(
-          kUnknownVideoCodec, false, gfx::Size(320, 240), NULL, NULL));
-}
-
-}  // namespace media
diff --git a/media/base/android/media_codec_decoder.cc b/media/base/android/media_codec_decoder.cc
index cdbaf07..67d7188 100644
--- a/media/base/android/media_codec_decoder.cc
+++ b/media/base/android/media_codec_decoder.cc
@@ -738,9 +738,7 @@
              << " subsamples size:" << unit->subsamples.size();
 
     status = media_codec_bridge_->QueueSecureInputBuffer(
-        index, &unit->data[0], unit->data.size(),
-        reinterpret_cast<const uint8_t*>(&unit->key_id[0]), unit->key_id.size(),
-        reinterpret_cast<const uint8_t*>(&unit->iv[0]), unit->iv.size(),
+        index, &unit->data[0], unit->data.size(), unit->key_id, unit->iv,
         unit->subsamples.empty() ? nullptr : &unit->subsamples[0],
         unit->subsamples.size(), unit->timestamp);
   }
diff --git a/media/base/android/media_codec_decoder_unittest.cc b/media/base/android/media_codec_decoder_unittest.cc
index 322407b..2b14820 100644
--- a/media/base/android/media_codec_decoder_unittest.cc
+++ b/media/base/android/media_codec_decoder_unittest.cc
@@ -7,9 +7,10 @@
 #include "base/thread_task_runner_handle.h"
 #include "base/timer/timer.h"
 #include "media/base/android/media_codec_audio_decoder.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_codec_util.h"
 #include "media/base/android/media_codec_video_decoder.h"
 #include "media/base/android/media_statistics.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/android/test_data_factory.h"
 #include "media/base/android/test_statistics.h"
 #include "media/base/timestamp_constants.h"
@@ -18,15 +19,6 @@
 
 namespace media {
 
-// Helper macro to skip the test if MediaCodecBridge isn't available.
-#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
-  do {                                                            \
-    if (!MediaCodecBridge::IsAvailable()) {                       \
-      VLOG(0) << "Could not run test - not supported on device."; \
-      return;                                                     \
-    }                                                             \
-  } while (0)
-
 namespace {
 
 const base::TimeDelta kDefaultTimeout = base::TimeDelta::FromMilliseconds(200);
diff --git a/media/base/android/media_codec_player_unittest.cc b/media/base/android/media_codec_player_unittest.cc
index 46b95fcb..628de1ce 100644
--- a/media/base/android/media_codec_player_unittest.cc
+++ b/media/base/android/media_codec_player_unittest.cc
@@ -8,10 +8,11 @@
 #include "base/logging.h"
 #include "base/timer/timer.h"
 #include "media/base/android/demuxer_android.h"
-#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_codec_player.h"
+#include "media/base/android/media_codec_util.h"
 #include "media/base/android/media_player_manager.h"
 #include "media/base/android/media_task_runner.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/android/test_data_factory.h"
 #include "media/base/android/test_statistics.h"
 #include "media/base/timestamp_constants.h"
@@ -20,15 +21,6 @@
 
 namespace media {
 
-// Helper macro to skip the test if MediaCodecBridge isn't available.
-#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
-  do {                                                            \
-    if (!MediaCodecBridge::IsAvailable()) {                       \
-      VLOG(0) << "Could not run test - not supported on device."; \
-      return;                                                     \
-    }                                                             \
-  } while (0)
-
 #define RUN_ON_MEDIA_THREAD(CLASS, METHOD, ...)                               \
   do {                                                                        \
     if (!GetMediaTaskRunner()->BelongsToCurrentThread()) {                    \
diff --git a/media/base/android/media_codec_util.cc b/media/base/android/media_codec_util.cc
new file mode 100644
index 0000000..cb31ef9
--- /dev/null
+++ b/media/base/android/media_codec_util.cc
@@ -0,0 +1,225 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/android/media_codec_util.h"
+
+#include <algorithm>
+
+#include "base/android/build_info.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "jni/MediaCodecUtil_jni.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::JavaIntArrayToIntVector;
+using base::android::ScopedJavaLocalRef;
+
+namespace media {
+
+// static
+const std::string CodecTypeToAndroidMimeType(const std::string& codec) {
+  // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"?
+  if (codec == "avc1")
+    return "video/avc";
+  if (codec == "hvc1")
+    return "video/hevc";
+  if (codec == "mp4a")
+    return "audio/mp4a-latm";
+  if (codec == "vp8" || codec == "vp8.0")
+    return "video/x-vnd.on2.vp8";
+  if (codec == "vp9" || codec == "vp9.0")
+    return "video/x-vnd.on2.vp9";
+  if (codec == "vorbis")
+    return "audio/vorbis";
+  if (codec == "opus")
+    return "audio/opus";
+  return std::string();
+}
+
+// TODO(qinmin): using a map to help all the conversions in this class.
+const std::string AndroidMimeTypeToCodecType(const std::string& mime) {
+  if (mime == "video/mp4v-es")
+    return "mp4v";
+  if (mime == "video/avc")
+    return "avc1";
+  if (mime == "video/hevc")
+    return "hvc1";
+  if (mime == "video/x-vnd.on2.vp8")
+    return "vp8";
+  if (mime == "video/x-vnd.on2.vp9")
+    return "vp9";
+  if (mime == "audio/mp4a-latm")
+    return "mp4a";
+  if (mime == "audio/mpeg")
+    return "mp3";
+  if (mime == "audio/vorbis")
+    return "vorbis";
+  if (mime == "audio/opus")
+    return "opus";
+  return std::string();
+}
+
+std::string GetDefaultCodecName(const std::string& mime_type,
+                                MediaCodecDirection direction) {
+  if (!MediaCodecUtil::IsMediaCodecAvailable())
+    return std::string();
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
+  ScopedJavaLocalRef<jstring> j_codec_name =
+      Java_MediaCodecUtil_getDefaultCodecName(env, j_mime.obj(), direction);
+  return ConvertJavaStringToUTF8(env, j_codec_name.obj());
+}
+
+bool SupportsGetName() {
+  // MediaCodec.getName() is only available on JB MR2 and greater.
+  return base::android::BuildInfo::GetInstance()->sdk_int() >= 18;
+}
+
+// Represents supported codecs on android.
+// TODO(qinmin): Currently the codecs string only contains one codec. Do we
+// need to support codecs separated by comma. (e.g. "vp8" -> "vp8, vp8.0")?
+struct CodecsInfo {
+  std::string codecs;  // E.g. "vp8" or "avc1".
+  std::string name;    // E.g. "OMX.google.vp8.decoder".
+  MediaCodecDirection direction;
+};
+
+// Get a list of supported codecs.
+std::vector<CodecsInfo> GetCodecsInfo() {
+  std::vector<CodecsInfo> codecs_info;
+  if (!MediaCodecUtil::IsMediaCodecAvailable())
+    return codecs_info;
+
+  JNIEnv* env = AttachCurrentThread();
+  std::string mime_type;
+  ScopedJavaLocalRef<jobjectArray> j_codec_info_array =
+      Java_MediaCodecUtil_getCodecsInfo(env);
+  jsize len = env->GetArrayLength(j_codec_info_array.obj());
+  for (jsize i = 0; i < len; ++i) {
+    ScopedJavaLocalRef<jobject> j_info(
+        env, env->GetObjectArrayElement(j_codec_info_array.obj(), i));
+    ScopedJavaLocalRef<jstring> j_codec_type =
+        Java_CodecInfo_codecType(env, j_info.obj());
+    ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type);
+    ScopedJavaLocalRef<jstring> j_codec_name =
+        Java_CodecInfo_codecName(env, j_info.obj());
+    CodecsInfo info;
+    info.codecs = AndroidMimeTypeToCodecType(mime_type);
+    ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name);
+    info.direction = static_cast<MediaCodecDirection>(
+        Java_CodecInfo_direction(env, j_info.obj()));
+    codecs_info.push_back(info);
+  }
+  return codecs_info;
+}
+
+// static
+bool MediaCodecUtil::IsMediaCodecAvailable() {
+  // MediaCodec is only available on JB and greater.
+  if (base::android::BuildInfo::GetInstance()->sdk_int() < 16)
+    return false;
+  // Blacklist some devices on Jellybean as for MediaCodec support is buggy.
+  // http://crbug.com/365494.
+  if (base::android::BuildInfo::GetInstance()->sdk_int() == 16) {
+    std::string model(base::android::BuildInfo::GetInstance()->model());
+    return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000";
+  }
+  return true;
+}
+
+// static
+bool MediaCodecUtil::SupportsSetParameters() {
+  // MediaCodec.setParameters() is only available starting with K.
+  return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
+}
+
+// static
+std::set<int> MediaCodecUtil::GetEncoderColorFormats(
+    const std::string& mime_type) {
+  std::set<int> color_formats;
+  if (!IsMediaCodecAvailable())
+    return color_formats;
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
+  ScopedJavaLocalRef<jintArray> j_color_format_array =
+      Java_MediaCodecUtil_getEncoderColorFormatsForMime(env, j_mime.obj());
+
+  if (j_color_format_array.obj()) {
+    std::vector<int> formats;
+    JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats);
+    color_formats = std::set<int>(formats.begin(), formats.end());
+  }
+
+  return color_formats;
+}
+
+// static
+bool MediaCodecUtil::CanDecode(const std::string& codec, bool is_secure) {
+  if (!IsMediaCodecAvailable())
+    return false;
+
+  JNIEnv* env = AttachCurrentThread();
+  std::string mime = CodecTypeToAndroidMimeType(codec);
+  if (mime.empty())
+    return false;
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
+  return Java_MediaCodecUtil_canDecode(env, j_mime.obj(), is_secure);
+}
+
+// static
+bool MediaCodecUtil::IsKnownUnaccelerated(const std::string& mime_type,
+                                          MediaCodecDirection direction) {
+  if (!IsMediaCodecAvailable())
+    return true;
+
+  std::string codec_name;
+  if (SupportsGetName()) {
+    codec_name = GetDefaultCodecName(mime_type, direction);
+  } else {
+    std::string codec_type = AndroidMimeTypeToCodecType(mime_type);
+    std::vector<CodecsInfo> codecs_info = GetCodecsInfo();
+    for (size_t i = 0; i < codecs_info.size(); ++i) {
+      if (codecs_info[i].codecs == codec_type &&
+          codecs_info[i].direction == direction) {
+        codec_name = codecs_info[i].name;
+        break;
+      }
+    }
+  }
+  DVLOG(1) << __PRETTY_FUNCTION__ << "Default codec for " << mime_type << " : "
+           << codec_name;
+  // It would be nice if MediaCodecInfo externalized some notion of
+  // HW-acceleration but it doesn't. Android Media guidance is that the
+  // "OMX.google" prefix is always used for SW decoders, so that's what we
+  // use. "OMX.SEC.*" codec is Samsung software implementation - report it
+  // as unaccelerated as well. Also temporary blacklist Exynos and MediaTek
+  // devices while HW decoder video freezes and distortions are
+  // investigated - http://crbug.com/446974.
+  if (codec_name.length() > 0) {
+    return (base::StartsWith(codec_name, "OMX.google.",
+                             base::CompareCase::SENSITIVE) ||
+            base::StartsWith(codec_name, "OMX.SEC.",
+                             base::CompareCase::SENSITIVE) ||
+            base::StartsWith(codec_name, "OMX.MTK.",
+                             base::CompareCase::SENSITIVE) ||
+            base::StartsWith(codec_name, "OMX.Exynos.",
+                             base::CompareCase::SENSITIVE));
+  }
+  return true;
+}
+
+// static
+bool MediaCodecUtil::RegisterMediaCodecUtil(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace media
diff --git a/media/base/android/media_codec_util.h b/media/base/android/media_codec_util.h
new file mode 100644
index 0000000..604ce5d2
--- /dev/null
+++ b/media/base/android/media_codec_util.h
@@ -0,0 +1,63 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_ANDROID_MEDIA_CODEC_UTIL_H_
+#define MEDIA_BASE_ANDROID_MEDIA_CODEC_UTIL_H_
+
+#include <jni.h>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+// Helper macro to skip the test if MediaCodecBridge isn't available.
+#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
+  do {                                                            \
+    if (!MediaCodecUtil::IsMediaCodecAvailable()) {               \
+      VLOG(0) << "Could not run test - not supported on device."; \
+      return;                                                     \
+    }                                                             \
+  } while (0)
+
+// Codec direction. Keep this in sync with MediaCodecUtil.java.
+enum MediaCodecDirection {
+  MEDIA_CODEC_DECODER,
+  MEDIA_CODEC_ENCODER,
+};
+
+class MEDIA_EXPORT MediaCodecUtil {
+ public:
+  // Returns true if MediaCodec is available on the device.
+  // All other static methods check IsAvailable() internally. There's no need
+  // to check IsAvailable() explicitly before calling them.
+  static bool IsMediaCodecAvailable();
+
+  // Returns true if MediaCodec.setParameters() is available on the device.
+  static bool SupportsSetParameters();
+
+  // Returns whether MediaCodecBridge has a decoder that |is_secure| and can
+  // decode |codec| type.
+  static bool CanDecode(const std::string& codec, bool is_secure);
+
+  // Get a list of encoder supported color formats for |mime_type|.
+  // The mapping of color format name and its value refers to
+  // MediaCodecInfo.CodecCapabilities.
+  static std::set<int> GetEncoderColorFormats(const std::string& mime_type);
+
+  // Returns true if |mime_type| is known to be unaccelerated (i.e. backed by a
+  // software codec instead of a hardware one).
+  static bool IsKnownUnaccelerated(const std::string& mime_type,
+                                   MediaCodecDirection direction);
+
+  static bool RegisterMediaCodecUtil(JNIEnv* env);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_ANDROID_MEDIA_CODEC_UTIL_H_
diff --git a/media/base/android/media_codec_video_decoder.cc b/media/base/android/media_codec_video_decoder.cc
index f20bbeb..928f2e7 100644
--- a/media/base/android/media_codec_video_decoder.cc
+++ b/media/base/android/media_codec_video_decoder.cc
@@ -6,8 +6,8 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_statistics.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/demuxer_stream.h"
 #include "media/base/timestamp_constants.h"
 
diff --git a/media/base/android/media_decoder_job.cc b/media/base/android/media_decoder_job.cc
index 3bf5279..ed367d7 100644
--- a/media/base/android/media_decoder_job.cc
+++ b/media/base/android/media_decoder_job.cc
@@ -285,13 +285,9 @@
   }
 
   MediaCodecStatus status = media_codec_bridge_->QueueSecureInputBuffer(
-      input_buf_index,
-      &unit.data[0], unit.data.size(),
-      reinterpret_cast<const uint8*>(&unit.key_id[0]), unit.key_id.size(),
-      reinterpret_cast<const uint8*>(&unit.iv[0]), unit.iv.size(),
+      input_buf_index, &unit.data[0], unit.data.size(), unit.key_id, unit.iv,
       unit.subsamples.empty() ? NULL : &unit.subsamples[0],
-      unit.subsamples.size(),
-      unit.timestamp);
+      unit.subsamples.size(), unit.timestamp);
 
   // In case of MEDIA_CODEC_NO_KEY, we must reuse the |input_buf_index_|.
   // Otherwise MediaDrm will report errors.
diff --git a/media/base/android/media_jni_registrar.cc b/media/base/android/media_jni_registrar.cc
index 2020469..cc8bc1d 100644
--- a/media/base/android/media_jni_registrar.cc
+++ b/media/base/android/media_jni_registrar.cc
@@ -10,10 +10,11 @@
 
 #include "media/audio/android/audio_manager_android.h"
 #include "media/audio/android/audio_record_input.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_codec_util.h"
 #include "media/base/android/media_drm_bridge.h"
 #include "media/base/android/media_player_bridge.h"
 #include "media/base/android/media_player_listener.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/android/webaudio_media_codec_bridge.h"
 #include "media/capture/video/android/video_capture_device_android.h"
 #include "media/capture/video/android/video_capture_device_factory_android.h"
@@ -21,24 +22,19 @@
 namespace media {
 
 static base::android::RegistrationMethod kMediaRegisteredMethods[] = {
-  { "AudioManagerAndroid",
-    AudioManagerAndroid::RegisterAudioManager },
-  { "AudioRecordInput",
-    AudioRecordInputStream::RegisterAudioRecordInput },
-  { "MediaCodecBridge",
-    MediaCodecBridge::RegisterMediaCodecBridge },
-  { "MediaDrmBridge",
-    MediaDrmBridge::RegisterMediaDrmBridge },
-  { "MediaPlayerBridge",
-    MediaPlayerBridge::RegisterMediaPlayerBridge },
-  { "MediaPlayerListener",
-    MediaPlayerListener::RegisterMediaPlayerListener },
-  { "VideoCaptureDevice",
-    VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice },
-  { "VideoCaptureDeviceFactory",
-    VideoCaptureDeviceFactoryAndroid::RegisterVideoCaptureDeviceFactory },
-  { "WebAudioMediaCodecBridge",
-    WebAudioMediaCodecBridge::RegisterWebAudioMediaCodecBridge },
+    {"AudioManagerAndroid", AudioManagerAndroid::RegisterAudioManager},
+    {"AudioRecordInput", AudioRecordInputStream::RegisterAudioRecordInput},
+    {"MediaDrmBridge", MediaDrmBridge::RegisterMediaDrmBridge},
+    {"MediaPlayerBridge", MediaPlayerBridge::RegisterMediaPlayerBridge},
+    {"MediaPlayerListener", MediaPlayerListener::RegisterMediaPlayerListener},
+    {"SdkMediaCodecBridge", SdkMediaCodecBridge::RegisterSdkMediaCodecBridge},
+    {"MediaCodecUtil", MediaCodecUtil::RegisterMediaCodecUtil},
+    {"VideoCaptureDevice",
+     VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice},
+    {"VideoCaptureDeviceFactory",
+     VideoCaptureDeviceFactoryAndroid::RegisterVideoCaptureDeviceFactory},
+    {"WebAudioMediaCodecBridge",
+     WebAudioMediaCodecBridge::RegisterWebAudioMediaCodecBridge},
 };
 
 bool RegisterJni(JNIEnv* env) {
diff --git a/media/base/android/media_source_player_unittest.cc b/media/base/android/media_source_player_unittest.cc
index fd4a725..b7cab6c 100644
--- a/media/base/android/media_source_player_unittest.cc
+++ b/media/base/android/media_source_player_unittest.cc
@@ -9,11 +9,12 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/stringprintf.h"
 #include "media/base/android/audio_decoder_job.h"
-#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_codec_util.h"
 #include "media/base/android/media_drm_bridge.h"
 #include "media/base/android/media_player_manager.h"
 #include "media/base/android/media_source_player.h"
 #include "media/base/android/media_url_interceptor.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/android/video_decoder_job.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/decoder_buffer.h"
@@ -24,15 +25,6 @@
 
 namespace media {
 
-// Helper macro to skip the test if MediaCodecBridge isn't available.
-#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
-  do {                                                            \
-    if (!MediaCodecBridge::IsAvailable()) {                       \
-      VLOG(0) << "Could not run test - not supported on device."; \
-      return;                                                     \
-    }                                                             \
-  } while (0)
-
 const base::TimeDelta kDefaultDuration =
     base::TimeDelta::FromMilliseconds(10000);
 
diff --git a/media/base/android/ndk_media_codec_bridge.cc b/media/base/android/ndk_media_codec_bridge.cc
new file mode 100644
index 0000000..ae23aff
--- /dev/null
+++ b/media/base/android/ndk_media_codec_bridge.cc
@@ -0,0 +1,228 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/android/ndk_media_codec_bridge.h"
+
+#include <media/NdkMediaError.h>
+#include <media/NdkMediaFormat.h>
+
+#include "base/strings/string_util.h"
+#include "media/base/decrypt_config.h"
+
+namespace {
+const char kMediaFormatKeyCropLeft[] = "crop-left";
+const char kMediaFormatKeyCropRight[] = "crop-right";
+const char kMediaFormatKeyCropBottom[] = "crop-bottom";
+const char kMediaFormatKeyCropTop[] = "crop-top";
+}
+
+namespace media {
+
+// Translate media_status_t to MediaCodecStatus.
+static MediaCodecStatus TranslateMediaCodecStatus(media_status_t status) {
+  switch (status) {
+    case AMEDIA_OK:
+      return MEDIA_CODEC_OK;
+    case AMEDIA_DRM_NEED_KEY:
+      return MEDIA_CODEC_NO_KEY;
+    default:
+      return MEDIA_CODEC_ERROR;
+  }
+}
+
+NdkMediaCodecBridge::~NdkMediaCodecBridge() {}
+
+NdkMediaCodecBridge::NdkMediaCodecBridge(const std::string& mime,
+                                         bool is_secure,
+                                         MediaCodecDirection direction) {
+  if (base::StartsWith(mime, "video", base::CompareCase::SENSITIVE) &&
+      is_secure && direction == MEDIA_CODEC_DECODER) {
+    // TODO(qinmin): get the secure decoder name from java.
+    NOTIMPLEMENTED();
+    return;
+  }
+
+  if (direction == MEDIA_CODEC_DECODER)
+    media_codec_.reset(AMediaCodec_createDecoderByType(mime.c_str()));
+  else
+    media_codec_.reset(AMediaCodec_createEncoderByType(mime.c_str()));
+}
+
+MediaCodecStatus NdkMediaCodecBridge::Reset() {
+  media_status_t status = AMediaCodec_flush(media_codec_.get());
+  return TranslateMediaCodecStatus(status);
+}
+
+bool NdkMediaCodecBridge::Start() {
+  return AMEDIA_OK == AMediaCodec_start(media_codec_.get());
+}
+
+void NdkMediaCodecBridge::Stop() {
+  AMediaCodec_stop(media_codec_.get());
+}
+
+void NdkMediaCodecBridge::GetOutputFormat(int* width, int* height) {
+  AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
+  int left, right, bottom, top;
+  bool has_left = AMediaFormat_getInt32(format, kMediaFormatKeyCropLeft, &left);
+  bool has_right =
+      AMediaFormat_getInt32(format, kMediaFormatKeyCropRight, &right);
+  bool has_bottom =
+      AMediaFormat_getInt32(format, kMediaFormatKeyCropBottom, &bottom);
+  bool has_top = AMediaFormat_getInt32(format, kMediaFormatKeyCropTop, &top);
+  if (has_left && has_right && has_bottom && has_top) {
+    // Use crop size as it is more accurate. right and bottom are inclusive.
+    *width = right - left + 1;
+    *height = top - bottom + 1;
+  } else {
+    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, width);
+    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height);
+  }
+}
+
+int NdkMediaCodecBridge::GetOutputSamplingRate() {
+  AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
+  int sample_rate = 0;
+  AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sample_rate);
+  DCHECK(sample_rate != 0);
+  return sample_rate;
+}
+
+MediaCodecStatus NdkMediaCodecBridge::QueueInputBuffer(
+    int index,
+    const uint8* data,
+    size_t data_size,
+    const base::TimeDelta& presentation_time) {
+  if (data_size > base::checked_cast<size_t>(kint32max))
+    return MEDIA_CODEC_ERROR;
+  if (data && !FillInputBuffer(index, data, data_size))
+    return MEDIA_CODEC_ERROR;
+
+  media_status_t status =
+      AMediaCodec_queueInputBuffer(media_codec_.get(), index, 0, data_size,
+                                   presentation_time.InMicroseconds(), 0);
+  return TranslateMediaCodecStatus(status);
+}
+
+MediaCodecStatus NdkMediaCodecBridge::QueueSecureInputBuffer(
+    int index,
+    const uint8* data,
+    size_t data_size,
+    const std::vector<char>& key_id,
+    const std::vector<char>& iv,
+    const SubsampleEntry* subsamples,
+    int subsamples_size,
+    const base::TimeDelta& presentation_time) {
+  if (data_size > base::checked_cast<size_t>(kint32max))
+    return MEDIA_CODEC_ERROR;
+  if (key_id.size() > 16 || iv.size())
+    return MEDIA_CODEC_ERROR;
+  if (data && !FillInputBuffer(index, data, data_size))
+    return MEDIA_CODEC_ERROR;
+
+  int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
+  std::vector<size_t> clear_data, encrypted_data;
+  if (subsamples_size == 0) {
+    DCHECK(!subsamples);
+    clear_data.push_back(0);
+    encrypted_data.push_back(data_size);
+  } else {
+    DCHECK_GT(subsamples_size, 0);
+    DCHECK(subsamples);
+    for (int i = 0; i < subsamples_size; ++i) {
+      DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max());
+      if (subsamples[i].cypher_bytes >
+          static_cast<uint32>(std::numeric_limits<int32>::max())) {
+        return MEDIA_CODEC_ERROR;
+      }
+      clear_data.push_back(subsamples[i].clear_bytes);
+      encrypted_data.push_back(subsamples[i].cypher_bytes);
+    }
+  }
+
+  AMediaCodecCryptoInfo* crypto_info = AMediaCodecCryptoInfo_new(
+      new_subsamples_size,
+      reinterpret_cast<uint8*>(const_cast<char*>(key_id.data())),
+      reinterpret_cast<uint8*>(const_cast<char*>(iv.data())),
+      AMEDIACODECRYPTOINFO_MODE_AES_CTR, clear_data.data(),
+      encrypted_data.data());
+
+  media_status_t status = AMediaCodec_queueSecureInputBuffer(
+      media_codec_.get(), index, 0, crypto_info,
+      presentation_time.InMicroseconds(), 0);
+  return TranslateMediaCodecStatus(status);
+}
+
+void NdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
+  AMediaCodec_queueInputBuffer(media_codec_.get(), input_buffer_index, 0, 0, 0,
+                               AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
+}
+
+MediaCodecStatus NdkMediaCodecBridge::DequeueInputBuffer(
+    const base::TimeDelta& timeout,
+    int* index) {
+  *index = AMediaCodec_dequeueInputBuffer(media_codec_.get(),
+                                          timeout.InMicroseconds());
+  if (*index >= 0)
+    return MEDIA_CODEC_OK;
+  else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
+    return MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
+  else
+    return MEDIA_CODEC_ERROR;
+}
+
+MediaCodecStatus NdkMediaCodecBridge::DequeueOutputBuffer(
+    const base::TimeDelta& timeout,
+    int* index,
+    size_t* offset,
+    size_t* size,
+    base::TimeDelta* presentation_time,
+    bool* end_of_stream,
+    bool* key_frame) {
+  AMediaCodecBufferInfo buffer_info;
+  *index = AMediaCodec_dequeueOutputBuffer(media_codec_.get(), &buffer_info,
+                                           timeout.InMicroseconds());
+  *offset = buffer_info.offset;
+  *size = buffer_info.size;
+  *presentation_time =
+      base::TimeDelta::FromMicroseconds(buffer_info.presentationTimeUs);
+  if (end_of_stream)
+    *end_of_stream = buffer_info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
+  if (key_frame)
+    *key_frame = false;  // This is deprecated.
+  if (*index >= 0)
+    return MEDIA_CODEC_OK;
+  else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
+    return MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
+  else
+    return MEDIA_CODEC_ERROR;
+}
+
+void NdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
+  AMediaCodec_releaseOutputBuffer(media_codec_.get(), index, render);
+}
+
+void NdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
+                                         uint8** data,
+                                         size_t* capacity) {
+  *data = AMediaCodec_getInputBuffer(media_codec_.get(), input_buffer_index,
+                                     capacity);
+}
+
+bool NdkMediaCodecBridge::CopyFromOutputBuffer(int index,
+                                               size_t offset,
+                                               void* dst,
+                                               int dst_size) {
+  size_t capacity;
+  uint8_t* src_data =
+      AMediaCodec_getOutputBuffer(media_codec_.get(), index, &capacity);
+
+  if (capacity < offset || capacity - offset < static_cast<size_t>(dst_size))
+    return false;
+
+  memcpy(dst, src_data + offset, dst_size);
+  return true;
+}
+
+}  // namespace media
diff --git a/media/base/android/ndk_media_codec_bridge.h b/media/base/android/ndk_media_codec_bridge.h
new file mode 100644
index 0000000..75bada9
--- /dev/null
+++ b/media/base/android/ndk_media_codec_bridge.h
@@ -0,0 +1,79 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_ANDROID_NDK_MEDIA_CODEC_BRIDGE_H_
+#define MEDIA_BASE_ANDROID_NDK_MEDIA_CODEC_BRIDGE_H_
+
+#include <media/NdkMediaCodec.h>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "media/base/android/media_codec_bridge.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+class MEDIA_EXPORT NdkMediaCodecBridge : public MediaCodecBridge {
+ public:
+  ~NdkMediaCodecBridge() override;
+
+  // MediaCodecBridge implementation.
+  MediaCodecStatus Reset() override;
+  bool Start() override;
+  void Stop() override;
+  void GetOutputFormat(int* width, int* height) override;
+  int GetOutputSamplingRate() override;
+  MediaCodecStatus QueueInputBuffer(
+      int index,
+      const uint8* data,
+      size_t data_size,
+      const base::TimeDelta& presentation_time) override;
+  using MediaCodecBridge::QueueSecureInputBuffer;
+  MediaCodecStatus QueueSecureInputBuffer(
+      int index,
+      const uint8* data,
+      size_t data_size,
+      const std::vector<char>& key_id,
+      const std::vector<char>& iv,
+      const SubsampleEntry* subsamples,
+      int subsamples_size,
+      const base::TimeDelta& presentation_time) override;
+  void QueueEOS(int input_buffer_index);
+  MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout,
+                                      int* index) override;
+  MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout,
+                                       int* index,
+                                       size_t* offset,
+                                       size_t* size,
+                                       base::TimeDelta* presentation_time,
+                                       bool* end_of_stream,
+                                       bool* key_frame) override;
+  void ReleaseOutputBuffer(int index, bool render) override;
+  void GetInputBuffer(int input_buffer_index,
+                      uint8** data,
+                      size_t* capacity) override;
+  bool CopyFromOutputBuffer(int index,
+                            size_t offset,
+                            void* dst,
+                            int dst_size) override;
+
+ protected:
+  NdkMediaCodecBridge(const std::string& mime,
+                      bool is_secure,
+                      MediaCodecDirection direction);
+
+ private:
+  struct AMediaCodecDeleter {
+    inline void operator()(AMediaCodec* ptr) const { AMediaCodec_delete(ptr); }
+  };
+
+  scoped_ptr<AMediaCodec, AMediaCodecDeleter> media_codec_;
+
+  DISALLOW_COPY_AND_ASSIGN(NdkMediaCodecBridge);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_ANDROID_NDK_MEDIA_CODEC_BRIDGE_H_
diff --git a/media/base/android/sdk_media_codec_bridge.cc b/media/base/android/sdk_media_codec_bridge.cc
new file mode 100644
index 0000000..01cfa3f
--- /dev/null
+++ b/media/base/android/sdk_media_codec_bridge.cc
@@ -0,0 +1,638 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/android/sdk_media_codec_bridge.h"
+
+#include <algorithm>
+
+#include "base/android/build_info.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_util.h"
+#include "jni/MediaCodecBridge_jni.h"
+#include "media/base/bit_reader.h"
+#include "media/base/decrypt_config.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::JavaIntArrayToIntVector;
+using base::android::ScopedJavaLocalRef;
+
+#define RETURN_ON_ERROR(condition)                             \
+  do {                                                         \
+    if (!(condition)) {                                        \
+      LOG(ERROR) << "Unable to parse AAC header: " #condition; \
+      return false;                                            \
+    }                                                          \
+  } while (0)
+
+namespace media {
+
+enum {
+  kBufferFlagSyncFrame = 1,    // BUFFER_FLAG_SYNC_FRAME
+  kBufferFlagEndOfStream = 4,  // BUFFER_FLAG_END_OF_STREAM
+  kConfigureFlagEncode = 1,    // CONFIGURE_FLAG_ENCODE
+};
+
+static ScopedJavaLocalRef<jintArray>
+ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) {
+  ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
+  env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
+  return j_array;
+}
+
+static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
+  switch (codec) {
+    case kCodecMP3:
+      return "audio/mpeg";
+    case kCodecVorbis:
+      return "audio/vorbis";
+    case kCodecOpus:
+      return "audio/opus";
+    case kCodecAAC:
+      return "audio/mp4a-latm";
+    default:
+      return std::string();
+  }
+}
+
+static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
+  switch (codec) {
+    case kCodecH264:
+      return "video/avc";
+    case kCodecHEVC:
+      return "video/hevc";
+    case kCodecVP8:
+      return "video/x-vnd.on2.vp8";
+    case kCodecVP9:
+      return "video/x-vnd.on2.vp9";
+    default:
+      return std::string();
+  }
+}
+
+SdkMediaCodecBridge::SdkMediaCodecBridge(const std::string& mime,
+                                         bool is_secure,
+                                         MediaCodecDirection direction) {
+  JNIEnv* env = AttachCurrentThread();
+  CHECK(env);
+  DCHECK(!mime.empty());
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
+  j_media_codec_.Reset(
+      Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction));
+}
+
+SdkMediaCodecBridge::~SdkMediaCodecBridge() {
+  JNIEnv* env = AttachCurrentThread();
+  CHECK(env);
+  if (j_media_codec_.obj())
+    Java_MediaCodecBridge_release(env, j_media_codec_.obj());
+}
+
+MediaCodecStatus SdkMediaCodecBridge::Reset() {
+  JNIEnv* env = AttachCurrentThread();
+  return static_cast<MediaCodecStatus>(
+      Java_MediaCodecBridge_flush(env, j_media_codec_.obj()));
+}
+
+bool SdkMediaCodecBridge::Start() {
+  JNIEnv* env = AttachCurrentThread();
+  return Java_MediaCodecBridge_start(env, j_media_codec_.obj());
+}
+
+void SdkMediaCodecBridge::Stop() {
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_stop(env, j_media_codec_.obj());
+}
+
+void SdkMediaCodecBridge::GetOutputFormat(int* width, int* height) {
+  JNIEnv* env = AttachCurrentThread();
+
+  *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj());
+  *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj());
+}
+
+int SdkMediaCodecBridge::GetOutputSamplingRate() {
+  JNIEnv* env = AttachCurrentThread();
+
+  return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj());
+}
+
+MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer(
+    int index,
+    const uint8* data,
+    size_t data_size,
+    const base::TimeDelta& presentation_time) {
+  DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
+  if (data_size > base::checked_cast<size_t>(kint32max))
+    return MEDIA_CODEC_ERROR;
+  if (data && !FillInputBuffer(index, data, data_size))
+    return MEDIA_CODEC_ERROR;
+  JNIEnv* env = AttachCurrentThread();
+  return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer(
+      env, j_media_codec_.obj(), index, 0, data_size,
+      presentation_time.InMicroseconds(), 0));
+}
+
+// TODO(timav): Combine this and above methods together keeping only the first
+// interface after we switch to Spitzer pipeline.
+MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer(
+    int index,
+    const uint8* data,
+    size_t data_size,
+    const std::vector<char>& key_id,
+    const std::vector<char>& iv,
+    const SubsampleEntry* subsamples,
+    int subsamples_size,
+    const base::TimeDelta& presentation_time) {
+  DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
+  if (data_size > base::checked_cast<size_t>(kint32max))
+    return MEDIA_CODEC_ERROR;
+  if (data && !FillInputBuffer(index, data, data_size))
+    return MEDIA_CODEC_ERROR;
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jbyteArray> j_key_id = base::android::ToJavaByteArray(
+      env, reinterpret_cast<const uint8*>(key_id.data()), key_id.size());
+  ScopedJavaLocalRef<jbyteArray> j_iv = base::android::ToJavaByteArray(
+      env, reinterpret_cast<const uint8*>(iv.data()), iv.size());
+
+  // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array|
+  // to indicate that all data is encrypted. But it doesn't specify what
+  // |cypher_array| and |subsamples_size| should be in that case. Passing
+  // one subsample here just to be on the safe side.
+  int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
+
+  scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]);
+  scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]);
+
+  if (subsamples_size == 0) {
+    DCHECK(!subsamples);
+    native_clear_array[0] = 0;
+    native_cypher_array[0] = data_size;
+  } else {
+    DCHECK_GT(subsamples_size, 0);
+    DCHECK(subsamples);
+    for (int i = 0; i < subsamples_size; ++i) {
+      DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max());
+      if (subsamples[i].cypher_bytes >
+          static_cast<uint32>(std::numeric_limits<jint>::max())) {
+        return MEDIA_CODEC_ERROR;
+      }
+
+      native_clear_array[i] = subsamples[i].clear_bytes;
+      native_cypher_array[i] = subsamples[i].cypher_bytes;
+    }
+  }
+
+  ScopedJavaLocalRef<jintArray> clear_array =
+      ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size);
+  ScopedJavaLocalRef<jintArray> cypher_array =
+      ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size);
+
+  return static_cast<MediaCodecStatus>(
+      Java_MediaCodecBridge_queueSecureInputBuffer(
+          env, j_media_codec_.obj(), index, 0, j_iv.obj(), j_key_id.obj(),
+          clear_array.obj(), cypher_array.obj(), new_subsamples_size,
+          presentation_time.InMicroseconds()));
+}
+
+void SdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
+  DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index;
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_queueInputBuffer(env, j_media_codec_.obj(),
+                                         input_buffer_index, 0, 0, 0,
+                                         kBufferFlagEndOfStream);
+}
+
+MediaCodecStatus SdkMediaCodecBridge::DequeueInputBuffer(
+    const base::TimeDelta& timeout,
+    int* index) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer(
+      env, j_media_codec_.obj(), timeout.InMicroseconds());
+  *index = Java_DequeueInputResult_index(env, result.obj());
+  MediaCodecStatus status = static_cast<MediaCodecStatus>(
+      Java_DequeueInputResult_status(env, result.obj()));
+  DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
+           << ", index: " << *index;
+  return status;
+}
+
+MediaCodecStatus SdkMediaCodecBridge::DequeueOutputBuffer(
+    const base::TimeDelta& timeout,
+    int* index,
+    size_t* offset,
+    size_t* size,
+    base::TimeDelta* presentation_time,
+    bool* end_of_stream,
+    bool* key_frame) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> result =
+      Java_MediaCodecBridge_dequeueOutputBuffer(env, j_media_codec_.obj(),
+                                                timeout.InMicroseconds());
+  *index = Java_DequeueOutputResult_index(env, result.obj());
+  *offset = base::checked_cast<size_t>(
+      Java_DequeueOutputResult_offset(env, result.obj()));
+  *size = base::checked_cast<size_t>(
+      Java_DequeueOutputResult_numBytes(env, result.obj()));
+  if (presentation_time) {
+    *presentation_time = base::TimeDelta::FromMicroseconds(
+        Java_DequeueOutputResult_presentationTimeMicroseconds(env,
+                                                              result.obj()));
+  }
+  int flags = Java_DequeueOutputResult_flags(env, result.obj());
+  if (end_of_stream)
+    *end_of_stream = flags & kBufferFlagEndOfStream;
+  if (key_frame)
+    *key_frame = flags & kBufferFlagSyncFrame;
+  MediaCodecStatus status = static_cast<MediaCodecStatus>(
+      Java_DequeueOutputResult_status(env, result.obj()));
+  DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
+           << ", index: " << *index << ", offset: " << *offset
+           << ", size: " << *size << ", flags: " << flags;
+  return status;
+}
+
+void SdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
+  DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index;
+  JNIEnv* env = AttachCurrentThread();
+  CHECK(env);
+
+  Java_MediaCodecBridge_releaseOutputBuffer(env, j_media_codec_.obj(), index,
+                                            render);
+}
+
+int SdkMediaCodecBridge::GetOutputBuffersCount() {
+  JNIEnv* env = AttachCurrentThread();
+  return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj());
+}
+
+size_t SdkMediaCodecBridge::GetOutputBuffersCapacity() {
+  JNIEnv* env = AttachCurrentThread();
+  return Java_MediaCodecBridge_getOutputBuffersCapacity(env,
+                                                        j_media_codec_.obj());
+}
+
+void SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
+                                         uint8** data,
+                                         size_t* capacity) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer(
+      env, j_media_codec_.obj(), input_buffer_index));
+  *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
+  *capacity =
+      base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj()));
+}
+
+bool SdkMediaCodecBridge::CopyFromOutputBuffer(int index,
+                                               size_t offset,
+                                               void* dst,
+                                               int dst_size) {
+  void* src_data = nullptr;
+  size_t src_capacity = GetOutputBufferAddress(index, offset, &src_data);
+  if (src_capacity < offset ||
+      src_capacity - offset < static_cast<size_t>(dst_size)) {
+    return false;
+  }
+  memcpy(dst, static_cast<uint8*>(src_data) + offset, dst_size);
+  return true;
+}
+
+int SdkMediaCodecBridge::GetOutputBufferAddress(int index,
+                                                size_t offset,
+                                                void** addr) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> j_buffer(
+      Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index));
+  *addr =
+      reinterpret_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())) +
+      offset;
+  return env->GetDirectBufferCapacity(j_buffer.obj()) - offset;
+}
+
+// static
+bool SdkMediaCodecBridge::RegisterSdkMediaCodecBridge(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+// static
+AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) {
+  if (!MediaCodecUtil::IsMediaCodecAvailable())
+    return nullptr;
+
+  const std::string mime = AudioCodecToAndroidMimeType(codec);
+  return mime.empty() ? nullptr : new AudioCodecBridge(mime);
+}
+
+// static
+bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) {
+  return MediaCodecUtil::IsKnownUnaccelerated(
+      AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER);
+}
+
+AudioCodecBridge::AudioCodecBridge(const std::string& mime)
+    // Audio codec doesn't care about security level and there is no need for
+    // audio encoding yet.
+    : SdkMediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {}
+
+bool AudioCodecBridge::ConfigureAndStart(const AudioCodec& codec,
+                                         int sample_rate,
+                                         int channel_count,
+                                         const uint8* extra_data,
+                                         size_t extra_data_size,
+                                         int64 codec_delay_ns,
+                                         int64 seek_preroll_ns,
+                                         bool play_audio,
+                                         jobject media_crypto) {
+  JNIEnv* env = AttachCurrentThread();
+
+  if (!media_codec())
+    return false;
+
+  std::string codec_string = AudioCodecToAndroidMimeType(codec);
+  if (codec_string.empty())
+    return false;
+
+  ScopedJavaLocalRef<jstring> j_mime =
+      ConvertUTF8ToJavaString(env, codec_string);
+  ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat(
+      env, j_mime.obj(), sample_rate, channel_count));
+  DCHECK(!j_format.is_null());
+
+  if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size,
+                            codec_delay_ns, seek_preroll_ns)) {
+    return false;
+  }
+
+  if (!Java_MediaCodecBridge_configureAudio(env, media_codec(), j_format.obj(),
+                                            media_crypto, 0, play_audio)) {
+    return false;
+  }
+
+  return Start();
+}
+
+bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
+                                            const AudioCodec& codec,
+                                            const uint8* extra_data,
+                                            size_t extra_data_size,
+                                            int64 codec_delay_ns,
+                                            int64 seek_preroll_ns) {
+  if (extra_data_size == 0 && codec != kCodecOpus)
+    return true;
+
+  JNIEnv* env = AttachCurrentThread();
+  switch (codec) {
+    case kCodecVorbis: {
+      if (extra_data[0] != 2) {
+        LOG(ERROR) << "Invalid number of vorbis headers before the codec "
+                   << "header: " << extra_data[0];
+        return false;
+      }
+
+      size_t header_length[2];
+      // |total_length| keeps track of the total number of bytes before the last
+      // header.
+      size_t total_length = 1;
+      const uint8* current_pos = extra_data;
+      // Calculate the length of the first 2 headers.
+      for (int i = 0; i < 2; ++i) {
+        header_length[i] = 0;
+        while (total_length < extra_data_size) {
+          size_t size = *(++current_pos);
+          total_length += 1 + size;
+          if (total_length > 0x80000000) {
+            LOG(ERROR) << "Vorbis header size too large";
+            return false;
+          }
+          header_length[i] += size;
+          if (size < 0xFF)
+            break;
+        }
+        if (total_length >= extra_data_size) {
+          LOG(ERROR) << "Invalid vorbis header size in the extra data";
+          return false;
+        }
+      }
+      current_pos++;
+      // The first header is identification header.
+      ScopedJavaLocalRef<jbyteArray> first_header =
+          base::android::ToJavaByteArray(env, current_pos, header_length[0]);
+      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0,
+                                                 first_header.obj());
+      // The last header is codec header.
+      ScopedJavaLocalRef<jbyteArray> last_header =
+          base::android::ToJavaByteArray(env, extra_data + total_length,
+                                         extra_data_size - total_length);
+      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1,
+                                                 last_header.obj());
+      break;
+    }
+    case kCodecAAC: {
+      media::BitReader reader(extra_data, extra_data_size);
+
+      // The following code is copied from aac.cc
+      // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
+      uint8 profile = 0;
+      uint8 frequency_index = 0;
+      uint8 channel_config = 0;
+      RETURN_ON_ERROR(reader.ReadBits(5, &profile));
+      RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
+
+      if (0xf == frequency_index)
+        RETURN_ON_ERROR(reader.SkipBits(24));
+      RETURN_ON_ERROR(reader.ReadBits(4, &channel_config));
+
+      if (profile == 5 || profile == 29) {
+        // Read extension config.
+        RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
+        if (frequency_index == 0xf)
+          RETURN_ON_ERROR(reader.SkipBits(24));
+        RETURN_ON_ERROR(reader.ReadBits(5, &profile));
+      }
+
+      if (profile < 1 || profile > 4 || frequency_index == 0xf ||
+          channel_config > 7) {
+        LOG(ERROR) << "Invalid AAC header";
+        return false;
+      }
+      const size_t kCsdLength = 2;
+      uint8 csd[kCsdLength];
+      csd[0] = profile << 3 | frequency_index >> 1;
+      csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3;
+      ScopedJavaLocalRef<jbyteArray> byte_array =
+          base::android::ToJavaByteArray(env, csd, kCsdLength);
+      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0,
+                                                 byte_array.obj());
+
+      // TODO(qinmin): pass an extra variable to this function to determine
+      // whether we need to call this.
+      Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format);
+      break;
+    }
+    case kCodecOpus: {
+      if (!extra_data || extra_data_size == 0 || codec_delay_ns < 0 ||
+          seek_preroll_ns < 0) {
+        LOG(ERROR) << "Invalid Opus Header";
+        return false;
+      }
+
+      // csd0 - Opus Header
+      ScopedJavaLocalRef<jbyteArray> csd0 =
+          base::android::ToJavaByteArray(env, extra_data, extra_data_size);
+      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj());
+
+      // csd1 - Codec Delay
+      ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray(
+          env, reinterpret_cast<const uint8*>(&codec_delay_ns),
+          sizeof(int64_t));
+      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj());
+
+      // csd2 - Seek Preroll
+      ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray(
+          env, reinterpret_cast<const uint8*>(&seek_preroll_ns),
+          sizeof(int64_t));
+      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj());
+      break;
+    }
+    default:
+      LOG(ERROR) << "Invalid header encountered for codec: "
+                 << AudioCodecToAndroidMimeType(codec);
+      return false;
+  }
+  return true;
+}
+
+int64 AudioCodecBridge::PlayOutputBuffer(int index,
+                                         size_t size,
+                                         size_t offset,
+                                         bool postpone) {
+  DCHECK_LE(0, index);
+  int numBytes = base::checked_cast<int>(size);
+
+  void* buffer = nullptr;
+  int capacity = GetOutputBufferAddress(index, offset, &buffer);
+  numBytes = std::min(capacity, numBytes);
+  CHECK_GE(numBytes, 0);
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray(
+      env, static_cast<uint8*>(buffer), numBytes);
+  return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(),
+                                                byte_array.obj(), postpone);
+}
+
+void AudioCodecBridge::SetVolume(double volume) {
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_setVolume(env, media_codec(), volume);
+}
+
+// static
+bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec,
+                                            MediaCodecDirection direction) {
+  return MediaCodecUtil::IsKnownUnaccelerated(
+      VideoCodecToAndroidMimeType(codec), direction);
+}
+
+// static
+VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec,
+                                                  bool is_secure,
+                                                  const gfx::Size& size,
+                                                  jobject surface,
+                                                  jobject media_crypto) {
+  if (!MediaCodecUtil::IsMediaCodecAvailable())
+    return nullptr;
+
+  const std::string mime = VideoCodecToAndroidMimeType(codec);
+  if (mime.empty())
+    return nullptr;
+
+  scoped_ptr<VideoCodecBridge> bridge(
+      new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER));
+  if (!bridge->media_codec())
+    return nullptr;
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
+  ScopedJavaLocalRef<jobject> j_format(
+      Java_MediaCodecBridge_createVideoDecoderFormat(
+          env, j_mime.obj(), size.width(), size.height()));
+  DCHECK(!j_format.is_null());
+  if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(),
+                                            j_format.obj(), surface,
+                                            media_crypto, 0)) {
+    return nullptr;
+  }
+
+  return bridge->Start() ? bridge.release() : nullptr;
+}
+
+// static
+VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec,
+                                                  const gfx::Size& size,
+                                                  int bit_rate,
+                                                  int frame_rate,
+                                                  int i_frame_interval,
+                                                  int color_format) {
+  if (!MediaCodecUtil::IsMediaCodecAvailable())
+    return nullptr;
+
+  const std::string mime = VideoCodecToAndroidMimeType(codec);
+  if (mime.empty())
+    return nullptr;
+
+  scoped_ptr<VideoCodecBridge> bridge(
+      new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER));
+  if (!bridge->media_codec())
+    return nullptr;
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
+  ScopedJavaLocalRef<jobject> j_format(
+      Java_MediaCodecBridge_createVideoEncoderFormat(
+          env, j_mime.obj(), size.width(), size.height(), bit_rate, frame_rate,
+          i_frame_interval, color_format));
+  DCHECK(!j_format.is_null());
+  if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(),
+                                            j_format.obj(), nullptr, nullptr,
+                                            kConfigureFlagEncode)) {
+    return nullptr;
+  }
+
+  return bridge->Start() ? bridge.release() : nullptr;
+}
+
+VideoCodecBridge::VideoCodecBridge(const std::string& mime,
+                                   bool is_secure,
+                                   MediaCodecDirection direction)
+    : SdkMediaCodecBridge(mime, is_secure, direction),
+      adaptive_playback_supported_for_testing_(-1) {}
+
+void VideoCodecBridge::SetVideoBitrate(int bps) {
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps);
+}
+
+void VideoCodecBridge::RequestKeyFrameSoon() {
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec());
+}
+
+bool VideoCodecBridge::IsAdaptivePlaybackSupported(int width, int height) {
+  if (adaptive_playback_supported_for_testing_ == 0)
+    return false;
+  else if (adaptive_playback_supported_for_testing_ > 0)
+    return true;
+  JNIEnv* env = AttachCurrentThread();
+  return Java_MediaCodecBridge_isAdaptivePlaybackSupported(env, media_codec(),
+                                                           width, height);
+}
+
+}  // namespace media
diff --git a/media/base/android/sdk_media_codec_bridge.h b/media/base/android/sdk_media_codec_bridge.h
new file mode 100644
index 0000000..3518ad71
--- /dev/null
+++ b/media/base/android/sdk_media_codec_bridge.h
@@ -0,0 +1,196 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_
+#define MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_
+
+#include <jni.h>
+#include <set>
+#include <string>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "media/base/android/media_codec_bridge.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/media_export.h"
+#include "media/base/video_decoder_config.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace media {
+
+// This class implements MediaCodecBridge using android MediaCodec SDK APIs.
+class MEDIA_EXPORT SdkMediaCodecBridge : public MediaCodecBridge {
+ public:
+  ~SdkMediaCodecBridge() override;
+
+  // MediaCodecBridge implementations.
+  MediaCodecStatus Reset() override;
+  bool Start() override;
+  void Stop() override;
+  void GetOutputFormat(int* width, int* height) override;
+  int GetOutputSamplingRate() override;
+  MediaCodecStatus QueueInputBuffer(
+      int index,
+      const uint8* data,
+      size_t data_size,
+      const base::TimeDelta& presentation_time) override;
+  using MediaCodecBridge::QueueSecureInputBuffer;
+  MediaCodecStatus QueueSecureInputBuffer(
+      int index,
+      const uint8* data,
+      size_t data_size,
+      const std::vector<char>& key_id,
+      const std::vector<char>& iv,
+      const SubsampleEntry* subsamples,
+      int subsamples_size,
+      const base::TimeDelta& presentation_time) override;
+  void QueueEOS(int input_buffer_index) override;
+  MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout,
+                                      int* index) override;
+  MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout,
+                                       int* index,
+                                       size_t* offset,
+                                       size_t* size,
+                                       base::TimeDelta* presentation_time,
+                                       bool* end_of_stream,
+                                       bool* key_frame) override;
+  void ReleaseOutputBuffer(int index, bool render) override;
+  int GetOutputBuffersCount() override;
+  size_t GetOutputBuffersCapacity() override;
+  void GetInputBuffer(int input_buffer_index,
+                      uint8** data,
+                      size_t* capacity) override;
+  bool CopyFromOutputBuffer(int index,
+                            size_t offset,
+                            void* dst,
+                            int dst_size) override;
+
+  static bool RegisterSdkMediaCodecBridge(JNIEnv* env);
+
+ protected:
+  SdkMediaCodecBridge(const std::string& mime,
+                      bool is_secure,
+                      MediaCodecDirection direction);
+
+  // Called to get the buffer address given the output buffer index and offset.
+  // This function returns the size of the output and |addr| is the pointer to
+  // the address to read.
+  int GetOutputBufferAddress(int index, size_t offset, void** addr);
+
+  jobject media_codec() { return j_media_codec_.obj(); }
+  MediaCodecDirection direction_;
+
+ private:
+  // Java MediaCodec instance.
+  base::android::ScopedJavaGlobalRef<jobject> j_media_codec_;
+
+  DISALLOW_COPY_AND_ASSIGN(SdkMediaCodecBridge);
+};
+
+// Class for handling audio decoding using android MediaCodec APIs.
+// TODO(qinmin): implement the logic to switch between NDK and SDK
+// MediaCodecBridge.
+class MEDIA_EXPORT AudioCodecBridge : public SdkMediaCodecBridge {
+ public:
+  // Returns an AudioCodecBridge instance if |codec| is supported, or a NULL
+  // pointer otherwise.
+  static AudioCodecBridge* Create(const AudioCodec& codec);
+
+  // See MediaCodecUtil::IsKnownUnaccelerated().
+  static bool IsKnownUnaccelerated(const AudioCodec& codec);
+
+  // Start the audio codec bridge.
+  bool ConfigureAndStart(const AudioCodec& codec,
+                         int sample_rate,
+                         int channel_count,
+                         const uint8* extra_data,
+                         size_t extra_data_size,
+                         int64 codec_delay_ns,
+                         int64 seek_preroll_ns,
+                         bool play_audio,
+                         jobject media_crypto) WARN_UNUSED_RESULT;
+
+  // Plays the output buffer right away or save for later playback if |postpone|
+  // is set to true. This call must be called after DequeueOutputBuffer() and
+  // before ReleaseOutputBuffer. The data is extracted from the output buffers
+  // using |index|, |size| and |offset|. Returns the playback head position
+  // expressed in frames.
+  // When |postpone| is set to true, the next PlayOutputBuffer() should have
+  // postpone == false, and it will play two buffers: the postponed one and
+  // the one identified by |index|.
+  int64 PlayOutputBuffer(int index,
+                         size_t size,
+                         size_t offset,
+                         bool postpone = false);
+
+  // Set the volume of the audio output.
+  void SetVolume(double volume);
+
+ private:
+  explicit AudioCodecBridge(const std::string& mime);
+
+  // Configure the java MediaFormat object with the extra codec data passed in.
+  bool ConfigureMediaFormat(jobject j_format,
+                            const AudioCodec& codec,
+                            const uint8* extra_data,
+                            size_t extra_data_size,
+                            int64 codec_delay_ns,
+                            int64 seek_preroll_ns);
+};
+
+// Class for handling video encoding/decoding using android MediaCodec APIs.
+// TODO(qinmin): implement the logic to switch between NDK and SDK
+// MediaCodecBridge.
+class MEDIA_EXPORT VideoCodecBridge : public SdkMediaCodecBridge {
+ public:
+  // See MediaCodecUtil::IsKnownUnaccelerated().
+  static bool IsKnownUnaccelerated(const VideoCodec& codec,
+                                   MediaCodecDirection direction);
+
+  // Create, start, and return a VideoCodecBridge decoder or NULL on failure.
+  static VideoCodecBridge* CreateDecoder(
+      const VideoCodec& codec,  // e.g. media::kCodecVP8
+      bool is_secure,
+      const gfx::Size& size,  // Output frame size.
+      jobject surface,        // Output surface, optional.
+      jobject media_crypto);  // MediaCrypto object, optional.
+
+  // Create, start, and return a VideoCodecBridge encoder or NULL on failure.
+  static VideoCodecBridge* CreateEncoder(
+      const VideoCodec& codec,  // e.g. media::kCodecVP8
+      const gfx::Size& size,    // input frame size
+      int bit_rate,             // bits/second
+      int frame_rate,           // frames/second
+      int i_frame_interval,     // count
+      int color_format);        // MediaCodecInfo.CodecCapabilities.
+
+  void SetVideoBitrate(int bps);
+  void RequestKeyFrameSoon();
+
+  // Returns whether adaptive playback is supported for this object given
+  // the new size.
+  bool IsAdaptivePlaybackSupported(int width, int height);
+
+  // Test-only method to set the return value of IsAdaptivePlaybackSupported().
+  // Without this function, the return value of that function will be device
+  // dependent. If |adaptive_playback_supported| is equal to 0, the return value
+  // will be false. If |adaptive_playback_supported| is larger than 0, the
+  // return value will be true.
+  void set_adaptive_playback_supported_for_testing(
+      int adaptive_playback_supported) {
+    adaptive_playback_supported_for_testing_ = adaptive_playback_supported;
+  }
+
+ private:
+  VideoCodecBridge(const std::string& mime,
+                   bool is_secure,
+                   MediaCodecDirection direction);
+
+  int adaptive_playback_supported_for_testing_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_
diff --git a/media/base/android/sdk_media_codec_bridge_unittest.cc b/media/base/android/sdk_media_codec_bridge_unittest.cc
new file mode 100644
index 0000000..2f6274f
--- /dev/null
+++ b/media/base/android/sdk_media_codec_bridge_unittest.cc
@@ -0,0 +1,300 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "media/base/android/media_codec_util.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
+#include "media/base/decoder_buffer.h"
+#include "media/base/test_data_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace {
+
+// The first frame of
+// http://www.html5rocks.com/en/tutorials/audio/quick/test.mp3
+unsigned char test_mp3[] = {
+    0xff, 0xfb, 0xd2, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x05, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x7e, 0x40,
+    0xc0, 0x19, 0x4a, 0x80, 0x0d, 0x60, 0x48, 0x1b, 0x40, 0xf7, 0xbd, 0xb9,
+    0xd9, 0x40, 0x6f, 0x82, 0x01, 0x8b, 0x17, 0xa0, 0x80, 0xc5, 0x01, 0xad,
+    0x9a, 0xd3, 0x00, 0x12, 0xc0, 0x72, 0x93, 0x67, 0xd0, 0x03, 0x6f, 0xa4,
+    0xc0, 0xc3, 0x23, 0xee, 0x9b, 0xc0, 0xcc, 0x02, 0xa0, 0xa1, 0x30, 0x0c,
+    0x52, 0x2d, 0xfd, 0x6e, 0x08, 0x83, 0x60, 0x40, 0x46, 0x06, 0x4b, 0x20,
+    0x82, 0x82, 0x7f, 0xd4, 0x81, 0xe7, 0x00, 0x64, 0x20, 0x18, 0xec, 0xc2,
+    0x06, 0x57, 0x0f, 0x81, 0x93, 0x0b, 0x00, 0x66, 0xe3, 0xb7, 0xe8, 0x32,
+    0x6e, 0xf0, 0x32, 0xb0, 0x58, 0x0c, 0x7c, 0x3a, 0x03, 0x22, 0x14, 0x80,
+    0xc9, 0x01, 0x80, 0x30, 0x20, 0x14, 0x0c, 0x96, 0x73, 0xfe, 0x9f, 0x6c,
+    0x0c, 0xd2, 0x25, 0x0f, 0xdc, 0x0c, 0x32, 0x43, 0x03, 0x27, 0x87, 0xc0,
+    0xc2, 0xc0, 0x20, 0xfc, 0x42, 0xc5, 0xff, 0xff, 0xd4, 0x80, 0x01, 0x01,
+    0x80, 0xc3, 0x81, 0x01, 0x95, 0x03, 0x28, 0x82, 0xc0, 0xc3, 0x01, 0xa1,
+    0x06, 0x81, 0x87, 0xc2, 0x40, 0x64, 0xc1, 0xf0, 0x12, 0x02, 0xff, 0xf6,
+    0x5b, 0x9f, 0x44, 0xdc, 0xdd, 0x0b, 0x38, 0x59, 0xe0, 0x31, 0x71, 0x60,
+    0x0c, 0xb4, 0x22, 0x03, 0x3b, 0x96, 0x40, 0xc8, 0x63, 0x90, 0x0a, 0x23,
+    0x81, 0x9e, 0x4c, 0x20, 0x65, 0xb3, 0x18, 0x19, 0x6c, 0x42, 0x06, 0x36,
+    0x1d, 0x01, 0x90, 0x87, 0xdf, 0xff, 0xd0, 0x65, 0xa6, 0xea, 0x66, 0xfd,
+    0x40, 0x0c, 0x48, 0x03, 0x1a, 0x09, 0x01, 0x21, 0x98, 0x19, 0x2c, 0x36,
+    0x06, 0x43, 0x21, 0x81, 0x92, 0xca, 0x60, 0x64, 0x70, 0xb8, 0x19, 0x20,
+    0x6c, 0x02, 0x83, 0x80, 0xcb, 0x60, 0x65, 0x32, 0x28, 0x18, 0x64, 0x24,
+    0x06, 0x3a, 0x0c, 0x00, 0xe1, 0x00, 0x18, 0xd0, 0x35, 0xff, 0xff, 0xff,
+    0xe8, 0x32, 0xef, 0xb2, 0x90, 0x65, 0xbb, 0xdd, 0x94, 0x82, 0x0b, 0x4c,
+    0xfa, 0x25, 0xf3, 0x74, 0x13, 0x0f, 0xf8, 0x19, 0x28, 0x84, 0x06, 0x36,
+    0x11, 0x01, 0x20, 0x80, 0x18, 0xb4, 0x52, 0x0e, 0x15, 0x00, 0x30, 0x50,
+    0x0c, 0x84, 0x32, 0x03, 0x11, 0x04, 0x03, 0x48, 0x04, 0x00, 0x00, 0x31,
+    0x21, 0x00, 0x0c, 0x84, 0x18, 0x03, 0x07, 0x85, 0x40, 0xc6, 0xa5, 0x70,
+    0x32, 0xb8, 0x7c, 0x0c, 0x54, 0x04, 0x00, 0xd0, 0x08, 0x59, 0x58, 0x18,
+    0x20, 0x14, 0x06, 0x30, 0x30, 0x01, 0x9b, 0x86, 0x00, 0x6b, 0x54, 0xa8,
+    0x19, 0x8c, 0x2a, 0x06, 0x16, 0x09, 0x01, 0xa0, 0xd0, 0xa0, 0x69, 0x74,
+    0xb8, 0x19, 0xc4, 0x4a, 0xa3, 0xda, 0x9d, 0x1e, 0x4f, 0x05, 0xc0, 0x5b,
+    0x0b, 0x03, 0xc2, 0x76, 0xa3, 0x4f, 0xb9, 0x16, 0xc2, 0x70, 0x41, 0x07,
+    0xa0, 0x84, 0x16, 0x38, 0x4a, 0xc8, 0xaf, 0xee, 0x7f, 0x93, 0xb5, 0x5c,
+    0x39, 0x1e, 0x29, 0xd9, 0x8c, 0x80, 0xb5, 0x80, 0xe6, 0x85, 0xb2, 0x99,
+    0x68, 0x85, 0x46, 0x91, 0x60, 0xdb, 0x06, 0xfa, 0x38, 0x7a, 0xc7, 0xac,
+    0x85, 0xa8, 0xd3, 0xe6, 0x99, 0x3b, 0x66, 0x43, 0x23, 0x1f, 0x84, 0xe1,
+    0x65, 0x5e, 0xbc, 0x84, 0x18, 0x62, 0xe6, 0x42, 0x0b, 0x82, 0xe4, 0xd3,
+    0x42, 0xd2, 0x05, 0x81, 0x4e, 0xe4, 0x9f, 0x8c, 0xc8, 0x7f, 0xa3, 0xe0,
+    0x8d, 0xf1, 0x0f, 0x38, 0xe5, 0x3f, 0xc4, 0x2c, 0x24, 0x65, 0x8d, 0xb9,
+    0x58, 0xac, 0x39, 0x0e, 0x37, 0x99, 0x2e, 0x85, 0xe0, 0xb7, 0x98, 0x41,
+    0x20, 0x38, 0x1b, 0x95, 0x07, 0xfa, 0xa8, 0x9c, 0x21, 0x0f, 0x13, 0x8c,
+    0xa5, 0xc1, 0x76, 0xae, 0x0b, 0xc1, 0x30, 0x27, 0x08, 0xc1, 0xf6, 0x4d,
+    0xce, 0xb4, 0x41, 0x38, 0x1e, 0x82, 0x10, 0x74, 0x45, 0x91, 0x90, 0xff,
+    0x41, 0x8b, 0x62, 0x1a, 0x71, 0xb6, 0x45, 0x63, 0x8c, 0xce, 0xb8, 0x54,
+    0x1b, 0xe8, 0x5d, 0x9e, 0x35, 0x9d, 0x6c, 0xac, 0xe8, 0x83, 0xa1, 0xe9,
+    0x3f, 0x13, 0x74, 0x11, 0x04, 0x10, 0xf1, 0x37, 0x38, 0xc6, 0x00, 0x60,
+    0x27, 0x48, 0x38, 0x85, 0x92, 0x76, 0xb7, 0xf3, 0xa7, 0x1c, 0x4b, 0xf9,
+    0x3b, 0x5a, 0x88, 0xac, 0x60, 0x1b, 0x85, 0x81, 0x16, 0xab, 0x44, 0x17,
+    0x08, 0x2e, 0x0f, 0xd4, 0xe2, 0xde, 0x49, 0xc9, 0xe1, 0xc0, 0xc0, 0xa0,
+    0x7e, 0x73, 0xa1, 0x67, 0xf8, 0xf5, 0x9f, 0xc4, 0x21, 0x50, 0x4f, 0x05,
+    0x2c, 0xfc, 0x5c, 0xaa, 0x85, 0xb0, 0xfa, 0x67, 0x80, 0x7e, 0x0f, 0xfd,
+    0x92, 0x30, 0xd5, 0xa0, 0xd4, 0x05, 0xdd, 0x06, 0x68, 0x1d, 0x6e, 0x4e,
+    0x8b, 0x79, 0xd6, 0xfc, 0xff, 0x2e, 0x6e, 0x7c, 0xba, 0x03, 0x90, 0xd4,
+    0x25, 0x65, 0x8e, 0xe7, 0x3a, 0xd1, 0xd6, 0xdc, 0xf0, 0xbe, 0x12, 0xc4,
+    0x31, 0x08, 0x16, 0x70, 0x31, 0x85, 0x61, 0x38, 0x27, 0x0a, 0x91, 0x5f,
+    0x03, 0x38, 0xeb, 0x37, 0x13, 0x48, 0x41, 0xbe, 0x7f, 0x04, 0x70, 0x62,
+    0x2b, 0x15, 0x91, 0x67, 0x63, 0x4f, 0xad, 0xa7, 0x1d, 0x3f, 0x44, 0x17,
+    0x02, 0x08, 0x0d, 0xf2, 0xfc, 0x03, 0xa0, 0x74, 0x21, 0x8b, 0x07, 0x3a,
+    0x8d, 0x0f, 0x54, 0x58, 0x94, 0x12, 0xc5, 0x62, 0x18, 0xb9, 0x42, 0xf0,
+    0x6c, 0x73, 0xa0, 0x92, 0xad, 0x27, 0x1c, 0x20, 0x0f, 0xc1, 0xca, 0x44,
+    0x87, 0x47, 0xc5, 0x43, 0x23, 0x01, 0xda, 0x23, 0xe2, 0x89, 0x38, 0x9f,
+    0x1f, 0x8d, 0x8c, 0xc6, 0x95, 0xa3, 0x34, 0x21, 0x21, 0x2d, 0x49, 0xea,
+    0x4b, 0x05, 0x85, 0xf5, 0x58, 0x25, 0x13, 0xcd, 0x51, 0x19, 0x1a, 0x88,
+    0xa6, 0x83, 0xd6, 0xd0, 0xbc, 0x25, 0x19, 0x1c, 0x92, 0x12, 0x44, 0x5d,
+    0x1c, 0x04, 0xf1, 0x99, 0xdf, 0x92, 0x8e, 0x09, 0x85, 0xf3, 0x88, 0x82,
+    0x4c, 0x22, 0x17, 0xc5, 0x25, 0x23, 0xed, 0x78, 0xf5, 0x41, 0xd1, 0xe9,
+    0x8a, 0xb3, 0x52, 0xd1, 0x3d, 0x79, 0x81, 0x4d, 0x31, 0x24, 0xf9, 0x38,
+    0x96, 0xbc, 0xf4, 0x8c, 0x25, 0xe9, 0xf2, 0x73, 0x94, 0x85, 0xc2, 0x61,
+    0x6a, 0x34, 0x68, 0x65, 0x78, 0x87, 0xa6, 0x4f};
+
+}  // namespace
+
+namespace media {
+
+// Helper macro to skip the test if MediaCodecBridge isn't available.
+#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
+  do {                                                            \
+    if (!MediaCodecUtil::IsMediaCodecAvailable()) {               \
+      VLOG(0) << "Could not run test - not supported on device."; \
+      return;                                                     \
+    }                                                             \
+  } while (0)
+
+static const int kPresentationTimeBase = 100;
+
+static inline const base::TimeDelta InfiniteTimeOut() {
+  return base::TimeDelta::FromMicroseconds(-1);
+}
+
+void DecodeMediaFrame(VideoCodecBridge* media_codec,
+                      const uint8* data,
+                      size_t data_size,
+                      const base::TimeDelta input_presentation_timestamp,
+                      const base::TimeDelta initial_timestamp_lower_bound) {
+  base::TimeDelta input_pts = input_presentation_timestamp;
+  base::TimeDelta timestamp = initial_timestamp_lower_bound;
+  base::TimeDelta new_timestamp;
+  for (int i = 0; i < 10; ++i) {
+    int input_buf_index = -1;
+    MediaCodecStatus status =
+        media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
+    ASSERT_EQ(MEDIA_CODEC_OK, status);
+
+    media_codec->QueueInputBuffer(input_buf_index, data, data_size,
+                                  input_presentation_timestamp);
+
+    size_t unused_offset = 0;
+    size_t size = 0;
+    bool eos = false;
+    int output_buf_index = -1;
+    status = media_codec->DequeueOutputBuffer(
+        InfiniteTimeOut(), &output_buf_index, &unused_offset, &size,
+        &new_timestamp, &eos, nullptr);
+
+    if (status == MEDIA_CODEC_OK && output_buf_index > 0) {
+      media_codec->ReleaseOutputBuffer(output_buf_index, false);
+    }
+    // Output time stamp should not be smaller than old timestamp.
+    ASSERT_TRUE(new_timestamp >= timestamp);
+    input_pts += base::TimeDelta::FromMicroseconds(33000);
+    timestamp = new_timestamp;
+  }
+}
+
+TEST(SdkMediaCodecBridgeTest, Initialize) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<media::MediaCodecBridge> media_codec;
+  media_codec.reset(VideoCodecBridge::CreateDecoder(
+      kCodecH264, false, gfx::Size(640, 480), nullptr, nullptr));
+}
+
+TEST(SdkMediaCodecBridgeTest, DoNormal) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<media::AudioCodecBridge> media_codec;
+  media_codec.reset(AudioCodecBridge::Create(kCodecMP3));
+
+  ASSERT_TRUE(media_codec->ConfigureAndStart(kCodecMP3, 44100, 2, nullptr, 0, 0,
+                                             0, false, nullptr));
+
+  int input_buf_index = -1;
+  MediaCodecStatus status =
+      media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
+  ASSERT_EQ(MEDIA_CODEC_OK, status);
+  ASSERT_GE(input_buf_index, 0);
+
+  int64 input_pts = kPresentationTimeBase;
+  media_codec->QueueInputBuffer(input_buf_index, test_mp3, sizeof(test_mp3),
+                                base::TimeDelta::FromMicroseconds(++input_pts));
+
+  status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
+  media_codec->QueueInputBuffer(input_buf_index, test_mp3, sizeof(test_mp3),
+                                base::TimeDelta::FromMicroseconds(++input_pts));
+
+  status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
+  media_codec->QueueEOS(input_buf_index);
+
+  input_pts = kPresentationTimeBase;
+  bool eos = false;
+  while (!eos) {
+    size_t unused_offset = 0;
+    size_t size = 0;
+    base::TimeDelta timestamp;
+    int output_buf_index = -1;
+    status = media_codec->DequeueOutputBuffer(InfiniteTimeOut(),
+                                              &output_buf_index, &unused_offset,
+                                              &size, &timestamp, &eos, nullptr);
+    switch (status) {
+      case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
+        FAIL();
+        return;
+
+      case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
+        continue;
+
+      case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
+        continue;
+
+      default:
+        break;
+    }
+    ASSERT_GE(output_buf_index, 0);
+    EXPECT_LE(1u, size);
+    if (!eos)
+      EXPECT_EQ(++input_pts, timestamp.InMicroseconds());
+    ASSERT_LE(input_pts, kPresentationTimeBase + 2);
+  }
+  ASSERT_EQ(input_pts, kPresentationTimeBase + 2);
+}
+
+TEST(SdkMediaCodecBridgeTest, InvalidVorbisHeader) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<media::AudioCodecBridge> media_codec;
+  media_codec.reset(AudioCodecBridge::Create(kCodecVorbis));
+
+  // The first byte of the header is not 0x02.
+  uint8 invalid_first_byte[] = {0x00, 0xff, 0xff, 0xff, 0xff};
+  EXPECT_FALSE(media_codec->ConfigureAndStart(
+      kCodecVorbis, 44100, 2, invalid_first_byte, sizeof(invalid_first_byte), 0,
+      0, false, nullptr));
+
+  // Size of the header does not match with the data we passed in.
+  uint8 invalid_size[] = {0x02, 0x01, 0xff, 0x01, 0xff};
+  EXPECT_FALSE(media_codec->ConfigureAndStart(
+      kCodecVorbis, 44100, 2, invalid_size, sizeof(invalid_size), 0, 0, false,
+      nullptr));
+
+  // Size of the header is too large.
+  size_t large_size = 8 * 1024 * 1024 + 2;
+  uint8* very_large_header = new uint8[large_size];
+  very_large_header[0] = 0x02;
+  for (size_t i = 1; i < large_size - 1; ++i)
+    very_large_header[i] = 0xff;
+  very_large_header[large_size - 1] = 0xfe;
+  EXPECT_FALSE(media_codec->ConfigureAndStart(kCodecVorbis, 44100, 2,
+                                              very_large_header, 0x80000000, 0,
+                                              0, false, nullptr));
+  delete[] very_large_header;
+}
+
+TEST(SdkMediaCodecBridgeTest, InvalidOpusHeader) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<media::AudioCodecBridge> media_codec;
+  media_codec.reset(AudioCodecBridge::Create(kCodecOpus));
+  uint8 dummy_extra_data[] = {0, 0};
+
+  // Extra Data is NULL.
+  EXPECT_FALSE(media_codec->ConfigureAndStart(kCodecOpus, 48000, 2, nullptr, 0,
+                                              -1, 0, false, nullptr));
+
+  // Codec Delay is < 0.
+  EXPECT_FALSE(media_codec->ConfigureAndStart(
+      kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data), -1, 0,
+      false, nullptr));
+
+  // Seek Preroll is < 0.
+  EXPECT_FALSE(media_codec->ConfigureAndStart(
+      kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data), 0, -1,
+      false, nullptr));
+}
+
+TEST(SdkMediaCodecBridgeTest, PresentationTimestampsDoNotDecrease) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<VideoCodecBridge> media_codec(VideoCodecBridge::CreateDecoder(
+      kCodecVP8, false, gfx::Size(320, 240), nullptr, nullptr));
+  EXPECT_TRUE(media_codec.get());
+  scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vp8-I-frame-320x240");
+  DecodeMediaFrame(media_codec.get(), buffer->data(), buffer->data_size(),
+                   base::TimeDelta(), base::TimeDelta());
+
+  // Simulate a seek to 10 seconds, and each chunk has 2 I-frames.
+  std::vector<uint8> chunk(buffer->data(),
+                           buffer->data() + buffer->data_size());
+  chunk.insert(chunk.end(), buffer->data(),
+               buffer->data() + buffer->data_size());
+  media_codec->Reset();
+  DecodeMediaFrame(media_codec.get(), &chunk[0], chunk.size(),
+                   base::TimeDelta::FromMicroseconds(10000000),
+                   base::TimeDelta::FromMicroseconds(9900000));
+
+  // Simulate a seek to 5 seconds.
+  media_codec->Reset();
+  DecodeMediaFrame(media_codec.get(), &chunk[0], chunk.size(),
+                   base::TimeDelta::FromMicroseconds(5000000),
+                   base::TimeDelta::FromMicroseconds(4900000));
+}
+
+TEST(SdkMediaCodecBridgeTest, CreateUnsupportedCodec) {
+  EXPECT_EQ(nullptr, AudioCodecBridge::Create(kUnknownAudioCodec));
+  EXPECT_EQ(nullptr, VideoCodecBridge::CreateDecoder(kUnknownVideoCodec, false,
+                                                     gfx::Size(320, 240),
+                                                     nullptr, nullptr));
+}
+
+}  // namespace media
diff --git a/media/base/android/video_decoder_job.cc b/media/base/android/video_decoder_job.cc
index d43f450..d74ba4ae 100644
--- a/media/base/android/video_decoder_job.cc
+++ b/media/base/android/video_decoder_job.cc
@@ -7,8 +7,8 @@
 #include "base/bind.h"
 #include "base/lazy_instance.h"
 #include "base/threading/thread.h"
-#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_drm_bridge.h"
+#include "media/base/android/sdk_media_codec_bridge.h"
 
 namespace media {
 
diff --git a/media/media.gyp b/media/media.gyp
index e463802..4b25ca1 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -1182,12 +1182,12 @@
       ],
       'sources': [
         'base/android/access_unit_queue_unittest.cc',
-        'base/android/media_codec_bridge_unittest.cc',
         'base/android/media_codec_decoder_unittest.cc',
         'base/android/media_codec_player_unittest.cc',
         'base/android/media_drm_bridge_unittest.cc',
         'base/android/media_player_bridge_unittest.cc',
         'base/android/media_source_player_unittest.cc',
+        'base/android/sdk_media_codec_bridge_unittest.cc',
         'base/android/test_data_factory.cc',
         'base/android/test_data_factory.h',
         'base/android/test_statistics.h',
@@ -1807,6 +1807,7 @@
             'base/android/java/src/org/chromium/media/AudioManagerAndroid.java',
             'base/android/java/src/org/chromium/media/AudioRecordInput.java',
             'base/android/java/src/org/chromium/media/MediaCodecBridge.java',
+            'base/android/java/src/org/chromium/media/MediaCodecUtil.java',
             'base/android/java/src/org/chromium/media/MediaDrmBridge.java',
             'base/android/java/src/org/chromium/media/MediaPlayerBridge.java',
             'base/android/java/src/org/chromium/media/MediaPlayerListener.java',
@@ -1856,6 +1857,8 @@
             'base/android/media_codec_player.h',
             'base/android/media_codec_video_decoder.cc',
             'base/android/media_codec_video_decoder.h',
+            'base/android/media_codec_util.cc',
+            'base/android/media_codec_util.h',
             'base/android/media_common_android.h',
             'base/android/media_decoder_job.cc',
             'base/android/media_decoder_job.h',
@@ -1882,12 +1885,28 @@
             'base/android/media_task_runner.h',
             'base/android/media_url_interceptor.h',
             'base/android/provision_fetcher.h',
+            'base/android/sdk_media_codec_bridge.cc',
+            'base/android/sdk_media_codec_bridge.h',
             'base/android/video_decoder_job.cc',
             'base/android/video_decoder_job.h',
             'base/android/webaudio_media_codec_bridge.cc',
             'base/android/webaudio_media_codec_bridge.h',
             'base/android/webaudio_media_codec_info.h',
           ],
+          'conditions': [
+            # Only 64 bit builds are using android-21 NDK library, check common.gypi
+            ['target_arch=="arm64" or target_arch=="x64" or target_arch=="mips64el"', {
+              'sources': [
+                'base/android/ndk_media_codec_bridge.cc',
+                'base/android/ndk_media_codec_bridge.h',
+              ],
+              'link_settings': {
+                'libraries': [
+                  '-lmediandk',
+                ],
+              },
+            }],
+          ],
           'dependencies': [
             '../base/base.gyp:base',
             '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
diff --git a/net/base/filename_util_internal.cc b/net/base/filename_util_internal.cc
index 57183dc..4cfedcd8 100644
--- a/net/base/filename_util_internal.cc
+++ b/net/base/filename_util_internal.cc
@@ -31,7 +31,12 @@
     size_t length = filename->size();
     size_t pos = filename->find_last_not_of(FILE_PATH_LITERAL(" ."));
     filename->resize((pos == std::string::npos) ? 0 : (pos + 1));
+#if defined(OS_WIN)
     base::TrimWhitespace(*filename, base::TRIM_TRAILING, filename);
+#else
+    base::TrimWhitespaceASCII(*filename, base::TRIM_TRAILING, filename);
+#endif
+
     if (filename->empty())
       return;
     size_t trimmed = length - filename->size();
diff --git a/net/test/python_utils_unittest.cc b/net/test/python_utils_unittest.cc
index 57b7f476..a713e72f 100644
--- a/net/test/python_utils_unittest.cc
+++ b/net/test/python_utils_unittest.cc
@@ -61,6 +61,6 @@
   cmd_line.AppendArg(python_cmd);
   std::string output;
   EXPECT_TRUE(base::GetAppOutput(cmd_line, &output));
-  base::TrimWhitespace(output, base::TRIM_TRAILING, &output);
+  base::TrimWhitespaceASCII(output, base::TRIM_TRAILING, &output);
   EXPECT_EQ(input, output);
 }
diff --git a/pdf/document_loader.cc b/pdf/document_loader.cc
index 868a8c4..5bbed1a0 100644
--- a/pdf/document_loader.cc
+++ b/pdf/document_loader.cc
@@ -36,8 +36,8 @@
         std::string range_end;
         if (pos != std::string::npos)
           range_end = range.substr(pos + 1);
-        TrimWhitespaceASCII(range, base::TRIM_LEADING, &range);
-        TrimWhitespaceASCII(range_end, base::TRIM_LEADING, &range_end);
+        base::TrimWhitespaceASCII(range, base::TRIM_LEADING, &range);
+        base::TrimWhitespaceASCII(range_end, base::TRIM_LEADING, &range_end);
         *start = atoi(range.c_str());
         *end = atoi(range_end.c_str());
         return true;
@@ -145,7 +145,7 @@
         if (semi_colon_pos != std::string::npos) {
           type = type.substr(0, semi_colon_pos);
         }
-        TrimWhitespace(type, base::TRIM_ALL, &type);
+        TrimWhitespaceASCII(type, base::TRIM_ALL, &type);
       } else if (base::LowerCaseEqualsASCII(it.name(), "content-disposition")) {
         disposition = it.values();
       }
diff --git a/sync/BUILD.gn b/sync/BUILD.gn
index 2f0f730..71fc74a 100644
--- a/sync/BUILD.gn
+++ b/sync/BUILD.gn
@@ -879,10 +879,10 @@
   android_library("sync_java_test_support") {
     testonly = true
     deps = [
+      "android:sync_java",
       "//base:base_java",
       "//base:base_java_test_support",
       "//third_party/jsr-305:jsr_305_javalib",
-      "android:sync_java",
     ]
     DEPRECATED_java_in_dir = "test/android/javatests/src"
   }
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 4238e835..5ebb58b 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -752,8 +752,6 @@
 
 crbug.com/484370 [ Win Debug ] svg/custom/gradient-userSpaceOnUse-with-percentage.svg [ Failure ]
 
-crbug.com/116710 [ Win Debug ] transforms/3d/point-mapping/3d-point-mapping-preserve-3d.html [ Failure ]
-
 # Printing Layout broken in these tests.
 crbug.com/377696 printing/setPrinting.html [ Skip ]
 crbug.com/377696 printing/width-overflow.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/compositing/backface-visibility-transformed-expected.png b/third_party/WebKit/LayoutTests/compositing/backface-visibility-transformed-expected.png
index 6e07a2e..bc9a785 100644
--- a/third_party/WebKit/LayoutTests/compositing/backface-visibility-transformed-expected.png
+++ b/third_party/WebKit/LayoutTests/compositing/backface-visibility-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
index 598901a..e1f5c92 100644
--- a/third_party/WebKit/LayoutTests/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/dom/node-filter-use-counters.html b/third_party/WebKit/LayoutTests/fast/dom/node-filter-use-counters.html
new file mode 100644
index 0000000..14a3ae1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/node-filter-use-counters.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>NodeFilter UseCounters</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+test(function() {
+  var NodeFilterIsFunction = 1059; // From UseCounter.h
+
+  assert_false(internals.isUseCounted(document, NodeFilterIsFunction));
+
+  var filterCalled = false;
+  var filter = function() {
+    assert_true(internals.isUseCounted(document, NodeFilterIsFunction));
+    filter.called = true;
+  };
+
+  var iterator = document.createNodeIterator(document, 0, filter);
+  iterator.filter.acceptNode(document);
+  assert_true(filter.called);
+}, 'NodeFilter UseCounter for callback function');
+
+test(function() {
+  var NodeFilterIsObject = 1060; // From UseCounter.h
+
+  assert_false(internals.isUseCounted(document, NodeFilterIsObject));
+
+  var filter = {
+    acceptNodeCalled: false,
+    acceptNode: function() {
+      assert_true(internals.isUseCounted(document, NodeFilterIsObject));
+      filter.called = true;
+    }
+  };
+
+  var iterator = document.createNodeIterator(document, 0, filter);
+  iterator.filter.acceptNode(document);
+  assert_true(filter.called);
+}, 'NodeFilter UseCounter for callback function');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments-expected.txt b/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments-expected.txt
index 86022b4..e5ff6cd 100644
--- a/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments-expected.txt
@@ -4,6 +4,8 @@
 
 
 Successfully obtained FileSystem: file__0:Temporary
+PASS fileSystem.root.moveTo(null) threw exception TypeError: Failed to execute 'moveTo' on 'Entry': parameter 1 is not of type 'DirectoryEntry'..
+PASS fileSystem.root.copyTo(null) threw exception TypeError: Failed to execute 'copyTo' on 'Entry': parameter 1 is not of type 'DirectoryEntry'..
 PASS writer.error is null
 PASS writer.write(null) threw exception TypeError: Failed to execute 'write' on 'FileWriter': parameter 1 is not of type 'Blob'..
 PASS writer.error is null
diff --git a/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments.html b/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments.html
index 19495e4..ba87454 100644
--- a/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments.html
+++ b/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments.html
@@ -18,6 +18,8 @@
     window.fileSystem = fs;
     debug("Successfully obtained FileSystem: " + fileSystem.name);
 
+    shouldThrow("fileSystem.root.moveTo(null)");
+    shouldThrow("fileSystem.root.copyTo(null)");
     fileSystem.root.getFile("/test", { create: true }, function(entry) {
         entry.createWriter(function(writer) {
             window.writer = writer;
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/backface-visibility-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/backface-visibility-transformed-expected.png
new file mode 100644
index 0000000..6e07a2e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/compositing/backface-visibility-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/geometry/vertical-scroll-composited-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/geometry/vertical-scroll-composited-expected.png
new file mode 100644
index 0000000..96a745f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/compositing/geometry/vertical-scroll-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
new file mode 100644
index 0000000..598901a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/nested-reflection-animated-expected.png
new file mode 100644
index 0000000..38634564
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/nested-reflection-animated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/transform-inside-reflection-expected.png
new file mode 100644
index 0000000..0cf6a2a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/transform-inside-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/android/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
new file mode 100644
index 0000000..b905bb7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
new file mode 100644
index 0000000..f7a07e9e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/android/media/video-layer-crash-expected.png
new file mode 100644
index 0000000..5b53bbe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/android/media/video-transformed-expected.png
new file mode 100644
index 0000000..49346e41
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/media/video-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/general/perspective-units-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/general/perspective-units-expected.png
new file mode 100644
index 0000000..7cb846c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/general/perspective-units-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
new file mode 100644
index 0000000..81d32f2b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
new file mode 100644
index 0000000..c455c60a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-expected.png
new file mode 100644
index 0000000..2f2d944f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
new file mode 100644
index 0000000..d772043
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
new file mode 100644
index 0000000..3848ee814
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/platform/android/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
new file mode 100644
index 0000000..7fb3b24
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png
index d0dbdc0..d79b934 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png
index 96a745f1..2f459985 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png
index bf790f1..b45d024 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png
index 38634564..6c65c589 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png
index 0cf6a2a..f0154a6a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
index b905bb7..b6e878a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
index f7a07e9e..0102e495 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png
index 5b53bbe..6a0526f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png
index 49346e41..7e0e513 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png
index 7cb846c..710f11652 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
index 81d32f2b..07b957e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
index c455c60a..b1a3574 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png
index 2f2d944f..bc9146b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
index d772043..4f99c115 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
index 3848ee814..69827c7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
index a341ef37..86086f55 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-expected.png
index f101ab3..8948eadf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
index 90f2b8a..819ca38 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
index 03cfd4d5..509260e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
index 06a112ba..e019cae 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-expected.png
index 04c7734aae..9326d29 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
index 5eda092..344a6306 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
index 0cc9602..4eeba60 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
index 4ed0094..eb91ba1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-expected.png
index 5e6426a..6466c73 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
index 1ed76505..ad4bf90a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
index 3c043c20..675e272 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-deep-expected.png
index 19a67dc..b215d68 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png
index 77b7cb6..59358cd 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/vertical-scroll-composited-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/vertical-scroll-composited-expected.png
index 96a745f1..2f459985 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/vertical-scroll-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/vertical-scroll-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/perpendicular-layer-sorting-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/perpendicular-layer-sorting-expected.png
index bf790f1..b45d024 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/perpendicular-layer-sorting-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/perpendicular-layer-sorting-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png
index d1ef18e..d27567f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png
index f1f5eda..cad9908 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/transform-inside-reflection-expected.png
index 1bc5fb79..bb10b7d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/transform-inside-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/transform-inside-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
index 861a2c5..cb048616 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png
index 7090363..878ae797 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/general/perspective-units-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/general/perspective-units-expected.png
index 64a3bac..6a608a73 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/general/perspective-units-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/general/perspective-units-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
index 6ea69e6..4040a8a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
index fb7ba570..bef14c1e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-expected.png
index 7841001..933a1929 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
index d4d4e9b..9442da9b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
index aa223a8..c110b94 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/geometry/layer-due-to-layer-children-expected.png
index 5ac8156..d484463e 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/geometry/layer-due-to-layer-children-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/geometry/layer-due-to-layer-children-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/nested-reflection-animated-expected.png
index f5027d61..19427c2 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/nested-reflection-animated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/nested-reflection-animated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/transform-inside-reflection-expected.png
index b5ba0d6..c805f41 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/transform-inside-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/transform-inside-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
index 214782df..00f9db8 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
index 5a3c8eb6..363c4b8 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/media/video-layer-crash-expected.png
index faae7af..9be8946e 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/media/video-layer-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/media/video-transformed-expected.png
index 8e2b2f6..d83de2f8 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/media/video-transformed-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/media/video-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/general/transform-origin-z-change-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/general/transform-origin-z-change-expected.png
new file mode 100644
index 0000000..31128b99
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/general/transform-origin-z-change-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
index 010752cf..45d36d6 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
index eface4b..707929c8 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-deep-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-deep-expected.png
index 7888087..a37a800 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png
index 000f41e..72d1b311 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/vertical-scroll-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/vertical-scroll-composited-expected.png
index 3adcda9..f08c2b5 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/vertical-scroll-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/vertical-scroll-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/perpendicular-layer-sorting-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/perpendicular-layer-sorting-expected.png
index 2f7a463..a505f0c8 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/perpendicular-layer-sorting-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/perpendicular-layer-sorting-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png
index 9b8c8a0..87a94b2 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-animated-expected.png
index 0c4e95c0..dc86fe2 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-animated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-animated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/transform-inside-reflection-expected.png
index d57757b..a3403cc6 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/transform-inside-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/transform-inside-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
index d052d94..b16a1966 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png
index 678bc1c..dfa30bab 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/general/perspective-units-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/general/perspective-units-expected.png
index e11aec8..14b2a3b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/general/perspective-units-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/general/perspective-units-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
index 9f42f39..1e1f09b6 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
index 121fe2f..cd61512 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-expected.png
index 688d518a..2563581 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
index 78a00780..e7aeea4 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
index 08647a2..66fbeb0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/transforms/3d/general/transform-origin-z-change-expected.png b/third_party/WebKit/LayoutTests/transforms/3d/general/transform-origin-z-change-expected.png
index 31128b99..d761571 100644
--- a/third_party/WebKit/LayoutTests/transforms/3d/general/transform-origin-z-change-expected.png
+++ b/third_party/WebKit/LayoutTests/transforms/3d/general/transform-origin-z-change-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
index 7fb3b24..b474717 100644
--- a/third_party/WebKit/LayoutTests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
Binary files differ
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp b/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp
index 45e5517..2346c0bf 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp
@@ -36,6 +36,7 @@
 #include "bindings/core/v8/V8Node.h"
 #include "core/dom/Node.h"
 #include "core/dom/NodeFilter.h"
+#include "core/frame/UseCounter.h"
 #include "wtf/OwnPtr.h"
 
 namespace blink {
@@ -73,6 +74,7 @@
     v8::Local<v8::Function> callback;
     v8::Local<v8::Value> receiver;
     if (filter->IsFunction()) {
+        UseCounter::countIfNotPrivateScript(isolate, callingExecutionContext(isolate), UseCounter::NodeFilterIsFunction);
         callback = v8::Local<v8::Function>::Cast(filter);
         receiver = v8::Undefined(isolate);
     } else {
@@ -86,6 +88,7 @@
             exceptionState.throwTypeError("NodeFilter object does not have an acceptNode function");
             return NodeFilter::FILTER_REJECT;
         }
+        UseCounter::countIfNotPrivateScript(isolate, callingExecutionContext(isolate), UseCounter::NodeFilterIsObject);
         callback = v8::Local<v8::Function>::Cast(value);
         receiver = filter;
     }
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index b80e959b..315a91b 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -49,6 +49,8 @@
   deps = [
     ":make_core_generated",
     ":prerequisites",
+    "inspector:instrumentation_sources",
+    "inspector:protocol_sources",
     "//gin",
     "//skia",
     "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated",
@@ -60,8 +62,6 @@
     "//third_party/npapi",
     "//third_party/qcms",
     "//third_party/sqlite",
-    "inspector:instrumentation_sources",
-    "inspector:protocol_sources",
 
     # FIXME: don't depend on bindings/modules http://crbug.com/358074
     "//third_party/WebKit/Source/bindings/modules:bindings_modules_generated",
@@ -97,9 +97,9 @@
   ]
   deps = [
     ":make_core_generated",
-    "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated",
     "inspector:instrumentation_sources",
     "inspector:protocol_sources",
+    "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated",
 
     # FIXME: don't depend on bindings_modules http://crbug.com/358074
     "//third_party/WebKit/Source/bindings/modules/v8:bindings_modules_generated",
@@ -423,6 +423,8 @@
   public_deps = [
     ":make_core_generated",
     ":prerequisites",
+    "inspector:instrumentation_sources",
+    "inspector:protocol_sources",
     "//gin",
     "//skia",
     "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated",
@@ -434,8 +436,6 @@
     "//third_party/npapi",
     "//third_party/qcms",
     "//third_party/sqlite",
-    "inspector:instrumentation_sources",
-    "inspector:protocol_sources",
 
     # FIXME: don't depend on bindings/modules http://crbug.com/358074
     "//third_party/WebKit/Source/bindings/modules:bindings_modules_generated",
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 445fa206..ecc81deb 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -914,6 +914,8 @@
         RTCPeerConnectionSetRemoteDescriptionLegacyNoFailureCallback = 1056,
         RTCPeerConnectionSetRemoteDescriptionLegacyCompliant = 1057,
         RTCPeerConnectionGetStatsLegacyNonCompliant = 1058,
+        NodeFilterIsFunction = 1059,
+        NodeFilterIsObject = 1060,
 
         // Add new features immediately above this line. Don't change assigned
         // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/modules/filesystem/Entry.idl b/third_party/WebKit/Source/modules/filesystem/Entry.idl
index b00bc1d..d7162ef1 100644
--- a/third_party/WebKit/Source/modules/filesystem/Entry.idl
+++ b/third_party/WebKit/Source/modules/filesystem/Entry.idl
@@ -39,8 +39,8 @@
     readonly attribute DOMFileSystem filesystem;
 
     void getMetadata(MetadataCallback successCallback, optional ErrorCallback errorCallback);
-    [LegacyInterfaceTypeChecking] void moveTo(DirectoryEntry parent, [TreatUndefinedAs=NullString] optional DOMString? name, optional EntryCallback successCallback, optional ErrorCallback errorCallback);
-    [LegacyInterfaceTypeChecking] void copyTo(DirectoryEntry parent, [TreatUndefinedAs=NullString] optional DOMString? name, optional EntryCallback successCallback, optional ErrorCallback errorCallback);
+    void moveTo(DirectoryEntry parent, [TreatUndefinedAs=NullString] optional DOMString? name, optional EntryCallback successCallback, optional ErrorCallback errorCallback);
+    void copyTo(DirectoryEntry parent, [TreatUndefinedAs=NullString] optional DOMString? name, optional EntryCallback successCallback, optional ErrorCallback errorCallback);
     DOMString toURL();
     void remove(VoidCallback successCallback, optional ErrorCallback errorCallback);
     void getParent(optional EntryCallback successCallback, optional ErrorCallback errorCallback);
diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn
index c0c5565..7de949b 100644
--- a/third_party/boringssl/BUILD.gn
+++ b/third_party/boringssl/BUILD.gn
@@ -74,6 +74,7 @@
     if (is_android) {
       rebased_android_toolchain_root =
           rebase_path(android_toolchain_root, root_build_dir)
+
       # Else /usr/bin/as gets picked up.
       asmflags += [ "-B${rebased_android_toolchain_root}/bin" ]
     }
diff --git a/third_party/cacheinvalidation/BUILD.gn b/third_party/cacheinvalidation/BUILD.gn
index 6035d5dc..083c6ff 100644
--- a/third_party/cacheinvalidation/BUILD.gn
+++ b/third_party/cacheinvalidation/BUILD.gn
@@ -115,11 +115,11 @@
 
   deps = [
     ":cacheinvalidation",
+    "src/google/cacheinvalidation:cacheinvalidation_proto_cpp",
     "//base",
     "//base/test:run_all_unittests",
     "//testing/gmock",
     "//testing/gtest",
-    "src/google/cacheinvalidation:cacheinvalidation_proto_cpp",
   ]
 }
 
diff --git a/third_party/libvpx_new/BUILD.gn b/third_party/libvpx_new/BUILD.gn
index 26aff0a..e2a0320 100644
--- a/third_party/libvpx_new/BUILD.gn
+++ b/third_party/libvpx_new/BUILD.gn
@@ -55,6 +55,7 @@
     if (is_android) {
       rebased_android_toolchain_root =
           rebase_path(android_toolchain_root, root_build_dir)
+
       # Else /usr/bin/as gets picked up.
       asmflags += [ "-B${rebased_android_toolchain_root}/bin" ]
     }
diff --git a/tools/gn/example/BUILD.gn b/tools/gn/example/BUILD.gn
index 58af9523..a18390e 100644
--- a/tools/gn/example/BUILD.gn
+++ b/tools/gn/example/BUILD.gn
@@ -8,8 +8,8 @@
   ]
 
   deps = [
-    ":hello_static",
     ":hello_shared",
+    ":hello_static",
   ]
 }
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index abd8810..5ea6df9 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -63782,6 +63782,8 @@
   <int value="1057"
       label="RTCPeerConnectionSetRemoteDescriptionLegacyCompliant"/>
   <int value="1058" label="RTCPeerConnectionGetStatsLegacyNonCompliant"/>
+  <int value="1059" label="NodeFilterIsFunction"/>
+  <int value="1060" label="NodeFilterIsObject"/>
 </enum>
 
 <enum name="FetchRequestMode" type="int">
diff --git a/ui/base/clipboard/clipboard_util_win.cc b/ui/base/clipboard/clipboard_util_win.cc
index c0c05b0..ed5fe5f 100644
--- a/ui/base/clipboard/clipboard_util_win.cc
+++ b/ui/base/clipboard/clipboard_util_win.cc
@@ -446,7 +446,7 @@
       fragment_start != std::string::npos &&
       fragment_end != std::string::npos) {
     *html = cf_html.substr(fragment_start, fragment_end - fragment_start);
-    base::TrimWhitespace(*html, base::TRIM_ALL, html);
+    base::TrimWhitespaceASCII(*html, base::TRIM_ALL, html);
   }
 }
 
@@ -464,7 +464,7 @@
       size_t src_start = line_start + src_url_str.length();
       if (src_end != std::string::npos && src_start != std::string::npos) {
         *base_url = cf_html.substr(src_start, src_end - src_start);
-        base::TrimWhitespace(*base_url, base::TRIM_ALL, base_url);
+        base::TrimWhitespaceASCII(*base_url, base::TRIM_ALL, base_url);
       }
     }
   }
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index b057366..fbc801d 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -137,8 +137,8 @@
   settings.initial_debug_state.SetRecordRenderingStats(
       command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
 
-  settings.use_property_trees =
-      command_line->HasSwitch(cc::switches::kEnableCompositorPropertyTrees);
+  if (command_line->HasSwitch(cc::switches::kDisableCompositorPropertyTrees))
+    settings.use_property_trees = false;
   settings.use_zero_copy = IsUIZeroCopyEnabled();
 
   settings.renderer_settings.use_rgba_4444_textures =
diff --git a/ui/gfx/font_fallback_win.cc b/ui/gfx/font_fallback_win.cc
index 1612f3c7..c578ba8 100644
--- a/ui/gfx/font_fallback_win.cc
+++ b/ui/gfx/font_fallback_win.cc
@@ -206,8 +206,8 @@
     const size_t index = font_names->back().find('(');
     if (index != std::string::npos) {
       font_names->back().resize(index);
-      base::TrimWhitespace(font_names->back(), base::TRIM_TRAILING,
-                           &font_names->back());
+      base::TrimWhitespaceASCII(font_names->back(), base::TRIM_TRAILING,
+                                &font_names->back());
     }
   }
 }