diff --git a/.gitignore b/.gitignore
index d8a09d0..1736faeb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -406,6 +406,7 @@
 /third_party/valgrind
 /third_party/v4l2capture
 /third_party/wayland/src
+/third_party/wayland-protocols/src
 /third_party/webdriver/pylib
 /third_party/webdriver/python/selenium
 /third_party/webgl
diff --git a/BUILD.gn b/BUILD.gn
index 3aeba3c..1637b803 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -603,7 +603,7 @@
     deps += [ "//components/proximity_auth:proximity_auth_unittests" ]
   }
 
-  if (!is_component_build && (is_win || is_linux)) {
+  if (is_win || is_linux) {
     deps += [ "//mash:all" ]
   }
 
diff --git a/DEPS b/DEPS
index 97377a7..d028a714 100644
--- a/DEPS
+++ b/DEPS
@@ -39,11 +39,11 @@
   # 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': '362c900625dc2ece854678455776b711c1e44c04',
+  'skia_revision': '9323dc6a72de301f23e1187adc2365395b4b23d8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'd8db4d6236058d45d02c5b96c441497a96f7eb6c',
+  'v8_revision': '2472199b500c7d5f1bd57447d87f98df0bf45f83',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -148,7 +148,7 @@
     Var('chromium_git') + '/external/snappy.git' + '@' + '762bb32f0c9d2f31ba4958c7c0933d22e80c20bf',
 
   'src/tools/gyp':
-    Var('chromium_git') + '/external/gyp.git' + '@' + 'f4d65e35719cfe02257ece126c109cfc053ca35c',
+    Var('chromium_git') + '/external/gyp.git' + '@' + 'e2313c02ad7b6d589b38fe578f5d39970a9bbc20',
 
   'src/tools/swarming_client':
    Var('chromium_git') + '/external/swarming.client.git' + '@' +  Var('swarming_revision'),
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 0841c6e..b7e300b 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1525,7 +1525,7 @@
   }
 
   if (is_android) {
-    apk_deps = [
+    deps += [
       ":base_java",
       ":base_java_unittest_support",
     ]
diff --git a/base/files/file.cc b/base/files/file.cc
index 47b9f88f..036d43b 100644
--- a/base/files/file.cc
+++ b/base/files/file.cc
@@ -50,13 +50,12 @@
       async_(false) {
 }
 
-File::File(RValue other)
-    : file_(other.object->TakePlatformFile()),
-      tracing_path_(other.object->tracing_path_),
-      error_details_(other.object->error_details()),
-      created_(other.object->created()),
-      async_(other.object->async_) {
-}
+File::File(File&& other)
+    : file_(other.TakePlatformFile()),
+      tracing_path_(other.tracing_path_),
+      error_details_(other.error_details()),
+      created_(other.created()),
+      async_(other.async_) {}
 
 File::~File() {
   // Go through the AssertIOAllowed logic.
@@ -72,15 +71,14 @@
   return file.Pass();
 }
 
-File& File::operator=(RValue other) {
-  if (this != other.object) {
-    Close();
-    SetPlatformFile(other.object->TakePlatformFile());
-    tracing_path_ = other.object->tracing_path_;
-    error_details_ = other.object->error_details();
-    created_ = other.object->created();
-    async_ = other.object->async_;
-  }
+File& File::operator=(File&& other) {
+  DCHECK_NE(this, &other);
+  Close();
+  SetPlatformFile(other.TakePlatformFile());
+  tracing_path_ = other.tracing_path_;
+  error_details_ = other.error_details();
+  created_ = other.created();
+  async_ = other.async_;
   return *this;
 }
 
diff --git a/base/files/file.h b/base/files/file.h
index 66b78fa5..ba4dd34 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -53,7 +53,7 @@
 // to the OS is not considered const, even if there is no apparent change to
 // member variables.
 class BASE_EXPORT File {
-  MOVE_ONLY_TYPE_FOR_CPP_03(File, RValue)
+  MOVE_ONLY_TYPE_FOR_CPP_03(File)
 
  public:
   // FLAG_(OPEN|CREATE).* are mutually exclusive. You should specify exactly one
@@ -169,16 +169,14 @@
   // Creates an object with a specific error_details code.
   explicit File(Error error_details);
 
-  // Move constructor for C++03 move emulation of this type.
-  File(RValue other);
+  File(File&& other);
 
   ~File();
 
   // Takes ownership of |platform_file|.
   static File CreateForAsyncHandle(PlatformFile platform_file);
 
-  // Move operator= for C++03 move emulation of this type.
-  File& operator=(RValue other);
+  File& operator=(File&& other);
 
   // Creates or opens the given file.
   void Initialize(const FilePath& path, uint32 flags);
diff --git a/base/memory/scoped_vector.h b/base/memory/scoped_vector.h
index 250947f..5bfd94e3 100644
--- a/base/memory/scoped_vector.h
+++ b/base/memory/scoped_vector.h
@@ -20,7 +20,7 @@
 // we have support for moveable types inside containers).
 template <class T>
 class ScopedVector {
-  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedVector, RValue)
+  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedVector)
 
  public:
   typedef typename std::vector<T*>::allocator_type allocator_type;
@@ -39,10 +39,10 @@
 
   ScopedVector() {}
   ~ScopedVector() { clear(); }
-  ScopedVector(RValue other) { swap(*other.object); }
+  ScopedVector(ScopedVector&& other) { swap(other); }
 
-  ScopedVector& operator=(RValue rhs) {
-    swap(*rhs.object);
+  ScopedVector& operator=(ScopedVector&& rhs) {
+    swap(rhs);
     return *this;
   }
 
diff --git a/base/move.h b/base/move.h
index ce8a8e1..fe0517e 100644
--- a/base/move.h
+++ b/base/move.h
@@ -9,7 +9,7 @@
 
 #include "base/compiler_specific.h"
 
-// Macro with the boilerplate that makes a type move-only in C++03.
+// Macro with the boilerplate that makes a type move-only in C++11.
 //
 // USAGE
 //
@@ -24,121 +24,21 @@
 //   * Used as the right-hand side of an assignment
 //   * Returned from a function
 //
-// Each class will still need to define their own "move constructor" and "move
-// operator=" to make this useful.  Here's an example of the macro, the move
-// constructor, and the move operator= from the scoped_ptr class:
+// Each class will still need to define their own move constructor and move
+// operator= to make this useful.  Here's an example of the macro, the move
+// constructor, and the move operator= from a hypothetical scoped_ptr class:
 //
 //  template <typename T>
 //  class scoped_ptr {
-//     MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
+//    MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type);
 //   public:
-//    scoped_ptr(RValue& other) : ptr_(other.release()) { }
-//    scoped_ptr& operator=(RValue& other) {
-//      swap(other);
+//    scoped_ptr(scoped_ptr&& other) : ptr_(other.release()) { }
+//    scoped_ptr& operator=(scoped_ptr&& other) {
+//      reset(other.release());
 //      return *this;
 //    }
 //  };
 //
-// Note that the constructor must NOT be marked explicit.
-//
-// For consistency, the second parameter to the macro should always be RValue
-// unless you have a strong reason to do otherwise.  It is only exposed as a
-// macro parameter so that the move constructor and move operator= don't look
-// like they're using a phantom type.
-//
-//
-// HOW THIS WORKS
-//
-// For a thorough explanation of this technique, see:
-//
-//   http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor
-//
-// The summary is that we take advantage of 2 properties:
-//
-//   1) non-const references will not bind to r-values.
-//   2) C++ can apply one user-defined conversion when initializing a
-//      variable.
-//
-// The first lets us disable the copy constructor and assignment operator
-// by declaring private version of them with a non-const reference parameter.
-//
-// For l-values, direct initialization still fails like in
-// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment
-// operators are private.
-//
-// For r-values, the situation is different. The copy constructor and
-// assignment operator are not viable due to (1), so we are trying to call
-// a non-existent constructor and non-existing operator= rather than a private
-// one.  Since we have not committed an error quite yet, we can provide an
-// alternate conversion sequence and a constructor.  We add
-//
-//   * a private struct named "RValue"
-//   * a user-defined conversion "operator RValue()"
-//   * a "move constructor" and "move operator=" that take the RValue& as
-//     their sole parameter.
-//
-// Only r-values will trigger this sequence and execute our "move constructor"
-// or "move operator=."  L-values will match the private copy constructor and
-// operator= first giving a "private in this context" error.  This combination
-// gives us a move-only type.
-//
-// For signaling a destructive transfer of data from an l-value, we provide a
-// method named Pass() which creates an r-value for the current instance
-// triggering the move constructor or move operator=.
-//
-// Other ways to get r-values is to use the result of an expression like a
-// function call.
-//
-// Here's an example with comments explaining what gets triggered where:
-//
-//    class Foo {
-//      MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue);
-//
-//     public:
-//       ... API ...
-//       Foo(RValue other);           // Move constructor.
-//       Foo& operator=(RValue rhs);  // Move operator=
-//    };
-//
-//    Foo MakeFoo();  // Function that returns a Foo.
-//
-//    Foo f;
-//    Foo f_copy(f);  // ERROR: Foo(Foo&) is private in this context.
-//    Foo f_assign;
-//    f_assign = f;   // ERROR: operator=(Foo&) is private in this context.
-//
-//
-//    Foo f(MakeFoo());      // R-value so alternate conversion executed.
-//    Foo f_copy(f.Pass());  // R-value so alternate conversion executed.
-//    f = f_copy.Pass();     // R-value so alternate conversion executed.
-//
-//
-// IMPLEMENTATION SUBTLETIES WITH RValue
-//
-// The RValue struct is just a container for a pointer back to the original
-// object. It should only ever be created as a temporary, and no external
-// class should ever declare it or use it in a parameter.
-//
-// It is tempting to want to use the RValue type in function parameters, but
-// excluding the limited usage here for the move constructor and move
-// operator=, doing so would mean that the function could take both r-values
-// and l-values equially which is unexpected.  See COMPARED To Boost.Move for
-// more details.
-//
-// An alternate, and incorrect, implementation of the RValue class used by
-// Boost.Move makes RValue a fieldless child of the move-only type. RValue&
-// is then used in place of RValue in the various operators.  The RValue& is
-// "created" by doing *reinterpret_cast<RValue*>(this).  This has the appeal
-// of never creating a temporary RValue struct even with optimizations
-// disabled.  Also, by virtue of inheritance you can treat the RValue
-// reference as if it were the move-only type itself.  Unfortunately,
-// using the result of this reinterpret_cast<> is actually undefined behavior
-// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer
-// will generate non-working code.
-//
-// In optimized builds, both implementations generate the same assembly so we
-// choose the one that adheres to the standard.
-//
 //
 // WHY HAVE typedef void MoveOnlyTypeForCPP03
 //
@@ -148,84 +48,19 @@
 // easy and automatic in helper templates for Callback<>/Bind().
 // See IsMoveOnlyType template and its usage in base/callback_internal.h
 // for more details.
-//
-//
-// COMPARED TO C++11
-//
-// In C++11, you would implement this functionality using an r-value reference
-// and our .Pass() method would be replaced with a call to std::move().
-//
-// This emulation also has a deficiency where it uses up the single
-// user-defined conversion allowed by C++ during initialization.  This can
-// cause problems in some API edge cases.  For instance, in scoped_ptr, it is
-// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a
-// value of type scoped_ptr<Child> even if you add a constructor to
-// scoped_ptr<> that would make it look like it should work.  C++11 does not
-// have this deficiency.
-//
-//
-// COMPARED TO Boost.Move
-//
-// Our implementation similar to Boost.Move, but we keep the RValue struct
-// private to the move-only type, and we don't use the reinterpret_cast<> hack.
-//
-// In Boost.Move, RValue is the boost::rv<> template.  This type can be used
-// when writing APIs like:
-//
-//   void MyFunc(boost::rv<Foo>& f)
-//
-// that can take advantage of rv<> to avoid extra copies of a type.  However you
-// would still be able to call this version of MyFunc with an l-value:
-//
-//   Foo f;
-//   MyFunc(f);  // Uh oh, we probably just destroyed |f| w/o calling Pass().
-//
-// unless someone is very careful to also declare a parallel override like:
-//
-//   void MyFunc(const Foo& f)
-//
-// that would catch the l-values first.  This was declared unsafe in C++11 and
-// a C++11 compiler will explicitly fail MyFunc(f).  Unfortunately, we cannot
-// ensure this in C++03.
-//
-// Since we have no need for writing such APIs yet, our implementation keeps
-// RValue private and uses a .Pass() method to do the conversion instead of
-// trying to write a version of "std::move()." Writing an API like std::move()
-// would require the RValue struct to be public.
-//
-//
-// CAVEATS
-//
-// If you include a move-only type as a field inside a class that does not
-// explicitly declare a copy constructor, the containing class's implicit
-// copy constructor will change from Containing(const Containing&) to
-// Containing(Containing&).  This can cause some unexpected errors.
-//
-//   http://llvm.org/bugs/show_bug.cgi?id=11528
-//
-// The workaround is to explicitly declare your copy constructor.
-//
-#define MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \
- private: \
-  struct rvalue_type { \
-    explicit rvalue_type(type* object) : object(object) {} \
-    type* object; \
-  }; \
-  type(type&); \
-  void operator=(type&); \
- public: \
-  operator rvalue_type() { return rvalue_type(this); } \
-  type Pass() WARN_UNUSED_RESULT { return type(rvalue_type(this)); } \
-  typedef void MoveOnlyTypeForCPP03; \
- private:
 
-#define MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \
- private: \
-  type(const type&); \
-  void operator=(const type&); \
- public: \
+#define MOVE_ONLY_TYPE_FOR_CPP_03(type) \
+  MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type)
+
+#define MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type)   \
+ private:                                                       \
+  type(const type&) = delete;                                   \
+  void operator=(const type&) = delete;                         \
+                                                                \
+ public:                                                        \
   type&& Pass() WARN_UNUSED_RESULT { return std::move(*this); } \
-  typedef void MoveOnlyTypeForCPP03; \
+  typedef void MoveOnlyTypeForCPP03;                            \
+                                                                \
  private:
 
 #define TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \
diff --git a/base/process/process.h b/base/process/process.h
index 6ff7d76..36f8574 100644
--- a/base/process/process.h
+++ b/base/process/process.h
@@ -32,19 +32,17 @@
 // the process dies, and it may be reused by the system, which means that it may
 // end up pointing to the wrong process.
 class BASE_EXPORT Process {
-  MOVE_ONLY_TYPE_FOR_CPP_03(Process, RValue)
+  MOVE_ONLY_TYPE_FOR_CPP_03(Process)
 
  public:
   explicit Process(ProcessHandle handle = kNullProcessHandle);
 
-  // Move constructor for C++03 move emulation of this type.
-  Process(RValue other);
+  Process(Process&& other);
 
   // The destructor does not terminate the process.
   ~Process();
 
-  // Move operator= for C++03 move emulation of this type.
-  Process& operator=(RValue other);
+  Process& operator=(Process&& other);
 
   // Returns an object for the current process.
   static Process Current();
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index 2320ce7..7b2eed78 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -217,16 +217,14 @@
 Process::~Process() {
 }
 
-Process::Process(RValue other)
-    : process_(other.object->process_) {
-  other.object->Close();
+Process::Process(Process&& other) : process_(other.process_) {
+  other.Close();
 }
 
-Process& Process::operator=(RValue other) {
-  if (this != other.object) {
-    process_ = other.object->process_;
-    other.object->Close();
-  }
+Process& Process::operator=(Process&& other) {
+  DCHECK_NE(this, &other);
+  process_ = other.process_;
+  other.Close();
   return *this;
 }
 
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index 818864f..e7f35b3 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -25,21 +25,20 @@
   CHECK_NE(handle, ::GetCurrentProcess());
 }
 
-Process::Process(RValue other)
-    : is_current_process_(other.object->is_current_process_),
-      process_(other.object->process_.Take()) {
-  other.object->Close();
+Process::Process(Process&& other)
+    : is_current_process_(other.is_current_process_),
+      process_(other.process_.Take()) {
+  other.Close();
 }
 
 Process::~Process() {
 }
 
-Process& Process::operator=(RValue other) {
-  if (this != other.object) {
-    process_.Set(other.object->process_.Take());
-    is_current_process_ = other.object->is_current_process_;
-    other.object->Close();
-  }
+Process& Process::operator=(Process&& other) {
+  DCHECK_NE(this, &other);
+  process_.Set(other.process_.Take());
+  is_current_process_ = other.is_current_process_;
+  other.Close();
   return *this;
 }
 
diff --git a/base/security_unittest.cc b/base/security_unittest.cc
index a9c73f7c..cd387fb 100644
--- a/base/security_unittest.cc
+++ b/base/security_unittest.cc
@@ -85,7 +85,7 @@
   }
 }
 
-#if defined(OS_IOS) || defined(OS_WIN) || defined(THREAD_SANITIZER) || defined(OS_MACOSX)
+#if defined(OS_IOS) || defined(OS_WIN) || defined(OS_MACOSX)
 #define MAYBE_NewOverflow DISABLED_NewOverflow
 #else
 #define MAYBE_NewOverflow NewOverflow
diff --git a/base/win/scoped_handle.h b/base/win/scoped_handle.h
index d1eb1d6..3e8a748 100644
--- a/base/win/scoped_handle.h
+++ b/base/win/scoped_handle.h
@@ -36,7 +36,7 @@
 //     this explicitly is necessary because of bug 528394 and VC++ 2015.
 template <class Traits, class Verifier>
 class GenericScopedHandle {
-  MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle, RValue)
+  MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle)
 
  public:
   typedef typename Traits::Handle Handle;
@@ -47,9 +47,9 @@
     Set(handle);
   }
 
-  // Move constructor for C++03 move emulation of this type.
-  GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) {
-    Set(other.object->Take());
+  GenericScopedHandle(GenericScopedHandle&& other)
+      : handle_(Traits::NullHandle()) {
+    Set(other.Take());
   }
 
   ~GenericScopedHandle() {
@@ -60,11 +60,9 @@
     return Traits::IsHandleValid(handle_);
   }
 
-  // Move operator= for C++03 move emulation of this type.
-  GenericScopedHandle& operator=(RValue other) {
-    if (this != other.object) {
-      Set(other.object->Take());
-    }
+  GenericScopedHandle& operator=(GenericScopedHandle&& other) {
+    DCHECK_NE(this, &other);
+    Set(other.Take());
     return *this;
   }
 
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py
index 08577cde..460d157 100755
--- a/build/android/gyp/apkbuilder.py
+++ b/build/android/gyp/apkbuilder.py
@@ -45,9 +45,10 @@
                       required=True)
   parser.add_argument('--dex-file',
                       help='Path to the classes.dex to use')
-  # TODO(agrieve): Switch this to be a list of files rather than a directory.
-  parser.add_argument('--native-libs-dir',
-                      help='Directory containing native libraries to include',
+  parser.add_argument('--native-libs',
+                      action='append',
+                      help='GYP-list of native libraries to include. '
+                           'Can be specified multiple times.',
                       default=[])
   parser.add_argument('--android-abi',
                       help='Android architecture to use for native libraries')
@@ -62,18 +63,17 @@
       options.uncompressed_assets)
   options.native_lib_placeholders = build_utils.ParseGypList(
       options.native_lib_placeholders)
+  all_libs = []
+  for gyp_list in options.native_libs:
+    all_libs.extend(build_utils.ParseGypList(gyp_list))
+  options.native_libs = all_libs
 
-  if not options.android_abi and (options.native_libs_dir or
+  if not options.android_abi and (options.native_libs or
                                   options.native_lib_placeholders):
-    raise Exception('Must specify --android-abi with --native-libs-dir')
+    raise Exception('Must specify --android-abi with --native-libs')
   return options
 
 
-def _ListSubPaths(path):
-  """Returns a list of full paths to all files in the given path."""
-  return [os.path.join(path, name) for name in os.listdir(path)]
-
-
 def _SplitAssetPath(path):
   """Returns (src, dest) given an asset path in the form src[:dest]."""
   path_parts = path.split(':')
@@ -122,10 +122,7 @@
   args = build_utils.ExpandFileArgs(args)
   options = _ParseArgs(args)
 
-  native_libs = []
-  if options.native_libs_dir:
-    native_libs = _ListSubPaths(options.native_libs_dir)
-    native_libs.sort()
+  native_libs = sorted(options.native_libs)
 
   input_paths = [options.resource_apk, __file__] + native_libs
   if options.dex_file:
diff --git a/build/android/gyp/pack_relocations.py b/build/android/gyp/pack_relocations.py
index e112265..1a4824ae 100755
--- a/build/android/gyp/pack_relocations.py
+++ b/build/android/gyp/pack_relocations.py
@@ -64,6 +64,8 @@
   parser.add_option('--libraries', action='append',
       help='List of libraries')
   parser.add_option('--stamp', help='Path to touch on success')
+  parser.add_option('--filelistjson',
+                    help='Output path of filelist.json to write')
 
   options, _ = parser.parse_args(args)
   enable_packing = (options.enable_packing == '1' and
@@ -80,10 +82,12 @@
 
   build_utils.MakeDirectory(options.packed_libraries_dir)
 
+  output_paths = []
   for library in libraries:
     library_path = os.path.join(options.stripped_libraries_dir, library)
     output_path = os.path.join(
         options.packed_libraries_dir, os.path.basename(library))
+    output_paths.append(output_path)
 
     if enable_packing and library not in exclude_packing_set:
       PackLibraryRelocations(options.android_pack_relocations,
@@ -92,6 +96,9 @@
     else:
       CopyLibraryUnchanged(library_path, output_path)
 
+  if options.filelistjson:
+    build_utils.WriteJson({ 'files': output_paths }, options.filelistjson)
+
   if options.depfile:
     build_utils.WriteDepfile(
         options.depfile,
diff --git a/build/android/incremental_install/create_install_script.py b/build/android/incremental_install/create_install_script.py
index ff8e2c1..3de4ed67 100755
--- a/build/android/incremental_install/create_install_script.py
+++ b/build/android/incremental_install/create_install_script.py
@@ -37,14 +37,14 @@
 # Exported to allow test runner to be able to install incremental apks.
 def GetInstallParameters():
   apk_path = {apk_path}
-  lib_dir = {lib_dir}
+  native_libs = {native_libs}
   dex_files = {dex_files}
   splits = {splits}
   show_proguard_warning = {show_proguard_warning}
 
   return dict(apk_path=_ResolvePath(apk_path),
               dex_files=[_ResolvePath(p) for p in dex_files],
-              lib_dir=_ResolvePath(lib_dir),
+              native_libs=[_ResolvePath(p) for p in native_libs],
               show_proguard_warning=show_proguard_warning,
               splits=[_ResolvePath(p) for p in splits])
 
@@ -57,8 +57,8 @@
       _ResolvePath(cmd_path),
       '--output-directory', _ResolvePath(output_directory),
   ]
-  if params['lib_dir']:
-    cmd_args.extend(('--lib-dir', params['lib_dir']))
+  for native_lib in params['native_libs']:
+    cmd_args.extend(('--native_lib', native_lib))
   for dex_path in params['dex_files']:
     cmd_args.extend(('--dex-file', dex_path))
   for split in params['splits']:
@@ -92,8 +92,11 @@
                       default=[],
                       help='A glob matching the apk splits. '
                            'Can be specified multiple times.')
-  parser.add_argument('--lib-dir',
-                      help='Path to native libraries directory.')
+  parser.add_argument('--native-libs',
+                      action='append',
+                      default=[],
+                      help='GYP-list of paths to native libraries. Can be '
+                      'repeated.')
   parser.add_argument('--dex-file',
                       action='append',
                       default=[],
@@ -108,6 +111,10 @@
 
   options = parser.parse_args(args)
   options.dex_files += build_utils.ParseGypList(options.dex_file_list)
+  all_libs = []
+  for gyp_list in options.native_libs:
+    all_libs.extend(build_utils.ParseGypList(gyp_list))
+  options.native_libs = all_libs
   return options
 
 
@@ -125,7 +132,7 @@
       'cmd_path': pformat(relativize(installer_path)),
       'apk_path': pformat(relativize(options.apk_path)),
       'output_directory': pformat(relativize(options.output_directory)),
-      'lib_dir': pformat(relativize(options.lib_dir)),
+      'native_libs': pformat([relativize(p) for p in options.native_libs]),
       'dex_files': pformat([relativize(p) for p in options.dex_files]),
       'show_proguard_warning': pformat(options.show_proguard_warning),
       'splits': pformat([relativize(p) for p in options.splits]),
diff --git a/build/android/incremental_install/installer.py b/build/android/incremental_install/installer.py
index 54fb73ef..e418cdb 100755
--- a/build/android/incremental_install/installer.py
+++ b/build/android/incremental_install/installer.py
@@ -11,7 +11,6 @@
 import logging
 import os
 import posixpath
-import shutil
 import sys
 
 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))
@@ -65,7 +64,7 @@
   logging.info('Uninstall took %s seconds.', main_timer.GetDelta())
 
 
-def Install(device, apk, split_globs=None, lib_dir=None, dex_files=None,
+def Install(device, apk, split_globs=None, native_libs=None, dex_files=None,
             enable_device_cache=True, use_concurrency=True,
             show_proguard_warning=False):
   """Installs the given incremental apk and all required supporting files.
@@ -74,7 +73,7 @@
     device: A DeviceUtils instance.
     apk: The path to the apk, or an ApkHelper instance.
     split_globs: Glob patterns for any required apk splits (optional).
-    lib_dir: Directory containing the app's native libraries (optional).
+    native_libs: List of app's native libraries (optional).
     dex_files: List of .dex.jar files that comprise the app's Dalvik code.
     enable_device_cache: Whether to enable on-device caching of checksums.
     use_concurrency: Whether to speed things up using multiple threads.
@@ -105,11 +104,14 @@
 
   # Push .so and .dex files to the device (if they have changed).
   def do_push_files():
-    if lib_dir:
+    if native_libs:
       push_native_timer.Start()
-      device_lib_dir = posixpath.join(device_incremental_dir, 'lib')
-      device.PushChangedFiles([(lib_dir, device_lib_dir)],
-                              delete_device_stale=True)
+      with build_utils.TempDir() as temp_dir:
+        device_lib_dir = posixpath.join(device_incremental_dir, 'lib')
+        for path in native_libs:
+          os.symlink(path, os.path.join(temp_dir, os.path.basename(path)))
+        device.PushChangedFiles([(temp_dir, device_lib_dir)],
+                                delete_device_stale=True)
       push_native_timer.Stop(log=False)
 
     if dex_files:
@@ -121,7 +123,7 @@
         # Ensure no two files have the same name.
         transformed_names = _TransformDexPaths(dex_files)
         for src_path, dest_name in zip(dex_files, transformed_names):
-          shutil.copyfile(src_path, os.path.join(temp_dir, dest_name))
+          os.symlink(src_path, os.path.join(temp_dir, dest_name))
         device.PushChangedFiles([(temp_dir, device_dex_dir)],
                                 delete_device_stale=True)
       push_dex_timer.Stop(log=False)
@@ -201,10 +203,14 @@
                       dest='splits',
                       help='A glob matching the apk splits. '
                            'Can be specified multiple times.')
-  parser.add_argument('--lib-dir',
-                      help='Path to native libraries directory.')
-  parser.add_argument('--dex-files',
-                      help='List of dex files to push.',
+  parser.add_argument('--native_lib',
+                      dest='native_libs',
+                      help='Path to native library (repeatable)',
+                      action='append',
+                      default=[])
+  parser.add_argument('--dex-file',
+                      dest='dex_files',
+                      help='Path to dex files (repeatable)',
                       action='append',
                       default=[])
   parser.add_argument('-d', '--device', dest='device',
@@ -270,7 +276,7 @@
   if args.uninstall:
     Uninstall(device, apk.GetPackageName())
   else:
-    Install(device, apk, split_globs=args.splits, lib_dir=args.lib_dir,
+    Install(device, apk, split_globs=args.splits, native_libs=args.native_libs,
             dex_files=args.dex_files, enable_device_cache=args.cache,
             use_concurrency=args.threading,
             show_proguard_warning=args.show_proguard_warning)
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 2567d863..527a447 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -667,7 +667,8 @@
 #   output_apk_path: Output path for the generated .apk.
 #   native_lib_placeholders: List of placeholder filenames to add to the apk
 #     (optional).
-#   native_libs_dir: Directory containing native libraries.
+#   native_libs: List of native libraries.
+#   native_libs_filearg: @FileArg() of additionaly native libraries.
 #   write_asset_list: Adds an extra file to the assets, which contains a list of
 #     all other asset files.
 template("package_apk") {
@@ -689,9 +690,7 @@
       "//tools/android/md5sum",
     ]  # Used when deploying APKs
 
-    inputs = [
-      invoker.resource_packaged_apk_path,
-    ]
+    inputs = invoker.native_libs + [ invoker.resource_packaged_apk_path ]
     if (defined(invoker.dex_path)) {
       inputs += [ invoker.dex_path ]
     }
@@ -727,13 +726,16 @@
       _rebased_dex_path = rebase_path(invoker.dex_path, root_build_dir)
       args += [ "--dex-file=$_rebased_dex_path" ]
     }
-    if (defined(invoker.native_libs_dir) || _native_lib_placeholders != []) {
+    if (invoker.native_libs != [] || defined(invoker.native_libs_filearg) ||
+        _native_lib_placeholders != []) {
       args += [ "--android-abi=$android_app_abi" ]
     }
-    if (defined(invoker.native_libs_dir)) {
-      _rebased_native_libs_dir =
-          rebase_path(invoker.native_libs_dir, root_build_dir)
-      args += [ "--native-libs-dir=$_rebased_native_libs_dir/$android_app_abi" ]
+    if (invoker.native_libs != []) {
+      _rebased_native_libs = rebase_path(invoker.native_libs, root_build_dir)
+      args += [ "--native-libs=$_rebased_native_libs" ]
+    }
+    if (defined(invoker.native_libs_filearg)) {
+      args += [ "--native-libs=${invoker.native_libs_filearg}" ]
     }
     if (_native_lib_placeholders != []) {
       args += [ "--native-lib-placeholders=$_native_lib_placeholders" ]
@@ -840,6 +842,10 @@
   if (defined(invoker.incremental_deps)) {
     _incremental_deps = invoker.incremental_deps
   }
+  _native_libs = []
+  if (defined(invoker.native_libs)) {
+    _native_libs = invoker.native_libs
+  }
 
   # TODO(agrieve): Remove support for asset_location in favor of using
   # android_assets() everywhere (http://crbug.com/547162).
@@ -1014,10 +1020,11 @@
                              "assets_build_config",
                              "emma_instrument",
                              "native_lib_placeholders",
-                             "native_libs_dir",
+                             "native_libs_filearg",
                              "write_asset_list",
                            ])
     deps = _deps + [ ":${_package_resources_target_name}" ]
+    native_libs = _native_libs
 
     if (defined(_dex_path)) {
       dex_path = _dex_path
@@ -1045,8 +1052,12 @@
           get_label_info(_dex_target, "target_gen_dir") + "/bootstrap.dex"
     }
 
+    native_libs = []
+
     # http://crbug.com/384638
-    if (defined(invoker.native_libs_dir)) {
+    _has_native_libs =
+        defined(invoker.native_libs_filearg) || _native_libs != []
+    if (_has_native_libs) {
       native_lib_placeholders = [ "libfix.crbug.384638.so" ]
     }
 
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 704ca6d..fe8e24f 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1293,30 +1293,29 @@
     _srcjar_deps += invoker.srcjar_deps
   }
 
-  _load_library_from_apk = false
+  _use_chromium_linker =
+      defined(invoker.use_chromium_linker) && invoker.use_chromium_linker &&
+      chromium_linker_supported
+  _enable_relocation_packing =
+      defined(invoker.enable_relocation_packing) &&
+      invoker.enable_relocation_packing && _use_chromium_linker
+  _load_library_from_apk =
+      defined(invoker.load_library_from_apk) && invoker.load_library_from_apk
+
+  assert(_use_chromium_linker || true)  # Mark as used.
+  assert(_enable_relocation_packing || true)  # Mark as used.
+
+  assert(
+      !_load_library_from_apk || _use_chromium_linker,
+      "Loading library from the apk requires use" + " of the Chromium linker.")
 
   # The dependency that makes the chromium linker, if any is needed.
-  _chromium_linker_dep = []
+  _native_libs_deps = []
 
   if (defined(invoker.native_libs) && invoker.native_libs != []) {
-    _use_chromium_linker = false
-    if (defined(invoker.use_chromium_linker)) {
-      _use_chromium_linker =
-          invoker.use_chromium_linker && chromium_linker_supported
-      _chromium_linker_dep = [ "//base/android/linker:chromium_android_linker" ]
-    }
-
-    if (defined(invoker.load_library_from_apk) &&
-        invoker.load_library_from_apk) {
-      _load_library_from_apk = true
-      assert(_use_chromium_linker,
-             "Loading library from the apk requires use" +
-                 " of the Chromium linker.")
-    }
-
     if (is_component_build) {
       _native_libs += [ "$root_shlib_dir/libc++_shared.so" ]
-      _chromium_linker_dep += [ "//build/android:cpplib_stripped" ]
+      _native_libs_deps += [ "//build/android:cpplib_stripped" ]
     }
 
     # Allow native_libs to be in the form "foo.so" or "foo.cr.so"
@@ -1326,21 +1325,6 @@
             _first_ext_removed,
             "$root_shlib_dir/{{source_name_part}}$shlib_extension")
 
-    # Add in target_cpu so that other architectures are not accidentally
-    # included when switching target_cpu without doing a clean build.
-    _native_libs_dir = gen_dir + "/lib-$target_cpu"
-
-    if (_use_chromium_linker) {
-      _native_libs +=
-          [ "$root_shlib_dir/libchromium_android_linker$shlib_extension" ]
-    }
-
-    _enable_relocation_packing = false
-    if (_use_chromium_linker && defined(invoker.enable_relocation_packing) &&
-        invoker.enable_relocation_packing) {
-      _enable_relocation_packing = true
-    }
-
     _native_lib_version_rule = ""
     if (defined(invoker.native_lib_version_rule)) {
       _native_lib_version_rule = invoker.native_lib_version_rule
@@ -1387,7 +1371,7 @@
     build_config = _build_config
     android_manifest = _android_manifest
 
-    deps = _chromium_linker_dep + _android_manifest_deps
+    deps = _native_libs_deps + _android_manifest_deps
     if (defined(invoker.deps)) {
       deps += invoker.deps
     }
@@ -1592,62 +1576,67 @@
     }
   }
 
-  if (_native_libs != []) {
+  _native_libs_file_arg_dep = ":$build_config_target"
+  _native_libs_file_arg = "@FileArg($_rebased_build_config:native:libraries)"
+
+  if (_native_libs != [] && _enable_relocation_packing) {
     _prepare_native_target_name = "${_template_name}__prepare_native"
+    _native_libs_dir = "$gen_dir/packed-libs"
+    _native_libs_json = "$gen_dir/packed-libs/filelist.json"
+    _rebased_native_libs_json = rebase_path(_native_libs_json, root_build_dir)
+
+    _native_libs_file_arg_dep = ":$_prepare_native_target_name"
+    _native_libs_file_arg = "@FileArg($_rebased_native_libs_json:files)"
+
     action(_prepare_native_target_name) {
       forward_variables_from(invoker,
                              [
-                               "data_deps",
+                               "deps",
                                "public_deps",
                              ])
       script = "//build/android/gyp/pack_relocations.py"
-      packed_libraries_dir = "$_native_libs_dir/$android_app_abi"
       depfile = "$target_gen_dir/$target_name.d"
       outputs = [
         depfile,
+        _native_libs_json,
       ]
 
-      inputs = _native_libs
-      deps = _chromium_linker_dep
+      inputs = _native_libs + [ _build_config ]
 
-      inputs += [ _build_config ]
-      deps += [ ":$build_config_target" ]
-
-      rebased_gdbserver = rebase_path(android_gdbserver, root_build_dir)
-      skip_packing_list = [
-        rebased_gdbserver,
-        "libchromium_android_linker.so",
+      deps += _native_libs_deps
+      deps += [
+        ":$build_config_target",
+        relocation_packer_target,
       ]
 
-      enable_packing_arg = 0
-      if (_enable_relocation_packing) {
-        enable_packing_arg = 1
-        deps += [ relocation_packer_target ]
-      }
-
       args = [
         "--depfile",
         rebase_path(depfile, root_build_dir),
-        "--enable-packing=$enable_packing_arg",
-        "--exclude-packing-list=$skip_packing_list",
+        "--enable-packing=1",
         "--android-pack-relocations",
         rebase_path(relocation_packer_exe, root_build_dir),
         "--stripped-libraries-dir",
         rebase_path(root_build_dir, root_build_dir),
         "--packed-libraries-dir",
-        rebase_path(packed_libraries_dir, root_build_dir),
+        rebase_path(_native_libs_dir, root_build_dir),
         "--libraries=@FileArg(${_rebased_build_config}:native:libraries)",
-        "--clear-dir",
+        "--filelistjson=$_rebased_native_libs_json",
       ]
+    }
+  }
 
-      if (defined(invoker.deps)) {
-        deps += invoker.deps
-      }
+  _extra_native_libs = []
+  _extra_native_libs_deps = []
+  if (_native_libs != []) {
+    if (is_debug) {
+      _extra_native_libs = [ android_gdbserver ]
+    }
 
-      if (is_debug) {
-        inputs += [ android_gdbserver ]
-        args += [ "--libraries=$rebased_gdbserver" ]
-      }
+    if (_use_chromium_linker) {
+      _extra_native_libs =
+          [ "$root_shlib_dir/libchromium_android_linker$shlib_extension" ]
+      _extra_native_libs_deps +=
+          [ "//base/android/linker:chromium_android_linker" ]
     }
   }
 
@@ -1660,6 +1649,7 @@
                              "deps",
                              "extensions_to_not_compress",
                              "language_splits",
+                             "public_deps",
                              "shared_resources",
                              "write_asset_list",
                            ])
@@ -1700,13 +1690,14 @@
             ]
 
     if (_native_libs != [] && !_create_abi_split) {
-      native_libs_dir = _native_libs_dir
+      deps += _native_libs_deps + _extra_native_libs_deps +
+              [ _native_libs_file_arg_dep ]
+      native_libs_filearg = _native_libs_file_arg
+      native_libs = _extra_native_libs
 
       # Placeholders necessary for some older devices.
       # http://crbug.com/395038
       forward_variables_from(invoker, [ "native_lib_placeholders" ])
-
-      deps += [ ":$_prepare_native_target_name" ]
     }
   }
 
@@ -1738,17 +1729,22 @@
       keystore_path = _keystore_path
       keystore_password = _keystore_password
 
-      native_libs_dir = _native_libs_dir
-
       # Placeholders necessary for some older devices.
       # http://crbug.com/395038
-      forward_variables_from(invoker, [ "native_lib_placeholders" ])
+      deps = []
+      forward_variables_from(invoker,
+                             [
+                               "deps",
+                               "native_lib_placeholders",
+                               "public_deps",
+                             ])
 
-      deps = [
-        ":${_manifest_rule}",
-        ":${_prepare_native_target_name}",
-      ]
-      incremental_deps = deps
+      incremental_deps = deps + [ ":$_manifest_rule" ]
+      deps = []
+      deps = incremental_deps + _native_libs_deps + _extra_native_libs_deps +
+             [ _native_libs_file_arg_dep ]
+      native_libs_filearg = _native_libs_file_arg
+      native_libs = _extra_native_libs
     }
   }
 
@@ -1757,7 +1753,7 @@
     script = "//build/android/incremental_install/create_install_script.py"
     depfile = "$target_gen_dir/$target_name.d"
     deps = [
-      ":$build_config_target",
+      _native_libs_file_arg_dep,
     ]
 
     _generated_script_path =
@@ -1783,9 +1779,13 @@
     if (_proguard_enabled) {
       args += [ "--show-proguard-warning" ]
     }
-    if (defined(_native_libs_dir)) {
-      _rebased_native_libs_dir = rebase_path(_native_libs_dir, root_build_dir)
-      args += [ "--lib-dir=$_rebased_native_libs_dir/$android_app_abi" ]
+    if (defined(_native_libs_file_arg)) {
+      args += [ "--native-libs=$_native_libs_file_arg" ]
+    }
+    if (_extra_native_libs != []) {
+      _rebased_extra_native_libs =
+          rebase_path(_extra_native_libs, root_build_dir)
+      args += [ "--native-libs=$_rebased_extra_native_libs" ]
     }
     if (_create_density_splits) {
       args += [ "--split=${_rebased_apk_path_no_ext}-density-*.apk" ]
@@ -1804,7 +1804,8 @@
     forward_variables_from(invoker, [ "data_deps" ])
 
     # device/commands is used by the installer script to push files via .zip.
-    data_deps += [ "//build/android/pylib/device/commands" ]
+    data_deps += [ "//build/android/pylib/device/commands" ] +
+                 _native_libs_deps + _extra_native_libs_deps
 
     # Since the _incremental.apk does not include use .so nor .dex from the
     # actual target, but instead loads them at runtime, we need to explicitly
@@ -1814,9 +1815,6 @@
       ":${_template_name}__create_incremental",
       ":${java_target}",
     ]
-    if (_native_libs != []) {
-      public_deps += [ ":$_prepare_native_target_name" ]
-    }
   }
 }
 
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index abd4f438..d0e41e56 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -128,10 +128,6 @@
 // http://crbug.com/272095
 "race:base::g_top_manager\n"
 
-// http://crbug.com/273047
-"race:base::*::g_lazy_tls_ptr\n"
-"race:IPC::SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_\n"
-
 // http://crbug.com/280466
 "race:content::WebRtcAudioCapturer::SetCapturerSource\n"
 
@@ -144,9 +140,6 @@
 // http://crbug.com/310851
 "race:net::ProxyResolverV8Tracing::Job::~Job\n"
 
-// http://crbug.com/313726
-"race:CallbackWasCalled\n"
-
 // http://crbug.com/327330
 "race:PrepareTextureMailbox\n"
 "race:cc::LayerTreeHost::PaintLayerContents\n"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationListener.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationListener.java
index eb1c09f..ecc488f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationListener.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationListener.java
@@ -20,6 +20,12 @@
     public static final int ACTION_SOURCE_MEDIA_SESSION = 1001;
 
     /**
+     * The media action was received by unplugging the headset,
+     * which broadcasts an ACTION_AUDIO_BECOMING_NOISY intent.
+     */
+    public static final int ACTION_SOURCE_HEADSET_UNPLUG = 1002;
+
+    /**
      * Called when the user wants to resume the playback.
      * @param actionSource The source the listener got the action from.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
index d2c05de..7ed81e46 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -7,12 +7,15 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.Service;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
 import android.os.Build;
 import android.os.IBinder;
 import android.support.v4.app.NotificationCompat;
@@ -27,6 +30,7 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Log;
+import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.tab.Tab;
 
@@ -162,6 +166,8 @@
                 manager.onPlay(MediaNotificationListener.ACTION_SOURCE_MEDIA_NOTIFICATION);
             } else if (ACTION_PAUSE.equals(action)) {
                 manager.onPause(MediaNotificationListener.ACTION_SOURCE_MEDIA_NOTIFICATION);
+            } else if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(action)) {
+                manager.onPause(MediaNotificationListener.ACTION_SOURCE_HEADSET_UNPLUG);
             }
         }
     }
@@ -171,6 +177,33 @@
      */
     public static final class PlaybackListenerService extends ListenerService {
         private static final int NOTIFICATION_ID = R.id.media_playback_notification;
+
+        @Override
+        public void onCreate() {
+            super.onCreate();
+            IntentFilter filter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
+            registerReceiver(mAudioBecomingNoisyReceiver, filter);
+        }
+
+        @Override
+        public void onDestroy() {
+            unregisterReceiver(mAudioBecomingNoisyReceiver);
+            super.onDestroy();
+        }
+
+        private BroadcastReceiver mAudioBecomingNoisyReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (!AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
+                        return;
+                    }
+
+                    Intent i = new Intent(context, PlaybackListenerService.class);
+                    i.setAction(intent.getAction());
+                    i.putExtra(ListenerService.EXTRA_NOTIFICATION_ID, NOTIFICATION_ID);
+                    context.startService(i);
+                }
+            };
     }
 
     /**
@@ -299,6 +332,11 @@
         return sManagers.get(notificationId);
     }
 
+    @VisibleForTesting
+    protected static boolean hasManagerForTesting(int notificationId) {
+        return getManager(notificationId) != null;
+    }
+
     private final Context mContext;
 
     // ListenerService running for the notification. Only non-null when showing.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
index 1c7572b..94d5785 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
@@ -171,6 +171,8 @@
             return MediaSessionUMA.MEDIA_SESSION_ACTION_SOURCE_MEDIA_NOTIFICATION;
         } else if (source == MediaNotificationListener.ACTION_SOURCE_MEDIA_SESSION) {
             return MediaSessionUMA.MEDIA_SESSION_ACTION_SOURCE_MEDIA_SESSION;
+        } else if (source == MediaNotificationListener.ACTION_SOURCE_HEADSET_UNPLUG) {
+            return MediaSessionUMA.MEDIA_SESSION_ACTION_SOURCE_HEADSET_UNPLUG;
         }
 
         assert false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/MediaSessionUMA.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/MediaSessionUMA.java
index d5174d5..239e2f2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/MediaSessionUMA.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/MediaSessionUMA.java
@@ -13,7 +13,8 @@
     // MediaSessionAction defined in tools/metrics/histograms/histograms.xml.
     public static final int MEDIA_SESSION_ACTION_SOURCE_MEDIA_NOTIFICATION = 0;
     public static final int MEDIA_SESSION_ACTION_SOURCE_MEDIA_SESSION = 1;
-    public static final int MEDIA_SESSION_ACTION_SOURCE_MAX = 2;
+    public static final int MEDIA_SESSION_ACTION_SOURCE_HEADSET_UNPLUG = 2;
+    public static final int MEDIA_SESSION_ACTION_SOURCE_MAX = 3;
 
     public static void recordPlay(int action) {
         assert action >= 0 && action < MEDIA_SESSION_ACTION_SOURCE_MAX;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java
new file mode 100644
index 0000000..5a1c982
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java
@@ -0,0 +1,76 @@
+// 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.chrome.browser.media.ui;
+
+import android.content.Intent;
+import android.media.AudioManager;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.test.ChromeActivityTestCaseBase;
+import org.chromium.chrome.test.util.TestHttpServerClient;
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
+import org.chromium.content.browser.test.util.DOMUtils;
+import org.chromium.content.common.ContentSwitches;
+
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Tests for checking whether the media are paused when unplugging the headset
+ */
+@CommandLineFlags.Add(ContentSwitches.DISABLE_GESTURE_REQUIREMENT_FOR_MEDIA_PLAYBACK)
+public class PauseOnHeadsetUnplugTest extends ChromeActivityTestCaseBase<ChromeActivity> {
+    private static final String TEST_URL =
+            "content/test/data/android/media/media-session.html";
+    private static final String VIDEO_ID = "long-video";
+
+    public PauseOnHeadsetUnplugTest() {
+        super(ChromeActivity.class);
+    }
+
+    @SmallTest
+    public void testPause()
+            throws IllegalArgumentException, InterruptedException, TimeoutException {
+        Tab tab = getActivity().getActivityTab();
+
+        assertTrue(DOMUtils.isMediaPaused(tab.getWebContents(), VIDEO_ID));
+        DOMUtils.playMedia(tab.getWebContents(), VIDEO_ID);
+        assertTrue(DOMUtils.waitForMediaPlay(tab.getWebContents(), VIDEO_ID));
+        assertTrue(waitForNotificationReady());
+
+        simulateHeadsetUnplug();
+        assertTrue(DOMUtils.waitForMediaPause(tab.getWebContents(), VIDEO_ID));
+    }
+
+    @Override
+    public void startMainActivity() throws InterruptedException {
+        startMainActivityWithURL(TestHttpServerClient.getUrl(TEST_URL));
+    }
+
+    private boolean waitForNotificationReady()
+            throws InterruptedException {
+        return CriteriaHelper.pollForCriteria(new Criteria() {
+                @Override
+                public boolean isSatisfied() {
+                    return MediaNotificationManager.hasManagerForTesting(
+                            R.id.media_playback_notification);
+                }
+            });
+    }
+
+    private void simulateHeadsetUnplug() {
+        Intent i = new Intent(getInstrumentation().getTargetContext(),
+                              MediaNotificationManager.PlaybackListenerService.class);
+        i.setAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
+        i.putExtra(MediaButtonReceiver.EXTRA_NOTIFICATION_ID,
+                   R.id.media_playback_notification);
+
+        getInstrumentation().getContext().startService(i);
+    }
+}
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index eef47b83..2d8b3951 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -814,7 +814,7 @@
 
   // After all the platform Breakpads have been initialized, store the command
   // line for crash reporting.
-  crash_keys::SetSwitchesFromCommandLine(&command_line);
+  crash_keys::SetCrashKeysFromCommandLine(command_line);
 }
 
 void ChromeMainDelegate::SandboxInitialized(const std::string& process_type) {
@@ -944,7 +944,7 @@
   breakpad::InitCrashReporter(process_type);
 
   // Reset the command line for the newly spawned process.
-  crash_keys::SetSwitchesFromCommandLine(command_line);
+  crash_keys::SetCrashKeysFromCommandLine(*command_line);
 }
 
 #endif  // OS_MACOSX
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index a977d342..3a41ca91b 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -967,8 +967,8 @@
 
   // Reset the command line in the crash report details, since we may have
   // just changed it to include experiments.
-  crash_keys::SetSwitchesFromCommandLine(
-      base::CommandLine::ForCurrentProcess());
+  crash_keys::SetCrashKeysFromCommandLine(
+      *base::CommandLine::ForCurrentProcess());
 
   // Mac starts it earlier in |PreMainMessageLoopStart()| (because it is
   // needed when loading the MainMenu.nib and the language doesn't depend on
diff --git a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
index 07358be3..512d2d4 100644
--- a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
+++ b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
@@ -111,7 +111,6 @@
     "ljacajndfccfgnfohlgkdphmbnpkjflk",  // Chrome Remote Desktop (Dev Build)
 };
 
-#if 0
 // List of manifest entries from https://developer.chrome.com/apps/manifest.
 // Unsafe entries are commented out and special cases too.
 const char* const kSafeManifestEntries[] = {
@@ -376,7 +375,6 @@
     // Web capabilities are safe.
     "webview",
 };
-#endif
 
 // Return true iff |entry| is contained in |char_array|.
 bool ArrayContainsImpl(const char* const char_array[],
@@ -398,7 +396,6 @@
   return ArrayContainsImpl(char_array, N, entry);
 }
 
-#if 0
 // Returns true for platform apps that are considered safe for Public Sessions,
 // which among other things requires the manifest top-level entries to be
 // contained in the |kSafeManifestEntries| whitelist and all permissions to be
@@ -483,7 +480,6 @@
 
   return true;
 }
-#endif
 
 }  // namespace
 
@@ -527,7 +523,6 @@
       return true;
     }
 
-#if 0
     // Allow force-installed platform app if all manifest contents are
     // whitelisted.
     if ((extension->location() == extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD
@@ -535,7 +530,6 @@
         && IsPlatformAppSafeForPublicSession(extension)) {
       return true;
     }
-#endif
   } else if (account_type_ == policy::DeviceLocalAccount::TYPE_KIOSK_APP) {
     // For single-app kiosk sessions, allow platform apps, extesions and
     // shared modules.
diff --git a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc
index b612370..180be997 100644
--- a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc
+++ b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc
@@ -122,7 +122,6 @@
   EXPECT_NE(base::string16(), error);
   error.clear();
 
-#if 0
   // Verify that a minimal platform app can be installed from location
   // EXTERNAL_POLICY.
   {
@@ -302,7 +301,6 @@
     EXPECT_EQ(base::string16(), error);
     error.clear();
   }
-#endif
 }
 
 TEST(DeviceLocalAccountManagementPolicyProviderTest, KioskAppSession) {
diff --git a/chrome/browser/extensions/extension_disabled_ui.cc b/chrome/browser/extensions/extension_disabled_ui.cc
index 05226597..640af2ff 100644
--- a/chrome/browser/extensions/extension_disabled_ui.cc
+++ b/chrome/browser/extensions/extension_disabled_ui.cc
@@ -339,7 +339,8 @@
 base::string16 ExtensionDisabledGlobalError::GetBubbleViewAcceptButtonLabel() {
   if (extensions::util::IsExtensionSupervised(extension_,
                                               service_->profile()) &&
-      extensions::util::NeedCustodianApprovalForPermissionIncrease()) {
+      extensions::util::NeedCustodianApprovalForPermissionIncrease(
+          service_->profile())) {
     // TODO(treib): Probably use a new string here once we get UX design.
     // For now, just use "OK". crbug.com/461261
     return l10n_util::GetStringUTF16(IDS_OK);
@@ -356,7 +357,8 @@
 base::string16 ExtensionDisabledGlobalError::GetBubbleViewCancelButtonLabel() {
   if (extensions::util::IsExtensionSupervised(extension_,
                                               service_->profile())) {
-    if (extensions::util::NeedCustodianApprovalForPermissionIncrease()) {
+    if (extensions::util::NeedCustodianApprovalForPermissionIncrease(
+        service_->profile())) {
       // If the supervised user can't approve the update, then there is no
       // "cancel" button.
       return base::string16();
@@ -376,7 +378,8 @@
     Browser* browser) {
   if (extensions::util::IsExtensionSupervised(extension_,
                                               service_->profile()) &&
-      extensions::util::NeedCustodianApprovalForPermissionIncrease()) {
+      extensions::util::NeedCustodianApprovalForPermissionIncrease(
+          service_->profile())) {
     return;
   }
   // Delay extension reenabling so this bubble closes properly.
@@ -393,7 +396,8 @@
     // For custodian-installed extensions, this button should only exist if the
     // supervised user can approve the update. Otherwise there is only an "OK"
     // button.
-    DCHECK(!extensions::util::NeedCustodianApprovalForPermissionIncrease());
+    DCHECK(!extensions::util::NeedCustodianApprovalForPermissionIncrease(
+        service_->profile()));
     // Supervised users may never remove custodian-installed extensions.
     return;
   }
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index c5e68c7..e8023b3b 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -1647,7 +1647,8 @@
     // to a permissions increase, send a request to the custodian if the
     // supervised user themselves can't re-enable the extension.
     if (extensions::util::IsExtensionSupervised(extension, profile_) &&
-        extensions::util::NeedCustodianApprovalForPermissionIncrease() &&
+        extensions::util::NeedCustodianApprovalForPermissionIncrease(
+            profile_) &&
         !ExtensionSyncService::Get(profile_)->HasPendingReenable(
             extension->id(), *extension->version())) {
       SupervisedUserService* supervised_user_service =
diff --git a/chrome/browser/extensions/extension_service_sync_unittest.cc b/chrome/browser/extensions/extension_service_sync_unittest.cc
index 3bd4e75..1f16ad13 100644
--- a/chrome/browser/extensions/extension_service_sync_unittest.cc
+++ b/chrome/browser/extensions/extension_service_sync_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <map>
 #include <string>
 
 #include "base/bind.h"
@@ -25,6 +26,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/browser_sync/browser/profile_sync_service.h"
 #include "components/crx_file/id_util.h"
+#include "components/variations/variations_associated_data.h"
 #include "extensions/browser/app_sorting.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
@@ -276,6 +278,103 @@
   EXPECT_FALSE(service()->IsExtensionEnabled(good2));
 }
 
+TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
+  // Start the extension service with three extensions already installed.
+  base::FilePath source_install_dir =
+      data_dir().AppendASCII("good").AppendASCII("Extensions");
+  base::FilePath pref_path =
+      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
+
+  InitializeInstalledExtensionService(pref_path, source_install_dir);
+
+  // The user has enabled sync.
+  ProfileSyncServiceFactory::GetForProfile(profile())->SetSyncSetupCompleted();
+  // Make sure ExtensionSyncService is created, so it'll be notified of changes.
+  extension_sync_service();
+
+  service()->Init();
+  ASSERT_TRUE(service()->is_ready());
+  ASSERT_EQ(3u, loaded_.size());
+  ASSERT_TRUE(service()->IsExtensionEnabled(good0));
+
+  syncer::FakeSyncChangeProcessor* processor =
+      new syncer::FakeSyncChangeProcessor;
+  extension_sync_service()->MergeDataAndStartSyncing(
+      syncer::EXTENSIONS,
+      syncer::SyncDataList(),
+      make_scoped_ptr(processor),
+      make_scoped_ptr(new syncer::SyncErrorFactoryMock));
+
+  processor->changes().clear();
+
+  // Simulate various incoming sync changes, and make sure they don't result in
+  // any outgoing changes.
+
+  {
+    const Extension* extension = service()->GetExtensionById(good0, true);
+    ASSERT_TRUE(extension);
+
+    // Disable the extension.
+    ExtensionSyncData data(*extension, false, Extension::DISABLE_USER_ACTION,
+                           false, false, ExtensionSyncData::BOOLEAN_UNSET);
+    syncer::SyncChangeList list(
+        1, data.GetSyncChange(syncer::SyncChange::ACTION_UPDATE));
+
+    extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
+
+    EXPECT_TRUE(processor->changes().empty());
+  }
+
+  {
+    const Extension* extension = service()->GetExtensionById(good0, true);
+    ASSERT_TRUE(extension);
+
+    // Set incognito enabled to true.
+    ExtensionSyncData data(*extension, false, Extension::DISABLE_NONE, true,
+                           false, ExtensionSyncData::BOOLEAN_UNSET);
+    syncer::SyncChangeList list(
+        1, data.GetSyncChange(syncer::SyncChange::ACTION_UPDATE));
+
+    extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
+
+    EXPECT_TRUE(processor->changes().empty());
+  }
+
+  {
+    const Extension* extension = service()->GetExtensionById(good0, true);
+    ASSERT_TRUE(extension);
+
+    // Add another disable reason.
+    ExtensionSyncData data(*extension, false,
+                           Extension::DISABLE_USER_ACTION |
+                               Extension::DISABLE_PERMISSIONS_INCREASE,
+                           false, false, ExtensionSyncData::BOOLEAN_UNSET);
+    syncer::SyncChangeList list(
+        1, data.GetSyncChange(syncer::SyncChange::ACTION_UPDATE));
+
+    extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
+
+    EXPECT_TRUE(processor->changes().empty());
+  }
+
+  {
+    const Extension* extension = service()->GetExtensionById(good0, true);
+    ASSERT_TRUE(extension);
+
+    // Uninstall the extension.
+    ExtensionSyncData data(*extension, false,
+                           Extension::DISABLE_USER_ACTION |
+                               Extension::DISABLE_PERMISSIONS_INCREASE,
+                           false, false, ExtensionSyncData::BOOLEAN_UNSET);
+    syncer::SyncChangeList list(
+        1, data.GetSyncChange(syncer::SyncChange::ACTION_DELETE));
+
+    extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
+
+    EXPECT_TRUE(processor->changes().empty());
+  }
+}
+
 TEST_F(ExtensionServiceSyncTest, GetSyncData) {
   InitializeEmptyExtensionService();
   InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
@@ -1423,6 +1522,9 @@
 class ExtensionServiceTestSupervised : public ExtensionServiceSyncTest,
                                        public SupervisedUserService::Delegate {
  public:
+  ExtensionServiceTestSupervised()
+      : field_trial_list_(new base::MockEntropyProvider()) {}
+
   void SetUp() override {
     ExtensionServiceSyncTest::SetUp();
 
@@ -1440,6 +1542,17 @@
   }
 
  protected:
+  void InitNeedCustodianApprovalFieldTrial(bool enabled) {
+    // Group name doesn't matter.
+    base::FieldTrialList::CreateFieldTrial(
+        "SupervisedUserExtensionPermissionIncrease", "group");
+    std::map<std::string, std::string> params;
+    params["legacy_supervised_user"] = enabled ? "true" : "false";
+    params["child_account"] = enabled ? "true" : "false";
+    variations::AssociateVariationParams(
+        "SupervisedUserExtensionPermissionIncrease", "group", params);
+  }
+
   void InitServices(bool profile_is_supervised) {
     ExtensionServiceInitParams params = CreateDefaultInitParams();
     params.profile_is_supervised = profile_is_supervised;
@@ -1497,6 +1610,8 @@
   base::FilePath pem_path() const {
     return base_path().AppendASCII("permissions.pem");
   }
+
+  base::FieldTrialList field_trial_list_;
 };
 
 class MockPermissionRequestCreator : public PermissionRequestCreator {
@@ -1581,10 +1696,7 @@
 }
 
 TEST_F(ExtensionServiceTestSupervised, UpdateWithPermissionIncreaseNoApproval) {
-  // Explicitly disable the "need custodian approval" field trial.
-  base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
-  base::FieldTrialList::CreateFieldTrial(
-      "SupervisedUserExtensionPermissionIncrease", "");
+  InitNeedCustodianApprovalFieldTrial(false);
 
   InitServices(true /* profile_is_supervised */);
 
@@ -1606,10 +1718,7 @@
 
 TEST_F(ExtensionServiceTestSupervised,
        UpdateWithPermissionIncreaseApprovalOldVersion) {
-  // Explicitly enable the "need custodian approval" field trial.
-  base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
-  base::FieldTrialList::CreateFieldTrial(
-      "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval");
+  InitNeedCustodianApprovalFieldTrial(true);
 
   InitServices(true /* profile_is_supervised */);
 
@@ -1659,10 +1768,7 @@
 
 TEST_F(ExtensionServiceTestSupervised,
        UpdateWithPermissionIncreaseApprovalMatchingVersion) {
-  // Explicitly enable the "need custodian approval" field trial.
-  base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
-  base::FieldTrialList::CreateFieldTrial(
-      "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval");
+  InitNeedCustodianApprovalFieldTrial(true);
 
   InitServices(true /* profile_is_supervised */);
 
@@ -1700,10 +1806,7 @@
 
 TEST_F(ExtensionServiceTestSupervised,
        UpdateWithPermissionIncreaseApprovalNewVersion) {
-  // Explicitly enable the "need custodian approval" field trial.
-  base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
-  base::FieldTrialList::CreateFieldTrial(
-      "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval");
+  InitNeedCustodianApprovalFieldTrial(true);
 
   InitServices(true /* profile_is_supervised */);
 
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc
index e0a8cdf..29c6f90 100644
--- a/chrome/browser/extensions/extension_sync_service.cc
+++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/extensions/extension_sync_service.h"
 
+#include "base/auto_reset.h"
 #include "base/basictypes.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/bookmark_app_helper.h"
@@ -127,6 +128,7 @@
     : profile_(profile),
       registry_observer_(this),
       prefs_observer_(this),
+      ignore_updates_(false),
       flare_(sync_start_util::GetFlareForSyncableService(profile->GetPath())) {
   registry_observer_.Add(ExtensionRegistry::Get(profile_));
   prefs_observer_.Add(ExtensionPrefs::Get(profile_));
@@ -143,7 +145,7 @@
 
 void ExtensionSyncService::SyncExtensionChangeIfNeeded(
     const Extension& extension) {
-  if (!extensions::util::ShouldSync(&extension, profile_))
+  if (ignore_updates_ || !extensions::util::ShouldSync(&extension, profile_))
     return;
 
   syncer::ModelType type =
@@ -298,6 +300,10 @@
 
 void ExtensionSyncService::ApplySyncData(
     const ExtensionSyncData& extension_sync_data) {
+  // Ignore any pref change notifications etc. while we're applying incoming
+  // sync data, so that we don't end up notifying ourselves.
+  base::AutoReset<bool> ignore_updates(&ignore_updates_, true);
+
   syncer::ModelType type = extension_sync_data.is_app() ? syncer::APPS
                                                         : syncer::EXTENSIONS;
   const std::string& id = extension_sync_data.id();
@@ -364,7 +370,9 @@
   int incoming_disable_reasons = extension_sync_data.disable_reasons();
   if (!!incoming_disable_reasons == extension_sync_data.enabled()) {
     // The enabled flag disagrees with the presence of disable reasons. This
-    // must come from an old (<M45) client which doesn't sync disable reasons.
+    // must either come from an old (<M45) client which doesn't sync disable
+    // reasons, or the extension is blacklisted (which doesn't have a
+    // corresponding disable reason).
     // Update |disable_reasons| based on the enabled flag.
     if (extension_sync_data.enabled())
       disable_reasons &= ~kKnownSyncableDisableReasons;
@@ -596,14 +604,16 @@
   // See crbug.com/256795.
   // Possible fix: Set NeedsSync here, then in MergeDataAndStartSyncing, if
   // NeedsSync is set but the extension isn't installed, send a sync deletion.
-  syncer::ModelType type =
-      extension->is_app() ? syncer::APPS : syncer::EXTENSIONS;
-  SyncBundle* bundle = GetSyncBundle(type);
-  if (bundle->IsSyncing()) {
-    bundle->PushSyncDeletion(extension->id(),
-                             CreateSyncData(*extension).GetSyncData());
-  } else if (extension_service()->is_ready() && !flare_.is_null()) {
-    flare_.Run(type);  // Tell sync to start ASAP.
+  if (!ignore_updates_) {
+    syncer::ModelType type =
+        extension->is_app() ? syncer::APPS : syncer::EXTENSIONS;
+    SyncBundle* bundle = GetSyncBundle(type);
+    if (bundle->IsSyncing()) {
+      bundle->PushSyncDeletion(extension->id(),
+                               CreateSyncData(*extension).GetSyncData());
+    } else if (extension_service()->is_ready() && !flare_.is_null()) {
+      flare_.Run(type);  // Tell sync to start ASAP.
+    }
   }
 
   pending_updates_.erase(extension->id());
diff --git a/chrome/browser/extensions/extension_sync_service.h b/chrome/browser/extensions/extension_sync_service.h
index 2c225330..1135bd0 100644
--- a/chrome/browser/extensions/extension_sync_service.h
+++ b/chrome/browser/extensions/extension_sync_service.h
@@ -125,6 +125,12 @@
   ScopedObserver<extensions::ExtensionPrefs,
                  extensions::ExtensionPrefsObserver> prefs_observer_;
 
+  // When this is set to true, any incoming updates (from the observers as well
+  // as from explicit SyncExtensionChangeIfNeeded calls) are ignored. This is
+  // set during ApplySyncData, so that ExtensionSyncService doesn't end up
+  // notifying itself while applying sync changes.
+  bool ignore_updates_;
+
   extensions::SyncBundle app_sync_bundle_;
   extensions::SyncBundle extension_sync_bundle_;
 
diff --git a/chrome/browser/extensions/extension_util.cc b/chrome/browser/extensions/extension_util.cc
index 639d7a4..d2d3065 100644
--- a/chrome/browser/extensions/extension_util.cc
+++ b/chrome/browser/extensions/extension_util.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/sync_helper.h"
+#include "components/variations/variations_associated_data.h"
 #include "content/public/browser/site_instance.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
@@ -371,14 +372,20 @@
 #endif
 }
 
-bool IsExtensionSupervised(const Extension* extension, Profile* profile) {
+bool IsExtensionSupervised(const Extension* extension, const Profile* profile) {
   return extension->was_installed_by_custodian() && profile->IsSupervised();
 }
 
-bool NeedCustodianApprovalForPermissionIncrease() {
-  const std::string group_name = base::FieldTrialList::FindFullName(
+bool NeedCustodianApprovalForPermissionIncrease(const Profile* profile) {
+  if (!profile->IsSupervised())
+    return false;
+  // Query the trial group name first, to make sure it's properly initialized.
+  base::FieldTrialList::FindFullName(
       kSupervisedUserExtensionPermissionIncreaseFieldTrialName);
-  return group_name == "NeedCustodianApproval";
+  std::string value = variations::GetVariationParamValue(
+      kSupervisedUserExtensionPermissionIncreaseFieldTrialName,
+      profile->IsChild() ? "child_account" : "legacy_supervised_user");
+  return value == "true";
 }
 
 }  // namespace util
diff --git a/chrome/browser/extensions/extension_util.h b/chrome/browser/extensions/extension_util.h
index aa8f613d..b0d03797 100644
--- a/chrome/browser/extensions/extension_util.h
+++ b/chrome/browser/extensions/extension_util.h
@@ -130,11 +130,11 @@
 bool CanHostedAppsOpenInWindows();
 
 // Returns true for custodian-installed extensions in a supervised profile.
-bool IsExtensionSupervised(const Extension* extension, Profile* profile);
+bool IsExtensionSupervised(const Extension* extension, const Profile* profile);
 
 // Returns true if supervised users need approval from their custodian for
 // approving escalated permissions on updated extensions.
-bool NeedCustodianApprovalForPermissionIncrease();
+bool NeedCustodianApprovalForPermissionIncrease(const Profile* profile);
 
 }  // namespace util
 }  // namespace extensions
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 90a75997..3e5e7a2 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -71,6 +71,7 @@
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/dom_distiller/core/distilled_page_prefs.h"
 #include "components/enhanced_bookmarks/bookmark_server_cluster_service.h"
+#include "components/flags_ui/pref_service_flags_storage.h"
 #include "components/gcm_driver/gcm_channel_status_syncer.h"
 #include "components/network_time/network_time_tracker.h"
 #include "components/omnibox/browser/zero_suggest_provider.h"
@@ -247,7 +248,7 @@
   component_updater::RegisterPrefsForRecoveryComponent(registry);
   component_updater::SupervisedUserWhitelistInstaller::RegisterPrefs(registry);
   ExternalProtocolHandler::RegisterPrefs(registry);
-  FlagsUI::RegisterPrefs(registry);
+  flags_ui::PrefServiceFlagsStorage::RegisterPrefs(registry);
   geolocation::RegisterPrefs(registry);
   GLStringManager::RegisterPrefs(registry);
   GpuModeManager::RegisterPrefs(registry);
@@ -490,7 +491,7 @@
   chromeos::UserImageSyncObserver::RegisterProfilePrefs(registry);
   extensions::EnterprisePlatformKeysPrivateChallengeUserKeyFunction::
       RegisterProfilePrefs(registry);
-  FlagsUI::RegisterProfilePrefs(registry);
+  flags_ui::PrefServiceFlagsStorage::RegisterProfilePrefs(registry);
 #endif
 
 #if defined(OS_WIN)
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc
index e07bf6a..071327ef 100644
--- a/chrome/browser/printing/pdf_to_emf_converter.cc
+++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/printing/pdf_to_emf_converter.h"
 
 #include <queue>
+#include <utility>
 
 #include "base/files/file.h"
 #include "base/files/file_util.h"
@@ -113,21 +114,21 @@
 
  private:
   class GetPageCallbackData {
-    MOVE_ONLY_TYPE_FOR_CPP_03(GetPageCallbackData, RValue);
+    MOVE_ONLY_TYPE_FOR_CPP_03(GetPageCallbackData);
 
    public:
     GetPageCallbackData(int page_number,
                         PdfToEmfConverter::GetPageCallback callback)
         : page_number_(page_number), callback_(callback) {}
 
-    // Move constructor for STL.
-    GetPageCallbackData(RValue other) { this->operator=(other); }
+    GetPageCallbackData(GetPageCallbackData&& other) {
+      *this = std::move(other);
+    }
 
-    // Move assignment for STL.
-    GetPageCallbackData& operator=(RValue rhs) {
-      page_number_ = rhs.object->page_number_;
-      callback_ = rhs.object->callback_;
-      emf_ = rhs.object->emf_.Pass();
+    GetPageCallbackData& operator=(GetPageCallbackData&& rhs) {
+      page_number_ = rhs.page_number_;
+      callback_ = rhs.callback_;
+      emf_ = std::move(rhs.emf_);
       return *this;
     }
 
diff --git a/chrome/browser/profile_resetter/profile_resetter.cc b/chrome/browser/profile_resetter/profile_resetter.cc
index 0c2a49b..bbbf0c4 100644
--- a/chrome/browser/profile_resetter/profile_resetter.cc
+++ b/chrome/browser/profile_resetter/profile_resetter.cc
@@ -83,7 +83,6 @@
 void ProfileResetter::Reset(
     ProfileResetter::ResettableFlags resettable_flags,
     scoped_ptr<BrandcodedDefaultSettings> master_settings,
-    bool accepted_send_feedback,
     const base::Closure& callback) {
   DCHECK(CalledOnValidThread());
   DCHECK(master_settings);
diff --git a/chrome/browser/profile_resetter/profile_resetter.h b/chrome/browser/profile_resetter/profile_resetter.h
index b4044fa..31f92cd5 100644
--- a/chrome/browser/profile_resetter/profile_resetter.h
+++ b/chrome/browser/profile_resetter/profile_resetter.h
@@ -60,11 +60,9 @@
 
   // Resets |resettable_flags| and calls |callback| on the UI thread on
   // completion. |default_settings| allows the caller to specify some default
-  // settings. |default_settings| shouldn't be NULL. |accepted_send_feedback|
-  // identifies whether the user accepted to send feedback or not.
+  // settings. |default_settings| shouldn't be NULL.
   void Reset(ResettableFlags resettable_flags,
              scoped_ptr<BrandcodedDefaultSettings> master_settings,
-             bool accepted_send_feedback,
              const base::Closure& callback);
 
   bool IsActive() const;
diff --git a/chrome/browser/profile_resetter/profile_resetter_test_base.cc b/chrome/browser/profile_resetter/profile_resetter_test_base.cc
index f149672..b1e12428 100644
--- a/chrome/browser/profile_resetter/profile_resetter_test_base.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_test_base.cc
@@ -35,7 +35,6 @@
       new BrandcodedDefaultSettings);
   resetter_->Reset(resettable_flags,
                    master_settings.Pass(),
-                   false,
                    base::Bind(&ProfileResetterMockObject::StopLoop,
                               base::Unretained(&mock_object_)));
   mock_object_.RunLoop();
@@ -48,7 +47,6 @@
       new BrandcodedDefaultSettings(prefs));
   resetter_->Reset(resettable_flags,
                    master_settings.Pass(),
-                   false,
                    base::Bind(&ProfileResetterMockObject::StopLoop,
                               base::Unretained(&mock_object_)));
   mock_object_.RunLoop();
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc
index e8f42af7..e4c3f92 100644
--- a/chrome/browser/push_messaging/push_messaging_service_impl.cc
+++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -441,7 +441,8 @@
       // Do not get a certificate if message payloads have not been enabled.
       if (!AreMessagePayloadsEnabled()) {
         DidSubscribeWithPublicKey(app_identifier, callback, subscription_id,
-                                  std::string() /* public_key */);
+                                  std::string() /* public_key */,
+                                  std::string() /* auth_secret */);
         return;
       }
 
@@ -475,7 +476,8 @@
     const PushMessagingAppIdentifier& app_identifier,
     const content::PushMessagingService::RegisterCallback& callback,
     const std::string& subscription_id,
-    const std::string& public_key) {
+    const std::string& public_key,
+    const std::string& auth_secret) {
   if (!public_key.size() && AreMessagePayloadsEnabled()) {
     SubscribeEndWithError(
         callback, content::PUSH_REGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE);
@@ -486,13 +488,9 @@
 
   IncreasePushSubscriptionCount(1, false /* is_pending */);
 
-  // TODO(peter): Hook up the authentication tag in the gcm_driver.
-  std::string authentication;
-
   SubscribeEnd(callback, subscription_id,
                std::vector<uint8_t>(public_key.begin(), public_key.end()),
-               std::vector<uint8_t>(authentication.begin(),
-                                    authentication.end()),
+               std::vector<uint8_t>(auth_secret.begin(), auth_secret.end()),
                content::PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE);
 }
 
@@ -543,17 +541,14 @@
 
 void PushMessagingServiceImpl::DidGetPublicKey(
     const PushMessagingService::PublicKeyCallback& callback,
-    const std::string& public_key) const {
+    const std::string& public_key,
+    const std::string& auth_secret) const {
   // I/O errors might prevent the GCM Driver from retrieving a key-pair.
   const bool success = !!public_key.size();
 
-  // TODO(peter): Hook up the authentication tag in the gcm_driver.
-  std::string authentication;
-
   callback.Run(success,
                std::vector<uint8_t>(public_key.begin(), public_key.end()),
-               std::vector<uint8_t>(authentication.begin(),
-                                    authentication.end()));
+               std::vector<uint8_t>(auth_secret.begin(), auth_secret.end()));
 }
 
 // Unsubscribe methods ---------------------------------------------------------
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.h b/chrome/browser/push_messaging/push_messaging_service_impl.h
index 4cd099f..0d2ce7bc 100644
--- a/chrome/browser/push_messaging/push_messaging_service_impl.h
+++ b/chrome/browser/push_messaging/push_messaging_service_impl.h
@@ -151,7 +151,8 @@
       const PushMessagingAppIdentifier& app_identifier,
       const content::PushMessagingService::RegisterCallback& callback,
       const std::string& subscription_id,
-      const std::string& public_key);
+      const std::string& public_key,
+      const std::string& auth_secret);
 
   void DidRequestPermission(
       const PushMessagingAppIdentifier& app_identifier,
@@ -162,7 +163,8 @@
   // GetPublicEncryptionKey method ---------------------------------------------
 
   void DidGetPublicKey(const PushMessagingService::PublicKeyCallback& callback,
-                       const std::string& public_key) const;
+                       const std::string& public_key,
+                       const std::string& auth_secret) const;
 
   // Unsubscribe methods -------------------------------------------------------
 
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
index b655cfe..9424143 100644
--- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
+++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
@@ -218,11 +218,11 @@
   },
 
   listeners: {
+    'arrow-drop-click': 'toggleCastModeHidden_',
     'tap': 'onTap_',
   },
 
   ready: function() {
-    this.addEventListener('arrow-drop-click', this.toggleCastModeHidden_);
     this.showSinkList_();
   },
 
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc
index 93f81e3..caf06c2 100644
--- a/chrome/browser/safe_browsing/download_protection_service.cc
+++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -447,6 +447,7 @@
                         base::TimeTicks::Now() - start_time_);
     UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestNetworkDuration",
                         base::TimeTicks::Now() - request_start_time_);
+
     FinishRequest(result, reason);
   }
 
@@ -710,15 +711,6 @@
 // the server if we're not on one of those platforms.
 // TODO(noelutz): change this code once the UI is done for Linux.
 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
-    // User can manually blacklist a sha256 via flag, for testing.
-    // In this case we don't actually send the request.
-    if (item_ && service_ &&
-        service_->IsHashManuallyBlacklisted(item_->GetHash())) {
-      DVLOG(1) << "Download verdict overridden to DANGEROUS by flag.";
-      PostFinishTask(DANGEROUS, REASON_MANUAL_BLACKLIST);
-      return;
-    }
-
     // The URLFetcher is owned by the UI thread, so post a message to
     // start the pingback.
     BrowserThread::PostTask(
@@ -771,6 +763,19 @@
     SendRequest();
   }
 
+  // If the hash of either the original file or any executables within an
+  // archive matches the blacklist flag, return true.
+  bool IsDownloadManuallyBlacklisted(const ClientDownloadRequest& request) {
+    if (service_->IsHashManuallyBlacklisted(request.digests().sha256()))
+      return true;
+
+    for (auto bin_itr : request.archived_binary()) {
+      if (service_->IsHashManuallyBlacklisted(bin_itr.digests().sha256()))
+        return true;
+    }
+    return false;
+  }
+
   void SendRequest() {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
@@ -850,8 +855,18 @@
       FinishRequest(UNKNOWN, REASON_INVALID_REQUEST_PROTO);
       return;
     }
-    service_->client_download_request_callbacks_.Notify(item_, &request);
 
+    // User can manually blacklist a sha256 via flag, for testing.
+    // This is checked just before the request is sent, to verify the request
+    // would have been sent.  This emmulates the server returning a DANGEROUS
+    // verdict as closely as possible.
+    if (IsDownloadManuallyBlacklisted(request)) {
+      DVLOG(1) << "Download verdict overridden to DANGEROUS by flag.";
+      PostFinishTask(DANGEROUS, REASON_MANUAL_BLACKLIST);
+      return;
+    }
+
+    service_->client_download_request_callbacks_.Notify(item_, &request);
     DVLOG(2) << "Sending a request for URL: "
              << item_->GetUrlChain().back();
     DVLOG(2) << "Detected " << request.archived_binary().size() << " archived "
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
index f54a270..3ec5c7b 100644
--- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -2035,29 +2035,29 @@
 class DownloadProtectionServiceFlagTest : public DownloadProtectionServiceTest {
  protected:
   DownloadProtectionServiceFlagTest()
-      : blacklisted_hash_("abcdefghijklmnopqrstuvwxyz012345") {}
+      // Matches unsigned.exe within zipfile_one_unsigned_binary.zip
+      : blacklisted_hash_hex_("1e954d9ce0389e2ba7447216f21761f98d1e6540c2abecdbecff570e36c493db") {}
 
   void SetUp() override {
+    std::vector<uint8> bytes;
+    ASSERT_TRUE(base::HexStringToBytes(blacklisted_hash_hex_, &bytes) &&
+                bytes.size() == 32);
+    blacklisted_hash_ = std::string(bytes.begin(), bytes.end());
+
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kSbManualDownloadBlacklist,
-        base::HexEncode(blacklisted_hash_.c_str(), blacklisted_hash_.size()));
+        blacklisted_hash_hex_);
+
     DownloadProtectionServiceTest::SetUp();
   }
 
+  // Hex 64 chars
+  const std::string blacklisted_hash_hex_;
   // Binary 32 bytes
-  const std::string blacklisted_hash_;
+  std::string blacklisted_hash_;
 };
 
 TEST_F(DownloadProtectionServiceFlagTest, CheckClientDownloadOverridenByFlag) {
-  ClientDownloadResponse response;
-  response.set_verdict(ClientDownloadResponse::SAFE);
-  net::FakeURLFetcherFactory factory(NULL);
-  // Empty response means SAFE.
-  factory.SetFakeResponse(
-      DownloadProtectionService::GetDownloadRequestUrl(),
-      response.SerializeAsString(),
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
   std::vector<GURL> url_chain;
@@ -2103,4 +2103,51 @@
 #endif
 }
 
+// Test a real .zip with a real .exe in it, where the .exe is manually
+// blacklisted by hash.
+TEST_F(DownloadProtectionServiceFlagTest,
+       CheckClientDownloadZipOverridenByFlag) {
+  const base::FilePath zip_path =
+      testdata_path_.AppendASCII("zipfile_one_unsigned_binary.zip");
+
+  base::FilePath final_path(FILE_PATH_LITERAL("a.zip"));
+  std::vector<GURL> url_chain;
+  url_chain.push_back(GURL("http://www.evil.com/a.zip"));
+  GURL referrer("http://www.google.com/");
+  std::string zip_hash("hash");  // not blacklisted
+
+  content::MockDownloadItem item;
+  EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(zip_path));
+  EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
+  EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
+  EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(zip_hash));
+  EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
+  EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
+  EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
+
+  EXPECT_CALL(*sb_service_->mock_database_manager(),
+              MatchDownloadWhitelistUrl(_))
+      .WillRepeatedly(Return(false));
+
+  download_service_->CheckClientDownload(
+      &item, base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
+                        base::Unretained(this)));
+  MessageLoop::current()->Run();
+
+  EXPECT_FALSE(HasClientDownloadRequest());
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
+  // Overriden by flag:
+  EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
+#else
+  // On !(OS_WIN || OS_MACOSX || OS_CHROMEOS),
+  // no file types are currently supported. Hence all
+  // requests to CheckClientDownload() result in a verdict of UNKNOWN.
+  EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
+#endif
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
index 8ce3037..fd575c38 100644
--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
+++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h"
 
+#include <utility>
+
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
@@ -79,17 +81,15 @@
   }
 }
 
-SpellcheckHunspellDictionary::DictionaryFile::DictionaryFile(RValue other)
-    : path(other.object->path),
-      file(other.object->file.Pass()) {
-}
+SpellcheckHunspellDictionary::DictionaryFile::DictionaryFile(
+    DictionaryFile&& other)
+    : path(other.path), file(std::move(other.file)) {}
 
 SpellcheckHunspellDictionary::DictionaryFile&
-SpellcheckHunspellDictionary::DictionaryFile::operator=(RValue other) {
-  if (this != other.object) {
-    path = other.object->path;
-    file = other.object->file.Pass();
-  }
+    SpellcheckHunspellDictionary::DictionaryFile::
+    operator=(DictionaryFile&& other) {
+  path = other.path;
+  file = std::move(other.file);
   return *this;
 }
 
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
index a2c5068..a53dc005 100644
--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
+++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
@@ -92,14 +92,13 @@
 
   // Dictionary file information to be passed between the FILE and UI threads.
   struct DictionaryFile {
-    MOVE_ONLY_TYPE_FOR_CPP_03(DictionaryFile, RValue)
+    MOVE_ONLY_TYPE_FOR_CPP_03(DictionaryFile)
    public:
     DictionaryFile();
     ~DictionaryFile();
 
-    // C++03 move emulation of this type.
-    DictionaryFile(RValue other);
-    DictionaryFile& operator=(RValue other);
+    DictionaryFile(DictionaryFile&& other);
+    DictionaryFile& operator=(DictionaryFile&& other);
 
     // The desired location of the dictionary file, whether or not it exists.
     base::FilePath path;
diff --git a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
index 8574e16f..4cc6cd6 100644
--- a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
+++ b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
@@ -5,7 +5,10 @@
 #import "chrome/browser/ui/cocoa/app_menu/app_menu_controller.h"
 
 #include "base/basictypes.h"
+#include "base/bind.h"
 #include "base/mac/bundle_locations.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/scoped_observer.h"
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
@@ -119,7 +122,8 @@
   ToolbarActionsBarObserverHelper(AppMenuController* controller,
                                   ToolbarActionsBar* toolbar_actions_bar)
       : controller_(controller),
-        scoped_observer_(this) {
+        scoped_observer_(this),
+        weak_ptr_factory_(this) {
     scoped_observer_.Add(toolbar_actions_bar);
   }
   ~ToolbarActionsBarObserverHelper() override {}
@@ -130,11 +134,24 @@
     scoped_observer_.RemoveAll();
   }
   void OnToolbarActionsBarDidStartResize() override {
+    // No point in having multiple pending update calls.
+    weak_ptr_factory_.InvalidateWeakPtrs();
+    // Edge case: If the resize is caused by an action being added while the
+    // menu is open, we need to wait for both toolbars to be updated. This can
+    // happen if a user's data is synced with the menu open.
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&ToolbarActionsBarObserverHelper::UpdateSubmenu,
+                   weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  void UpdateSubmenu() {
     [controller_ updateBrowserActionsSubmenu];
   }
 
   AppMenuController* controller_;
   ScopedObserver<ToolbarActionsBar, ToolbarActionsBarObserver> scoped_observer_;
+  base::WeakPtrFactory<ToolbarActionsBarObserverHelper> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarObserverHelper);
 };
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm b/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm
index bd97931..8a51d8a5 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm
@@ -408,3 +408,50 @@
   resizeAndActivateWrench(kNumExtensions / 2, "GlobalError Half");
   resizeAndActivateWrench(1, "GlobalError One");
 }
+
+void AddExtensionWithMenuOpen(ToolbarController* toolbarController,
+                              ExtensionService* extensionService,
+                              const base::Closure& closure) {
+  AppMenuController* appMenuController =
+      [toolbarController appMenuController];
+
+  scoped_refptr<const extensions::Extension> extension =
+      extensions::extension_action_test_util::CreateActionExtension(
+          "extension",
+          extensions::extension_action_test_util::BROWSER_ACTION);
+  extensionService->AddExtension(extension.get());
+
+  base::RunLoop().RunUntilIdle();
+
+  // Close the app menu.
+  [appMenuController cancel];
+  EXPECT_FALSE([appMenuController isMenuOpen]);
+  base::MessageLoop::current()->PostTask(FROM_HERE, closure);
+}
+
+// Test adding an extension while the app menu is open. Regression test for
+// crbug.com/561237.
+IN_PROC_BROWSER_TEST_F(BrowserActionButtonUiTest, AddExtensionWithMenuOpen) {
+  // Add an extension to ensure the overflow menu is present.
+  scoped_refptr<const extensions::Extension> extension =
+      extensions::extension_action_test_util::CreateActionExtension(
+          "original extension",
+          extensions::extension_action_test_util::BROWSER_ACTION);
+  extension_service()->AddExtension(extension.get());
+  ASSERT_EQ(1, static_cast<int>(model()->toolbar_items().size()));
+  model()->SetVisibleIconCount(0);
+
+  MoveMouseToCenter(wrenchButton());
+
+  base::RunLoop runLoop;
+  // Click on the app menu, and pass in a callback to continue the test in
+  // AddExtensionWithMenuOpen (due to the blocking nature of Cocoa menus,
+  // passing in runLoop.QuitClosure() is not sufficient here.)
+  ui_controls::SendMouseEventsNotifyWhenDone(
+      ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
+      base::Bind(&AddExtensionWithMenuOpen,
+                 base::Unretained(toolbarController()),
+                 extension_service(),
+                 runLoop.QuitClosure()));
+  runLoop.Run();
+}
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
index a7c651d..3f6313c 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -78,7 +78,7 @@
 void SortContainer(std::vector<Type1>* to_sort,
                    const std::vector<Type2>& reference,
                    FunctionType equal) {
-  DCHECK_GE(to_sort->size(), reference.size()) <<
+  CHECK_GE(to_sort->size(), reference.size()) <<
       "|to_sort| must contain all elements in |reference|.";
   if (reference.empty())
     return;
diff --git a/chrome/browser/ui/webui/flags_ui.cc b/chrome/browser/ui/webui/flags_ui.cc
index bd26150..0cd3433 100644
--- a/chrome/browser/ui/webui/flags_ui.cc
+++ b/chrome/browser/ui/webui/flags_ui.cc
@@ -335,16 +335,3 @@
   return ResourceBundle::GetSharedInstance().
       LoadDataResourceBytesForScale(IDR_FLAGS_FAVICON, scale_factor);
 }
-
-// static
-void FlagsUI::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterListPref(flags_ui::prefs::kEnabledLabsExperiments);
-}
-
-#if defined(OS_CHROMEOS)
-// static
-void FlagsUI::RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterListPref(flags_ui::prefs::kEnabledLabsExperiments);
-}
-
-#endif
diff --git a/chrome/browser/ui/webui/flags_ui.h b/chrome/browser/ui/webui/flags_ui.h
index 1afd5ef..2bfb282 100644
--- a/chrome/browser/ui/webui/flags_ui.h
+++ b/chrome/browser/ui/webui/flags_ui.h
@@ -31,10 +31,6 @@
 
   static base::RefCountedMemory* GetFaviconResourceBytes(
       ui::ScaleFactor scale_factor);
-  static void RegisterPrefs(PrefRegistrySimple* registry);
-#if defined(OS_CHROMEOS)
-  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
-#endif
 
  private:
   base::WeakPtrFactory<FlagsUI> weak_factory_;
diff --git a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
index 0af19b52..9f77a9a 100644
--- a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
+++ b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
@@ -204,7 +204,6 @@
   resetter_->Reset(
       ProfileResetter::ALL,
       default_settings.Pass(),
-      send_settings,
       base::Bind(&ResetProfileSettingsHandler::OnResetProfileSettingsDone,
                  AsWeakPtr(),
                  send_settings));
diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler.cc b/chrome/browser/ui/webui/settings/reset_settings_handler.cc
index 53b19a9..3cc4661 100644
--- a/chrome/browser/ui/webui/settings/reset_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/reset_settings_handler.cc
@@ -168,7 +168,6 @@
   resetter_->Reset(
       ProfileResetter::ALL,
       default_settings.Pass(),
-      send_settings,
       base::Bind(&ResetSettingsHandler::OnResetProfileSettingsDone,
                  AsWeakPtr(),
                  send_settings));
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc
index 1a670fb..96553c3 100644
--- a/chrome/common/crash_keys.cc
+++ b/chrome/common/crash_keys.cc
@@ -11,7 +11,6 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/flags_ui/flags_ui_switches.h"
 #include "content/public/common/content_switches.h"
@@ -29,9 +28,6 @@
 
 const char kFontKeyName[] = "font_key_name";
 
-const char kSwitch[] = "switch-%" PRIuS;
-const char kNumSwitches[] = "num-switches";
-
 const char kExtensionID[] = "extension-%" PRIuS;
 const char kNumExtensionsCount[] = "num-extensions";
 
@@ -94,7 +90,6 @@
 #endif
     { kChannel, kSmallSize },
     { kActiveURL, kLargeSize },
-    { kNumSwitches, kSmallSize },
     { kNumVariations, kSmallSize },
     { kVariations, kLargeSize },
     { kNumExtensionsCount, kSmallSize },
@@ -154,23 +149,7 @@
   std::vector<base::debug::CrashKey> keys(
       fixed_keys, fixed_keys + arraysize(fixed_keys));
 
-  // Register the switches.
-  {
-    // The fixed_keys names are string constants. Use static storage for
-    // formatted key names as well, since they will persist for the duration of
-    // the program.
-    static char formatted_keys[kSwitchesMaxCount][sizeof(kSwitch) + 1] =
-        {{ 0 }};
-    const size_t formatted_key_len = sizeof(formatted_keys[0]);
-    for (size_t i = 0; i < kSwitchesMaxCount; ++i) {
-      // Name the keys using 1-based indexing.
-      int n = base::snprintf(
-          formatted_keys[i], formatted_key_len, kSwitch, i + 1);
-      DCHECK_GT(n, 0);
-      base::debug::CrashKey crash_key = { formatted_keys[i], kSmallSize };
-      keys.push_back(crash_key);
-    }
-  }
+  crash_keys::GetCrashKeysForCommandLineSwitches(&keys);
 
   // Register the extension IDs.
   {
@@ -268,43 +247,8 @@
   return false;
 }
 
-void SetSwitchesFromCommandLine(const base::CommandLine* command_line) {
-  DCHECK(command_line);
-  if (!command_line)
-    return;
-
-  const base::CommandLine::StringVector& argv = command_line->argv();
-
-  // Set the number of switches in case size > kNumSwitches.
-  base::debug::SetCrashKeyValue(kNumSwitches,
-      base::StringPrintf("%" PRIuS, argv.size() - 1));
-
-  size_t key_i = 1;  // Key names are 1-indexed.
-
-  // Go through the argv, skipping the exec path.
-  for (size_t i = 1; i < argv.size(); ++i) {
-#if defined(OS_WIN)
-    std::string switch_str = base::WideToUTF8(argv[i]);
-#else
-    std::string switch_str = argv[i];
-#endif
-
-    // Skip uninteresting switches.
-    if (IsBoringSwitch(switch_str))
-      continue;
-
-    // Stop if there are too many switches.
-    if (i > crash_keys::kSwitchesMaxCount)
-      break;
-
-    std::string key = base::StringPrintf(kSwitch, key_i++);
-    base::debug::SetCrashKeyValue(key, switch_str);
-  }
-
-  // Clear any remaining switches.
-  for (; key_i <= kSwitchesMaxCount; ++key_i) {
-    base::debug::ClearCrashKey(base::StringPrintf(kSwitch, key_i));
-  }
+void SetCrashKeysFromCommandLine(const base::CommandLine& command_line) {
+  return SetSwitchesFromCommandLine(command_line, &IsBoringSwitch);
 }
 
 void SetActiveExtensions(const std::set<std::string>& extensions) {
diff --git a/chrome/common/crash_keys.h b/chrome/common/crash_keys.h
index 03767fe96..97f85ed0 100644
--- a/chrome/common/crash_keys.h
+++ b/chrome/common/crash_keys.h
@@ -22,8 +22,9 @@
 // reporting server. Returns the size of the union of all keys.
 size_t RegisterChromeCrashKeys();
 
-// Sets the kSwitch and kNumSwitches keys based on the given |command_line|.
-void SetSwitchesFromCommandLine(const base::CommandLine* command_line);
+// Sets the kNumSwitches key and the set of keys named using kSwitchFormat based
+// on the given |command_line|.
+void SetCrashKeysFromCommandLine(const base::CommandLine& command_line);
 
 // Sets the list of "active" extensions in this process. We overload "active" to
 // mean different things depending on the process type:
@@ -49,14 +50,6 @@
 // The URL of the active tab.
 extern const char kActiveURL[];
 
-// Process command line switches. |kSwitch| should be formatted with an integer,
-// in the range [1, kSwitchesMaxCount].
-const size_t kSwitchesMaxCount = 15;
-extern const char kSwitch[];
-// The total number of switches, used to report the total in case more than
-// |kSwitchesMaxCount| are present.
-extern const char kNumSwitches[];
-
 // Installed extensions. |kExtensionID| should be formatted with an integer,
 // in the range [0, kExtensionIDMaxCount).
 const size_t kExtensionIDMaxCount = 10;
diff --git a/chrome/common/crash_keys_unittest.cc b/chrome/common/crash_keys_unittest.cc
index 5dd04b2..42f996a2 100644
--- a/chrome/common/crash_keys_unittest.cc
+++ b/chrome/common/crash_keys_unittest.cc
@@ -57,50 +57,6 @@
 
 CrashKeysTest* CrashKeysTest::self_ = NULL;
 
-TEST_F(CrashKeysTest, Switches) {
-  // Set three switches.
-  {
-    base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-    for (int i = 1; i <= 3; ++i)
-      command_line.AppendSwitch(base::StringPrintf("--flag-%d", i));
-    crash_keys::SetSwitchesFromCommandLine(&command_line);
-    EXPECT_EQ("--flag-1", GetKeyValue("switch-1"));
-    EXPECT_EQ("--flag-2", GetKeyValue("switch-2"));
-    EXPECT_EQ("--flag-3", GetKeyValue("switch-3"));
-    EXPECT_FALSE(HasCrashKey("switch-4"));
-  }
-
-  // Set more than the max switches.
-  {
-    base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-    const int kMax = crash_keys::kSwitchesMaxCount + 2;
-    EXPECT_GT(kMax, 15);
-    for (int i = 1; i <= kMax; ++i)
-      command_line.AppendSwitch(base::StringPrintf("--many-%d", i));
-    crash_keys::SetSwitchesFromCommandLine(&command_line);
-    EXPECT_EQ("--many-1", GetKeyValue("switch-1"));
-    EXPECT_EQ("--many-9", GetKeyValue("switch-9"));
-    EXPECT_EQ("--many-15", GetKeyValue("switch-15"));
-    EXPECT_FALSE(HasCrashKey("switch-16"));
-    EXPECT_FALSE(HasCrashKey("switch-17"));
-  }
-
-  // Set fewer to ensure that old ones are erased.
-  {
-    base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-    for (int i = 1; i <= 5; ++i)
-      command_line.AppendSwitch(base::StringPrintf("--fewer-%d", i));
-    crash_keys::SetSwitchesFromCommandLine(&command_line);
-    EXPECT_EQ("--fewer-1", GetKeyValue("switch-1"));
-    EXPECT_EQ("--fewer-2", GetKeyValue("switch-2"));
-    EXPECT_EQ("--fewer-3", GetKeyValue("switch-3"));
-    EXPECT_EQ("--fewer-4", GetKeyValue("switch-4"));
-    EXPECT_EQ("--fewer-5", GetKeyValue("switch-5"));
-    for (int i = 6; i < 20; ++i)
-      EXPECT_FALSE(HasCrashKey(base::StringPrintf(crash_keys::kSwitch, i)));
-  }
-}
-
 TEST_F(CrashKeysTest, Extensions) {
   // Set three extensions.
   {
@@ -162,20 +118,21 @@
   }
 }
 
-#if defined(OS_CHROMEOS)
 TEST_F(CrashKeysTest, IgnoreBoringFlags) {
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   command_line.AppendSwitch("--enable-logging");
-  command_line.AppendSwitch("--user-data-dir=/tmp");
   command_line.AppendSwitch("--v=1");
-  command_line.AppendSwitch("--default-wallpaper-small=test.png");
 
   command_line.AppendSwitch("--vv=1");
   command_line.AppendSwitch("--vvv");
   command_line.AppendSwitch("--enable-multi-profiles");
   command_line.AppendSwitch("--device-management-url=https://foo/bar");
+#if defined(OS_CHROMEOS)
+  command_line.AppendSwitch("--user-data-dir=/tmp");
+  command_line.AppendSwitch("--default-wallpaper-small=test.png");
+#endif
 
-  crash_keys::SetSwitchesFromCommandLine(&command_line);
+  crash_keys::SetCrashKeysFromCommandLine(command_line);
 
   EXPECT_EQ("--vv=1", GetKeyValue("switch-1"));
   EXPECT_EQ("--vvv", GetKeyValue("switch-2"));
@@ -183,4 +140,3 @@
   EXPECT_EQ("--device-management-url=https://foo/bar", GetKeyValue("switch-4"));
   EXPECT_FALSE(HasCrashKey("switch-5"));
 }
-#endif
diff --git a/chrome/common/media_galleries/picasa_types.cc b/chrome/common/media_galleries/picasa_types.cc
index c39cbf0..6404259 100644
--- a/chrome/common/media_galleries/picasa_types.cc
+++ b/chrome/common/media_galleries/picasa_types.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/common/media_galleries/picasa_types.h"
 
+#include <utility>
+
 #include "base/logging.h"
 #include "chrome/common/media_galleries/pmp_constants.h"
 
@@ -66,26 +68,23 @@
 AlbumTableFiles::~AlbumTableFiles() {
 }
 
-AlbumTableFiles::AlbumTableFiles(RValue other)
-    : indicator_file(other.object->indicator_file.Pass()),
-      category_file(other.object->category_file.Pass()),
-      date_file(other.object->date_file.Pass()),
-      filename_file(other.object->filename_file.Pass()),
-      name_file(other.object->name_file.Pass()),
-      token_file(other.object->token_file.Pass()),
-      uid_file(other.object->uid_file.Pass()) {
-}
+AlbumTableFiles::AlbumTableFiles(AlbumTableFiles&& other)
+    : indicator_file(std::move(other.indicator_file)),
+      category_file(std::move(other.category_file)),
+      date_file(std::move(other.date_file)),
+      filename_file(std::move(other.filename_file)),
+      name_file(std::move(other.name_file)),
+      token_file(std::move(other.token_file)),
+      uid_file(std::move(other.uid_file)) {}
 
-AlbumTableFiles& AlbumTableFiles::operator=(RValue other) {
-  if (this != other.object) {
-    indicator_file = other.object->indicator_file.Pass();
-    category_file = other.object->category_file.Pass();
-    date_file = other.object->date_file.Pass();
-    filename_file = other.object->filename_file.Pass();
-    name_file = other.object->name_file.Pass();
-    token_file = other.object->token_file.Pass();
-    uid_file = other.object->uid_file.Pass();
-  }
+AlbumTableFiles& AlbumTableFiles::operator=(AlbumTableFiles&& other) {
+  indicator_file = std::move(other.indicator_file);
+  category_file = std::move(other.category_file);
+  date_file = std::move(other.date_file);
+  filename_file = std::move(other.filename_file);
+  name_file = std::move(other.name_file);
+  token_file = std::move(other.token_file);
+  uid_file = std::move(other.uid_file);
   return *this;
 }
 
diff --git a/chrome/common/media_galleries/picasa_types.h b/chrome/common/media_galleries/picasa_types.h
index b76946a5..03cc78c 100644
--- a/chrome/common/media_galleries/picasa_types.h
+++ b/chrome/common/media_galleries/picasa_types.h
@@ -55,15 +55,14 @@
 };
 
 struct AlbumTableFiles {
-  MOVE_ONLY_TYPE_FOR_CPP_03(AlbumTableFiles, RValue)
+  MOVE_ONLY_TYPE_FOR_CPP_03(AlbumTableFiles)
  public:
   AlbumTableFiles();
   explicit AlbumTableFiles(const base::FilePath& directory_path);
   ~AlbumTableFiles();
 
-  // C++03 move emulation of this type.
-  AlbumTableFiles(RValue other);
-  AlbumTableFiles& operator=(RValue other);
+  AlbumTableFiles(AlbumTableFiles&& other);
+  AlbumTableFiles& operator=(AlbumTableFiles&& other);
 
   // Special empty file used to confirm existence of table.
   base::File indicator_file;
diff --git a/chrome/installer/setup/BUILD.gn b/chrome/installer/setup/BUILD.gn
index e600847c..e8ec7c5 100644
--- a/chrome/installer/setup/BUILD.gn
+++ b/chrome/installer/setup/BUILD.gn
@@ -24,7 +24,6 @@
       ":lib",
       "//base/allocator",
       "//build/config/sanitizers:deps",
-      "//components/crash/content/app",
       "//components/crash/content/app:app_breakpad_mac_win_to_be_deleted",
     ]
   }
@@ -57,7 +56,6 @@
       "//chrome/common:version_header",
       "//chrome/installer/util",
       "//chrome_elf:constants",
-      "//components/crash/content/app",
       "//components/crash/content/app:app_breakpad_mac_win_to_be_deleted",
       "//components/crash/content/app:lib",
       "//components/crash/core/common",
diff --git a/chrome/installer/setup/installer_crash_reporting.cc b/chrome/installer/setup/installer_crash_reporting.cc
index c41035c..0382b48 100644
--- a/chrome/installer/setup/installer_crash_reporting.cc
+++ b/chrome/installer/setup/installer_crash_reporting.cc
@@ -4,6 +4,10 @@
 
 #include "chrome/installer/setup/installer_crash_reporting.h"
 
+#include <iterator>
+#include <vector>
+
+#include "base/command_line.h"
 #include "base/debug/crash_logging.h"
 #include "base/debug/leak_annotations.h"
 #include "base/logging.h"
@@ -127,7 +131,10 @@
     // kLargeSize, which is wasteful.)
     { kStateKey, crash_keys::kMediumSize },
   };
-  return base::debug::InitCrashKeys(&kFixedKeys[0], arraysize(kFixedKeys),
+  std::vector<base::debug::CrashKey> keys(std::begin(kFixedKeys),
+                                          std::end(kFixedKeys));
+  crash_keys::GetCrashKeysForCommandLineSwitches(&keys);
+  return base::debug::InitCrashKeys(keys.data(), keys.size(),
                                     crash_keys::kChunkMaxLength);
 }
 
@@ -146,4 +153,8 @@
     SetCrashKeyValue(kStateKey, base::UTF16ToUTF8(state_key));
 }
 
+void SetCrashKeysFromCommandLine(const base::CommandLine& command_line) {
+  crash_keys::SetSwitchesFromCommandLine(command_line, nullptr);
+}
+
 }  // namespace installer
diff --git a/chrome/installer/setup/installer_crash_reporting.h b/chrome/installer/setup/installer_crash_reporting.h
index b551667..4542194 100644
--- a/chrome/installer/setup/installer_crash_reporting.h
+++ b/chrome/installer/setup/installer_crash_reporting.h
@@ -5,6 +5,10 @@
 #ifndef CHROME_INSTALLER_SETUP_INSTALLER_CRASH_REPORTING_H_
 #define CHROME_INSTALLER_SETUP_INSTALLER_CRASH_REPORTING_H_
 
+namespace base {
+class CommandLine;
+}  // namespace base
+
 namespace installer {
 
 class InstallerState;
@@ -20,6 +24,9 @@
 // once.
 void SetInitialCrashKeys(const InstallerState& installer_state);
 
+// Sets crash keys for the switches given in |command_line|.
+void SetCrashKeysFromCommandLine(const base::CommandLine& command_line);
+
 }  // namespace installer
 
 #endif  // CHROME_INSTALLER_SETUP_INSTALLER_CRASH_REPORTING_H_
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index d371651..2bee926 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -1653,6 +1653,7 @@
 
   installer::ConfigureCrashReporting(installer_state);
   installer::SetInitialCrashKeys(installer_state);
+  installer::SetCrashKeysFromCommandLine(cmd_line);
 
   // Make sure the process exits cleanly on unexpected errors.
   base::EnableTerminationOnHeapCorruption();
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
index 786e5d67e..49c9254 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
@@ -46,7 +46,8 @@
       : url_tld_token_net_(features::kUrlTldToken + std::string("net")),
         page_link_domain_phishing_(features::kPageLinkDomain +
                                    std::string("phishing.com")),
-        page_term_login_(features::kPageTerm + std::string("login")) {
+        page_term_login_(features::kPageTerm + std::string("login")),
+        page_text_(base::ASCIIToUTF16("login")) {
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -108,6 +109,19 @@
         base::Bind(&PhishingClassifierTest::HandleRequest,
                    base::Unretained(this)));
     ASSERT_TRUE(embedded_test_server()->Start());
+
+    host_resolver()->AddRule("*", "127.0.0.1");
+
+    // No scorer yet, so the classifier is not ready.
+    ASSERT_FALSE(classifier_->is_ready());
+
+    // Now set the scorer.
+    classifier_->set_phishing_scorer(scorer_.get());
+    ASSERT_TRUE(classifier_->is_ready());
+
+    // These tests don't exercise the extraction timing.
+    EXPECT_CALL(*clock_, Now())
+        .WillRepeatedly(::testing::Return(base::TimeTicks::Now()));
   }
 
   void TearDownOnMainThread() override {
@@ -196,6 +210,7 @@
   const std::string url_tld_token_net_;
   const std::string page_link_domain_phishing_;
   const std::string page_term_login_;
+  const base::string16 page_text_;
 };
 
 // This test flakes on Mac with force compositing mode.
@@ -203,31 +218,20 @@
 // Flaky on Chrome OS, running into a memory allocation error.
 // http://crbug.com/544085
 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
-#define MAYBE_TestClassification DISABLED_TestClassification
+#define MAYBE_TestClassificationOfPhishingDotCom \
+  DISABLED_TestClassificationOfPhishingDotCom
 #else
-#define MAYBE_TestClassification TestClassification
+#define MAYBE_TestClassificationOfPhishingDotCom \
+  TestClassificationOfPhishingDotCom
 #endif
-IN_PROC_BROWSER_TEST_F(PhishingClassifierTest, MAYBE_TestClassification) {
-  host_resolver()->AddRule("*", "127.0.0.1");
-
-  // No scorer yet, so the classifier is not ready.
-  ASSERT_FALSE(classifier_->is_ready());
-
-  // Now set the scorer.
-  classifier_->set_phishing_scorer(scorer_.get());
-  ASSERT_TRUE(classifier_->is_ready());
-
-  // This test doesn't exercise the extraction timing.
-  EXPECT_CALL(*clock_, Now())
-      .WillRepeatedly(::testing::Return(base::TimeTicks::Now()));
-
-  base::string16 page_text = base::ASCIIToUTF16("login");
+IN_PROC_BROWSER_TEST_F(PhishingClassifierTest,
+                       MAYBE_TestClassificationOfPhishingDotCom) {
   float phishy_score;
   FeatureMap features;
 
   LoadHtml("host.net",
       "<html><body><a href=\"http://phishing.com/\">login</a></body></html>");
-  EXPECT_TRUE(RunPhishingClassifier(&page_text, &phishy_score, &features));
+  EXPECT_TRUE(RunPhishingClassifier(&page_text_, &phishy_score, &features));
   // Note: features.features() might contain other features that simply aren't
   // in the model.
   EXPECT_THAT(features.features(),
@@ -235,11 +239,27 @@
                     Contains(Pair(page_link_domain_phishing_, 1.0)),
                     Contains(Pair(page_term_login_, 1.0))));
   EXPECT_FLOAT_EQ(0.5, phishy_score);
+}
+
+// This test flakes on Mac with force compositing mode.
+// http://crbug.com/316709
+// Flaky on Chrome OS, running into a memory allocation error.
+// http://crbug.com/544085
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
+#define MAYBE_TestClassificationOfSafeDotCom \
+  DISABLED_TestClassificationOfSafeDotCom
+#else
+#define MAYBE_TestClassificationOfSafeDotCom TestClassificationOfSafeDotCom
+#endif
+IN_PROC_BROWSER_TEST_F(PhishingClassifierTest,
+                       MAYBE_TestClassificationOfSafeDotCom) {
+  float phishy_score;
+  FeatureMap features;
 
   // Change the link domain to something non-phishy.
   LoadHtml("host.net",
            "<html><body><a href=\"http://safe.com/\">login</a></body></html>");
-  EXPECT_FALSE(RunPhishingClassifier(&page_text, &phishy_score, &features));
+  EXPECT_FALSE(RunPhishingClassifier(&page_text_, &phishy_score, &features));
   EXPECT_THAT(features.features(),
               AllOf(Contains(Pair(url_tld_token_net_, 1.0)),
                     Contains(Pair(page_term_login_, 1.0))));
@@ -247,12 +267,43 @@
               Not(Contains(Pair(page_link_domain_phishing_, 1.0))));
   EXPECT_GE(phishy_score, 0.0);
   EXPECT_LT(phishy_score, 0.5);
+}
+
+// This test flakes on Mac with force compositing mode.
+// http://crbug.com/316709
+// Flaky on Chrome OS, running into a memory allocation error.
+// http://crbug.com/544085
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
+#define MAYBE_TestClassificationWhenNoTld DISABLED_TestClassificationWhenNoTld
+#else
+#define MAYBE_TestClassificationWhenNoTld TestClassificationWhenNoTld
+#endif
+IN_PROC_BROWSER_TEST_F(PhishingClassifierTest,
+                       MAYBE_TestClassificationWhenNoTld) {
+  float phishy_score;
+  FeatureMap features;
 
   // Extraction should fail for this case since there is no TLD.
   LoadHtml("localhost", "<html><body>content</body></html>");
-  EXPECT_FALSE(RunPhishingClassifier(&page_text, &phishy_score, &features));
+  EXPECT_FALSE(RunPhishingClassifier(&page_text_, &phishy_score, &features));
   EXPECT_EQ(0U, features.features().size());
   EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score);
+}
+
+// This test flakes on Mac with force compositing mode.
+// http://crbug.com/316709
+// Flaky on Chrome OS, running into a memory allocation error.
+// http://crbug.com/544085
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
+#define MAYBE_TestClassificationWhenNotHttp \
+  DISABLED_TestClassificationWhenNotHttp
+#else
+#define MAYBE_TestClassificationWhenNotHttp TestClassificationWhenNotHttp
+#endif
+IN_PROC_BROWSER_TEST_F(PhishingClassifierTest,
+                       MAYBE_TestClassificationWhenNotHttp) {
+  float phishy_score;
+  FeatureMap features;
 
   // Extraction should also fail for this case because the URL is not http.
   net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
@@ -263,13 +314,30 @@
   GURL test_url = https_server.GetURL("/title1.html");
   ui_test_utils::NavigateToURL(browser(),
                                test_url.ReplaceComponents(replace_host));
-  EXPECT_FALSE(RunPhishingClassifier(&page_text, &phishy_score, &features));
+  EXPECT_FALSE(RunPhishingClassifier(&page_text_, &phishy_score, &features));
   EXPECT_EQ(0U, features.features().size());
   EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score);
+}
+
+// This test flakes on Mac with force compositing mode.
+// http://crbug.com/316709
+// Flaky on Chrome OS, running into a memory allocation error.
+// http://crbug.com/544085
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
+#define MAYBE_TestClassificationWhenPostRequest \
+  DISABLED_TestClassificationWhenPostRequest
+#else
+#define MAYBE_TestClassificationWhenPostRequest \
+  TestClassificationWhenPostRequest
+#endif
+IN_PROC_BROWSER_TEST_F(PhishingClassifierTest,
+                       MAYBE_TestClassificationWhenPostRequest) {
+  float phishy_score;
+  FeatureMap features;
 
   // Extraction should fail for this case because the URL is a POST request.
   LoadHtmlPost("host.net", "<html><body>content</body></html>");
-  EXPECT_FALSE(RunPhishingClassifier(&page_text, &phishy_score, &features));
+  EXPECT_FALSE(RunPhishingClassifier(&page_text_, &phishy_score, &features));
   EXPECT_EQ(0U, features.features().size());
   EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score);
 }
@@ -281,11 +349,6 @@
 #define MAYBE_DisableDetection DisableDetection
 #endif
 IN_PROC_BROWSER_TEST_F(PhishingClassifierTest, MAYBE_DisableDetection) {
-  // No scorer yet, so the classifier is not ready.
-  EXPECT_FALSE(classifier_->is_ready());
-
-  // Now set the scorer.
-  classifier_->set_phishing_scorer(scorer_.get());
   EXPECT_TRUE(classifier_->is_ready());
 
   // Set a NULL scorer, which turns detection back off.
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc
index 4109708..ce70b2b 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc
@@ -25,12 +25,11 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/browser_message_filter.h"
 #include "content/public/browser/browser_thread.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"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/renderer/render_frame.h"
-#include "content/public/renderer/render_view.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
@@ -41,8 +40,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebView.h"
 #include "url/gurl.h"
 
 using base::ASCIIToUTF16;
@@ -144,9 +141,6 @@
   }
 
  protected:
-  PhishingClassifierDelegateTest()
-      : render_view_routing_id_(MSG_ROUTING_NONE) {}
-
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(switches::kSingleProcess);
 #if defined(OS_WIN)
@@ -157,12 +151,10 @@
 
   void SetUpOnMainThread() override {
     intercepting_filter_ = new InterceptingMessageFilter();
-    render_view_routing_id_ =
-        GetWebContents()->GetRenderViewHost()->GetRoutingID();
 
     GetWebContents()->GetRenderProcessHost()->AddFilter(
         intercepting_filter_.get());
-    content::RenderFrame* render_frame = GetRenderView()->GetMainRenderFrame();
+    content::RenderFrame* render_frame = GetRenderFrame();
     classifier_ = new StrictMock<MockPhishingClassifier>(render_frame);
     delegate_ = PhishingClassifierDelegate::Create(render_frame, classifier_);
 
@@ -222,8 +214,12 @@
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
 
-  content::RenderView* GetRenderView() {
-    return content::RenderView::FromRoutingID(render_view_routing_id_);
+  content::RenderFrame* GetRenderFrame() {
+    int render_frame_routing_id =
+        GetWebContents()->GetMainFrame()->GetRoutingID();
+    content::RenderFrame* render_frame =
+        content::RenderFrame::FromRoutingID(render_frame_routing_id);
+    return render_frame;
   }
 
   // Returns the URL that was loaded.
@@ -252,7 +248,6 @@
   std::string response_content_;
   scoped_ptr<ClientPhishingRequest> verdict_;
   StrictMock<MockPhishingClassifier>* classifier_;  // Owned by |delegate_|.
-  int32_t render_view_routing_id_;
   PhishingClassifierDelegate* delegate_;  // Owned by the RenderView.
   scoped_refptr<content::MessageLoopRunner> runner_;
 };
diff --git a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
index 1494c49d..06414c3 100644
--- a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
@@ -29,10 +29,10 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/interstitial_page.h"
-#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/render_frame.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "net/dns/mock_host_resolver.h"
@@ -42,8 +42,8 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebScriptSource.h"
-#include "third_party/WebKit/public/web/WebView.h"
 
 using ::testing::DoAll;
 using ::testing::Invoke;
@@ -66,8 +66,7 @@
   }
 
  protected:
-  PhishingDOMFeatureExtractorTest()
-      : render_view_routing_id_(MSG_ROUTING_NONE), weak_factory_(this) {}
+  PhishingDOMFeatureExtractorTest() : weak_factory_(this) {}
 
   ~PhishingDOMFeatureExtractorTest() override {}
 
@@ -80,8 +79,6 @@
   }
 
   void SetUpOnMainThread() override {
-    render_view_routing_id_ =
-        GetWebContents()->GetRenderViewHost()->GetRoutingID();
     extractor_.reset(new PhishingDOMFeatureExtractor(&clock_));
 
     embedded_test_server()->RegisterRequestHandler(
@@ -91,8 +88,8 @@
     host_resolver()->AddRule("*", "127.0.0.1");
   }
 
-  // Runs the DOMFeatureExtractor on the RenderView, waiting for the
-  // completion callback.  Returns the success boolean from the callback.
+  // Runs the DOMFeatureExtractor, waiting for the completion callback.
+  // Returns the success boolean from the callback.
   bool ExtractFeatures(FeatureMap* features) {
     success_ = false;
     PostTaskToInProcessRendererAndWait(
@@ -103,9 +100,11 @@
   }
 
   blink::WebFrame* GetWebFrame() {
-    content::RenderView* render_view =
-        content::RenderView::FromRoutingID(render_view_routing_id_);
-    return render_view->GetWebView()->mainFrame();
+    int render_frame_routing_id =
+        GetWebContents()->GetMainFrame()->GetRoutingID();
+    content::RenderFrame* render_frame =
+        content::RenderFrame::FromRoutingID(render_frame_routing_id);
+    return render_frame->GetWebFrame();
   }
 
   void ExtractFeaturesInternal(FeatureMap* features) {
@@ -172,8 +171,6 @@
     return url;
   }
 
-  int32 render_view_routing_id_;
-
   // Map of url -> response body for network requests from the renderer.
   // Any urls not in this map are served a 404 error.
   std::map<std::string, std::string> responses_;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 8ce7c9f..523198f 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1645,14 +1645,14 @@
             chrome_tests_unit_gypi_values.chrome_unit_tests_offline_pages_sources,
             ".",
             "//chrome")
+    deps += [
+      ":unit_tests_java",
+      "//v8:v8_external_startup_data_assets",
+    ]
     deps -= [ "//third_party/libaddressinput" ]
 
     android_manifest =
         "//chrome/test/android/unit_tests_apk/AndroidManifest.xml"
-    apk_deps = [
-      ":unit_tests_java",
-      "//v8:v8_external_startup_data_assets",
-    ]
     isolate_file = "../unit_tests.isolate"
 
     # Some android targets still depend on --gc-sections to link.
diff --git a/chromecast/base/metrics/cast_metrics_helper.cc b/chromecast/base/metrics/cast_metrics_helper.cc
index 30f2810..9680c800 100644
--- a/chromecast/base/metrics/cast_metrics_helper.cc
+++ b/chromecast/base/metrics/cast_metrics_helper.cc
@@ -91,6 +91,7 @@
 CastMetricsHelper::CastMetricsHelper(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner)
     : task_runner_(task_runner),
+      session_id_("00000000000000000000000000000000"),
       metrics_sink_(NULL),
       logged_first_audio_(false),
       record_action_callback_(base::Bind(&base::RecordComputedAction)) {
diff --git a/components/BUILD.gn b/components/BUILD.gn
index c032af8..fa9fe7a 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -490,26 +490,23 @@
 
     deps += [
       "//components/invalidation/impl",
+      "//components/invalidation/impl:java",
       "//components/safe_json",
+      "//components/safe_json/android:safe_json_java",
       "//components/signin/core/browser",
+      "//components/signin/core/browser/android:java",
+      "//components/variations/android:variations_java",
+      "//content/public/android:content_java",
       "//content/public/android:content_java",
       "//content/public/browser",
       "//net",
+      "//ui/android:ui_java",
       "//ui/base",
       "//ui/gfx",
     ]
 
-    apk_deps = [
-      "//components/invalidation/impl:java",
-      "//components/safe_json/android:safe_json_java",
-      "//components/signin/core/browser/android:java",
-      "//components/variations/android:variations_java",
-      "//content/public/android:content_java",
-      "//ui/android:ui_java",
-    ]
-
     if (enable_configuration_policy) {
-      apk_deps += [ "//components/policy/android:policy_java" ]
+      deps += [ "//components/policy/android:policy_java" ]
     }
   }
 
@@ -702,7 +699,7 @@
     isolate_file = "components_browsertests.isolate"
     android_manifest =
         "${target_gen_dir}/components_browsertests_manifest/AndroidManifest.xml"
-    apk_deps = [
+    deps += [
       ":components_browsertests_assets",
       ":components_browsertests_java",
       ":components_browsertests_manifest",
diff --git a/components/bitmap_uploader/bitmap_uploader.cc b/components/bitmap_uploader/bitmap_uploader.cc
index d5709522..2a9a081 100644
--- a/components/bitmap_uploader/bitmap_uploader.cc
+++ b/components/bitmap_uploader/bitmap_uploader.cc
@@ -23,7 +23,7 @@
 const uint32_t g_transparent_color = 0x00000000;
 
 void LostContext(void*) {
-  DCHECK(false);
+  // TODO(fsamuel): Figure out if there's something useful to do here.
 }
 
 void OnGotContentHandlerID(uint32_t content_handler_id) {}
@@ -66,7 +66,7 @@
   gles2_context_ = MojoGLES2CreateContext(
       gles2_client.PassInterface().PassHandle().release().value(),
       nullptr,
-      &LostContext, NULL, mojo::Environment::GetDefaultAsyncWaiter());
+      &LostContext, nullptr, mojo::Environment::GetDefaultAsyncWaiter());
   MojoGLES2MakeCurrent(gles2_context_);
 }
 
diff --git a/components/browser_sync/browser/profile_sync_service.cc b/components/browser_sync/browser/profile_sync_service.cc
index 04cb904..3b8bf73 100644
--- a/components/browser_sync/browser/profile_sync_service.cc
+++ b/components/browser_sync/browser/profile_sync_service.cc
@@ -297,6 +297,23 @@
 
   sync_prefs_.AddSyncPrefObserver(this);
 
+  SyncInitialState sync_state = CAN_START;
+  if (!IsSignedIn()) {
+    sync_state = NOT_SIGNED_IN;
+  } else if (IsManaged()) {
+    sync_state = IS_MANAGED;
+  } else if (!IsSyncRequested()) {
+    if (HasSyncSetupCompleted()) {
+      sync_state = NOT_REQUESTED;
+    } else {
+      sync_state = NOT_REQUESTED_NOT_SETUP;
+    }
+  } else if (!HasSyncSetupCompleted()) {
+    sync_state = NEEDS_CONFIRMATION;
+  }
+  UMA_HISTOGRAM_ENUMERATION("Sync.InitialState", sync_state,
+                            SYNC_INITIAL_STATE_LIMIT);
+
   // If sync isn't allowed, the only thing to do is to turn it off.
   if (!IsSyncAllowed()) {
     RequestStop(CLEAR_DATA);
diff --git a/components/browser_sync/browser/profile_sync_service.h b/components/browser_sync/browser/profile_sync_service.h
index 6f6a9345..e2203f24 100644
--- a/components/browser_sync/browser/profile_sync_service.h
+++ b/components/browser_sync/browser/profile_sync_service.h
@@ -640,6 +640,23 @@
     AUTH_ERROR_LIMIT
   };
 
+  // The initial state of sync, for the Sync.InitialState histogram. Even if
+  // this value is CAN_START, sync startup might fail for reasons that we may
+  // want to consider logging in the future, such as sync being disabled via
+  // Google Dashboard (birthday error), a passphrase needed for decryption, or
+  // the version of Chrome being too old. This enum is used to back a UMA
+  // histogram, and should therefore be treated as append-only.
+  enum SyncInitialState {
+    CAN_START,                // Sync can attempt to start up.
+    NOT_SIGNED_IN,            // There is no signed in user.
+    NOT_REQUESTED,            // The user turned off sync.
+    NOT_REQUESTED_NOT_SETUP,  // The user turned off sync and setup completed
+                              // is false. Might indicate a stop-and-clear.
+    NEEDS_CONFIRMATION,       // The user must confirm sync settings.
+    IS_MANAGED,               // Sync is disallowed by enterprise policy.
+    SYNC_INITIAL_STATE_LIMIT
+  };
+
   friend class ProfileSyncServicePasswordTest;
   friend class SyncTest;
   friend class TestProfileSyncService;
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 861bd3a5..1683204b 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -125,6 +125,7 @@
     ],
     'crash_unittest_sources': [
       'crash/content/app/crash_keys_win_unittest.cc',
+      'crash/core/common/crash_keys_unittest.cc',
       'crash/core/common/objc_zombie_unittest.mm',
     ],
     'crx_file_unittest_sources': [
diff --git a/components/crash/core/common/BUILD.gn b/components/crash/core/common/BUILD.gn
index e602f4e..dc7216dc 100644
--- a/components/crash/core/common/BUILD.gn
+++ b/components/crash/core/common/BUILD.gn
@@ -22,14 +22,17 @@
 
 source_set("unit_tests") {
   testonly = true
+  sources = [
+    "crash_keys_unittest.cc",
+  ]
+
+  deps = [
+    ":common",
+    "//base",
+    "//testing/gtest",
+  ]
+
   if (is_mac || is_ios) {
-    sources = [
-      "objc_zombie_unittest.mm",
-    ]
-    deps = [
-      ":common",
-      "//base",
-      "//testing/gtest",
-    ]
+    sources += [ "objc_zombie_unittest.mm" ]
   }
 }
diff --git a/components/crash/core/common/crash_keys.cc b/components/crash/core/common/crash_keys.cc
index 3c3f2fb..f34409e 100644
--- a/components/crash/core/common/crash_keys.cc
+++ b/components/crash/core/common/crash_keys.cc
@@ -4,11 +4,14 @@
 
 #include "components/crash/core/common/crash_keys.h"
 
+#include "base/command_line.h"
 #include "base/debug/crash_logging.h"
 #include "base/format_macros.h"
+#include "base/logging.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 
 namespace crash_keys {
 
@@ -33,6 +36,9 @@
 const char kNumVariations[] = "num-experiments";
 const char kVariations[] = "variations";
 
+const char kSwitchFormat[] = "switch-%" PRIuS;
+const char kNumSwitches[] = "num-switches";
+
 const char kBug464926CrashKey[] = "bug-464926-info";
 
 #if defined(OS_MACOSX)
@@ -100,4 +106,64 @@
   base::debug::SetCrashKeyValue(kVariations, variations_string);
 }
 
+void GetCrashKeysForCommandLineSwitches(
+    std::vector<base::debug::CrashKey>* keys) {
+  DCHECK(keys);
+  base::debug::CrashKey crash_key = { kNumSwitches, kSmallSize };
+  keys->push_back(crash_key);
+
+  // Use static storage for formatted key names, since they will persist for
+  // the duration of the program.
+  static char formatted_keys[kSwitchesMaxCount][sizeof(kSwitchFormat) + 1] =
+      {{ 0 }};
+  const size_t formatted_key_len = sizeof(formatted_keys[0]);
+
+  // sizeof(kSwitchFormat) is platform-dependent, so make sure formatted_keys
+  // actually have space for a 2-digit switch number plus null-terminator.
+  static_assert(formatted_key_len >= 10,
+                "insufficient space for \"switch-NN\"");
+
+  for (size_t i = 0; i < kSwitchesMaxCount; ++i) {
+    // Name the keys using 1-based indexing.
+    int n = base::snprintf(formatted_keys[i], formatted_key_len, kSwitchFormat,
+                           i + 1);
+    DCHECK_GT(n, 0);
+    base::debug::CrashKey crash_key = { formatted_keys[i], kSmallSize };
+    keys->push_back(crash_key);
+  }
+}
+
+void SetSwitchesFromCommandLine(const base::CommandLine& command_line,
+                                SwitchFilterFunction skip_filter) {
+  const base::CommandLine::StringVector& argv = command_line.argv();
+
+  // Set the number of switches in case size > kNumSwitches.
+  base::debug::SetCrashKeyValue(kNumSwitches,
+      base::StringPrintf("%" PRIuS, argv.size() - 1));
+
+  size_t key_i = 1;  // Key names are 1-indexed.
+
+  // Go through the argv, skipping the exec path. Stop if there are too many
+  // switches to hold in crash keys.
+  for (size_t i = 1; i < argv.size() && key_i <= crash_keys::kSwitchesMaxCount;
+       ++i) {
+#if defined(OS_WIN)
+    std::string switch_str = base::WideToUTF8(argv[i]);
+#else
+    std::string switch_str = argv[i];
+#endif
+
+    // Skip uninteresting switches.
+    if (skip_filter && (*skip_filter)(switch_str))
+      continue;
+
+    std::string key = base::StringPrintf(kSwitchFormat, key_i++);
+    base::debug::SetCrashKeyValue(key, switch_str);
+  }
+
+  // Clear any remaining switches.
+  for (; key_i <= kSwitchesMaxCount; ++key_i)
+    base::debug::ClearCrashKey(base::StringPrintf(kSwitchFormat, key_i));
+}
+
 }  // namespace crash_keys
diff --git a/components/crash/core/common/crash_keys.h b/components/crash/core/common/crash_keys.h
index 6ddb3562..2265505 100644
--- a/components/crash/core/common/crash_keys.h
+++ b/components/crash/core/common/crash_keys.h
@@ -8,8 +8,13 @@
 #include <string>
 #include <vector>
 
+#include "base/debug/crash_logging.h"
 #include "build/build_config.h"
 
+namespace base {
+class CommandLine;
+}  // namespace base
+
 namespace crash_keys {
 
 // Sets the ID (which may either be a full GUID or a GUID that was already
@@ -21,6 +26,20 @@
 // Sets the list of active experiment/variations info.
 void SetVariationsList(const std::vector<std::string>& variations);
 
+// Adds a common set of crash keys for holding command-line switches to |keys|.
+void GetCrashKeysForCommandLineSwitches(
+    std::vector<base::debug::CrashKey>* keys);
+
+// A function returning true if |flag| is a switch that should be filtered out
+// of crash keys.
+using SwitchFilterFunction = bool (*)(const std::string& flag);
+
+// Sets the kNumSwitches key and a set of keys named using kSwitchFormat based
+// on the given |command_line|. If |skip_filter| is not null, ignore any switch
+// for which it returns true.
+void SetSwitchesFromCommandLine(const base::CommandLine& command_line,
+                                SwitchFilterFunction skip_filter);
+
 // Crash Key Constants /////////////////////////////////////////////////////////
 
 // kChunkMaxLength is the platform-specific maximum size that a value in a
@@ -71,6 +90,18 @@
 // typically set by SetExperimentList.
 extern const char kVariations[];
 
+// The maximum number of command line switches to process. |kSwitchFormat|
+// should be formatted with an integer in the range [1, kSwitchesMaxCount].
+const size_t kSwitchesMaxCount = 15;
+
+// A printf-style format string naming the set of crash keys corresponding to
+// at most |kSwitchesMaxCount| command line switches.
+extern const char kSwitchFormat[];
+
+// The total number of switches, used to report the total in case more than
+// |kSwitchesMaxCount| are present.
+extern const char kNumSwitches[];
+
 // Used to help investigate bug 464926.
 extern const char kBug464926CrashKey[];
 
diff --git a/components/crash/core/common/crash_keys_unittest.cc b/components/crash/core/common/crash_keys_unittest.cc
new file mode 100644
index 0000000..ef8a802
--- /dev/null
+++ b/components/crash/core/common/crash_keys_unittest.cc
@@ -0,0 +1,140 @@
+// Copyright 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 "components/crash/core/common/crash_keys.h"
+
+#include <map>
+#include <string>
+
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/debug/crash_logging.h"
+#include "base/format_macros.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class CrashKeysTest : public testing::Test {
+ public:
+  void SetUp() override {
+    self_ = this;
+    base::debug::SetCrashKeyReportingFunctions(
+        &SetCrashKeyValue, &ClearCrashKey);
+
+    std::vector<base::debug::CrashKey> keys;
+    crash_keys::GetCrashKeysForCommandLineSwitches(&keys);
+    base::debug::InitCrashKeys(keys.data(), keys.size(),
+                               crash_keys::kChunkMaxLength);
+    ASSERT_FALSE(keys.empty());
+  }
+
+  void TearDown() override {
+    base::debug::ResetCrashLoggingForTesting();
+    self_ = NULL;
+  }
+
+  bool HasCrashKey(const std::string& key) {
+    return keys_.find(key) != keys_.end();
+  }
+
+  std::string GetKeyValue(const std::string& key) {
+    std::map<std::string, std::string>::const_iterator it = keys_.find(key);
+    if (it == keys_.end())
+      return std::string();
+    return it->second;
+  }
+
+ private:
+  static void SetCrashKeyValue(const base::StringPiece& key,
+                               const base::StringPiece& value) {
+    self_->keys_[key.as_string()] = value.as_string();
+  }
+
+  static void ClearCrashKey(const base::StringPiece& key) {
+    self_->keys_.erase(key.as_string());
+  }
+
+  static CrashKeysTest* self_;
+
+  std::map<std::string, std::string> keys_;
+};
+
+CrashKeysTest* CrashKeysTest::self_ = NULL;
+
+TEST_F(CrashKeysTest, Switches) {
+  // Set three switches.
+  {
+    base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+    for (size_t i = 1; i <= 3; ++i)
+      command_line.AppendSwitch(base::StringPrintf("--flag-%" PRIuS, i));
+    crash_keys::SetSwitchesFromCommandLine(command_line, nullptr);
+    EXPECT_EQ("--flag-1", GetKeyValue("switch-1"));
+    EXPECT_EQ("--flag-2", GetKeyValue("switch-2"));
+    EXPECT_EQ("--flag-3", GetKeyValue("switch-3"));
+    EXPECT_FALSE(HasCrashKey("switch-4"));
+  }
+
+  // Set more than the max switches.
+  {
+    base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+    const size_t kMax = crash_keys::kSwitchesMaxCount + 2;
+    EXPECT_GT(kMax, static_cast<size_t>(15));
+    for (size_t i = 1; i <= kMax; ++i)
+      command_line.AppendSwitch(base::StringPrintf("--many-%" PRIuS, i));
+    crash_keys::SetSwitchesFromCommandLine(command_line, nullptr);
+    EXPECT_EQ("--many-1", GetKeyValue("switch-1"));
+    EXPECT_EQ("--many-9", GetKeyValue("switch-9"));
+    EXPECT_EQ("--many-15", GetKeyValue("switch-15"));
+    EXPECT_FALSE(HasCrashKey("switch-16"));
+    EXPECT_FALSE(HasCrashKey("switch-17"));
+  }
+
+  // Set fewer to ensure that old ones are erased.
+  {
+    base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+    for (size_t i = 1; i <= 5; ++i)
+      command_line.AppendSwitch(base::StringPrintf("--fewer-%" PRIuS, i));
+    crash_keys::SetSwitchesFromCommandLine(command_line, nullptr);
+    EXPECT_EQ("--fewer-1", GetKeyValue("switch-1"));
+    EXPECT_EQ("--fewer-2", GetKeyValue("switch-2"));
+    EXPECT_EQ("--fewer-3", GetKeyValue("switch-3"));
+    EXPECT_EQ("--fewer-4", GetKeyValue("switch-4"));
+    EXPECT_EQ("--fewer-5", GetKeyValue("switch-5"));
+    for (size_t i = 6; i < 20; ++i)
+      EXPECT_FALSE(HasCrashKey(base::StringPrintf(crash_keys::kSwitchFormat,
+                                                  i)));
+  }
+}
+
+namespace {
+
+bool IsBoringFlag(const std::string& flag) {
+  return flag.compare("--boring") == 0;
+}
+
+}  // namespace
+
+TEST_F(CrashKeysTest, FilterFlags) {
+  using crash_keys::kSwitchesMaxCount;
+
+  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+  command_line.AppendSwitch("--not-boring-1");
+  command_line.AppendSwitch("--boring");
+
+  // Include the max number of non-boring switches, to make sure that only the
+  // switches actually included in the crash keys are counted.
+  for (size_t i = 2; i <= kSwitchesMaxCount; ++i)
+    command_line.AppendSwitch(base::StringPrintf("--not-boring-%" PRIuS, i));
+
+  crash_keys::SetSwitchesFromCommandLine(command_line, &IsBoringFlag);
+
+  // If the boring keys are filtered out, every single key should now be
+  // not-boring.
+  for (size_t i = 1; i <= kSwitchesMaxCount; ++i) {
+    std::string switch_name = base::StringPrintf(crash_keys::kSwitchFormat, i);
+    std::string switch_value = base::StringPrintf("--not-boring-%" PRIuS, i);
+    EXPECT_EQ(switch_value, GetKeyValue(switch_name)) << "switch_name is " <<
+        switch_name;
+  }
+}
diff --git a/components/flags_ui.gypi b/components/flags_ui.gypi
index b5292cd..f4c6275 100644
--- a/components/flags_ui.gypi
+++ b/components/flags_ui.gypi
@@ -17,6 +17,7 @@
         '../components/components_strings.gyp:components_strings',
         '../ui/base/ui_base.gyp:ui_base',
         'flags_ui_switches',
+        'pref_registry',
       ],
       'sources': [
         # Note: sources list duplicated in GN build.
diff --git a/components/flags_ui/BUILD.gn b/components/flags_ui/BUILD.gn
index 3125261..8669902 100644
--- a/components/flags_ui/BUILD.gn
+++ b/components/flags_ui/BUILD.gn
@@ -22,6 +22,7 @@
     ":switches",
     "//base",
     "//base:prefs",
+    "//components/pref_registry",
     "//components/strings",
     "//ui/base",
   ]
diff --git a/components/flags_ui/DEPS b/components/flags_ui/DEPS
index 112ca0e..e7e9488 100644
--- a/components/flags_ui/DEPS
+++ b/components/flags_ui/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/pref_registry",
   "+grit/components_strings.h",
   "+ui/base",
 ]
diff --git a/components/flags_ui/pref_service_flags_storage.cc b/components/flags_ui/pref_service_flags_storage.cc
index 544f0dd..758070d 100644
--- a/components/flags_ui/pref_service_flags_storage.cc
+++ b/components/flags_ui/pref_service_flags_storage.cc
@@ -4,10 +4,12 @@
 
 #include "components/flags_ui/pref_service_flags_storage.h"
 
+#include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/scoped_user_pref_update.h"
 #include "base/values.h"
 #include "components/flags_ui/flags_ui_pref_names.h"
+#include "components/pref_registry/pref_registry_syncable.h"
 
 namespace flags_ui {
 
@@ -45,4 +47,17 @@
   return true;
 }
 
+// static
+void PrefServiceFlagsStorage::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterListPref(prefs::kEnabledLabsExperiments);
+}
+
+#if defined(OS_CHROMEOS)
+// static
+void PrefServiceFlagsStorage::RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterListPref(prefs::kEnabledLabsExperiments);
+}
+#endif  // defined(OS_CHROMEOS)
+
 }  // namespace flags_ui
diff --git a/components/flags_ui/pref_service_flags_storage.h b/components/flags_ui/pref_service_flags_storage.h
index a559f8c09..b230ac11 100644
--- a/components/flags_ui/pref_service_flags_storage.h
+++ b/components/flags_ui/pref_service_flags_storage.h
@@ -5,10 +5,16 @@
 #ifndef COMPONENTS_FLAGS_UI_PREF_SERVICE_FLAGS_STORAGE_H_
 #define COMPONENTS_FLAGS_UI_PREF_SERVICE_FLAGS_STORAGE_H_
 
-#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "build/build_config.h"
 #include "components/flags_ui/flags_storage.h"
 
 class PrefService;
+class PrefRegistrySimple;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
 
 namespace flags_ui {
 
@@ -22,8 +28,16 @@
   std::set<std::string> GetFlags() override;
   bool SetFlags(const std::set<std::string>& flags) override;
 
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
+#if defined(OS_CHROMEOS)
+  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+#endif  // defined(OS_CHROMEOS)
+
  private:
   PrefService* prefs_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrefServiceFlagsStorage);
 };
 
 }  // namespace flags_ui
diff --git a/components/gcm_driver/crypto/gcm_encryption_provider.cc b/components/gcm_driver/crypto/gcm_encryption_provider.cc
index 3378c61..0e3873e 100644
--- a/components/gcm_driver/crypto/gcm_encryption_provider.cc
+++ b/components/gcm_driver/crypto/gcm_encryption_provider.cc
@@ -127,7 +127,8 @@
 
 void GCMEncryptionProvider::DidGetPublicKey(const std::string& app_id,
                                             const PublicKeyCallback& callback,
-                                            const KeyPair& pair) {
+                                            const KeyPair& pair,
+                                            const std::string& auth_secret) {
   if (!pair.IsInitialized()) {
     key_store_->CreateKeys(
         app_id, base::Bind(&GCMEncryptionProvider::DidCreatePublicKey,
@@ -136,19 +137,21 @@
   }
 
   DCHECK_EQ(KeyPair::ECDH_P256, pair.type());
-  callback.Run(pair.public_key());
+  callback.Run(pair.public_key(), auth_secret);
 }
 
 void GCMEncryptionProvider::DidCreatePublicKey(
     const PublicKeyCallback& callback,
-    const KeyPair& pair) {
+    const KeyPair& pair,
+    const std::string& auth_secret) {
   if (!pair.IsInitialized()) {
-    callback.Run(std::string());
+    callback.Run(std::string() /* public_key */,
+                 std::string() /* auth_secret */);
     return;
   }
 
   DCHECK_EQ(KeyPair::ECDH_P256, pair.type());
-  callback.Run(pair.public_key());
+  callback.Run(pair.public_key(), auth_secret);
 }
 
 void GCMEncryptionProvider::DecryptMessageWithKey(
@@ -158,7 +161,8 @@
     const std::string& salt,
     const std::string& dh,
     uint64_t rs,
-    const KeyPair& pair) {
+    const KeyPair& pair,
+    const std::string& auth_secret) {
   if (!pair.IsInitialized()) {
     DLOG(ERROR) << "Unable to retrieve the keys for the incoming message.";
     failure_callback.Run(DECRYPTION_FAILURE_NO_KEYS);
@@ -177,8 +181,8 @@
 
   std::string plaintext;
 
-  GCMMessageCryptographer cryptographer(
-      GCMMessageCryptographer::Label::P256, pair.public_key(), dh);
+  GCMMessageCryptographer cryptographer(GCMMessageCryptographer::Label::P256,
+                                        pair.public_key(), dh, auth_secret);
   if (!cryptographer.Decrypt(message.raw_data, shared_secret, salt, rs,
                              &plaintext)) {
     DLOG(ERROR) << "Unable to decrypt the incoming data.";
diff --git a/components/gcm_driver/crypto/gcm_encryption_provider.h b/components/gcm_driver/crypto/gcm_encryption_provider.h
index 2e7f81b..3757d722 100644
--- a/components/gcm_driver/crypto/gcm_encryption_provider.h
+++ b/components/gcm_driver/crypto/gcm_encryption_provider.h
@@ -28,8 +28,9 @@
 // and decryption of incoming messages.
 class GCMEncryptionProvider {
  public:
-  // Callback to be invoked when the public encryption key is available.
-  using PublicKeyCallback = base::Callback<void(const std::string&)>;
+  // Callback to be invoked when the public key and auth secret are available.
+  using PublicKeyCallback = base::Callback<void(const std::string&,
+                                                const std::string&)>;
 
   // Callback to be invoked when a message has been decrypted.
   using MessageDecryptedCallback = base::Callback<void(const IncomingMessage&)>;
@@ -67,8 +68,8 @@
       const base::FilePath& store_path,
       const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner);
 
-  // Retrieves the public encryption key belonging to |app_id|. If no keys have
-  // been associated with |app_id| yet, they will be created.
+  // Retrieves the public key and authentication secret associated with the
+  // |app_id|. If none have been associated yet, they will be created.
   void GetPublicKey(const std::string& app_id,
                     const PublicKeyCallback& callback);
 
@@ -89,10 +90,12 @@
 
   void DidGetPublicKey(const std::string& app_id,
                        const PublicKeyCallback& callback,
-                       const KeyPair& pair);
+                       const KeyPair& pair,
+                       const std::string& auth_secret);
 
   void DidCreatePublicKey(const PublicKeyCallback& callback,
-                          const KeyPair& pair);
+                          const KeyPair& pair,
+                          const std::string& auth_secret);
 
   void DecryptMessageWithKey(const IncomingMessage& message,
                              const MessageDecryptedCallback& success_callback,
@@ -100,7 +103,8 @@
                              const std::string& salt,
                              const std::string& dh,
                              uint64_t rs,
-                             const KeyPair& pair);
+                             const KeyPair& pair,
+                             const std::string& auth_secret);
 
   scoped_ptr<GCMKeyStore> key_store_;
 
diff --git a/components/gcm_driver/crypto/gcm_encryption_provider_unittest.cc b/components/gcm_driver/crypto/gcm_encryption_provider_unittest.cc
index edb0bae..cb68d88 100644
--- a/components/gcm_driver/crypto/gcm_encryption_provider_unittest.cc
+++ b/components/gcm_driver/crypto/gcm_encryption_provider_unittest.cc
@@ -58,13 +58,19 @@
   }
 
   // To be used as a callback for GCMEncryptionProvider::GetPublicKey().
-  void DidGetPublicKey(std::string* key_out, const std::string& key) {
+  void DidGetPublicKey(std::string* key_out,
+                       std::string* auth_secret_out,
+                       const std::string& key,
+                       const std::string& auth_secret) {
     *key_out = key;
+    *auth_secret_out = auth_secret;
   }
 
   // To be used as a callback for GCMKeyStore::CreateKeys().
-  void DidCreateKeys(KeyPair* pair_out, const KeyPair& pair) {
+  void DidCreateKeys(KeyPair* pair_out, std::string* auth_secret_out,
+                     const KeyPair& pair, const std::string& auth_secret) {
     *pair_out = pair;
+    *auth_secret_out = auth_secret;
   }
 
  protected:
@@ -213,16 +219,17 @@
   EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_FAILURE_NO_KEYS,
             failure_reason());
 
-  std::string public_key;
+  std::string public_key, auth_secret;
   encryption_provider()->GetPublicKey(
       kExampleAppId,
       base::Bind(&GCMEncryptionProviderTest::DidGetPublicKey,
-                 base::Unretained(this), &public_key));
+                 base::Unretained(this), &public_key, &auth_secret));
 
   // Getting (or creating) the public key will be done asynchronously.
   base::RunLoop().RunUntilIdle();
 
   ASSERT_GT(public_key.size(), 0u);
+  ASSERT_GT(auth_secret.size(), 0u);
 
   ASSERT_NO_FATAL_FAILURE(Decrypt(message));
   ASSERT_EQ(DECRYPTION_FAILED, decryption_result());
@@ -235,8 +242,8 @@
   // public/private key-pair and performing the cryptographic operations. This
   // is more of an integration test than a unit test.
 
-  KeyPair pair;
-  KeyPair server_pair;
+  KeyPair pair, server_pair;
+  std::string auth_secret, server_authentication;
 
   // Retrieve the public/private key-pair immediately from the key store, given
   // that the GCMEncryptionProvider will only share the public key with users.
@@ -244,12 +251,12 @@
   encryption_provider()->key_store_->CreateKeys(
       kExampleAppId,
       base::Bind(&GCMEncryptionProviderTest::DidCreateKeys,
-                 base::Unretained(this), &pair));
+                 base::Unretained(this), &pair, &auth_secret));
 
   encryption_provider()->key_store_->CreateKeys(
       std::string(kExampleAppId) + "-server",
       base::Bind(&GCMEncryptionProviderTest::DidCreateKeys,
-                 base::Unretained(this), &server_pair));
+                 base::Unretained(this), &server_pair, &server_authentication));
 
   // Creating the public keys will be done asynchronously.
   base::RunLoop().RunUntilIdle();
@@ -278,7 +285,7 @@
   // random |salt|, storing the result in |record_size| and the message.
   GCMMessageCryptographer cryptographer(
       GCMMessageCryptographer::Label::P256, pair.public_key(),
-      server_pair.public_key());
+      server_pair.public_key(), auth_secret);
 
   ASSERT_TRUE(cryptographer.Encrypt(kExampleMessage, shared_secret, salt,
                                     &record_size, &message.raw_data));
diff --git a/components/gcm_driver/crypto/gcm_key_store.cc b/components/gcm_driver/crypto/gcm_key_store.cc
index 10976e79..beb539ac 100644
--- a/components/gcm_driver/crypto/gcm_key_store.cc
+++ b/components/gcm_driver/crypto/gcm_key_store.cc
@@ -19,6 +19,10 @@
 // browsers still reporting the previous values.
 const char kDatabaseUMAClientName[] = "GCMKeyStore";
 
+// Number of cryptographically secure random bytes to generate as a key pair's
+// authentication secret. Must be at least 16 bytes.
+const size_t kAuthSecretBytes = 16;
+
 enum class GCMKeyStore::State {
    UNINITIALIZED,
    INITIALIZING,
@@ -47,13 +51,16 @@
 void GCMKeyStore::GetKeysAfterInitialize(const std::string& app_id,
                                          const KeysCallback& callback) {
   DCHECK(state_ == State::INITIALIZED || state_ == State::FAILED);
-  const auto iter = key_pairs_.find(app_id);
+  const auto& iter = key_pairs_.find(app_id);
   if (iter == key_pairs_.end() || state_ != State::INITIALIZED) {
-    callback.Run(KeyPair());
+    callback.Run(KeyPair(), std::string() /* auth_secret */);
     return;
   }
 
-  callback.Run(iter->second);
+  const auto& auth_secret_iter = auth_secrets_.find(app_id);
+  DCHECK(auth_secret_iter != auth_secrets_.end());
+
+  callback.Run(iter->second, auth_secret_iter->second);
 }
 
 void GCMKeyStore::CreateKeys(const std::string& app_id,
@@ -66,7 +73,7 @@
                                             const KeysCallback& callback) {
   DCHECK(state_ == State::INITIALIZED || state_ == State::FAILED);
   if (state_ != State::INITIALIZED) {
-    callback.Run(KeyPair());
+    callback.Run(KeyPair(), std::string() /* auth_secret */);
     return;
   }
 
@@ -77,13 +84,21 @@
   if (!CreateP256KeyPair(&private_key, &public_key_x509, &public_key)) {
     NOTREACHED() << "Unable to initialize a P-256 key pair.";
 
-    callback.Run(KeyPair());
+    callback.Run(KeyPair(), std::string() /* auth_secret */);
     return;
   }
 
+  std::string auth_secret;
+
+  // Create the authentication secret, which has to be a cryptographically
+  // secure random number of at least 128 bits (16 bytes).
+  crypto::RandBytes(base::WriteInto(&auth_secret, kAuthSecretBytes + 1),
+                    kAuthSecretBytes);
+
   // Store the keys in a new EncryptionData object.
   EncryptionData encryption_data;
   encryption_data.set_app_id(app_id);
+  encryption_data.set_auth_secret(auth_secret);
 
   KeyPair* pair = encryption_data.add_keys();
   pair->set_type(KeyPair::ECDH_P256);
@@ -103,24 +118,26 @@
   database_->UpdateEntries(
       entries_to_save.Pass(), keys_to_remove.Pass(),
       base::Bind(&GCMKeyStore::DidStoreKeys, weak_factory_.GetWeakPtr(), app_id,
-                 *pair, callback));
+                 *pair, auth_secret, callback));
 }
 
 void GCMKeyStore::DidStoreKeys(const std::string& app_id,
                                const KeyPair& pair,
+                               const std::string& auth_secret,
                                const KeysCallback& callback,
                                bool success) {
   DCHECK_EQ(0u, key_pairs_.count(app_id));
 
   if (!success) {
     DVLOG(1) << "Unable to store the created key in the GCM Key Store.";
-    callback.Run(KeyPair());
+    callback.Run(KeyPair(), std::string() /* auth_secret */);
     return;
   }
 
   key_pairs_[app_id] = pair;
+  auth_secrets_[app_id] = auth_secret;
 
-  callback.Run(key_pairs_[app_id]);
+  callback.Run(key_pairs_[app_id], auth_secret);
 }
 
 void GCMKeyStore::DeleteKeys(const std::string& app_id,
@@ -161,6 +178,7 @@
   }
 
   key_pairs_.erase(app_id);
+  auth_secrets_.erase(app_id);
 
   callback.Run(true /* success */);
 }
@@ -210,7 +228,9 @@
 
   for (const EncryptionData& entry : *entries) {
     DCHECK_EQ(1, entry.keys_size());
+
     key_pairs_[entry.app_id()] = entry.keys(0);
+    auth_secrets_[entry.app_id()] = entry.auth_secret();
   }
 
   state_ = State::INITIALIZED;
diff --git a/components/gcm_driver/crypto/gcm_key_store.h b/components/gcm_driver/crypto/gcm_key_store.h
index 41de906..eb23acb 100644
--- a/components/gcm_driver/crypto/gcm_key_store.h
+++ b/components/gcm_driver/crypto/gcm_key_store.h
@@ -38,7 +38,8 @@
 // rather than returning the result. Do not rely on the timing of the callbacks.
 class GCMKeyStore {
  public:
-  using KeysCallback = base::Callback<void(const KeyPair& pair)>;
+  using KeysCallback = base::Callback<void(const KeyPair& pair,
+                                           const std::string& auth_secret)>;
   using DeleteCallback = base::Callback<void(bool success)>;
 
   GCMKeyStore(
@@ -68,6 +69,7 @@
 
   void DidStoreKeys(const std::string& app_id,
                     const KeyPair& pair,
+                    const std::string& auth_secret,
                     const KeysCallback& callback,
                     bool success);
 
@@ -103,8 +105,10 @@
   // finished initializing.
   GCMDelayedTaskController delayed_task_controller_;
 
-  // Mapping of an app id to the loaded EncryptedData structure.
+  // Mapping of an app id to the loaded key pair and authentication secrets.
+  // TODO(peter): Switch these to std::unordered_map<> once allowed.
   std::map<std::string, KeyPair> key_pairs_;
+  std::map<std::string, std::string> auth_secrets_;
 
   base::WeakPtrFactory<GCMKeyStore> weak_factory_;
 
diff --git a/components/gcm_driver/crypto/gcm_key_store_unittest.cc b/components/gcm_driver/crypto/gcm_key_store_unittest.cc
index 27f659d..9bf1e074 100644
--- a/components/gcm_driver/crypto/gcm_key_store_unittest.cc
+++ b/components/gcm_driver/crypto/gcm_key_store_unittest.cc
@@ -45,10 +45,10 @@
   }
 
   // Callback to use with GCMKeyStore::{GetKeys, CreateKeys} calls.
-  void GotKeys(KeyPair* pair_out, const KeyPair& pair) {
-    DCHECK(pair_out);
-
+  void GotKeys(KeyPair* pair_out, std::string* auth_secret_out,
+               const KeyPair& pair, const std::string& auth_secret) {
     *pair_out = pair;
+    *auth_secret_out = auth_secret;
   }
 
   // Callback to use with GCMKeyStore::DeleteKeys calls.
@@ -70,21 +70,26 @@
 
 TEST_F(GCMKeyStoreTest, CreatedByDefault) {
   KeyPair pair;
+  std::string auth_secret;
   gcm_key_store()->GetKeys(kFakeAppId,
                            base::Bind(&GCMKeyStoreTest::GotKeys,
-                                      base::Unretained(this), &pair));
+                                      base::Unretained(this), &pair,
+                                      &auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
   ASSERT_FALSE(pair.IsInitialized());
   EXPECT_FALSE(pair.has_type());
+  EXPECT_EQ(0u, auth_secret.size());
 }
 
 TEST_F(GCMKeyStoreTest, CreateAndGetKeys) {
   KeyPair pair;
+  std::string auth_secret;
   gcm_key_store()->CreateKeys(kFakeAppId,
                               base::Bind(&GCMKeyStoreTest::GotKeys,
-                                         base::Unretained(this), &pair));
+                                         base::Unretained(this), &pair,
+                                         &auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
@@ -95,10 +100,14 @@
   EXPECT_GT(pair.public_key().size(), 0u);
   EXPECT_GT(pair.private_key().size(), 0u);
 
+  ASSERT_GT(auth_secret.size(), 0u);
+
   KeyPair read_pair;
+  std::string read_auth_secret;
   gcm_key_store()->GetKeys(kFakeAppId,
                            base::Bind(&GCMKeyStoreTest::GotKeys,
-                                      base::Unretained(this), &read_pair));
+                                      base::Unretained(this), &read_pair,
+                                      &read_auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
@@ -107,13 +116,17 @@
   EXPECT_EQ(pair.type(), read_pair.type());
   EXPECT_EQ(pair.private_key(), read_pair.private_key());
   EXPECT_EQ(pair.public_key(), read_pair.public_key());
+
+  EXPECT_EQ(auth_secret, read_auth_secret);
 }
 
 TEST_F(GCMKeyStoreTest, KeysPersistenceBetweenInstances) {
   KeyPair pair;
+  std::string auth_secret;
   gcm_key_store()->CreateKeys(kFakeAppId,
                               base::Bind(&GCMKeyStoreTest::GotKeys,
-                                         base::Unretained(this), &pair));
+                                         base::Unretained(this), &pair,
+                                         &auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
@@ -123,30 +136,37 @@
   CreateKeyStore();
 
   KeyPair read_pair;
+  std::string read_auth_secret;
   gcm_key_store()->GetKeys(kFakeAppId,
                            base::Bind(&GCMKeyStoreTest::GotKeys,
-                                      base::Unretained(this), &read_pair));
+                                      base::Unretained(this), &read_pair,
+                                      &read_auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
   ASSERT_TRUE(read_pair.IsInitialized());
   EXPECT_TRUE(read_pair.has_type());
+  EXPECT_GT(read_auth_secret.size(), 0u);
 }
 
 TEST_F(GCMKeyStoreTest, CreateAndDeleteKeys) {
   KeyPair pair;
+  std::string auth_secret;
   gcm_key_store()->CreateKeys(kFakeAppId,
                               base::Bind(&GCMKeyStoreTest::GotKeys,
-                                         base::Unretained(this), &pair));
+                                         base::Unretained(this), &pair,
+                                         &auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
   ASSERT_TRUE(pair.IsInitialized());
 
   KeyPair read_pair;
+  std::string read_auth_secret;
   gcm_key_store()->GetKeys(kFakeAppId,
                            base::Bind(&GCMKeyStoreTest::GotKeys,
-                                      base::Unretained(this), &read_pair));
+                                      base::Unretained(this), &read_pair,
+                                      &read_auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
@@ -164,7 +184,8 @@
 
   gcm_key_store()->GetKeys(kFakeAppId,
                            base::Bind(&GCMKeyStoreTest::GotKeys,
-                                      base::Unretained(this), &read_pair));
+                                      base::Unretained(this), &read_pair,
+                                      &read_auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
@@ -173,9 +194,11 @@
 
 TEST_F(GCMKeyStoreTest, GetKeysMultipleAppIds) {
   KeyPair pair;
+  std::string auth_secret;
   gcm_key_store()->CreateKeys(kFakeAppId,
                               base::Bind(&GCMKeyStoreTest::GotKeys,
-                                         base::Unretained(this), &pair));
+                                         base::Unretained(this), &pair,
+                                         &auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
@@ -183,16 +206,19 @@
 
   gcm_key_store()->CreateKeys(kSecondFakeAppId,
                               base::Bind(&GCMKeyStoreTest::GotKeys,
-                                         base::Unretained(this), &pair));
+                                         base::Unretained(this), &pair,
+                                         &auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
   ASSERT_TRUE(pair.IsInitialized());
 
   KeyPair read_pair;
+  std::string read_auth_secret;
   gcm_key_store()->GetKeys(kFakeAppId,
                            base::Bind(&GCMKeyStoreTest::GotKeys,
-                                      base::Unretained(this), &read_pair));
+                                      base::Unretained(this), &read_pair,
+                                      &read_auth_secret));
 
   base::RunLoop().RunUntilIdle();
 
@@ -202,18 +228,22 @@
 
 TEST_F(GCMKeyStoreTest, SuccessiveCallsBeforeInitialization) {
   KeyPair pair;
+  std::string auth_secret;
   gcm_key_store()->CreateKeys(kFakeAppId,
                               base::Bind(&GCMKeyStoreTest::GotKeys,
-                                         base::Unretained(this), &pair));
+                                         base::Unretained(this), &pair,
+                                         &auth_secret));
 
   // Deliberately do not run the message loop, so that the callback has not
   // been resolved yet. The following EXPECT() ensures this.
   EXPECT_FALSE(pair.IsInitialized());
 
   KeyPair read_pair;
+  std::string read_auth_secret;
   gcm_key_store()->GetKeys(kFakeAppId,
                            base::Bind(&GCMKeyStoreTest::GotKeys,
-                                      base::Unretained(this), &read_pair));
+                                      base::Unretained(this), &read_pair,
+                                      &read_auth_secret));
 
   EXPECT_FALSE(read_pair.IsInitialized());
 
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer.cc b/components/gcm_driver/crypto/gcm_message_cryptographer.cc
index 1daf5794..574a2576 100644
--- a/components/gcm_driver/crypto/gcm_message_cryptographer.cc
+++ b/components/gcm_driver/crypto/gcm_message_cryptographer.cc
@@ -73,13 +73,16 @@
 GCMMessageCryptographer::GCMMessageCryptographer(
     Label label,
     const base::StringPiece& recipient_public_key,
-    const base::StringPiece& sender_public_key)
+    const base::StringPiece& sender_public_key,
+    const std::string& auth_secret)
     : content_encryption_key_info_(
           InfoForContentEncoding("aesgcm128", label, recipient_public_key,
                                  sender_public_key)),
       nonce_info_(
           InfoForContentEncoding("nonce", label, recipient_public_key,
-                                 sender_public_key)) {}
+                                 sender_public_key)),
+      auth_secret_(auth_secret) {
+}
 
 GCMMessageCryptographer::~GCMMessageCryptographer() {}
 
@@ -94,8 +97,10 @@
   if (salt.size() != kSaltSize)
     return false;
 
-  std::string content_encryption_key = DeriveContentEncryptionKey(key, salt);
-  std::string nonce = DeriveNonce(key, salt);
+  std::string ikm = DeriveInputKeyingMaterial(key);
+
+  std::string content_encryption_key = DeriveContentEncryptionKey(ikm, salt);
+  std::string nonce = DeriveNonce(ikm, salt);
 
   // draft-thomson-http-encryption allows between 0 and 255 octets of padding to
   // be inserted before the enciphered content, with the length of the padding
@@ -120,12 +125,11 @@
   return true;
 }
 
-bool GCMMessageCryptographer::Decrypt(
-    const base::StringPiece& ciphertext,
-    const base::StringPiece& key,
-    const base::StringPiece& salt,
-    size_t record_size,
-    std::string* plaintext) const {
+bool GCMMessageCryptographer::Decrypt(const base::StringPiece& ciphertext,
+                                      const base::StringPiece& key,
+                                      const base::StringPiece& salt,
+                                      size_t record_size,
+                                      std::string* plaintext) const {
   DCHECK(plaintext);
 
   if (salt.size() != kSaltSize || record_size <= 1)
@@ -140,8 +144,10 @@
     return false;
   }
 
-  std::string content_encryption_key = DeriveContentEncryptionKey(key, salt);
-  std::string nonce = DeriveNonce(key, salt);
+  std::string ikm = DeriveInputKeyingMaterial(key);
+
+  std::string content_encryption_key = DeriveContentEncryptionKey(ikm, salt);
+  std::string nonce = DeriveNonce(ikm, salt);
 
   std::string decrypted_record;
   if (!EncryptDecryptRecordInternal(DECRYPT, ciphertext, content_encryption_key,
@@ -172,6 +178,22 @@
   return true;
 }
 
+std::string GCMMessageCryptographer::DeriveInputKeyingMaterial(
+    const base::StringPiece& key) const {
+  if (allow_empty_auth_secret_for_tests_ && auth_secret_.empty())
+    return key.as_string();
+
+  CHECK(!auth_secret_.empty());
+
+  crypto::HKDF hkdf(key, auth_secret_,
+                    "Content-Encoding: auth",
+                    32, /* key_bytes_to_generate */
+                    0,  /* iv_bytes_to_generate */
+                    0   /* subkey_secret_bytes_to_generate */);
+
+  return hkdf.client_write_key().as_string();
+}
+
 std::string GCMMessageCryptographer::DeriveContentEncryptionKey(
     const base::StringPiece& key,
     const base::StringPiece& salt) const {
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer.h b/components/gcm_driver/crypto/gcm_message_cryptographer.h
index 0ee275d3..de74cd3a 100644
--- a/components/gcm_driver/crypto/gcm_message_cryptographer.h
+++ b/components/gcm_driver/crypto/gcm_message_cryptographer.h
@@ -45,7 +45,8 @@
   // the key agreement, and the public keys of both the recipient and sender.
   GCMMessageCryptographer(Label label,
                           const base::StringPiece& recipient_public_key,
-                          const base::StringPiece& sender_public_key);
+                          const base::StringPiece& sender_public_key,
+                          const std::string& auth_secret);
 
   ~GCMMessageCryptographer();
 
@@ -70,8 +71,10 @@
                std::string* plaintext) const WARN_UNUSED_RESULT;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, AuthSecretAffectsIKM);
   FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, InvalidRecordPadding);
   FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, NonceGeneration);
+  FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, ReferenceTest);
 
   // Size, in bytes, of the authentication tag included in the messages.
   static const size_t kAuthenticationTagBytes;
@@ -86,6 +89,11 @@
                                     const base::StringPiece& nonce,
                                     std::string* output) const;
 
+  // Derives the input keying material (IKM) to use for deriving the content
+  // encryption key and the nonce. If |auth_secret_| is not the empty string,
+  // another HKDF will be invoked between the |key| and the |auth_secret_|.
+  std::string DeriveInputKeyingMaterial(const base::StringPiece& key) const;
+
   // Derives the content encryption key from |key| and |salt|.
   std::string DeriveContentEncryptionKey(const base::StringPiece& key,
                                          const base::StringPiece& salt) const;
@@ -99,6 +107,17 @@
   // the sender and recipient's public keys.
   std::string content_encryption_key_info_;
   std::string nonce_info_;
+
+  // The pre-shared authentication secret associated with the subscription.
+  std::string auth_secret_;
+
+  // Whether an empty auth secret is acceptable when deriving the IKM. This only
+  // is the case when running tests against the reference vectors.
+  bool allow_empty_auth_secret_for_tests_ = false;
+
+  void set_allow_empty_auth_secret_for_tests(bool value) {
+    allow_empty_auth_secret_for_tests_ = value;
+  }
 };
 
 }  // namespace gcm
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc b/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc
index b54e5fc..878f5dc3 100644
--- a/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc
+++ b/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc
@@ -31,6 +31,8 @@
     "BAuzSrdIyKZsHnuOhqklkIKi6fl65V9OdPy6nFwI2SywL5-6I5SkkDtfIL9y7NkoEE345jv2Eo"
     "5n4NIbLJIBjTM";
 
+const char kAuthSecretCommon[] = "MyAuthenticationSecret";
+
 // A test vector contains the information necessary to either encrypt or decrypt
 // a message. These vectors were created using a JavaScript implementation of
 // the same RFCs that the GCMMessageCryptographer implements.
@@ -48,14 +50,14 @@
     "AhA6n2oFYPWIh-cXwyv1m2C0JvmjHB4ZkXj8QylESXU",
     "tsJYqAGvFDk6lDEv7daecw",
     4096,
-    "Vhe0Wn01NnZ_AFDgdvD4rthl2Pz9u7-WX-BAHsGX"
+    "NFivl-fJJkKHJPvHlDM3P6SHyBdmr5Caqxm1m-Is"
    },
    // Empty message.
    { "",
     "lMyvTong4VR053jfCpWmMDGW5dEDAqiTZUIU-inhTjU",
     "wH3uvZqcN6oey9whiGpn1A",
     4096,
-    "l81ck9Au-SbeTqQdPx-ky7Y"
+    "Pnoyj0pZJ0daULfQFPWUlBA"
    },
    // Message with an invalid salt size.
    { "Hello, world!",
@@ -68,35 +70,35 @@
 
 const TestVector kDecryptionTestVectors[] = {
   // Simple message.
-  { "bkXjWrS4fIVFJOnBgUG6ZY9Kgip6bDX7QYHueYVc",
+  { "o7t04QCaL2YHs_UQWqJo_4RZ8rnLCJsoQeAGbvVv",
     "47ZytAw9qHlm-Q8g-7rH81rUPzaCgGcoFvlS1qxQtQk",
     "EuR7EVetcaWpndXd_dKeyA",
     4096,
     "Hello, world!"
    },
    // Simple message with 16 bytes of padding.
-   { "IkCA6-h14nYSJHsCy0iC7BlkXuO4bc_dyNo_D_d5R1fVaG7jggdhdO29H-1d5w",
+   { "mCKryg4tyVSkEM5B5fmV8FzTcMvzB3a8PRii3SY3uM8nXOc4yLpB0XgXjnDKbw",
      "MYSsNybwrTzRIzQYUq_yFPc6ugcTrJdEZJDM4NswvUg",
      "8sEAMQYnufo2UkKl80cUGQ",
      4096,
      "Hello, world!"
    },
    // Empty message.
-   { "ebRdG2oMvjURqU4NXeY_XvM",
+   { "k27iDM90-Jmc6q5Eb9Nx2IM",
      "S3-Ki_-XtzR66gUp_zR75CC5JXO62pyr5fWfneTYwFE",
      "4RM6s19jJHdmqiVEJDp9jg",
      4096,
      ""
    },
    // Message with an invalid salt size.
-   { "rt4OiodS087DAQo6e24wA55k0hRPAHgz7OX7m-nj",
+   { "iGrOpmJC5XTTf7wtgdhZ_qT",
      "wW3Iy5ma803lLd-ysPdHUe2NB3HqXbY0XhCCdG5Y1Gw",
      "N7oMH_xohAhMhOY",
      4096,
      nullptr  // expected to fail
    },
    // Message with an invalid record size.
-   { "HNT3GJAt4XHmIagUhh-osH1",
+   { "iGrOpmJC5XTTf7wtgdhZ_qT",
      "kR5BMfqMKOD1yrLKE2giObXHI7merrMtnoO2oqneqXA",
      "SQeJSPrqHvTdSfAMF8bBzQ",
      8,
@@ -133,7 +135,8 @@
 
     cryptographer_.reset(
         new GCMMessageCryptographer(GCMMessageCryptographer::Label::P256,
-                                    local_public_key, peer_public_key));
+                                    local_public_key, peer_public_key,
+                                    kAuthSecretCommon));
   }
 
  protected:
@@ -220,9 +223,10 @@
 
   const std::string salt = GenerateRandomSalt();
 
-  const std::string nonce = cryptographer()->DeriveNonce(key(), salt);
+  const std::string ikm = cryptographer()->DeriveInputKeyingMaterial(key());
+  const std::string nonce = cryptographer()->DeriveNonce(ikm, salt);
   const std::string content_encryption_key =
-      cryptographer()->DeriveContentEncryptionKey(key(), salt);
+      cryptographer()->DeriveContentEncryptionKey(ikm, salt);
 
   ASSERT_GT(message.size(), 1u);
   const size_t record_size = message.size() + 1;
@@ -324,6 +328,56 @@
   }
 }
 
+TEST_F(GCMMessageCryptographerTest, AuthSecretAffectsIKM) {
+  std::string public_key;
+  ASSERT_TRUE(base::Base64UrlDecode(
+      kLocalPublicKeyCommon, base::Base64UrlDecodePolicy::IGNORE_PADDING,
+      &public_key));
+
+  // Fake IKM to use in the DeriveInputKeyingMaterial calls.
+  const char kFakeIKM[] = "HelloWorld";
+
+  GCMMessageCryptographer hello_cryptographer(
+      GCMMessageCryptographer::Label::P256, public_key, public_key, "Hello");
+
+  GCMMessageCryptographer world_cryptographer(
+      GCMMessageCryptographer::Label::P256, public_key, public_key, "World");
+
+  ASSERT_NE(hello_cryptographer.DeriveInputKeyingMaterial(kFakeIKM), kFakeIKM);
+  ASSERT_NE(world_cryptographer.DeriveInputKeyingMaterial(kFakeIKM), kFakeIKM);
+
+  ASSERT_NE(hello_cryptographer.DeriveInputKeyingMaterial(kFakeIKM),
+            world_cryptographer.DeriveInputKeyingMaterial(kFakeIKM));
+
+  std::string salt = GenerateRandomSalt();
+
+  // Verify that the IKM actually gets used by the transformations.
+  size_t hello_record_size, world_record_size;
+  std::string hello_ciphertext, world_ciphertext;
+
+  ASSERT_TRUE(hello_cryptographer.Encrypt(kExamplePlaintext, key(), salt,
+                                          &hello_record_size,
+                                          &hello_ciphertext));
+  ASSERT_TRUE(world_cryptographer.Encrypt(kExamplePlaintext, key(), salt,
+                                          &world_record_size,
+                                          &world_ciphertext));
+
+  // If the ciphertexts differ despite the same key and salt, it got used.
+  ASSERT_NE(hello_ciphertext, world_ciphertext);
+
+  // Verify that the different ciphertexts can also be translated back to the
+  // plaintext content. This will fail if the auth secret isn't considered.
+  std::string hello_plaintext, world_plaintext;
+
+  ASSERT_TRUE(hello_cryptographer.Decrypt(hello_ciphertext, key(), salt,
+                                          hello_record_size, &hello_plaintext));
+  ASSERT_TRUE(world_cryptographer.Decrypt(world_ciphertext, key(), salt,
+                                          world_record_size, &world_plaintext));
+
+  EXPECT_EQ(kExamplePlaintext, hello_plaintext);
+  EXPECT_EQ(kExamplePlaintext, world_plaintext);
+}
+
 // Reference test against the HTTP encryption coding IETF draft. Both the
 // encrypting and decrypting routines of the GCMMessageCryptographer are
 // covered by this test.
@@ -413,7 +467,11 @@
   ASSERT_EQ(sender_shared_secret, receiver_shared_secret);
 
   GCMMessageCryptographer cryptographer(
-      GCMMessageCryptographer::Label::P256, receiver_public, sender_public);
+      GCMMessageCryptographer::Label::P256, receiver_public, sender_public,
+      "" /* auth_secret */);
+
+  // The reference vectors do not use an authentication secret.
+  cryptographer.set_allow_empty_auth_secret_for_tests(true);
 
   size_t record_size = 0;
   std::string ciphertext;
diff --git a/components/gcm_driver/crypto/proto/gcm_encryption_data.proto b/components/gcm_driver/crypto/proto/gcm_encryption_data.proto
index 16cf212..a435c4a 100644
--- a/components/gcm_driver/crypto/proto/gcm_encryption_data.proto
+++ b/components/gcm_driver/crypto/proto/gcm_encryption_data.proto
@@ -36,11 +36,15 @@
 // in case we need to force-cycle all keys, allowing the old keys to remain
 // valid for a period of time enabling the web app to update.
 //
-// Next tag: 3
+// Next tag: 4
 message EncryptionData {
   // The app id to whom this encryption data belongs.
   required string app_id = 1;
 
   // The actual public/private key-pairs.
   repeated KeyPair keys = 2;
+
+  // The authentication secret associated with the subscription. Must be a
+  // cryptographically secure number of at least 12 bytes.
+  optional bytes auth_secret = 3;
 }
diff --git a/components/gcm_driver/gcm_driver.h b/components/gcm_driver/gcm_driver.h
index cb5eae2..48590697a 100644
--- a/components/gcm_driver/gcm_driver.h
+++ b/components/gcm_driver/gcm_driver.h
@@ -79,7 +79,8 @@
                               GCMClient::Result result)> RegisterCallback;
   typedef base::Callback<void(const std::string& message_id,
                               GCMClient::Result result)> SendCallback;
-  typedef base::Callback<void(const std::string&)> GetPublicKeyCallback;
+  typedef base::Callback<void(const std::string&, const std::string&)>
+      GetPublicKeyCallback;
   typedef base::Callback<void(GCMClient::Result result)> UnregisterCallback;
   typedef base::Callback<void(const GCMClient::GCMStatistics& stats)>
       GetGCMStatisticsCallback;
@@ -127,9 +128,10 @@
             const OutgoingMessage& message,
             const SendCallback& callback);
 
-  // Get the public encryption key associated with |app_id|. If no keys have
-  // been associated with |app_id| yet, they will be created. The |callback|
-  // will be invoked when it is available.
+  // Get the public encryption key and the authentication secret associated with
+  // |app_id|. If none have been associated with |app_id| yet, they will be
+  // created. The |callback| will be invoked when it is available.
+  // TODO(peter): Rename this method to GetEncryptionInfo().
   void GetPublicKey(const std::string& app_id,
                     const GetPublicKeyCallback& callback);
 
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn
index 4e41104..5f4a08a 100644
--- a/components/html_viewer/BUILD.gn
+++ b/components/html_viewer/BUILD.gn
@@ -328,7 +328,7 @@
   ]
 
   if (is_android) {
-    apk_deps = [ ":unittest_assets" ]
+    deps += [ ":unittest_assets" ]
     write_asset_list = true
   }
 
diff --git a/components/html_viewer/web_mime_registry_impl.cc b/components/html_viewer/web_mime_registry_impl.cc
index 07975117..c85656a 100644
--- a/components/html_viewer/web_mime_registry_impl.cc
+++ b/components/html_viewer/web_mime_registry_impl.cc
@@ -65,15 +65,11 @@
     const blink::WebString& codecs,
     const blink::WebString& key_system) {
   const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
-  // Not supporting the container is a flat-out no.
-  if (!media::IsSupportedMediaMimeType(mime_type_ascii))
-    return IsNotSupported;
 
   // Mojo does not currently support any key systems.
   if (!key_system.isEmpty())
     return IsNotSupported;
 
-  // Check that codecs are appropriate for the container type.
   std::vector<std::string> codec_vector;
   media::ParseCodecString(ToASCIIOrEmpty(codecs), &codec_vector, false);
   return static_cast<WebMimeRegistry::SupportsType>(
diff --git a/components/mus/public/cpp/lib/in_flight_change.h b/components/mus/public/cpp/lib/in_flight_change.h
index 80c6780c..3dc42a7 100644
--- a/components/mus/public/cpp/lib/in_flight_change.h
+++ b/components/mus/public/cpp/lib/in_flight_change.h
@@ -20,8 +20,9 @@
 enum class ChangeType {
   ADD_TRANSIENT_WINDOW,
   BOUNDS,
-  PROPERTY,
+  DELETE_WINDOW,
   NEW_WINDOW,
+  PROPERTY,
   REMOVE_TRANSIENT_WINDOW_FROM_PARENT
 };
 
diff --git a/components/mus/public/cpp/lib/window.cc b/components/mus/public/cpp/lib/window.cc
index 5284785a..8dffc7f5 100644
--- a/components/mus/public/cpp/lib/window.cc
+++ b/components/mus/public/cpp/lib/window.cc
@@ -167,7 +167,7 @@
     return;
 
   if (connection_)
-    tree_client()->DestroyWindow(id_);
+    tree_client()->DestroyWindow(this);
   while (!children_.empty()) {
     Window* child = children_.front();
     if (!OwnsWindow(connection_, child)) {
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.cc b/components/mus/public/cpp/lib/window_tree_client_impl.cc
index dee1d57c..163f1a3 100644
--- a/components/mus/public/cpp/lib/window_tree_client_impl.cc
+++ b/components/mus/public/cpp/lib/window_tree_client_impl.cc
@@ -150,9 +150,11 @@
   // TODO(sky): deal with pipe being closed before we get OnEmbed().
 }
 
-void WindowTreeClientImpl::DestroyWindow(Id window_id) {
+void WindowTreeClientImpl::DestroyWindow(Window* window) {
   DCHECK(tree_);
-  tree_->DeleteWindow(window_id, ActionCompletedCallback());
+  const uint32_t change_id = ScheduleInFlightChange(make_scoped_ptr(
+      new CrashInFlightChange(window, ChangeType::DELETE_WINDOW)));
+  tree_->DeleteWindow(change_id, window->id());
 }
 
 void WindowTreeClientImpl::AddChild(Id child_id, Id parent_id) {
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.h b/components/mus/public/cpp/lib/window_tree_client_impl.h
index baa116e..16caa4c 100644
--- a/components/mus/public/cpp/lib/window_tree_client_impl.h
+++ b/components/mus/public/cpp/lib/window_tree_client_impl.h
@@ -43,7 +43,7 @@
 
   // API exposed to the window implementations that pushes local changes to the
   // service.
-  void DestroyWindow(Id window_id);
+  void DestroyWindow(Window* window);
 
   // These methods take TransportIds. For windows owned by the current
   // connection, the connection id high word can be zero. In all cases, the
diff --git a/components/mus/public/cpp/tests/test_window_tree.cc b/components/mus/public/cpp/tests/test_window_tree.cc
index 031a3c2..46c64511 100644
--- a/components/mus/public/cpp/tests/test_window_tree.cc
+++ b/components/mus/public/cpp/tests/test_window_tree.cc
@@ -25,8 +25,7 @@
     uint32_t window_id,
     mojo::Map<mojo::String, mojo::Array<uint8_t>> properties) {}
 
-void TestWindowTree::DeleteWindow(uint32_t window_id,
-                                  const DeleteWindowCallback& callback) {}
+void TestWindowTree::DeleteWindow(uint32_t change_id, uint32_t window_id) {}
 
 void TestWindowTree::SetWindowBounds(uint32_t change_id,
                                      uint32_t window_id,
diff --git a/components/mus/public/cpp/tests/test_window_tree.h b/components/mus/public/cpp/tests/test_window_tree.h
index 56eace6..6db82a4 100644
--- a/components/mus/public/cpp/tests/test_window_tree.h
+++ b/components/mus/public/cpp/tests/test_window_tree.h
@@ -27,8 +27,7 @@
       uint32_t change_id,
       uint32_t window_id,
       mojo::Map<mojo::String, mojo::Array<uint8_t>> properties) override;
-  void DeleteWindow(uint32_t window_id,
-                    const DeleteWindowCallback& callback) override;
+  void DeleteWindow(uint32_t change_id, uint32_t window_id) override;
   void SetWindowBounds(uint32_t change_id,
                        uint32_t window_id,
                        mojo::RectPtr bounds) override;
diff --git a/components/mus/public/interfaces/window_tree.mojom b/components/mus/public/interfaces/window_tree.mojom
index 1e70b2e..455929a 100644
--- a/components/mus/public/interfaces/window_tree.mojom
+++ b/components/mus/public/interfaces/window_tree.mojom
@@ -95,7 +95,7 @@
   // Deletes a window. This does not recurse. No hierarchy change notifications
   // are sent as a result of this. Only the connection that created the window
   // can delete it.
-  DeleteWindow(uint32 window_id) => (bool success);
+  DeleteWindow(uint32 change_id, uint32 window_id);
 
   // Sets the specified bounds of the specified window.
   SetWindowBounds(uint32 change_id, uint32 window_id, mojo.Rect bounds);
diff --git a/components/mus/ws/window_tree_apptest.cc b/components/mus/ws/window_tree_apptest.cc
index 63ba178..70613fc 100644
--- a/components/mus/ws/window_tree_apptest.cc
+++ b/components/mus/ws/window_tree_apptest.cc
@@ -134,15 +134,6 @@
   run_loop.Run();
 }
 
-bool DeleteWindow(WindowTree* ws, Id window_id) {
-  base::RunLoop run_loop;
-  bool result = false;
-  ws->DeleteWindow(window_id,
-                   base::Bind(&BoolResultCallback, &run_loop, &result));
-  run_loop.Run();
-  return result;
-}
-
 bool SetWindowVisibility(WindowTree* ws, Id window_id, bool visible) {
   base::RunLoop run_loop;
   bool result = false;
@@ -226,6 +217,12 @@
     return on_change_completed_result_;
   }
 
+  bool DeleteWindow(Id id) {
+    const uint32_t change_id = GetAndAdvanceChangeId();
+    tree()->DeleteWindow(change_id, id);
+    return WaitForChangeCompleted(change_id);
+  }
+
   // Waits for all messages to be received by |ws|. This is done by attempting
   // to create a bogus window. When we get the response we know all messages
   // have been processed.
@@ -1012,7 +1009,7 @@
   {
     changes1()->clear();
     changes2()->clear();
-    ASSERT_TRUE(DeleteWindow(ws2(), window_2_2));
+    ASSERT_TRUE(ws_client2()->DeleteWindow(window_2_2));
     EXPECT_TRUE(changes2()->empty());
 
     ws_client1_->WaitForChangeCount(1);
@@ -1024,7 +1021,7 @@
 // Verifies DeleteWindow isn't allowed from a separate connection.
 TEST_F(WindowTreeAppTest, DeleteWindowFromAnotherConnectionDisallowed) {
   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
-  EXPECT_FALSE(DeleteWindow(ws2(), BuildWindowId(connection_id_1(), 1)));
+  EXPECT_FALSE(ws_client2()->DeleteWindow(BuildWindowId(connection_id_1(), 1)));
 }
 
 // Verifies if a window was deleted and then reused that other clients are
@@ -1050,7 +1047,7 @@
   // Delete 2.
   {
     changes1()->clear();
-    ASSERT_TRUE(DeleteWindow(ws2(), window_2_2));
+    ASSERT_TRUE(ws_client2()->DeleteWindow(window_2_2));
 
     ws_client1_->WaitForChangeCount(1);
     EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_2),
@@ -1749,7 +1746,7 @@
             SingleChangeToDescription(*changes1()));
 
   changes1()->clear();
-  ASSERT_TRUE(DeleteWindow(ws2(), window_2_1));
+  ASSERT_TRUE(ws_client2()->DeleteWindow(window_2_1));
   ws_client1()->WaitForChangeCount(2);
   EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_2),
             ChangesToDescription1(*changes1())[0]);
diff --git a/components/mus/ws/window_tree_impl.cc b/components/mus/ws/window_tree_impl.cc
index c9bcb47..18edf8a 100644
--- a/components/mus/ws/window_tree_impl.cc
+++ b/components/mus/ws/window_tree_impl.cc
@@ -634,8 +634,7 @@
       NewWindow(WindowIdFromTransportId(transport_window_id), properties));
 }
 
-void WindowTreeImpl::DeleteWindow(Id transport_window_id,
-                                  const Callback<void(bool)>& callback) {
+void WindowTreeImpl::DeleteWindow(uint32_t change_id, Id transport_window_id) {
   ServerWindow* window =
       GetWindow(WindowIdFromTransportId(transport_window_id));
   bool success = false;
@@ -646,7 +645,7 @@
         connection_manager_->GetConnection(window->id().connection_id);
     success = connection && connection->DeleteWindowImpl(this, window);
   }
-  callback.Run(success);
+  client_->OnChangeCompleted(change_id, success);
 }
 
 void WindowTreeImpl::AddWindow(Id parent_id,
diff --git a/components/mus/ws/window_tree_impl.h b/components/mus/ws/window_tree_impl.h
index 7503302c..e17d0d0 100644
--- a/components/mus/ws/window_tree_impl.h
+++ b/components/mus/ws/window_tree_impl.h
@@ -196,8 +196,7 @@
                  Id transport_window_id,
                  mojo::Map<mojo::String, mojo::Array<uint8_t>>
                      transport_properties) override;
-  void DeleteWindow(Id transport_window_id,
-                    const mojo::Callback<void(bool)>& callback) override;
+  void DeleteWindow(uint32_t change_id, Id transport_window_id) override;
   void AddWindow(Id parent_id,
                  Id child_id,
                  const mojo::Callback<void(bool)>& callback) override;
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index 6d44c35..7a82df4 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -213,7 +213,8 @@
 // that this only takes a transferred IPC::ChannelHandle or one to be
 // transferred via IPC.
 class NaClProcessHost::ScopedChannelHandle {
-  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedChannelHandle, RValue);
+  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedChannelHandle);
+
  public:
   ScopedChannelHandle() {
   }
@@ -221,8 +222,8 @@
       : handle_(handle) {
     DCHECK(IsSupportedHandle(handle_));
   }
-  ScopedChannelHandle(RValue other) : handle_(other.object->handle_) {
-    other.object->handle_ = IPC::ChannelHandle();
+  ScopedChannelHandle(ScopedChannelHandle&& other) : handle_(other.handle_) {
+    other.handle_ = IPC::ChannelHandle();
     DCHECK(IsSupportedHandle(handle_));
   }
   ~ScopedChannelHandle() {
diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc
index dfc7af8f..07d20e2b 100644
--- a/components/nacl/renderer/ppb_nacl_private_impl.cc
+++ b/components/nacl/renderer/ppb_nacl_private_impl.cc
@@ -66,6 +66,10 @@
 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/web/WebURLLoaderOptions.h"
 
+#if defined(OS_WIN)
+#include "base/win/scoped_handle.h"
+#endif
+
 namespace nacl {
 namespace {
 
@@ -121,6 +125,17 @@
  public:
   NaClPluginInstance(PP_Instance instance):
       nexe_load_manager(instance), pexe_size(0) {}
+  ~NaClPluginInstance() {
+    // Make sure that we do not leak a file descriptor if the NaCl loader
+    // process never called ppapi_start() to initialize PPAPI.
+    if (instance_info) {
+#if defined(OS_WIN)
+      base::win::ScopedHandle closer(instance_info->channel_handle.pipe.handle);
+#else
+      base::ScopedFD closer(instance_info->channel_handle.socket.fd);
+#endif
+    }
+  }
 
   NexeLoadManager nexe_load_manager;
   scoped_ptr<JsonManifest> json_manifest;
diff --git a/components/password_manager/core/browser/password_store_consumer.h b/components/password_manager/core/browser/password_store_consumer.h
index 4321e66..01a15b4 100644
--- a/components/password_manager/core/browser/password_store_consumer.h
+++ b/components/password_manager/core/browser/password_store_consumer.h
@@ -32,7 +32,7 @@
   virtual void OnGetPasswordStoreResults(
       ScopedVector<autofill::PasswordForm> results) = 0;
 
-  // TODO(crbug.com/562554): The argument's type would ideally be just
+  // TODO(crbug.com/561749): The argument's type would ideally be just
   // std::vector<scoped_ptr<InteractionsStats>>, but currently it is not
   // possible to pass that into a callback.
   virtual void OnGetSiteStatistics(
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index d016810..207c796 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -4938,7 +4938,7 @@
         'type': 'array',
         'items': { 'type': 'string' },
       },
-      'supported_on': ['chrome_os:19-'],
+      'supported_on': ['chrome_os:19-40'],
       'device_only': True,
       'features': {
         'dynamic_refresh': True,
@@ -4955,7 +4955,7 @@
       'name': 'DeviceIdleLogoutTimeout',
       'type': 'int',
       'schema': { 'type': 'integer' },
-      'supported_on': ['chrome_os:19-'],
+      'supported_on': ['chrome_os:19-40'],
       'device_only': True,
       'features': {
         'dynamic_refresh': True,
@@ -4974,7 +4974,7 @@
       'name': 'DeviceIdleLogoutWarningDuration',
       'type': 'int',
       'schema': { 'type': 'integer' },
-      'supported_on': ['chrome_os:19-'],
+      'supported_on': ['chrome_os:19-40'],
       'device_only': True,
       'features': {
         'dynamic_refresh': True,
@@ -4993,7 +4993,7 @@
       'name': 'DeviceLoginScreenSaverId',
       'type': 'string',
       'schema': { 'type': 'string' },
-      'supported_on': ['chrome_os:19-'],
+      'supported_on': ['chrome_os:19-40'],
       'device_only': True,
       'features': {
         'dynamic_refresh': True,
@@ -5010,7 +5010,7 @@
       'name': 'DeviceLoginScreenSaverTimeout',
       'type': 'int',
       'schema': { 'type': 'integer' },
-      'supported_on': ['chrome_os:19-'],
+      'supported_on': ['chrome_os:19-40'],
       'device_only': True,
       'features': {
         'dynamic_refresh': True,
@@ -5032,7 +5032,7 @@
         'type': 'array',
         'items': { 'type': 'string' },
       },
-      'supported_on': ['chrome_os:19-'],
+      'supported_on': ['chrome_os:19-40'],
       'device_only': True,
       'features': {
         'dynamic_refresh': True,
diff --git a/components/scheduler/common/scheduler_switches.cc b/components/scheduler/common/scheduler_switches.cc
index 8ea8fe9..a47ae93 100644
--- a/components/scheduler/common/scheduler_switches.cc
+++ b/components/scheduler/common/scheduler_switches.cc
@@ -12,5 +12,9 @@
 // done.
 const char kEnableVirtualizedTime[] = "enable-virtualized-time";
 
+// Disable task throttling of timer tasks from background pages.
+const char kDisableBackgroundTimerThrottling[] =
+    "disable-background-timer-throttling";
+
 }  // namespace switches
 }  // namespace scheduler
diff --git a/components/scheduler/common/scheduler_switches.h b/components/scheduler/common/scheduler_switches.h
index 2a8cb0cb..207feb1 100644
--- a/components/scheduler/common/scheduler_switches.h
+++ b/components/scheduler/common/scheduler_switches.h
@@ -9,6 +9,7 @@
 namespace switches {
 
 extern const char kEnableVirtualizedTime[];
+extern const char kDisableBackgroundTimerThrottling[];
 
 }  // namespace switches
 }  // namespace scheduler
diff --git a/components/scheduler/renderer/renderer_web_scheduler_impl.cc b/components/scheduler/renderer/renderer_web_scheduler_impl.cc
index 922b1bdc..4faa081 100644
--- a/components/scheduler/renderer/renderer_web_scheduler_impl.cc
+++ b/components/scheduler/renderer/renderer_web_scheduler_impl.cc
@@ -4,7 +4,9 @@
 
 #include "components/scheduler/renderer/renderer_web_scheduler_impl.h"
 
+#include "base/command_line.h"
 #include "components/scheduler/base/task_queue.h"
+#include "components/scheduler/common/scheduler_switches.h"
 #include "components/scheduler/renderer/renderer_scheduler_impl.h"
 #include "components/scheduler/renderer/web_view_scheduler_impl.h"
 #include "third_party/WebKit/public/platform/WebPassOwnPtr.h"
@@ -32,8 +34,10 @@
 
 blink::WebPassOwnPtr<blink::WebViewScheduler>
 RendererWebSchedulerImpl::createWebViewScheduler(blink::WebView* web_view) {
-  return blink::adoptWebPtr(
-      new WebViewSchedulerImpl(web_view, renderer_scheduler_));
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  return blink::adoptWebPtr(new WebViewSchedulerImpl(
+      web_view, renderer_scheduler_,
+      command_line->HasSwitch(switches::kDisableBackgroundTimerThrottling)));
 }
 
 void RendererWebSchedulerImpl::addPendingNavigation() {
diff --git a/components/scheduler/renderer/web_view_scheduler_impl.cc b/components/scheduler/renderer/web_view_scheduler_impl.cc
index 658fdbb..781158a 100644
--- a/components/scheduler/renderer/web_view_scheduler_impl.cc
+++ b/components/scheduler/renderer/web_view_scheduler_impl.cc
@@ -15,10 +15,13 @@
 
 WebViewSchedulerImpl::WebViewSchedulerImpl(
     blink::WebView* web_view,
-    RendererSchedulerImpl* renderer_scheduler)
+    RendererSchedulerImpl* renderer_scheduler,
+    bool disable_background_timer_throttling)
     : web_view_(web_view),
       renderer_scheduler_(renderer_scheduler),
-      page_in_background_(false) {}
+      page_in_background_(false),
+      disable_background_timer_throttling_(
+          disable_background_timer_throttling) {}
 
 WebViewSchedulerImpl::~WebViewSchedulerImpl() {
   // TODO(alexclarke): Find out why we can't rely on the web view outliving the
@@ -29,7 +32,8 @@
 }
 
 void WebViewSchedulerImpl::setPageInBackground(bool page_in_background) {
-  if (page_in_background_ == page_in_background)
+  if (disable_background_timer_throttling_ ||
+      page_in_background_ == page_in_background)
     return;
 
   page_in_background_ = page_in_background;
diff --git a/components/scheduler/renderer/web_view_scheduler_impl.h b/components/scheduler/renderer/web_view_scheduler_impl.h
index a5dd7d7..4fdc40a7 100644
--- a/components/scheduler/renderer/web_view_scheduler_impl.h
+++ b/components/scheduler/renderer/web_view_scheduler_impl.h
@@ -28,7 +28,8 @@
 class SCHEDULER_EXPORT WebViewSchedulerImpl : public blink::WebViewScheduler {
  public:
   WebViewSchedulerImpl(blink::WebView* web_view,
-                       RendererSchedulerImpl* renderer_scheduler);
+                       RendererSchedulerImpl* renderer_scheduler,
+                       bool disable_background_timer_throttling);
 
   ~WebViewSchedulerImpl() override;
 
@@ -50,6 +51,7 @@
   blink::WebView* web_view_;
   RendererSchedulerImpl* renderer_scheduler_;
   bool page_in_background_;
+  bool disable_background_timer_throttling_;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewSchedulerImpl);
 };
diff --git a/components/scheduler/renderer/web_view_scheduler_impl_unittest.cc b/components/scheduler/renderer/web_view_scheduler_impl_unittest.cc
index 750811c..2a1f4d6 100644
--- a/components/scheduler/renderer/web_view_scheduler_impl_unittest.cc
+++ b/components/scheduler/renderer/web_view_scheduler_impl_unittest.cc
@@ -31,8 +31,8 @@
     delagate_ = SchedulerTqmDelegateForTest::Create(
         mock_task_runner_, make_scoped_ptr(new TestTimeSource(clock_.get())));
     scheduler_.reset(new RendererSchedulerImpl(delagate_));
-    web_view_scheduler_.reset(
-        new WebViewSchedulerImpl(nullptr, scheduler_.get()));
+    web_view_scheduler_.reset(new WebViewSchedulerImpl(
+        nullptr, scheduler_.get(), DisableBackgroundTimerThrottling()));
     web_frame_scheduler_ = web_view_scheduler_->createWebFrameSchedulerImpl();
   }
 
@@ -43,6 +43,8 @@
     scheduler_.reset();
   }
 
+  virtual bool DisableBackgroundTimerThrottling() const { return false; }
+
   scoped_ptr<base::SimpleTestTickClock> clock_;
   scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
   scoped_refptr<SchedulerTqmDelegate> delagate_;
@@ -127,7 +129,7 @@
 
 TEST_F(WebViewSchedulerImplTest, RepeatingTimers_OneBackgroundOneForeground) {
   scoped_ptr<WebViewSchedulerImpl> web_view_scheduler2(
-      new WebViewSchedulerImpl(nullptr, scheduler_.get()));
+      new WebViewSchedulerImpl(nullptr, scheduler_.get(), false));
   scoped_ptr<WebFrameSchedulerImpl> web_frame_scheduler2 =
       web_view_scheduler2->createWebFrameSchedulerImpl();
 
@@ -150,4 +152,27 @@
   EXPECT_EQ(1, run_count2);
 }
 
+class WebViewSchedulerImplTestWithDisabledBackgroundTimerThrottling
+    : public WebViewSchedulerImplTest {
+ public:
+  WebViewSchedulerImplTestWithDisabledBackgroundTimerThrottling() {}
+  ~WebViewSchedulerImplTestWithDisabledBackgroundTimerThrottling() override {}
+
+  bool DisableBackgroundTimerThrottling() const override { return true; }
+};
+
+TEST_F(WebViewSchedulerImplTestWithDisabledBackgroundTimerThrottling,
+       RepeatingTimer_PageInBackground) {
+  web_view_scheduler_->setPageInBackground(true);
+
+  int run_count = 0;
+  web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
+      BLINK_FROM_HERE,
+      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      1.0);
+
+  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+  EXPECT_EQ(1000, run_count);
+}
+
 }  // namespace scheduler
diff --git a/components/sync_driver/device_info_service.cc b/components/sync_driver/device_info_service.cc
index f210b2f8..933ff1ec 100644
--- a/components/sync_driver/device_info_service.cc
+++ b/components/sync_driver/device_info_service.cc
@@ -14,6 +14,12 @@
 
 namespace sync_driver_v2 {
 
+using syncer::SyncError;
+using syncer_v2::EntityChangeList;
+using syncer_v2::EntityData;
+using syncer_v2::EntityDataList;
+using syncer_v2::MetadataChangeList;
+using syncer_v2::SimpleMetadataChangeList;
 using sync_driver::DeviceInfo;
 using sync_pb::DeviceInfoSpecifics;
 
@@ -23,6 +29,8 @@
       local_device_info_provider_(local_device_info_provider) {
   DCHECK(local_device_info_provider);
 
+  // This is not threadsafe, but presuably the provider initializes on the same
+  // thread as us so we're okay.
   if (local_device_info_provider->GetLocalDeviceInfo()) {
     OnProviderInitialized();
   } else {
@@ -34,23 +42,22 @@
 
 DeviceInfoService::~DeviceInfoService() {}
 
-syncer_v2::MetadataChanges* DeviceInfoService::CreateMetadataChanges() {
-  // TODO(skym): Implementation.
-  return nullptr;
+scoped_ptr<MetadataChangeList> DeviceInfoService::CreateMetadataChangeList() {
+  return make_scoped_ptr(new SimpleMetadataChangeList());
 }
 
-syncer::SyncError DeviceInfoService::MergeSyncData(
-    syncer_v2::MetadataChanges* metadata_changes,
-    syncer_v2::EntityDataList entity_data_list) {
+SyncError DeviceInfoService::MergeSyncData(
+    scoped_ptr<MetadataChangeList> metadata_change_list,
+    EntityDataList entity_data_list) {
   // TODO(skym): Implementation.
-  return syncer::SyncError();
+  return SyncError();
 }
 
-syncer::SyncError DeviceInfoService::ApplySyncChanges(
-    syncer_v2::MetadataChanges* metadata_changes,
-    syncer_v2::EntityChangeList entity_changes) {
+SyncError DeviceInfoService::ApplySyncChanges(
+    scoped_ptr<MetadataChangeList> metadata_change_list,
+    EntityChangeList entity_changes) {
   // TODO(skym): Implementation.
-  return syncer::SyncError();
+  return SyncError();
 }
 
 void DeviceInfoService::LoadMetadata(MetadataCallback callback) {
@@ -66,10 +73,9 @@
   // TODO(skym): Implementation.
 }
 
-std::string DeviceInfoService::GetClientTag(
-    const syncer_v2::EntityData* entity_data) {
-  // TODO(skym): Implementation.
-  return "";
+std::string DeviceInfoService::GetClientTag(const EntityData& entity_data) {
+  DCHECK(entity_data.specifics.has_device_info());
+  return entity_data.specifics.device_info().cache_guid();
 }
 
 bool DeviceInfoService::IsSyncing() const {
diff --git a/components/sync_driver/device_info_service.h b/components/sync_driver/device_info_service.h
index 76a4126a..4c8ac29 100644
--- a/components/sync_driver/device_info_service.h
+++ b/components/sync_driver/device_info_service.h
@@ -15,6 +15,7 @@
 #include "components/sync_driver/device_info_tracker.h"
 #include "components/sync_driver/local_device_info_provider.h"
 #include "sync/api/model_type_service.h"
+#include "sync/internal_api/public/simple_metadata_change_list.h"
 
 namespace syncer {
 class SyncError;
@@ -41,17 +42,17 @@
   ~DeviceInfoService() override;
 
   // ModelTypeService implementation.
-  syncer_v2::MetadataChanges* CreateMetadataChanges() override;
+  scoped_ptr<syncer_v2::MetadataChangeList> CreateMetadataChangeList() override;
   syncer::SyncError MergeSyncData(
-      syncer_v2::MetadataChanges* metadata_changes,
+      scoped_ptr<syncer_v2::MetadataChangeList> metadata_change_list,
       syncer_v2::EntityDataList entity_data_list) override;
   syncer::SyncError ApplySyncChanges(
-      syncer_v2::MetadataChanges* metadata_changes,
+      scoped_ptr<syncer_v2::MetadataChangeList> metadata_change_list,
       syncer_v2::EntityChangeList entity_changes) override;
   void LoadMetadata(MetadataCallback callback) override;
   void GetData(ClientKeyList client_keys, DataCallback callback) override;
   void GetAllData(DataCallback callback) override;
-  std::string GetClientTag(const syncer_v2::EntityData* entity_data) override;
+  std::string GetClientTag(const syncer_v2::EntityData& entity_data) override;
 
   // DeviceInfoTracker implementation.
   bool IsSyncing() const override;
diff --git a/components/sync_driver/device_info_service_unittest.cc b/components/sync_driver/device_info_service_unittest.cc
index 5144bd5..1aa553a9 100644
--- a/components/sync_driver/device_info_service_unittest.cc
+++ b/components/sync_driver/device_info_service_unittest.cc
@@ -11,53 +11,81 @@
 
 namespace sync_driver_v2 {
 
+using syncer_v2::EntityData;
 using sync_driver::DeviceInfo;
 using sync_driver::DeviceInfoTracker;
 using sync_driver::LocalDeviceInfoProviderMock;
+using sync_pb::EntitySpecifics;
 
 namespace {
 
 class DeviceInfoServiceTest : public testing::Test,
                               public DeviceInfoTracker::Observer {
  protected:
-  DeviceInfoServiceTest() : num_device_info_changed_callbacks_(0) {}
-
-  void InitFully() {
-    local_device_.reset(new LocalDeviceInfoProviderMock(
-        "guid_1", "client_1", "Chromium 10k", "Chrome 10k",
-        sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id"));
-    service_.reset(new DeviceInfoService(local_device_.get()));
-    service_->AddObserver(this);
-  }
-
-  void InitPartially() {
-    local_device_.reset(new LocalDeviceInfoProviderMock());
-    service_.reset(new DeviceInfoService(local_device_.get()));
-    service_->AddObserver(this);
-  }
-
   ~DeviceInfoServiceTest() override { service_->RemoveObserver(this); }
 
   void OnDeviceInfoChange() override { num_device_info_changed_callbacks_++; }
 
  protected:
+  DeviceInfoServiceTest() : num_device_info_changed_callbacks_(0) {}
+
+  DeviceInfoService* InitFully() {
+    local_device_.reset(new LocalDeviceInfoProviderMock(
+        "guid_1", "client_1", "Chromium 10k", "Chrome 10k",
+        sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id"));
+    service_.reset(new DeviceInfoService(local_device_.get()));
+    service_->AddObserver(this);
+    return service_.get();
+  }
+
+  DeviceInfoService* InitPartially() {
+    local_device_.reset(new LocalDeviceInfoProviderMock());
+    service_.reset(new DeviceInfoService(local_device_.get()));
+    service_->AddObserver(this);
+    return service_.get();
+  }
+
+  int num_device_info_changed_callbacks() {
+    return num_device_info_changed_callbacks_;
+  }
+  LocalDeviceInfoProviderMock* local_device() { return local_device_.get(); }
+
+ private:
   int num_device_info_changed_callbacks_;
   scoped_ptr<LocalDeviceInfoProviderMock> local_device_;
   scoped_ptr<DeviceInfoService> service_;
 };
 
 TEST_F(DeviceInfoServiceTest, StartSyncEmptyInitialData) {
-  InitFully();
-  EXPECT_FALSE(service_->IsSyncing());
+  DeviceInfoService* service = InitFully();
+  EXPECT_FALSE(service->IsSyncing());
 }
 
 TEST_F(DeviceInfoServiceTest, DelayedProviderInitialization) {
-  InitPartially();
-  local_device_->Initialize(make_scoped_ptr(
+  DeviceInfoService* service = InitPartially();
+  local_device()->Initialize(make_scoped_ptr(
       new DeviceInfo("guid_1", "client_1", "Chromium 10k", "Chrome 10k",
                      sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id")));
+  EXPECT_FALSE(service->IsSyncing());
+}
 
-  EXPECT_FALSE(service_->IsSyncing());
+TEST_F(DeviceInfoServiceTest, GetClientTagNormal) {
+  DeviceInfoService* service = InitFully();
+  const std::string guid = "abc";
+  EntitySpecifics entity_specifics;
+  entity_specifics.mutable_device_info()->set_cache_guid(guid);
+  EntityData entity_data;
+  entity_data.specifics = entity_specifics;
+  EXPECT_EQ(guid, service->GetClientTag(entity_data));
+}
+
+TEST_F(DeviceInfoServiceTest, GetClientTagEmpty) {
+  DeviceInfoService* service = InitFully();
+  EntitySpecifics entity_specifics;
+  entity_specifics.mutable_device_info();
+  EntityData entity_data;
+  entity_data.specifics = entity_specifics;
+  EXPECT_EQ("", service->GetClientTag(entity_data));
 }
 
 }  // namespace
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 7133cdd..9501557 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -429,7 +429,6 @@
       "//ui/aura",
       "//ui/aura_extra",
       "//ui/strings",
-      "//ui/views/mus:for_component",
       "//ui/wm",
     ]
     sources += [
@@ -440,7 +439,10 @@
       "web_contents/web_contents_view_mus.cc",
       "web_contents/web_contents_view_mus.h",
     ]
-    defines += [ "MOJO_RUNNER_CLIENT" ]
+    if (toolkit_views) {
+      deps += [ "//ui/views/mus:for_component" ]
+      defines += [ "MOJO_RUNNER_CLIENT" ]
+    }
   } else {  # Not aura.
     sources -= [
       "media/capture/cursor_renderer_aura.cc",
diff --git a/content/browser/DEPS b/content/browser/DEPS
index dec16bf..42ad828 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -87,6 +87,7 @@
   "+third_party/WebKit/public/web/WebPopupType.h",
   "+third_party/WebKit/public/web/WebSandboxFlags.h",
   "+third_party/WebKit/public/web/WebSerializedScriptValueVersion.h",
+  "+third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h",
   "+third_party/WebKit/public/web/WebTextDirection.h",
   "+third_party/WebKit/public/web/WebTextInputType.h",
   "+third_party/WebKit/public/web/WebTreeScopeType.h",
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index 3e558cc..fb140c24a 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -192,7 +192,9 @@
   }
 }
 
-jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) {
+jint BrowserAccessibilityManagerAndroid::GetRootId(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (GetRoot())
     return static_cast<jint>(GetRoot()->GetId());
   else
@@ -200,18 +202,25 @@
 }
 
 jboolean BrowserAccessibilityManagerAndroid::IsNodeValid(
-    JNIEnv* env, jobject obj, jint id) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id) {
   return GetFromID(id) != NULL;
 }
 
 void BrowserAccessibilityManagerAndroid::HitTest(
-    JNIEnv* env, jobject obj, jint x, jint y) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint x,
+    jint y) {
   if (delegate())
     delegate()->AccessibilityHitTest(gfx::Point(x, y));
 }
 
 jboolean BrowserAccessibilityManagerAndroid::IsEditableText(
-    JNIEnv* env, jobject obj, jint id) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id) {
   BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
       GetFromID(id));
   if (!node)
@@ -221,7 +230,9 @@
 }
 
 jint BrowserAccessibilityManagerAndroid::GetEditableTextSelectionStart(
-    JNIEnv* env, jobject obj, jint id) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id) {
   BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
       GetFromID(id));
   if (!node)
@@ -231,7 +242,9 @@
 }
 
 jint BrowserAccessibilityManagerAndroid::GetEditableTextSelectionEnd(
-    JNIEnv* env, jobject obj, jint id) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id) {
   BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
       GetFromID(id));
   if (!node)
@@ -241,7 +254,10 @@
 }
 
 jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
-    JNIEnv* env, jobject obj, jobject info, jint id) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& info,
+    jint id) {
   BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
       GetFromID(id));
   if (!node)
@@ -351,7 +367,11 @@
 }
 
 jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityEvent(
-    JNIEnv* env, jobject obj, jobject event, jint id, jint event_type) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& event,
+    jint id,
+    jint event_type) {
   BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
       GetFromID(id));
   if (!node)
@@ -452,33 +472,42 @@
   return true;
 }
 
-void BrowserAccessibilityManagerAndroid::Click(
-    JNIEnv* env, jobject obj, jint id) {
+void BrowserAccessibilityManagerAndroid::Click(JNIEnv* env,
+                                               const JavaParamRef<jobject>& obj,
+                                               jint id) {
   BrowserAccessibility* node = GetFromID(id);
   if (node)
     DoDefaultAction(*node);
 }
 
-void BrowserAccessibilityManagerAndroid::Focus(
-    JNIEnv* env, jobject obj, jint id) {
+void BrowserAccessibilityManagerAndroid::Focus(JNIEnv* env,
+                                               const JavaParamRef<jobject>& obj,
+                                               jint id) {
   BrowserAccessibility* node = GetFromID(id);
   if (node)
     SetFocus(node, true);
 }
 
-void BrowserAccessibilityManagerAndroid::Blur(JNIEnv* env, jobject obj) {
+void BrowserAccessibilityManagerAndroid::Blur(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   SetFocus(GetRoot(), true);
 }
 
 void BrowserAccessibilityManagerAndroid::ScrollToMakeNodeVisible(
-    JNIEnv* env, jobject obj, jint id) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id) {
   BrowserAccessibility* node = GetFromID(id);
   if (node)
     ScrollToMakeVisible(*node, gfx::Rect(node->GetLocation().size()));
 }
 
 void BrowserAccessibilityManagerAndroid::SetTextFieldValue(
-    JNIEnv* env, jobject obj, jint id, jstring value) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id,
+    const JavaParamRef<jstring>& value) {
   BrowserAccessibility* node = GetFromID(id);
   if (node) {
     BrowserAccessibilityManager::SetValue(
@@ -487,14 +516,21 @@
 }
 
 void BrowserAccessibilityManagerAndroid::SetSelection(
-    JNIEnv* env, jobject obj, jint id, jint start, jint end) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id,
+    jint start,
+    jint end) {
   BrowserAccessibility* node = GetFromID(id);
   if (node)
     SetTextSelection(*node, start, end);
 }
 
 jboolean BrowserAccessibilityManagerAndroid::AdjustSlider(
-    JNIEnv* env, jobject obj, jint id, jboolean increment) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id,
+    jboolean increment) {
   BrowserAccessibility* node = GetFromID(id);
   if (!node)
     return false;
@@ -549,7 +585,10 @@
 }
 
 jint BrowserAccessibilityManagerAndroid::FindElementType(
-    JNIEnv* env, jobject obj, jint start_id, jstring element_type_str,
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint start_id,
+    const JavaParamRef<jstring>& element_type_str,
     jboolean forwards) {
   BrowserAccessibility* node = GetFromID(start_id);
   if (!node)
@@ -606,8 +645,12 @@
 }
 
 jboolean BrowserAccessibilityManagerAndroid::NextAtGranularity(
-    JNIEnv* env, jobject obj, jint granularity, jboolean extend_selection,
-    jint id, jint cursor_index) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint granularity,
+    jboolean extend_selection,
+    jint id,
+    jint cursor_index) {
   BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
       GetFromID(id));
   if (!node)
@@ -632,8 +675,12 @@
 }
 
 jboolean BrowserAccessibilityManagerAndroid::PreviousAtGranularity(
-    JNIEnv* env, jobject obj, jint granularity, jboolean extend_selection,
-    jint id, jint cursor_index) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint granularity,
+    jboolean extend_selection,
+    jint id,
+    jint cursor_index) {
   BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
       GetFromID(id));
   if (!node)
@@ -738,13 +785,17 @@
 }
 
 void BrowserAccessibilityManagerAndroid::SetAccessibilityFocus(
-    JNIEnv* env, jobject obj, jint id) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id) {
   if (delegate_)
     delegate_->AccessibilitySetAccessibilityFocus(id);
 }
 
 bool BrowserAccessibilityManagerAndroid::IsSlider(
-    JNIEnv* env, jobject obj, jint id) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id) {
   BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
       GetFromID(id));
   if (!node)
@@ -754,7 +805,10 @@
 }
 
 bool BrowserAccessibilityManagerAndroid::Scroll(
-    JNIEnv* env, jobject obj, jint id, int direction) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint id,
+    int direction) {
   BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
       GetFromID(id));
   if (!node)
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.h b/content/browser/accessibility/browser_accessibility_manager_android.h
index 4c69b23..669b262 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -80,37 +80,76 @@
   // --------------------------------------------------------------------------
 
   // Tree methods.
-  jint GetRootId(JNIEnv* env, jobject obj);
-  jboolean IsNodeValid(JNIEnv* env, jobject obj, jint id);
-  void HitTest(JNIEnv* env, jobject obj, jint x, jint y);
+  jint GetRootId(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  jboolean IsNodeValid(JNIEnv* env,
+                       const base::android::JavaParamRef<jobject>& obj,
+                       jint id);
+  void HitTest(JNIEnv* env,
+               const base::android::JavaParamRef<jobject>& obj,
+               jint x,
+               jint y);
 
   // Methods to get information about a specific node.
-  jboolean IsEditableText(JNIEnv* env, jobject obj, jint id);
-  jint GetEditableTextSelectionStart(JNIEnv* env, jobject obj, jint id);
-  jint GetEditableTextSelectionEnd(JNIEnv* env, jobject obj, jint id);
+  jboolean IsEditableText(JNIEnv* env,
+                          const base::android::JavaParamRef<jobject>& obj,
+                          jint id);
+  jint GetEditableTextSelectionStart(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint id);
+  jint GetEditableTextSelectionEnd(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint id);
 
   // Populate Java accessibility data structures with info about a node.
   jboolean PopulateAccessibilityNodeInfo(
-      JNIEnv* env, jobject obj, jobject info, jint id);
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jobject>& info,
+      jint id);
   jboolean PopulateAccessibilityEvent(
-      JNIEnv* env, jobject obj, jobject event, jint id, jint event_type);
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jobject>& event,
+      jint id,
+      jint event_type);
 
   // Perform actions.
-  void Click(JNIEnv* env, jobject obj, jint id);
-  void Focus(JNIEnv* env, jobject obj, jint id);
-  void Blur(JNIEnv* env, jobject obj);
-  void ScrollToMakeNodeVisible(JNIEnv* env, jobject obj, jint id);
-  void SetTextFieldValue(JNIEnv* env, jobject obj, jint id, jstring value);
-  void SetSelection(JNIEnv* env, jobject obj, jint id, jint start, jint end);
-  jboolean AdjustSlider(JNIEnv* env, jobject obj, jint id, jboolean increment);
+  void Click(JNIEnv* env,
+             const base::android::JavaParamRef<jobject>& obj,
+             jint id);
+  void Focus(JNIEnv* env,
+             const base::android::JavaParamRef<jobject>& obj,
+             jint id);
+  void Blur(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void ScrollToMakeNodeVisible(JNIEnv* env,
+                               const base::android::JavaParamRef<jobject>& obj,
+                               jint id);
+  void SetTextFieldValue(JNIEnv* env,
+                         const base::android::JavaParamRef<jobject>& obj,
+                         jint id,
+                         const base::android::JavaParamRef<jstring>& value);
+  void SetSelection(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& obj,
+                    jint id,
+                    jint start,
+                    jint end);
+  jboolean AdjustSlider(JNIEnv* env,
+                        const base::android::JavaParamRef<jobject>& obj,
+                        jint id,
+                        jboolean increment);
 
   // Return the id of the next node in tree order in the direction given by
   // |forwards|, starting with |start_id|, that matches |element_type|,
   // where |element_type| is a special uppercase string from TalkBack or
   // BrailleBack indicating general categories of web content like
   // "SECTION" or "CONTROL".  Return 0 if not found.
-  jint FindElementType(JNIEnv* env, jobject obj, jint start_id,
-                       jstring element_type, jboolean forwards);
+  jint FindElementType(JNIEnv* env,
+                       const base::android::JavaParamRef<jobject>& obj,
+                       jint start_id,
+                       const base::android::JavaParamRef<jstring>& element_type,
+                       jboolean forwards);
 
   // Respond to a ACTION_[NEXT/PREVIOUS]_AT_MOVEMENT_GRANULARITY action
   // and move the cursor/selection within the given node id. We keep track
@@ -119,12 +158,19 @@
   // in Blink, too, and either way calls
   // Java_BrowserAccessibilityManager_finishGranularityMove with the
   // result.
-  jboolean NextAtGranularity(JNIEnv* env, jobject obj,
-                             jint granularity, jboolean extend_selection,
-                             jint id, jint cursor_index);
-  jboolean PreviousAtGranularity(JNIEnv* env, jobject obj,
-                                 jint granularity, jboolean extend_selection,
-                                 jint id, jint cursor_index);
+  jboolean NextAtGranularity(JNIEnv* env,
+                             const base::android::JavaParamRef<jobject>& obj,
+                             jint granularity,
+                             jboolean extend_selection,
+                             jint id,
+                             jint cursor_index);
+  jboolean PreviousAtGranularity(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint granularity,
+      jboolean extend_selection,
+      jint id,
+      jint cursor_index);
 
   // Helper functions to compute the next start and end index when moving
   // forwards or backwards by character, word, or line. This part is
@@ -142,14 +188,21 @@
   // Set accessibility focus. This sends a message to the renderer to
   // asynchronously load inline text boxes for this node only, enabling more
   // accurate movement by granularities on this node.
-  void SetAccessibilityFocus(JNIEnv* env, jobject obj, jint id);
+  void SetAccessibilityFocus(JNIEnv* env,
+                             const base::android::JavaParamRef<jobject>& obj,
+                             jint id);
 
   // Returns true if the object is a slider.
-  bool IsSlider(JNIEnv* env, jobject obj, jint id);
+  bool IsSlider(JNIEnv* env,
+                const base::android::JavaParamRef<jobject>& obj,
+                jint id);
 
   // Scrolls any scrollable container by about 80% of one page in the
   // given direction.
-  bool Scroll(JNIEnv* env, jobject obj, jint id, int direction);
+  bool Scroll(JNIEnv* env,
+              const base::android::JavaParamRef<jobject>& obj,
+              jint id,
+              int direction);
 
  protected:
   // AXTreeDelegate overrides.
diff --git a/content/browser/android/background_sync_network_observer_android.cc b/content/browser/android/background_sync_network_observer_android.cc
index fe139768..05d46ecd 100644
--- a/content/browser/android/background_sync_network_observer_android.cc
+++ b/content/browser/android/background_sync_network_observer_android.cc
@@ -51,7 +51,7 @@
 
 void BackgroundSyncNetworkObserverAndroid::Observer::
     NotifyConnectionTypeChanged(JNIEnv* env,
-                                jobject jcaller,
+                                const JavaParamRef<jobject>& jcaller,
                                 jint new_connection_type) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
diff --git a/content/browser/android/background_sync_network_observer_android.h b/content/browser/android/background_sync_network_observer_android.h
index 49e8b0a..14c09f1 100644
--- a/content/browser/android/background_sync_network_observer_android.h
+++ b/content/browser/android/background_sync_network_observer_android.h
@@ -46,9 +46,10 @@
     // connection type changes. This updates the current connection type seen by
     // this class and calls the |network_changed_callback| provided to the
     // constructor, on the IO thread, with the new connection type.
-    void NotifyConnectionTypeChanged(JNIEnv* env,
-                                     jobject jcaller,
-                                     jint new_connection_type);
+    void NotifyConnectionTypeChanged(
+        JNIEnv* env,
+        const base::android::JavaParamRef<jobject>& jcaller,
+        jint new_connection_type);
 
    private:
     friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
diff --git a/content/browser/android/content_video_view.cc b/content/browser/android/content_video_view.cc
index 24d4647e..78c3bcf3 100644
--- a/content/browser/android/content_video_view.cc
+++ b/content/browser/android/content_video_view.cc
@@ -122,8 +122,10 @@
     Java_ContentVideoView_onExitFullscreen(env, content_video_view.obj());
 }
 
-void ContentVideoView::RecordFullscreenPlayback(
-    JNIEnv*, jobject, bool is_portrait_video, bool is_orientation_portrait) {
+void ContentVideoView::RecordFullscreenPlayback(JNIEnv*,
+                                                const JavaParamRef<jobject>&,
+                                                bool is_portrait_video,
+                                                bool is_orientation_portrait) {
   UMA_HISTOGRAM_BOOLEAN("MobileFullscreenVideo.OrientationPortrait",
                         is_orientation_portrait);
   UMA_HISTOGRAM_BOOLEAN("MobileFullscreenVideo.VideoPortrait",
@@ -131,7 +133,9 @@
 }
 
 void ContentVideoView::RecordExitFullscreenPlayback(
-    JNIEnv*, jobject, bool is_portrait_video,
+    JNIEnv*,
+    const JavaParamRef<jobject>&,
+    bool is_portrait_video,
     long playback_duration_in_milliseconds_before_orientation_change,
     long playback_duration_in_milliseconds_after_orientation_change) {
   bool orientation_changed = (
@@ -172,24 +176,27 @@
   }
 }
 
-bool ContentVideoView::IsPlaying(JNIEnv*, jobject obj) {
+bool ContentVideoView::IsPlaying(JNIEnv*, const JavaParamRef<jobject>& obj) {
   media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
   return player ? player->IsPlaying() : false;
 }
 
-void ContentVideoView::ExitFullscreen(
-    JNIEnv*, jobject, jboolean release_media_player) {
+void ContentVideoView::ExitFullscreen(JNIEnv*,
+                                      const JavaParamRef<jobject>&,
+                                      jboolean release_media_player) {
   j_content_video_view_.reset();
   manager_->ExitFullscreen(release_media_player);
 }
 
-void ContentVideoView::SetSurface(JNIEnv* env, jobject obj,
-                                  jobject surface) {
+void ContentVideoView::SetSurface(JNIEnv* env,
+                                  const JavaParamRef<jobject>& obj,
+                                  const JavaParamRef<jobject>& surface) {
   manager_->SetVideoSurface(
       gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
 }
 
-void ContentVideoView::RequestMediaMetadata(JNIEnv* env, jobject obj) {
+void ContentVideoView::RequestMediaMetadata(JNIEnv* env,
+                                            const JavaParamRef<jobject>& obj) {
   base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&ContentVideoView::UpdateMediaMetadata,
diff --git a/content/browser/android/content_video_view.h b/content/browser/android/content_video_view.h
index 37b7f2e..ae54fac 100644
--- a/content/browser/android/content_video_view.h
+++ b/content/browser/android/content_video_view.h
@@ -41,16 +41,21 @@
   static ContentVideoView* GetInstance();
 
   // Getter method called by the Java class to get the media information.
-  bool IsPlaying(JNIEnv*, jobject obj);
-  void RequestMediaMetadata(JNIEnv*, jobject obj);
+  bool IsPlaying(JNIEnv*, const base::android::JavaParamRef<jobject>& obj);
+  void RequestMediaMetadata(JNIEnv*,
+                            const base::android::JavaParamRef<jobject>& obj);
 
   // Called when the Java fullscreen view is destroyed. If
   // |release_media_player| is true, |manager_| needs to release the player
   // as we are quitting the app.
-  void ExitFullscreen(JNIEnv*, jobject, jboolean release_media_player);
+  void ExitFullscreen(JNIEnv*,
+                      const base::android::JavaParamRef<jobject>&,
+                      jboolean release_media_player);
 
   // Called by the Java class to pass the surface object to the player.
-  void SetSurface(JNIEnv*, jobject obj, jobject surface);
+  void SetSurface(JNIEnv*,
+                  const base::android::JavaParamRef<jobject>& obj,
+                  const base::android::JavaParamRef<jobject>& surface);
 
   // Method called by |manager_| to inform the Java class about player status
   // change.
@@ -62,10 +67,14 @@
   void OnExitFullscreen();
 
   // Functions called to record fullscreen playback UMA metrics.
-  void RecordFullscreenPlayback(
-      JNIEnv*, jobject, bool is_portrait_video, bool is_orientation_portrait);
+  void RecordFullscreenPlayback(JNIEnv*,
+                                const base::android::JavaParamRef<jobject>&,
+                                bool is_portrait_video,
+                                bool is_orientation_portrait);
   void RecordExitFullscreenPlayback(
-      JNIEnv*, jobject, bool is_portrait_video,
+      JNIEnv*,
+      const base::android::JavaParamRef<jobject>&,
+      bool is_portrait_video,
       long playback_duration_in_milliseconds_before_orientation_change,
       long playback_duration_in_milliseconds_after_orientation_change);
 
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 7aa79ee..0c3a6ae1 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -257,19 +257,22 @@
 }
 
 base::android::ScopedJavaLocalRef<jobject>
-ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
+ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env,
+                                           const JavaParamRef<jobject>& obj) {
   return web_contents_->GetJavaWebContents();
 }
 
 base::android::ScopedJavaLocalRef<jobject>
-ContentViewCoreImpl::GetJavaWindowAndroid(JNIEnv* env, jobject obj) {
+ContentViewCoreImpl::GetJavaWindowAndroid(JNIEnv* env,
+                                          const JavaParamRef<jobject>& obj) {
   if (!window_android_)
     return ScopedJavaLocalRef<jobject>();
   return window_android_->GetJavaObject();
 }
 
-void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
-                                                         jobject obj) {
+void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
   java_ref_.reset();
   // Java peer has gone, ContentViewCore is not functional and waits to
@@ -811,10 +814,11 @@
 // Methods called from Java via JNI
 // ----------------------------------------------------------------------------
 
-void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
-                                               jobject obj,
-                                               jlong selectPopupSourceFrame,
-                                               jintArray indices) {
+void ContentViewCoreImpl::SelectPopupMenuItems(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jlong selectPopupSourceFrame,
+    const JavaParamRef<jintArray>& indices) {
   RenderFrameHostImpl* rfhi =
       reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
   DCHECK(rfhi);
@@ -836,7 +840,9 @@
   return web_contents_;
 }
 
-void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
+void ContentViewCoreImpl::SetFocus(JNIEnv* env,
+                                   const JavaParamRef<jobject>& obj,
+                                   jboolean focused) {
   SetFocusInternal(focused);
 }
 
@@ -850,44 +856,46 @@
     GetRenderWidgetHostViewAndroid()->Blur();
 }
 
-void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
-                                                     jobject obj,
-                                                     jint orientation) {
+void ContentViewCoreImpl::SendOrientationChangeEvent(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint orientation) {
   if (device_orientation_ != orientation) {
     device_orientation_ = orientation;
     SendOrientationChangeEventInternal();
   }
 }
 
-jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
-                                           jobject obj,
-                                           jobject motion_event,
-                                           jlong time_ms,
-                                           jint android_action,
-                                           jint pointer_count,
-                                           jint history_size,
-                                           jint action_index,
-                                           jfloat pos_x_0,
-                                           jfloat pos_y_0,
-                                           jfloat pos_x_1,
-                                           jfloat pos_y_1,
-                                           jint pointer_id_0,
-                                           jint pointer_id_1,
-                                           jfloat touch_major_0,
-                                           jfloat touch_major_1,
-                                           jfloat touch_minor_0,
-                                           jfloat touch_minor_1,
-                                           jfloat orientation_0,
-                                           jfloat orientation_1,
-                                           jfloat tilt_0,
-                                           jfloat tilt_1,
-                                           jfloat raw_pos_x,
-                                           jfloat raw_pos_y,
-                                           jint android_tool_type_0,
-                                           jint android_tool_type_1,
-                                           jint android_button_state,
-                                           jint android_meta_state,
-                                           jboolean is_touch_handle_event) {
+jboolean ContentViewCoreImpl::OnTouchEvent(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& motion_event,
+    jlong time_ms,
+    jint android_action,
+    jint pointer_count,
+    jint history_size,
+    jint action_index,
+    jfloat pos_x_0,
+    jfloat pos_y_0,
+    jfloat pos_x_1,
+    jfloat pos_y_1,
+    jint pointer_id_0,
+    jint pointer_id_1,
+    jfloat touch_major_0,
+    jfloat touch_major_1,
+    jfloat touch_minor_0,
+    jfloat touch_minor_1,
+    jfloat orientation_0,
+    jfloat orientation_1,
+    jfloat tilt_0,
+    jfloat tilt_1,
+    jfloat raw_pos_x,
+    jfloat raw_pos_y,
+    jint android_tool_type_0,
+    jint android_tool_type_1,
+    jint android_button_state,
+    jint android_meta_state,
+    jboolean is_touch_handle_event) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   // Avoid synthesizing a touch event if it cannot be forwarded.
   if (!rwhv)
@@ -932,11 +940,12 @@
   return dpi_scale_;
 }
 
-jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
-                                                 jobject obj,
-                                                 jlong time_ms,
-                                                 jfloat x,
-                                                 jfloat y) {
+jboolean ContentViewCoreImpl::SendMouseMoveEvent(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jlong time_ms,
+    jfloat x,
+    jfloat y) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (!rwhv)
     return false;
@@ -950,14 +959,15 @@
   return true;
 }
 
-jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
-                                                  jobject obj,
-                                                  jlong time_ms,
-                                                  jfloat x,
-                                                  jfloat y,
-                                                  jfloat ticks_x,
-                                                  jfloat ticks_y,
-                                                  jfloat pixels_per_tick) {
+jboolean ContentViewCoreImpl::SendMouseWheelEvent(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jlong time_ms,
+    jfloat x,
+    jfloat y,
+    jfloat ticks_x,
+    jfloat ticks_y,
+    jfloat pixels_per_tick) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (!rwhv)
     return false;
@@ -987,7 +997,7 @@
 }
 
 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
-                                      jobject obj,
+                                      const JavaParamRef<jobject>& obj,
                                       jlong time_ms,
                                       jfloat x,
                                       jfloat y,
@@ -1003,14 +1013,21 @@
   SendGestureEvent(event);
 }
 
-void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
+void ContentViewCoreImpl::ScrollEnd(JNIEnv* env,
+                                    const JavaParamRef<jobject>& obj,
+                                    jlong time_ms) {
   WebGestureEvent event = MakeGestureEvent(
       WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
   SendGestureEvent(event);
 }
 
-void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
-                                   jfloat x, jfloat y, jfloat dx, jfloat dy) {
+void ContentViewCoreImpl::ScrollBy(JNIEnv* env,
+                                   const JavaParamRef<jobject>& obj,
+                                   jlong time_ms,
+                                   jfloat x,
+                                   jfloat y,
+                                   jfloat dx,
+                                   jfloat dy) {
   WebGestureEvent event = MakeGestureEvent(
       WebInputEvent::GestureScrollUpdate, time_ms, x, y);
   event.data.scrollUpdate.deltaX = -dx / dpi_scale();
@@ -1020,7 +1037,7 @@
 }
 
 void ContentViewCoreImpl::FlingStart(JNIEnv* env,
-                                     jobject obj,
+                                     const JavaParamRef<jobject>& obj,
                                      jlong time_ms,
                                      jfloat x,
                                      jfloat y,
@@ -1036,7 +1053,9 @@
   SendGestureEvent(event);
 }
 
-void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
+void ContentViewCoreImpl::FlingCancel(JNIEnv* env,
+                                      const JavaParamRef<jobject>& obj,
+                                      jlong time_ms) {
   WebGestureEvent event = MakeGestureEvent(
       WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
   event.data.flingCancel.preventBoosting = true;
@@ -1044,8 +1063,11 @@
   SendGestureEvent(event);
 }
 
-void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
-                                    jfloat x, jfloat y) {
+void ContentViewCoreImpl::SingleTap(JNIEnv* env,
+                                    const JavaParamRef<jobject>& obj,
+                                    jlong time_ms,
+                                    jfloat x,
+                                    jfloat y) {
   // Tap gestures should always be preceded by a TapDown, ensuring consistency
   // with the touch-based gesture detection pipeline.
   WebGestureEvent tap_down_event = MakeGestureEvent(
@@ -1059,8 +1081,11 @@
   SendGestureEvent(tap_event);
 }
 
-void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
-                                    jfloat x, jfloat y) {
+void ContentViewCoreImpl::DoubleTap(JNIEnv* env,
+                                    const JavaParamRef<jobject>& obj,
+                                    jlong time_ms,
+                                    jfloat x,
+                                    jfloat y) {
   WebGestureEvent event = MakeGestureEvent(
       WebInputEvent::GestureDoubleTap, time_ms, x, y);
   // Set the tap count to 1 even for DoubleTap, in order to be consistent with
@@ -1070,29 +1095,40 @@
   SendGestureEvent(event);
 }
 
-void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
-                                    jfloat x, jfloat y) {
+void ContentViewCoreImpl::LongPress(JNIEnv* env,
+                                    const JavaParamRef<jobject>& obj,
+                                    jlong time_ms,
+                                    jfloat x,
+                                    jfloat y) {
   WebGestureEvent event = MakeGestureEvent(
       WebInputEvent::GestureLongPress, time_ms, x, y);
 
   SendGestureEvent(event);
 }
 
-void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
-                                     jfloat x, jfloat y) {
+void ContentViewCoreImpl::PinchBegin(JNIEnv* env,
+                                     const JavaParamRef<jobject>& obj,
+                                     jlong time_ms,
+                                     jfloat x,
+                                     jfloat y) {
   WebGestureEvent event = MakeGestureEvent(
       WebInputEvent::GesturePinchBegin, time_ms, x, y);
   SendGestureEvent(event);
 }
 
-void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
+void ContentViewCoreImpl::PinchEnd(JNIEnv* env,
+                                   const JavaParamRef<jobject>& obj,
+                                   jlong time_ms) {
   WebGestureEvent event = MakeGestureEvent(
       WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
   SendGestureEvent(event);
 }
 
-void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
-                                  jfloat anchor_x, jfloat anchor_y,
+void ContentViewCoreImpl::PinchBy(JNIEnv* env,
+                                  const JavaParamRef<jobject>& obj,
+                                  jlong time_ms,
+                                  jfloat anchor_x,
+                                  jfloat anchor_y,
                                   jfloat delta) {
   WebGestureEvent event = MakeGestureEvent(
       WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
@@ -1101,51 +1137,63 @@
   SendGestureEvent(event);
 }
 
-void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
-                                                   jfloat x1, jfloat y1,
-                                                   jfloat x2, jfloat y2) {
+void ContentViewCoreImpl::SelectBetweenCoordinates(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jfloat x1,
+    jfloat y1,
+    jfloat x2,
+    jfloat y2) {
   SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
                            gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
 }
 
-void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
-                                    jfloat x, jfloat y) {
+void ContentViewCoreImpl::MoveCaret(JNIEnv* env,
+                                    const JavaParamRef<jobject>& obj,
+                                    jfloat x,
+                                    jfloat y) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (rwhv)
     rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
 }
 
-void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
+void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (rwhv)
     rwhv->DismissTextHandles();
 }
 
-void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
-                                                          jobject obj,
-                                                          jboolean hidden) {
+void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jboolean hidden) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (rwhv)
     rwhv->SetTextHandlesTemporarilyHidden(hidden);
 }
 
-void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
+void ContentViewCoreImpl::ResetGestureDetection(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (rwhv)
     rwhv->ResetGestureDetection();
 }
 
-void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
-                                                     jobject obj,
-                                                     jboolean enabled) {
+void ContentViewCoreImpl::SetDoubleTapSupportEnabled(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jboolean enabled) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (rwhv)
     rwhv->SetDoubleTapSupportEnabled(enabled);
 }
 
-void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
-                                                          jobject obj,
-                                                          jboolean enabled) {
+void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jboolean enabled) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (rwhv)
     rwhv->SetMultiTouchZoomSupportEnabled(enabled);
@@ -1153,31 +1201,31 @@
 
 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jboolean allow) {
   java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
 }
 
 void ContentViewCoreImpl::AddJavascriptInterface(
     JNIEnv* env,
-    jobject /* obj */,
-    jobject object,
-    jstring name,
-    jclass safe_annotation_clazz) {
-  ScopedJavaLocalRef<jobject> scoped_object(env, object);
-  ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
+    const JavaParamRef<jobject>& /* obj */,
+    const JavaParamRef<jobject>& object,
+    const JavaParamRef<jstring>& name,
+    const JavaParamRef<jclass>& safe_annotation_clazz) {
   java_bridge_dispatcher_host_->AddNamedObject(
-      ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
+      ConvertJavaStringToUTF8(env, name), object, safe_annotation_clazz);
 }
 
-void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
-                                                    jobject /* obj */,
-                                                    jstring name) {
+void ContentViewCoreImpl::RemoveJavascriptInterface(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& /* obj */,
+    const JavaParamRef<jstring>& name) {
   java_bridge_dispatcher_host_->RemoveNamedObject(
       ConvertJavaStringToUTF8(env, name));
 }
 
-void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
+void ContentViewCoreImpl::WasResized(JNIEnv* env,
+                                     const JavaParamRef<jobject>& obj) {
   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   gfx::Size physical_size(
       Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
@@ -1192,7 +1240,9 @@
   }
 }
 
-long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
+long ContentViewCoreImpl::GetNativeImeAdapter(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
   if (!rwhva)
     return 0;
@@ -1238,21 +1288,24 @@
                                         is_non_ime_change);
 }
 
-void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
-                                                  bool enabled) {
+void ContentViewCoreImpl::SetAccessibilityEnabled(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    bool enabled) {
   SetAccessibilityEnabledInternal(enabled);
 }
 
-void ContentViewCoreImpl::SetTextTrackSettings(JNIEnv* env,
-                                               jobject obj,
-                                               jboolean textTracksEnabled,
-                                               jstring textTrackBackgroundColor,
-                                               jstring textTrackFontFamily,
-                                               jstring textTrackFontStyle,
-                                               jstring textTrackFontVariant,
-                                               jstring textTrackTextColor,
-                                               jstring textTrackTextShadow,
-                                               jstring textTrackTextSize) {
+void ContentViewCoreImpl::SetTextTrackSettings(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jboolean textTracksEnabled,
+    const JavaParamRef<jstring>& textTrackBackgroundColor,
+    const JavaParamRef<jstring>& textTrackFontFamily,
+    const JavaParamRef<jstring>& textTrackFontStyle,
+    const JavaParamRef<jstring>& textTrackFontVariant,
+    const JavaParamRef<jstring>& textTrackTextColor,
+    const JavaParamRef<jstring>& textTrackTextShadow,
+    const JavaParamRef<jstring>& textTrackTextSize) {
   FrameMsg_TextTrackSettings_Params params;
   params.text_tracks_enabled = textTracksEnabled;
   params.text_track_background_color = ConvertJavaStringToUTF8(
@@ -1311,7 +1364,7 @@
 }
 
 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
-                                               jobject obj,
+                                               const JavaParamRef<jobject>& obj,
                                                jint x,
                                                jint y,
                                                jint width,
@@ -1327,13 +1380,16 @@
       GetWebContents()->GetRoutingID(), rect));
 }
 
-jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
+jint ContentViewCoreImpl::GetCurrentRenderProcessId(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return GetRenderProcessIdFromRenderViewHost(
       web_contents_->GetRenderViewHost());
 }
 
-void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
-    jboolean opaque) {
+void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env,
+                                              const JavaParamRef<jobject>& jobj,
+                                              jboolean opaque) {
   if (GetRenderWidgetHostViewAndroid()) {
     if (opaque)
       GetRenderWidgetHostViewAndroid()->SetBackgroundColorToDefault();
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index 55157a1..c3acf0b 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -71,56 +71,66 @@
   // Methods called from Java via JNI
   // --------------------------------------------------------------------------
 
-  base::android::ScopedJavaLocalRef<jobject> GetWebContentsAndroid(JNIEnv* env,
-                                                                   jobject obj);
-  base::android::ScopedJavaLocalRef<jobject> GetJavaWindowAndroid(JNIEnv* env,
-                                                                  jobject obj);
+  base::android::ScopedJavaLocalRef<jobject> GetWebContentsAndroid(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  base::android::ScopedJavaLocalRef<jobject> GetJavaWindowAndroid(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
-  void OnJavaContentViewCoreDestroyed(JNIEnv* env, jobject obj);
+  void OnJavaContentViewCoreDestroyed(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Notifies the ContentViewCore that items were selected in the currently
   // showing select popup.
-  void SelectPopupMenuItems(JNIEnv* env, jobject obj,
-                            jlong selectPopupSourceFrame,
-                            jintArray indices);
+  void SelectPopupMenuItems(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jlong selectPopupSourceFrame,
+      const base::android::JavaParamRef<jintArray>& indices);
 
-  void SendOrientationChangeEvent(JNIEnv* env, jobject obj, jint orientation);
-  jboolean OnTouchEvent(JNIEnv* env,
-                        jobject obj,
-                        jobject motion_event,
-                        jlong time_ms,
-                        jint android_action,
-                        jint pointer_count,
-                        jint history_size,
-                        jint action_index,
-                        jfloat pos_x_0,
-                        jfloat pos_y_0,
-                        jfloat pos_x_1,
-                        jfloat pos_y_1,
-                        jint pointer_id_0,
-                        jint pointer_id_1,
-                        jfloat touch_major_0,
-                        jfloat touch_major_1,
-                        jfloat touch_minor_0,
-                        jfloat touch_minor_1,
-                        jfloat orientation_0,
-                        jfloat orientation_1,
-                        jfloat tilt_0,
-                        jfloat tilt_1,
-                        jfloat raw_pos_x,
-                        jfloat raw_pos_y,
-                        jint android_tool_type_0,
-                        jint android_tool_type_1,
-                        jint android_button_state,
-                        jint android_meta_state,
-                        jboolean is_touch_handle_event);
+  void SendOrientationChangeEvent(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint orientation);
+  jboolean OnTouchEvent(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jobject>& motion_event,
+      jlong time_ms,
+      jint android_action,
+      jint pointer_count,
+      jint history_size,
+      jint action_index,
+      jfloat pos_x_0,
+      jfloat pos_y_0,
+      jfloat pos_x_1,
+      jfloat pos_y_1,
+      jint pointer_id_0,
+      jint pointer_id_1,
+      jfloat touch_major_0,
+      jfloat touch_major_1,
+      jfloat touch_minor_0,
+      jfloat touch_minor_1,
+      jfloat orientation_0,
+      jfloat orientation_1,
+      jfloat tilt_0,
+      jfloat tilt_1,
+      jfloat raw_pos_x,
+      jfloat raw_pos_y,
+      jint android_tool_type_0,
+      jint android_tool_type_1,
+      jint android_button_state,
+      jint android_meta_state,
+      jboolean is_touch_handle_event);
   jboolean SendMouseMoveEvent(JNIEnv* env,
-                              jobject obj,
+                              const base::android::JavaParamRef<jobject>& obj,
                               jlong time_ms,
                               jfloat x,
                               jfloat y);
   jboolean SendMouseWheelEvent(JNIEnv* env,
-                               jobject obj,
+                               const base::android::JavaParamRef<jobject>& obj,
                                jlong time_ms,
                                jfloat x,
                                jfloat y,
@@ -128,89 +138,145 @@
                                jfloat ticks_y,
                                jfloat pixels_per_tick);
   void ScrollBegin(JNIEnv* env,
-                   jobject obj,
+                   const base::android::JavaParamRef<jobject>& obj,
                    jlong time_ms,
                    jfloat x,
                    jfloat y,
                    jfloat hintx,
                    jfloat hinty,
                    jboolean target_viewport);
-  void ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms);
-  void ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
-                jfloat x, jfloat y, jfloat dx, jfloat dy);
+  void ScrollEnd(JNIEnv* env,
+                 const base::android::JavaParamRef<jobject>& obj,
+                 jlong time_ms);
+  void ScrollBy(JNIEnv* env,
+                const base::android::JavaParamRef<jobject>& obj,
+                jlong time_ms,
+                jfloat x,
+                jfloat y,
+                jfloat dx,
+                jfloat dy);
   void FlingStart(JNIEnv* env,
-                  jobject obj,
+                  const base::android::JavaParamRef<jobject>& obj,
                   jlong time_ms,
                   jfloat x,
                   jfloat y,
                   jfloat vx,
                   jfloat vy,
                   jboolean target_viewport);
-  void FlingCancel(JNIEnv* env, jobject obj, jlong time_ms);
-  void SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
-                 jfloat x, jfloat y);
-  void DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
-                 jfloat x, jfloat y);
-  void LongPress(JNIEnv* env, jobject obj, jlong time_ms,
-                 jfloat x, jfloat y);
-  void PinchBegin(JNIEnv* env, jobject obj, jlong time_ms, jfloat x, jfloat y);
-  void PinchEnd(JNIEnv* env, jobject obj, jlong time_ms);
-  void PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
-               jfloat x, jfloat y, jfloat delta);
-  void SelectBetweenCoordinates(JNIEnv* env, jobject obj,
-                                jfloat x1, jfloat y1,
-                                jfloat x2, jfloat y2);
-  void MoveCaret(JNIEnv* env, jobject obj, jfloat x, jfloat y);
-  void DismissTextHandles(JNIEnv* env, jobject obj);
-  void SetTextHandlesTemporarilyHidden(JNIEnv* env,
-                                       jobject obj,
-                                       jboolean hidden);
+  void FlingCancel(JNIEnv* env,
+                   const base::android::JavaParamRef<jobject>& obj,
+                   jlong time_ms);
+  void SingleTap(JNIEnv* env,
+                 const base::android::JavaParamRef<jobject>& obj,
+                 jlong time_ms,
+                 jfloat x,
+                 jfloat y);
+  void DoubleTap(JNIEnv* env,
+                 const base::android::JavaParamRef<jobject>& obj,
+                 jlong time_ms,
+                 jfloat x,
+                 jfloat y);
+  void LongPress(JNIEnv* env,
+                 const base::android::JavaParamRef<jobject>& obj,
+                 jlong time_ms,
+                 jfloat x,
+                 jfloat y);
+  void PinchBegin(JNIEnv* env,
+                  const base::android::JavaParamRef<jobject>& obj,
+                  jlong time_ms,
+                  jfloat x,
+                  jfloat y);
+  void PinchEnd(JNIEnv* env,
+                const base::android::JavaParamRef<jobject>& obj,
+                jlong time_ms);
+  void PinchBy(JNIEnv* env,
+               const base::android::JavaParamRef<jobject>& obj,
+               jlong time_ms,
+               jfloat x,
+               jfloat y,
+               jfloat delta);
+  void SelectBetweenCoordinates(JNIEnv* env,
+                                const base::android::JavaParamRef<jobject>& obj,
+                                jfloat x1,
+                                jfloat y1,
+                                jfloat x2,
+                                jfloat y2);
+  void MoveCaret(JNIEnv* env,
+                 const base::android::JavaParamRef<jobject>& obj,
+                 jfloat x,
+                 jfloat y);
+  void DismissTextHandles(JNIEnv* env,
+                          const base::android::JavaParamRef<jobject>& obj);
+  void SetTextHandlesTemporarilyHidden(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jboolean hidden);
 
-  void ResetGestureDetection(JNIEnv* env, jobject obj);
-  void SetDoubleTapSupportEnabled(JNIEnv* env, jobject obj, jboolean enabled);
-  void SetMultiTouchZoomSupportEnabled(JNIEnv* env,
-                                       jobject obj,
-                                       jboolean enabled);
+  void ResetGestureDetection(JNIEnv* env,
+                             const base::android::JavaParamRef<jobject>& obj);
+  void SetDoubleTapSupportEnabled(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jboolean enabled);
+  void SetMultiTouchZoomSupportEnabled(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jboolean enabled);
 
-  long GetNativeImeAdapter(JNIEnv* env, jobject obj);
-  void SetFocus(JNIEnv* env, jobject obj, jboolean focused);
+  long GetNativeImeAdapter(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& obj);
+  void SetFocus(JNIEnv* env,
+                const base::android::JavaParamRef<jobject>& obj,
+                jboolean focused);
 
   jint GetBackgroundColor(JNIEnv* env, jobject obj);
   void SetBackgroundColor(JNIEnv* env, jobject obj, jint color);
-  void SetAllowJavascriptInterfacesInspection(JNIEnv* env,
-                                              jobject obj,
-                                              jboolean allow);
-  void AddJavascriptInterface(JNIEnv* env,
-                              jobject obj,
-                              jobject object,
-                              jstring name,
-                              jclass safe_annotation_clazz);
-  void RemoveJavascriptInterface(JNIEnv* env, jobject obj, jstring name);
-  void WasResized(JNIEnv* env, jobject obj);
+  void SetAllowJavascriptInterfacesInspection(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jboolean allow);
+  void AddJavascriptInterface(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jobject>& object,
+      const base::android::JavaParamRef<jstring>& name,
+      const base::android::JavaParamRef<jclass>& safe_annotation_clazz);
+  void RemoveJavascriptInterface(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& name);
+  void WasResized(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
 
-  void SetAccessibilityEnabled(JNIEnv* env, jobject obj, bool enabled);
+  void SetAccessibilityEnabled(JNIEnv* env,
+                               const base::android::JavaParamRef<jobject>& obj,
+                               bool enabled);
 
-  void SetTextTrackSettings(JNIEnv* env,
-                            jobject obj,
-                            jboolean textTracksEnabled,
-                            jstring textTrackBackgroundColor,
-                            jstring textTrackFontFamily,
-                            jstring textTrackFontStyle,
-                            jstring textTrackFontVariant,
-                            jstring textTrackTextColor,
-                            jstring textTrackTextShadow,
-                            jstring textTrackTextSize);
+  void SetTextTrackSettings(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jboolean textTracksEnabled,
+      const base::android::JavaParamRef<jstring>& textTrackBackgroundColor,
+      const base::android::JavaParamRef<jstring>& textTrackFontFamily,
+      const base::android::JavaParamRef<jstring>& textTrackFontStyle,
+      const base::android::JavaParamRef<jstring>& textTrackFontVariant,
+      const base::android::JavaParamRef<jstring>& textTrackTextColor,
+      const base::android::JavaParamRef<jstring>& textTrackTextShadow,
+      const base::android::JavaParamRef<jstring>& textTrackTextSize);
 
   void ExtractSmartClipData(JNIEnv* env,
-                            jobject obj,
+                            const base::android::JavaParamRef<jobject>& obj,
                             jint x,
                             jint y,
                             jint width,
                             jint height);
 
-  void SetBackgroundOpaque(JNIEnv* env, jobject jobj, jboolean opaque);
+  void SetBackgroundOpaque(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& jobj,
+                           jboolean opaque);
 
-  jint GetCurrentRenderProcessId(JNIEnv* env, jobject obj);
+  jint GetCurrentRenderProcessId(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // --------------------------------------------------------------------------
   // Public methods that call to Java via JNI
diff --git a/content/browser/android/content_view_render_view.cc b/content/browser/android/content_view_render_view.cc
index 906744c1..24fdbc2f 100644
--- a/content/browser/android/content_view_render_view.cc
+++ b/content/browser/android/content_view_render_view.cc
@@ -52,12 +52,15 @@
   return reinterpret_cast<intptr_t>(content_view_render_view);
 }
 
-void ContentViewRenderView::Destroy(JNIEnv* env, jobject obj) {
+void ContentViewRenderView::Destroy(JNIEnv* env,
+                                    const JavaParamRef<jobject>& obj) {
   delete this;
 }
 
 void ContentViewRenderView::SetCurrentContentViewCore(
-    JNIEnv* env, jobject obj, jlong native_content_view_core) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jlong native_content_view_core) {
   InitCompositor();
   ContentViewCoreImpl* content_view_core =
       reinterpret_cast<ContentViewCoreImpl*>(native_content_view_core);
@@ -65,19 +68,25 @@
                                               : scoped_refptr<cc::Layer>());
 }
 
-void ContentViewRenderView::SurfaceCreated(
-    JNIEnv* env, jobject obj) {
+void ContentViewRenderView::SurfaceCreated(JNIEnv* env,
+                                           const JavaParamRef<jobject>& obj) {
   current_surface_format_ = 0;
   InitCompositor();
 }
 
-void ContentViewRenderView::SurfaceDestroyed(JNIEnv* env, jobject obj) {
+void ContentViewRenderView::SurfaceDestroyed(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj) {
   compositor_->SetSurface(NULL);
   current_surface_format_ = 0;
 }
 
-void ContentViewRenderView::SurfaceChanged(JNIEnv* env, jobject obj,
-    jint format, jint width, jint height, jobject surface) {
+void ContentViewRenderView::SurfaceChanged(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint format,
+    jint width,
+    jint height,
+    const JavaParamRef<jobject>& surface) {
   if (current_surface_format_ != format) {
     current_surface_format_ = format;
     compositor_->SetSurface(surface);
@@ -86,12 +95,16 @@
 }
 
 void ContentViewRenderView::SetOverlayVideoMode(
-    JNIEnv* env, jobject obj, bool enabled) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    bool enabled) {
   compositor_->SetHasTransparentBackground(enabled);
   SetNeedsComposite(env, obj);
 }
 
-void ContentViewRenderView::SetNeedsComposite(JNIEnv* env, jobject obj) {
+void ContentViewRenderView::SetNeedsComposite(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (compositor_)
     compositor_->SetNeedsComposite();
 }
@@ -111,8 +124,9 @@
     compositor_.reset(Compositor::Create(this, root_window_));
 }
 
-jlong ContentViewRenderView::GetUIResourceProvider(JNIEnv* env,
-                                                   jobject obj) {
+jlong ContentViewRenderView::GetUIResourceProvider(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (!compositor_)
     return 0;
   return reinterpret_cast<intptr_t>(&compositor_->GetUIResourceProvider());
diff --git a/content/browser/android/content_view_render_view.h b/content/browser/android/content_view_render_view.h
index 980759ed..9bf846c 100644
--- a/content/browser/android/content_view_render_view.h
+++ b/content/browser/android/content_view_render_view.h
@@ -29,19 +29,31 @@
                         gfx::NativeWindow root_window);
 
   // Methods called from Java via JNI -----------------------------------------
-  void Destroy(JNIEnv* env, jobject obj);
-  void SetCurrentContentViewCore(JNIEnv* env, jobject obj,
-                                 jlong native_content_view_core);
-  void SurfaceCreated(JNIEnv* env, jobject obj);
-  void SurfaceDestroyed(JNIEnv* env, jobject obj);
-  void SurfaceChanged(JNIEnv* env, jobject obj,
-                      jint format, jint width, jint height, jobject surface);
-  void SetOverlayVideoMode(JNIEnv* env, jobject obj, bool enabled);
-  void SetNeedsComposite(JNIEnv* env, jobject obj);
+  void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void SetCurrentContentViewCore(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jlong native_content_view_core);
+  void SurfaceCreated(JNIEnv* env,
+                      const base::android::JavaParamRef<jobject>& obj);
+  void SurfaceDestroyed(JNIEnv* env,
+                        const base::android::JavaParamRef<jobject>& obj);
+  void SurfaceChanged(JNIEnv* env,
+                      const base::android::JavaParamRef<jobject>& obj,
+                      jint format,
+                      jint width,
+                      jint height,
+                      const base::android::JavaParamRef<jobject>& surface);
+  void SetOverlayVideoMode(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& obj,
+                           bool enabled);
+  void SetNeedsComposite(JNIEnv* env,
+                         const base::android::JavaParamRef<jobject>& obj);
 
   // TODO(yusufo): Remove this once the compositor code is
   // refactored to use a unified system.
-  jlong GetUIResourceProvider(JNIEnv* env, jobject obj);
+  jlong GetUIResourceProvider(JNIEnv* env,
+                              const base::android::JavaParamRef<jobject>& obj);
 
   // CompositorClient implementation
   void UpdateLayerTreeHost() override;
diff --git a/content/browser/android/date_time_chooser_android.cc b/content/browser/android/date_time_chooser_android.cc
index b555ef6..4f38402a 100644
--- a/content/browser/android/date_time_chooser_android.cc
+++ b/content/browser/android/date_time_chooser_android.cc
@@ -19,6 +19,7 @@
 using base::android::ConvertJavaStringToUTF16;
 using base::android::ConvertUTF8ToJavaString;
 using base::android::ConvertUTF16ToJavaString;
+using base::android::JavaRef;
 
 
 namespace {
@@ -50,12 +51,13 @@
 }
 
 void DateTimeChooserAndroid::ReplaceDateTime(JNIEnv* env,
-                                             jobject,
+                                             const JavaRef<jobject>&,
                                              jdouble value) {
   host_->Send(new ViewMsg_ReplaceDateTime(host_->GetRoutingID(), value));
 }
 
-void DateTimeChooserAndroid::CancelDialog(JNIEnv* env, jobject) {
+void DateTimeChooserAndroid::CancelDialog(JNIEnv* env,
+                                          const JavaRef<jobject>&) {
   host_->Send(new ViewMsg_CancelDateTimeDialog(host_->GetRoutingID()));
 }
 
@@ -100,7 +102,7 @@
       step,
       suggestions_array.obj()));
   if (j_date_time_chooser_.is_null())
-    ReplaceDateTime(env, j_date_time_chooser_.obj(), dialog_value);
+    ReplaceDateTime(env, j_date_time_chooser_, dialog_value);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/content/browser/android/date_time_chooser_android.h b/content/browser/android/date_time_chooser_android.h
index 6e6c895..ee527ab 100644
--- a/content/browser/android/date_time_chooser_android.h
+++ b/content/browser/android/date_time_chooser_android.h
@@ -38,10 +38,12 @@
                   const std::vector<DateTimeSuggestion>& suggestions);
 
   // Replaces the current value
-  void ReplaceDateTime(JNIEnv* env, jobject, jdouble value);
+  void ReplaceDateTime(JNIEnv* env,
+                       const base::android::JavaRef<jobject>&,
+                       jdouble value);
 
   // Closes the dialog without propagating any changes.
-  void CancelDialog(JNIEnv* env, jobject);
+  void CancelDialog(JNIEnv* env, const base::android::JavaRef<jobject>&);
 
  private:
   RenderViewHost* host_;
diff --git a/content/browser/android/interstitial_page_delegate_android.cc b/content/browser/android/interstitial_page_delegate_android.cc
index ce727ef..ee4bba84 100644
--- a/content/browser/android/interstitial_page_delegate_android.cc
+++ b/content/browser/android/interstitial_page_delegate_android.cc
@@ -31,13 +31,16 @@
     Java_InterstitialPageDelegateAndroid_onNativeDestroyed(env, obj.obj());
 }
 
-void InterstitialPageDelegateAndroid::Proceed(JNIEnv* env, jobject obj) {
+void InterstitialPageDelegateAndroid::Proceed(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (page_)
     page_->Proceed();
 }
 
-void InterstitialPageDelegateAndroid::DontProceed(JNIEnv* env,
-                                                  jobject obj) {
+void InterstitialPageDelegateAndroid::DontProceed(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (page_)
     page_->DontProceed();
 }
diff --git a/content/browser/android/interstitial_page_delegate_android.h b/content/browser/android/interstitial_page_delegate_android.h
index bd28d38..69816b6 100644
--- a/content/browser/android/interstitial_page_delegate_android.h
+++ b/content/browser/android/interstitial_page_delegate_android.h
@@ -31,8 +31,9 @@
   void set_interstitial_page(InterstitialPage* page) { page_ = page; }
 
   // Methods called from Java.
-  void Proceed(JNIEnv* env, jobject obj);
-  void DontProceed(JNIEnv* env, jobject obj);
+  void Proceed(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void DontProceed(JNIEnv* env,
+                   const base::android::JavaParamRef<jobject>& obj);
 
   // Implementation of InterstitialPageDelegate
   std::string GetHTMLContents() override;
diff --git a/content/browser/android/tracing_controller_android.cc b/content/browser/android/tracing_controller_android.cc
index b75914db..35545aad 100644
--- a/content/browser/android/tracing_controller_android.cc
+++ b/content/browser/android/tracing_controller_android.cc
@@ -25,14 +25,16 @@
 
 TracingControllerAndroid::~TracingControllerAndroid() {}
 
-void TracingControllerAndroid::Destroy(JNIEnv* env, jobject obj) {
+void TracingControllerAndroid::Destroy(JNIEnv* env,
+                                       const JavaParamRef<jobject>& obj) {
   delete this;
 }
 
-bool TracingControllerAndroid::StartTracing(JNIEnv* env,
-                                            jobject obj,
-                                            jstring jcategories,
-                                            jstring jtraceoptions) {
+bool TracingControllerAndroid::StartTracing(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jcategories,
+    const JavaParamRef<jstring>& jtraceoptions) {
   std::string categories =
       base::android::ConvertJavaStringToUTF8(env, jcategories);
   std::string options =
@@ -46,9 +48,10 @@
       TracingController::StartTracingDoneCallback());
 }
 
-void TracingControllerAndroid::StopTracing(JNIEnv* env,
-                                           jobject obj,
-                                           jstring jfilepath) {
+void TracingControllerAndroid::StopTracing(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jfilepath) {
   base::FilePath file_path(
       base::android::ConvertJavaStringToUTF8(env, jfilepath));
   if (!TracingController::GetInstance()->StopTracing(
@@ -77,8 +80,9 @@
     Java_TracingControllerAndroid_onTracingStopped(env, obj.obj());
 }
 
-bool TracingControllerAndroid::GetKnownCategoryGroupsAsync(JNIEnv* env,
-                                                           jobject obj) {
+bool TracingControllerAndroid::GetKnownCategoryGroupsAsync(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (!TracingController::GetInstance()->GetCategories(
           base::Bind(&TracingControllerAndroid::OnKnownCategoriesReceived,
                      weak_factory_.GetWeakPtr()))) {
diff --git a/content/browser/android/tracing_controller_android.h b/content/browser/android/tracing_controller_android.h
index 58e6b94d..09f1648 100644
--- a/content/browser/android/tracing_controller_android.h
+++ b/content/browser/android/tracing_controller_android.h
@@ -17,14 +17,18 @@
 class TracingControllerAndroid {
  public:
   TracingControllerAndroid(JNIEnv* env, jobject obj);
-  void Destroy(JNIEnv* env, jobject obj);
+  void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
 
   bool StartTracing(JNIEnv* env,
-                    jobject obj,
-                    jstring categories,
-                    jstring trace_options);
-  void StopTracing(JNIEnv* env, jobject obj, jstring jfilepath);
-  bool GetKnownCategoryGroupsAsync(JNIEnv* env, jobject obj);
+                    const base::android::JavaParamRef<jobject>& obj,
+                    const base::android::JavaParamRef<jstring>& categories,
+                    const base::android::JavaParamRef<jstring>& trace_options);
+  void StopTracing(JNIEnv* env,
+                   const base::android::JavaParamRef<jobject>& obj,
+                   const base::android::JavaParamRef<jstring>& jfilepath);
+  bool GetKnownCategoryGroupsAsync(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
   static void GenerateTracingFilePath(base::FilePath* file_path);
 
  private:
diff --git a/content/browser/android/web_contents_observer_proxy.cc b/content/browser/android/web_contents_observer_proxy.cc
index 923f5a6b..22ab07c 100644
--- a/content/browser/android/web_contents_observer_proxy.cc
+++ b/content/browser/android/web_contents_observer_proxy.cc
@@ -48,7 +48,8 @@
   return reinterpret_cast<intptr_t>(native_observer);
 }
 
-void WebContentsObserverProxy::Destroy(JNIEnv* env, jobject obj) {
+void WebContentsObserverProxy::Destroy(JNIEnv* env,
+                                       const JavaParamRef<jobject>& obj) {
   delete this;
 }
 
diff --git a/content/browser/android/web_contents_observer_proxy.h b/content/browser/android/web_contents_observer_proxy.h
index a366cfb..4c61bb2 100644
--- a/content/browser/android/web_contents_observer_proxy.h
+++ b/content/browser/android/web_contents_observer_proxy.h
@@ -27,7 +27,7 @@
   WebContentsObserverProxy(JNIEnv* env, jobject obj, WebContents* web_contents);
   ~WebContentsObserverProxy() override;
 
-  void Destroy(JNIEnv* env, jobject obj);
+  void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
 
  private:
   void RenderViewReady() override;
diff --git a/content/browser/device_sensors/sensor_manager_android.cc b/content/browser/device_sensors/sensor_manager_android.cc
index 7c9f7c0..e821fb44 100644
--- a/content/browser/device_sensors/sensor_manager_android.cc
+++ b/content/browser/device_sensors/sensor_manager_android.cc
@@ -76,8 +76,11 @@
       base::LeakySingletonTraits<SensorManagerAndroid>>::get();
 }
 
-void SensorManagerAndroid::GotOrientation(
-    JNIEnv*, jobject, double alpha, double beta, double gamma) {
+void SensorManagerAndroid::GotOrientation(JNIEnv*,
+                                          const JavaParamRef<jobject>&,
+                                          double alpha,
+                                          double beta,
+                                          double gamma) {
   base::AutoLock autolock(orientation_buffer_lock_);
 
   if (!device_orientation_buffer_)
@@ -95,8 +98,11 @@
   }
 }
 
-void SensorManagerAndroid::GotOrientationAbsolute(
-    JNIEnv*, jobject, double alpha, double beta, double gamma) {
+void SensorManagerAndroid::GotOrientationAbsolute(JNIEnv*,
+                                                  const JavaParamRef<jobject>&,
+                                                  double alpha,
+                                                  double beta,
+                                                  double gamma) {
   base::AutoLock autolock(orientation_absolute_buffer_lock_);
 
   if (!device_orientation_absolute_buffer_)
@@ -111,9 +117,11 @@
   }
 }
 
-
-void SensorManagerAndroid::GotAcceleration(
-    JNIEnv*, jobject, double x, double y, double z) {
+void SensorManagerAndroid::GotAcceleration(JNIEnv*,
+                                           const JavaParamRef<jobject>&,
+                                           double x,
+                                           double y,
+                                           double z) {
   base::AutoLock autolock(motion_buffer_lock_);
 
   if (!device_motion_buffer_)
@@ -135,7 +143,11 @@
 }
 
 void SensorManagerAndroid::GotAccelerationIncludingGravity(
-    JNIEnv*, jobject, double x, double y, double z) {
+    JNIEnv*,
+    const JavaParamRef<jobject>&,
+    double x,
+    double y,
+    double z) {
   base::AutoLock autolock(motion_buffer_lock_);
 
   if (!device_motion_buffer_)
@@ -156,8 +168,11 @@
   }
 }
 
-void SensorManagerAndroid::GotRotationRate(
-    JNIEnv*, jobject, double alpha, double beta, double gamma) {
+void SensorManagerAndroid::GotRotationRate(JNIEnv*,
+                                           const JavaParamRef<jobject>&,
+                                           double alpha,
+                                           double beta,
+                                           double gamma) {
   base::AutoLock autolock(motion_buffer_lock_);
 
   if (!device_motion_buffer_)
@@ -178,7 +193,9 @@
   }
 }
 
-void SensorManagerAndroid::GotLight(JNIEnv*, jobject, double value) {
+void SensorManagerAndroid::GotLight(JNIEnv*,
+                                    const JavaParamRef<jobject>&,
+                                    double value) {
   base::AutoLock autolock(light_buffer_lock_);
 
   if (!device_light_buffer_)
diff --git a/content/browser/device_sensors/sensor_manager_android.h b/content/browser/device_sensors/sensor_manager_android.h
index 44595563..3626aba 100644
--- a/content/browser/device_sensors/sensor_manager_android.h
+++ b/content/browser/device_sensors/sensor_manager_android.h
@@ -35,17 +35,35 @@
   static SensorManagerAndroid* GetInstance();
 
   // Called from Java via JNI.
-  void GotLight(JNIEnv*, jobject, double value);
-  void GotOrientation(JNIEnv*, jobject,
-                      double alpha, double beta, double gamma);
-  void GotOrientationAbsolute(JNIEnv*, jobject,
-                      double alpha, double beta, double gamma);
-  void GotAcceleration(JNIEnv*, jobject,
-                       double x, double y, double z);
-  void GotAccelerationIncludingGravity(JNIEnv*, jobject,
-                                       double x, double y, double z);
-  void GotRotationRate(JNIEnv*, jobject,
-                       double alpha, double beta, double gamma);
+  void GotLight(JNIEnv*,
+                const base::android::JavaParamRef<jobject>&,
+                double value);
+  void GotOrientation(JNIEnv*,
+                      const base::android::JavaParamRef<jobject>&,
+                      double alpha,
+                      double beta,
+                      double gamma);
+  void GotOrientationAbsolute(JNIEnv*,
+                              const base::android::JavaParamRef<jobject>&,
+                              double alpha,
+                              double beta,
+                              double gamma);
+  void GotAcceleration(JNIEnv*,
+                       const base::android::JavaParamRef<jobject>&,
+                       double x,
+                       double y,
+                       double z);
+  void GotAccelerationIncludingGravity(
+      JNIEnv*,
+      const base::android::JavaParamRef<jobject>&,
+      double x,
+      double y,
+      double z);
+  void GotRotationRate(JNIEnv*,
+                       const base::android::JavaParamRef<jobject>&,
+                       double alpha,
+                       double beta,
+                       double gamma);
 
   // Shared memory related methods.
   void StartFetchingDeviceLightData(DeviceLightHardwareBuffer* buffer);
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index 3b6a207..2ac257fb 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -5,6 +5,7 @@
 #include "content/browser/devtools/render_frame_devtools_agent_host.h"
 
 #include "base/basictypes.h"
+#include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/child_process_security_policy_impl.h"
@@ -20,6 +21,7 @@
 #include "content/browser/devtools/protocol/security_handler.h"
 #include "content/browser/devtools/protocol/service_worker_handler.h"
 #include "content/browser/devtools/protocol/tracing_handler.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
@@ -30,6 +32,7 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/render_widget_host_iterator.h"
 #include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/content_switches.h"
 
 #if defined(OS_ANDROID)
 #include "content/browser/power_save_blocker_impl.h"
@@ -43,6 +46,8 @@
 namespace {
 base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
 
+bool browser_side_navigation = false;
+
 static RenderFrameDevToolsAgentHost* FindAgentHost(RenderFrameHost* host) {
   if (g_instances == NULL)
     return NULL;
@@ -231,6 +236,7 @@
 
 // RenderFrameDevToolsAgentHost ------------------------------------------------
 
+// static
 scoped_refptr<DevToolsAgentHost>
 DevToolsAgentHost::GetOrCreateFor(RenderFrameHost* frame_host) {
   while (frame_host && !ShouldCreateDevToolsFor(frame_host))
@@ -244,6 +250,7 @@
   return result;
 }
 
+// static
 scoped_refptr<DevToolsAgentHost>
 DevToolsAgentHost::GetOrCreateFor(WebContents* web_contents) {
   RenderFrameDevToolsAgentHost* result = FindAgentHost(web_contents);
@@ -303,6 +310,9 @@
 void RenderFrameDevToolsAgentHost::OnCancelPendingNavigation(
     RenderFrameHost* pending,
     RenderFrameHost* current) {
+  if (browser_side_navigation)
+    return;
+
   RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(pending);
   if (!agent_host)
     return;
@@ -337,7 +347,12 @@
       emulation_handler_(nullptr),
       frame_trace_recorder_(nullptr),
       protocol_handler_(new DevToolsProtocolHandler(this)),
-      current_frame_crashed_(false) {
+      current_frame_crashed_(false),
+      pending_handle_(nullptr),
+      in_navigation_(0),
+      frame_tree_node_(host->frame_tree_node()) {
+  browser_side_navigation = base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableBrowserSideNavigation);
   DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher();
   dispatcher->SetDOMHandler(dom_handler_.get());
   dispatcher->SetInputHandler(input_handler_.get());
@@ -434,6 +449,13 @@
   if (protocol_handler_->HandleOptionalMessage(session_id(), message, &call_id))
     return true;
 
+  if (in_navigation_ > 0) {
+    DCHECK(browser_side_navigation);
+    in_navigation_protocol_message_buffer_[call_id] =
+        std::make_pair(session_id(), message);
+    return true;
+  }
+
   if (current_)
     current_->DispatchProtocolMessage(session_id(), call_id, message);
   if (pending_)
@@ -479,6 +501,7 @@
   service_worker_handler_->Detached();
   tracing_handler_->Detached();
   frame_trace_recorder_.reset();
+  in_navigation_protocol_message_buffer_.clear();
 
   // TODO(kaznacheev): Move this call back to DevToolsManager when
   // extensions::ProcessManager no longer relies on this notification.
@@ -493,9 +516,65 @@
     g_instances.Get().erase(it);
 }
 
+void RenderFrameDevToolsAgentHost::DidStartNavigation(
+    NavigationHandle* navigation_handle) {
+  if (!browser_side_navigation)
+    return;
+  if (!MatchesMyTreeNode(navigation_handle))
+    return;
+  DCHECK(current_);
+  DCHECK(in_navigation_ >= 0);
+  ++in_navigation_;
+}
+
+void RenderFrameDevToolsAgentHost::ReadyToCommitNavigation(
+    NavigationHandle* navigation_handle) {
+  // ReadyToCommitNavigation should only be called in PlzNavigate.
+  DCHECK(browser_side_navigation);
+
+  if (MatchesMyTreeNode(navigation_handle) && in_navigation_ != 0) {
+    RenderFrameHostImpl* render_frame_host_impl =
+        static_cast<RenderFrameHostImpl*>(
+            navigation_handle->GetRenderFrameHost());
+    if (current_->host() != render_frame_host_impl || current_frame_crashed_) {
+      SetPending(render_frame_host_impl);
+      pending_handle_ = navigation_handle;
+    }
+  }
+}
+
+void RenderFrameDevToolsAgentHost::DidFinishNavigation(
+    NavigationHandle* navigation_handle) {
+  if (!browser_side_navigation)
+    return;
+
+  if (MatchesMyTreeNode(navigation_handle) && in_navigation_ != 0) {
+    --in_navigation_;
+    DCHECK(in_navigation_ >= 0);
+    if (pending_handle_ == navigation_handle) {
+      // This navigation handle did set the pending FrameHostHolder.
+      DCHECK(pending_);
+      if (navigation_handle->HasCommitted()) {
+        DCHECK(pending_->host() == navigation_handle->GetRenderFrameHost());
+        CommitPending();
+      } else {
+        DiscardPending();
+      }
+      pending_handle_ = nullptr;
+    }
+    DispatchBufferedProtocolMessagesIfNecessary();
+  }
+
+  if (navigation_handle->HasCommitted())
+    service_worker_handler_->UpdateHosts();
+}
+
 void RenderFrameDevToolsAgentHost::AboutToNavigateRenderFrame(
     RenderFrameHost* old_host,
     RenderFrameHost* new_host) {
+  if (browser_side_navigation)
+    return;
+
   DCHECK(!pending_ || pending_->host() != old_host);
   if (!current_ || current_->host() != old_host)
     return;
@@ -508,6 +587,9 @@
 void RenderFrameDevToolsAgentHost::RenderFrameHostChanged(
     RenderFrameHost* old_host,
     RenderFrameHost* new_host) {
+  if (browser_side_navigation)
+    return;
+
   DCHECK(!pending_ || pending_->host() != old_host);
   if (!current_ || current_->host() != old_host)
     return;
@@ -522,7 +604,8 @@
 
 void RenderFrameDevToolsAgentHost::FrameDeleted(RenderFrameHost* rfh) {
   if (pending_ && pending_->host() == rfh) {
-    DiscardPending();
+    if (!browser_side_navigation)
+      DiscardPending();
     return;
   }
 
@@ -544,6 +627,9 @@
   HostClosed();
   pending_.reset();
   current_.reset();
+  frame_tree_node_ = nullptr;
+  pending_handle_ = nullptr;
+  WebContentsObserver::Observe(nullptr);
   Release();
 }
 
@@ -611,6 +697,7 @@
   // Pending set in AboutToNavigateRenderFrame turned out to be interstitial.
   // Connect back to the real one.
   DiscardPending();
+  pending_handle_ = nullptr;
 }
 
 void RenderFrameDevToolsAgentHost::DidDetachInterstitialPage() {
@@ -622,6 +709,8 @@
     RenderFrameHost* render_frame_host,
     const GURL& url,
     ui::PageTransition transition_type) {
+  if (browser_side_navigation)
+    return;
   if (pending_ && pending_->host() == render_frame_host)
     CommitPending();
   service_worker_handler_->UpdateHosts();
@@ -633,10 +722,24 @@
     int error_code,
     const base::string16& error_description,
     bool was_ignored_by_handler) {
+  if (browser_side_navigation)
+    return;
   if (pending_ && pending_->host() == render_frame_host)
     DiscardPending();
 }
 
+void RenderFrameDevToolsAgentHost::
+    DispatchBufferedProtocolMessagesIfNecessary() {
+  if (in_navigation_ == 0 && in_navigation_protocol_message_buffer_.size()) {
+    DCHECK(current_);
+    for (const auto& pair : in_navigation_protocol_message_buffer_) {
+      current_->DispatchProtocolMessage(pair.second.first, pair.first,
+                                        pair.second.second);
+    }
+    in_navigation_protocol_message_buffer_.clear();
+  }
+}
+
 void RenderFrameDevToolsAgentHost::UpdateProtocolHandlers(
     RenderFrameHostImpl* host) {
   dom_handler_->SetRenderFrameHost(host);
@@ -659,6 +762,10 @@
   UpdateProtocolHandlers(nullptr);
   disconnected_ = current_.Pass();
   disconnected_->Detach();
+  frame_tree_node_ = nullptr;
+  in_navigation_protocol_message_buffer_.clear();
+  in_navigation_ = 0;
+  pending_handle_ = nullptr;
   WebContentsObserver::Observe(nullptr);
 }
 
@@ -668,6 +775,7 @@
   RenderFrameHostImpl* host =
       static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
   DCHECK(host);
+  frame_tree_node_ = host->frame_tree_node();
   current_ = disconnected_.Pass();
   SetPending(host);
   CommitPending();
@@ -754,4 +862,11 @@
   return current_ && current_->host()->GetParent();
 }
 
+bool RenderFrameDevToolsAgentHost::MatchesMyTreeNode(
+    NavigationHandle* navigation_handle) {
+  return frame_tree_node_ ==
+         static_cast<NavigationHandleImpl*>(navigation_handle)
+             ->frame_tree_node();
+}
+
 }  // namespace content
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h
index dec2ba7c..7d53f85 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -23,6 +23,8 @@
 class BrowserContext;
 class DevToolsFrameTraceRecorder;
 class DevToolsProtocolHandler;
+class FrameTreeNode;
+class NavigationHandle;
 class RenderFrameHostImpl;
 
 #if defined(OS_ANDROID)
@@ -87,6 +89,9 @@
   void InspectElement(int x, int y) override;
 
   // WebContentsObserver overrides.
+  void DidStartNavigation(NavigationHandle* navigation_handle) override;
+  void ReadyToCommitNavigation(NavigationHandle* navigation_handle) override;
+  void DidFinishNavigation(NavigationHandle* navigation_handle) override;
   void RenderFrameHostChanged(RenderFrameHost* old_host,
                               RenderFrameHost* new_host) override;
   void FrameDeleted(RenderFrameHost* rfh) override;
@@ -111,6 +116,8 @@
   void AboutToNavigateRenderFrame(RenderFrameHost* old_host,
                                   RenderFrameHost* new_host);
 
+  void DispatchBufferedProtocolMessagesIfNecessary();
+
   void SetPending(RenderFrameHostImpl* host);
   void CommitPending();
   void DiscardPending();
@@ -125,10 +132,13 @@
   void OnSwapCompositorFrame(const IPC::Message& message);
   void DestroyOnRenderFrameGone();
 
+  bool MatchesMyTreeNode(NavigationHandle* navigation_handle);
+
   class FrameHostHolder;
 
   scoped_ptr<FrameHostHolder> current_;
   scoped_ptr<FrameHostHolder> pending_;
+
   // Stores per-host state between DisconnectWebContents and ConnectWebContents.
   scoped_ptr<FrameHostHolder> disconnected_;
 
@@ -150,6 +160,22 @@
   scoped_ptr<DevToolsProtocolHandler> protocol_handler_;
   bool current_frame_crashed_;
 
+  // PlzNavigate
+
+  // Handle that caused the setting of pending_.
+  NavigationHandle* pending_handle_;
+
+  // Navigation counter and queue for buffering protocol messages during a
+  // navigation.
+  int in_navigation_;
+
+  // <call_id> -> <session_id, message>
+  std::map<int, std::pair<int, std::string>>
+      in_navigation_protocol_message_buffer_;
+
+  // The FrameTreeNode associated with this agent.
+  FrameTreeNode* frame_tree_node_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderFrameDevToolsAgentHost);
 };
 
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 7e0a7669..6a98bc2 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -135,30 +135,6 @@
       params->callback());
 }
 
-class MapValueIteratorAdapter {
- public:
-  explicit MapValueIteratorAdapter(
-      base::hash_map<int64, DownloadItem*>::const_iterator iter)
-    : iter_(iter) {
-  }
-  ~MapValueIteratorAdapter() {}
-
-  DownloadItem* operator*() { return iter_->second; }
-
-  MapValueIteratorAdapter& operator++() {
-    ++iter_;
-    return *this;
-  }
-
-  bool operator!=(const MapValueIteratorAdapter& that) const {
-    return iter_ != that.iter_;
-  }
-
- private:
-  base::hash_map<int64, DownloadItem*>::const_iterator iter_;
-  // Allow copy and assign.
-};
-
 class DownloadItemFactoryImpl : public DownloadItemFactory {
  public:
   DownloadItemFactoryImpl() {}
diff --git a/content/browser/frame_host/navigation_controller_android.cc b/content/browser/frame_host/navigation_controller_android.cc
index 43c7a36..a7590fd 100644
--- a/content/browser/frame_host/navigation_controller_android.cc
+++ b/content/browser/frame_host/navigation_controller_android.cc
@@ -90,97 +90,111 @@
   return base::android::ScopedJavaLocalRef<jobject>(obj_);
 }
 
-jboolean NavigationControllerAndroid::CanGoBack(JNIEnv* env, jobject obj) {
+jboolean NavigationControllerAndroid::CanGoBack(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return navigation_controller_->CanGoBack();
 }
 
-jboolean NavigationControllerAndroid::CanGoForward(JNIEnv* env,
-                                                   jobject obj) {
+jboolean NavigationControllerAndroid::CanGoForward(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return navigation_controller_->CanGoForward();
 }
 
-jboolean NavigationControllerAndroid::CanGoToOffset(JNIEnv* env,
-                                                    jobject obj,
-                                                    jint offset) {
+jboolean NavigationControllerAndroid::CanGoToOffset(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint offset) {
   return navigation_controller_->CanGoToOffset(offset);
 }
 
-void NavigationControllerAndroid::GoBack(JNIEnv* env, jobject obj) {
+void NavigationControllerAndroid::GoBack(JNIEnv* env,
+                                         const JavaParamRef<jobject>& obj) {
   navigation_controller_->GoBack();
 }
 
-void NavigationControllerAndroid::GoForward(JNIEnv* env, jobject obj) {
+void NavigationControllerAndroid::GoForward(JNIEnv* env,
+                                            const JavaParamRef<jobject>& obj) {
   navigation_controller_->GoForward();
 }
 
 void NavigationControllerAndroid::GoToOffset(JNIEnv* env,
-                                             jobject obj,
+                                             const JavaParamRef<jobject>& obj,
                                              jint offset) {
   navigation_controller_->GoToOffset(offset);
 }
 
-jboolean NavigationControllerAndroid::IsInitialNavigation(JNIEnv* env,
-                                                          jobject obj) {
+jboolean NavigationControllerAndroid::IsInitialNavigation(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return navigation_controller_->IsInitialNavigation();
 }
 
-void NavigationControllerAndroid::LoadIfNecessary(JNIEnv* env, jobject obj) {
+void NavigationControllerAndroid::LoadIfNecessary(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   navigation_controller_->LoadIfNecessary();
 }
 
-void NavigationControllerAndroid::ContinuePendingReload(JNIEnv* env,
-                                                        jobject obj) {
+void NavigationControllerAndroid::ContinuePendingReload(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   navigation_controller_->ContinuePendingReload();
 }
 
 void NavigationControllerAndroid::Reload(JNIEnv* env,
-                                         jobject obj,
+                                         const JavaParamRef<jobject>& obj,
                                          jboolean check_for_repost) {
   navigation_controller_->Reload(check_for_repost);
 }
 
 void NavigationControllerAndroid::ReloadIgnoringCache(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jboolean check_for_repost) {
   navigation_controller_->ReloadIgnoringCache(check_for_repost);
 }
 
 void NavigationControllerAndroid::ReloadDisableLoFi(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jboolean check_for_repost) {
   navigation_controller_->ReloadDisableLoFi(check_for_repost);
 }
 
-void NavigationControllerAndroid::RequestRestoreLoad(JNIEnv* env, jobject obj) {
+void NavigationControllerAndroid::RequestRestoreLoad(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   navigation_controller_->SetNeedsReload();
 }
 
-void NavigationControllerAndroid::CancelPendingReload(JNIEnv* env,
-                                                      jobject obj) {
+void NavigationControllerAndroid::CancelPendingReload(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   navigation_controller_->CancelPendingReload();
 }
 
-void NavigationControllerAndroid::GoToNavigationIndex(JNIEnv* env,
-                                                      jobject obj,
-                                                      jint index) {
+void NavigationControllerAndroid::GoToNavigationIndex(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint index) {
   navigation_controller_->GoToIndex(index);
 }
 
 void NavigationControllerAndroid::LoadUrl(
     JNIEnv* env,
-    jobject obj,
-    jstring url,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& url,
     jint load_url_type,
     jint transition_type,
-    jstring j_referrer_url,
+    const JavaParamRef<jstring>& j_referrer_url,
     jint referrer_policy,
     jint ua_override_option,
-    jstring extra_headers,
-    jbyteArray post_data,
-    jstring base_url_for_data_url,
-    jstring virtual_url_for_data_url,
+    const JavaParamRef<jstring>& extra_headers,
+    const JavaParamRef<jbyteArray>& post_data,
+    const JavaParamRef<jstring>& base_url_for_data_url,
+    const JavaParamRef<jstring>& virtual_url_for_data_url,
     jboolean can_load_local_resources,
     jboolean is_renderer_initiated,
     jboolean should_replace_current_entry) {
@@ -227,15 +241,18 @@
   navigation_controller_->LoadURLWithParams(params);
 }
 
-void NavigationControllerAndroid::ClearHistory(JNIEnv* env, jobject obj) {
+void NavigationControllerAndroid::ClearHistory(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   // TODO(creis): Do callers of this need to know if it fails?
   if (navigation_controller_->CanPruneAllButLastCommitted())
     navigation_controller_->PruneAllButLastCommitted();
 }
 
-jint NavigationControllerAndroid::GetNavigationHistory(JNIEnv* env,
-                                                       jobject obj,
-                                                       jobject history) {
+jint NavigationControllerAndroid::GetNavigationHistory(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& history) {
   // Iterate through navigation entries to populate the list
   int count = navigation_controller_->GetEntryCount();
   for (int i = 0; i < count; ++i) {
@@ -248,8 +265,8 @@
 
 void NavigationControllerAndroid::GetDirectedNavigationHistory(
     JNIEnv* env,
-    jobject obj,
-    jobject history,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& history,
     jboolean is_forward,
     jint max_entries) {
   // Iterate through navigation entries to populate the list
@@ -271,30 +288,32 @@
 ScopedJavaLocalRef<jstring>
 NavigationControllerAndroid::GetOriginalUrlForVisibleNavigationEntry(
     JNIEnv* env,
-    jobject obj) {
+    const JavaParamRef<jobject>& obj) {
   NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
   if (entry == NULL)
     return ScopedJavaLocalRef<jstring>(env, NULL);
   return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
 }
 
-void NavigationControllerAndroid::ClearSslPreferences(JNIEnv* env,
-                                                      jobject obj) {
+void NavigationControllerAndroid::ClearSslPreferences(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   content::SSLHostStateDelegate* delegate =
       navigation_controller_->GetBrowserContext()->GetSSLHostStateDelegate();
   if (delegate)
     delegate->Clear();
 }
 
-bool NavigationControllerAndroid::GetUseDesktopUserAgent(JNIEnv* env,
-                                                         jobject obj) {
+bool NavigationControllerAndroid::GetUseDesktopUserAgent(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
   return entry && entry->GetIsOverridingUserAgent();
 }
 
 void NavigationControllerAndroid::SetUseDesktopUserAgent(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jboolean enabled,
     jboolean reload_on_state_change) {
   if (GetUseDesktopUserAgent(env, obj) == enabled)
@@ -318,7 +337,7 @@
 
 base::android::ScopedJavaLocalRef<jobject>
 NavigationControllerAndroid::GetEntryAtIndex(JNIEnv* env,
-                                             jobject obj,
+                                             const JavaParamRef<jobject>& obj,
                                              int index) {
   if (index < 0 || index >= navigation_controller_->GetEntryCount())
     return base::android::ScopedJavaLocalRef<jobject>();
@@ -329,7 +348,8 @@
 }
 
 base::android::ScopedJavaLocalRef<jobject>
-NavigationControllerAndroid::GetPendingEntry(JNIEnv* env, jobject obj) {
+NavigationControllerAndroid::GetPendingEntry(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj) {
   content::NavigationEntry* entry = navigation_controller_->GetPendingEntry();
 
   if (!entry)
@@ -339,31 +359,35 @@
       env, entry, navigation_controller_->GetPendingEntryIndex());
 }
 
-jint NavigationControllerAndroid::GetLastCommittedEntryIndex(JNIEnv* env,
-                                                             jobject obj) {
+jint NavigationControllerAndroid::GetLastCommittedEntryIndex(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return navigation_controller_->GetLastCommittedEntryIndex();
 }
 
-jboolean NavigationControllerAndroid::RemoveEntryAtIndex(JNIEnv* env,
-                                                         jobject obj,
-                                                         jint index) {
+jboolean NavigationControllerAndroid::RemoveEntryAtIndex(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint index) {
   return navigation_controller_->RemoveEntryAtIndex(index);
 }
 
-jboolean NavigationControllerAndroid::CanCopyStateOver(JNIEnv* env,
-                                                       jobject obj) {
+jboolean NavigationControllerAndroid::CanCopyStateOver(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return navigation_controller_->GetEntryCount() == 0 &&
       !navigation_controller_->GetPendingEntry();
 }
 
-jboolean NavigationControllerAndroid::CanPruneAllButLastCommitted(JNIEnv* env,
-                                                                  jobject obj) {
+jboolean NavigationControllerAndroid::CanPruneAllButLastCommitted(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return navigation_controller_->CanPruneAllButLastCommitted();
 }
 
 void NavigationControllerAndroid::CopyStateFrom(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jlong source_navigation_controller_android) {
   navigation_controller_->CopyStateFrom(
       *(reinterpret_cast<NavigationControllerAndroid*>(
@@ -372,7 +396,7 @@
 
 void NavigationControllerAndroid::CopyStateFromAndPrune(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jlong source_navigation_controller_android,
     jboolean replace_entry) {
   navigation_controller_->CopyStateFromAndPrune(
diff --git a/content/browser/frame_host/navigation_controller_android.h b/content/browser/frame_host/navigation_controller_android.h
index eef4684..ab820dcd7 100644
--- a/content/browser/frame_host/navigation_controller_android.h
+++ b/content/browser/frame_host/navigation_controller_android.h
@@ -33,67 +33,107 @@
 
   base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
 
-  jboolean CanGoBack(JNIEnv* env, jobject obj);
-  jboolean CanGoForward(JNIEnv* env, jobject obj);
-  jboolean CanGoToOffset(JNIEnv* env, jobject obj, jint offset);
-  void GoBack(JNIEnv* env, jobject obj);
-  void GoForward(JNIEnv* env, jobject obj);
-  void GoToOffset(JNIEnv* env, jobject obj, jint offset);
-  jboolean IsInitialNavigation(JNIEnv* env, jobject obj);
-  void LoadIfNecessary(JNIEnv* env, jobject obj);
-  void ContinuePendingReload(JNIEnv* env, jobject obj);
-  void Reload(JNIEnv* env, jobject obj, jboolean check_for_repost);
-  void ReloadIgnoringCache(JNIEnv* env, jobject obj, jboolean check_for_repost);
-  void ReloadDisableLoFi(JNIEnv* env, jobject obj, jboolean check_for_repost);
-  void RequestRestoreLoad(JNIEnv* env, jobject obj);
-  void CancelPendingReload(JNIEnv* env, jobject obj);
-  void GoToNavigationIndex(JNIEnv* env, jobject obj, jint index);
-  void LoadUrl(JNIEnv* env,
-               jobject obj,
-               jstring url,
-               jint load_url_type,
-               jint transition_type,
-               jstring j_referrer_url,
-               jint referrer_policy,
-               jint ua_override_option,
-               jstring extra_headers,
-               jbyteArray post_data,
-               jstring base_url_for_data_url,
-               jstring virtual_url_for_data_url,
-               jboolean can_load_local_resources,
-               jboolean is_renderer_initiated,
-               jboolean should_replace_current_entry);
-  void ClearSslPreferences(JNIEnv* env, jobject /* obj */);
-  bool GetUseDesktopUserAgent(JNIEnv* env, jobject /* obj */);
-  void SetUseDesktopUserAgent(JNIEnv* env,
-                              jobject /* obj */,
-                              jboolean state,
-                              jboolean reload_on_state_change);
-  base::android::ScopedJavaLocalRef<jobject> GetEntryAtIndex(JNIEnv* env,
-                                                             jobject obj,
-                                                             int index);
-  base::android::ScopedJavaLocalRef<jobject> GetPendingEntry(JNIEnv* env,
-                                                             jobject /* obj */);
-  int GetNavigationHistory(JNIEnv* env, jobject obj, jobject history);
-  void GetDirectedNavigationHistory(JNIEnv* env,
-                                    jobject obj,
-                                    jobject history,
-                                    jboolean is_forward,
-                                    jint max_entries);
+  jboolean CanGoBack(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& obj);
+  jboolean CanGoForward(JNIEnv* env,
+                        const base::android::JavaParamRef<jobject>& obj);
+  jboolean CanGoToOffset(JNIEnv* env,
+                         const base::android::JavaParamRef<jobject>& obj,
+                         jint offset);
+  void GoBack(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void GoForward(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void GoToOffset(JNIEnv* env,
+                  const base::android::JavaParamRef<jobject>& obj,
+                  jint offset);
+  jboolean IsInitialNavigation(JNIEnv* env,
+                               const base::android::JavaParamRef<jobject>& obj);
+  void LoadIfNecessary(JNIEnv* env,
+                       const base::android::JavaParamRef<jobject>& obj);
+  void ContinuePendingReload(JNIEnv* env,
+                             const base::android::JavaParamRef<jobject>& obj);
+  void Reload(JNIEnv* env,
+              const base::android::JavaParamRef<jobject>& obj,
+              jboolean check_for_repost);
+  void ReloadIgnoringCache(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& obj,
+                           jboolean check_for_repost);
+  void ReloadDisableLoFi(JNIEnv* env,
+                         const base::android::JavaParamRef<jobject>& obj,
+                         jboolean check_for_repost);
+  void RequestRestoreLoad(JNIEnv* env,
+                          const base::android::JavaParamRef<jobject>& obj);
+  void CancelPendingReload(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& obj);
+  void GoToNavigationIndex(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& obj,
+                           jint index);
+  void LoadUrl(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& url,
+      jint load_url_type,
+      jint transition_type,
+      const base::android::JavaParamRef<jstring>& j_referrer_url,
+      jint referrer_policy,
+      jint ua_override_option,
+      const base::android::JavaParamRef<jstring>& extra_headers,
+      const base::android::JavaParamRef<jbyteArray>& post_data,
+      const base::android::JavaParamRef<jstring>& base_url_for_data_url,
+      const base::android::JavaParamRef<jstring>& virtual_url_for_data_url,
+      jboolean can_load_local_resources,
+      jboolean is_renderer_initiated,
+      jboolean should_replace_current_entry);
+  void ClearSslPreferences(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& /* obj */);
+  bool GetUseDesktopUserAgent(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& /* obj */);
+  void SetUseDesktopUserAgent(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& /* obj */,
+      jboolean state,
+      jboolean reload_on_state_change);
+  base::android::ScopedJavaLocalRef<jobject> GetEntryAtIndex(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      int index);
+  base::android::ScopedJavaLocalRef<jobject> GetPendingEntry(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& /* obj */);
+  int GetNavigationHistory(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& obj,
+                           const base::android::JavaParamRef<jobject>& history);
+  void GetDirectedNavigationHistory(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jobject>& history,
+      jboolean is_forward,
+      jint max_entries);
   base::android::ScopedJavaLocalRef<jstring>
-      GetOriginalUrlForVisibleNavigationEntry(JNIEnv* env, jobject obj);
-  void ClearHistory(JNIEnv* env, jobject obj);
-  int GetLastCommittedEntryIndex(JNIEnv* env, jobject obj);
-  jboolean RemoveEntryAtIndex(JNIEnv* env, jobject obj, jint index);
-  jboolean CanCopyStateOver(JNIEnv* env, jobject obj);
-  jboolean CanPruneAllButLastCommitted(JNIEnv* env, jobject obj);
+  GetOriginalUrlForVisibleNavigationEntry(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  void ClearHistory(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& obj);
+  int GetLastCommittedEntryIndex(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean RemoveEntryAtIndex(JNIEnv* env,
+                              const base::android::JavaParamRef<jobject>& obj,
+                              jint index);
+  jboolean CanCopyStateOver(JNIEnv* env,
+                            const base::android::JavaParamRef<jobject>& obj);
+  jboolean CanPruneAllButLastCommitted(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
   void CopyStateFrom(JNIEnv* env,
-                     jobject obj,
+                     const base::android::JavaParamRef<jobject>& obj,
                      jlong source_native_navigation_controller_android);
   void CopyStateFromAndPrune(JNIEnv* env,
-                     jobject obj,
-                     jlong source_native_navigation_controller_android,
-                     jboolean replace_entry);
+                             const base::android::JavaParamRef<jobject>& obj,
+                             jlong source_native_navigation_controller_android,
+                             jboolean replace_entry);
 
  private:
   NavigationController* navigation_controller_;
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h
index 2e1dbc2..7fcc0188 100644
--- a/content/browser/frame_host/navigation_handle_impl.h
+++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
+#include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/navigation_throttle.h"
@@ -157,6 +158,9 @@
       scoped_refptr<net::HttpResponseHeaders> response_headers,
       const ThrottleChecksFinishedCallback& callback);
 
+  // Returns the FrameTreeNode this navigation is happening in.
+  FrameTreeNode* frame_tree_node() { return frame_tree_node_; }
+
   // Called when the navigation was redirected. This will update the |url_| and
   // inform the delegate.
   void DidRedirectNavigation(const GURL& new_url);
diff --git a/content/browser/media/android/media_session.cc b/content/browser/media/android/media_session.cc
index 48ceb546..60360f4 100644
--- a/content/browser/media/android/media_session.cc
+++ b/content/browser/media/android/media_session.cc
@@ -112,7 +112,9 @@
   AbandonSystemAudioFocusIfNeeded();
 }
 
-void MediaSession::OnSuspend(JNIEnv* env, jobject obj, jboolean temporary) {
+void MediaSession::OnSuspend(JNIEnv* env,
+                             const JavaParamRef<jobject>& obj,
+                             jboolean temporary) {
   // TODO(mlamouri): this check makes it so that if a MediaSession is paused and
   // then loses audio focus, it will still stay in the Suspended state.
   // See https://crbug.com/539998
@@ -129,7 +131,7 @@
   UpdateWebContents();
 }
 
-void MediaSession::OnResume(JNIEnv* env, jobject obj) {
+void MediaSession::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   if (audio_focus_state_ != State::SUSPENDED)
     return;
 
diff --git a/content/browser/media/android/media_session.h b/content/browser/media/android/media_session.h
index 992ad4f..9ba76c3 100644
--- a/content/browser/media/android/media_session.h
+++ b/content/browser/media/android/media_session.h
@@ -62,11 +62,13 @@
 
   // Called when the Android system requests the MediaSession to be suspended.
   // Called by Java through JNI.
-  void OnSuspend(JNIEnv* env, jobject obj, jboolean temporary);
+  void OnSuspend(JNIEnv* env,
+                 const base::android::JavaParamRef<jobject>& obj,
+                 jboolean temporary);
 
   // Called when the Android system requests the MediaSession to be resumed.
   // Called by Java through JNI.
-  void OnResume(JNIEnv* env, jobject obj);
+  void OnResume(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
 
   // Called when the user requests resuming the session. No-op if the session is
   // not controllable.
diff --git a/content/browser/mojo/service_registry_android.cc b/content/browser/mojo/service_registry_android.cc
index d2187a3..7978cff7 100644
--- a/content/browser/mojo/service_registry_android.cc
+++ b/content/browser/mojo/service_registry_android.cc
@@ -57,11 +57,12 @@
 }
 
 // Methods called from Java.
-void ServiceRegistryAndroid::AddService(JNIEnv* env,
-                                        jobject j_service_registry,
-                                        jobject j_manager,
-                                        jobject j_factory,
-                                        jstring j_name) {
+void ServiceRegistryAndroid::AddService(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& j_service_registry,
+    const JavaParamRef<jobject>& j_manager,
+    const JavaParamRef<jobject>& j_factory,
+    const JavaParamRef<jstring>& j_name) {
   std::string name(ConvertJavaStringToUTF8(env, j_name));
 
   ScopedJavaGlobalRef<jobject> j_scoped_service_registry;
@@ -79,17 +80,19 @@
                                     j_scoped_manager, j_scoped_factory));
 }
 
-void ServiceRegistryAndroid::RemoveService(JNIEnv* env,
-                                           jobject j_service_registry,
-                                           jstring j_name) {
+void ServiceRegistryAndroid::RemoveService(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& j_service_registry,
+    const JavaParamRef<jstring>& j_name) {
   std::string name(ConvertJavaStringToUTF8(env, j_name));
   service_registry_->Remove(name);
 }
 
-void ServiceRegistryAndroid::ConnectToRemoteService(JNIEnv* env,
-                                                    jobject j_service_registry,
-                                                    jstring j_name,
-                                                    jint j_handle) {
+void ServiceRegistryAndroid::ConnectToRemoteService(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& j_service_registry,
+    const JavaParamRef<jstring>& j_name,
+    jint j_handle) {
   std::string name(ConvertJavaStringToUTF8(env, j_name));
   mojo::ScopedMessagePipeHandle handle((mojo::MessagePipeHandle(j_handle)));
   service_registry_->Connect(name, std::move(handle));
diff --git a/content/browser/mojo/service_registry_android.h b/content/browser/mojo/service_registry_android.h
index eb53d27..d1027fb 100644
--- a/content/browser/mojo/service_registry_android.h
+++ b/content/browser/mojo/service_registry_android.h
@@ -26,16 +26,21 @@
   virtual ~ServiceRegistryAndroid();
 
   // Methods called from Java.
-  void AddService(JNIEnv* env,
-                  jobject j_service_registry,
-                  jobject j_manager,
-                  jobject j_factory,
-                  jstring j_name);
-  void RemoveService(JNIEnv* env, jobject j_service_registry, jstring j_name);
-  void ConnectToRemoteService(JNIEnv* env,
-                              jobject j_service_registry,
-                              jstring j_name,
-                              jint handle);
+  void AddService(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& j_service_registry,
+      const base::android::JavaParamRef<jobject>& j_manager,
+      const base::android::JavaParamRef<jobject>& j_factory,
+      const base::android::JavaParamRef<jstring>& j_name);
+  void RemoveService(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& j_service_registry,
+      const base::android::JavaParamRef<jstring>& j_name);
+  void ConnectToRemoteService(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& j_service_registry,
+      const base::android::JavaParamRef<jstring>& j_name,
+      jint handle);
 
   const base::android::ScopedJavaGlobalRef<jobject>& GetObj() { return obj_; }
 
diff --git a/content/browser/renderer_host/ime_adapter_android.cc b/content/browser/renderer_host/ime_adapter_android.cc
index 7fe8485..d70d4969 100644
--- a/content/browser/renderer_host/ime_adapter_android.cc
+++ b/content/browser/renderer_host/ime_adapter_android.cc
@@ -124,7 +124,7 @@
 }
 
 bool ImeAdapterAndroid::SendSyntheticKeyEvent(JNIEnv*,
-                                              jobject,
+                                              const JavaParamRef<jobject>&,
                                               int type,
                                               long time_ms,
                                               int key_code,
@@ -137,12 +137,17 @@
   return true;
 }
 
-bool ImeAdapterAndroid::SendKeyEvent(JNIEnv* env, jobject,
-                                     jobject original_key_event,
-                                     int action, int modifiers,
-                                     long time_ms, int key_code,
-                                     int scan_code, bool is_system_key,
-                                     int unicode_char) {
+bool ImeAdapterAndroid::SendKeyEvent(
+    JNIEnv* env,
+    const JavaParamRef<jobject>&,
+    const JavaParamRef<jobject>& original_key_event,
+    int action,
+    int modifiers,
+    long time_ms,
+    int key_code,
+    int scan_code,
+    bool is_system_key,
+    int unicode_char) {
   NativeWebKeyboardEvent event = NativeWebKeyboardEventFromKeyEvent(
           env, original_key_event, action, modifiers,
           time_ms, key_code, scan_code, is_system_key, unicode_char);
@@ -167,9 +172,9 @@
 }
 
 void ImeAdapterAndroid::SetComposingText(JNIEnv* env,
-                                         jobject obj,
-                                         jobject text,
-                                         jstring text_str,
+                                         const JavaParamRef<jobject>& obj,
+                                         const JavaParamRef<jobject>& text,
+                                         const JavaParamRef<jstring>& text_str,
                                          int new_cursor_pos) {
   RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
   if (!rwhi)
@@ -201,7 +206,9 @@
   rwhi->ImeSetComposition(text16, underlines, new_cursor_pos, new_cursor_pos);
 }
 
-void ImeAdapterAndroid::CommitText(JNIEnv* env, jobject, jstring text_str) {
+void ImeAdapterAndroid::CommitText(JNIEnv* env,
+                                   const JavaParamRef<jobject>&,
+                                   const JavaParamRef<jstring>& text_str) {
   RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
   if (!rwhi)
     return;
@@ -210,7 +217,8 @@
   rwhi->ImeConfirmComposition(text16, gfx::Range::InvalidRange(), false);
 }
 
-void ImeAdapterAndroid::FinishComposingText(JNIEnv* env, jobject) {
+void ImeAdapterAndroid::FinishComposingText(JNIEnv* env,
+                                            const JavaParamRef<jobject>&) {
   RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
   if (!rwhi)
     return;
@@ -219,7 +227,9 @@
                               true);
 }
 
-void ImeAdapterAndroid::AttachImeAdapter(JNIEnv* env, jobject java_object) {
+void ImeAdapterAndroid::AttachImeAdapter(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& java_object) {
   java_ime_adapter_ = JavaObjectWeakGlobalRef(env, java_object);
 }
 
@@ -240,8 +250,11 @@
   }
 }
 
-void ImeAdapterAndroid::SetEditableSelectionOffsets(JNIEnv*, jobject,
-                                                    int start, int end) {
+void ImeAdapterAndroid::SetEditableSelectionOffsets(
+    JNIEnv*,
+    const JavaParamRef<jobject>&,
+    int start,
+    int end) {
   RenderFrameHost* rfh = GetFocusedFrame();
   if (!rfh)
     return;
@@ -250,8 +263,10 @@
                                                      start, end));
 }
 
-void ImeAdapterAndroid::SetComposingRegion(JNIEnv*, jobject,
-                                           int start, int end) {
+void ImeAdapterAndroid::SetComposingRegion(JNIEnv*,
+                                           const JavaParamRef<jobject>&,
+                                           int start,
+                                           int end) {
   RenderFrameHost* rfh = GetFocusedFrame();
   if (!rfh)
     return;
@@ -264,15 +279,18 @@
       rfh->GetRoutingID(), start, end, underlines));
 }
 
-void ImeAdapterAndroid::DeleteSurroundingText(JNIEnv*, jobject,
-                                              int before, int after) {
+void ImeAdapterAndroid::DeleteSurroundingText(JNIEnv*,
+                                              const JavaParamRef<jobject>&,
+                                              int before,
+                                              int after) {
   RenderFrameHostImpl* rfh =
       static_cast<RenderFrameHostImpl*>(GetFocusedFrame());
   if (rfh)
     rfh->ExtendSelectionAndDelete(before, after);
 }
 
-void ImeAdapterAndroid::ResetImeAdapter(JNIEnv* env, jobject) {
+void ImeAdapterAndroid::ResetImeAdapter(JNIEnv* env,
+                                        const JavaParamRef<jobject>&) {
   java_ime_adapter_.reset();
 }
 
diff --git a/content/browser/renderer_host/ime_adapter_android.h b/content/browser/renderer_host/ime_adapter_android.h
index f6b57fd..0830f272 100644
--- a/content/browser/renderer_host/ime_adapter_android.h
+++ b/content/browser/renderer_host/ime_adapter_android.h
@@ -30,32 +30,51 @@
   // Called from java -> native
   // The java side is responsible to translate android KeyEvent various enums
   // and values into the corresponding blink::WebInputEvent.
-  bool SendKeyEvent(JNIEnv* env, jobject,
-                    jobject original_key_event,
-                    int action, int meta_state,
-                    long event_time, int key_code,
-                    int scan_code, bool is_system_key,
-                    int unicode_text);
+  bool SendKeyEvent(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>&,
+      const base::android::JavaParamRef<jobject>& original_key_event,
+      int action,
+      int meta_state,
+      long event_time,
+      int key_code,
+      int scan_code,
+      bool is_system_key,
+      int unicode_text);
   // |event_type| is a value of WebInputEvent::Type.
   bool SendSyntheticKeyEvent(JNIEnv*,
-                             jobject,
+                             const base::android::JavaParamRef<jobject>&,
                              int event_type,
                              long timestamp_ms,
                              int native_key_code,
                              int modifiers,
                              int unicode_char);
   void SetComposingText(JNIEnv*,
-                        jobject obj,
-                        jobject text,
-                        jstring text_str,
+                        const base::android::JavaParamRef<jobject>& obj,
+                        const base::android::JavaParamRef<jobject>& text,
+                        const base::android::JavaParamRef<jstring>& text_str,
                         int new_cursor_pos);
-  void CommitText(JNIEnv*, jobject, jstring text_str);
-  void FinishComposingText(JNIEnv* env, jobject);
-  void AttachImeAdapter(JNIEnv*, jobject java_object);
-  void SetEditableSelectionOffsets(JNIEnv*, jobject, int start, int end);
-  void SetComposingRegion(JNIEnv*, jobject, int start, int end);
-  void DeleteSurroundingText(JNIEnv*, jobject, int before, int after);
-  void ResetImeAdapter(JNIEnv*, jobject);
+  void CommitText(JNIEnv*,
+                  const base::android::JavaParamRef<jobject>&,
+                  const base::android::JavaParamRef<jstring>& text_str);
+  void FinishComposingText(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>&);
+  void AttachImeAdapter(
+      JNIEnv*,
+      const base::android::JavaParamRef<jobject>& java_object);
+  void SetEditableSelectionOffsets(JNIEnv*,
+                                   const base::android::JavaParamRef<jobject>&,
+                                   int start,
+                                   int end);
+  void SetComposingRegion(JNIEnv*,
+                          const base::android::JavaParamRef<jobject>&,
+                          int start,
+                          int end);
+  void DeleteSurroundingText(JNIEnv*,
+                             const base::android::JavaParamRef<jobject>&,
+                             int before,
+                             int after);
+  void ResetImeAdapter(JNIEnv*, const base::android::JavaParamRef<jobject>&);
 
   // Called from native -> java
   void CancelComposition();
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index f88d475..3cf784d 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1462,6 +1462,7 @@
     cc::switches::kTopControlsShowThreshold,
 
     scheduler::switches::kEnableVirtualizedTime,
+    scheduler::switches::kDisableBackgroundTimerThrottling,
 
 #if defined(ENABLE_PLUGINS)
     switches::kEnablePepperTesting,
@@ -2125,6 +2126,11 @@
 bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
     BrowserContext* browser_context,
     const GURL& url) {
+  // This needs to be checked first to ensure that --single-process
+  // and --site-per-process can be used together.
+  if (run_renderer_in_process())
+    return true;
+
   // If --site-per-process is enabled, do not try to reuse renderer processes
   // when over the limit.
   // TODO(nick): This is overly conservative and isn't launchable. Move this
@@ -2134,9 +2140,6 @@
   if (SiteIsolationPolicy::AreCrossProcessFramesPossible())
     return false;
 
-  if (run_renderer_in_process())
-    return true;
-
   // NOTE: Sometimes it's necessary to create more render processes than
   //       GetMaxRendererProcessCount(), for instance when we want to create
   //       a renderer process for a browser context that has no existing
diff --git a/content/browser/shared_worker/shared_worker_message_filter.cc b/content/browser/shared_worker/shared_worker_message_filter.cc
index 9f75967..ebf79ff2 100644
--- a/content/browser/shared_worker/shared_worker_message_filter.cc
+++ b/content/browser/shared_worker/shared_worker_message_filter.cc
@@ -9,6 +9,7 @@
 #include "content/common/devtools_messages.h"
 #include "content/common/view_messages.h"
 #include "content/common/worker_messages.h"
+#include "third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h"
 
 namespace content {
 namespace {
@@ -77,18 +78,13 @@
 
 void SharedWorkerMessageFilter::OnCreateWorker(
     const ViewHostMsg_CreateWorker_Params& params,
-    int* route_id) {
-  bool url_error = false;
-  *route_id = GetNextRoutingID();
+    ViewHostMsg_CreateWorker_Reply* reply) {
+  reply->route_id = GetNextRoutingID();
   SharedWorkerServiceImpl::GetInstance()->CreateWorker(
-      params,
-      *route_id,
-      this,
-      resource_context_,
-      WorkerStoragePartitionId(partition_),
-      &url_error);
-  if (url_error)
-    *route_id = MSG_ROUTING_NONE;
+      params, reply->route_id, this, resource_context_,
+      WorkerStoragePartitionId(partition_), &reply->error);
+  if (reply->error != blink::WebWorkerCreationErrorNone)
+    reply->route_id = MSG_ROUTING_NONE;
 }
 
 void SharedWorkerMessageFilter::OnForwardToWorker(const IPC::Message& message) {
diff --git a/content/browser/shared_worker/shared_worker_message_filter.h b/content/browser/shared_worker/shared_worker_message_filter.h
index 6e41bfe..b5f54e5 100644
--- a/content/browser/shared_worker/shared_worker_message_filter.h
+++ b/content/browser/shared_worker/shared_worker_message_filter.h
@@ -11,6 +11,7 @@
 
 class GURL;
 struct ViewHostMsg_CreateWorker_Params;
+struct ViewHostMsg_CreateWorker_Reply;
 
 namespace content {
 class MessagePortMessageFilter;
@@ -43,7 +44,7 @@
  private:
   // Message handlers.
   void OnCreateWorker(const ViewHostMsg_CreateWorker_Params& params,
-                      int* route_id);
+                      ViewHostMsg_CreateWorker_Reply* reply);
   void OnForwardToWorker(const IPC::Message& message);
   void OnDocumentDetached(unsigned long long document_id);
   void OnWorkerContextClosed(int worker_route_id);
diff --git a/content/browser/shared_worker/shared_worker_service_impl.cc b/content/browser/shared_worker/shared_worker_service_impl.cc
index af5b65d..ad4e433 100644
--- a/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -284,9 +284,9 @@
     SharedWorkerMessageFilter* filter,
     ResourceContext* resource_context,
     const WorkerStoragePartitionId& partition_id,
-    bool* url_mismatch) {
+    blink::WebWorkerCreationError* creation_error) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  *url_mismatch = false;
+  *creation_error = blink::WebWorkerCreationErrorNone;
   scoped_ptr<SharedWorkerInstance> instance(
       new SharedWorkerInstance(params.url,
                                params.name,
@@ -303,7 +303,7 @@
           params.render_frame_route_id));
   if (SharedWorkerPendingInstance* pending = FindPendingInstance(*instance)) {
     if (params.url != pending->instance()->url()) {
-      *url_mismatch = true;
+      *creation_error = blink::WebWorkerCreationErrorURLMismatch;
       return;
     }
     pending->AddRequest(request.Pass());
@@ -312,7 +312,7 @@
   scoped_ptr<SharedWorkerPendingInstance> pending_instance(
       new SharedWorkerPendingInstance(instance.Pass()));
   pending_instance->AddRequest(request.Pass());
-  ReserveRenderProcessToCreateWorker(pending_instance.Pass(), url_mismatch);
+  ReserveRenderProcessToCreateWorker(pending_instance.Pass(), creation_error);
 }
 
 void SharedWorkerServiceImpl::ForwardToWorker(
@@ -466,11 +466,11 @@
 
 void SharedWorkerServiceImpl::ReserveRenderProcessToCreateWorker(
     scoped_ptr<SharedWorkerPendingInstance> pending_instance,
-    bool* url_mismatch) {
+    blink::WebWorkerCreationError* creation_error) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!FindPendingInstance(*pending_instance->instance()));
-  if (url_mismatch)
-    *url_mismatch = false;
+  if (creation_error)
+    *creation_error = blink::WebWorkerCreationErrorNone;
   if (!pending_instance->requests()->size())
     return;
   int worker_process_id = -1;
@@ -479,8 +479,8 @@
   SharedWorkerHost* host = FindSharedWorkerHost(*pending_instance->instance());
   if (host) {
     if (pending_instance->instance()->url() != host->instance()->url()) {
-      if (url_mismatch)
-        *url_mismatch = true;
+      if (creation_error)
+        *creation_error = blink::WebWorkerCreationErrorURLMismatch;
       return;
     }
     worker_process_id = host->process_id();
diff --git a/content/browser/shared_worker/shared_worker_service_impl.h b/content/browser/shared_worker/shared_worker_service_impl.h
index ea68ae6..aae153d 100644
--- a/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/content/browser/shared_worker/shared_worker_service_impl.h
@@ -14,6 +14,7 @@
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/worker_service.h"
+#include "third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h"
 
 struct ViewHostMsg_CreateWorker_Params;
 
@@ -50,7 +51,7 @@
                     SharedWorkerMessageFilter* filter,
                     ResourceContext* resource_context,
                     const WorkerStoragePartitionId& partition_id,
-                    bool* url_mismatch);
+                    blink::WebWorkerCreationError* creation_error);
   void ForwardToWorker(const IPC::Message& message,
                        SharedWorkerMessageFilter* filter);
   void DocumentDetached(unsigned long long document_id,
@@ -123,7 +124,7 @@
   // will be called on IO thread.
   void ReserveRenderProcessToCreateWorker(
       scoped_ptr<SharedWorkerPendingInstance> pending_instance,
-      bool* url_mismatch);
+      blink::WebWorkerCreationError* creation_error);
 
   // Called after the render process is reserved to create Shared Worker in it.
   void RenderProcessReservedCallback(int pending_instance_id,
diff --git a/content/browser/shared_worker/shared_worker_service_impl_unittest.cc b/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
index 5c39068..6fe97578 100644
--- a/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
+++ b/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
@@ -243,7 +243,7 @@
                       const std::string& name,
                       unsigned long long document_id,
                       int render_frame_route_id,
-                      int* connector_route_id) {
+                      ViewHostMsg_CreateWorker_Reply* reply) {
   ViewHostMsg_CreateWorker_Params params;
   params.url = GURL(url);
   params.name = base::ASCIIToUTF16(name);
@@ -251,8 +251,8 @@
   params.security_policy_type = blink::WebContentSecurityPolicyTypeReport;
   params.document_id = document_id;
   params.render_frame_route_id = render_frame_route_id;
-  EXPECT_TRUE(renderer->OnMessageReceived(
-      new ViewHostMsg_CreateWorker(params, connector_route_id)));
+  EXPECT_TRUE(
+      renderer->OnMessageReceived(new ViewHostMsg_CreateWorker(params, reply)));
 }
 
 class MockSharedWorkerConnector {
@@ -262,8 +262,7 @@
         temporary_remote_port_route_id_(0),
         remote_port_id_(0),
         local_port_route_id_(0),
-        local_port_id_(0),
-        route_id_(0) {}
+        local_port_id_(0) {}
   void Create(const std::string& url,
               const std::string& name,
               unsigned long long document_id,
@@ -273,12 +272,8 @@
                           &remote_port_id_,
                           &local_port_route_id_,
                           &local_port_id_);
-    PostCreateWorker(renderer_host_,
-                     url,
-                     name,
-                     document_id,
-                     render_frame_route_id,
-                     &route_id_);
+    PostCreateWorker(renderer_host_, url, name, document_id,
+                     render_frame_route_id, &create_worker_reply_);
   }
   void SendQueueMessages() {
     EXPECT_TRUE(renderer_host_->OnMessageReceived(
@@ -294,7 +289,8 @@
   void SendConnect() {
     EXPECT_TRUE(
         renderer_host_->OnMessageReceived(new ViewHostMsg_ForwardToWorker(
-            WorkerMsg_Connect(route_id_, remote_port_id_, MSG_ROUTING_NONE))));
+            WorkerMsg_Connect(create_worker_reply_.route_id, remote_port_id_,
+                              MSG_ROUTING_NONE))));
   }
   void SendSendQueuedMessages(
       const std::vector<QueuedMessage>& queued_messages) {
@@ -308,7 +304,10 @@
   int remote_port_id() { return remote_port_id_; }
   int local_port_route_id() { return local_port_route_id_; }
   int local_port_id() { return local_port_id_; }
-  int route_id() { return route_id_; }
+  int route_id() { return create_worker_reply_.route_id; }
+  blink::WebWorkerCreationError creation_error() {
+    return create_worker_reply_.error;
+  }
 
  private:
   MockRendererProcessHost* renderer_host_;
@@ -316,7 +315,7 @@
   int remote_port_id_;
   int local_port_route_id_;
   int local_port_id_;
-  int route_id_;
+  ViewHostMsg_CreateWorker_Reply create_worker_reply_;
 };
 
 void CheckWorkerProcessMsgCreateWorker(
@@ -731,6 +730,8 @@
                        kDocumentIDs[1],
                        kRenderFrameRouteIDs[1]);
     EXPECT_EQ(MSG_ROUTING_NONE, connector1->route_id());
+    EXPECT_EQ(blink::WebWorkerCreationErrorURLMismatch,
+              connector1->creation_error());
     EXPECT_EQ(0U, renderer_host1->QueuedMessageCount());
     RunAllPendingInMessageLoop();
     EXPECT_EQ(0U, renderer_host1->QueuedMessageCount());
diff --git a/content/browser/time_zone_monitor_android.cc b/content/browser/time_zone_monitor_android.cc
index 8018cf7..4eb777b 100644
--- a/content/browser/time_zone_monitor_android.cc
+++ b/content/browser/time_zone_monitor_android.cc
@@ -26,8 +26,9 @@
   return RegisterNativesImpl(env);
 }
 
-void TimeZoneMonitorAndroid::TimeZoneChangedFromJava(JNIEnv* env,
-                                                     jobject caller) {
+void TimeZoneMonitorAndroid::TimeZoneChangedFromJava(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& caller) {
   NotifyRenderers();
 }
 
diff --git a/content/browser/time_zone_monitor_android.h b/content/browser/time_zone_monitor_android.h
index cb3cb9f21..7714111 100644
--- a/content/browser/time_zone_monitor_android.h
+++ b/content/browser/time_zone_monitor_android.h
@@ -23,7 +23,9 @@
   static bool Register(JNIEnv* env);
 
   // Called by the Java implementation when the system time zone changes.
-  void TimeZoneChangedFromJava(JNIEnv* env, jobject caller);
+  void TimeZoneChangedFromJava(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& caller);
 
  private:
   // Java provider of system time zone change notifications.
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index 782c6c8f..e4fa397 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -281,56 +281,65 @@
 }
 
 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetTitle(
-    JNIEnv* env, jobject obj) const {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) const {
   return base::android::ConvertUTF16ToJavaString(env,
                                                  web_contents_->GetTitle());
 }
 
 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetVisibleURL(
-    JNIEnv* env, jobject obj) const {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) const {
   return base::android::ConvertUTF8ToJavaString(
       env, web_contents_->GetVisibleURL().spec());
 }
 
-bool WebContentsAndroid::IsLoading(JNIEnv* env, jobject obj) const {
+bool WebContentsAndroid::IsLoading(JNIEnv* env,
+                                   const JavaParamRef<jobject>& obj) const {
   return web_contents_->IsLoading();
 }
 
-bool WebContentsAndroid::IsLoadingToDifferentDocument(JNIEnv* env,
-                                                      jobject obj) const {
+bool WebContentsAndroid::IsLoadingToDifferentDocument(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) const {
   return web_contents_->IsLoadingToDifferentDocument();
 }
 
-void WebContentsAndroid::Stop(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::Stop(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   web_contents_->Stop();
 }
 
-void WebContentsAndroid::Cut(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::Cut(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   web_contents_->Cut();
 }
 
-void WebContentsAndroid::Copy(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::Copy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   web_contents_->Copy();
 }
 
-void WebContentsAndroid::Paste(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::Paste(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   web_contents_->Paste();
 }
 
-void WebContentsAndroid::Replace(JNIEnv* env, jobject obj, jstring jstr) {
+void WebContentsAndroid::Replace(JNIEnv* env,
+                                 const JavaParamRef<jobject>& obj,
+                                 const JavaParamRef<jstring>& jstr) {
   web_contents_->Replace(base::android::ConvertJavaStringToUTF16(env, jstr));
 }
 
-void WebContentsAndroid::SelectAll(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::SelectAll(JNIEnv* env,
+                                   const JavaParamRef<jobject>& obj) {
   web_contents_->SelectAll();
 }
 
-void WebContentsAndroid::Unselect(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::Unselect(JNIEnv* env,
+                                  const JavaParamRef<jobject>& obj) {
   web_contents_->Unselect();
 }
 
-void WebContentsAndroid::InsertCSS(
-    JNIEnv* env, jobject jobj, jstring jcss) {
+void WebContentsAndroid::InsertCSS(JNIEnv* env,
+                                   const JavaParamRef<jobject>& jobj,
+                                   const JavaParamRef<jstring>& jcss) {
   web_contents_->InsertCSS(base::android::ConvertJavaStringToUTF8(env, jcss));
 }
 
@@ -348,55 +357,59 @@
   return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
 }
 
-jint WebContentsAndroid::GetBackgroundColor(JNIEnv* env, jobject obj) {
+jint WebContentsAndroid::GetBackgroundColor(JNIEnv* env,
+                                            const JavaParamRef<jobject>& obj) {
   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
   if (!rwhva)
     return SK_ColorWHITE;
   return rwhva->GetCachedBackgroundColor();
 }
 
-ScopedJavaLocalRef<jstring> WebContentsAndroid::GetURL(JNIEnv* env,
-                                                       jobject obj) const {
+ScopedJavaLocalRef<jstring> WebContentsAndroid::GetURL(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) const {
   return ConvertUTF8ToJavaString(env, web_contents_->GetURL().spec());
 }
 
 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetLastCommittedURL(
     JNIEnv* env,
-    jobject) const {
+    const JavaParamRef<jobject>&) const {
   return ConvertUTF8ToJavaString(env,
                                  web_contents_->GetLastCommittedURL().spec());
 }
 
-
-jboolean WebContentsAndroid::IsIncognito(JNIEnv* env, jobject obj) {
+jboolean WebContentsAndroid::IsIncognito(JNIEnv* env,
+                                         const JavaParamRef<jobject>& obj) {
   return web_contents_->GetBrowserContext()->IsOffTheRecord();
 }
 
-void WebContentsAndroid::ResumeLoadingCreatedWebContents(JNIEnv* env,
-                                                         jobject obj) {
+void WebContentsAndroid::ResumeLoadingCreatedWebContents(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   web_contents_->ResumeLoadingCreatedWebContents();
 }
 
-void WebContentsAndroid::OnHide(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::OnHide(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   web_contents_->WasHidden();
 }
 
-void WebContentsAndroid::OnShow(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::OnShow(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   web_contents_->WasShown();
 }
 
-void WebContentsAndroid::ReleaseMediaPlayers(JNIEnv* env, jobject jobj) {
+void WebContentsAndroid::ReleaseMediaPlayers(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& jobj) {
 #if defined(ENABLE_BROWSER_CDMS)
   web_contents_->ForEachFrame(
       base::Bind(&ReleaseAllMediaPlayers, base::Unretained(web_contents_)));
 #endif // defined(ENABLE_BROWSER_CDMS)
 }
 
-void WebContentsAndroid::ShowInterstitialPage(
-    JNIEnv* env,
-    jobject obj,
-    jstring jurl,
-    jlong delegate_ptr) {
+void WebContentsAndroid::ShowInterstitialPage(JNIEnv* env,
+                                              const JavaParamRef<jobject>& obj,
+                                              const JavaParamRef<jstring>& jurl,
+                                              jlong delegate_ptr) {
   GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
   InterstitialPageDelegateAndroid* delegate =
       reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
@@ -406,30 +419,33 @@
   interstitial->Show();
 }
 
-jboolean WebContentsAndroid::IsShowingInterstitialPage(JNIEnv* env,
-                                                        jobject obj) {
+jboolean WebContentsAndroid::IsShowingInterstitialPage(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return web_contents_->ShowingInterstitialPage();
 }
 
-jboolean WebContentsAndroid::FocusLocationBarByDefault(JNIEnv* env,
-                                                       jobject obj) {
+jboolean WebContentsAndroid::FocusLocationBarByDefault(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return web_contents_->FocusLocationBarByDefault();
 }
 
 jboolean WebContentsAndroid::IsRenderWidgetHostViewReady(
     JNIEnv* env,
-    jobject obj) {
+    const JavaParamRef<jobject>& obj) {
   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   return view && view->HasValidFrame();
 }
 
-void WebContentsAndroid::ExitFullscreen(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::ExitFullscreen(JNIEnv* env,
+                                        const JavaParamRef<jobject>& obj) {
   web_contents_->ExitFullscreen();
 }
 
 void WebContentsAndroid::UpdateTopControlsState(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     bool enable_hiding,
     bool enable_showing,
     bool animate) {
@@ -442,7 +458,8 @@
                                                 animate));
 }
 
-void WebContentsAndroid::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::ShowImeIfNeeded(JNIEnv* env,
+                                         const JavaParamRef<jobject>& obj) {
   RenderViewHost* host = web_contents_->GetRenderViewHost();
   if (!host)
     return;
@@ -451,7 +468,7 @@
 
 void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
     JNIEnv* env,
-    jobject obj) {
+    const JavaParamRef<jobject>& obj) {
   RenderViewHost* host = web_contents_->GetRenderViewHost();
   if (!host)
     return;
@@ -459,24 +476,28 @@
       host->GetRoutingID(), gfx::Rect()));
 }
 
-void WebContentsAndroid::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::SelectWordAroundCaret(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   RenderViewHost* host = web_contents_->GetRenderViewHost();
   if (!host)
     return;
   host->SelectWordAroundCaret();
 }
 
-void WebContentsAndroid::AdjustSelectionByCharacterOffset(JNIEnv* env,
-                                                          jobject obj,
-                                                          jint start_adjust,
-                                                          jint end_adjust) {
+void WebContentsAndroid::AdjustSelectionByCharacterOffset(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint start_adjust,
+    jint end_adjust) {
   web_contents_->AdjustSelectionByCharacterOffset(start_adjust, end_adjust);
 }
 
-void WebContentsAndroid::EvaluateJavaScript(JNIEnv* env,
-                                            jobject obj,
-                                            jstring script,
-                                            jobject callback) {
+void WebContentsAndroid::EvaluateJavaScript(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& script,
+    const JavaParamRef<jobject>& callback) {
   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
   DCHECK(rvh);
 
@@ -506,10 +527,11 @@
       ConvertJavaStringToUTF16(env, script), js_callback);
 }
 
-void WebContentsAndroid::EvaluateJavaScriptForTests(JNIEnv* env,
-                                                    jobject obj,
-                                                    jstring script,
-                                                    jobject callback) {
+void WebContentsAndroid::EvaluateJavaScriptForTests(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& script,
+    const JavaParamRef<jobject>& callback) {
   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
   DCHECK(rvh);
 
@@ -539,10 +561,11 @@
       ConvertJavaStringToUTF16(env, script), js_callback);
 }
 
-void WebContentsAndroid::AddMessageToDevToolsConsole(JNIEnv* env,
-                                                     jobject jobj,
-                                                     jint level,
-                                                     jstring message) {
+void WebContentsAndroid::AddMessageToDevToolsConsole(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& jobj,
+    jint level,
+    const JavaParamRef<jstring>& message) {
   DCHECK_GE(level, 0);
   DCHECK_LE(level, CONSOLE_MESSAGE_LEVEL_LAST);
 
@@ -551,11 +574,12 @@
       ConvertJavaStringToUTF8(env, message));
 }
 
-void WebContentsAndroid::SendMessageToFrame(JNIEnv* env,
-                                            jobject obj,
-                                            jstring frame_name,
-                                            jstring message,
-                                            jstring target_origin) {
+void WebContentsAndroid::SendMessageToFrame(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& frame_name,
+    const JavaParamRef<jstring>& message,
+    const JavaParamRef<jstring>& target_origin) {
   base::string16 source_origin;
   base::string16 j_target_origin(ConvertJavaStringToUTF16(env, target_origin));
   base::string16 j_message(ConvertJavaStringToUTF16(env, message));
@@ -566,20 +590,22 @@
 
 jboolean WebContentsAndroid::HasAccessedInitialDocument(
     JNIEnv* env,
-    jobject jobj) {
+    const JavaParamRef<jobject>& jobj) {
   return static_cast<WebContentsImpl*>(web_contents_)->
       HasAccessedInitialDocument();
 }
 
-jint WebContentsAndroid::GetThemeColor(JNIEnv* env, jobject obj) {
+jint WebContentsAndroid::GetThemeColor(JNIEnv* env,
+                                       const JavaParamRef<jobject>& obj) {
   return web_contents_->GetThemeColor();
 }
 
-void WebContentsAndroid::RequestAccessibilitySnapshot(JNIEnv* env,
-                                                      jobject obj,
-                                                      jobject callback,
-                                                      jfloat y_offset,
-                                                      jfloat x_scroll) {
+void WebContentsAndroid::RequestAccessibilitySnapshot(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& callback,
+    jfloat y_offset,
+    jfloat x_scroll) {
   // Secure the Java callback in a scoped object and give ownership of it to the
   // base::Callback.
   ScopedJavaGlobalRef<jobject> j_callback;
@@ -596,20 +622,24 @@
       snapshot_callback);
 }
 
-void WebContentsAndroid::ResumeMediaSession(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::ResumeMediaSession(JNIEnv* env,
+                                            const JavaParamRef<jobject>& obj) {
   web_contents_->ResumeMediaSession();
 }
 
-void WebContentsAndroid::SuspendMediaSession(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::SuspendMediaSession(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj) {
   web_contents_->SuspendMediaSession();
 }
 
-void WebContentsAndroid::StopMediaSession(JNIEnv* env, jobject obj) {
+void WebContentsAndroid::StopMediaSession(JNIEnv* env,
+                                          const JavaParamRef<jobject>& obj) {
   web_contents_->StopMediaSession();
 }
 
-ScopedJavaLocalRef<jstring>  WebContentsAndroid::GetEncoding(
-    JNIEnv* env, jobject obj) const {
+ScopedJavaLocalRef<jstring> WebContentsAndroid::GetEncoding(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) const {
   return base::android::ConvertUTF8ToJavaString(env,
                                                 web_contents_->GetEncoding());
 }
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h
index 7710bb2..1bc37393 100644
--- a/content/browser/web_contents/web_contents_android.h
+++ b/content/browser/web_contents/web_contents_android.h
@@ -39,89 +39,130 @@
   base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
 
   // Methods called from Java
-  base::android::ScopedJavaLocalRef<jstring> GetTitle(JNIEnv* env,
-                                                      jobject obj) const;
-  base::android::ScopedJavaLocalRef<jstring> GetVisibleURL(JNIEnv* env,
-                                                           jobject obj) const;
-
-  bool IsLoading(JNIEnv* env, jobject obj) const;
-  bool IsLoadingToDifferentDocument(JNIEnv* env, jobject obj) const;
-
-  void Stop(JNIEnv* env, jobject obj);
-  void Cut(JNIEnv* env, jobject obj);
-  void Copy(JNIEnv* env, jobject obj);
-  void Paste(JNIEnv* env, jobject obj);
-  void Replace(JNIEnv* env, jobject obj, jstring jstr);
-  void SelectAll(JNIEnv* env, jobject obj);
-  void Unselect(JNIEnv* env, jobject obj);
-  jint GetBackgroundColor(JNIEnv* env, jobject obj);
-  base::android::ScopedJavaLocalRef<jstring> GetURL(JNIEnv* env, jobject) const;
-  base::android::ScopedJavaLocalRef<jstring> GetLastCommittedURL(JNIEnv* env,
-                                                                 jobject) const;
-  jboolean IsIncognito(JNIEnv* env, jobject obj);
-
-  void ResumeLoadingCreatedWebContents(JNIEnv* env, jobject obj);
-
-  void OnHide(JNIEnv* env, jobject obj);
-  void OnShow(JNIEnv* env, jobject obj);
-  void ReleaseMediaPlayers(JNIEnv* env, jobject jobj);
-
-  void ShowInterstitialPage(
-      JNIEnv* env, jobject obj, jstring jurl, jlong delegate_ptr);
-  jboolean IsShowingInterstitialPage(JNIEnv* env, jobject obj);
-  jboolean FocusLocationBarByDefault(JNIEnv* env, jobject obj);
-  jboolean IsRenderWidgetHostViewReady(JNIEnv* env, jobject obj);
-  void ExitFullscreen(JNIEnv* env, jobject obj);
-  void UpdateTopControlsState(
+  base::android::ScopedJavaLocalRef<jstring> GetTitle(
       JNIEnv* env,
-      jobject obj,
-      bool enable_hiding,
-      bool enable_showing,
-      bool animate);
-  void ShowImeIfNeeded(JNIEnv* env, jobject obj);
-  void ScrollFocusedEditableNodeIntoView(JNIEnv* env, jobject obj);
-  void SelectWordAroundCaret(JNIEnv* env, jobject obj);
-  void AdjustSelectionByCharacterOffset(JNIEnv* env,
-                                        jobject obj,
-                                        jint start_adjust,
-                                        jint end_adjust);
-  void InsertCSS(JNIEnv* env, jobject jobj, jstring jcss);
+      const base::android::JavaParamRef<jobject>& obj) const;
+  base::android::ScopedJavaLocalRef<jstring> GetVisibleURL(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj) const;
+
+  bool IsLoading(JNIEnv* env,
+                 const base::android::JavaParamRef<jobject>& obj) const;
+  bool IsLoadingToDifferentDocument(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj) const;
+
+  void Stop(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void Cut(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void Copy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void Paste(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void Replace(JNIEnv* env,
+               const base::android::JavaParamRef<jobject>& obj,
+               const base::android::JavaParamRef<jstring>& jstr);
+  void SelectAll(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void Unselect(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  jint GetBackgroundColor(JNIEnv* env,
+                          const base::android::JavaParamRef<jobject>& obj);
+  base::android::ScopedJavaLocalRef<jstring> GetURL(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>&) const;
+  base::android::ScopedJavaLocalRef<jstring> GetLastCommittedURL(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>&) const;
+  jboolean IsIncognito(JNIEnv* env,
+                       const base::android::JavaParamRef<jobject>& obj);
+
+  void ResumeLoadingCreatedWebContents(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+
+  void OnHide(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void OnShow(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void ReleaseMediaPlayers(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& jobj);
+
+  void ShowInterstitialPage(JNIEnv* env,
+                            const base::android::JavaParamRef<jobject>& obj,
+                            const base::android::JavaParamRef<jstring>& jurl,
+                            jlong delegate_ptr);
+  jboolean IsShowingInterstitialPage(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean FocusLocationBarByDefault(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean IsRenderWidgetHostViewReady(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  void ExitFullscreen(JNIEnv* env,
+                      const base::android::JavaParamRef<jobject>& obj);
+  void UpdateTopControlsState(JNIEnv* env,
+                              const base::android::JavaParamRef<jobject>& obj,
+                              bool enable_hiding,
+                              bool enable_showing,
+                              bool animate);
+  void ShowImeIfNeeded(JNIEnv* env,
+                       const base::android::JavaParamRef<jobject>& obj);
+  void ScrollFocusedEditableNodeIntoView(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  void SelectWordAroundCaret(JNIEnv* env,
+                             const base::android::JavaParamRef<jobject>& obj);
+  void AdjustSelectionByCharacterOffset(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint start_adjust,
+      jint end_adjust);
+  void InsertCSS(JNIEnv* env,
+                 const base::android::JavaParamRef<jobject>& jobj,
+                 const base::android::JavaParamRef<jstring>& jcss);
   void EvaluateJavaScript(JNIEnv* env,
-                          jobject obj,
-                          jstring script,
-                          jobject callback);
-  void EvaluateJavaScriptForTests(JNIEnv* env,
-                                  jobject obj,
-                                  jstring script,
-                                  jobject callback);
+                          const base::android::JavaParamRef<jobject>& obj,
+                          const base::android::JavaParamRef<jstring>& script,
+                          const base::android::JavaParamRef<jobject>& callback);
+  void EvaluateJavaScriptForTests(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& script,
+      const base::android::JavaParamRef<jobject>& callback);
 
-  void AddMessageToDevToolsConsole(JNIEnv* env,
-                                   jobject jobj,
-                                   jint level,
-                                   jstring message);
+  void AddMessageToDevToolsConsole(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& jobj,
+      jint level,
+      const base::android::JavaParamRef<jstring>& message);
 
-  void SendMessageToFrame(JNIEnv* env,
-                          jobject obj,
-                          jstring frame_name,
-                          jstring message,
-                          jstring target_origin);
+  void SendMessageToFrame(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& frame_name,
+      const base::android::JavaParamRef<jstring>& message,
+      const base::android::JavaParamRef<jstring>& target_origin);
 
-  jboolean HasAccessedInitialDocument(JNIEnv* env, jobject jobj);
+  jboolean HasAccessedInitialDocument(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& jobj);
 
-  jint GetThemeColor(JNIEnv* env, jobject obj);
+  jint GetThemeColor(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& obj);
 
-  void RequestAccessibilitySnapshot(JNIEnv* env,
-                                    jobject obj,
-                                    jobject callback,
-                                    jfloat y_offset,
-                                    jfloat x_scroll);
+  void RequestAccessibilitySnapshot(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jobject>& callback,
+      jfloat y_offset,
+      jfloat x_scroll);
 
-  void ResumeMediaSession(JNIEnv* env, jobject obj);
-  void SuspendMediaSession(JNIEnv* env, jobject obj);
-  void StopMediaSession(JNIEnv* env, jobject obj);
+  void ResumeMediaSession(JNIEnv* env,
+                          const base::android::JavaParamRef<jobject>& obj);
+  void SuspendMediaSession(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& obj);
+  void StopMediaSession(JNIEnv* env,
+                        const base::android::JavaParamRef<jobject>& obj);
 
-  base::android::ScopedJavaLocalRef<jstring> GetEncoding(JNIEnv* env,
-                                                         jobject obj) const;
+  base::android::ScopedJavaLocalRef<jstring> GetEncoding(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj) const;
 
   // Relay the access from Java layer to GetScaledContentBitmap through JNI.
   void GetContentBitmap(JNIEnv* env,
diff --git a/content/child/scoped_web_callbacks.h b/content/child/scoped_web_callbacks.h
index 7f578dd..b0c3b2b4 100644
--- a/content/child/scoped_web_callbacks.h
+++ b/content/child/scoped_web_callbacks.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_CHILD_SCOPED_WEB_CALLBACKS_H_
 #define CONTENT_CHILD_SCOPED_WEB_CALLBACKS_H_
 
+#include <utility>
+
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/move.h"
@@ -64,7 +66,7 @@
 // our desired default behavior before deleting the WebCallbacks.
 template <typename CallbacksType>
 class ScopedWebCallbacks {
-  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedWebCallbacks, RValue);
+  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedWebCallbacks);
 
  public:
   using DestructionCallback =
@@ -80,11 +82,11 @@
       destruction_callback_.Run(callbacks_.Pass());
   }
 
-  ScopedWebCallbacks(RValue other) { *this = other; }
+  ScopedWebCallbacks(ScopedWebCallbacks&& other) { *this = std::move(other); }
 
-  ScopedWebCallbacks& operator=(RValue other) {
-    callbacks_ = other.object->callbacks_.Pass();
-    destruction_callback_ = other.object->destruction_callback_;
+  ScopedWebCallbacks& operator=(ScopedWebCallbacks&& other) {
+    callbacks_ = std::move(other.callbacks_);
+    destruction_callback_ = other.destruction_callback_;
     return *this;
   }
 
diff --git a/content/child/web_memory_dump_provider_adapter.cc b/content/child/web_memory_dump_provider_adapter.cc
index 84f7099..d5fbdfb 100644
--- a/content/child/web_memory_dump_provider_adapter.cc
+++ b/content/child/web_memory_dump_provider_adapter.cc
@@ -28,8 +28,9 @@
     LAZY_INSTANCE_INITIALIZER;
 bool g_heap_profiling_enabled = false;
 
-void ReportAllocation(void* address, size_t size) {
+void ReportAllocation(void* address, size_t size, const char* type_name) {
   AllocationContext context = AllocationContextTracker::GetContextSnapshot();
+  context.type_name = type_name;
   AutoLock lock(g_allocation_register_lock.Get());
 
   if (g_allocation_register)
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index faf6e0d..e1cae894 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -545,6 +545,7 @@
   import_dirs = [ "//mojo/services" ]
 
   deps = [
+    "//components/mus/public/interfaces",
     "//content/public/common:mojo_bindings",
     "//mojo/application/public/interfaces",
     "//skia/public/interfaces",
diff --git a/content/common/DEPS b/content/common/DEPS
index f7b55bd..e2d9fd7 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -57,6 +57,7 @@
   "+third_party/WebKit/public/web/WebPluginAction.h",
   "+third_party/WebKit/public/web/WebPopupType.h",
   "+third_party/WebKit/public/web/WebSandboxFlags.h",
+  "+third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h",
   "+third_party/WebKit/public/web/WebTextDirection.h",
   "+third_party/WebKit/public/web/WebTreeScopeType.h",
   "+third_party/WebKit/public/web/WebWindowFeatures.h",
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 9e9ea06..e1375a5 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -50,6 +50,7 @@
 #include "third_party/WebKit/public/web/WebMediaPlayerAction.h"
 #include "third_party/WebKit/public/web/WebPluginAction.h"
 #include "third_party/WebKit/public/web/WebPopupType.h"
+#include "third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h"
 #include "third_party/WebKit/public/web/WebTextDirection.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/ime/text_input_mode.h"
@@ -85,6 +86,8 @@
 IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScreenOrientationType,
                               blink::WebScreenOrientationUndefined,
                               blink::WebScreenOrientationLandscapeSecondary)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebWorkerCreationError,
+                          blink::WebWorkerCreationErrorLast)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::WebTextDirection,
                           blink::WebTextDirection::WebTextDirectionLast)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::WebDisplayMode,
@@ -376,6 +379,15 @@
   IPC_STRUCT_MEMBER(int, render_frame_route_id)
 IPC_STRUCT_END()
 
+IPC_STRUCT_BEGIN(ViewHostMsg_CreateWorker_Reply)
+  // The route id for the created worker.
+  IPC_STRUCT_MEMBER(int, route_id)
+
+  // The error that occurred, if the browser failed to create the
+  // worker.
+  IPC_STRUCT_MEMBER(blink::WebWorkerCreationError, error)
+IPC_STRUCT_END()
+
 IPC_STRUCT_BEGIN(ViewHostMsg_DateTimeDialogValue_Params)
   IPC_STRUCT_MEMBER(ui::TextInputType, dialog_type)
   IPC_STRUCT_MEMBER(double, dialog_value)
@@ -1129,10 +1141,11 @@
 
 // A renderer sends this to the browser process when it wants to create a
 // worker.  The browser will create the worker process if necessary, and
-// will return the route id on success.  On error returns MSG_ROUTING_NONE.
+// will return the route id on in the reply on success.  On error returns
+// MSG_ROUTING_NONE and an error type.
 IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_CreateWorker,
                             ViewHostMsg_CreateWorker_Params,
-                            int /* route_id */)
+                            ViewHostMsg_CreateWorker_Reply)
 
 // A renderer sends this to the browser process when a document has been
 // detached. The browser will use this to constrain the lifecycle of worker
diff --git a/content/renderer/media/webrtc_audio_renderer.cc b/content/renderer/media/webrtc_audio_renderer.cc
index 9015afc..e58347b 100644
--- a/content/renderer/media/webrtc_audio_renderer.cc
+++ b/content/renderer/media/webrtc_audio_renderer.cc
@@ -565,10 +565,10 @@
 
 void WebRtcAudioRenderer::PrepareSink() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  media::AudioParameters sink_params;
+  media::AudioParameters new_sink_params;
   {
     base::AutoLock lock(lock_);
-    sink_params = sink_params_;
+    new_sink_params = sink_params_;
   }
   // WebRTC does not yet support higher rates than 96000 on the client side
   // and 48000 is the preferred sample rate. Therefore, if 192000 is detected,
@@ -598,47 +598,50 @@
   DVLOG(1) << "Using WebRTC output buffer size: " << frames_per_10ms;
   media::AudioParameters source_params(
       media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
-      sink_params.channel_layout(), sample_rate, 16, frames_per_10ms);
-  source_params.set_channels_for_discrete(sink_params.channels());
+      new_sink_params.channel_layout(), sample_rate, 16, frames_per_10ms);
+  source_params.set_channels_for_discrete(new_sink_params.channels());
 
   const int frames_per_buffer = GetOptimalBufferSize(
       sample_rate, sink_->GetOutputParameters().frames_per_buffer());
 
-  sink_params.Reset(sink_params.format(), sink_params.channel_layout(),
-                    sample_rate, 16, frames_per_buffer);
+  new_sink_params.Reset(
+      new_sink_params.format(), new_sink_params.channel_layout(),
+      sample_rate, 16, frames_per_buffer);
 
   // Create a FIFO if re-buffering is required to match the source input with
   // the sink request. The source acts as provider here and the sink as
   // consumer.
-  int fifo_delay_milliseconds = 0;
-  scoped_ptr<media::AudioPullFifo> audio_fifo;
-  if (source_params.frames_per_buffer() != sink_params_.frames_per_buffer()) {
+  int new_fifo_delay_milliseconds = 0;
+  scoped_ptr<media::AudioPullFifo> new_audio_fifo;
+  if (source_params.frames_per_buffer() !=
+      new_sink_params.frames_per_buffer()) {
     DVLOG(1) << "Rebuffering from " << source_params.frames_per_buffer()
-             << " to " << sink_params_.frames_per_buffer();
-    audio_fifo.reset(new media::AudioPullFifo(
+             << " to " << new_sink_params.frames_per_buffer();
+    new_audio_fifo.reset(new media::AudioPullFifo(
         source_params.channels(), source_params.frames_per_buffer(),
         base::Bind(&WebRtcAudioRenderer::SourceCallback,
                    base::Unretained(this))));
 
-    if (sink_params.frames_per_buffer() > source_params.frames_per_buffer()) {
+    if (new_sink_params.frames_per_buffer() >
+        source_params.frames_per_buffer()) {
       int frame_duration_milliseconds =
           base::Time::kMillisecondsPerSecond /
           static_cast<double>(source_params.sample_rate());
-      fifo_delay_milliseconds = (sink_params_.frames_per_buffer() -
-                                 source_params.frames_per_buffer()) *
-                                frame_duration_milliseconds;
+      new_fifo_delay_milliseconds = (new_sink_params.frames_per_buffer() -
+                                     source_params.frames_per_buffer()) *
+                                    frame_duration_milliseconds;
     }
   }
 
   {
     base::AutoLock lock(lock_);
-    sink_params_ = sink_params;
-    fifo_delay_milliseconds_ = fifo_delay_milliseconds;
-    if (audio_fifo.get())
-      audio_fifo_ = audio_fifo.Pass();
+    sink_params_ = new_sink_params;
+    fifo_delay_milliseconds_ = new_fifo_delay_milliseconds;
+    if (new_audio_fifo.get())
+      audio_fifo_ = new_audio_fifo.Pass();
   }
 
-  sink_->Initialize(sink_params, this);
+  sink_->Initialize(new_sink_params, this);
 }
 
 }  // namespace content
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index c6c147e..64d5aa4 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -454,9 +454,6 @@
     const WebString& codecs,
     const WebString& key_system) {
   const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
-  // Not supporting the container is a flat-out no.
-  if (!media::IsSupportedMediaMimeType(mime_type_ascii))
-    return IsNotSupported;
 
   if (!key_system.isEmpty()) {
     // Check whether the key system is supported with the mime_type and codecs.
@@ -479,7 +476,6 @@
     // Continue processing the mime_type and codecs.
   }
 
-  // Check that codecs are appropriate for the container type.
   std::vector<std::string> codec_vector;
   media::ParseCodecString(ToASCIIOrEmpty(codecs), &codec_vector, false);
   return static_cast<WebMimeRegistry::SupportsType>(
diff --git a/content/renderer/shared_worker_repository.cc b/content/renderer/shared_worker_repository.cc
index 46dcb915..357cc951 100644
--- a/content/renderer/shared_worker_repository.cc
+++ b/content/renderer/shared_worker_repository.cc
@@ -26,8 +26,8 @@
     const blink::WebString& name,
     DocumentID document_id,
     const blink::WebString& content_security_policy,
-    blink::WebContentSecurityPolicyType security_policy_type) {
-  int route_id = MSG_ROUTING_NONE;
+    blink::WebContentSecurityPolicyType security_policy_type,
+    blink::WebWorkerCreationError* error) {
   ViewHostMsg_CreateWorker_Params params;
   params.url = url;
   params.name = name;
@@ -35,13 +35,15 @@
   params.security_policy_type = security_policy_type;
   params.document_id = document_id;
   params.render_frame_route_id = render_frame()->GetRoutingID();
-  Send(new ViewHostMsg_CreateWorker(params, &route_id));
-  if (route_id == MSG_ROUTING_NONE)
+  ViewHostMsg_CreateWorker_Reply reply;
+  Send(new ViewHostMsg_CreateWorker(params, &reply));
+  if (reply.route_id == MSG_ROUTING_NONE) {
+    *error = reply.error;
     return NULL;
+  }
   documents_with_workers_.insert(document_id);
   return new WebSharedWorkerProxy(ChildThreadImpl::current()->GetRouter(),
-                                  document_id,
-                                  route_id,
+                                  document_id, reply.route_id,
                                   params.render_frame_route_id);
 }
 
diff --git a/content/renderer/shared_worker_repository.h b/content/renderer/shared_worker_repository.h
index 67fbd90..004398d3 100644
--- a/content/renderer/shared_worker_repository.h
+++ b/content/renderer/shared_worker_repository.h
@@ -28,7 +28,8 @@
       const blink::WebString& name,
       DocumentID document_id,
       const blink::WebString& content_security_policy,
-      blink::WebContentSecurityPolicyType) override;
+      blink::WebContentSecurityPolicyType,
+      blink::WebWorkerCreationError* error) override;
   void documentDetached(DocumentID document_id) override;
 
  private:
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 674f7cf..804da0b 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -441,17 +441,15 @@
             "//content")
     sources -=
         [ "../browser/battery_status/battery_monitor_impl_browsertest.cc" ]
-    deps -= [ "//device/battery" ]
     deps += [
+      ":content_browsertests_java",
+      ":content_browsertests_manifest",
       "//content/shell:content_shell_lib",
+      "//content/shell/android:content_shell_assets",
       "//content/shell/android:content_shell_jni_headers",
       "//testing/android/native_test:native_test_support",
     ]
-    apk_deps = [
-      ":content_browsertests_java",
-      ":content_browsertests_manifest",
-      "//content/shell/android:content_shell_assets",
-    ]
+    deps -= [ "//device/battery" ]
     android_manifest =
         "${target_gen_dir}/content_browsertests_manifest/AndroidManifest.xml"
     isolate_file = "//content/content_browsertests.isolate"
@@ -708,7 +706,7 @@
     ]
     deps -= [ "//device/battery" ]
 
-    apk_deps = [
+    deps += [
       "//base:base_java_unittest_support",
       "//content/public/android:content_java",
       "//v8:v8_external_startup_data_assets",
@@ -830,7 +828,7 @@
   ]
 
   if (is_android) {
-    apk_deps = [
+    deps += [
       "//content/public/test/android:content_java_test_support",
       "//content/shell/android:content_shell_assets",
     ]
@@ -896,10 +894,8 @@
       deps += [
         "//gpu:test_support",
         "//media/base/android",
-        "//testing/gmock",
-      ]
-      apk_deps = [
         "//media/base/android:media_java",
+        "//testing/gmock",
         "//ui/android:ui_java",
       ]
     }
diff --git a/dbus/file_descriptor.cc b/dbus/file_descriptor.cc
index c740f28..b6908817 100644
--- a/dbus/file_descriptor.cc
+++ b/dbus/file_descriptor.cc
@@ -21,9 +21,8 @@
       FROM_HERE, base::Bind(&base::DeletePointer<FileDescriptor>, fd), false);
 }
 
-FileDescriptor::FileDescriptor(RValue other)
-    : value_(-1), owner_(false), valid_(false) {
-  Swap(other.object);
+FileDescriptor::FileDescriptor(FileDescriptor&& other) : FileDescriptor() {
+  Swap(&other);
 }
 
 FileDescriptor::~FileDescriptor() {
@@ -31,8 +30,8 @@
     base::File auto_closer(value_);
 }
 
-FileDescriptor& FileDescriptor::operator=(RValue other) {
-  Swap(other.object);
+FileDescriptor& FileDescriptor::operator=(FileDescriptor&& other) {
+  Swap(&other);
   return *this;
 }
 
diff --git a/dbus/file_descriptor.h b/dbus/file_descriptor.h
index 8a41097..41f7b4e 100644
--- a/dbus/file_descriptor.h
+++ b/dbus/file_descriptor.h
@@ -34,7 +34,7 @@
 // also allows the caller to do this work on the File thread to conform
 // with i/o restrictions.
 class CHROME_DBUS_EXPORT FileDescriptor {
-  MOVE_ONLY_TYPE_FOR_CPP_03(FileDescriptor, RValue);
+  MOVE_ONLY_TYPE_FOR_CPP_03(FileDescriptor);
 
  public:
   // This provides a simple way to pass around file descriptors since they must
@@ -49,13 +49,11 @@
   explicit FileDescriptor(int value) : value_(value), owner_(false),
       valid_(false) {}
 
-  // Move constructor for C++03 move emulation of this type.
-  FileDescriptor(RValue other);
+  FileDescriptor(FileDescriptor&& other);
 
   virtual ~FileDescriptor();
 
-  // Move operator= for C++03 move emulation of this type.
-  FileDescriptor& operator=(RValue other);
+  FileDescriptor& operator=(FileDescriptor&& other);
 
   // Retrieves value as an int without affecting ownership.
   int value() const;
diff --git a/device/BUILD.gn b/device/BUILD.gn
index e4f56a50..5c53606 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -138,9 +138,11 @@
 
   if (is_android) {
     sources -= [ "battery/battery_status_service_unittest.cc" ]
+    deps += [
+      ":bluetooth_test_java",
+      ":bluetooth_test_jni_headers",
+    ]
     deps -= [ "//device/battery" ]
-    deps += [ ":bluetooth_test_jni_headers" ]
-    apk_deps = [ ":bluetooth_test_java" ]
   }
 
   if (is_chromeos) {
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 8244ec63..7193022c 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -127,6 +127,7 @@
     "command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc",
     "command_buffer/tests/gl_cube_map_texture_unittest.cc",
     "command_buffer/tests/gl_depth_texture_unittest.cc",
+    "command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc",
     "command_buffer/tests/gl_ext_srgb_unittest.cc",
     "command_buffer/tests/gl_fence_sync_unittest.cc",
     "command_buffer/tests/gl_gpu_memory_buffer_unittest.cc",
@@ -176,7 +177,7 @@
 
   if (is_android) {
     libs += [ "android" ]
-    apk_deps = [ "//ui/android:ui_java" ]
+    deps += [ "//ui/android:ui_java" ]
   }
 }
 
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h
index c823b19..64147b4 100644
--- a/gpu/GLES2/gl2extchromium.h
+++ b/gpu/GLES2/gl2extchromium.h
@@ -1163,6 +1163,12 @@
 
 #endif /* GL_CHROMIUM_path_rendering */
 
+#ifndef GL_EXT_multisample_compatibility
+#define GL_EXT_multisample_compatibility 1
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#endif /* GL_EXT_multisample_compatiblity */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 0d8b7df..67579a0 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -84,6 +84,10 @@
    'state_flag': 'framebuffer_state_.clear_state_dirty'},
   {'name': 'rasterizer_discard', 'es3': True},
   {'name': 'primitive_restart_fixed_index', 'es3': True},
+  {'name': 'multisample_ext', 'default': True,
+   'extension_flag': 'ext_multisample_compatibility'},
+  {'name': 'sample_alpha_to_one_ext',
+   'extension_flag': 'ext_multisample_compatibility'},
 ]
 
 _STATES = {
@@ -1077,9 +1081,11 @@
   'Capability': {
     'type': 'GLenum',
     'valid': ["GL_%s" % cap['name'].upper() for cap in _CAPABILITY_FLAGS
-        if 'es3' not in cap or cap['es3'] != True],
+        if ('es3' not in cap or cap['es3'] != True)
+              and 'extension_flag' not in cap],
     'valid_es3': ["GL_%s" % cap['name'].upper() for cap in _CAPABILITY_FLAGS
-        if 'es3' in cap and cap['es3'] == True],
+        if ('es3' in cap and cap['es3'] == True)
+              and 'extension_flag' not in cap],
     'invalid': [
       'GL_CLIP_PLANE0',
       'GL_POINT_SPRITE',
@@ -10015,6 +10021,8 @@
       f.write("struct EnableFlags {\n")
       f.write("  EnableFlags();\n")
       for capability in _CAPABILITY_FLAGS:
+        if 'extension_flag' in capability:
+          continue
         f.write("  bool %s;\n" % capability['name'])
       f.write("};\n\n")
     self.generated_cpp_filenames.append(filename)
@@ -10120,6 +10128,9 @@
           capability_es3 = 'es3' in capability and capability['es3'] == True
           if capability_es3 and not es3_caps or not capability_es3 and es3_caps:
             continue
+          if 'extension_flag' in capability:
+            f.write("  if (feature_info_->feature_flags().%s) {\n  " %
+                       capability['extension_flag'])
           if test_prev:
             f.write("""  if (prev_state->enable_flags.cached_%s !=
                                 enable_flags.cached_%s) {\n""" %
@@ -10128,6 +10139,8 @@
                      (capability_name.upper(), capability_name))
           if test_prev:
             f.write("  }")
+          if 'extension_flag' in capability:
+            f.write("  }")
 
       f.write("  if (prev_state) {")
       WriteCapabilities(True, False)
@@ -10253,6 +10266,8 @@
     with CHeaderWriter(filename, comment) as f:
       code = []
       for capability in _CAPABILITY_FLAGS:
+        if 'extension_flag' in capability:
+          continue
         code.append("%s(%s)" %
                     (capability['name'],
                      ('false', 'true')['default' in capability]))
@@ -10268,6 +10283,8 @@
   switch (cap) {
 """)
       for capability in _CAPABILITY_FLAGS:
+        if 'extension_flag' in capability:
+          continue
         f.write("    case GL_%s:\n" % capability['name'].upper())
         f.write("""      if (enable_flags.%(name)s != enabled) {
          *changed = true;
@@ -10285,6 +10302,8 @@
   switch (cap) {
 """)
       for capability in _CAPABILITY_FLAGS:
+        if 'extension_flag' in capability:
+          continue
         f.write("    case GL_%s:\n" % capability['name'].upper())
         f.write("      *enabled = enable_flags.%s;\n" % capability['name'])
         f.write("      return true;\n")
@@ -10380,11 +10399,17 @@
       bool es3_capable) {""")
       for capability in _CAPABILITY_FLAGS:
         capability_es3 = 'es3' in capability and capability['es3'] == True
-        if not capability_es3:
-          f.write("  ExpectEnableDisable(GL_%s, %s);\n" %
-                     (capability['name'].upper(),
-                      ('false', 'true')['default' in capability]))
-
+        if capability_es3:
+          continue
+        if 'extension_flag' in capability:
+          f.write("  if (group_->feature_info()->feature_flags().%s) {\n" %
+                   capability['extension_flag'])
+          f.write("  ")
+        f.write("  ExpectEnableDisable(GL_%s, %s);\n" %
+                (capability['name'].upper(),
+                 ('false', 'true')['default' in capability]))
+        if 'extension_flag' in capability:
+          f.write("  }")
       f.write("  if (es3_capable) {")
       for capability in _CAPABILITY_FLAGS:
         capability_es3 = 'es3' in capability and capability['es3'] == True
@@ -11023,6 +11048,8 @@
         if not item['enum'] in gl_state_valid:
           gl_state_valid.append(item['enum'])
   for capability in _CAPABILITY_FLAGS:
+    if 'extension_flag' in capability:
+      continue
     valid_value = "GL_%s" % capability['name'].upper()
     if not valid_value in gl_state_valid:
       gl_state_valid.append(valid_value)
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
index 411d7b4..b84fbb0 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -745,9 +745,15 @@
         0x8074, "GL_VERTEX_ARRAY_KHR",
     },
     {
+        0x809D, "GL_MULTISAMPLE_EXT",
+    },
+    {
         0x809E, "GL_SAMPLE_ALPHA_TO_COVERAGE",
     },
     {
+        0x809F, "GL_SAMPLE_ALPHA_TO_ONE_EXT",
+    },
+    {
         0x80A0, "GL_SAMPLE_COVERAGE",
     },
     {
diff --git a/gpu/command_buffer/service/context_state_autogen.h b/gpu/command_buffer/service/context_state_autogen.h
index 7ca2faa..7278a24 100644
--- a/gpu/command_buffer/service/context_state_autogen.h
+++ b/gpu/command_buffer/service/context_state_autogen.h
@@ -36,6 +36,10 @@
   bool cached_rasterizer_discard;
   bool primitive_restart_fixed_index;
   bool cached_primitive_restart_fixed_index;
+  bool multisample_ext;
+  bool cached_multisample_ext;
+  bool sample_alpha_to_one_ext;
+  bool cached_sample_alpha_to_one_ext;
 };
 
 GLfloat blend_color_red;
@@ -169,6 +173,17 @@
         return;
       enable_flags.cached_primitive_restart_fixed_index = enable;
       break;
+    case GL_MULTISAMPLE_EXT:
+      if (enable_flags.cached_multisample_ext == enable && !ignore_cached_state)
+        return;
+      enable_flags.cached_multisample_ext = enable;
+      break;
+    case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+      if (enable_flags.cached_sample_alpha_to_one_ext == enable &&
+          !ignore_cached_state)
+        return;
+      enable_flags.cached_sample_alpha_to_one_ext = enable;
+      break;
     default:
       NOTREACHED();
       return;
diff --git a/gpu/command_buffer/service/context_state_impl_autogen.h b/gpu/command_buffer/service/context_state_impl_autogen.h
index 450f0e2..ce9f70f 100644
--- a/gpu/command_buffer/service/context_state_impl_autogen.h
+++ b/gpu/command_buffer/service/context_state_impl_autogen.h
@@ -34,7 +34,11 @@
       rasterizer_discard(false),
       cached_rasterizer_discard(false),
       primitive_restart_fixed_index(false),
-      cached_primitive_restart_fixed_index(false) {}
+      cached_primitive_restart_fixed_index(false),
+      multisample_ext(true),
+      cached_multisample_ext(true),
+      sample_alpha_to_one_ext(false),
+      cached_sample_alpha_to_one_ext(false) {}
 
 void ContextState::Initialize() {
   blend_color_red = 0.0f;
@@ -176,6 +180,19 @@
         enable_flags.cached_stencil_test) {
       EnableDisable(GL_STENCIL_TEST, enable_flags.cached_stencil_test);
     }
+    if (feature_info_->feature_flags().ext_multisample_compatibility) {
+      if (prev_state->enable_flags.cached_multisample_ext !=
+          enable_flags.cached_multisample_ext) {
+        EnableDisable(GL_MULTISAMPLE_EXT, enable_flags.cached_multisample_ext);
+      }
+    }
+    if (feature_info_->feature_flags().ext_multisample_compatibility) {
+      if (prev_state->enable_flags.cached_sample_alpha_to_one_ext !=
+          enable_flags.cached_sample_alpha_to_one_ext) {
+        EnableDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT,
+                      enable_flags.cached_sample_alpha_to_one_ext);
+      }
+    }
     if (feature_info_->IsES3Capable()) {
       if (prev_state->enable_flags.cached_rasterizer_discard !=
           enable_flags.cached_rasterizer_discard) {
@@ -200,6 +217,13 @@
     EnableDisable(GL_SAMPLE_COVERAGE, enable_flags.cached_sample_coverage);
     EnableDisable(GL_SCISSOR_TEST, enable_flags.cached_scissor_test);
     EnableDisable(GL_STENCIL_TEST, enable_flags.cached_stencil_test);
+    if (feature_info_->feature_flags().ext_multisample_compatibility) {
+      EnableDisable(GL_MULTISAMPLE_EXT, enable_flags.cached_multisample_ext);
+    }
+    if (feature_info_->feature_flags().ext_multisample_compatibility) {
+      EnableDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT,
+                    enable_flags.cached_sample_alpha_to_one_ext);
+    }
     if (feature_info_->IsES3Capable()) {
       EnableDisable(GL_RASTERIZER_DISCARD,
                     enable_flags.cached_rasterizer_discard);
@@ -408,6 +432,10 @@
       return enable_flags.rasterizer_discard;
     case GL_PRIMITIVE_RESTART_FIXED_INDEX:
       return enable_flags.primitive_restart_fixed_index;
+    case GL_MULTISAMPLE_EXT:
+      return enable_flags.multisample_ext;
+    case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+      return enable_flags.sample_alpha_to_one_ext;
     default:
       NOTREACHED();
       return false;
@@ -781,6 +809,18 @@
             static_cast<GLint>(enable_flags.primitive_restart_fixed_index);
       }
       return true;
+    case GL_MULTISAMPLE_EXT:
+      *num_written = 1;
+      if (params) {
+        params[0] = static_cast<GLint>(enable_flags.multisample_ext);
+      }
+      return true;
+    case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+      *num_written = 1;
+      if (params) {
+        params[0] = static_cast<GLint>(enable_flags.sample_alpha_to_one_ext);
+      }
+      return true;
     default:
       return false;
   }
@@ -1149,6 +1189,18 @@
             static_cast<GLfloat>(enable_flags.primitive_restart_fixed_index);
       }
       return true;
+    case GL_MULTISAMPLE_EXT:
+      *num_written = 1;
+      if (params) {
+        params[0] = static_cast<GLfloat>(enable_flags.multisample_ext);
+      }
+      return true;
+    case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+      *num_written = 1;
+      if (params) {
+        params[0] = static_cast<GLfloat>(enable_flags.sample_alpha_to_one_ext);
+      }
+      return true;
     default:
       return false;
   }
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index fdc16a25..90ddfdb4 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -174,7 +174,8 @@
       chromium_image_ycbcr_422(false),
       enable_subscribe_uniform(false),
       emulate_primitive_restart_fixed_index(false),
-      ext_render_buffer_format_bgra8888(false) {}
+      ext_render_buffer_format_bgra8888(false),
+      ext_multisample_compatibility(false) {}
 
 FeatureInfo::Workarounds::Workarounds() :
 #define GPU_OP(type, name) name(false),
@@ -798,6 +799,15 @@
     }
   }
 
+  if (!disable_all_multisample &&
+      (!gl_version_info_->is_es ||
+       extensions.Contains("GL_EXT_multisample_compatibility"))) {
+    AddExtensionString("GL_EXT_multisample_compatibility");
+    feature_flags_.ext_multisample_compatibility = true;
+    validators_.capability.AddValue(GL_MULTISAMPLE_EXT);
+    validators_.capability.AddValue(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+  }
+
   if (extensions.Contains("GL_INTEL_framebuffer_CMAA")) {
     feature_flags_.chromium_screen_space_antialiasing = true;
     AddExtensionString("GL_CHROMIUM_screen_space_antialiasing");
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index 653afd9..3258bdf 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -85,6 +85,7 @@
     bool enable_subscribe_uniform;
     bool emulate_primitive_restart_fixed_index;
     bool ext_render_buffer_format_bgra8888;
+    bool ext_multisample_compatibility;
   };
 
   struct Workarounds {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 892d6da..06194d8 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -5156,6 +5156,22 @@
         return true;
       }
       return false;
+    case GL_MULTISAMPLE_EXT:
+      state_.enable_flags.multisample_ext = enabled;
+      if (state_.enable_flags.cached_multisample_ext != enabled ||
+          state_.ignore_cached_state) {
+        state_.enable_flags.cached_multisample_ext = enabled;
+        return true;
+      }
+      return false;
+    case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+      state_.enable_flags.sample_alpha_to_one_ext = enabled;
+      if (state_.enable_flags.cached_sample_alpha_to_one_ext != enabled ||
+          state_.ignore_cached_state) {
+        state_.enable_flags.cached_sample_alpha_to_one_ext = enabled;
+        return true;
+      }
+      return false;
     default:
       NOTREACHED();
       return false;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
index dd117162..d934bce 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
@@ -22,6 +22,12 @@
   ExpectEnableDisable(GL_SAMPLE_COVERAGE, false);
   ExpectEnableDisable(GL_SCISSOR_TEST, false);
   ExpectEnableDisable(GL_STENCIL_TEST, false);
+  if (group_->feature_info()->feature_flags().ext_multisample_compatibility) {
+    ExpectEnableDisable(GL_MULTISAMPLE_EXT, true);
+  }
+  if (group_->feature_info()->feature_flags().ext_multisample_compatibility) {
+    ExpectEnableDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT, false);
+  }
   if (es3_capable) {
     ExpectEnableDisable(GL_RASTERIZER_DISCARD, false);
     ExpectEnableDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX, false);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
index b726ade4..c0b6de5 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
@@ -499,6 +499,27 @@
                         GLES2DecoderTestWithBlendEquationAdvanced,
                         ::testing::Bool());
 
+class GLES2DecoderTestWithEXTMultisampleCompatibility
+    : public GLES2DecoderTest {
+ public:
+  GLES2DecoderTestWithEXTMultisampleCompatibility() {}
+
+  void SetUp() override {
+    InitState init;
+    init.gl_version = "opengl es 3.1";
+    init.has_alpha = true;
+    init.has_depth = true;
+    init.request_alpha = true;
+    init.request_depth = true;
+    init.bind_generates_resource = true;
+    init.extensions = "GL_EXT_multisample_compatibility ";
+    InitDecoder(init);
+  }
+};
+INSTANTIATE_TEST_CASE_P(Service,
+                        GLES2DecoderTestWithEXTMultisampleCompatibility,
+                        ::testing::Bool());
+
 TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, GenDeletePaths) {
   static GLuint kFirstClientID = client_path_id_ + 88;
   static GLsizei kPathCount = 58;
@@ -1665,4 +1686,3 @@
 
 }  // namespace gles2
 }  // namespace gpu
-
diff --git a/gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc b/gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc
index 9d36a26f..8268b668 100644
--- a/gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc
+++ b/gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc
@@ -44,7 +44,8 @@
 }
 
 TEST_F(GLChromiumFramebufferMultisampleTest, DrawAndResolve) {
-  if (!GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample")) {
+  if (!(GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample") &&
+        GLTestHelper::HasExtension("GL_OES_rgb8_rgba8"))) {
     return;
   }
 
diff --git a/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc b/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc
index 6243ea3..2120c81ed 100644
--- a/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc
+++ b/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc
@@ -1196,9 +1196,8 @@
   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
 }
 
-// Fails on Nexus 9
 TEST_P(CHROMIUMPathRenderingWithTexturingTest,
-       DISABLED_TestProgramPathFragmentInputGenArgs) {
+       TestProgramPathFragmentInputGenArgs) {
   if (!IsApplicable())
     return;
 
diff --git a/gpu/command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc b/gpu/command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc
new file mode 100644
index 0000000..37fc923
--- /dev/null
+++ b/gpu/command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc
@@ -0,0 +1,242 @@
+// Copyright (c) 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 <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES2/gl2extchromium.h>
+
+#include "gpu/command_buffer/tests/gl_manager.h"
+#include "gpu/command_buffer/tests/gl_test_utils.h"
+#include "gpu/config/gpu_test_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define SHADER0(Src) #Src
+
+namespace gpu {
+
+class EXTMultisampleCompatibilityTest : public testing::Test {
+ public:
+ protected:
+  static const GLuint kWidth = 100;
+  static const GLuint kHeight = 100;
+
+  void SetUp() override { gl_.Initialize(GLManager::Options()); }
+
+  void TearDown() override { gl_.Destroy(); }
+
+  void PrepareForDraw() {
+    static const char* v_shader_str = SHADER0(
+        attribute vec4 a_Position; void main() { gl_Position = a_Position; });
+    static const char* f_shader_str =
+        SHADER0(precision mediump float; uniform vec4 color;
+                void main() { gl_FragColor = color; });
+
+    GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
+    glUseProgram(program);
+    GLuint position_loc = glGetAttribLocation(program, "a_Position");
+    color_loc_ = glGetUniformLocation(program, "color");
+
+    GLuint vbo = 0;
+    glGenBuffers(1, &vbo);
+    glBindBuffer(GL_ARRAY_BUFFER, vbo);
+    static float vertices[] = {
+        1.0f,  1.0f, -1.0f, 1.0f,  -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
+        -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f,  -1.0f, 1.0f, 1.0f,
+    };
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+    glEnableVertexAttribArray(position_loc);
+    glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+    // Create a sample buffer.
+    GLsizei num_samples = 4, max_samples = 0;
+    glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+    num_samples = std::min(num_samples, max_samples);
+    GLuint sample_rb;
+    glGenRenderbuffers(1, &sample_rb);
+    glBindRenderbuffer(GL_RENDERBUFFER, sample_rb);
+    glRenderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, num_samples,
+                                             GL_RGBA8_OES, kWidth, kHeight);
+    GLint param = 0;
+    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
+                                 &param);
+    EXPECT_GE(param, num_samples);
+
+    glGenFramebuffers(1, &sample_fbo_);
+    glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo_);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                              GL_RENDERBUFFER, sample_rb);
+    EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+              glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    // Create another FBO to resolve the multisample buffer into.
+    GLuint resolve_tex;
+    glGenTextures(1, &resolve_tex);
+    glBindTexture(GL_TEXTURE_2D, resolve_tex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, NULL);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glGenFramebuffers(1, &resolve_fbo_);
+    glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo_);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                           resolve_tex, 0);
+    EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+              glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    glViewport(0, 0, kWidth, kHeight);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glEnable(GL_BLEND);
+    glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo_);
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+  }
+
+  void PrepareForVerify() {
+    // Resolve.
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, sample_fbo_);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo_);
+    glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glBlitFramebufferCHROMIUM(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
+                              GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo_);
+  }
+
+  bool IsApplicable() const {
+    return GLTestHelper::HasExtension("GL_EXT_multisample_compatibility") &&
+           GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample") &&
+           GLTestHelper::HasExtension("GL_OES_rgb8_rgba8") &&
+           !GPUTestBotConfig::CurrentConfigMatches("AMD");
+  }
+  GLuint sample_fbo_;
+  GLuint resolve_fbo_;
+  GLuint color_loc_;
+
+  GLManager gl_;
+};
+
+TEST_F(EXTMultisampleCompatibilityTest, TestSimple) {
+  if (!IsApplicable()) {
+    return;
+  }
+
+  EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
+  glDisable(GL_MULTISAMPLE_EXT);
+  EXPECT_FALSE(glIsEnabled(GL_MULTISAMPLE_EXT));
+  glEnable(GL_MULTISAMPLE_EXT);
+  EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
+
+  EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
+  glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+  EXPECT_TRUE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
+  glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+  EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
+
+  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+TEST_F(EXTMultisampleCompatibilityTest, DrawAndResolve) {
+  // Test that disabling GL_MULTISAMPLE_EXT is handled correctly.
+  if (!IsApplicable()) {
+    return;
+  }
+
+  static const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
+  static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+  static const float kRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
+
+  // Different drivers seem to behave differently with respect to resulting
+  // values. These might be due to different MSAA sample counts causing
+  // different samples to hit.  Other option is driver bugs. Just test that
+  // disabling multisample causes a difference.
+  scoped_ptr<uint8[]> results[3];
+  const GLint kResultSize = kWidth * kHeight * 4;
+  for (int pass = 0; pass < 3; pass++) {
+    PrepareForDraw();
+    // Green: from top right to bottom left.
+    glUniform4fv(color_loc_, 1, kGreen);
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    // Blue: from top left to bottom right.
+    glUniform4fv(color_loc_, 1, kBlue);
+    glDrawArrays(GL_TRIANGLES, 3, 3);
+
+    // Red, with and without MSAA: from bottom left to top right.
+    if (pass == 1) {
+      glDisable(GL_MULTISAMPLE_EXT);
+    }
+    glUniform4fv(color_loc_, 1, kRed);
+    glDrawArrays(GL_TRIANGLES, 6, 3);
+    if (pass == 1) {
+      glEnable(GL_MULTISAMPLE_EXT);
+    }
+    PrepareForVerify();
+    results[pass].reset(new uint8[kResultSize]);
+    memset(results[pass].get(), GLTestHelper::kCheckClearValue, kResultSize);
+    glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
+                 results[pass].get());
+  }
+  EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
+  // Verify that rendering is deterministic, so that the pass above does not
+  // come from non-deterministic rendering.
+  EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
+}
+
+TEST_F(EXTMultisampleCompatibilityTest, DrawAlphaOneAndResolve) {
+  // Test that enabling GL_SAMPLE_ALPHA_TO_ONE_EXT affects rendering.
+  if (!IsApplicable()) {
+    return;
+  }
+
+  // SAMPLE_ALPHA_TO_ONE is specified to transform alpha values of
+  // covered samples to 1.0. In order to detect it, we use non-1.0
+  // alpha.
+  static const float kBlue[] = {0.0f, 0.0f, 1.0f, 0.5f};
+  static const float kGreen[] = {0.0f, 1.0f, 0.0f, 0.5f};
+  static const float kRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
+
+  // Different drivers seem to behave differently with respect to resulting
+  // alpha value. These might be due to different MSAA sample counts causing
+  // different samples to hit.  Other option is driver bugs. Testing exact or
+  // even approximate sample values is not that easy.  Thus, just test
+  // representative positions which have fractional pixels, inspecting that
+  // normal rendering is different to SAMPLE_ALPHA_TO_ONE rendering.
+  scoped_ptr<uint8[]> results[3];
+  const GLint kResultSize = kWidth * kHeight * 4;
+
+  for (int pass = 0; pass < 3; ++pass) {
+    PrepareForDraw();
+    if (pass == 1) {
+      glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+    }
+    glEnable(GL_MULTISAMPLE_EXT);
+    glUniform4fv(color_loc_, 1, kGreen);
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    glUniform4fv(color_loc_, 1, kBlue);
+    glDrawArrays(GL_TRIANGLES, 3, 3);
+
+    glDisable(GL_MULTISAMPLE_EXT);
+    glUniform4fv(color_loc_, 1, kRed);
+    glDrawArrays(GL_TRIANGLES, 6, 3);
+
+    PrepareForVerify();
+    results[pass].reset(new uint8[kResultSize]);
+    memset(results[pass].get(), GLTestHelper::kCheckClearValue, kResultSize);
+    glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
+                 results[pass].get());
+    if (pass == 1) {
+      glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+    }
+  }
+  EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
+  // Verify that rendering is deterministic, so that the pass above does not
+  // come from non-deterministic rendering.
+  EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
+}
+
+}  // namespace gpu
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 04af4a9..ba1ad9a 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@
 {
   "name": "gpu driver bug list",
   // Please update the version number whenever you change this file.
-  "version": "8.34",
+  "version": "8.35",
   "entries": [
     {
       "id": 1,
@@ -1622,6 +1622,22 @@
       "features": [
         "force_cube_complete"
       ]
+    },
+    {
+      "id": 138,
+      "description": "NVIDIA drivers before 346 lack features in NV_path_rendering and related extensions to implement driver level path rendering.",
+      "cr_bugs": [344330],
+      "os": {
+        "type": "android"
+      },
+      "gl_vendor": "NVIDIA.*",
+      "driver_version": {
+        "op": "<",
+        "value": "346"
+      },
+      "features": [
+        "disable_gl_path_rendering"
+      ]
     }
   ]
 }
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 777c61d..68aaaff 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -367,6 +367,7 @@
         'command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc',
         'command_buffer/tests/gl_cube_map_texture_unittest.cc',
         'command_buffer/tests/gl_depth_texture_unittest.cc',
+        'command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc',	
         'command_buffer/tests/gl_ext_srgb_unittest.cc',
         'command_buffer/tests/gl_fence_sync_unittest.cc',
         'command_buffer/tests/gl_gpu_memory_buffer_unittest.cc',
diff --git a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.cc b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.cc
index ee4e2b4..3140ee2 100644
--- a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.cc
+++ b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.cc
@@ -26,9 +26,11 @@
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/sessions/core/tab_restore_service.h"
+#include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
 #include "ios/chrome/browser/history/history_service_factory.h"
 #include "ios/chrome/browser/history/web_history_service_factory.h"
+#include "ios/chrome/browser/ios_chrome_io_thread.h"
 #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
 #include "ios/chrome/browser/pref_names.h"
 #include "ios/chrome/browser/search_engines/template_url_service_factory.h"
@@ -36,7 +38,6 @@
 #include "ios/chrome/browser/web_data_service_factory.h"
 #include "ios/net/http_cache_helper.h"
 #include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/public/provider/chrome/browser/browsing_data/ios_chrome_browsing_data_remover_provider.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 #include "ios/public/provider/chrome/browser/keyed_service_provider.h"
 #include "ios/web/public/user_metrics.h"
@@ -48,7 +49,6 @@
 #include "net/ssl/channel_id_store.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
-#include "url/origin.h"
 
 using base::UserMetricsAction;
 using web::WebThread;
@@ -110,9 +110,7 @@
     : browser_state_(browser_state),
       delete_begin_(delete_begin),
       delete_end_(delete_end),
-      main_context_getter_(browser_state->GetRequestContext()),
-      provider_(ios::GetChromeBrowserProvider()
-                    ->GetIOSChromeBrowsingDataRemoverProvider(browser_state)) {
+      main_context_getter_(browser_state->GetRequestContext()) {
   DCHECK(browser_state);
   // crbug.com/140910: Many places were calling this with base::Time() as
   // delete_end, even though they should've used base::Time::Max(). Work around
@@ -141,7 +139,6 @@
   DCHECK_CURRENTLY_ON_WEB_THREAD(WebThread::UI);
   set_removing(true);
   remove_mask_ = remove_mask;
-  url::Origin remove_origin(remove_url);
 
   PrefService* prefs = browser_state_->GetPrefs();
   bool may_delete_history =
@@ -181,10 +178,18 @@
     // Need to clear the host cache and accumulated speculative data, as it also
     // reveals some history: we have no mechanism to track when these items were
     // created, so we'll clear them all. Better safe than sorry.
-    waiting_for_clear_hostname_resolution_cache_ = true;
-    provider_->ClearHostnameResolutionCache(base::Bind(
-        &IOSChromeBrowsingDataRemover::OnClearedHostnameResolutionCache,
-        base::Unretained(this)));
+    IOSChromeIOThread* ios_chrome_io_thread =
+        GetApplicationContext()->GetIOSChromeIOThread();
+    if (ios_chrome_io_thread) {
+      waiting_for_clear_hostname_resolution_cache_ = true;
+      web::WebThread::PostTaskAndReply(
+          web::WebThread::IO, FROM_HERE,
+          base::Bind(&IOSChromeIOThread::ClearHostCache,
+                     base::Unretained(ios_chrome_io_thread)),
+          base::Bind(
+              &IOSChromeBrowsingDataRemover::OnClearedHostnameResolutionCache,
+              base::Unretained(this)));
+    }
 
     // As part of history deletion we also delete the auto-generated keywords.
     // Because the TemplateURLService is shared between incognito and
@@ -266,33 +271,36 @@
     // hours/days to the safebrowsing cookies since they aren't the result of
     // any user action.
     if (delete_begin_ == base::Time()) {
-      net::URLRequestContextGetter* safe_browsing_context =
-          provider_->GetSafeBrowsingURLRequestContext();
+      scoped_refptr<net::URLRequestContextGetter> safe_browsing_context =
+          make_scoped_refptr(ios::GetChromeBrowserProvider()
+                                 ->GetSafeBrowsingURLRequestContext());
       if (safe_browsing_context) {
         ++waiting_for_clear_cookies_count_;
         WebThread::PostTask(
             WebThread::IO, FROM_HERE,
             base::Bind(&IOSChromeBrowsingDataRemover::ClearCookiesOnIOThread,
-                       base::Unretained(this),
-                       base::Unretained(safe_browsing_context)));
+                       base::Unretained(this), safe_browsing_context, GURL()));
       }
     }
 
+    ++waiting_for_clear_cookies_count_;
+    WebThread::PostTask(
+        WebThread::IO, FROM_HERE,
+        base::Bind(&IOSChromeBrowsingDataRemover::ClearCookiesOnIOThread,
+                   base::Unretained(this), main_context_getter_, remove_url));
+
     // TODO(mkwst): If we're not removing passwords, then clear the 'zero-click'
     // flag for all credentials in the password store.
   }
 
   if (remove_mask & REMOVE_CHANNEL_IDS) {
     web::RecordAction(UserMetricsAction("ClearBrowsingData_ChannelIDs"));
-    // Since we are running on the UI thread don't call GetURLRequestContext().
-    net::URLRequestContextGetter* rq_context =
-        browser_state_->GetRequestContext();
-    if (rq_context) {
+    if (main_context_getter_) {
       waiting_for_clear_channel_ids_ = true;
       WebThread::PostTask(
           WebThread::IO, FROM_HERE,
           base::Bind(&IOSChromeBrowsingDataRemover::ClearChannelIDsOnIOThread,
-                     base::Unretained(this), base::Unretained(rq_context)));
+                     base::Unretained(this), main_context_getter_));
     }
   }
 
@@ -345,18 +353,10 @@
     DCHECK(delete_begin_.is_null()) << "Partial clearing not supported";
     ClearHttpCache(browser_state_->GetRequestContext(),
                    WebThread::GetTaskRunnerForThread(WebThread::IO),
-                   base::Bind(&IOSChromeBrowsingDataRemover::ClearedCache,
+                   base::Bind(&IOSChromeBrowsingDataRemover::OnClearedCache,
                               base::Unretained(this)));
   }
 
-  if (remove_mask & REMOVE_COOKIES) {
-    waiting_for_clear_storage_partition_data_ = true;
-    provider_->ClearStoragePartition(
-        remove_url, delete_begin_, delete_end_,
-        base::Bind(&IOSChromeBrowsingDataRemover::OnClearedStoragePartitionData,
-                   base::Unretained(this)));
-  }
-
   // Remove omnibox zero-suggest cache results.
   if ((remove_mask & (REMOVE_CACHE | REMOVE_COOKIES)))
     prefs->SetString(omnibox::kZeroSuggestCachedResults, std::string());
@@ -418,8 +418,7 @@
          !waiting_for_clear_hostname_resolution_cache_ &&
          !waiting_for_clear_keyword_data_ &&
          !waiting_for_clear_networking_history_ &&
-         !waiting_for_clear_passwords_ &&
-         !waiting_for_clear_storage_partition_data_;
+         !waiting_for_clear_passwords_;
 }
 
 void IOSChromeBrowsingDataRemover::OnKeywordsLoaded() {
@@ -473,7 +472,7 @@
   NotifyAndDeleteIfDone();
 }
 
-void IOSChromeBrowsingDataRemover::ClearedCache(int error) {
+void IOSChromeBrowsingDataRemover::OnClearedCache(int error) {
   waiting_for_clear_cache_ = false;
 
   NotifyAndDeleteIfDone();
@@ -500,29 +499,37 @@
 }
 
 void IOSChromeBrowsingDataRemover::ClearCookiesOnIOThread(
-    net::URLRequestContextGetter* rq_context) {
+    const scoped_refptr<net::URLRequestContextGetter>& rq_context,
+    const GURL& storage_url) {
   DCHECK_CURRENTLY_ON_WEB_THREAD(WebThread::IO);
   net::CookieStore* cookie_store =
       rq_context->GetURLRequestContext()->cookie_store();
-  cookie_store->DeleteAllCreatedBetweenAsync(
-      delete_begin_, delete_end_,
-      base::Bind(&IOSChromeBrowsingDataRemover::OnClearedCookies,
-                 base::Unretained(this)));
+  if (storage_url.is_empty()) {
+    cookie_store->DeleteAllCreatedBetweenAsync(
+        delete_begin_, delete_end_,
+        base::Bind(&IOSChromeBrowsingDataRemover::OnClearedCookies,
+                   base::Unretained(this)));
+  } else {
+    cookie_store->DeleteAllCreatedBetweenForHostAsync(
+        delete_begin_, delete_end_, storage_url,
+        base::Bind(&IOSChromeBrowsingDataRemover::OnClearedCookies,
+                   base::Unretained(this)));
+  }
 }
 
 void IOSChromeBrowsingDataRemover::ClearChannelIDsOnIOThread(
-    net::URLRequestContextGetter* rq_context) {
+    const scoped_refptr<net::URLRequestContextGetter>& rq_context) {
   DCHECK_CURRENTLY_ON_WEB_THREAD(WebThread::IO);
   net::ChannelIDService* channel_id_service =
       rq_context->GetURLRequestContext()->channel_id_service();
   channel_id_service->GetChannelIDStore()->DeleteAllCreatedBetween(
       delete_begin_, delete_end_,
       base::Bind(&IOSChromeBrowsingDataRemover::OnClearedChannelIDsOnIOThread,
-                 base::Unretained(this), base::Unretained(rq_context)));
+                 base::Unretained(this), rq_context));
 }
 
 void IOSChromeBrowsingDataRemover::OnClearedChannelIDsOnIOThread(
-    net::URLRequestContextGetter* rq_context) {
+    const scoped_refptr<net::URLRequestContextGetter>& rq_context) {
   // Need to close open SSL connections which may be using the channel ids we
   // are deleting.
   // TODO(mattm): http://crbug.com/166069 Make the server bound cert
@@ -554,12 +561,6 @@
   NotifyAndDeleteIfDone();
 }
 
-void IOSChromeBrowsingDataRemover::OnClearedStoragePartitionData() {
-  DCHECK_CURRENTLY_ON_WEB_THREAD(WebThread::UI);
-  waiting_for_clear_storage_partition_data_ = false;
-  NotifyAndDeleteIfDone();
-}
-
 // static
 IOSChromeBrowsingDataRemover::CallbackSubscription
 IOSChromeBrowsingDataRemover::RegisterOnBrowsingDataRemovedCallback(
diff --git a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h
index 6f14bc4..aaf15d2 100644
--- a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h
+++ b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h
@@ -21,7 +21,6 @@
 
 namespace ios {
 class ChromeBrowserState;
-class IOSChromeBrowsingDataRemoverProvider;
 }
 
 namespace net {
@@ -189,7 +188,7 @@
 
   // Callback for when the cache has been deleted. Invokes
   // NotifyAndDeleteIfDone.
-  void ClearedCache(int error);
+  void OnClearedCache(int error);
 
   // Callback for when passwords for the requested time range have been cleared.
   void OnClearedPasswords();
@@ -198,14 +197,18 @@
   void OnClearedCookies(int num_deleted);
 
   // Invoked on the IO thread to delete cookies.
-  void ClearCookiesOnIOThread(net::URLRequestContextGetter* rq_context);
+  void ClearCookiesOnIOThread(
+      const scoped_refptr<net::URLRequestContextGetter>& rq_context,
+      const GURL& storage_url);
 
   // Invoked on the IO thread to delete channel IDs.
-  void ClearChannelIDsOnIOThread(net::URLRequestContextGetter* rq_context);
+  void ClearChannelIDsOnIOThread(
+      const scoped_refptr<net::URLRequestContextGetter>& rq_context);
 
   // Callback on IO Thread when channel IDs have been deleted. Clears SSL
   // connection pool and posts to UI thread to run OnClearedChannelIDs.
-  void OnClearedChannelIDsOnIOThread(net::URLRequestContextGetter* rq_context);
+  void OnClearedChannelIDsOnIOThread(
+      const scoped_refptr<net::URLRequestContextGetter>& rq_context);
 
   // Callback for when channel IDs have been deleted. Invokes
   // NotifyAndDeleteIfDone.
@@ -218,9 +221,6 @@
   // been deleted.
   void OnClearedAutofillOriginURLs();
 
-  // Callback on UI thread when the storage partition related data are cleared.
-  void OnClearedStoragePartitionData();
-
   void OnClearedDomainReliabilityMonitor();
 
   // Returns true if we're all done.
@@ -254,7 +254,6 @@
   bool waiting_for_clear_keyword_data_ = false;
   bool waiting_for_clear_networking_history_ = false;
   bool waiting_for_clear_passwords_ = false;
-  bool waiting_for_clear_storage_partition_data_ = false;
 
   // The removal mask for the current removal operation.
   int remove_mask_ = 0;
@@ -266,10 +265,6 @@
 
   scoped_ptr<TemplateURLService::Subscription> template_url_sub_;
 
-  // Object that supports legacy functionality and functionality that has not
-  // yet been ported to //ios/chrome.
-  scoped_ptr<ios::IOSChromeBrowsingDataRemoverProvider> provider_;
-
   DISALLOW_COPY_AND_ASSIGN(IOSChromeBrowsingDataRemover);
 };
 
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm
index a1fd050..d9a0584 100644
--- a/ios/chrome/browser/prefs/browser_prefs.mm
+++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -10,6 +10,7 @@
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
 #include "components/dom_distiller/core/distilled_page_prefs.h"
 #include "components/enhanced_bookmarks/bookmark_server_cluster_service.h"
+#include "components/flags_ui/pref_service_flags_storage.h"
 #include "components/gcm_driver/gcm_channel_status_syncer.h"
 #include "components/network_time/network_time_tracker.h"
 #include "components/omnibox/browser/zero_suggest_provider.h"
@@ -49,6 +50,7 @@
 
 void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
   BrowserStateInfoCache::RegisterPrefs(registry);
+  flags_ui::PrefServiceFlagsStorage::RegisterPrefs(registry);
   gcm::GCMChannelStatusSyncer::RegisterPrefs(registry);
   ios::SigninManagerFactory::RegisterPrefs(registry);
   IOSChromeMetricsServiceClient::RegisterPrefs(registry);
diff --git a/ios/public/provider/chrome/browser/browsing_data/ios_chrome_browsing_data_remover_provider.h b/ios/public/provider/chrome/browser/browsing_data/ios_chrome_browsing_data_remover_provider.h
deleted file mode 100644
index 692ebed..0000000
--- a/ios/public/provider/chrome/browser/browsing_data/ios_chrome_browsing_data_remover_provider.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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 IOS_PUBLIC_PROVIDER_CHROME_BROWSER_BROWSING_DATA_IOS_CHROME_BROWSING_DATA_REMOVER_PROVIDER_H_
-#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_BROWSING_DATA_IOS_CHROME_BROWSING_DATA_REMOVER_PROVIDER_H_
-
-#include "base/basictypes.h"
-#include "base/callback_forward.h"
-
-class GURL;
-
-namespace base {
-class Time;
-}
-
-namespace net {
-class URLRequestContextGetter;
-}
-
-namespace ios {
-
-class ChromeBrowserState;
-
-// A class that provides additional functionality to
-// IOSChromeBrowsingDataRemover.
-class IOSChromeBrowsingDataRemoverProvider {
- public:
-  virtual ~IOSChromeBrowsingDataRemoverProvider() {}
-
-  // Clears the hostname resolution cache and runs |callback| on completion.
-  // If the hostname resolution cache doesn't exist, runs |callback|
-  // immediately.
-  virtual void ClearHostnameResolutionCache(const base::Closure& callback) = 0;
-
-  // Gets the URLRequestContextGetter used by the SafeBrowsing service. Returns
-  // null if there is no SafeBrowsing service.
-  virtual net::URLRequestContextGetter* GetSafeBrowsingURLRequestContext() = 0;
-
-  // Clears the relevant storage partition and runs |callback| on
-  // completion.
-  virtual void ClearStoragePartition(const GURL& remove_url,
-                                     base::Time delete_begin,
-                                     base::Time delete_end,
-                                     const base::Closure& callback) = 0;
-};
-
-}  // namespace ios
-
-#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_BROWSING_DATA_IOS_CHROME_BROWSING_DATA_REMOVER_PROVIDER_H_
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.cc b/ios/public/provider/chrome/browser/chrome_browser_provider.cc
index a12824c..285144b6 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.cc
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.cc
@@ -10,7 +10,6 @@
 #include "components/metrics/metrics_provider.h"
 #include "components/sync_sessions/local_session_event_router.h"
 #include "components/sync_sessions/synced_window_delegates_getter.h"
-#include "ios/public/provider/chrome/browser/browsing_data/ios_chrome_browsing_data_remover_provider.h"
 #include "ios/public/provider/chrome/browser/keyed_service_provider.h"
 
 namespace ios {
@@ -82,12 +81,6 @@
   return nullptr;
 }
 
-scoped_ptr<IOSChromeBrowsingDataRemoverProvider>
-ChromeBrowserProvider::GetIOSChromeBrowsingDataRemoverProvider(
-    ChromeBrowserState* browser_state) {
-  return nullptr;
-}
-
 GeolocationUpdaterProvider*
 ChromeBrowserProvider::GetGeolocationUpdaterProvider() {
   return nullptr;
@@ -138,4 +131,9 @@
   return nullptr;
 }
 
+net::URLRequestContextGetter*
+ChromeBrowserProvider::GetSafeBrowsingURLRequestContext() {
+  return nullptr;
+}
+
 }  // namespace ios
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h
index 470b3e4..4509c50 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.h
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "components/favicon_base/favicon_callback.h"
 
@@ -57,7 +58,6 @@
 class ChromeBrowserStateManager;
 class ChromeIdentityService;
 class GeolocationUpdaterProvider;
-class IOSChromeBrowsingDataRemoverProvider;
 class SigninResourcesProvider;
 class StringProvider;
 class LiveTabContextProvider;
@@ -103,8 +103,6 @@
   virtual StringProvider* GetStringProvider();
   // Returns an instance of a LiveTabContextProvider.
   virtual LiveTabContextProvider* GetLiveTabContextProvider();
-  virtual scoped_ptr<IOSChromeBrowsingDataRemoverProvider>
-  GetIOSChromeBrowsingDataRemoverProvider(ChromeBrowserState* browser_state);
   virtual GeolocationUpdaterProvider* GetGeolocationUpdaterProvider();
   // Returns "enabled", "disabled", or "default".
   virtual std::string DataReductionProxyAvailability();
@@ -139,6 +137,10 @@
   // Returns the SyncedWindowDelegatesGetter implementation.
   virtual scoped_ptr<browser_sync::SyncedWindowDelegatesGetter>
   CreateSyncedWindowDelegatesGetter(ios::ChromeBrowserState* browser_state);
+
+  // Gets the URLRequestContextGetter used by the SafeBrowsing service. Returns
+  // null if there is no SafeBrowsing service.
+  virtual net::URLRequestContextGetter* GetSafeBrowsingURLRequestContext();
 };
 
 }  // namespace ios
diff --git a/media/BUILD.gn b/media/BUILD.gn
index eb4c38f..f6b5209d 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -691,13 +691,13 @@
 
   if (is_android) {
     isolate_file = "media_unittests.isolate"
-    deps += [ "//media/base/android:unittests" ]
     sources -= [
       "filters/decrypting_audio_decoder_unittest.cc",
       "filters/decrypting_video_decoder_unittest.cc",
     ]
-    apk_deps = [
+    deps += [
       "//media/base/android:media_java",
+      "//media/base/android:unittests",
       "//ui/android:ui_java",
     ]
   }
diff --git a/media/audio/win/audio_low_latency_output_win_unittest.cc b/media/audio/win/audio_low_latency_output_win_unittest.cc
index a981b33..4c39228 100644
--- a/media/audio/win/audio_low_latency_output_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_output_win_unittest.cc
@@ -380,10 +380,12 @@
   uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
       (aosw.bits_per_sample() / 8);
 
-  // Wait for the first callback and verify its parameters.
+  // Wait for the first callback and verify its parameters.  Ignore any
+  // subsequent callbacks that might arrive.
   EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet)))
       .WillOnce(DoAll(QuitLoop(loop.task_runner()),
-                      Return(aosw.samples_per_packet())));
+                      Return(aosw.samples_per_packet())))
+      .WillRepeatedly(Return(0));
 
   aos->Start(&source);
   loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
diff --git a/media/base/mime_util.cc b/media/base/mime_util.cc
index c70cd6f..bb85b91b 100644
--- a/media/base/mime_util.cc
+++ b/media/base/mime_util.cc
@@ -112,11 +112,8 @@
   bool IsDefaultCodecSupportedLowerCase(
       const std::string& mime_type_lower_case) const;
 
-  using MimeTypes = base::hash_set<std::string>;
-  MimeTypes media_map_;
-
   // A map of mime_types and hash map of the supported codecs for the mime_type.
-  MediaFormatMappings media_format_format_map_;
+  MediaFormatMappings media_format_map_;
 
   // Keeps track of whether proprietary codec support should be
   // advertised to callers.
@@ -132,55 +129,6 @@
 static base::LazyInstance<MimeUtil>::Leaky g_media_mime_util =
     LAZY_INSTANCE_INITIALIZER;
 
-
-// A list of media types: http://en.wikipedia.org/wiki/Internet_media_type
-// A comprehensive mime type list: http://plugindoc.mozdev.org/winmime.php
-// This set of codecs is supported by all variations of Chromium.
-static const char* const common_media_types[] = {
-  // Ogg.
-  "audio/ogg",
-  "application/ogg",
-#if !defined(OS_ANDROID)  // Android doesn't support Ogg Theora.
-  "video/ogg",
-#endif
-
-  // WebM.
-  "video/webm",
-  "audio/webm",
-
-  // Wav.
-  "audio/wav",
-  "audio/x-wav",
-
-#if defined(OS_ANDROID)
-  // HLS.
-  "application/vnd.apple.mpegurl",
-  "application/x-mpegurl",
-#endif
-};
-
-// List of proprietary types only supported by Google Chrome.
-static const char* const proprietary_media_types[] = {
-  // MPEG-4.
-  "video/mp4",
-  "video/x-m4v",
-  "audio/mp4",
-  "audio/x-m4a",
-
-  // MP3.
-  "audio/mp3",
-  "audio/x-mp3",
-  "audio/mpeg",
-
-  // AAC / ADTS
-  "audio/aac",
-
-#if defined(ENABLE_MPEG2TS_STREAM_PARSER)
-  // MPEG-2 TS.
-  "video/mp2t",
-#endif
-};
-
 #if defined(OS_ANDROID)
 static bool IsCodecSupportedOnAndroid(MimeUtil::Codec codec) {
   switch (codec) {
@@ -230,11 +178,15 @@
 }
 #endif
 
+enum MediaFormatType { COMMON, PROPRIETARY };
+
 struct MediaFormat {
   const char* const mime_type;
+  MediaFormatType format_type;
   const char* const codecs_list;
 };
 
+#if defined(USE_PROPRIETARY_CODECS)
 // Following is the list of RFC 6381 compliant codecs:
 //   mp4a.66     - MPEG-2 AAC MAIN
 //   mp4a.67     - MPEG-2 AAC LC
@@ -269,37 +221,46 @@
 #endif
     "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.02,mp4a.40.5,"
     "mp4a.40.05,mp4a.40.29";
+#endif  // USE_PROPRIETARY_CODECS
 
-// These containers are also included in
-// common_media_types/proprietary_media_types. See crbug.com/461012.
-static const MediaFormat format_codec_mappings[] = {
-    {"video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0"},
-    {"audio/webm", "opus,vorbis"},
-    {"audio/wav", "1"},
-    {"audio/x-wav", "1"},
-// Android does not support Opus in Ogg container.
+// A list of media types (https://en.wikipedia.org/wiki/Media_type) and
+// corresponding media codecs supported by these types/containers.
+// Media formats marked as PROPRIETARY are not supported by Chromium, only
+// Google Chrome browser supports them.
+static const MediaFormat kFormatCodecMappings[] = {
+    {"video/webm", COMMON, "opus,vorbis,vp8,vp8.0,vp9,vp9.0"},
+    {"audio/webm", COMMON, "opus,vorbis"},
+    {"audio/wav", COMMON, "1"},
+    {"audio/x-wav", COMMON, "1"},
 #if defined(OS_ANDROID)
-    {"video/ogg", "theora,vorbis"},
-    {"audio/ogg", "vorbis"},
-    {"application/ogg", "theora,vorbis"},
+    // Android does not support Opus in Ogg container.
+    // Android does not support Theora and thus video/ogg.
+    {"audio/ogg", COMMON, "vorbis"},
+    {"application/ogg", COMMON, "vorbis"},
 #else
-    {"video/ogg", "opus,theora,vorbis"},
-    {"audio/ogg", "opus,vorbis"},
-    {"application/ogg", "opus,theora,vorbis"},
+    {"video/ogg", COMMON, "opus,theora,vorbis"},
+    {"audio/ogg", COMMON, "opus,vorbis"},
+    {"application/ogg", COMMON, "opus,theora,vorbis"},
 #endif
-    {"audio/mpeg", "mp3"},
-    {"audio/mp3", ""},
-    {"audio/x-mp3", ""},
-    {"audio/aac", ""},
-    {"audio/mp4", kMP4AudioCodecsExpression},
-    {"audio/x-m4a", kMP4AudioCodecsExpression},
-    {"video/mp4", kMP4VideoCodecsExpression},
-    {"video/x-m4v", kMP4VideoCodecsExpression},
+#if defined(USE_PROPRIETARY_CODECS)
+    {"audio/mpeg", PROPRIETARY, "mp3"},
+    {"audio/mp3", PROPRIETARY, ""},
+    {"audio/x-mp3", PROPRIETARY, ""},
+    {"audio/aac", PROPRIETARY, ""},  // AAC / ADTS
+    {"audio/mp4", PROPRIETARY, kMP4AudioCodecsExpression},
+    {"audio/x-m4a", PROPRIETARY, kMP4AudioCodecsExpression},
+    {"video/mp4", PROPRIETARY, kMP4VideoCodecsExpression},
+    {"video/x-m4v", PROPRIETARY, kMP4VideoCodecsExpression},
 #if defined(ENABLE_MPEG2TS_STREAM_PARSER)
-    {"video/mp2t", kMP4VideoCodecsExpression},
+    {"video/mp2t", PROPRIETARY, kMP4VideoCodecsExpression},
 #endif
-    {"application/x-mpegurl", kMP4VideoCodecsExpression},
-    {"application/vnd.apple.mpegurl", kMP4VideoCodecsExpression}};
+#if defined(OS_ANDROID)
+    // HTTP Live Streaming (HLS)
+    {"application/x-mpegurl", PROPRIETARY, kMP4VideoCodecsExpression},
+    {"application/vnd.apple.mpegurl", PROPRIETARY, kMP4VideoCodecsExpression}
+#endif
+#endif  // USE_PROPRIETARY_CODECS
+};
 
 struct CodecIDMappings {
   const char* const codec_id;
@@ -423,13 +384,8 @@
 
 void MimeUtil::InitializeMimeTypeMaps() {
   // Initialize the supported media types.
-  for (size_t i = 0; i < arraysize(common_media_types); ++i)
-    media_map_.insert(common_media_types[i]);
 #if defined(USE_PROPRIETARY_CODECS)
   allow_proprietary_codecs_ = true;
-
-  for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
-    media_map_.insert(proprietary_media_types[i]);
 #endif
 
   for (size_t i = 0; i < arraysize(kUnambiguousCodecStringMap); ++i) {
@@ -443,10 +399,9 @@
   }
 
   // Initialize the supported media formats.
-  for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) {
+  for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i) {
     std::vector<std::string> mime_type_codecs;
-    ParseCodecString(format_codec_mappings[i].codecs_list,
-                     &mime_type_codecs,
+    ParseCodecString(kFormatCodecMappings[i].codecs_list, &mime_type_codecs,
                      false);
 
     CodecSet codecs;
@@ -458,12 +413,13 @@
       codecs.insert(codec);
     }
 
-    media_format_format_map_[format_codec_mappings[i].mime_type] = codecs;
+    media_format_map_[kFormatCodecMappings[i].mime_type] = codecs;
   }
 }
 
 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const {
-  return media_map_.find(base::ToLowerASCII(mime_type)) != media_map_.end();
+  return media_format_map_.find(base::ToLowerASCII(mime_type)) !=
+         media_format_map_.end();
 }
 
 void MimeUtil::ParseCodecString(const std::string& codecs,
@@ -495,9 +451,9 @@
     const std::vector<std::string>& codecs) const {
   const std::string mime_type_lower_case = base::ToLowerASCII(mime_type);
   MediaFormatMappings::const_iterator it_media_format_map =
-      media_format_format_map_.find(mime_type_lower_case);
-  if (it_media_format_map == media_format_format_map_.end())
-    return codecs.empty() ? MayBeSupported : IsNotSupported;
+      media_format_map_.find(mime_type_lower_case);
+  if (it_media_format_map == media_format_map_.end())
+    return IsNotSupported;
 
   if (it_media_format_map->second.empty()) {
     // We get here if the mimetype does not expect a codecs parameter.
@@ -533,8 +489,9 @@
 }
 
 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() {
-  for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
-    media_map_.erase(proprietary_media_types[i]);
+  for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i)
+    if (kFormatCodecMappings[i].format_type == PROPRIETARY)
+      media_format_map_.erase(kFormatCodecMappings[i].mime_type);
   allow_proprietary_codecs_ = false;
 }
 
diff --git a/media/blink/key_system_config_selector.cc b/media/blink/key_system_config_selector.cc
index 205b861..625e421 100644
--- a/media/blink/key_system_config_selector.cc
+++ b/media/blink/key_system_config_selector.cc
@@ -283,14 +283,10 @@
   // parameters can be rejected. http://crbug.com/417561
   std::string container_lower = base::ToLowerASCII(container_mime_type);
 
-  // Check that |container_mime_type| is supported by Chrome.
-  if (!media::IsSupportedMediaMimeType(container_lower))
-    return false;
-
-  // Check that |codecs| are supported by Chrome. This is done primarily to
-  // validate extended codecs, but it also ensures that the CDM cannot support
-  // codecs that Chrome does not (which could complicate the robustness
-  // algorithm).
+  // Check that |container_mime_type| and |codecs| are supported by Chrome. This
+  // is done primarily to validate extended codecs, but it also ensures that the
+  // CDM cannot support codecs that Chrome does not (which could complicate the
+  // robustness algorithm).
   std::vector<std::string> codec_vector;
   media::ParseCodecString(codecs, &codec_vector, false);
   if (!codec_vector.empty() &&
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index cf1bd5e..2e14819 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -251,9 +251,6 @@
   SetNetworkState(WebMediaPlayer::NetworkStateLoading);
   SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
   media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
-  memory_usage_reporting_timer_.Start(
-      FROM_HERE, base::TimeDelta::FromMilliseconds(500), this,
-      &WebMediaPlayerImpl::ReportMemoryUsage);
 
   // Media source pipelines can start immediately.
   if (load_type == LoadTypeMediaSource) {
@@ -288,7 +285,7 @@
   media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
 
   if (delegate_ && playback_rate_ > 0)
-    delegate_->DidPlay(this);
+    NotifyPlaybackStarted();
 }
 
 void WebMediaPlayerImpl::pause() {
@@ -305,7 +302,7 @@
   media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
 
   if (!was_already_paused && delegate_)
-    delegate_->DidPause(this);
+    NotifyPlaybackPaused();
 }
 
 bool WebMediaPlayerImpl::supportsSave() const {
@@ -401,9 +398,9 @@
     else if (rate > kMaxRate)
       rate = kMaxRate;
     if (playback_rate_ == 0 && !paused_ && delegate_)
-      delegate_->DidPlay(this);
+      NotifyPlaybackStarted();
   } else if (playback_rate_ != 0 && !paused_ && delegate_) {
-    delegate_->DidPause(this);
+    NotifyPlaybackPaused();
   }
 
   playback_rate_ = rate;
@@ -894,6 +891,10 @@
   // Blink expects a timeChanged() in response to a seek().
   if (should_notify_time_changed_)
     client_->timeChanged();
+
+  // Once we have enough, start reporting the total memory usage. We'll also
+  // report once playback starts.
+  ReportMemoryUsage();
 }
 
 void WebMediaPlayerImpl::OnDemuxerOpened() {
@@ -1098,6 +1099,23 @@
       ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
 }
 
+void WebMediaPlayerImpl::NotifyPlaybackStarted() {
+  if (delegate_)
+    delegate_->DidPlay(this);
+  if (!memory_usage_reporting_timer_.IsRunning()) {
+    memory_usage_reporting_timer_.Start(FROM_HERE,
+                                        base::TimeDelta::FromSeconds(2), this,
+                                        &WebMediaPlayerImpl::ReportMemoryUsage);
+  }
+}
+
+void WebMediaPlayerImpl::NotifyPlaybackPaused() {
+  if (delegate_)
+    delegate_->DidPause(this);
+  memory_usage_reporting_timer_.Stop();
+  ReportMemoryUsage();
+}
+
 void WebMediaPlayerImpl::ReportMemoryUsage() {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
 
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index 5b53753..c3ad6a6 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -234,6 +234,11 @@
   // |ended_| state by clamping current time to duration upon |ended_|.
   void UpdatePausedTime();
 
+  // Notifies |delegate_| that playback has started or was paused; also starts
+  // or stops the memory usage reporting timer respectively.
+  void NotifyPlaybackStarted();
+  void NotifyPlaybackPaused();
+
   // Called at low frequency to tell external observers how much memory we're
   // using for video playback.  Called by |memory_usage_reporting_timer_|.
   void ReportMemoryUsage();
diff --git a/media/midi/BUILD.gn b/media/midi/BUILD.gn
index 01a2e09f..59a8e9c 100644
--- a/media/midi/BUILD.gn
+++ b/media/midi/BUILD.gn
@@ -179,7 +179,7 @@
   ]
 
   if (is_android) {
-    apk_deps = [ ":midi_java" ]
+    deps += [ ":midi_java" ]
     isolate_file = "midi_unittests.isolate"
   }
 
diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc
index 0ac9ecd..7f213730 100644
--- a/media/midi/midi_manager_alsa.cc
+++ b/media/midi/midi_manager_alsa.cc
@@ -493,9 +493,9 @@
 MidiManagerAlsa::MidiPortStateBase::FindConnected(
     const MidiManagerAlsa::MidiPort& port) {
   // Exact match required for connected ports.
-  auto it = std::find_if(ports_.begin(), ports_.end(), [&port](MidiPort* p) {
-    return p->MatchConnected(port);
-  });
+  auto it = std::find_if(
+      ports_.begin(), ports_.end(),
+      [&port](scoped_ptr<MidiPort>& p) { return p->MatchConnected(port); });
   return it;
 }
 
@@ -519,9 +519,9 @@
     // Pass 1. Match on path, id, midi_device, port_id.
     // This is the best possible match for hardware card-based clients.
     // This will also match the empty id correctly for devices without an id.
-    auto it = std::find_if(ports_.begin(), ports_.end(), [&port](MidiPort* p) {
-      return p->MatchCardPass1(port);
-    });
+    auto it = std::find_if(
+        ports_.begin(), ports_.end(),
+        [&port](scoped_ptr<MidiPort>& p) { return p->MatchCardPass1(port); });
     if (it != ports_.end())
       return it;
 
@@ -530,9 +530,9 @@
       // This will give us a high-confidence match when a user moves a device to
       // another USB/Firewire/Thunderbolt/etc port, but only works if the device
       // has a hardware id.
-      it = std::find_if(ports_.begin(), ports_.end(), [&port](MidiPort* p) {
-        return p->MatchCardPass2(port);
-      });
+      it = std::find_if(
+          ports_.begin(), ports_.end(),
+          [&port](scoped_ptr<MidiPort>& p) { return p->MatchCardPass2(port); });
       if (it != ports_.end())
         return it;
     }
@@ -540,18 +540,18 @@
     // Else, we have a non-card-based client.
     // Pass 1. Match on client_id, port_id, client_name, port_name.
     // This will give us a reasonably good match.
-    auto it = std::find_if(ports_.begin(), ports_.end(), [&port](MidiPort* p) {
-      return p->MatchNoCardPass1(port);
-    });
+    auto it = std::find_if(
+        ports_.begin(), ports_.end(),
+        [&port](scoped_ptr<MidiPort>& p) { return p->MatchNoCardPass1(port); });
     if (it != ports_.end())
       return it;
 
     // Pass 2. Match on port_id, client_name, port_name.
     // This is weaker but similar to pass 2 in the hardware card-based clients
     // match.
-    it = std::find_if(ports_.begin(), ports_.end(), [&port](MidiPort* p) {
-      return p->MatchNoCardPass2(port);
-    });
+    it = std::find_if(
+        ports_.begin(), ports_.end(),
+        [&port](scoped_ptr<MidiPort>& p) { return p->MatchNoCardPass2(port); });
     if (it != ports_.end())
       return it;
   }
@@ -562,14 +562,9 @@
 
 MidiManagerAlsa::MidiPortStateBase::MidiPortStateBase() = default;
 
-void MidiManagerAlsa::TemporaryMidiPortState::Insert(
-    scoped_ptr<MidiPort> port) {
-  ports().push_back(port.release());
-}
-
 MidiManagerAlsa::MidiPortState::MidiPortState() = default;
 
-uint32 MidiManagerAlsa::MidiPortState::Insert(scoped_ptr<MidiPort> port) {
+uint32 MidiManagerAlsa::MidiPortState::push_back(scoped_ptr<MidiPort> port) {
   // Add the web midi index.
   uint32 web_port_index = 0;
   switch (port->type()) {
@@ -581,7 +576,7 @@
       break;
   }
   port->set_web_port_index(web_port_index);
-  ports().push_back(port.release());
+  MidiPortStateBase::push_back(port.Pass());
   return web_port_index;
 }
 
@@ -694,13 +689,13 @@
         PortDirection direction = port->direction();
         if (direction == PortDirection::kInput ||
             direction == PortDirection::kDuplex) {
-          midi_ports->Insert(make_scoped_ptr(new MidiPort(
+          midi_ports->push_back(make_scoped_ptr(new MidiPort(
               path, id, client_id, port_id, midi_device, client->name(),
               port->name(), manufacturer, version, MidiPort::Type::kInput)));
         }
         if (direction == PortDirection::kOutput ||
             direction == PortDirection::kDuplex) {
-          midi_ports->Insert(make_scoped_ptr(new MidiPort(
+          midi_ports->push_back(make_scoped_ptr(new MidiPort(
               path, id, client_id, port_id, midi_device, client->name(),
               port->name(), manufacturer, version, MidiPort::Type::kOutput)));
         }
@@ -1145,7 +1140,7 @@
   auto new_port_state = alsa_seq_state_.ToMidiPortState(alsa_cards_);
 
   // Disconnect any connected old ports that are now missing.
-  for (auto* old_port : port_state_) {
+  for (auto& old_port : port_state_) {
     if (old_port->connected() &&
         (new_port_state->FindConnected(*old_port) == new_port_state->end())) {
       old_port->set_connected(false);
@@ -1167,27 +1162,33 @@
   // Reconnect or add new ports.
   auto it = new_port_state->begin();
   while (it != new_port_state->end()) {
-    auto* new_port = *it;
+    auto& new_port = *it;
     auto old_port = port_state_.Find(*new_port);
     if (old_port == port_state_.end()) {
       // Add new port.
-      uint32 web_port_index = port_state_.Insert(make_scoped_ptr(new_port));
-      MidiPortInfo info(new_port->OpaqueKey(), new_port->manufacturer(),
-                        new_port->port_name(), new_port->version(),
+      const auto& opaque_key = new_port->OpaqueKey();
+      const auto& manufacturer = new_port->manufacturer();
+      const auto& port_name = new_port->port_name();
+      const auto& version = new_port->version();
+      const auto& type = new_port->type();
+      const auto& client_id = new_port->client_id();
+      const auto& port_id = new_port->port_id();
+
+      uint32 web_port_index = port_state_.push_back(new_port.Pass());
+      it = new_port_state->erase(it);
+
+      MidiPortInfo info(opaque_key, manufacturer, port_name, version,
                         MIDI_PORT_OPENED);
-      switch (new_port->type()) {
+      switch (type) {
         case MidiPort::Type::kInput:
-          if (Subscribe(web_port_index, new_port->client_id(),
-                        new_port->port_id()))
+          if (Subscribe(web_port_index, client_id, port_id))
             AddInputPort(info);
           break;
         case MidiPort::Type::kOutput:
-          if (CreateAlsaOutputPort(web_port_index, new_port->client_id(),
-                                   new_port->port_id()))
+          if (CreateAlsaOutputPort(web_port_index, client_id, port_id))
             AddOutputPort(info);
           break;
       }
-      it = new_port_state->weak_erase(it);
     } else if (!(*old_port)->connected()) {
       // Reconnect.
       uint32 web_port_index = (*old_port)->web_port_index();
diff --git a/media/midi/midi_manager_alsa.h b/media/midi/midi_manager_alsa.h
index 2dd95e6..d269f25 100644
--- a/media/midi/midi_manager_alsa.h
+++ b/media/midi/midi_manager_alsa.h
@@ -12,7 +12,6 @@
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
 #include "base/values.h"
@@ -177,7 +176,7 @@
 
   class MidiPortStateBase {
    public:
-    typedef ScopedVector<MidiPort>::iterator iterator;
+    typedef std::vector<scoped_ptr<MidiPort>>::iterator iterator;
 
     virtual ~MidiPortStateBase();
 
@@ -195,29 +194,31 @@
 
    protected:
     MidiPortStateBase();
-
-    std::vector<MidiPort*>& ports() { return ports_.get(); }
+    iterator erase(iterator position) { return ports_.erase(position); }
+    void push_back(scoped_ptr<MidiPort> port) { ports_.push_back(port.Pass()); }
 
    private:
-    ScopedVector<MidiPort> ports_;
+    std::vector<scoped_ptr<MidiPort>> ports_;
 
     DISALLOW_COPY_AND_ASSIGN(MidiPortStateBase);
   };
 
   class TemporaryMidiPortState final : public MidiPortStateBase {
    public:
-    // Removes a port from the list without deleting it.
-    iterator weak_erase(iterator position) { return ports().erase(position); }
-
-    void Insert(scoped_ptr<MidiPort> port);
+    iterator erase(iterator position) {
+      return MidiPortStateBase::erase(position);
+    };
+    void push_back(scoped_ptr<MidiPort> port) {
+      MidiPortStateBase::push_back(port.Pass());
+    }
   };
 
   class MidiPortState final : public MidiPortStateBase {
    public:
     MidiPortState();
 
-    // Inserts a port. Returns web_port_index.
-    uint32 Insert(scoped_ptr<MidiPort> port);
+    // Inserts a port at the end. Returns web_port_index.
+    uint32 push_back(scoped_ptr<MidiPort> port);
 
    private:
     uint32 num_input_ports_ = 0;
diff --git a/media/midi/midi_manager_alsa_unittest.cc b/media/midi/midi_manager_alsa_unittest.cc
index ce783f53..4c91625 100644
--- a/media/midi/midi_manager_alsa_unittest.cc
+++ b/media/midi/midi_manager_alsa_unittest.cc
@@ -376,10 +376,10 @@
   port_input_1_->set_web_port_index(5000);
   port_output_1_->set_web_port_index(5000);
 
-  midi_port_state_0_.Insert(port_input_0_.Pass());
-  midi_port_state_0_.Insert(port_output_0_.Pass());
-  midi_port_state_0_.Insert(port_input_1_.Pass());
-  midi_port_state_0_.Insert(port_output_1_.Pass());
+  midi_port_state_0_.push_back(port_input_0_.Pass());
+  midi_port_state_0_.push_back(port_output_0_.Pass());
+  midi_port_state_0_.push_back(port_input_1_.Pass());
+  midi_port_state_0_.push_back(port_output_1_.Pass());
 
   // First port of each type has index of 0.
   EXPECT_EQ(0U, port_input_0_tracking_pointer->web_port_index());
@@ -400,10 +400,10 @@
   port_input_1_->set_web_port_index(5000);
   port_output_1_->set_web_port_index(5000);
 
-  temporary_midi_port_state_0_.Insert(port_input_0_.Pass());
-  temporary_midi_port_state_0_.Insert(port_output_0_.Pass());
-  temporary_midi_port_state_0_.Insert(port_input_1_.Pass());
-  temporary_midi_port_state_0_.Insert(port_output_1_.Pass());
+  temporary_midi_port_state_0_.push_back(port_input_0_.Pass());
+  temporary_midi_port_state_0_.push_back(port_output_0_.Pass());
+  temporary_midi_port_state_0_.push_back(port_input_1_.Pass());
+  temporary_midi_port_state_0_.push_back(port_output_1_.Pass());
 
   // web_port_index is untouched.
   EXPECT_EQ(0U, port_input_0_tracking_pointer->web_port_index());
@@ -420,12 +420,12 @@
   auto* port_output_1_tracking_pointer = port_input_1_.get();
 
   // First port of each type has index of 0.
-  EXPECT_EQ(0U, midi_port_state_0_.Insert(port_input_0_.Pass()));
-  EXPECT_EQ(0U, midi_port_state_0_.Insert(port_output_0_.Pass()));
+  EXPECT_EQ(0U, midi_port_state_0_.push_back(port_input_0_.Pass()));
+  EXPECT_EQ(0U, midi_port_state_0_.push_back(port_output_0_.Pass()));
 
   // Second port of each type has index of 1.
-  EXPECT_EQ(1U, midi_port_state_0_.Insert(port_input_1_.Pass()));
-  EXPECT_EQ(1U, midi_port_state_0_.Insert(port_output_1_.Pass()));
+  EXPECT_EQ(1U, midi_port_state_0_.push_back(port_input_1_.Pass()));
+  EXPECT_EQ(1U, midi_port_state_0_.push_back(port_output_1_.Pass()));
 
   // Check again that the field matches what was returned.
   EXPECT_EQ(0U, port_input_0_tracking_pointer->web_port_index());
@@ -440,10 +440,10 @@
   auto* port_input_1_tracking_pointer = port_input_1_.get();
 
   // Insert port_input_0.
-  midi_port_state_0_.Insert(port_input_0_.Pass());
+  midi_port_state_0_.push_back(port_input_0_.Pass());
   // Look for port_input_1 (every field matches port_input_0).
   auto it = midi_port_state_0_.FindConnected(*port_input_1_tracking_pointer);
-  EXPECT_EQ(port_input_0_tracking_pointer, *it);
+  EXPECT_EQ(port_input_0_tracking_pointer, it->get());
   // Look for something else that we won't find.
   EXPECT_EQ(midi_port_state_0_.end(),
             midi_port_state_0_.FindConnected(*port_input_0_alt_path_));
@@ -454,16 +454,16 @@
   auto* port_input_1_tracking_pointer = port_input_1_.get();
 
   // Insert some stuff.
-  midi_port_state_0_.Insert(port_input_0_alt_path_.Pass());
-  midi_port_state_0_.Insert(port_input_0_alt_id_.Pass());
-  midi_port_state_0_.Insert(port_input_0_alt_client_name_.Pass());
+  midi_port_state_0_.push_back(port_input_0_alt_path_.Pass());
+  midi_port_state_0_.push_back(port_input_0_alt_id_.Pass());
+  midi_port_state_0_.push_back(port_input_0_alt_client_name_.Pass());
   // Insert port_input_0.
-  midi_port_state_0_.Insert(port_input_0_.Pass());
+  midi_port_state_0_.push_back(port_input_0_.Pass());
   // Insert some more stuff.
-  midi_port_state_0_.Insert(port_input_0_alt_port_id_.Pass());
+  midi_port_state_0_.push_back(port_input_0_alt_port_id_.Pass());
   // Look for port_input_1 (matches to port_input_0).
   auto it = midi_port_state_0_.FindConnected(*port_input_1_tracking_pointer);
-  EXPECT_EQ(port_input_0_tracking_pointer, *it);
+  EXPECT_EQ(port_input_0_tracking_pointer, it->get());
   // Look for something else that we won't find.
   EXPECT_EQ(midi_port_state_0_.end(),
             midi_port_state_0_.FindConnected(*port_input_minimal_));
@@ -493,25 +493,27 @@
   port_input_0_->set_connected(false);
 
   // Insert some stuff.
-  midi_port_state_0_.Insert(port_input_0_alt_id_.Pass());
-  midi_port_state_0_.Insert(port_input_0_alt_path_.Pass());
+  midi_port_state_0_.push_back(port_input_0_alt_id_.Pass());
+  midi_port_state_0_.push_back(port_input_0_alt_path_.Pass());
   // Insert port_input_0.
-  midi_port_state_0_.Insert(port_input_0_.Pass());
+  midi_port_state_0_.push_back(port_input_0_.Pass());
 
   // Add "no card" stuff.
   port_input_1_no_card_->set_connected(false);
-  midi_port_state_0_.Insert(port_input_1_no_card_.Pass());
+  midi_port_state_0_.push_back(port_input_1_no_card_.Pass());
 
   // Insert some more stuff.
-  midi_port_state_0_.Insert(port_input_0_alt_port_id_.Pass());
+  midi_port_state_0_.push_back(port_input_0_alt_port_id_.Pass());
 
   // Look for port_input_1, should trigger exact match.
-  EXPECT_EQ(port_input_0_tracking_pointer, *midi_port_state_0_.FindDisconnected(
-                                               *port_input_1_tracking_pointer));
+  EXPECT_EQ(port_input_0_tracking_pointer,
+            midi_port_state_0_.FindDisconnected(*port_input_1_tracking_pointer)
+                ->get());
 
   // Look for no card exact match.
-  EXPECT_EQ(port_input_1_no_card_tracking_pointer,
-            *midi_port_state_0_.FindDisconnected(*port_input_0_no_card_.get()));
+  EXPECT_EQ(
+      port_input_1_no_card_tracking_pointer,
+      midi_port_state_0_.FindDisconnected(*port_input_0_no_card_.get())->get());
 
   // Look for something else that we won't find.
   EXPECT_EQ(midi_port_state_0_.end(),
@@ -528,22 +530,23 @@
   port_input_0_->set_connected(false);
 
   // Insert some stuff.
-  midi_port_state_0_.Insert(port_input_0_alt_path_.Pass());
-  midi_port_state_0_.Insert(port_input_0_alt_id_.Pass());
+  midi_port_state_0_.push_back(port_input_0_alt_path_.Pass());
+  midi_port_state_0_.push_back(port_input_0_alt_id_.Pass());
 
   // Add no card stuff.
   port_input_1_no_card_->set_connected(false);
-  midi_port_state_0_.Insert(port_input_1_no_card_.Pass());
+  midi_port_state_0_.push_back(port_input_1_no_card_.Pass());
 
   // Look for port_input_0, should find port_input_0_alt_path.
-  EXPECT_EQ(
-      port_input_0_alt_path_tracking_pointer,
-      *midi_port_state_0_.FindDisconnected(*port_input_0_tracking_pointer));
+  EXPECT_EQ(port_input_0_alt_path_tracking_pointer,
+            midi_port_state_0_.FindDisconnected(*port_input_0_tracking_pointer)
+                ->get());
 
   // Look for no card partial match.
   EXPECT_EQ(port_input_1_no_card_tracking_pointer,
-            *midi_port_state_0_.FindDisconnected(
-                *port_input_0_no_card_alt_client_id_.get()));
+            midi_port_state_0_.FindDisconnected(
+                                  *port_input_0_no_card_alt_client_id_.get())
+                ->get());
 
   // Won't find this.
   EXPECT_EQ(midi_port_state_0_.end(),
diff --git a/native_client_sdk/src/BUILDING.rst b/native_client_sdk/src/BUILDING.rst
index 973a2e9..b41caae 100644
--- a/native_client_sdk/src/BUILDING.rst
+++ b/native_client_sdk/src/BUILDING.rst
@@ -84,8 +84,8 @@
 
   make TOOLCHAIN=newlib CONFIG=Debug -j8
 
-The valid toolchains are: `newlib`, `glibc`, `clang-newlib`, `pnacl` and
-`bionic`.  The valid configurations are: `Debug` and `Release`.
+The valid toolchains are: `newlib`, `glibc`, `clang-newlib` and `pnacl`.
+The valid configurations are: `Debug` and `Release`.
 
 To run the example::
 
diff --git a/native_client_sdk/src/build_tools/build_projects.py b/native_client_sdk/src/build_tools/build_projects.py
index 0c5077a..f1a76c2 100755
--- a/native_client_sdk/src/build_tools/build_projects.py
+++ b/native_client_sdk/src/build_tools/build_projects.py
@@ -30,7 +30,6 @@
   'win': ['x86_32']
 }
 VALID_TOOLCHAINS = [
-  'bionic',
   'newlib',
   'clang-newlib',
   'glibc',
@@ -213,10 +212,6 @@
   make_cmd = [make, '-j', jobs]
 
   make_cmd.append('CONFIG='+config)
-  # We always ENABLE_BIONIC in case we need it.  If neither --bionic nor
-  # -t bionic have been provided on the command line, then VALID_TOOLCHAINS
-  # will not contain a bionic target.
-  make_cmd.append('ENABLE_BIONIC=1')
   if not deps:
     make_cmd.append('IGNORE_DEPS=1')
 
@@ -256,8 +251,6 @@
   parser.add_argument('--config',
       help='Choose configuration to build (Debug or Release).  Builds both '
            'by default')
-  parser.add_argument('--bionic',
-      help='Enable bionic projects', action='store_true')
   parser.add_argument('-x', '--experimental',
       help='Build experimental projects', action='store_true')
   parser.add_argument('-t', '--toolchain',
@@ -301,8 +294,6 @@
     # e.g. If an example supports newlib and glibc, then the default will be
     # newlib.
     options.toolchain = ['pnacl', 'newlib', 'glibc', 'host', 'clang-newlib']
-    if options.experimental or options.bionic:
-      options.toolchain.append('bionic')
 
   if 'host' in options.toolchain:
     options.toolchain.remove('host')
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py
index a6433fa..69243be 100755
--- a/native_client_sdk/src/build_tools/build_sdk.py
+++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -67,7 +67,6 @@
 TOOLCHAIN_PACKAGE_MAP = {
     'arm_glibc': ('nacl_arm_glibc', '%(platform)s_arm_glibc', 'arm'),
     'x86_glibc': ('nacl_x86_glibc', '%(platform)s_x86_glibc', 'x86'),
-    'arm_bionic': ('nacl_arm_bionic', '%(platform)s_arm_bionic', 'arm'),
     'pnacl': ('pnacl_newlib', '%(platform)s_pnacl', 'pnacl')
     }
 
@@ -85,7 +84,7 @@
 def GetToolchainLibc(tcname):
   if tcname == 'pnacl':
     return 'newlib'
-  for libc in ('bionic', 'glibc', 'newlib', 'host'):
+  for libc in ('glibc', 'newlib', 'host'):
     if libc in tcname:
       return libc
 
@@ -125,10 +124,7 @@
   else:
     lib_suffix = ''
 
-  if tcname == 'arm_bionic':
-    tcdir = 'tc_newlib'
-  else:
-    tcdir = 'tc_' + GetToolchainLibc(tcname)
+  tcdir = 'tc_' + GetToolchainLibc(tcname)
 
   if tcname == 'pnacl':
     if arch is None:
@@ -167,9 +163,6 @@
 def BuildStepDownloadToolchains(toolchains):
   buildbot_common.BuildStep('Running package_version.py')
   args = [sys.executable, PKGVER, '--mode', 'nacl_core_sdk']
-  if 'arm_bionic' in toolchains:
-    build_platform = '%s_x86' % getos.GetPlatform()
-    args.extend(['--append', os.path.join(build_platform, 'nacl_arm_bionic')])
   args.extend(['sync', '--extract'])
   buildbot_common.Run(args, cwd=NACL_DIR)
 
@@ -293,9 +286,6 @@
       ('native_client/src/untrusted/valgrind/dynamic_annotations.h', 'nacl/'),
       ('ppapi/nacl_irt/public/irt_ppapi.h', ''),
   ],
-  'bionic': [
-      ('ppapi/nacl_irt/public/irt_ppapi.h', ''),
-  ],
 }
 
 def InstallFiles(src_root, dest_root, file_list):
@@ -354,13 +344,6 @@
 # already provided by the toolchain.
 # Mapping from libc to libraries gyp-build trusted libraries
 TOOLCHAIN_LIBS = {
-  'bionic' : [
-    'libminidump_generator.a',
-    'libnacl_dyncode.a',
-    'libnacl_exception.a',
-    'libnacl_list_mappings.a',
-    'libppapi.a',
-  ],
   'newlib' : [
     'libminidump_generator.a',
     'libnacl.a',
@@ -452,7 +435,7 @@
       xarches = (None, 'ia32', 'x64', 'arm')
     elif tc in ('x86_glibc', 'x86_newlib'):
       xarches = ('ia32', 'x64')
-    elif tc in ('arm_glibc', 'arm_bionic'):
+    elif tc == 'arm_glibc':
       xarches = ('arm',)
     else:
       raise AssertionError('unexpected toolchain value: %s' % tc)
@@ -869,13 +852,8 @@
 
 def main(args):
   parser = argparse.ArgumentParser(description=__doc__)
-  parser.add_argument('--nacl-tree-path',
-      help='Path to native client tree for bionic build.',
-      dest='nacl_tree_path')
   parser.add_argument('--qemu', help='Add qemu for ARM.',
       action='store_true')
-  parser.add_argument('--bionic', help='Add bionic build.',
-      action='store_true')
   parser.add_argument('--tar', help='Force the tar step.',
       action='store_true')
   parser.add_argument('--archive', help='Force the archive step.',
@@ -912,29 +890,6 @@
 
   buildbot_common.BuildStep('build_sdk')
 
-  if options.nacl_tree_path:
-    options.bionic = True
-    toolchain_build = os.path.join(options.nacl_tree_path, 'toolchain_build')
-    print 'WARNING: Building bionic toolchain from NaCl checkout.'
-    print 'This option builds bionic from the sources currently in the'
-    print 'provided NativeClient checkout, and the results instead of '
-    print 'downloading a toolchain from the builder. This may result in a'
-    print 'NaCl SDK that can not run on ToT chrome.'
-    print 'NOTE:  To clobber you will need to run toolchain_build_bionic.py'
-    print 'directly from the NativeClient checkout.'
-    print ''
-    response = raw_input("Type 'y' and hit enter to continue.\n")
-    if response != 'y' and response != 'Y':
-      print 'Aborting.'
-      return 1
-
-    # Get head version of NativeClient tree
-    buildbot_common.BuildStep('Build bionic toolchain.')
-    buildbot_common.Run([sys.executable, 'toolchain_build_bionic.py', '-f'],
-                        cwd=toolchain_build)
-  else:
-    toolchain_build = None
-
   if buildbot_common.IsSDKBuilder():
     options.archive = True
     # TODO(binji): re-enable app_engine build when the linux builder stops
@@ -947,11 +902,6 @@
   # Makefiles; the first toolchain will be the default.
   toolchains = ['pnacl', 'x86_glibc', 'arm_glibc', 'clang-newlib', 'host']
 
-  # Changes for experimental bionic builder
-  if options.bionic:
-    toolchains.append('arm_bionic')
-    options.build_app_engine = False
-
   print 'Building: ' + ' '.join(toolchains)
   platform = getos.GetPlatform()
 
@@ -965,10 +915,7 @@
   pepper_old = str(chrome_version - 1)
   pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver)
   pepperdir_old = os.path.join(OUT_DIR, 'pepper_' + pepper_old)
-  if options.bionic:
-    tarname = 'naclsdk_bionic.tar.bz2'
-  else:
-    tarname = 'naclsdk_%s.tar.bz2' % platform
+  tarname = 'naclsdk_%s.tar.bz2' % platform
   tarfile = os.path.join(OUT_DIR, tarname)
 
   if options.release:
@@ -993,16 +940,7 @@
     BuildStepCleanPepperDirs(pepperdir, pepperdir_old)
     BuildStepMakePepperDirs(pepperdir, ['include', 'toolchain', 'tools'])
     BuildStepDownloadToolchains(toolchains)
-    if options.nacl_tree_path:
-      # Instead of untarring, copy the raw bionic toolchain
-      not_bionic = [i for i in toolchains if i != 'arm_bionic']
-      BuildStepUntarToolchains(pepperdir, not_bionic)
-      tcname = GetToolchainDirName('arm_bionic')
-      srcdir = os.path.join(toolchain_build, 'out', tcname)
-      bionicdir = os.path.join(pepperdir, 'toolchain', tcname)
-      oshelpers.Copy(['-r', srcdir, bionicdir])
-    else:
-      BuildStepUntarToolchains(pepperdir, toolchains)
+    BuildStepUntarToolchains(pepperdir, toolchains)
     if platform == 'linux':
       buildbot_common.Move(os.path.join(pepperdir, 'toolchain', 'arm_trusted'),
                            os.path.join(OUT_DIR, 'arm_trusted'))
@@ -1044,8 +982,7 @@
   GenerateNotice(pepperdir)
 
   # Verify the SDK contains what we expect.
-  if not options.bionic:
-    BuildStepVerifyFilelist(pepperdir)
+  BuildStepVerifyFilelist(pepperdir)
 
   if options.tar:
     BuildStepTarBundle(pepper_ver, tarfile)
diff --git a/native_client_sdk/src/build_tools/buildbot_common.py b/native_client_sdk/src/build_tools/buildbot_common.py
index 58ebc0a..610a248 100644
--- a/native_client_sdk/src/build_tools/buildbot_common.py
+++ b/native_client_sdk/src/build_tools/buildbot_common.py
@@ -32,9 +32,9 @@
     (win|mac|linux)_nacl_sdk_build
 
   Builder names:
-    (windows|mac|linux)-sdk-multi(bionic)(rel)?"""
+    (windows|mac|linux)-sdk-multi(rel)?"""
   bot =  os.getenv('BUILDBOT_BUILDERNAME', '')
-  return '-sdk-multi' in bot or '-sdk-bionic-multi' in bot
+  return '-sdk-multi' in bot
 
 
 def ErrorExit(msg):
diff --git a/native_client_sdk/src/build_tools/buildbot_run.py b/native_client_sdk/src/build_tools/buildbot_run.py
index 5971a58..f6e4ee7 100755
--- a/native_client_sdk/src/build_tools/buildbot_run.py
+++ b/native_client_sdk/src/build_tools/buildbot_run.py
@@ -63,8 +63,6 @@
     new_script_dir = SCRIPT_DIR
 
   args = [sys.executable, 'build_sdk.py']
-  if 'bionic' in os.getenv('BUILDBOT_BUILDERNAME', ''):
-    args.append('--bionic')
 
   try:
     Run(args, cwd=new_script_dir)
@@ -87,11 +85,6 @@
     ])
 
   cmd.extend([sys.executable, 'test_sdk.py'])
-
-  # TODO(noelallen): crbug 386332
-  # For Bionic SDK, only build do a build test until we have hardware.
-  if 'bionic' in os.getenv('BUILDBOT_BUILDERNAME', ''):
-    cmd.extend(['build_examples', 'copy_tests', 'build_tests'])
   Run(cmd, cwd=SCRIPT_DIR)
 
 
diff --git a/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json b/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json
index cff07e5..18dea0923b 100644
--- a/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json
+++ b/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json
@@ -112,16 +112,6 @@
       "revision": 0,
       "stability": "canary",
       "version": 0
-    },
-    {
-      "archives": [],
-      "description": "Bionic Canary",
-      "name": "bionic_canary",
-      "recommended": "no",
-      "repath": "",
-      "revision": 0,
-      "stability": "canary",
-      "version": 0
     }
   ],
   "manifest_version": 2
diff --git a/native_client_sdk/src/build_tools/parse_dsc.py b/native_client_sdk/src/build_tools/parse_dsc.py
index 6511adae..3d862deeb 100755
--- a/native_client_sdk/src/build_tools/parse_dsc.py
+++ b/native_client_sdk/src/build_tools/parse_dsc.py
@@ -10,7 +10,6 @@
 import sys
 
 VALID_TOOLCHAINS = [
-  'bionic',
   'clang-newlib',
   'newlib',
   'glibc',
diff --git a/native_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py b/native_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py
index adfeddb..d23e43e 100755
--- a/native_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py
+++ b/native_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py
@@ -21,7 +21,7 @@
 sys.path.append(BUILD_TOOLS_DIR)
 import manifest_util
 import update_nacl_manifest
-from update_nacl_manifest import CANARY_BUNDLE_NAME, BIONIC_CANARY_BUNDLE_NAME
+from update_nacl_manifest import CANARY_BUNDLE_NAME
 
 
 HTTPS_BASE_URL = 'https://storage.googleapis.com' \
@@ -51,11 +51,6 @@
   return GetArchiveURL(basename, version)
 
 
-def GetBionicArchiveUrl(version):
-  basename = 'naclsdk_bionic.tar.bz2'
-  return GetArchiveURL(basename, version)
-
-
 def MakeGsUrl(rel_path):
   return update_nacl_manifest.GS_BUCKET_PATH + rel_path
 
@@ -84,10 +79,6 @@
   return MakeArchive(GetPlatformArchiveUrl(host_os, version), host_os)
 
 
-def MakeBionicArchive(host_os, version):
-  return MakeArchive(GetBionicArchiveUrl(version), host_os)
-
-
 def MakeNonPlatformArchive(basename, version):
   return MakeArchive(GetArchiveURL(basename, version), 'all')
 
@@ -285,9 +276,6 @@
 B26_0_1386_0_MLW = MakePlatformBundle(26, 177362, V26_0_1386_0, OS_MLW)
 B26_0_1386_1_MLW = MakePlatformBundle(26, 177439, V26_0_1386_1, OS_MLW)
 BTRUNK_140819_MLW = MakePlatformBundle(21, 140819, VTRUNK_140819, OS_MLW)
-BBIONIC_NONE = MakePepperBundle(0, stability=CANARY,
-                                bundle_name=BIONIC_CANARY_BUNDLE_NAME)
-BBIONIC_TRUNK_277776 = MakeBionicBundle(37, 277776, VTRUNK_277776, OS_L)
 NON_PEPPER_BUNDLE_NOARCHIVES = MakeNonPepperBundle('foo')
 NON_PEPPER_BUNDLE_ARCHIVES = MakeNonPepperBundle('bar', with_archives=True)
 
@@ -699,18 +687,6 @@
     self.assertRaises(update_nacl_manifest.UnknownLockedBundleException,
                       self._Run, OS_MLW)
 
-  def testUpdateBionic(self):
-    bionic_bundle = copy.deepcopy(BBIONIC_NONE)
-    self.manifest = MakeManifest(bionic_bundle)
-    self.history.Add(OS_MW, CANARY, V37_0_2054_0)
-    self.files.Add(BBIONIC_TRUNK_277776)
-    self.version_mapping[V37_0_2054_0] = VTRUNK_277776
-    self._MakeDelegate()
-    self._Run(OS_MLW)
-    self._ReadUploadedManifest()
-    self._AssertUploadedManifestHasBundle(BBIONIC_TRUNK_277776, CANARY,
-                                          bundle_name=BIONIC_CANARY_BUNDLE_NAME)
-
 
 class TestUpdateVitals(unittest.TestCase):
   def setUp(self):
diff --git a/native_client_sdk/src/build_tools/update_nacl_manifest.py b/native_client_sdk/src/build_tools/update_nacl_manifest.py
index a2d8776..82934b73 100755
--- a/native_client_sdk/src/build_tools/update_nacl_manifest.py
+++ b/native_client_sdk/src/build_tools/update_nacl_manifest.py
@@ -38,7 +38,6 @@
 GS_MANIFEST_BACKUP_DIR = GS_BUCKET_PATH + 'manifest_backups/'
 
 CANARY_BUNDLE_NAME = 'pepper_canary'
-BIONIC_CANARY_BUNDLE_NAME = 'bionic_canary'
 CANARY = 'canary'
 NACLPORTS_ARCHIVE_NAME = 'naclports.tar.bz2'
 
@@ -125,11 +124,6 @@
   return 'naclsdk_%s.tar.bz2' % platform
 
 
-def GetBionicArchiveName():
-  """Get the basename of an archive. Currently this is linux-only"""
-  return 'naclsdk_bionic.tar.bz2'
-
-
 def GetCanonicalArchiveName(url):
   """Get the canonical name of an archive given its URL.
 
@@ -361,14 +355,12 @@
         e.g. [('foo.tar.bz2', '18.0.1000.0'), ('bar.tar.bz2', '19.0.1100.20')]
         These archives must exist to consider a version for inclusion, as
         long as that version is greater than the archive's minimum version.
-    is_bionic: True if we are searching for bionic archives.
   """
-  def __init__(self, delegate, platforms, extra_archives=None, is_bionic=False):
+  def __init__(self, delegate, platforms, extra_archives=None):
     self.delegate = delegate
     self.history = delegate.GetHistory()
     self.platforms = platforms
     self.extra_archives = extra_archives
-    self.is_bionic = is_bionic
 
   def GetMostRecentSharedVersion(self, major_version):
     """Returns the most recent version of a pepper bundle that exists on all
@@ -421,11 +413,7 @@
     """
     archive_urls = self._GetAvailableArchivesFor(version)
 
-    if self.is_bionic:
-      # Bionic currently is Linux-only.
-      expected_archives = set([GetBionicArchiveName()])
-    else:
-      expected_archives = set(GetPlatformArchiveName(p) for p in self.platforms)
+    expected_archives = set(GetPlatformArchiveName(p) for p in self.platforms)
 
     if self.extra_archives:
       for extra_archive, min_version, max_version in self.extra_archives:
@@ -808,7 +796,7 @@
   manifest = delegate.GetRepoManifest()
   auto_update_bundles = []
   for bundle in manifest.GetBundles():
-    if not bundle.name.startswith(('pepper_', 'bionic_')):
+    if not bundle.name.startswith('pepper_'):
       continue
     archives = bundle.GetArchives()
     if not archives:
@@ -822,13 +810,7 @@
 
   for bundle in auto_update_bundles:
     try:
-      if bundle.name == BIONIC_CANARY_BUNDLE_NAME:
-        logger.info('>>> Looking for most recent bionic_canary...')
-        # Ignore extra_archives on bionic; There is no naclports bundle yet.
-        version_finder = VersionFinder(delegate, platforms, None,
-                                       is_bionic=True)
-        version, channel, archives = version_finder.GetMostRecentSharedCanary()
-      elif bundle.name == CANARY_BUNDLE_NAME:
+      if bundle.name == CANARY_BUNDLE_NAME:
         logger.info('>>> Looking for most recent pepper_canary...')
         version_finder = VersionFinder(delegate, platforms, extra_archives)
         version, channel, archives = version_finder.GetMostRecentSharedCanary()
diff --git a/native_client_sdk/src/doc/sdk/download.rst b/native_client_sdk/src/doc/sdk/download.rst
index 99400fcb..d207438 100644
--- a/native_client_sdk/src/doc/sdk/download.rst
+++ b/native_client_sdk/src/doc/sdk/download.rst
@@ -156,7 +156,6 @@
          pepper_36 (beta)
          pepper_37 (dev)
          pepper_canary (canary)
-         bionic_canary (canary)
 
 
    The sample output above shows that several bundles are available for
@@ -225,7 +224,6 @@
          pepper_36 (beta)
          pepper_37 (dev)
          pepper_canary (canary)
-         bionic_canary (canary)
 
    
    If you run ``naclsdk update`` now, it warns you with a message similar to
diff --git a/native_client_sdk/src/examples/demo/nacl_io_demo/example.dsc b/native_client_sdk/src/examples/demo/nacl_io_demo/example.dsc
index 8436f28..173299c 100644
--- a/native_client_sdk/src/examples/demo/nacl_io_demo/example.dsc
+++ b/native_client_sdk/src/examples/demo/nacl_io_demo/example.dsc
@@ -1,5 +1,5 @@
 {
-  'TOOLS': ['clang-newlib', 'glibc', 'pnacl', 'bionic', 'linux', 'mac'],
+  'TOOLS': ['clang-newlib', 'glibc', 'pnacl', 'linux', 'mac'],
   'TARGETS': [
     {
       'NAME' : 'nacl_io_demo',
diff --git a/native_client_sdk/src/libraries/nacl_io/jsfs/js_fs_node.cc b/native_client_sdk/src/libraries/nacl_io/jsfs/js_fs_node.cc
index 2c45b62..a9e7e9a 100644
--- a/native_client_sdk/src/libraries/nacl_io/jsfs/js_fs_node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/jsfs/js_fs_node.cc
@@ -70,8 +70,7 @@
     return EINVAL;
   }
 
-  // TODO(binji): find out the size of bionic stat fields.
-#if defined(__native_client__) && !defined(__BIONIC__)
+#if defined(__native_client__)
 #if defined(__GLIBC__)
 const char* format = "%d%lld%d%d%d%d%lld%lld%lld%lld%lld%lld%lld";
 #else
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_bionic.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_bionic.cc
deleted file mode 100644
index de3f759..0000000
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_bionic.cc
+++ /dev/null
@@ -1,502 +0,0 @@
-// Copyright (c) 2012 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 <sys/types.h>  // Include something that will define __BIONIC__.
-
-#include "nacl_io/kernel_wrap.h" // IRT_EXT is turned on in this header.
-
-// The entire file is wrapped in this #if. We do this so this .cc file can be
-// compiled, even on a non-bionic build.
-
-#if !defined(NACL_IO_IRT_EXT) && defined(__native_client__) && \
-    defined(__BIONIC__)
-
-#include <alloca.h>
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <irt_syscalls.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include "nacl_io/kernel_intercept.h"
-#include "nacl_io/kernel_wrap_real.h"
-#include "nacl_io/nacl_abi_types.h"
-#include "nacl_io/osmman.h"
-
-namespace {
-
-void stat_to_nacl_stat(const struct stat* buf, nacl_abi_stat* nacl_buf) {
-  memset(nacl_buf, 0, sizeof(struct nacl_abi_stat));
-  nacl_buf->nacl_abi_st_dev = buf->st_dev;
-  nacl_buf->nacl_abi_st_ino = buf->st_ino;
-  nacl_buf->nacl_abi_st_mode = buf->st_mode;
-  nacl_buf->nacl_abi_st_nlink = buf->st_nlink;
-  nacl_buf->nacl_abi_st_uid = buf->st_uid;
-  nacl_buf->nacl_abi_st_gid = buf->st_gid;
-  nacl_buf->nacl_abi_st_rdev = buf->st_rdev;
-  nacl_buf->nacl_abi_st_size = buf->st_size;
-  nacl_buf->nacl_abi_st_blksize = buf->st_blksize;
-  nacl_buf->nacl_abi_st_blocks = buf->st_blocks;
-  nacl_buf->nacl_abi_st_atime = buf->st_atime;
-  nacl_buf->nacl_abi_st_mtime = buf->st_mtime;
-  nacl_buf->nacl_abi_st_ctime = buf->st_ctime;
-}
-
-void nacl_stat_to_stat(const nacl_abi_stat* nacl_buf, struct stat* buf) {
-  memset(buf, 0, sizeof(struct stat));
-  buf->st_dev = nacl_buf->nacl_abi_st_dev;
-  buf->st_ino = nacl_buf->nacl_abi_st_ino;
-  buf->st_mode = nacl_buf->nacl_abi_st_mode;
-  buf->st_nlink = nacl_buf->nacl_abi_st_nlink;
-  buf->st_uid = nacl_buf->nacl_abi_st_uid;
-  buf->st_gid = nacl_buf->nacl_abi_st_gid;
-  buf->st_rdev = nacl_buf->nacl_abi_st_rdev;
-  buf->st_size = nacl_buf->nacl_abi_st_size;
-  buf->st_blksize = nacl_buf->nacl_abi_st_blksize;
-  buf->st_blocks = nacl_buf->nacl_abi_st_blocks;
-  buf->st_atime = nacl_buf->nacl_abi_st_atime;
-  buf->st_mtime = nacl_buf->nacl_abi_st_mtime;
-  buf->st_ctime = nacl_buf->nacl_abi_st_ctime;
-}
-
-}  // namespace
-
-static const int d_name_shift = offsetof (dirent, d_name) -
-  offsetof (struct nacl_abi_dirent, nacl_abi_d_name);
-
-EXTERN_C_BEGIN
-
-// Macro to get the REAL function pointer
-#define REAL(name) __nacl_irt_##name##_real
-
-// Macro to get the WRAP function
-#define WRAP(name) __nacl_irt_##name##_wrap
-
-// Declare REAL function pointer.
-#define DECLARE_REAL_PTR(name) typeof(__nacl_irt_##name) REAL(name);
-
-// Assign the REAL function pointer.
-#define ASSIGN_REAL_PTR(name) REAL(name) = __nacl_irt_##name;
-
-// Switch IRT's pointer to the REAL pointer
-#define USE_REAL(name) __nacl_irt_##name = (typeof(__nacl_irt_##name))REAL(name)
-
-// Switch IRT's pointer to the WRAP function
-#define USE_WRAP(name) __nacl_irt_##name = (typeof(__nacl_irt_##name))WRAP(name)
-
-#define EXPAND_SYMBOL_LIST_OPERATION(OP) \
-  OP(chdir);                             \
-  OP(close);                             \
-  OP(dup);                               \
-  OP(dup2);                              \
-  OP(exit);                              \
-  OP(fchdir);                            \
-  OP(fchmod);                            \
-  OP(fdatasync);                         \
-  OP(fstat);                             \
-  OP(fsync);                             \
-  OP(getcwd);                            \
-  OP(getdents);                          \
-  OP(isatty);                            \
-  OP(lstat);                             \
-  OP(mkdir);                             \
-  OP(mmap);                              \
-  OP(munmap);                            \
-  OP(open);                              \
-  OP(open_resource);                     \
-  OP(poll);                              \
-  OP(read);                              \
-  OP(readlink);                          \
-  OP(rmdir);                             \
-  OP(seek);                              \
-  OP(stat);                              \
-  OP(truncate);                          \
-  OP(write);
-
-EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR);
-
-int WRAP(chdir)(const char* pathname) {
-  ERRNO_RTN(ki_chdir(pathname));
-}
-
-int WRAP(close)(int fd) {
-  ERRNO_RTN(ki_close(fd));
-}
-
-int WRAP(dup)(int fd, int* newfd) NOTHROW {
-  *newfd = ki_dup(fd);
-  ERRNO_RTN(*newfd);
-}
-
-int WRAP(dup2)(int fd, int newfd) NOTHROW {
-  ERRNO_RTN(ki_dup2(fd, newfd));
-}
-
-void WRAP(exit)(int status) {
-  ki_exit(status);
-}
-
-int WRAP(fchdir)(int fd) NOTHROW {
-  ERRNO_RTN(ki_fchdir(fd));
-}
-
-int WRAP(fchmod)(int fd, mode_t mode) NOTHROW {
-  ERRNO_RTN(ki_fchmod(fd, mode));
-}
-
-int WRAP(fdatasync)(int fd) NOTHROW {
-  ERRNO_RTN(ki_fdatasync(fd));
-}
-
-int WRAP(fstat)(int fd, struct nacl_abi_stat* nacl_buf) {
-  struct stat buf;
-  memset(&buf, 0, sizeof(struct stat));
-  int res = ki_fstat(fd, &buf);
-  RTN_ERRNO_IF(res < 0);
-  stat_to_nacl_stat(&buf, nacl_buf);
-  return 0;
-}
-
-int WRAP(fsync)(int fd) NOTHROW {
-  ERRNO_RTN(ki_fsync(fd));
-}
-
-int WRAP(getcwd)(char* buf, size_t size) {
-  RTN_ERRNO_IF(ki_getcwd(buf, size) == NULL);
-  return 0;
-}
-
-int WRAP(getdents)(int fd, dirent* nacl_buf, size_t nacl_count, size_t* nread) {
-  int nacl_offset = 0;
-  // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
-  // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer
-  // is enough
-  char* buf = (char*)alloca(nacl_count);
-  int offset = 0;
-  int count;
-
-  count = ki_getdents(fd, (dirent*)buf, nacl_count);
-  RTN_ERRNO_IF(count < 0);
-
-  while (offset < count) {
-    dirent* d = (dirent*)(buf + offset);
-    nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)((char*)nacl_buf + nacl_offset);
-    nacl_d->nacl_abi_d_ino = d->d_ino;
-    nacl_d->nacl_abi_d_off = d->d_off;
-    nacl_d->nacl_abi_d_reclen = d->d_reclen - d_name_shift;
-    size_t d_name_len = d->d_reclen - offsetof(dirent, d_name);
-    memcpy(nacl_d->nacl_abi_d_name, d->d_name, d_name_len);
-
-    offset += d->d_reclen;
-    nacl_offset += nacl_d->nacl_abi_d_reclen;
-  }
-
-  *nread = nacl_offset;
-  return 0;
-}
-
-int WRAP(isatty)(int fd, int* result) {
-  *result = ki_isatty(fd);
-  RTN_ERRNO_IF(*result == 0);
-  return 0;
-}
-
-int WRAP(lstat)(const char* path, struct nacl_abi_stat* nacl_buf) {
-  struct stat buf;
-  memset(&buf, 0, sizeof(struct stat));
-  int res = ki_lstat(path, &buf);
-  RTN_ERRNO_IF(res < 0);
-  stat_to_nacl_stat(&buf, nacl_buf);
-  return 0;
-}
-
-int WRAP(mkdir)(const char* pathname, mode_t mode) {
-  ERRNO_RTN(ki_mkdir(pathname, mode));
-}
-
-int WRAP(mmap)(void** addr,
-               size_t length,
-               int prot,
-               int flags,
-               int fd,
-               int64_t offset) {
-  if (flags & MAP_ANONYMOUS)
-    return REAL(mmap)(addr, length, prot, flags, fd, offset);
-
-  *addr = ki_mmap(*addr, length, prot, flags, fd, offset);
-  RTN_ERRNO_IF(*addr == (void*)-1)
-  return 0;
-}
-
-int WRAP(munmap)(void* addr, size_t length) {
-  // Always let the real munmap run on the address range. It is not an error if
-  // there are no mapped pages in that range.
-  ki_munmap(addr, length);
-  return REAL(munmap)(addr, length);
-}
-
-int WRAP(open)(const char* pathname, int oflag, mode_t mode, int* newfd) {
-  *newfd = ki_open(pathname, oflag, mode);
-  ERRNO_RTN(*newfd);
-}
-
-int WRAP(open_resource)(const char* file, int* fd) {
-  *fd = ki_open_resource(file);
-  ERRNO_RTN(*fd);
-}
-
-int WRAP(poll)(struct pollfd* fds, nfds_t nfds, int timeout, int* count) {
-  *count = ki_poll(fds, nfds, timeout);
-  ERRNO_RTN(*count);
-}
-
-int WRAP(read)(int fd, void* buf, size_t count, size_t* nread) {
-  ssize_t signed_nread = ki_read(fd, buf, count);
-  *nread = static_cast<size_t>(signed_nread);
-  ERRNO_RTN(signed_nread);
-}
-
-int WRAP(readlink)(const char* path, char* buf, size_t count, size_t* nread) {
-  ssize_t signed_nread = ki_readlink(path, buf, count);
-  *nread = static_cast<size_t>(signed_nread);
-  ERRNO_RTN(signed_nread);
-}
-
-int WRAP(rmdir)(const char* pathname) {
-  ERRNO_RTN(ki_rmdir(pathname));
-}
-
-int WRAP(seek)(int fd, off64_t offset, int whence, int64_t* new_offset) {
-  *new_offset = ki_lseek(fd, offset, whence);
-  ERRNO_RTN(*new_offset);
-}
-
-int WRAP(select)(int nfds,
-                 fd_set* readfds,
-                 fd_set* writefds,
-                 fd_set* exceptfds,
-                 struct timeval* timeout,
-                 int* count) {
-  *count = ki_select(nfds, readfds, writefds, exceptfds, timeout);
-  ERRNO_RTN(*count);
-}
-
-int WRAP(stat)(const char* pathname, struct nacl_abi_stat* nacl_buf) {
-  struct stat buf;
-  memset(&buf, 0, sizeof(struct stat));
-  int res = ki_stat(pathname, &buf);
-  RTN_ERRNO_IF(res < 0);
-  stat_to_nacl_stat(&buf, nacl_buf);
-  return 0;
-}
-
-int WRAP(truncate)(const char* name, int64_t len) {
-  ERRNO_RTN(ki_truncate(name, len));
-}
-
-int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) {
-  ssize_t signed_nwrote = ki_write(fd, buf, count);
-  *nwrote = static_cast<size_t>(signed_nwrote);
-  ERRNO_RTN(signed_nwrote);
-}
-
-static void assign_real_pointers() {
-  static bool assigned = false;
-  if (!assigned) {
-    EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
-    assigned = true;
-  }
-}
-
-#define CHECK_REAL(func) \
-  if (!REAL(func)) {          \
-    assign_real_pointers();   \
-    if (!REAL(func))          \
-      return ENOSYS;          \
-  }
-
-// "real" functions, i.e. the unwrapped original functions.
-
-int _real_close(int fd) {
-  CHECK_REAL(close);
-  return REAL(close)(fd);
-}
-
-void _real_exit(int status) {
-  REAL(exit)(status);
-}
-
-int _real_fchdir(int fd) {
-  CHECK_REAL(fchdir);
-  return REAL(fchdir)(fd);
-}
-
-int _real_fchmod(int fd, mode_t mode) {
-  CHECK_REAL(fchmod);
-  return REAL(fchmod)(fd, mode);
-}
-
-int _real_fdatasync(int fd) {
-  CHECK_REAL(fdatasync);
-  return REAL(fdatasync)(fd);
-}
-
-int _real_fstat(int fd, struct stat* buf) {
-  struct nacl_abi_stat st;
-  CHECK_REAL(fstat);
-
-  int err = REAL(fstat)(fd, (struct stat*)&st);
-  if (err) {
-    errno = err;
-    return -1;
-  }
-
-  nacl_stat_to_stat(&st, buf);
-  return 0;
-}
-
-int _real_fsync(int fd) {
-  CHECK_REAL(fsync);
-  return REAL(fsync)(fd);
-}
-
-int _real_getdents(int fd, void* buf, size_t count, size_t* nread) {
-  // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
-  // See WRAP(getdents) above.
-  char* nacl_buf = (char*)alloca(count);
-  size_t offset = 0;
-  size_t nacl_offset = 0;
-  size_t nacl_nread;
-  CHECK_REAL(getdents);
-  int err = REAL(getdents)(fd, (dirent*)nacl_buf, count, &nacl_nread);
-  if (err)
-    return err;
-
-  while (nacl_offset < nacl_nread) {
-    dirent* d = (dirent*)((char*)buf + offset);
-    nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)(nacl_buf + nacl_offset);
-    d->d_ino = nacl_d->nacl_abi_d_ino;
-    d->d_off = nacl_d->nacl_abi_d_off;
-    d->d_reclen = nacl_d->nacl_abi_d_reclen + d_name_shift;
-    size_t d_name_len =
-        nacl_d->nacl_abi_d_reclen - offsetof(nacl_abi_dirent, nacl_abi_d_name);
-    memcpy(d->d_name, nacl_d->nacl_abi_d_name, d_name_len);
-
-    offset += d->d_reclen;
-    offset += nacl_d->nacl_abi_d_reclen;
-  }
-
-  *nread = offset;
-  return 0;
-}
-
-int _real_isatty(int fd, int* result) {
-  *result = isatty(fd);
-  return *result ? 0 : -1;
-}
-
-int _real_lseek(int fd, int64_t offset, int whence, int64_t* new_offset) {
-  CHECK_REAL(seek);
-  nacl_abi_off_t nacl_new_offs;
-  int ret = REAL(seek)(fd, offset, whence, &nacl_new_offs);
-  *new_offset = static_cast<off_t>(nacl_new_offs);
-  return ret;
-}
-
-int _real_lstat(const char* path, struct stat* buf) {
-  struct nacl_abi_stat st;
-  CHECK_REAL(lstat);
-
-  int err = REAL(lstat)(path, (struct stat*)&st);
-  if (err) {
-    errno = err;
-    return -1;
-  }
-
-  nacl_stat_to_stat(&st, buf);
-  return 0;
-}
-
-int _real_mkdir(const char* pathname, mode_t mode) {
-  CHECK_REAL(mkdir);
-  return REAL(mkdir)(pathname, mode);
-}
-
-int _real_mmap(void** addr,
-               size_t length,
-               int prot,
-               int flags,
-               int fd,
-               int64_t offset) {
-  CHECK_REAL(mmap);
-  return REAL(mmap)(addr, length, prot, flags, fd, offset);
-}
-
-int _real_munmap(void* addr, size_t length) {
-  CHECK_REAL(munmap);
-  return REAL(munmap)(addr, length);
-}
-
-int _real_open(const char* pathname, int oflag, mode_t mode, int* newfd) {
-  CHECK_REAL(open);
-  return REAL(open)(pathname, oflag, mode, newfd);
-}
-
-int _real_open_resource(const char* file, int* fd) {
-  CHECK_REAL(open_resource);
-  return REAL(open_resource)(file, fd);
-}
-
-int _real_read(int fd, void* buf, size_t count, size_t* nread) {
-  CHECK_REAL(read);
-  return REAL(read)(fd, buf, count, nread);
-}
-
-int _real_readlink(const char* path, char* buf, size_t count, size_t* nread) {
-  CHECK_REAL(readlink);
-  return REAL(readlink)(path, buf, count, nread);
-}
-
-int _real_rmdir(const char* pathname) {
-  CHECK_REAL(rmdir);
-  return REAL(rmdir)(pathname);
-}
-
-int _real_truncate(const char* pathname, int64_t len) {
-  CHECK_REAL(truncate);
-  return REAL(truncate)(pathname, len);
-}
-
-int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) {
-  CHECK_REAL(write);
-  return REAL(write)(fd, buf, count, nwrote);
-}
-
-int _real_getcwd(char* pathname, size_t len) {
-  CHECK_REAL(getcwd);
-  return REAL(getcwd)(pathname, len);
-}
-
-static bool s_wrapped = false;
-
-void kernel_wrap_init() {
-  if (!s_wrapped) {
-    assign_real_pointers();
-    EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
-    s_wrapped = true;
-  }
-}
-
-void kernel_wrap_uninit() {
-  if (s_wrapped) {
-    EXPAND_SYMBOL_LIST_OPERATION(USE_REAL)
-    s_wrapped = false;
-  }
-}
-
-EXTERN_C_END
-
-#endif  // defined(__native_client__) && defined(__BIONIC__)
diff --git a/native_client_sdk/src/libraries/nacl_io/library.dsc b/native_client_sdk/src/libraries/nacl_io/library.dsc
index d13f5c1..4e9a76fd 100644
--- a/native_client_sdk/src/libraries/nacl_io/library.dsc
+++ b/native_client_sdk/src/libraries/nacl_io/library.dsc
@@ -1,5 +1,5 @@
 {
-  'TOOLS': ['clang-newlib', 'glibc', 'bionic', 'pnacl', 'linux', 'mac'],
+  'TOOLS': ['clang-newlib', 'glibc', 'pnacl', 'linux', 'mac'],
   'SEARCH': [
     '.',
     'pepper',
@@ -37,7 +37,6 @@
         "kernel_intercept.cc",
         "kernel_object.cc",
         "kernel_proxy.cc",
-        "kernel_wrap_bionic.cc",
         "kernel_wrap_dummy.cc",
         "kernel_wrap_glibc.cc",
         "kernel_wrap_irt_ext.c",
diff --git a/native_client_sdk/src/libraries/ppapi_simple/library.dsc b/native_client_sdk/src/libraries/ppapi_simple/library.dsc
index 8729ebe0..b5c36fba 100644
--- a/native_client_sdk/src/libraries/ppapi_simple/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi_simple/library.dsc
@@ -1,5 +1,5 @@
 {
-  'TOOLS': ['bionic', 'glibc', 'pnacl', 'linux', 'mac', 'clang-newlib'],
+  'TOOLS': ['glibc', 'pnacl', 'linux', 'mac', 'clang-newlib'],
   'TARGETS': [
     {
       'NAME' : 'ppapi_simple',
diff --git a/native_client_sdk/src/libraries/ppapi_simple_cpp/library.dsc b/native_client_sdk/src/libraries/ppapi_simple_cpp/library.dsc
index 272589766..7e74dcd 100644
--- a/native_client_sdk/src/libraries/ppapi_simple_cpp/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi_simple_cpp/library.dsc
@@ -1,5 +1,5 @@
 {
-  'TOOLS': ['bionic', 'glibc', 'pnacl', 'linux', 'mac', 'clang-newlib'],
+  'TOOLS': ['glibc', 'pnacl', 'linux', 'mac', 'clang-newlib'],
   'SEARCH': [
     '.',
     '../ppapi_simple'
diff --git a/native_client_sdk/src/libraries/ppapi_stub/library.dsc b/native_client_sdk/src/libraries/ppapi_stub/library.dsc
deleted file mode 100644
index fcb15cf6..0000000
--- a/native_client_sdk/src/libraries/ppapi_stub/library.dsc
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  'TOOLS': ['bionic'],
-  'SEARCH': [
-      '.',
-  ],
-  'TARGETS': [
-    {
-      'NAME' : 'ppapi_stub',
-      'TYPE' : 'lib',
-      'SOURCES' : [
-        'main.c',
-        'ppapi_main.c',
-      ],
-    }
-  ],
-  'DEST': 'src',
-  'NAME': 'ppapi_stub',
-}
-
diff --git a/native_client_sdk/src/libraries/ppapi_stub/main.c b/native_client_sdk/src/libraries/ppapi_stub/main.c
deleted file mode 100644
index c1428bc..0000000
--- a/native_client_sdk/src/libraries/ppapi_stub/main.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2014 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.
- */
-
-/*
- * An application that doesn't define its own main but links in -lppapi
- * gets this one.  A plugin may instead have its own main that calls
- * PpapiPluginMain (or PpapiPluginStart) after doing some other setup.
- */
-
-int PpapiPluginMain();
-
-int main(void) {
-  return PpapiPluginMain();
-}
diff --git a/native_client_sdk/src/libraries/ppapi_stub/ppapi_main.c b/native_client_sdk/src/libraries/ppapi_stub/ppapi_main.c
deleted file mode 100644
index be540b6..0000000
--- a/native_client_sdk/src/libraries/ppapi_stub/ppapi_main.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2014 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 <pthread.h>
-
-#include "irt_syscalls.h"
-#include "ppapi/c/pp_module.h"
-#include "ppapi/c/ppp.h"
-
-struct PP_StartFunctions {
-  int32_t (*PPP_InitializeModule)(PP_Module module_id,
-                                  PPB_GetInterface get_browser_interface);
-  void (*PPP_ShutdownModule)();
-  const void* (*PPP_GetInterface)(const char* interface_name);
-};
-
-struct PP_ThreadFunctions {
-  /*
-   * This is a cut-down version of pthread_create()/pthread_join().
-   * We omit thread creation attributes and the thread's return value.
-   *
-   * We use uintptr_t as the thread ID type because pthread_t is not
-   * part of the stable ABI; a user thread library might choose an
-   * arbitrary size for its own pthread_t.
-   */
-  int (*thread_create)(uintptr_t* tid,
-                       void (*func)(void* thread_argument),
-                       void* thread_argument);
-  int (*thread_join)(uintptr_t tid);
-};
-
-#define NACL_IRT_PPAPIHOOK_v0_1 "nacl-irt-ppapihook-0.1"
-struct nacl_irt_ppapihook {
-  int (*ppapi_start)(const struct PP_StartFunctions*);
-  void (*ppapi_register_thread_creator)(const struct PP_ThreadFunctions*);
-};
-
-
-static int thread_create(uintptr_t *tid,
-                         void (*func)(void *thread_argument),
-                         void *thread_argument) {
-  /*
-   * We know that newlib and glibc use a small pthread_t type, so we
-   * do not need to wrap pthread_t values.
-   */
-  return pthread_create((pthread_t *) tid, NULL,
-                        (void *(*)(void *thread_argument)) func,
-                        thread_argument);
-}
-
-static int thread_join(uintptr_t tid) {
-  return pthread_join((pthread_t) tid, NULL);
-}
-
-/*
- * These are dangling references to functions that the application must define.
- */
-static const struct PP_StartFunctions ppapi_app_start_callbacks = {
-  PPP_InitializeModule,
-  PPP_ShutdownModule,
-  PPP_GetInterface
-};
-
-const static struct PP_ThreadFunctions thread_funcs = {
-  thread_create,
-  thread_join
-};
-
-static void fatal_error(const char *message) {
-  write(2, message, strlen(message));
-  _exit(127);
-}
-
-/*
- * We cannot tell at link time whether the application uses PPB_Audio,
- * because of the way that PPAPI is defined via runtime interface
- * query rather than a set of static functions.  This means that we
- * register the audio thread functions unconditionally.  This adds the
- * small overhead of pulling in pthread_create() even if the
- * application does not use PPB_Audio or libpthread.
- *
- * If an application developer wants to avoid that cost, they can
- * override this function with an empty definition.
- */
-void __nacl_register_thread_creator(const struct nacl_irt_ppapihook *hooks) {
-  hooks->ppapi_register_thread_creator(&thread_funcs);
-}
-
-int PpapiPluginStart(const struct PP_StartFunctions *funcs) {
-  struct nacl_irt_ppapihook hooks;
-  if (sizeof(hooks) != __nacl_irt_query(NACL_IRT_PPAPIHOOK_v0_1,
-                                        &hooks, sizeof(hooks))) {
-    fatal_error("PpapiPluginStart: PPAPI hooks not found\n");
-  }
-
-  __nacl_register_thread_creator(&hooks);
-  return hooks.ppapi_start(funcs);
-}
-
-
-/*
- * The application's main (or the one supplied in this library) calls this
- * to start the PPAPI world.
- */
-int PpapiPluginMain(void) {
-  return PpapiPluginStart(&ppapi_app_start_callbacks);
-}
diff --git a/native_client_sdk/src/resources/Makefile.library.template b/native_client_sdk/src/resources/Makefile.library.template
index 92b9452b..05768d2 100644
--- a/native_client_sdk/src/resources/Makefile.library.template
+++ b/native_client_sdk/src/resources/Makefile.library.template
@@ -85,7 +85,7 @@
 $(foreach src,$({{sources}}),$(eval $(call COMPILE_RULE,$(src),$({{cflags}}))))
 $(eval $(call LIB_RULE,{{name}},$({{sources}})))
 [[    if target['TYPE'] != 'static-lib':]]
-ifneq (,$(findstring $(TOOLCHAIN),glibc bionic))
+ifneq (,$(findstring $(TOOLCHAIN),glibc))
 $(eval $(call SO_RULE,{{name}},$({{sources}}),$(LIBS),$(DEPS)))
 endif
 [[  ]]
diff --git a/native_client_sdk/src/tests/nacl_io_test/example.dsc b/native_client_sdk/src/tests/nacl_io_test/example.dsc
index 08899cd8..0a1055d 100644
--- a/native_client_sdk/src/tests/nacl_io_test/example.dsc
+++ b/native_client_sdk/src/tests/nacl_io_test/example.dsc
@@ -1,5 +1,5 @@
 {
-  'TOOLS': ['bionic', 'clang-newlib', 'glibc', 'pnacl', 'linux', 'mac'],
+  'TOOLS': ['clang-newlib', 'glibc', 'pnacl', 'linux', 'mac'],
   'SEL_LDR': True,
 
   'TARGETS': [
diff --git a/native_client_sdk/src/tools/common.mk b/native_client_sdk/src/tools/common.mk
index d385bcf..c3227985 100644
--- a/native_client_sdk/src/tools/common.mk
+++ b/native_client_sdk/src/tools/common.mk
@@ -14,11 +14,7 @@
 # If your project only builds in one or the other then this should be overridden
 # accordingly.
 #
-ifneq ($(ENABLE_BIONIC),)
-ALL_TOOLCHAINS ?= pnacl glibc clang-newlib bionic
-else
 ALL_TOOLCHAINS ?= pnacl glibc clang-newlib
-endif
 
 VALID_TOOLCHAINS ?= $(ALL_TOOLCHAINS)
 TOOLCHAIN ?= $(word 1,$(VALID_TOOLCHAINS))
@@ -428,7 +424,7 @@
 include $(NACL_SDK_ROOT)/tools/host_vc.mk
 endif
 
-ifneq (,$(findstring $(TOOLCHAIN),glibc bionic clang-newlib))
+ifneq (,$(findstring $(TOOLCHAIN),glibc clang-newlib))
 include $(NACL_SDK_ROOT)/tools/nacl_gcc.mk
 endif
 
diff --git a/native_client_sdk/src/tools/create_nmf.py b/native_client_sdk/src/tools/create_nmf.py
index fe4abb9..c1fe50ca 100755
--- a/native_client_sdk/src/tools/create_nmf.py
+++ b/native_client_sdk/src/tools/create_nmf.py
@@ -552,13 +552,6 @@
       'ports/lib/glibc_arm/%s' % config_fallback,
     ]
 
-  bionic_dir = 'toolchain/%s_arm_bionic' % osname
-  if os.path.isdir(os.path.join(sdk_root, bionic_dir)):
-    libpath += [
-      '%s/arm-nacl/lib' % bionic_dir,
-      '%s/arm-nacl/usr/lib' % bionic_dir,
-      'lib/bionic_arm/%s' % config,
-    ]
   libpath = [os.path.normpath(p) for p in libpath]
   libpath = [os.path.join(sdk_root, p) for p in libpath]
   libpath.append(os.path.join(sdk_root, 'tools'))
diff --git a/native_client_sdk/src/tools/lib/get_shared_deps.py b/native_client_sdk/src/tools/lib/get_shared_deps.py
index 5a3a658..5325df9e 100644
--- a/native_client_sdk/src/tools/lib/get_shared_deps.py
+++ b/native_client_sdk/src/tools/lib/get_shared_deps.py
@@ -210,16 +210,9 @@
   files = []
   for dirname in lib_path:
     # The libc.so files in the the glibc toolchain is actually a linker
-    # script which references libc.so.<SHA1>.  This means the lib.so itself
-    # does not end up in the NEEDED section for glibc.  However with bionic
-    # the SONAME is actually libc.so.  If we pass glibc's libc.so to objdump
-    # if fails to parse it, os this filters out libc.so expept for within
-    # the bionic toolchain.
-    # TODO(bradnelson): Remove this once the SONAME in bionic is made to be
-    # unique in the same it is under glibc:
-    # https://code.google.com/p/nativeclient/issues/detail?id=3833
-    rel_dirname = os.path.relpath(dirname, SDK_DIR)
-    if name == 'libc.so' and 'bionic' not in rel_dirname:
+    # script which references libc.so.<SHA1>.  This means the libc.so itself
+    # does not end up in the NEEDED section for glibc.
+    if name == 'libc.so':
       continue
     filename = os.path.join(dirname, name)
     if os.path.exists(filename):
diff --git a/native_client_sdk/src/tools/nacl_gcc.mk b/native_client_sdk/src/tools/nacl_gcc.mk
index f4fd613..2249734 100644
--- a/native_client_sdk/src/tools/nacl_gcc.mk
+++ b/native_client_sdk/src/tools/nacl_gcc.mk
@@ -10,7 +10,6 @@
 #
 # Macros for TOOLS
 #
-ifneq ($(TOOLCHAIN),bionic)
 X86_32_CC := $(NACL_COMPILER_PREFIX) $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) -a x86_32 --tool=cc)
 X86_32_CXX := $(NACL_COMPILER_PREFIX) $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) -a x86_32 --tool=c++)
 X86_32_LINK := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) -a x86_32 --tool=c++)
@@ -24,7 +23,6 @@
 X86_64_LIB := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) -a x86_64 --tool=ar)
 X86_64_STRIP := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) -a x86_64 --tool=strip)
 X86_64_NM := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) -a x86_64 --tool=nm)
-endif
 
 ARM_CC := $(NACL_COMPILER_PREFIX) $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) -a arm --tool=cc)
 ARM_CXX := $(NACL_COMPILER_PREFIX) $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) -a arm --tool=c++)
@@ -71,18 +69,6 @@
 ARM_LDFLAGS ?= -Wl,-Map,$(ARM_OUTDIR)/$(TARGET)_arm.map
 endif
 
-#
-# Choose between static and dynamic linking for Bionic
-# (Default to dynamic)
-#
-ifeq ($(TOOLCHAIN),bionic)
-ifeq (,$(BIONIC_USE_DYNAMIC))
-BIONIC_LINK:=-static
-else
-BIONIC_LINK:=-Wl,-Ttext-segment=0x100000
-endif
-endif
-
 LDFLAGS_SHARED = -shared
 
 #
@@ -174,10 +160,7 @@
 # Determine which architectures to build for.  The user can set NACL_ARCH or
 # ARCHES in the environment to control this.
 #
-ifneq ($(TOOLCHAIN),bionic)
-VALID_ARCHES := x86_32 x86_64
-endif
-VALID_ARCHES += arm
+VALID_ARCHES := x86_32 x86_64 arm
 
 ifdef NACL_ARCH
 ifeq (,$(findstring $(NACL_ARCH),$(VALID_ARCHES)))
@@ -361,7 +344,7 @@
 all: $(ARM_OUTDIR)/$(1)_arm.nexe
 $(ARM_OUTDIR)/$(1)_arm.nexe: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_arm)) $(foreach dep,$(4),$(STAMPDIR)/$(dep).stamp)
 	$(MKDIR) -p $$(dir $$@)
-	$(call LOG,LINK,$$@,$(ARM_LINK) $(BIONIC_LINK) -o $$@ $$(filter %.o,$$^) $(NACL_LDFLAGS) $(ARM_LDFLAGS) $(LDFLAGS) $(foreach path,$(6),-L$(path)/$(TOOLCHAIN)_arm/$(CONFIG_DIR) -L$(path)/$(TOOLCHAIN)_arm/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(5))
+	$(call LOG,LINK,$$@,$(ARM_LINK) -o $$@ $$(filter %.o,$$^) $(NACL_LDFLAGS) $(ARM_LDFLAGS) $(LDFLAGS) $(foreach path,$(6),-L$(path)/$(TOOLCHAIN)_arm/$(CONFIG_DIR) -L$(path)/$(TOOLCHAIN)_arm/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(5))
 	$(call LOG,VALIDATE,$$@,$(NCVAL) $$@)
 endif
 endef
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 74d0c67..d41f31c 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1600,12 +1600,17 @@
   }
 
   if (is_android) {
-    apk_deps = [
+    deps += [
+      ":net_test_jni_headers",
       "//base:base_java_unittest_support",
       "//net/android:net_java",
-      "//net/android:net_javatests",
       "//net/android:net_java_test_support",
+      "//net/android:net_javatests",
       "//net/android:net_unittests_apk_resources",
+
+      # TODO(mmenke):  This depends on test_support_base, which depends on
+      #                icu.  Figure out a way to remove that dependency.
+      "//testing/android/native_test:native_test_native_code",
       "//v8:v8_external_startup_data_assets",
     ]
     android_manifest = "//net/android/unittest_support/AndroidManifest.xml"
@@ -1613,13 +1618,6 @@
       # See bug http://crbug.com/344533.
       "disk_cache/blockfile/index_table_v3_unittest.cc",
     ]
-    deps += [
-      ":net_test_jni_headers",
-
-      # TODO(mmenke):  This depends on test_support_base, which depends on
-      #                icu.  Figure out a way to remove that dependency.
-      "//testing/android/native_test:native_test_native_code",
-    ]
     set_sources_assignment_filter([])
     sources += [ "base/address_tracker_linux_unittest.cc" ]
     set_sources_assignment_filter(sources_assignment_filter)
diff --git a/net/base/file_stream_context.cc b/net/base/file_stream_context.cc
index 3ddf4bb..6d77d6d 100644
--- a/net/base/file_stream_context.cc
+++ b/net/base/file_stream_context.cc
@@ -4,6 +4,8 @@
 
 #include "net/base/file_stream_context.h"
 
+#include <utility>
+
 #include "base/files/file_path.h"
 #include "base/location.h"
 #include "base/profiler/scoped_tracker.h"
@@ -54,17 +56,13 @@
       error_code(error_code) {
 }
 
-FileStream::Context::OpenResult::OpenResult(RValue other)
-    : file(other.object->file.Pass()),
-      error_code(other.object->error_code) {
-}
+FileStream::Context::OpenResult::OpenResult(OpenResult&& other)
+    : file(std::move(other.file)), error_code(other.error_code) {}
 
 FileStream::Context::OpenResult& FileStream::Context::OpenResult::operator=(
-    RValue other) {
-  if (this != other.object) {
-    file = other.object->file.Pass();
-    error_code = other.object->error_code;
-  }
+    OpenResult&& other) {
+  file = std::move(other.file);
+  error_code = other.error_code;
   return *this;
 }
 
diff --git a/net/base/file_stream_context.h b/net/base/file_stream_context.h
index c1846c46..a42634d 100644
--- a/net/base/file_stream_context.h
+++ b/net/base/file_stream_context.h
@@ -110,13 +110,12 @@
   };
 
   struct OpenResult {
-    MOVE_ONLY_TYPE_FOR_CPP_03(OpenResult, RValue)
+    MOVE_ONLY_TYPE_FOR_CPP_03(OpenResult)
    public:
     OpenResult();
     OpenResult(base::File file, IOResult error_code);
-    // C++03 move emulation of this type.
-    OpenResult(RValue other);
-    OpenResult& operator=(RValue other);
+    OpenResult(OpenResult&& other);
+    OpenResult& operator=(OpenResult&& other);
 
     base::File file;
     IOResult error_code;
diff --git a/net/disk_cache/simple/simple_index_file_unittest.cc b/net/disk_cache/simple/simple_index_file_unittest.cc
index ede0417..a2603d8 100644
--- a/net/disk_cache/simple/simple_index_file_unittest.cc
+++ b/net/disk_cache/simple/simple_index_file_unittest.cc
@@ -292,8 +292,8 @@
   // thread after that.
   MessageLoopHelper helper;
   CallbackTest cb_shutdown(&helper, false);
-  cache_thread.task_runner()->PostTask(
-      FROM_HERE,
+  cache_thread.task_runner()->PostTaskAndReply(
+      FROM_HERE, base::Bind(&base::DoNothing),
       base::Bind(&CallbackTest::Run, base::Unretained(&cb_shutdown), net::OK));
   helper.WaitUntilCacheIoFinished(1);
 
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index cd12aac..ee01c29 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -14,7 +14,6 @@
 #include "base/lazy_instance.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/third_party/valgrind/memcheck.h"
 #include "net/spdy/hpack/hpack_constants.h"
 #include "net/spdy/spdy_frame_builder.h"
 #include "net/spdy/spdy_frame_reader.h"
diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn
index 2aee690..815f8b6 100644
--- a/remoting/BUILD.gn
+++ b/remoting/BUILD.gn
@@ -157,7 +157,7 @@
     }
 
     if (is_android) {
-      apk_deps = [ "//net/android:net_java" ]
+      deps += [ "//net/android:net_java" ]
     }
   }
 
diff --git a/remoting/base/typed_buffer.h b/remoting/base/typed_buffer.h
index c80f720..fd46646 100644
--- a/remoting/base/typed_buffer.h
+++ b/remoting/base/typed_buffer.h
@@ -10,6 +10,7 @@
 #include <algorithm>
 
 #include "base/basictypes.h"
+#include "base/logging.h"
 #include "base/move.h"
 
 namespace remoting {
@@ -20,11 +21,10 @@
 // move-only semantics and typed buffer getters.
 template <typename T>
 class TypedBuffer {
-  MOVE_ONLY_TYPE_FOR_CPP_03(TypedBuffer, RValue)
+  MOVE_ONLY_TYPE_FOR_CPP_03(TypedBuffer)
 
  public:
-  TypedBuffer() : buffer_(NULL), length_(0) {
-  }
+  TypedBuffer() : TypedBuffer(0) {}
 
   // Creates an instance of the object allocating a buffer of the given size.
   explicit TypedBuffer(uint32 length) : buffer_(NULL), length_(length) {
@@ -32,12 +32,7 @@
       buffer_ = reinterpret_cast<T*>(new uint8[length_]);
   }
 
-  // Move constructor for C++03 move emulation of this type.
-  TypedBuffer(RValue rvalue) : buffer_(NULL), length_(0) {
-    TypedBuffer temp;
-    temp.Swap(*rvalue.object);
-    Swap(temp);
-  }
+  TypedBuffer(TypedBuffer&& rvalue) : TypedBuffer() { Swap(rvalue); }
 
   ~TypedBuffer() {
     if (buffer_) {
@@ -46,11 +41,8 @@
     }
   }
 
-  // Move operator= for C++03 move emulation of this type.
-  TypedBuffer& operator=(RValue rvalue) {
-    TypedBuffer temp;
-    temp.Swap(*rvalue.object);
-    Swap(temp);
+  TypedBuffer& operator=(TypedBuffer&& rvalue) {
+    Swap(rvalue);
     return *this;
   }
 
diff --git a/remoting/protocol/webrtc_data_stream_adapter.cc b/remoting/protocol/webrtc_data_stream_adapter.cc
new file mode 100644
index 0000000..9c1dac1a
--- /dev/null
+++ b/remoting/protocol/webrtc_data_stream_adapter.cc
@@ -0,0 +1,276 @@
+// 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 "remoting/protocol/webrtc_data_stream_adapter.h"
+
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/thread_task_runner_handle.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "remoting/base/compound_buffer.h"
+#include "remoting/protocol/p2p_stream_socket.h"
+
+static const int kMaxSendBufferSize = 256 * 1024;
+
+namespace remoting {
+namespace protocol {
+
+class WebrtcDataStreamAdapter::Channel : public P2PStreamSocket,
+                                         public webrtc::DataChannelObserver {
+ public:
+  typedef base::Callback<void(Channel* adapter, bool success)>
+      ConnectedCallback;
+
+  Channel(const ConnectedCallback& connected_callback);
+  ~Channel() override;
+
+  void Start(rtc::scoped_refptr<webrtc::DataChannelInterface> channel);
+
+  std::string name() { return channel_->label(); }
+
+  // P2PStreamSocket interface.
+  int Read(const scoped_refptr<net::IOBuffer>& buffer, int buffer_size,
+           const net::CompletionCallback &callback) override;
+  int Write(const scoped_refptr<net::IOBuffer>& buffer, int buffer_size,
+            const net::CompletionCallback &callback) override;
+
+ private:
+  // webrtc::DataChannelObserver interface.
+  void OnStateChange() override;
+  void OnMessage(const webrtc::DataBuffer& buffer) override;
+  void OnBufferedAmountChange(uint64_t previous_amount) override;
+
+  int DoWrite(const scoped_refptr<net::IOBuffer>& buffer, int buffer_size);
+
+  rtc::scoped_refptr<webrtc::DataChannelInterface> channel_;
+  ConnectedCallback connected_callback_;
+
+  scoped_refptr<net::IOBuffer> write_buffer_;
+  int write_buffer_size_;
+  net::CompletionCallback write_callback_;
+
+  scoped_refptr<net::IOBuffer> read_buffer_;
+  int read_buffer_size_;
+  net::CompletionCallback read_callback_;
+
+  CompoundBuffer received_data_buffer_;
+
+  base::WeakPtrFactory<Channel> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(Channel);
+};
+
+WebrtcDataStreamAdapter::Channel::Channel(
+    const ConnectedCallback& connected_callback)
+    : connected_callback_(connected_callback), weak_factory_(this) {}
+
+WebrtcDataStreamAdapter::Channel::~Channel() {
+  if (channel_) {
+    channel_->UnregisterObserver();
+    channel_->Close();
+  }
+}
+
+void WebrtcDataStreamAdapter::Channel::Start(
+    rtc::scoped_refptr<webrtc::DataChannelInterface> channel) {
+  DCHECK(!channel_);
+
+  channel_ = channel;
+  channel_->RegisterObserver(this);
+
+   if (channel_->state() == webrtc::DataChannelInterface::kOpen) {
+    base::ResetAndReturn(&connected_callback_).Run(this, true);
+  } else {
+    DCHECK_EQ(channel_->state(), webrtc::DataChannelInterface::kConnecting);
+  }
+}
+
+int WebrtcDataStreamAdapter::Channel::Read(
+    const scoped_refptr<net::IOBuffer>& buffer, int buffer_size,
+    const net::CompletionCallback& callback) {
+  DCHECK(read_callback_.is_null());
+
+  if (received_data_buffer_.total_bytes() == 0) {
+    read_buffer_ = buffer;
+    read_buffer_size_ = buffer_size;
+    read_callback_ = callback;
+    return net::ERR_IO_PENDING;
+  }
+
+  int bytes_to_copy =
+      std::min(buffer_size, received_data_buffer_.total_bytes());
+  received_data_buffer_.CopyTo(buffer->data(), bytes_to_copy);
+  received_data_buffer_.CropFront(bytes_to_copy);
+  return bytes_to_copy;
+}
+
+int WebrtcDataStreamAdapter::Channel::Write(
+    const scoped_refptr<net::IOBuffer>& buffer, int buffer_size,
+    const net::CompletionCallback& callback) {
+  DCHECK(write_callback_.is_null());
+
+  if (channel_->buffered_amount() >= kMaxSendBufferSize) {
+    write_buffer_ = buffer;
+    write_buffer_size_ = buffer_size;
+    write_callback_ = callback;
+    return net::ERR_IO_PENDING;
+  }
+
+  return DoWrite(buffer, buffer_size);
+}
+
+void WebrtcDataStreamAdapter::Channel::OnStateChange() {
+  switch (channel_->state()) {
+    case webrtc::DataChannelInterface::kConnecting:
+      break;
+
+    case webrtc::DataChannelInterface::kOpen:
+      DCHECK(!connected_callback_.is_null());
+      base::ResetAndReturn(&connected_callback_).Run(this, true);
+      break;
+
+    case webrtc::DataChannelInterface::kClosing: {
+      // Hold weak pointer for self to detect when one of the callbacks deletes
+      // the channel.
+      base::WeakPtr<Channel> self = weak_factory_.GetWeakPtr();
+      if (!connected_callback_.is_null()) {
+        base::ResetAndReturn(&connected_callback_).Run(this, false);
+      }
+
+      if (self && !read_callback_.is_null()) {
+        read_buffer_ = nullptr;
+        base::ResetAndReturn(&read_callback_).Run(net::ERR_CONNECTION_CLOSED);
+      }
+
+      if (self && !write_callback_.is_null()) {
+        write_buffer_ = nullptr;
+        base::ResetAndReturn(&write_callback_).Run(net::ERR_CONNECTION_CLOSED);
+      }
+      break;
+    }
+    case webrtc::DataChannelInterface::kClosed:
+      DCHECK(connected_callback_.is_null());
+      break;
+  }
+}
+
+void WebrtcDataStreamAdapter::Channel::OnMessage(
+    const webrtc::DataBuffer& buffer) {
+  const char* data = reinterpret_cast<const char*>(buffer.data.data());
+  int data_size = buffer.data.size();
+
+  // If there is no outstanding read request then just copy the data to
+  // |received_data_buffer_|.
+  if (read_callback_.is_null()) {
+    received_data_buffer_.AppendCopyOf(data, data_size);
+    return;
+  }
+
+  DCHECK(received_data_buffer_.total_bytes() == 0);
+  int bytes_to_copy = std::min(read_buffer_size_, data_size);
+  memcpy(read_buffer_->data(), buffer.data.data(), bytes_to_copy);
+
+  if (bytes_to_copy < data_size) {
+    received_data_buffer_.AppendCopyOf(data + bytes_to_copy,
+                                       data_size - bytes_to_copy);
+  }
+  read_buffer_ = nullptr;
+  base::ResetAndReturn(&read_callback_).Run(bytes_to_copy);
+}
+
+void WebrtcDataStreamAdapter::Channel::OnBufferedAmountChange(
+    uint64_t previous_amount) {
+  if (channel_->buffered_amount() < kMaxSendBufferSize) {
+    base::ResetAndReturn(&write_callback_)
+        .Run(DoWrite(write_buffer_, write_buffer_size_));
+  }
+}
+
+int WebrtcDataStreamAdapter::Channel::DoWrite(
+    const scoped_refptr<net::IOBuffer>& buffer,
+    int buffer_size) {
+  webrtc::DataBuffer data_buffer(rtc::Buffer(buffer->data(), buffer_size),
+                                 true /* binary */);
+  if (channel_->Send(data_buffer)) {
+    return buffer_size;
+  } else {
+    return net::ERR_FAILED;
+  }
+}
+
+WebrtcDataStreamAdapter::WebrtcDataStreamAdapter() : weak_factory_(this) {}
+
+WebrtcDataStreamAdapter::~WebrtcDataStreamAdapter() {
+  DCHECK(pending_channels_.empty());
+}
+
+void WebrtcDataStreamAdapter::Initialize(
+    rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection,
+    bool is_server) {
+  peer_connection_ = peer_connection;
+  is_server_ = is_server;
+
+ if (!is_server_) {
+    for (auto& channel : pending_channels_) {
+      webrtc::DataChannelInit config;
+      config.reliable = true;
+      channel.second->Start(
+          peer_connection_->CreateDataChannel(channel.first, &config));
+    }
+ }
+}
+
+void WebrtcDataStreamAdapter::OnIncomingDataChannel(
+    webrtc::DataChannelInterface* data_channel) {
+  auto it = pending_channels_.find(data_channel->label());
+  if (!is_server_ || it == pending_channels_.end()) {
+    LOG(ERROR) << "Received unexpected data channel " << data_channel->label();
+    return;
+  }
+  it->second->Start(data_channel);
+}
+
+void WebrtcDataStreamAdapter::CreateChannel(
+    const std::string& name,
+    const ChannelCreatedCallback& callback) {
+  DCHECK(pending_channels_.find(name) == pending_channels_.end());
+
+  Channel* channel =
+      new Channel(base::Bind(&WebrtcDataStreamAdapter::OnChannelConnected,
+                             base::Unretained(this), callback));
+  pending_channels_[name] = channel;
+
+  if (peer_connection_ && !is_server_) {
+    webrtc::DataChannelInit config;
+    config.reliable = true;
+    channel->Start(peer_connection_->CreateDataChannel(name, &config));
+  }
+}
+
+void WebrtcDataStreamAdapter::CancelChannelCreation(const std::string& name) {
+  auto it = pending_channels_.find(name);
+  DCHECK(it != pending_channels_.end());
+  delete it->second;
+  pending_channels_.erase(it);
+}
+
+void WebrtcDataStreamAdapter::OnChannelConnected(
+    const ChannelCreatedCallback& connected_callback,
+    Channel* channel,
+    bool connected) {
+  auto it = pending_channels_.find(channel->name());
+  DCHECK(it != pending_channels_.end());
+  pending_channels_.erase(it);
+
+  // The callback can delete the channel which also holds the callback
+  // object which may cause crash if the callback carries some arguments. Copy
+  // the callback to stack to avoid this problem.
+  ChannelCreatedCallback callback = connected_callback;
+  callback.Run(make_scoped_ptr(channel));
+}
+
+}  // namespace protocol
+}  // namespace remoting
diff --git a/remoting/protocol/webrtc_data_stream_adapter.h b/remoting/protocol/webrtc_data_stream_adapter.h
new file mode 100644
index 0000000..1200db6
--- /dev/null
+++ b/remoting/protocol/webrtc_data_stream_adapter.h
@@ -0,0 +1,59 @@
+// 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 REMOTING_PROTOCOL_WEBRTC_DATA_STREAM_ADAPTER_H_
+#define REMOTING_PROTOCOL_WEBRTC_DATA_STREAM_ADAPTER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "remoting/protocol/stream_channel_factory.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+#include "third_party/webrtc/base/refcount.h"
+
+namespace rtc {
+class PeerConnectionInterface;
+}  // namespace rtc
+
+namespace remoting {
+namespace protocol {
+
+class WebrtcDataStreamAdapter : public StreamChannelFactory {
+ public:
+  WebrtcDataStreamAdapter();
+  ~WebrtcDataStreamAdapter() override;
+
+  void Initialize(
+      rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection,
+      bool is_server);
+
+  void OnIncomingDataChannel(webrtc::DataChannelInterface* data_channel);
+
+  // StreamChannelFactory interface.
+  void CreateChannel(const std::string& name,
+                     const ChannelCreatedCallback& callback) override;
+  void CancelChannelCreation(const std::string& name) override;
+
+ private:
+  class Channel;
+
+  void OnChannelConnected(const ChannelCreatedCallback& connected_callback,
+                          Channel* channel,
+                          bool connected);
+
+  rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
+  bool is_server_ = false;
+
+  std::map<std::string, Channel*> pending_channels_;
+
+  base::WeakPtrFactory<WebrtcDataStreamAdapter> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebrtcDataStreamAdapter);
+};
+
+}  // namespace protocol
+}  // namespace remoting
+
+#endif  // REMOTING_PROTOCOL_WEBRTC_DATA_STREAM_ADAPTER_H_
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc
index 4bc629b..295ef9ce 100644
--- a/remoting/protocol/webrtc_transport.cc
+++ b/remoting/protocol/webrtc_transport.cc
@@ -225,9 +225,7 @@
 
 StreamChannelFactory* WebrtcTransport::GetStreamChannelFactory() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  // TODO(sergeyu): Implement data stream support.
-  NOTIMPLEMENTED();
-  return nullptr;
+  return &data_stream_adapter_;
 }
 
 StreamChannelFactory* WebrtcTransport::GetMultiplexedChannelFactory() {
@@ -261,6 +259,9 @@
   peer_connection_ = peer_connection_factory_->CreatePeerConnection(
       rtc_config, &constraints, port_allocator_factory_, nullptr, this);
 
+  data_stream_adapter_.Initialize(peer_connection_,
+                                  role_ == TransportRole::SERVER);
+
   if (role_ == TransportRole::CLIENT) {
     webrtc::FakeConstraints offer_config;
     offer_config.AddMandatory(
@@ -269,6 +270,9 @@
     offer_config.AddMandatory(
         webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
         webrtc::MediaConstraintsInterface::kValueFalse);
+    offer_config.AddMandatory(
+        webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
+        webrtc::MediaConstraintsInterface::kValueTrue);
     peer_connection_->CreateOffer(
         CreateSessionDescriptionObserver::Create(
             base::Bind(&WebrtcTransport::OnLocalSessionDescriptionCreated,
@@ -386,7 +390,7 @@
 void WebrtcTransport::OnDataChannel(
     webrtc::DataChannelInterface* data_channel) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  // TODO(sergeyu): Use the data channel.
+  data_stream_adapter_.OnIncomingDataChannel(data_channel);
 }
 
 void WebrtcTransport::OnRenegotiationNeeded() {
diff --git a/remoting/protocol/webrtc_transport.h b/remoting/protocol/webrtc_transport.h
index cbc6458d..f480ee6 100644
--- a/remoting/protocol/webrtc_transport.h
+++ b/remoting/protocol/webrtc_transport.h
@@ -13,6 +13,7 @@
 #include "base/threading/thread_checker.h"
 #include "base/timer/timer.h"
 #include "remoting/protocol/transport.h"
+#include "remoting/protocol/webrtc_data_stream_adapter.h"
 #include "remoting/signaling/signal_strategy.h"
 #include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
 
@@ -90,6 +91,8 @@
   std::list<rtc::scoped_refptr<webrtc::MediaStreamInterface>>
       unclaimed_streams_;
 
+  WebrtcDataStreamAdapter data_stream_adapter_;
+
   base::WeakPtrFactory<WebrtcTransport> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(WebrtcTransport);
diff --git a/remoting/protocol/webrtc_transport_unittest.cc b/remoting/protocol/webrtc_transport_unittest.cc
index 8f21cca..d327085 100644
--- a/remoting/protocol/webrtc_transport_unittest.cc
+++ b/remoting/protocol/webrtc_transport_unittest.cc
@@ -7,10 +7,13 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "jingle/glue/thread_wrapper.h"
+#include "net/base/io_buffer.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "remoting/protocol/chromium_port_allocator_factory.h"
+#include "remoting/protocol/connection_tester.h"
 #include "remoting/protocol/fake_authenticator.h"
 #include "remoting/protocol/network_settings.h"
+#include "remoting/protocol/p2p_stream_socket.h"
 #include "remoting/signaling/fake_signal_strategy.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
@@ -21,6 +24,7 @@
 namespace {
 
 const char kTestJid[] = "client@gmail.com/321";
+const char kChannelName[] = "test_channel";
 
 class TestTransportEventHandler : public Transport::EventHandler {
  public:
@@ -82,12 +86,49 @@
   }
 
  protected:
-  void WaitUntilConnected() {
-    host_event_handler_.set_error_callback(base::Bind(
-        &WebrtcTransportTest::QuitRunLoopOnError, base::Unretained(this)));
-    client_event_handler_.set_error_callback(base::Bind(
-        &WebrtcTransportTest::QuitRunLoopOnError, base::Unretained(this)));
+  void InitializeConnection() {
+    signal_strategy_.reset(new FakeSignalStrategy(kTestJid));
 
+    host_transport_factory_.reset(new WebrtcTransportFactory(
+        signal_strategy_.get(),
+        ChromiumPortAllocatorFactory::Create(network_settings_, nullptr),
+        TransportRole::SERVER));
+    host_transport_ = host_transport_factory_->CreateTransport();
+    host_authenticator_.reset(new FakeAuthenticator(
+        FakeAuthenticator::HOST, 0, FakeAuthenticator::ACCEPT, false));
+
+    client_transport_factory_.reset(new WebrtcTransportFactory(
+        signal_strategy_.get(),
+        ChromiumPortAllocatorFactory::Create(network_settings_, nullptr),
+        TransportRole::CLIENT));
+    client_transport_ = client_transport_factory_->CreateTransport();
+    host_authenticator_.reset(new FakeAuthenticator(
+        FakeAuthenticator::CLIENT, 0, FakeAuthenticator::ACCEPT, false));
+
+    // Connect signaling between the two WebrtcTransport objects.
+    host_event_handler_.set_transport_info_callback(
+        base::Bind(&WebrtcTransportTest::ProcessTransportInfo,
+                   base::Unretained(this), &client_transport_));
+    client_event_handler_.set_transport_info_callback(
+        base::Bind(&WebrtcTransportTest::ProcessTransportInfo,
+                   base::Unretained(this), &host_transport_));
+  }
+
+  void StartConnection() {
+    host_event_handler_.set_connected_callback(base::Bind(&base::DoNothing));
+    client_event_handler_.set_connected_callback(base::Bind(&base::DoNothing));
+
+    host_event_handler_.set_error_callback(base::Bind(
+        &WebrtcTransportTest::OnSessionError, base::Unretained(this)));
+    client_event_handler_.set_error_callback(base::Bind(
+        &WebrtcTransportTest::OnSessionError, base::Unretained(this)));
+
+    host_transport_->Start(&host_event_handler_, host_authenticator_.get());
+    client_transport_->Start(&client_event_handler_,
+                             client_authenticator_.get());
+  }
+
+  void WaitUntilConnected() {
     int counter = 2;
     host_event_handler_.set_connected_callback(
         base::Bind(&WebrtcTransportTest::QuitRunLoopOnCounter,
@@ -102,7 +143,28 @@
     EXPECT_EQ(OK, error_);
   }
 
-  void QuitRunLoopOnError(ErrorCode error) {
+  void CreateDataStream() {
+    client_transport_->GetStreamChannelFactory()->CreateChannel(
+        kChannelName, base::Bind(&WebrtcTransportTest::OnClientChannelCreated,
+                                 base::Unretained(this)));
+    host_transport_->GetStreamChannelFactory()->CreateChannel(
+        kChannelName, base::Bind(&WebrtcTransportTest::OnHostChannelCreated,
+                                 base::Unretained(this)));
+  }
+
+  void OnClientChannelCreated(scoped_ptr<P2PStreamSocket> socket) {
+    client_socket_ = socket.Pass();
+    if (run_loop_ && host_socket_)
+      run_loop_->Quit();
+  }
+
+  void OnHostChannelCreated(scoped_ptr<P2PStreamSocket> socket) {
+    host_socket_ = socket.Pass();
+    if (run_loop_ && client_socket_)
+      run_loop_->Quit();
+  }
+
+  void OnSessionError(ErrorCode error) {
     error_ = error;
     run_loop_->Quit();
   }
@@ -131,41 +193,34 @@
   TestTransportEventHandler client_event_handler_;
   scoped_ptr<FakeAuthenticator> client_authenticator_;
 
+  scoped_ptr<P2PStreamSocket> client_socket_;
+  scoped_ptr<P2PStreamSocket> host_socket_;
+
   ErrorCode error_ = OK;
 };
 
 TEST_F(WebrtcTransportTest, Connects) {
-  signal_strategy_.reset(new FakeSignalStrategy(kTestJid));
-
-  host_transport_factory_.reset(new WebrtcTransportFactory(
-      signal_strategy_.get(),
-      ChromiumPortAllocatorFactory::Create(network_settings_, nullptr),
-      TransportRole::SERVER));
-  host_transport_ = host_transport_factory_->CreateTransport();
-  host_authenticator_.reset(new FakeAuthenticator(
-      FakeAuthenticator::HOST, 0, FakeAuthenticator::ACCEPT, false));
-
-  client_transport_factory_.reset(new WebrtcTransportFactory(
-      signal_strategy_.get(),
-      ChromiumPortAllocatorFactory::Create(network_settings_, nullptr),
-      TransportRole::CLIENT));
-  client_transport_ = client_transport_factory_->CreateTransport();
-  host_authenticator_.reset(new FakeAuthenticator(
-      FakeAuthenticator::CLIENT, 0, FakeAuthenticator::ACCEPT, false));
-
-  // Connect signaling between the two WebrtcTransport objects.
-  host_event_handler_.set_transport_info_callback(
-      base::Bind(&WebrtcTransportTest::ProcessTransportInfo,
-                 base::Unretained(this), &client_transport_));
-  client_event_handler_.set_transport_info_callback(
-      base::Bind(&WebrtcTransportTest::ProcessTransportInfo,
-                 base::Unretained(this), &host_transport_));
-
-  host_transport_->Start(&host_event_handler_, host_authenticator_.get());
-  client_transport_->Start(&client_event_handler_, client_authenticator_.get());
-
+  InitializeConnection();
+  StartConnection();
   WaitUntilConnected();
 }
 
+TEST_F(WebrtcTransportTest, DataStream) {
+  InitializeConnection();
+  CreateDataStream();
+  StartConnection();
+
+  run_loop_.reset(new base::RunLoop());
+  run_loop_->Run();
+
+  const int kMessageSize = 1024;
+  const int kMessages = 100;
+  StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
+                                kMessageSize, kMessages);
+  tester.Start();
+  message_loop_.Run();
+  tester.CheckResults();
+}
+
 }  // namespace protocol
 }  // namespace remoting
diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi
index 69f9bbc..3286efe 100644
--- a/remoting/remoting_srcs.gypi
+++ b/remoting/remoting_srcs.gypi
@@ -216,6 +216,8 @@
       'protocol/ice_connection_to_client.h',
       'protocol/video_frame_pump.cc',
       'protocol/video_frame_pump.h',
+      'protocol/webrtc_data_stream_adapter.cc',
+      'protocol/webrtc_data_stream_adapter.h',
       'protocol/webrtc_transport.cc',
       'protocol/webrtc_transport.h',
       'protocol/webrtc_video_capturer_adapter.cc',
diff --git a/storage/browser/blob/scoped_file.cc b/storage/browser/blob/scoped_file.cc
index 825dc04..b57e88208 100644
--- a/storage/browser/blob/scoped_file.cc
+++ b/storage/browser/blob/scoped_file.cc
@@ -29,8 +29,8 @@
       << " runner:" << file_task_runner.get();
 }
 
-ScopedFile::ScopedFile(RValue other) {
-  MoveFrom(*other.object);
+ScopedFile::ScopedFile(ScopedFile&& other) {
+  MoveFrom(other);
 }
 
 ScopedFile::~ScopedFile() {
diff --git a/storage/browser/blob/scoped_file.h b/storage/browser/blob/scoped_file.h
index a8fd730..583ce78 100644
--- a/storage/browser/blob/scoped_file.h
+++ b/storage/browser/blob/scoped_file.h
@@ -27,10 +27,7 @@
 // TODO(kinuko): Probably this can be moved under base or somewhere more
 // common place.
 class STORAGE_EXPORT ScopedFile {
-  // To support destructive assignment from an l-value assignment.
-  // This provides Pass() method which creates an r-value for the current
-  // instance. (See base/move.h for details)
-  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedFile, RValue)
+  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedFile)
 
  public:
   typedef base::Callback<void(const base::FilePath&)> ScopeOutCallback;
@@ -53,9 +50,9 @@
 
   // Move constructor and operator. The data of r-value will be transfered
   // in a destructive way. (See base/move.h)
-  ScopedFile(RValue other);
-  ScopedFile& operator=(RValue rhs) {
-    MoveFrom(*rhs.object);
+  ScopedFile(ScopedFile&& other);
+  ScopedFile& operator=(ScopedFile&& rhs) {
+    MoveFrom(rhs);
     return *this;
   }
 
diff --git a/sync/BUILD.gn b/sync/BUILD.gn
index c6fd22b8..d4d89d1 100644
--- a/sync/BUILD.gn
+++ b/sync/BUILD.gn
@@ -32,7 +32,7 @@
     "api/entity_data.cc",
     "api/entity_data.h",
     "api/metadata_batch.h",
-    "api/metadata_changes.h",
+    "api/metadata_change_list.h",
     "api/model_type_change_processor.cc",
     "api/model_type_change_processor.h",
     "api/model_type_service.cc",
@@ -235,6 +235,8 @@
     "internal_api/public/events/normal_get_updates_request_event.h",
     "internal_api/public/events/poll_get_updates_request_event.h",
     "internal_api/public/events/protocol_event.h",
+    "internal_api/public/fully_serialized_metadata_batch.cc",
+    "internal_api/public/fully_serialized_metadata_batch.h",
     "internal_api/public/http_bridge.h",
     "internal_api/public/http_bridge_network_resources.h",
     "internal_api/public/http_post_provider_factory.h",
@@ -264,6 +266,10 @@
     "internal_api/public/sessions/update_counters.h",
     "internal_api/public/shared_model_type_processor.h",
     "internal_api/public/shutdown_reason.h",
+    "internal_api/public/simple_metadata_change_list.cc",
+    "internal_api/public/simple_metadata_change_list.h",
+    "internal_api/public/specifics_only_data_batch.cc",
+    "internal_api/public/specifics_only_data_batch.h",
     "internal_api/public/sync_auth_provider.h",
     "internal_api/public/sync_context.h",
     "internal_api/public/sync_context_proxy.h",
diff --git a/sync/api/data_batch.h b/sync/api/data_batch.h
index 63359cf..f66b5960 100644
--- a/sync/api/data_batch.h
+++ b/sync/api/data_batch.h
@@ -9,7 +9,7 @@
 
 namespace syncer_v2 {
 
-// Interface used by the processor and service to communicate about data.
+// Interface used by the processor to read data requested from the service.
 class SYNC_EXPORT DataBatch {
  public:
   DataBatch() {}
diff --git a/sync/api/metadata_batch.h b/sync/api/metadata_batch.h
index 56ffffb..459999cde1 100644
--- a/sync/api/metadata_batch.h
+++ b/sync/api/metadata_batch.h
@@ -9,7 +9,7 @@
 
 namespace syncer_v2 {
 
-// Interface used by the processor and service to communicate about metadata.
+// Interface used by the processor to read metadata requested from the service.
 class SYNC_EXPORT MetadataBatch {
  public:
   MetadataBatch() {}
diff --git a/sync/api/metadata_changes.h b/sync/api/metadata_change_list.h
similarity index 60%
rename from sync/api/metadata_changes.h
rename to sync/api/metadata_change_list.h
index a3d4d3ba..e4435a8 100644
--- a/sync/api/metadata_changes.h
+++ b/sync/api/metadata_change_list.h
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SYNC_API_METADATA_CHANGES_H_
-#define SYNC_API_METADATA_CHANGES_H_
+#ifndef SYNC_API_METADATA_CHANGE_LIST_H_
+#define SYNC_API_METADATA_CHANGE_LIST_H_
 
 #include "sync/base/sync_export.h"
 
 namespace syncer_v2 {
 
 // Interface used by the processor and service to communicate about metadata.
-class SYNC_EXPORT MetadataChanges {
+class SYNC_EXPORT MetadataChangeList {
  public:
-  MetadataChanges() {}
-  virtual ~MetadataChanges() {}
+  MetadataChangeList() {}
+  virtual ~MetadataChangeList() {}
 };
 
 }  // namespace syncer_v2
 
-#endif  // SYNC_API_METADATA_CHANGES_H_
+#endif  // SYNC_API_METADATA_CHANGE_LIST_H_
diff --git a/sync/api/model_type_change_processor.h b/sync/api/model_type_change_processor.h
index 7781a0e3..70874b3 100644
--- a/sync/api/model_type_change_processor.h
+++ b/sync/api/model_type_change_processor.h
@@ -17,7 +17,7 @@
 
 namespace syncer_v2 {
 
-class MetadataChanges;
+class MetadataChangeList;
 
 // Interface used by the ModelTypeService to inform sync of local
 // changes.
@@ -30,11 +30,11 @@
   virtual void Put(const std::string& client_key,
                    const std::string& non_unique_name,
                    const sync_pb::EntitySpecifics& specifics,
-                   MetadataChanges* metadata_changes) = 0;
+                   MetadataChangeList* metadata_change_list) = 0;
 
   // Inform the processor of a deleted entity.
   virtual void Delete(const std::string& client_key,
-                      MetadataChanges* metadata_changes) = 0;
+                      MetadataChangeList* metadata_change_list) = 0;
 };
 
 }  // namespace syncer_v2
diff --git a/sync/api/model_type_service.h b/sync/api/model_type_service.h
index c09271b..6ae8bd3f 100644
--- a/sync/api/model_type_service.h
+++ b/sync/api/model_type_service.h
@@ -23,7 +23,7 @@
 
 class DataBatch;
 class MetadataBatch;
-class MetadataChanges;
+class MetadataChangeList;
 
 // Interface implemented by model types to receive updates from sync via the
 // SharedModelTypeProcessor. Provides a way for sync to update the data and
@@ -42,16 +42,17 @@
 
   // Creates an object used to communicate changes in the sync metadata to the
   // model type store.
-  virtual MetadataChanges* CreateMetadataChanges() = 0;
+  virtual scoped_ptr<MetadataChangeList> CreateMetadataChangeList() = 0;
 
   // Perform the initial merge of data from the sync server. Should only need
   // to be called when sync is first turned on, not on every restart.
-  virtual syncer::SyncError MergeSyncData(MetadataChanges* metadata_changes,
-                                          EntityDataList entity_data_list) = 0;
+  virtual syncer::SyncError MergeSyncData(
+      scoped_ptr<MetadataChangeList> metadata_change_list,
+      EntityDataList entity_data_list) = 0;
 
   // Apply changes from the sync server locally.
   virtual syncer::SyncError ApplySyncChanges(
-      MetadataChanges* metadata_changes,
+      scoped_ptr<MetadataChangeList> metadata_change_list,
       EntityChangeList entity_changes) = 0;
 
   // Asynchronously retrieve the sync metadata.
@@ -64,7 +65,7 @@
   virtual void GetAllData(DataCallback callback) = 0;
 
   // Get or generate a client tag for |entity_data|.
-  virtual std::string GetClientTag(const EntityData* entity_data) = 0;
+  virtual std::string GetClientTag(const EntityData& entity_data) = 0;
 
   // TODO(skym): See crbug/547087, do we need all these accessors?
   syncer_v2::ModelTypeChangeProcessor* change_processor();
diff --git a/sync/internal_api/public/fully_serialized_metadata_batch.cc b/sync/internal_api/public/fully_serialized_metadata_batch.cc
new file mode 100644
index 0000000..820bdeb
--- /dev/null
+++ b/sync/internal_api/public/fully_serialized_metadata_batch.cc
@@ -0,0 +1,20 @@
+// 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 "sync/internal_api/public/fully_serialized_metadata_batch.h"
+
+namespace syncer_v2 {
+
+void FullySerializedMetadataBatch::PutMetadata(
+    const std::string& client_key,
+    const std::string& serialized_metadata) {
+  // TODO(skym): Implementation.
+}
+
+void FullySerializedMetadataBatch::PutGlobalMetadata(
+    const std::string& serialized_global_metadata) {
+  // TODO(skym): Implementation.
+}
+
+}  // namespace syncer_v2
diff --git a/sync/internal_api/public/fully_serialized_metadata_batch.h b/sync/internal_api/public/fully_serialized_metadata_batch.h
new file mode 100644
index 0000000..99820249
--- /dev/null
+++ b/sync/internal_api/public/fully_serialized_metadata_batch.h
@@ -0,0 +1,32 @@
+// 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 SYNC_INTERNAL_API_PUBLIC_FULLY_SERIALIZED_METADATA_BATCH_H_
+#define SYNC_INTERNAL_API_PUBLIC_FULLY_SERIALIZED_METADATA_BATCH_H_
+
+#include <string>
+
+#include "sync/api/metadata_batch.h"
+
+namespace syncer_v2 {
+
+// An implementation of MetadataBatch meant for services that have no need to
+// understand any of the sync metadata, and simply store/read it in a fully
+// serialized form.
+class FullySerializedMetadataBatch : public MetadataBatch {
+ public:
+  // Incorperates the given metadata at the given storage key into the batch,
+  // handling deserialization. Multiple invocations with the same client key is
+  // currently undefined.
+  void PutMetadata(const std::string& client_key,
+                   const std::string& serialized_metadata);
+
+  // Incorperates the given global metadata into the batch, handling
+  // deserialization. Multiple invocations will use the last value.
+  void PutGlobalMetadata(const std::string& serialized_global_metadata);
+};
+
+}  // namespace syncer_v2
+
+#endif  // SYNC_INTERNAL_API_PUBLIC_FULLY_SERIALIZED_METADATA_BATCH_H_
diff --git a/sync/internal_api/public/shared_model_type_processor.h b/sync/internal_api/public/shared_model_type_processor.h
index 0c47f69b..a7d8f0f 100644
--- a/sync/internal_api/public/shared_model_type_processor.h
+++ b/sync/internal_api/public/shared_model_type_processor.h
@@ -69,9 +69,9 @@
   void Put(const std::string& client_key,
            const std::string& non_unique_name,
            const sync_pb::EntitySpecifics& specifics,
-           MetadataChanges* metadata_changes) override;
+           MetadataChangeList* metadata_change_list) override;
   void Delete(const std::string& client_key,
-              MetadataChanges* metadata_changes) override;
+              MetadataChangeList* metadata_change_list) override;
 
   // Returns the list of pending updates.
   //
diff --git a/sync/internal_api/public/simple_metadata_change_list.cc b/sync/internal_api/public/simple_metadata_change_list.cc
new file mode 100644
index 0000000..27d2b41
--- /dev/null
+++ b/sync/internal_api/public/simple_metadata_change_list.cc
@@ -0,0 +1,19 @@
+// 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 "sync/internal_api/public/simple_metadata_change_list.h"
+
+namespace syncer_v2 {
+
+SimpleMetadataChangeList::SimpleMetadataChangeList() {}
+
+SimpleMetadataChangeList::~SimpleMetadataChangeList() {}
+
+void SimpleMetadataChangeList::TranfserChanges(
+    ModelTypeStore* store,
+    ModelTypeStore::WriteBatch* write_batch) {
+  // TODO(skym): Implementation.
+}
+
+}  // namespace syncer_v2
diff --git a/sync/internal_api/public/simple_metadata_change_list.h b/sync/internal_api/public/simple_metadata_change_list.h
new file mode 100644
index 0000000..12bbe59
--- /dev/null
+++ b/sync/internal_api/public/simple_metadata_change_list.h
@@ -0,0 +1,31 @@
+// 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 SYNC_INTERNAL_API_PUBLIC_SIMPLE_METADATA_CHANGE_LIST_H_
+#define SYNC_INTERNAL_API_PUBLIC_SIMPLE_METADATA_CHANGE_LIST_H_
+
+#include "sync/api/metadata_change_list.h"
+#include "sync/api/model_type_store.h"
+#include "sync/base/sync_export.h"
+
+namespace syncer_v2 {
+
+// A MetadataChangeList implementation that is meant to be used in combination
+// with a ModelTypeStore. It accumulates changes in member fields, and then when
+// requested transfers them to the store/write batch.
+class SYNC_EXPORT SimpleMetadataChangeList : public MetadataChangeList {
+ public:
+  SimpleMetadataChangeList();
+  ~SimpleMetadataChangeList() override;
+
+  // Moves all currently accumulated changes into the write batch, clear out
+  // local copies. Calling this multiple times will work, but should not be
+  // necessary.
+  void TranfserChanges(ModelTypeStore* store,
+                       ModelTypeStore::WriteBatch* write_batch);
+};
+
+}  // namespace syncer_v2
+
+#endif  // SYNC_INTERNAL_API_PUBLIC_SIMPLE_METADATA_CHANGE_LIST_H_
diff --git a/sync/internal_api/public/specifics_only_data_batch.cc b/sync/internal_api/public/specifics_only_data_batch.cc
new file mode 100644
index 0000000..37896a7
--- /dev/null
+++ b/sync/internal_api/public/specifics_only_data_batch.cc
@@ -0,0 +1,15 @@
+// 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 "sync/internal_api/public/specifics_only_data_batch.h"
+
+namespace syncer_v2 {
+
+void SpecificsOnlyDataBatch::Put(
+    const std::string& client_key,
+    scoped_ptr<sync_pb::EntitySpecifics> specifics) {
+  // TODO(skym): Implementation.
+}
+
+}  // namespace syncer_v2
diff --git a/sync/internal_api/public/specifics_only_data_batch.h b/sync/internal_api/public/specifics_only_data_batch.h
new file mode 100644
index 0000000..bb3aa19
--- /dev/null
+++ b/sync/internal_api/public/specifics_only_data_batch.h
@@ -0,0 +1,29 @@
+// 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 SYNC_INTERNAL_API_PUBLIC_SPECIFICS_ONLY_DATA_BATCH_H_
+#define SYNC_INTERNAL_API_PUBLIC_SPECIFICS_ONLY_DATA_BATCH_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "sync/api/data_batch.h"
+#include "sync/protocol/sync.pb.h"
+
+namespace syncer_v2 {
+
+// An implementation of DataBatch that only takes the simplest data from the
+// service. The processor may need to help populate some fields.
+class SpecificsOnlyDataBatch : public DataBatch {
+ public:
+  // Takes ownership of the specifics tied to a given key used for storage. Put
+  // should be called at most once for any given client_key. Multiple uses of
+  // the same client_key is currently undefined.
+  void Put(const std::string& client_key,
+           scoped_ptr<sync_pb::EntitySpecifics> specifics);
+};
+
+}  // namespace syncer_v2
+
+#endif  // SYNC_INTERNAL_API_PUBLIC_SPECIFICS_ONLY_DATA_BATCH_H_
diff --git a/sync/internal_api/shared_model_type_processor.cc b/sync/internal_api/shared_model_type_processor.cc
index 97275a9..e653d62d 100644
--- a/sync/internal_api/shared_model_type_processor.cc
+++ b/sync/internal_api/shared_model_type_processor.cc
@@ -147,13 +147,12 @@
   FlushPendingCommitRequests();
 }
 
-void SharedModelTypeProcessor::Put(
-    const std::string& client_tag,
-    const std::string& non_unique_name,
-    const sync_pb::EntitySpecifics& specifics,
-    MetadataChanges* metadata_changes) {
+void SharedModelTypeProcessor::Put(const std::string& client_tag,
+                                   const std::string& non_unique_name,
+                                   const sync_pb::EntitySpecifics& specifics,
+                                   MetadataChangeList* metadata_change_list) {
   // TODO(skym): Update for new approach. Different objects, different caching,
-  // different loopups, metadat_changes, etc.
+  // different loopups, metadata_change_list, etc.
 
   DCHECK_EQ(type_, syncer::GetModelTypeFromSpecifics(specifics));
 
@@ -173,8 +172,9 @@
   FlushPendingCommitRequests();
 }
 
-void SharedModelTypeProcessor::Delete(const std::string& client_key,
-                                      MetadataChanges* metadata_changes) {
+void SharedModelTypeProcessor::Delete(
+    const std::string& client_key,
+    MetadataChangeList* metadata_change_list) {
   // TODO(skym): Update for new approach. Different caching, different lookup,
   // metadata changes.
 
diff --git a/sync/sync.gyp b/sync/sync.gyp
index bd41f74..45943fc 100644
--- a/sync/sync.gyp
+++ b/sync/sync.gyp
@@ -82,7 +82,7 @@
         'api/entity_data.cc',
         'api/entity_data.h',
         'api/metadata_batch.h',
-        'api/metadata_changes.h',
+        'api/metadata_change_list.h',
         'api/model_type_change_processor.cc',
         'api/model_type_change_processor.h',
         'api/model_type_service.cc',
@@ -288,6 +288,8 @@
         'internal_api/public/events/normal_get_updates_request_event.h',
         'internal_api/public/events/poll_get_updates_request_event.h',
         'internal_api/public/events/protocol_event.h',
+        'internal_api/public/fully_serialized_metadata_batch.h',
+        'internal_api/public/fully_serialized_metadata_batch.cc',
         'internal_api/public/http_bridge.h',
         'internal_api/public/http_bridge_network_resources.h',
         'internal_api/public/http_post_provider_factory.h',
@@ -317,6 +319,10 @@
         'internal_api/public/sessions/update_counters.h',
         'internal_api/public/shared_model_type_processor.h',
         'internal_api/public/shutdown_reason.h',
+        'internal_api/public/simple_metadata_change_list.cc',
+        'internal_api/public/simple_metadata_change_list.h',
+        'internal_api/public/specifics_only_data_batch.h',
+        'internal_api/public/specifics_only_data_batch.cc',
         'internal_api/public/sync_auth_provider.h',
         'internal_api/public/sync_context.h',
         'internal_api/public/sync_context_proxy.h',
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index a74b419..bd43079 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -5705,7 +5705,7 @@
       {
         "args": [
           "--site-per-process",
-          "--gtest_filter=-BrowserTest.InterstitialCancelsGuestViewDialogs:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:ErrorPageTest.*:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:IsolatedAppTest.*:MimeHandlerViewTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.ClientEmptyReferer:ReferrerPolicyTest.HttpsRedirect:SSLUITest.TestGoodFrameNavigation:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.AcceptTouchEvents:WebViewTest.IndexedDBIsolation:WebViewTest.ScreenCoordinates:WebViewTest.ContextMenusAPI_PreventDefault:WebViewTest.TestContextMenu:WebViewTest.NestedGuestContainerBounds:WebViewFocusTest.*:WebViewNewWindowTest.*:WebViewVisibilityTest.*:*.NavigateFromNTPToOptionsInSameTab:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs:SingleProcessTracingBrowserTest.TestMemoryInfra"
+          "--gtest_filter=-BrowserTest.InterstitialCancelsGuestViewDialogs:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:ErrorPageTest.*:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:IsolatedAppTest.*:MimeHandlerViewTest.*:*PDFExtensionTest.*:PhishingDOMFeatureExtractorTest.SubFrames:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.ClientEmptyReferer:ReferrerPolicyTest.HttpsRedirect:SSLUITest.TestGoodFrameNavigation:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.AcceptTouchEvents:WebViewTest.IndexedDBIsolation:WebViewTest.ScreenCoordinates:WebViewTest.ContextMenusAPI_PreventDefault:WebViewTest.TestContextMenu:WebViewTest.NestedGuestContainerBounds:WebViewFocusTest.*:WebViewNewWindowTest.*:WebViewVisibilityTest.*:*.NavigateFromNTPToOptionsInSameTab:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs:SingleProcessTracingBrowserTest.TestMemoryInfra"
         ],
         "test": "browser_tests"
       },
@@ -5736,7 +5736,7 @@
       {
         "args": [
           "--site-per-process",
-          "--gtest_filter=-BrowserTest.InterstitialCancelsGuestViewDialogs:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:ErrorPageTest.*:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:IsolatedAppTest.*:MimeHandlerViewTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.ClientEmptyReferer:ReferrerPolicyTest.HttpsRedirect:SSLUITest.TestGoodFrameNavigation:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.AcceptTouchEvents:WebViewTest.IndexedDBIsolation:WebViewTest.ScreenCoordinates:WebViewTest.ContextMenusAPI_PreventDefault:WebViewTest.TestContextMenu:WebViewTest.NestedGuestContainerBounds:WebViewFocusTest.*:WebViewNewWindowTest.*:WebViewVisibilityTest.*:*.NavigateFromNTPToOptionsInSameTab:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs:SingleProcessTracingBrowserTest.TestMemoryInfra"
+          "--gtest_filter=-BrowserTest.InterstitialCancelsGuestViewDialogs:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:ErrorPageTest.*:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:IsolatedAppTest.*:MimeHandlerViewTest.*:*PDFExtensionTest.*:PhishingDOMFeatureExtractorTest.SubFrames:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.ClientEmptyReferer:ReferrerPolicyTest.HttpsRedirect:SSLUITest.TestGoodFrameNavigation:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.AcceptTouchEvents:WebViewTest.IndexedDBIsolation:WebViewTest.ScreenCoordinates:WebViewTest.ContextMenusAPI_PreventDefault:WebViewTest.TestContextMenu:WebViewTest.NestedGuestContainerBounds:WebViewFocusTest.*:WebViewNewWindowTest.*:WebViewVisibilityTest.*:*.NavigateFromNTPToOptionsInSameTab:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs:SingleProcessTracingBrowserTest.TestMemoryInfra"
         ],
         "test": "browser_tests"
       },
diff --git a/testing/test.gni b/testing/test.gni
index a280a1b..a150c24 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -28,6 +28,7 @@
 
       # Don't use "*" to forward all variables since some (like output_name
       # and isolate_file) apply only to the APK below.
+      deps = []
       forward_variables_from(invoker,
                              [
                                "all_dependent_configs",
@@ -40,6 +41,7 @@
                                "data_deps",
                                "datadeps",
                                "defines",
+                               "deps",
                                "include_dirs",
                                "ldflags",
                                "lib_dirs",
@@ -53,36 +55,27 @@
                                "visibility",
                              ])
 
-      deps = []
       if (!defined(invoker.use_default_launcher) ||
           invoker.use_default_launcher) {
         deps += [ "//testing/android/native_test:native_test_native_code" ]
       }
-      if (defined(invoker.deps)) {
-        deps += invoker.deps
-      }
     }
 
     unittest_apk(apk_name) {
       forward_variables_from(invoker,
                              [
                                "android_manifest",
+                               "deps",
                                "use_default_launcher",
                                "write_asset_list",
                              ])
-
       unittests_dep = ":$library_name"
       apk_name = main_target_name
       if (defined(invoker.output_name)) {
         apk_name = invoker.output_name
         unittests_binary = "lib${apk_name}.so"
       }
-      deps = [
-        ":$library_name",
-      ]
-      if (defined(invoker.apk_deps)) {
-        deps += invoker.apk_deps
-      }
+      deps += [ ":$library_name" ]
       if (defined(invoker.apk_asset_location)) {
         asset_location = invoker.apk_asset_location
       }
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 66684ed8..d9a6e91 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1360,7 +1360,18 @@
 
 crbug.com/563694 [ Linux Mac Debug ] svg/hixie/perf/005.xml [ Failure ]
 
+crbug.com/564109 [ Win7 XP ]  http/tests/webfont/font-display.html [ Pass Timeout Failure ]
+
 crbug.com/558574 [ Win7 ] fast/forms/text/text-font-height-mismatch.html [ Failure ]
 crbug.com/558574 [ Win7 ] fast/text/emphasis.html [ Failure ]
 
 crbug.com/561595 [ XP ] plugins/webview-plugin-scroll.html [ Failure ]
+
+crbug.com/561519 [ Android ] css1/classification/list_style.html [ NeedsRebaseline ]
+crbug.com/561519 [ Android ] css1/classification/list_style_position.html [ NeedsRebaseline ]
+crbug.com/561519 [ Android ] css1/color_and_background/background_color.html [ NeedsRebaseline ]
+crbug.com/561519 [ Android ] css1/color_and_background/color.html [ NeedsRebaseline ]
+crbug.com/561519 [ Android ] css1/font_properties/font_style.html [ NeedsRebaseline ]
+crbug.com/561519 [ Android ] css1/font_properties/font_variant.html [ NeedsRebaseline ]
+crbug.com/561519 [ Android ] css1/formatting_model/canvas.html [ NeedsRebaseline ]
+crbug.com/561519 [ Android ] svg/canvas/canvas-pattern-svg.html [ NeedsRebaseline ]
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/percent-resolution-grid-item.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/percent-resolution-grid-item.html
index bff8f339..5fe0a42 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/percent-resolution-grid-item.html
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/percent-resolution-grid-item.html
@@ -5,8 +5,6 @@
 .grid {
     grid-template-columns: 100px 300px;
     grid-template-rows: 50px 150px;
-    height: 200px;
-    width: 400px;
 }
 
 .percentWidth {
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/quirks-mode-percent-resolution-grid-item-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/quirks-mode-percent-resolution-grid-item-expected.txt
new file mode 100644
index 0000000..014a42ab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/quirks-mode-percent-resolution-grid-item-expected.txt
@@ -0,0 +1,6 @@
+Test that resolving percent lengths on grid items works properly on a fixed grid with different writing modes in quirks mode.
+
+PASS
+PASS
+PASS
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/quirks-mode-percent-resolution-grid-item.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/quirks-mode-percent-resolution-grid-item.html
new file mode 100644
index 0000000..0581166
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/quirks-mode-percent-resolution-grid-item.html
@@ -0,0 +1,57 @@
+<html>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.grid {
+    grid-template-columns: 100px 300px;
+    grid-template-rows: 50px 150px;
+}
+
+.percentWidth {
+    width: 100%;
+    height: 15px;
+}
+
+.percentHeight {
+    width: 15px;
+    height: 100%;
+}
+
+.percentHeightAndWidth {
+    width: 100%;
+    height: 100%;
+}
+</style>
+<script src="../../resources/check-layout.js"></script>
+<body onload="checkLayout('.grid')">
+
+<p>Test that resolving percent lengths on grid items works properly on a fixed grid with different writing modes in quirks mode.</p>
+
+<div class="grid">
+    <div class="firstRowFirstColumn percentWidth" data-expected-width="100" data-expected-height="15"></div>
+    <div class="firstRowSecondColumn percentHeight" data-expected-width="15" data-expected-height="50"></div>
+    <div class="secondRowFirstColumn percentHeightAndWidth" data-expected-width="100" data-expected-height="150"></div>
+    <div class="secondRowSecondColumn percentHeightAndWidth" data-expected-width="300" data-expected-height="150"></div>
+</div>
+
+<div class="grid verticalRL">
+    <div class="firstRowFirstColumn percentWidth" data-expected-width="50" data-expected-height="15"></div>
+    <div class="firstRowSecondColumn percentHeight" data-expected-width="15" data-expected-height="300"></div>
+    <div class="secondRowFirstColumn percentHeightAndWidth" data-expected-width="150" data-expected-height="100"></div>
+    <div class="secondRowSecondColumn percentHeightAndWidth" data-expected-width="150" data-expected-height="300"></div>
+</div>
+
+<div class="grid">
+    <div class="firstRowFirstColumn percentWidth verticalRL" data-expected-width="100" data-expected-height="15"></div>
+    <div class="firstRowSecondColumn percentHeight verticalRL" data-expected-width="15" data-expected-height="50"></div>
+    <div class="secondRowFirstColumn percentHeightAndWidth verticalRL" data-expected-width="100" data-expected-height="150"></div>
+    <div class="secondRowSecondColumn percentHeightAndWidth verticalRL" data-expected-width="300" data-expected-height="150"></div>
+</div>
+
+<div class="grid">
+    <div class="firstRowFirstColumn percentWidth verticalRL" data-expected-width="100" data-expected-height="15"></div>
+    <div class="firstRowSecondColumn percentHeight" data-expected-width="15" data-expected-height="50"></div>
+    <div class="secondRowFirstColumn percentHeightAndWidth verticalRL" data-expected-width="100" data-expected-height="150"></div>
+    <div class="secondRowSecondColumn percentHeightAndWidth" data-expected-width="300" data-expected-height="150"></div>
+</div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/svg/css/anchor-change-href-expected.txt b/third_party/WebKit/LayoutTests/svg/css/anchor-change-href-expected.txt
new file mode 100644
index 0000000..17adcb20
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/css/anchor-change-href-expected.txt
@@ -0,0 +1,2 @@
+This text should be green
+PASS
diff --git a/third_party/WebKit/LayoutTests/svg/css/anchor-change-href.svg b/third_party/WebKit/LayoutTests/svg/css/anchor-change-href.svg
new file mode 100644
index 0000000..b460a4c8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/css/anchor-change-href.svg
@@ -0,0 +1,43 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <style>
+        :link { fill: red }
+        :visited { fill: green }
+    </style>
+    <a xlink:href="http://notvisited" name="x">
+        <text x="20" y="40">This text should be green</text>
+    </a>
+    <text x="20" y="60" id="result1">Not run (requires window.internals).</text>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        window.location.hash = "#x";
+
+        requestAnimationFrame(function(){
+
+            // Change href from non-visited to visited link.
+            getComputedStyle(document.documentElement);
+            document.querySelector("a").setAttribute("xlink:href", "#x");
+
+            if (window.internals) {
+                var resultText = document.getElementById("result1").firstChild;
+                var elementCount = internals.updateStyleAndReturnAffectedElementCount();
+
+                // The elementCount should have been 2, but visited links are
+                // not recognized in content_shell, thus the text color doesn't
+                // change and an inheritance propagation to text element is not
+                // necessary. Running this test in Chrome will cause a 2-element
+                // recalc and green text as expected.
+                if (elementCount == 1)
+                    resultText.data = "PASS";
+                else
+                    resultText.data = "FAIL: " + elementCount;
+            }
+
+            if (window.testRunner)
+                testRunner.notifyDone();
+        });
+    </script>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 36dedba4..25d05a08 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -403,6 +403,7 @@
     setter onerror
     setter onshow
 interface NotificationEvent : ExtendableEvent
+    getter action
     getter notification
     method constructor
 interface PermissionStatus : EventTarget
diff --git a/third_party/WebKit/LayoutTests/whitespace.txt b/third_party/WebKit/LayoutTests/whitespace.txt
new file mode 100644
index 0000000..cbf1507
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/whitespace.txt
@@ -0,0 +1,11 @@
+<blink>Hello world!</blink>
+
+She blinked slowly back at him.
+
+Then, backed away.
+
+"Speed, not haster.", he said.
+
+Her retort: "I implemented <blink> in Blink using Javscript!"
+
+"Amaze balls. You should visit a doctor.", said he.
diff --git a/third_party/WebKit/Source/core/css/CSSSelectorList.cpp b/third_party/WebKit/Source/core/css/CSSSelectorList.cpp
index ab68f70..e353f30 100644
--- a/third_party/WebKit/Source/core/css/CSSSelectorList.cpp
+++ b/third_party/WebKit/Source/core/css/CSSSelectorList.cpp
@@ -41,7 +41,7 @@
 CSSSelectorList::CSSSelectorList(const CSSSelectorList& other)
 {
     unsigned otherLength = other.length();
-    m_selectorArray = reinterpret_cast<CSSSelector*>(WTF::Partitions::fastMalloc(sizeof(CSSSelector) * otherLength));
+    m_selectorArray = reinterpret_cast<CSSSelector*>(WTF::Partitions::fastMalloc(sizeof(CSSSelector) * otherLength, WTF_HEAP_PROFILER_TYPE_NAME(CSSSelector)));
     for (unsigned i = 0; i < otherLength; ++i)
         new (&m_selectorArray[i]) CSSSelector(other.m_selectorArray[i]);
 }
@@ -62,7 +62,7 @@
             ++flattenedSize;
     }
     ASSERT(flattenedSize);
-    m_selectorArray = reinterpret_cast<CSSSelector*>(WTF::Partitions::fastMalloc(sizeof(CSSSelector) * flattenedSize));
+    m_selectorArray = reinterpret_cast<CSSSelector*>(WTF::Partitions::fastMalloc(sizeof(CSSSelector) * flattenedSize, WTF_HEAP_PROFILER_TYPE_NAME(CSSSelector)));
     size_t arrayIndex = 0;
     for (size_t i = 0; i < selectorVector.size(); ++i) {
         CSSParserSelector* current = selectorVector[i].get();
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.cpp b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
index 32ab3532..4cd11e1 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySet.cpp
+++ b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
@@ -52,7 +52,7 @@
 #if ENABLE(OILPAN)
     void* slot = Heap::allocate<StylePropertySet>(sizeForImmutableStylePropertySetWithPropertyCount(count));
 #else
-    void* slot = WTF::Partitions::fastMalloc(sizeForImmutableStylePropertySetWithPropertyCount(count));
+    void* slot = WTF::Partitions::fastMalloc(sizeForImmutableStylePropertySetWithPropertyCount(count), WTF_HEAP_PROFILER_TYPE_NAME(ImmutableStylePropertySet));
 #endif // ENABLE(OILPAN)
     return adoptRefWillBeNoop(new (slot) ImmutableStylePropertySet(properties, count, cssParserMode));
 }
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 822881a..51635775 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -5739,6 +5739,10 @@
 {
     if (frame())
         return frame()->frameScheduler()->loadingTaskRunner();
+    if (m_importsController)
+        return m_importsController->master()->loadingTaskRunner();
+    if (m_contextDocument)
+        return m_contextDocument->loadingTaskRunner();
     return Platform::current()->currentThread()->scheduler()->loadingTaskRunner();
 }
 
@@ -5746,6 +5750,10 @@
 {
     if (frame())
         return m_frame->frameScheduler()->timerTaskRunner();
+    if (m_importsController)
+        return m_importsController->master()->timerTaskRunner();
+    if (m_contextDocument)
+        return m_contextDocument->timerTaskRunner();
     return Platform::current()->currentThread()->scheduler()->timerTaskRunner();
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ElementData.cpp b/third_party/WebKit/Source/core/dom/ElementData.cpp
index 29dc6f3..0e40cb9 100644
--- a/third_party/WebKit/Source/core/dom/ElementData.cpp
+++ b/third_party/WebKit/Source/core/dom/ElementData.cpp
@@ -167,7 +167,7 @@
 #if ENABLE(OILPAN)
     void* slot = Heap::allocate<ElementData>(sizeForShareableElementDataWithAttributeCount(attributes.size()));
 #else
-    void* slot = WTF::Partitions::fastMalloc(sizeForShareableElementDataWithAttributeCount(attributes.size()));
+    void* slot = WTF::Partitions::fastMalloc(sizeForShareableElementDataWithAttributeCount(attributes.size()), WTF_HEAP_PROFILER_TYPE_NAME(ShareableElementData));
 #endif
     return adoptRefWillBeNoop(new (slot) ShareableElementData(attributes));
 }
@@ -207,7 +207,7 @@
 #if ENABLE(OILPAN)
     void* slot = Heap::allocate<ElementData>(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()));
 #else
-    void* slot = WTF::Partitions::fastMalloc(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()));
+    void* slot = WTF::Partitions::fastMalloc(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()), WTF_HEAP_PROFILER_TYPE_NAME(ShareableElementData));
 #endif
     return adoptRefWillBeNoop(new (slot) ShareableElementData(*this));
 }
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index adf0c2f..604bbf0 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -110,7 +110,7 @@
 void* Node::operator new(size_t size)
 {
     ASSERT(isMainThread());
-    return partitionAlloc(WTF::Partitions::nodePartition(), size);
+    return partitionAlloc(WTF::Partitions::nodePartition(), size, WTF_HEAP_PROFILER_TYPE_NAME(Node));
 }
 
 void Node::operator delete(void* ptr)
diff --git a/third_party/WebKit/Source/core/html/ImageData.cpp b/third_party/WebKit/Source/core/html/ImageData.cpp
index d44a311..27d788b1 100644
--- a/third_party/WebKit/Source/core/html/ImageData.cpp
+++ b/third_party/WebKit/Source/core/html/ImageData.cpp
@@ -179,6 +179,7 @@
     : m_size(size)
     , m_data(byteArray)
 {
+    ASSERT(size.width() >= 0 && size.height() >= 0);
     ASSERT_WITH_SECURITY_IMPLICATION(static_cast<unsigned>(size.width() * size.height() * 4) <= m_data->length());
 }
 
diff --git a/third_party/WebKit/Source/core/html/ImageData.idl b/third_party/WebKit/Source/core/html/ImageData.idl
index 77482a1..7df9d42 100644
--- a/third_party/WebKit/Source/core/html/ImageData.idl
+++ b/third_party/WebKit/Source/core/html/ImageData.idl
@@ -35,9 +35,8 @@
     RaisesException=Constructor,
     GarbageCollected,
 ] interface ImageData {
-    // TODO(philipj): width/height should be unsigned long.
-    readonly attribute long width;
-    readonly attribute long height;
+    readonly attribute unsigned long width;
+    readonly attribute unsigned long height;
     // TODO(philipj): Expose data.
     // readonly attribute Uint8ClampedArray data;
 };
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 4a4f729..e6f84ff 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -2508,7 +2508,7 @@
     }
 
     // For quirks mode, we skip most auto-height containing blocks when computing percentages.
-    return document().inQuirksMode() && !containingBlock->isTableCell() && !containingBlock->isOutOfFlowPositioned() && containingBlock->style()->logicalHeight().isAuto();
+    return document().inQuirksMode() && !containingBlock->isTableCell() && !containingBlock->isOutOfFlowPositioned() && !containingBlock->isLayoutGrid() && containingBlock->style()->logicalHeight().isAuto();
 }
 
 LayoutUnit LayoutBox::computePercentageLogicalHeight(const Length& height) const
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index d18a8bd..d7d0564 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -161,7 +161,7 @@
 void* LayoutObject::operator new(size_t sz)
 {
     ASSERT(isMainThread());
-    return partitionAlloc(WTF::Partitions::layoutPartition(), sz);
+    return partitionAlloc(WTF::Partitions::layoutPartition(), sz, WTF_HEAP_PROFILER_TYPE_NAME(LayoutObject));
 }
 
 void LayoutObject::operator delete(void* ptr)
diff --git a/third_party/WebKit/Source/core/layout/line/InlineBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineBox.cpp
index c9cd99a..30937274 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineBox.cpp
@@ -76,7 +76,7 @@
 
 void* InlineBox::operator new(size_t sz)
 {
-    return partitionAlloc(WTF::Partitions::layoutPartition(), sz);
+    return partitionAlloc(WTF::Partitions::layoutPartition(), sz, WTF_HEAP_PROFILER_TYPE_NAME(InlineBox));
 }
 
 void InlineBox::operator delete(void* ptr)
diff --git a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
index 6caebef2..5a4071e2 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
@@ -534,20 +534,23 @@
 
 void InlineTextBox::characterWidths(Vector<float>& widths) const
 {
+    if (!m_len)
+        return;
+
     FontCachePurgePreventer fontCachePurgePreventer;
+    ASSERT(lineLayoutItem().text());
 
     const ComputedStyle& styleToUse = lineLayoutItem().styleRef(isFirstLineStyle());
     const Font& font = styleToUse.font();
 
-    TextRun textRun = constructTextRun(styleToUse, font);
-
-    SimpleShaper shaper(&font, textRun);
     float lastWidth = 0;
     widths.resize(m_len);
     for (unsigned i = 0; i < m_len; i++) {
-        shaper.advance(i + 1);
-        widths[i] = shaper.runWidthSoFar() - lastWidth;
-        lastWidth = shaper.runWidthSoFar();
+        StringView substringView = lineLayoutItem().text().createView();
+        substringView.narrow(start(), 1 + i);
+        TextRun textRun = constructTextRun(styleToUse, font, substringView, m_len);
+        widths[i] = font.width(textRun, nullptr, nullptr) - lastWidth;
+        lastWidth = font.width(textRun, nullptr, nullptr);
     }
 }
 
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
index 5410c7e..346f2d9 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -1093,7 +1093,7 @@
 
 void* PaintLayer::operator new(size_t sz)
 {
-    return partitionAlloc(WTF::Partitions::layoutPartition(), sz);
+    return partitionAlloc(WTF::Partitions::layoutPartition(), sz, WTF_HEAP_PROFILER_TYPE_NAME(PaintLayer));
 }
 
 void PaintLayer::operator delete(void* ptr)
diff --git a/third_party/WebKit/Source/core/svg/SVGAElement.cpp b/third_party/WebKit/Source/core/svg/SVGAElement.cpp
index 78e42e7a..2251192 100644
--- a/third_party/WebKit/Source/core/svg/SVGAElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGAElement.cpp
@@ -91,9 +91,11 @@
         bool wasLink = isLink();
         setIsLink(!hrefString().isNull());
 
-        if (wasLink != isLink())
-            setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::LinkColorChange));
-
+        if (wasLink || isLink()) {
+            pseudoStateChanged(CSSSelector::PseudoLink);
+            pseudoStateChanged(CSSSelector::PseudoVisited);
+            pseudoStateChanged(CSSSelector::PseudoAnyLink);
+        }
         return;
     }
 
diff --git a/third_party/WebKit/Source/core/xml/XPathGrammar.y b/third_party/WebKit/Source/core/xml/XPathGrammar.y
index d74ac02..c69ea7832 100644
--- a/third_party/WebKit/Source/core/xml/XPathGrammar.y
+++ b/third_party/WebKit/Source/core/xml/XPathGrammar.y
@@ -38,7 +38,12 @@
 #include "core/xml/XPathVariableReference.h"
 #include "wtf/Partitions.h"
 
-#define YYMALLOC WTF::Partitions::fastMalloc
+void* yyFastMalloc(size_t size)
+{
+    return WTF::Partitions::fastMalloc(size, nullptr);
+}
+
+#define YYMALLOC yyFastMalloc
 #define YYFREE WTF::Partitions::fastFree
 
 #define YYENABLE_NLS 0
diff --git a/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp b/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp
index 4507fb1..5a167eb 100644
--- a/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp
+++ b/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp
@@ -192,7 +192,7 @@
 static char* allocateParameterArray(const char* data)
 {
     size_t length = strlen(data) + 1;
-    char* parameterArray = static_cast<char*>(WTF::Partitions::fastMalloc(length));
+    char* parameterArray = static_cast<char*>(WTF::Partitions::fastMalloc(length, WTF_HEAP_PROFILER_TYPE_NAME(XSLTProcessor)));
     memcpy(parameterArray, data, length);
     return parameterArray;
 }
@@ -202,7 +202,7 @@
     if (parameters.isEmpty())
         return nullptr;
 
-    const char** parameterArray = static_cast<const char**>(WTF::Partitions::fastMalloc(((parameters.size() * 2) + 1) * sizeof(char*)));
+    const char** parameterArray = static_cast<const char**>(WTF::Partitions::fastMalloc(((parameters.size() * 2) + 1) * sizeof(char*), WTF_HEAP_PROFILER_TYPE_NAME(XSLTProcessor)));
 
     unsigned index = 0;
     for (auto& parameter : parameters) {
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp
index f15fbabe..15675e0 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp
@@ -18,6 +18,9 @@
 
 DeviceOrientationAbsoluteController::~DeviceOrientationAbsoluteController()
 {
+#if !ENABLE(OILPAN)
+    stopUpdating();
+#endif
 }
 
 const char* DeviceOrientationAbsoluteController::supplementName()
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationEvent.idl b/third_party/WebKit/Source/modules/notifications/NotificationEvent.idl
index 762eec2d..2d4045d 100644
--- a/third_party/WebKit/Source/modules/notifications/NotificationEvent.idl
+++ b/third_party/WebKit/Source/modules/notifications/NotificationEvent.idl
@@ -10,5 +10,5 @@
     RuntimeEnabled=Notifications,
 ] interface NotificationEvent : ExtendableEvent {
     readonly attribute Notification notification;
-    [RuntimeEnabled=NotificationExperimental] readonly attribute DOMString action;
+    readonly attribute DOMString action;
 };
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationEventInit.idl b/third_party/WebKit/Source/modules/notifications/NotificationEventInit.idl
index 6409504..460ee7a6 100644
--- a/third_party/WebKit/Source/modules/notifications/NotificationEventInit.idl
+++ b/third_party/WebKit/Source/modules/notifications/NotificationEventInit.idl
@@ -6,5 +6,5 @@
 
 dictionary NotificationEventInit : ExtendableEventInit {
     Notification notification;
-    [RuntimeEnabled=NotificationExperimental] DOMString action = "";
+    DOMString action = "";
 };
diff --git a/third_party/WebKit/Source/modules/webmidi/MIDIOutput.cpp b/third_party/WebKit/Source/modules/webmidi/MIDIOutput.cpp
index 9ea9e0df..494578d 100644
--- a/third_party/WebKit/Source/modules/webmidi/MIDIOutput.cpp
+++ b/third_party/WebKit/Source/modules/webmidi/MIDIOutput.cpp
@@ -196,6 +196,8 @@
 
 void MIDIOutput::send(DOMUint8Array* array, double timestamp, ExceptionState& exceptionState)
 {
+    ASSERT(array);
+
     if (timestamp == 0.0)
         timestamp = now(executionContext());
 
@@ -203,9 +205,6 @@
     // This should be performed even if |array| is invalid.
     open();
 
-    if (!array)
-        return;
-
     if (MessageValidator::validate(array, exceptionState, midiAccess()->sysexEnabled()))
         midiAccess()->sendMIDIData(m_portIndex, array->data(), array->length(), timestamp);
 }
@@ -233,6 +232,7 @@
 
 void MIDIOutput::send(DOMUint8Array* data, ExceptionState& exceptionState)
 {
+    ASSERT(data);
     send(data, 0.0, exceptionState);
 }
 
diff --git a/third_party/WebKit/Source/modules/webmidi/MIDIOutput.idl b/third_party/WebKit/Source/modules/webmidi/MIDIOutput.idl
index e4fbf93..58a8635 100644
--- a/third_party/WebKit/Source/modules/webmidi/MIDIOutput.idl
+++ b/third_party/WebKit/Source/modules/webmidi/MIDIOutput.idl
@@ -35,6 +35,6 @@
     SetWrapperReferenceTo(MIDIAccess midiAccess),
 ] interface MIDIOutput : MIDIPort {
     // TODO(toyoshim): implement void clear()
-    [RaisesException, LegacyInterfaceTypeChecking] void send(Uint8Array data, optional double timestamp);
+    [RaisesException] void send(Uint8Array data, optional double timestamp);
     [RaisesException] void send(sequence<unsigned long> data, optional double timestamp);
 };
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 2bc8c089..c59f6534 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -363,7 +363,7 @@
     "//third_party/WebKit/Source/wtf:test_support",
   ]
   if (is_android) {
-    apk_deps = [
+    deps += [
       "//base:base_java",
       "//content/shell/android:content_shell_assets",
       "//net/android:net_java",
diff --git a/third_party/WebKit/Source/platform/PODArena.h b/third_party/WebKit/Source/platform/PODArena.h
index 3b74e9c4..e59e779be 100644
--- a/third_party/WebKit/Source/platform/PODArena.h
+++ b/third_party/WebKit/Source/platform/PODArena.h
@@ -64,7 +64,7 @@
             return adoptRef(new FastMallocAllocator);
         }
 
-        void* allocate(size_t size) override { return WTF::Partitions::fastMalloc(size); }
+        void* allocate(size_t size) override { return WTF::Partitions::fastMalloc(size, WTF_HEAP_PROFILER_TYPE_NAME(PODArena)); }
         void free(void* ptr) override { WTF::Partitions::fastFree(ptr); }
 
     protected:
diff --git a/third_party/WebKit/Source/platform/SharedBuffer.cpp b/third_party/WebKit/Source/platform/SharedBuffer.cpp
index 59eb223..c2a7a81 100644
--- a/third_party/WebKit/Source/platform/SharedBuffer.cpp
+++ b/third_party/WebKit/Source/platform/SharedBuffer.cpp
@@ -55,7 +55,7 @@
 
 static inline char* allocateSegment()
 {
-    return static_cast<char*>(WTF::Partitions::fastMalloc(SharedBuffer::kSegmentSize));
+    return static_cast<char*>(WTF::Partitions::fastMalloc(SharedBuffer::kSegmentSize, WTF_HEAP_PROFILER_TYPE_NAME(SharedBuffer)));
 }
 
 static inline void freeSegment(char* p)
diff --git a/third_party/WebKit/Source/platform/audio/AudioArray.h b/third_party/WebKit/Source/platform/audio/AudioArray.h
index d0c0ec6..ee875b0 100644
--- a/third_party/WebKit/Source/platform/audio/AudioArray.h
+++ b/third_party/WebKit/Source/platform/audio/AudioArray.h
@@ -78,7 +78,7 @@
             // Again, check for integer overflow.
             RELEASE_ASSERT(initialSize + extraAllocationBytes >= initialSize);
 
-            T* allocation = static_cast<T*>(WTF::Partitions::fastMalloc(initialSize + extraAllocationBytes));
+            T* allocation = static_cast<T*>(WTF::Partitions::fastMalloc(initialSize + extraAllocationBytes, WTF_HEAP_PROFILER_TYPE_NAME(AudioArray<T>)));
             RELEASE_ASSERT(allocation);
 
             T* alignedData = alignedAddress(allocation, alignment);
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescription.cpp b/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
index 5f51bbbc..f0ec8da 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
@@ -163,23 +163,20 @@
     return floorf(computedOrAdjustedSize * FontCacheKey::precisionMultiplier()) / FontCacheKey::precisionMultiplier();
 }
 
-FontCacheKey FontDescription::cacheKey(const FontFaceCreationParams& creationParams, FontTraits desiredTraits, bool loading, unsigned version) const
+FontCacheKey FontDescription::cacheKey(const FontFaceCreationParams& creationParams, FontTraits desiredTraits) const
 {
     FontTraits fontTraits = desiredTraits.bitfield() ? desiredTraits : traits();
 
     unsigned options =
-        version << 8 | // bit 9-15
-        static_cast<unsigned>(loading ? 1 : 0) << 7 | // bit 8
         static_cast<unsigned>(m_fields.m_syntheticItalic) << 6 | // bit 7
         static_cast<unsigned>(m_fields.m_syntheticBold) << 5 | // bit 6
         static_cast<unsigned>(m_fields.m_textRendering) << 3 | // bits 4-5
         static_cast<unsigned>(m_fields.m_orientation) << 1 | // bit 2-3
         static_cast<unsigned>(m_fields.m_subpixelTextPosition); // bit 1
 
-    return FontCacheKey(creationParams, effectiveFontSize(), options | fontTraits.bitfield() << 16);
+    return FontCacheKey(creationParams, effectiveFontSize(), options | fontTraits.bitfield() << 8);
 }
 
-
 void FontDescription::setDefaultTypesettingFeatures(TypesettingFeatures typesettingFeatures)
 {
     s_defaultTypesettingFeatures = typesettingFeatures;
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescription.h b/third_party/WebKit/Source/platform/fonts/FontDescription.h
index 5a90c97..55d7274 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescription.h
+++ b/third_party/WebKit/Source/platform/fonts/FontDescription.h
@@ -181,7 +181,7 @@
     FontFeatureSettings* featureSettings() const { return m_featureSettings.get(); }
 
     float effectiveFontSize() const; // Returns either the computedSize or the computedPixelSize
-    FontCacheKey cacheKey(const FontFaceCreationParams&, FontTraits desiredTraits = FontTraits(0), bool loading = false, unsigned version = 0) const;
+    FontCacheKey cacheKey(const FontFaceCreationParams&, FontTraits desiredTraits = FontTraits(0)) const;
 
     void setFamily(const FontFamily& family) { m_familyList = family; }
     void setComputedSize(float s) { m_computedSize = clampTo<float>(s); }
diff --git a/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp b/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
index 0ef4b73..184c6f2 100644
--- a/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
@@ -75,7 +75,7 @@
             FontCache::fontCache()->releaseFontData(toSimpleFontData(m_fontList[i]));
         }
     }
-    m_shapeCache.clear();
+    m_shapeCache.clear(); // Clear the weak pointer to the cache instance.
 }
 
 bool FontFallbackList::loadingCustomFonts() const
@@ -206,15 +206,8 @@
                 if (FontPlatformData* platformData = FontCache::fontCache()->getFontPlatformData(fontDescription, params))
                     result = FontCache::fontCache()->fontDataFromFontPlatformData(platformData);
             }
-
-            // Include loading state and version when constructing key, that way if called when a font is loading
-            // and then again once it has been loaded or updated different keys are produced.
-            if (result) {
-                FontCacheKey cacheKey = fontDescription.cacheKey(params, FontTraits(0),
-                    result->isLoading() || result->isLoadingFallback(),
-                    m_fontSelector ? m_fontSelector->version() : 0);
-                key.add(cacheKey);
-            }
+            if (result)
+                key.add(fontDescription.cacheKey(params));
         }
         currentFamily = currentFamily->next();
     }
diff --git a/third_party/WebKit/Source/platform/fonts/FontFallbackList.h b/third_party/WebKit/Source/platform/fonts/FontFallbackList.h
index a131fc6..ed072a98 100644
--- a/third_party/WebKit/Source/platform/fonts/FontFallbackList.h
+++ b/third_party/WebKit/Source/platform/fonts/FontFallbackList.h
@@ -84,6 +84,8 @@
             m_shapeCache = FontCache::fontCache()->getShapeCache(key)->weakPtr();
         }
         ASSERT(m_shapeCache);
+        if (fontSelector())
+            m_shapeCache->clearIfVersionChanged(fontSelector()->version());
         return m_shapeCache.get();
     }
 
diff --git a/third_party/WebKit/Source/platform/fonts/GlyphPage.h b/third_party/WebKit/Source/platform/fonts/GlyphPage.h
index d6314b663..643f6f6f 100644
--- a/third_party/WebKit/Source/platform/fonts/GlyphPage.h
+++ b/third_party/WebKit/Source/platform/fonts/GlyphPage.h
@@ -74,7 +74,7 @@
 public:
     static PassRefPtr<GlyphPage> createForMixedFontData(GlyphPageTreeNodeBase* owner)
     {
-        void* slot = WTF::Partitions::fastMalloc(sizeof(GlyphPage) + sizeof(SimpleFontData*) * GlyphPage::size);
+        void* slot = WTF::Partitions::fastMalloc(sizeof(GlyphPage) + sizeof(SimpleFontData*) * GlyphPage::size, WTF_HEAP_PROFILER_TYPE_NAME(GlyphPage));
         return adoptRef(new (slot) GlyphPage(owner));
     }
 
diff --git a/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp b/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
index 464dd1d..db4fb78 100644
--- a/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
+++ b/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
@@ -116,7 +116,7 @@
     {
         size_t vdmxSize = face->getTableSize(vdmxTag);
         if (vdmxSize && vdmxSize < maxVDMXTableSize) {
-            uint8_t* vdmxTable = (uint8_t*) WTF::Partitions::fastMalloc(vdmxSize);
+            uint8_t* vdmxTable = (uint8_t*)WTF::Partitions::fastMalloc(vdmxSize, WTF_HEAP_PROFILER_TYPE_NAME(SimpleFontData));
             if (vdmxTable
                 && face->getTableData(vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
                 && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.cpp b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.cpp
index 3f16310..49e575c5 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.cpp
@@ -316,7 +316,7 @@
         return nullptr;
     }
 
-    char* buffer = reinterpret_cast<char*>(WTF::Partitions::fastMalloc(tableSize));
+    char* buffer = reinterpret_cast<char*>(WTF::Partitions::fastMalloc(tableSize, WTF_HEAP_PROFILER_TYPE_NAME(HarfBuzzFontData)));
     if (!buffer)
         return nullptr;
     size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer);
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeCache.h b/third_party/WebKit/Source/platform/fonts/shaping/ShapeCache.h
index 8fb321d6..aab4748 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeCache.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeCache.h
@@ -128,7 +128,7 @@
     friend bool operator==(const SmallStringKey&, const SmallStringKey&);
 
 public:
-    ShapeCache(): m_weakFactory(this) { }
+    ShapeCache(): m_weakFactory(this), m_version(0) { }
 
     ShapeCacheEntry* add(const TextRun& run, ShapeCacheEntry entry)
     {
@@ -138,6 +138,14 @@
         return addSlowCase(run, entry);
     }
 
+    void clearIfVersionChanged(unsigned version)
+    {
+        if (version != m_version) {
+            clear();
+            m_version = version;
+        }
+    }
+
     void clear()
     {
         m_singleCharMap.clear();
@@ -209,6 +217,7 @@
     SingleCharMap m_singleCharMap;
     SmallStringMap m_shortStringMap;
     WeakPtrFactory<ShapeCache> m_weakFactory;
+    unsigned m_version;
 };
 
 inline bool operator==(const ShapeCache::SmallStringKey& a, const ShapeCache::SmallStringKey& b)
diff --git a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
index 4679a18..3f0096c 100644
--- a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
@@ -22,11 +22,11 @@
     WTF_MAKE_NONCOPYABLE(Buffer);
     USING_FAST_MALLOC(Buffer);
 public:
-    explicit Buffer(size_t bufferSize)
+    explicit Buffer(size_t bufferSize, const char* typeName)
     {
         m_capacity = WTF::Partitions::bufferActualSize(bufferSize);
         m_begin = m_end = static_cast<char*>(
-            WTF::Partitions::bufferMalloc(m_capacity));
+            WTF::Partitions::bufferMalloc(m_capacity, typeName));
         ANNOTATE_NEW_BUFFER(m_begin, m_capacity, 0);
     }
 
@@ -66,17 +66,17 @@
     size_t m_capacity;
 };
 
-ContiguousContainerBase::ContiguousContainerBase(size_t maxObjectSize)
+ContiguousContainerBase::ContiguousContainerBase(size_t maxObjectSize, const char* typeName)
     : m_endIndex(0)
     , m_maxObjectSize(maxObjectSize)
 {
 }
 
 ContiguousContainerBase::ContiguousContainerBase(
-    size_t maxObjectSize, size_t initialSizeBytes)
-    : ContiguousContainerBase(maxObjectSize)
+    size_t maxObjectSize, size_t initialSizeBytes, const char* typeName)
+    : ContiguousContainerBase(maxObjectSize, typeName)
 {
-    allocateNewBufferForNextAllocation(std::max(maxObjectSize, initialSizeBytes));
+    allocateNewBufferForNextAllocation(std::max(maxObjectSize, initialSizeBytes), typeName);
 }
 
 ContiguousContainerBase::~ContiguousContainerBase()
@@ -105,7 +105,7 @@
         + m_elements.capacity() * sizeof(m_elements[0]);
 }
 
-void* ContiguousContainerBase::allocate(size_t objectSize)
+void* ContiguousContainerBase::allocate(size_t objectSize, const char* typeName)
 {
     ASSERT(objectSize <= m_maxObjectSize);
 
@@ -122,7 +122,7 @@
         size_t newBufferSize = m_buffers.isEmpty()
             ? kDefaultInitialBufferSize * m_maxObjectSize
             : 2 * m_buffers.last()->capacity();
-        bufferForAlloc = allocateNewBufferForNextAllocation(newBufferSize);
+        bufferForAlloc = allocateNewBufferForNextAllocation(newBufferSize, typeName);
     }
 
     void* element = bufferForAlloc->allocate(objectSize);
@@ -162,10 +162,10 @@
 }
 
 ContiguousContainerBase::Buffer*
-ContiguousContainerBase::allocateNewBufferForNextAllocation(size_t bufferSize)
+ContiguousContainerBase::allocateNewBufferForNextAllocation(size_t bufferSize, const char* typeName)
 {
     ASSERT(m_buffers.isEmpty() || m_endIndex == m_buffers.size() - 1);
-    OwnPtr<Buffer> newBuffer = adoptPtr(new Buffer(bufferSize));
+    OwnPtr<Buffer> newBuffer = adoptPtr(new Buffer(bufferSize, typeName));
     Buffer* bufferToReturn = newBuffer.get();
     m_buffers.append(newBuffer.release());
     m_endIndex = m_buffers.size() - 1;
diff --git a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h
index dc6b5c04..53a968fc 100644
--- a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h
+++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h
@@ -39,8 +39,8 @@
 class PLATFORM_EXPORT ContiguousContainerBase {
     WTF_MAKE_NONCOPYABLE(ContiguousContainerBase);
 protected:
-    explicit ContiguousContainerBase(size_t maxObjectSize);
-    ContiguousContainerBase(size_t maxObjectSize, size_t initialSizeBytes);
+    explicit ContiguousContainerBase(size_t maxObjectSize, const char* typeName);
+    ContiguousContainerBase(size_t maxObjectSize, size_t initialSizeBytes, const char* typeName);
     ~ContiguousContainerBase();
 
     size_t size() const { return m_elements.size(); }
@@ -50,7 +50,7 @@
     size_t memoryUsageInBytes() const;
 
     // These do not invoke constructors or destructors.
-    void* allocate(size_t objectSize);
+    void* allocate(size_t objectSize, const char* typeName);
     void removeLast();
     void clear();
     void swap(ContiguousContainerBase&);
@@ -60,7 +60,7 @@
 private:
     class Buffer;
 
-    Buffer* allocateNewBufferForNextAllocation(size_t);
+    Buffer* allocateNewBufferForNextAllocation(size_t, const char* typeName);
 
     Vector<OwnPtr<Buffer>> m_buffers;
     unsigned m_endIndex;
@@ -106,9 +106,9 @@
     using const_reverse_iterator = IteratorWrapper<Vector<void*>::const_reverse_iterator, const BaseElementType>;
 
     explicit ContiguousContainer(size_t maxObjectSize)
-        : ContiguousContainerBase(align(maxObjectSize)) {}
+        : ContiguousContainerBase(align(maxObjectSize), WTF_HEAP_PROFILER_TYPE_NAME(BaseElementType)) {}
     ContiguousContainer(size_t maxObjectSize, size_t initialSizeBytes)
-        : ContiguousContainerBase(align(maxObjectSize), initialSizeBytes) {}
+        : ContiguousContainerBase(align(maxObjectSize), initialSizeBytes, WTF_HEAP_PROFILER_TYPE_NAME(BaseElementType)) {}
 
     ~ContiguousContainer()
     {
@@ -148,7 +148,7 @@
         static_assert(alignment % WTF_ALIGN_OF(DerivedElementType) == 0,
             "Derived type requires stronger alignment.");
         size_t allocSize = align(sizeof(DerivedElementType));
-        return *new (allocate(allocSize)) DerivedElementType(WTF::forward<Args>(args)...);
+        return *new (allocate(allocSize, WTF_HEAP_PROFILER_TYPE_NAME(DerivedElementType))) DerivedElementType(WTF::forward<Args>(args)...);
     }
 
     void removeLast()
@@ -174,7 +174,7 @@
     BaseElementType& appendByMoving(BaseElementType& item, size_t size)
     {
         ASSERT(size >= sizeof(BaseElementType));
-        void* newItem = allocate(size);
+        void* newItem = allocate(size, WTF_HEAP_PROFILER_TYPE_NAME(BaseElementType));
         memcpy(newItem, static_cast<void*>(&item), size);
         new (&item) BaseElementType;
         return *static_cast<BaseElementType*>(newItem);
diff --git a/third_party/WebKit/Source/platform/heap/HeapAllocator.h b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
index 4828ddb..259c46b 100644
--- a/third_party/WebKit/Source/platform/heap/HeapAllocator.h
+++ b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
@@ -82,7 +82,7 @@
     static bool expandHashTableBacking(void*, size_t);
 
     template <typename Return, typename Metadata>
-    static Return malloc(size_t size)
+    static Return malloc(size_t size, const char* typeName)
     {
         return reinterpret_cast<Return>(Heap::allocate<Metadata>(size, IsEagerlyFinalizedType<Metadata>::value));
     }
@@ -229,7 +229,7 @@
         // Consider using a LinkedHashSet instead if this compile-time assert fails:
         static_assert(!WTF::IsWeak<ValueArg>::value, "weak pointers in a ListHashSet will result in null entries in the set");
 
-        return malloc<void*, Node>(sizeof(Node));
+        return malloc<void*, Node>(sizeof(Node), nullptr /* Oilpan does not use the heap profiler at the moment. */);
     }
 
     template<typename VisitorDispatcher>
diff --git a/third_party/WebKit/Source/platform/text/BidiCharacterRun.cpp b/third_party/WebKit/Source/platform/text/BidiCharacterRun.cpp
index 72005043..569c68d0 100644
--- a/third_party/WebKit/Source/platform/text/BidiCharacterRun.cpp
+++ b/third_party/WebKit/Source/platform/text/BidiCharacterRun.cpp
@@ -45,7 +45,7 @@
 #ifndef NDEBUG
     bidiRunCounter().increment();
 #endif
-    return partitionAlloc(Partitions::layoutPartition(), sz);
+    return partitionAlloc(Partitions::layoutPartition(), sz, WTF_HEAP_PROFILER_TYPE_NAME(BidiCharacterRun));
 }
 
 void BidiCharacterRun::operator delete(void* ptr)
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index b32d00f..14d51c1 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -140,7 +140,7 @@
   }
 
   if (is_android) {
-    apk_deps = [
+    deps += [
       "//base:base_java",
       "//content/shell/android:content_shell_assets",
       "//net/android:net_java",
diff --git a/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp b/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp
index b7b59c40..1141c3a1 100644
--- a/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp
+++ b/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp
@@ -47,6 +47,7 @@
 #include "public/web/WebFrameClient.h"
 #include "public/web/WebKit.h"
 #include "public/web/WebSharedWorker.h"
+#include "public/web/WebSharedWorkerCreationErrors.h"
 #include "public/web/WebSharedWorkerRepositoryClient.h"
 #include "web/WebLocalFrameImpl.h"
 
@@ -128,8 +129,12 @@
         headerType = static_cast<WebContentSecurityPolicyType>((*headers)[0].second);
     }
 
-    OwnPtr<WebSharedWorkerConnector> webWorkerConnector = adoptPtr(m_client->createSharedWorkerConnector(url, name, getId(document), header, headerType));
+    WebWorkerCreationError creationError;
+    OwnPtr<WebSharedWorkerConnector> webWorkerConnector = adoptPtr(m_client->createSharedWorkerConnector(url, name, getId(document), header, headerType, &creationError));
     if (!webWorkerConnector) {
+        // TODO(estark): This assertion will shortly go away and each
+        // different error type will be handled. https://crbug.com/561216
+        ASSERT(creationError == WebWorkerCreationErrorURLMismatch);
         // Existing worker does not match this url, so return an error back to the caller.
         exceptionState.throwDOMException(URLMismatchError, "The location of the SharedWorker named '" + name + "' does not exactly match the provided URL ('" + url.elidedString() + "').");
         return;
diff --git a/third_party/WebKit/Source/wtf/Allocator.h b/third_party/WebKit/Source/wtf/Allocator.h
index a6ddd0b..5536245c 100644
--- a/third_party/WebKit/Source/wtf/Allocator.h
+++ b/third_party/WebKit/Source/wtf/Allocator.h
@@ -101,7 +101,7 @@
     \
     void* operator new(size_t size) \
     { \
-        return ::WTF::Partitions::fastMalloc(size);     \
+        return ::WTF::Partitions::fastMalloc(size, WTF_HEAP_PROFILER_TYPE_NAME(type)); \
     } \
     \
     void operator delete(void* p) \
@@ -111,7 +111,7 @@
     \
     void* operator new[](size_t size) \
     { \
-        return ::WTF::Partitions::fastMalloc(size);       \
+        return ::WTF::Partitions::fastMalloc(size, WTF_HEAP_PROFILER_TYPE_NAME(type)); \
     } \
     \
     void operator delete[](void* p) \
diff --git a/third_party/WebKit/Source/wtf/ArrayBufferContents.cpp b/third_party/WebKit/Source/wtf/ArrayBufferContents.cpp
index 6a75a528..b7461fdb 100644
--- a/third_party/WebKit/Source/wtf/ArrayBufferContents.cpp
+++ b/third_party/WebKit/Source/wtf/ArrayBufferContents.cpp
@@ -102,7 +102,7 @@
 {
     if (s_adjustAmountOfExternalAllocatedMemoryFunction)
         s_adjustAmountOfExternalAllocatedMemoryFunction(static_cast<int>(size));
-    data = partitionAllocGeneric(WTF::Partitions::bufferPartition(), size);
+    data = partitionAllocGeneric(WTF::Partitions::bufferPartition(), size, WTF_HEAP_PROFILER_TYPE_NAME(ArrayBufferContents));
     if (policy == ZeroInitialize && data)
         memset(data, '\0', size);
 }
diff --git a/third_party/WebKit/Source/wtf/BitVector.cpp b/third_party/WebKit/Source/wtf/BitVector.cpp
index 79a33228..0aaf1d4 100644
--- a/third_party/WebKit/Source/wtf/BitVector.cpp
+++ b/third_party/WebKit/Source/wtf/BitVector.cpp
@@ -80,7 +80,7 @@
     WTF_ANNOTATE_SCOPED_MEMORY_LEAK;
     numBits = (numBits + bitsInPointer() - 1) & ~(bitsInPointer() - 1);
     size_t size = sizeof(OutOfLineBits) + sizeof(uintptr_t) * (numBits / bitsInPointer());
-    void* allocation = Partitions::bufferMalloc(size);
+    void* allocation = Partitions::bufferMalloc(size, WTF_HEAP_PROFILER_TYPE_NAME(OutOfLineBits));
     OutOfLineBits* result = new (NotNull, allocation) OutOfLineBits(numBits);
     return result;
 }
diff --git a/third_party/WebKit/Source/wtf/Compiler.h b/third_party/WebKit/Source/wtf/Compiler.h
index b78b937..c2e509cf 100644
--- a/third_party/WebKit/Source/wtf/Compiler.h
+++ b/third_party/WebKit/Source/wtf/Compiler.h
@@ -150,7 +150,6 @@
 #define WTF_PRETTY_FUNCTION __FUNCTION__
 #endif
 
-
 /* NO_SANITIZE_UNRELATED_CAST - Disable runtime checks related to casts between
  * unrelated objects (-fsanitize=cfi-unrelated-cast or -fsanitize=vptr). */
 
diff --git a/third_party/WebKit/Source/wtf/InstanceCounter.cpp b/third_party/WebKit/Source/wtf/InstanceCounter.cpp
index a93a276..7431e09 100644
--- a/third_party/WebKit/Source/wtf/InstanceCounter.cpp
+++ b/third_party/WebKit/Source/wtf/InstanceCounter.cpp
@@ -38,28 +38,28 @@
 #if ENABLE(INSTANCE_COUNTER) || ENABLE(DETAILED_MEMORY_INFRA)
 
 #if COMPILER(CLANG)
-const size_t extractNameFunctionPrefixLength = sizeof("const char *WTF::extractNameFunction() [T = ") - 1;
-const size_t extractNameFunctionPostfixLength = sizeof("]") - 1;
+const size_t stringWithTypeNamePrefixLength = sizeof("const char *WTF::getStringWithTypeName() [T = ") - 1;
+const size_t stringWithTypeNamePostfixLength = sizeof("]") - 1;
 #elif COMPILER(GCC)
-const size_t extractNameFunctionPrefixLength = sizeof("const char* WTF::extractNameFunction() [with T = ") - 1;
-const size_t extractNameFunctionPostfixLength = sizeof("]") - 1;
+const size_t stringWithTypeNamePrefixLength = sizeof("const char* WTF::getStringWithTypeName() [with T = ") - 1;
+const size_t stringWithTypeNamePostfixLength = sizeof("]") - 1;
 #elif COMPILER(MSVC)
-const size_t extractNameFunctionPrefixLength = sizeof("const char *__cdecl WTF::extractNameFunction<class ") - 1;
-const size_t extractNameFunctionPostfixLength = sizeof(">(void)") - 1;
+const size_t stringWithTypeNamePrefixLength = sizeof("const char *__cdecl WTF::getStringWithTypeName<class ") - 1;
+const size_t stringWithTypeNamePostfixLength = sizeof(">(void)") - 1;
 #else
 #warning "Extracting typename is supported only in compiler GCC, CLANG and MSVC at this moment"
 #endif
 
 // This function is used to stringify a typename T without using RTTI.
-// The result of extractNameFunction<T>() is given as |funcName|. |extractTypeNameFromFunctionName| then extracts a typename string from |funcName|.
+// The result of stringWithTypeName<T>() is given as |funcName|. |extractTypeNameFromFunctionName| then extracts a typename string from |funcName|.
 String extractTypeNameFromFunctionName(const char* funcName)
 {
 #if COMPILER(CLANG) || COMPILER(GCC) || COMPILER(MSVC)
     size_t funcNameLength = strlen(funcName);
-    ASSERT(funcNameLength > extractNameFunctionPrefixLength + extractNameFunctionPostfixLength);
+    ASSERT(funcNameLength > stringWithTypeNamePrefixLength + stringWithTypeNamePostfixLength);
 
-    const char* funcNameWithoutPrefix = funcName + extractNameFunctionPrefixLength;
-    return String(funcNameWithoutPrefix, funcNameLength - extractNameFunctionPrefixLength - extractNameFunctionPostfixLength);
+    const char* funcNameWithoutPrefix = funcName + stringWithTypeNamePrefixLength;
+    return String(funcNameWithoutPrefix, funcNameLength - stringWithTypeNamePrefixLength - stringWithTypeNamePostfixLength);
 #else
     return String("unknown");
 #endif
@@ -84,15 +84,15 @@
     HashMap<String, int> m_counterMap;
 };
 
-void incrementInstanceCount(const char* extractNameFunctionName, void* ptr)
+void incrementInstanceCount(const char* stringWithTypeNameName, void* ptr)
 {
-    String instanceName = extractTypeNameFromFunctionName(extractNameFunctionName);
+    String instanceName = extractTypeNameFromFunctionName(stringWithTypeNameName);
     InstanceCounter::instance()->incrementInstanceCount(instanceName, ptr);
 }
 
-void decrementInstanceCount(const char* extractNameFunctionName, void* ptr)
+void decrementInstanceCount(const char* stringWithTypeNameName, void* ptr)
 {
-    String instanceName = extractTypeNameFromFunctionName(extractNameFunctionName);
+    String instanceName = extractTypeNameFromFunctionName(stringWithTypeNameName);
     InstanceCounter::instance()->decrementInstanceCount(instanceName, ptr);
 }
 
diff --git a/third_party/WebKit/Source/wtf/InstanceCounter.h b/third_party/WebKit/Source/wtf/InstanceCounter.h
index 37f13fa..db4a92e 100644
--- a/third_party/WebKit/Source/wtf/InstanceCounter.h
+++ b/third_party/WebKit/Source/wtf/InstanceCounter.h
@@ -26,7 +26,7 @@
 #ifndef InstanceCounter_h
 #define InstanceCounter_h
 
-#include "wtf/Compiler.h"
+#include "wtf/TypeTraits.h"
 #include "wtf/WTFExport.h"
 
 namespace WTF {
@@ -35,28 +35,21 @@
 WTF_EXPORT String dumpRefCountedInstanceCounts();
 
 #if ENABLE(INSTANCE_COUNTER) || ENABLE(DETAILED_MEMORY_INFRA)
-WTF_EXPORT void incrementInstanceCount(const char* extractNameFunctionName, void* ptr);
-WTF_EXPORT void decrementInstanceCount(const char* extractNameFunctionName, void* ptr);
+WTF_EXPORT void incrementInstanceCount(const char* stringWithTypeName, void* ptr);
+WTF_EXPORT void decrementInstanceCount(const char* stringWithTypeName, void* ptr);
 
 WTF_EXPORT String extractTypeNameFromFunctionName(const char* funcName);
 
 template<typename T>
-inline const char* extractNameFunction()
-{
-    return WTF_PRETTY_FUNCTION;
-}
-
-
-template<typename T>
 inline void incrementInstanceCount(T* p)
 {
-    incrementInstanceCount(extractNameFunction<T>(), p);
+    incrementInstanceCount(getStringWithTypeName<T>(), p);
 }
 
 template<typename T>
 inline void decrementInstanceCount(T* p)
 {
-    decrementInstanceCount(extractNameFunction<T>(), p);
+    decrementInstanceCount(getStringWithTypeName<T>(), p);
 }
 
 #endif // ENABLE(INSTANCE_COUNTER) || ENABLE(DETAILED_MEMORY_INFRA)
diff --git a/third_party/WebKit/Source/wtf/ListHashSet.h b/third_party/WebKit/Source/wtf/ListHashSet.h
index a2128b6..0c0f26ef 100644
--- a/third_party/WebKit/Source/wtf/ListHashSet.h
+++ b/third_party/WebKit/Source/wtf/ListHashSet.h
@@ -281,7 +281,7 @@
         Node* result = m_freeList;
 
         if (!result)
-            return static_cast<Node*>(WTF::Partitions::fastMalloc(sizeof(NodeBase)));
+            return static_cast<Node*>(WTF::Partitions::fastMalloc(sizeof(NodeBase), WTF_HEAP_PROFILER_TYPE_NAME(Node)));
 
         ASSERT(!result->m_isAllocated);
 
diff --git a/third_party/WebKit/Source/wtf/PartitionAlloc.cpp b/third_party/WebKit/Source/wtf/PartitionAlloc.cpp
index 73b55eb..8e6cdd9 100644
--- a/third_party/WebKit/Source/wtf/PartitionAlloc.cpp
+++ b/third_party/WebKit/Source/wtf/PartitionAlloc.cpp
@@ -1043,13 +1043,13 @@
     return true;
 }
 
-void* partitionReallocGeneric(PartitionRootGeneric* root, void* ptr, size_t newSize)
+void* partitionReallocGeneric(PartitionRootGeneric* root, void* ptr, size_t newSize, const char* typeName)
 {
 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
     return realloc(ptr, newSize);
 #else
     if (UNLIKELY(!ptr))
-        return partitionAllocGeneric(root, newSize);
+        return partitionAllocGeneric(root, newSize, typeName);
     if (UNLIKELY(!newSize)) {
         partitionFreeGeneric(root, ptr);
         return 0;
@@ -1067,7 +1067,7 @@
         // accessibility of memory pages and, if reducing the size, decommitting
         // them.
         if (partitionReallocDirectMappedInPlace(root, page, newSize)) {
-            PartitionAllocHooks::reallocHookIfEnabled(ptr, ptr, newSize);
+            PartitionAllocHooks::reallocHookIfEnabled(ptr, ptr, newSize, typeName);
             return ptr;
         }
     }
@@ -1086,7 +1086,7 @@
     }
 
     // This realloc cannot be resized in-place. Sadness.
-    void* ret = partitionAllocGeneric(root, newSize);
+    void* ret = partitionAllocGeneric(root, newSize, typeName);
     size_t copySize = actualOldSize;
     if (newSize < copySize)
         copySize = newSize;
diff --git a/third_party/WebKit/Source/wtf/PartitionAlloc.h b/third_party/WebKit/Source/wtf/PartitionAlloc.h
index 5fc1c32..1dba60909 100644
--- a/third_party/WebKit/Source/wtf/PartitionAlloc.h
+++ b/third_party/WebKit/Source/wtf/PartitionAlloc.h
@@ -102,6 +102,7 @@
 #include "wtf/CPU.h"
 #include "wtf/PageAllocator.h"
 #include "wtf/SpinLock.h"
+#include "wtf/TypeTraits.h"
 
 #include <limits.h>
 
@@ -406,24 +407,24 @@
 
 WTF_EXPORT NEVER_INLINE void* partitionAllocSlowPath(PartitionRootBase*, int, size_t, PartitionBucket*);
 WTF_EXPORT NEVER_INLINE void partitionFreeSlowPath(PartitionPage*);
-WTF_EXPORT NEVER_INLINE void* partitionReallocGeneric(PartitionRootGeneric*, void*, size_t);
+WTF_EXPORT NEVER_INLINE void* partitionReallocGeneric(PartitionRootGeneric*, void*, size_t, const char* typeName);
 
 WTF_EXPORT void partitionDumpStats(PartitionRoot*, const char* partitionName, bool isLightDump, PartitionStatsDumper*);
 WTF_EXPORT void partitionDumpStatsGeneric(PartitionRootGeneric*, const char* partitionName, bool isLightDump, PartitionStatsDumper*);
 
 class WTF_EXPORT PartitionAllocHooks {
 public:
-    typedef void AllocationHook(void* address, size_t);
+    typedef void AllocationHook(void* address, size_t, const char* typeName);
     typedef void FreeHook(void* address);
 
     static void setAllocationHook(AllocationHook* hook) { m_allocationHook = hook; }
     static void setFreeHook(FreeHook* hook) { m_freeHook = hook; }
 
-    static void allocationHookIfEnabled(void* address, size_t size)
+    static void allocationHookIfEnabled(void* address, size_t size, const char* typeName)
     {
         AllocationHook* allocationHook = m_allocationHook;
         if (UNLIKELY(allocationHook != nullptr))
-            allocationHook(address, size);
+            allocationHook(address, size, typeName);
     }
 
     static void freeHookIfEnabled(void* address)
@@ -433,14 +434,14 @@
             freeHook(address);
     }
 
-    static void reallocHookIfEnabled(void* oldAddress, void* newAddress, size_t size)
+    static void reallocHookIfEnabled(void* oldAddress, void* newAddress, size_t size, const char* typeName)
     {
         // Report a reallocation as a free followed by an allocation.
         AllocationHook* allocationHook = m_allocationHook;
         FreeHook* freeHook = m_freeHook;
         if (UNLIKELY(allocationHook && freeHook)) {
             freeHook(oldAddress);
-            allocationHook(newAddress, size);
+            allocationHook(newAddress, size, typeName);
         }
     }
 
@@ -451,6 +452,14 @@
     static FreeHook* m_freeHook;
 };
 
+// In official builds, do not include type info string literals to avoid
+// bloating the binary.
+#if defined(OFFICIAL_BUILD)
+#define WTF_HEAP_PROFILER_TYPE_NAME(T) nullptr
+#else
+#define WTF_HEAP_PROFILER_TYPE_NAME(T) ::WTF::getStringWithTypeName<T>()
+#endif
+
 ALWAYS_INLINE PartitionFreelistEntry* partitionFreelistMask(PartitionFreelistEntry* ptr)
 {
     // We use bswap on little endian as a fast mask for two reasons:
@@ -656,7 +665,7 @@
     return ret;
 }
 
-ALWAYS_INLINE void* partitionAlloc(PartitionRoot* root, size_t size)
+ALWAYS_INLINE void* partitionAlloc(PartitionRoot* root, size_t size, const char* typeName)
 {
 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
     void* result = malloc(size);
@@ -671,7 +680,7 @@
     ASSERT(size == index << kBucketShift);
     PartitionBucket* bucket = &root->buckets()[index];
     void* result = partitionBucketAlloc(root, 0, size, bucket);
-    PartitionAllocHooks::allocationHookIfEnabled(result, requestedSize);
+    PartitionAllocHooks::allocationHookIfEnabled(result, requestedSize, typeName);
     return result;
 #endif // defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
 }
@@ -732,7 +741,7 @@
     return bucket;
 }
 
-ALWAYS_INLINE void* partitionAllocGenericFlags(PartitionRootGeneric* root, int flags, size_t size)
+ALWAYS_INLINE void* partitionAllocGenericFlags(PartitionRootGeneric* root, int flags, size_t size, const char* typeName)
 {
 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
     void* result = malloc(size);
@@ -753,14 +762,14 @@
 #endif
     void* ret = partitionBucketAlloc(root, flags, size, bucket);
     spinLockUnlock(&root->lock);
-    PartitionAllocHooks::allocationHookIfEnabled(ret, requestedSize);
+    PartitionAllocHooks::allocationHookIfEnabled(ret, requestedSize, typeName);
     return ret;
 #endif
 }
 
-ALWAYS_INLINE void* partitionAllocGeneric(PartitionRootGeneric* root, size_t size)
+ALWAYS_INLINE void* partitionAllocGeneric(PartitionRootGeneric* root, size_t size, const char* typeName)
 {
-    return partitionAllocGenericFlags(root, 0, size);
+    return partitionAllocGenericFlags(root, 0, size, typeName);
 }
 
 ALWAYS_INLINE void partitionFreeGeneric(PartitionRootGeneric* root, void* ptr)
diff --git a/third_party/WebKit/Source/wtf/PartitionAllocTest.cpp b/third_party/WebKit/Source/wtf/PartitionAllocTest.cpp
index 77b1bf1..5c1142a 100644
--- a/third_party/WebKit/Source/wtf/PartitionAllocTest.cpp
+++ b/third_party/WebKit/Source/wtf/PartitionAllocTest.cpp
@@ -71,6 +71,8 @@
 const size_t kRealAllocSize = kTestAllocSize + kExtraAllocSize;
 const size_t kTestBucketIndex = kRealAllocSize >> WTF::kBucketShift;
 
+const char* kTypeName = nullptr;
+
 void TestSetup()
 {
     allocator.init();
@@ -137,7 +139,7 @@
     void* last = 0;
     size_t i;
     for (i = 0; i < numSlots; ++i) {
-        void* ptr = partitionAlloc(allocator.root(), size);
+        void* ptr = partitionAlloc(allocator.root(), size, kTypeName);
         EXPECT_TRUE(ptr);
         if (!i)
             first = partitionCookieFreePointerAdjust(ptr);
@@ -175,7 +177,7 @@
     ASSERT(!bucket->activePagesHead->numAllocatedSlots);
 
     for (size_t i = 0; i < kMaxFreeableSpans; ++i) {
-        void* ptr = partitionAlloc(allocator.root(), size);
+        void* ptr = partitionAlloc(allocator.root(), size, kTypeName);
         EXPECT_EQ(1, bucket->activePagesHead->numAllocatedSlots);
         partitionFree(ptr);
         EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots);
@@ -186,7 +188,7 @@
 void CycleGenericFreeCache(size_t size)
 {
     for (size_t i = 0; i < kMaxFreeableSpans; ++i) {
-        void* ptr = partitionAllocGeneric(genericAllocator.root(), size);
+        void* ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
         PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
         PartitionBucket* bucket = page->bucket;
         EXPECT_EQ(1, bucket->activePagesHead->numAllocatedSlots);
@@ -271,7 +273,7 @@
     EXPECT_EQ(seedPage, bucket->activePagesHead);
     EXPECT_EQ(0, bucket->activePagesHead->nextPage);
 
-    void* ptr = partitionAlloc(allocator.root(), kTestAllocSize);
+    void* ptr = partitionAlloc(allocator.root(), kTestAllocSize, kTypeName);
     EXPECT_TRUE(ptr);
     EXPECT_EQ(kPointerOffset, reinterpret_cast<size_t>(ptr) & kPartitionPageOffsetMask);
     // Check that the offset appears to include a guard page.
@@ -290,9 +292,9 @@
 TEST(PartitionAllocTest, SimpleLeak)
 {
     TestSetup();
-    void* leakedPtr = partitionAlloc(allocator.root(), kTestAllocSize);
+    void* leakedPtr = partitionAlloc(allocator.root(), kTestAllocSize, kTypeName);
     (void)leakedPtr;
-    void* leakedPtr2 = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize);
+    void* leakedPtr2 = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize, kTypeName);
     (void)leakedPtr2;
     EXPECT_FALSE(allocator.shutdown());
     EXPECT_FALSE(genericAllocator.shutdown());
@@ -303,8 +305,8 @@
 {
     TestSetup();
 
-    char* ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize));
-    char* ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize));
+    char* ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize, kTypeName));
+    char* ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize, kTypeName));
     EXPECT_TRUE(ptr1);
     EXPECT_TRUE(ptr2);
     ptrdiff_t diff = ptr2 - ptr1;
@@ -312,17 +314,17 @@
 
     // Check that we re-use the just-freed slot.
     partitionFree(ptr2);
-    ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize));
+    ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize, kTypeName));
     EXPECT_TRUE(ptr2);
     diff = ptr2 - ptr1;
     EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff);
     partitionFree(ptr1);
-    ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize));
+    ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize, kTypeName));
     EXPECT_TRUE(ptr1);
     diff = ptr2 - ptr1;
     EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff);
 
-    char* ptr3 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize));
+    char* ptr3 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize, kTypeName));
     EXPECT_TRUE(ptr3);
     diff = ptr3 - ptr1;
     EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize * 2), diff);
@@ -393,7 +395,7 @@
     char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointerOffset;
     partitionFree(ptr);
     EXPECT_EQ(page1, bucket->activePagesHead);
-    (void) partitionAlloc(allocator.root(), kTestAllocSize);
+    (void)partitionAlloc(allocator.root(), kTestAllocSize, kTypeName);
     EXPECT_EQ(page1, bucket->activePagesHead);
     EXPECT_EQ(page2, bucket->activePagesHead->nextPage);
 
@@ -409,7 +411,7 @@
     partitionFree(ptr);
     // Trying to allocate at this time should cause us to cycle around to page2
     // and find the recently freed slot.
-    char* newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize));
+    char* newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize, kTypeName));
     EXPECT_EQ(ptr, newPtr);
     EXPECT_EQ(page2, bucket->activePagesHead);
     EXPECT_EQ(page3, page2->nextPage);
@@ -419,7 +421,7 @@
     ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointerOffset;
     partitionFree(ptr);
     // This allocation should be satisfied by page1.
-    newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize));
+    newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize, kTypeName));
     EXPECT_EQ(ptr, newPtr);
     EXPECT_EQ(page1, bucket->activePagesHead);
     EXPECT_EQ(page2, page1->nextPage);
@@ -429,7 +431,7 @@
     FreeFullPage(page1);
 
     // Allocating whilst in this state exposed a bug, so keep the test.
-    ptr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize));
+    ptr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize, kTypeName));
     partitionFree(ptr);
 
     TestShutdown();
@@ -521,29 +523,29 @@
 {
     TestSetup();
 
-    void* ptr = partitionAllocGeneric(genericAllocator.root(), 1);
+    void* ptr = partitionAllocGeneric(genericAllocator.root(), 1, kTypeName);
     EXPECT_TRUE(ptr);
     partitionFreeGeneric(genericAllocator.root(), ptr);
-    ptr = partitionAllocGeneric(genericAllocator.root(), kGenericMaxBucketed + 1);
+    ptr = partitionAllocGeneric(genericAllocator.root(), kGenericMaxBucketed + 1, kTypeName);
     EXPECT_TRUE(ptr);
     partitionFreeGeneric(genericAllocator.root(), ptr);
 
-    ptr = partitionAllocGeneric(genericAllocator.root(), 1);
+    ptr = partitionAllocGeneric(genericAllocator.root(), 1, kTypeName);
     EXPECT_TRUE(ptr);
     void* origPtr = ptr;
     char* charPtr = static_cast<char*>(ptr);
     *charPtr = 'A';
 
     // Change the size of the realloc, remaining inside the same bucket.
-    void* newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 2);
+    void* newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 2, kTypeName);
     EXPECT_EQ(ptr, newPtr);
-    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1);
+    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1, kTypeName);
     EXPECT_EQ(ptr, newPtr);
-    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericSmallestBucket);
+    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericSmallestBucket, kTypeName);
     EXPECT_EQ(ptr, newPtr);
 
     // Change the size of the realloc, switching buckets.
-    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericSmallestBucket + 1);
+    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericSmallestBucket + 1, kTypeName);
     EXPECT_NE(newPtr, ptr);
     // Check that the realloc copied correctly.
     char* newCharPtr = static_cast<char*>(newPtr);
@@ -558,13 +560,13 @@
     // The realloc moved. To check that the old allocation was freed, we can
     // do an alloc of the old allocation size and check that the old allocation
     // address is at the head of the freelist and reused.
-    void* reusedPtr = partitionAllocGeneric(genericAllocator.root(), 1);
+    void* reusedPtr = partitionAllocGeneric(genericAllocator.root(), 1, kTypeName);
     EXPECT_EQ(reusedPtr, origPtr);
     partitionFreeGeneric(genericAllocator.root(), reusedPtr);
 
     // Downsize the realloc.
     ptr = newPtr;
-    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1);
+    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1, kTypeName);
     EXPECT_EQ(newPtr, origPtr);
     newCharPtr = static_cast<char*>(newPtr);
     EXPECT_EQ(*newCharPtr, 'B');
@@ -572,7 +574,7 @@
 
     // Upsize the realloc to outside the partition.
     ptr = newPtr;
-    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBucketed + 1);
+    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBucketed + 1, kTypeName);
     EXPECT_NE(newPtr, ptr);
     newCharPtr = static_cast<char*>(newPtr);
     EXPECT_EQ(*newCharPtr, 'C');
@@ -580,19 +582,19 @@
 
     // Upsize and downsize the realloc, remaining outside the partition.
     ptr = newPtr;
-    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBucketed * 10);
+    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBucketed * 10, kTypeName);
     newCharPtr = static_cast<char*>(newPtr);
     EXPECT_EQ(*newCharPtr, 'D');
     *newCharPtr = 'E';
     ptr = newPtr;
-    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBucketed * 2);
+    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBucketed * 2, kTypeName);
     newCharPtr = static_cast<char*>(newPtr);
     EXPECT_EQ(*newCharPtr, 'E');
     *newCharPtr = 'F';
 
     // Downsize the realloc to inside the partition.
     ptr = newPtr;
-    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1);
+    newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1, kTypeName);
     EXPECT_NE(newPtr, ptr);
     EXPECT_EQ(newPtr, origPtr);
     newCharPtr = static_cast<char*>(newPtr);
@@ -608,16 +610,16 @@
 {
     TestSetup();
 
-    void* ptr = partitionAllocGeneric(genericAllocator.root(), 0);
+    void* ptr = partitionAllocGeneric(genericAllocator.root(), 0, kTypeName);
     EXPECT_TRUE(ptr);
     partitionFreeGeneric(genericAllocator.root(), ptr);
 
     // kPartitionPageSize is interesting because it results in just one
     // allocation per page, which tripped up some corner cases.
     size_t size = kPartitionPageSize - kExtraAllocSize;
-    ptr = partitionAllocGeneric(genericAllocator.root(), size);
+    ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr);
-    void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size);
+    void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr2);
     partitionFreeGeneric(genericAllocator.root(), ptr);
     // Should be freeable at this point.
@@ -626,14 +628,14 @@
     partitionFreeGeneric(genericAllocator.root(), ptr2);
 
     size = (((kPartitionPageSize * kMaxPartitionPagesPerSlotSpan) - kSystemPageSize) / 2) - kExtraAllocSize;
-    ptr = partitionAllocGeneric(genericAllocator.root(), size);
+    ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr);
     memset(ptr, 'A', size);
-    ptr2 = partitionAllocGeneric(genericAllocator.root(), size);
+    ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr2);
-    void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size);
+    void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr3);
-    void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size);
+    void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr4);
 
     page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
@@ -647,9 +649,9 @@
     EXPECT_NE(-1, page->emptyCacheIndex);
     EXPECT_EQ(0, page->numAllocatedSlots);
     EXPECT_EQ(0, page->numUnprovisionedSlots);
-    void* newPtr = partitionAllocGeneric(genericAllocator.root(), size);
+    void* newPtr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_EQ(ptr3, newPtr);
-    newPtr = partitionAllocGeneric(genericAllocator.root(), size);
+    newPtr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_EQ(ptr2, newPtr);
 #if OS(LINUX) && !ENABLE(ASSERT)
     // On Linux, we have a guarantee that freelisting a page should cause its
@@ -667,7 +669,7 @@
 
     // Can we allocate a massive (512MB) size?
     // Allocate 512MB, but +1, to test for cookie writing alignment issues.
-    ptr = partitionAllocGeneric(genericAllocator.root(), 512 * 1024 * 1024 + 1);
+    ptr = partitionAllocGeneric(genericAllocator.root(), 512 * 1024 * 1024 + 1, kTypeName);
     partitionFreeGeneric(genericAllocator.root(), ptr);
 
     // Check a more reasonable, but still direct mapped, size.
@@ -675,7 +677,7 @@
     size = 20 * 1024 * 1024;
     size -= kSystemPageSize;
     size -= 1;
-    ptr = partitionAllocGeneric(genericAllocator.root(), size);
+    ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     char* charPtr = reinterpret_cast<char*>(ptr);
     *(charPtr + (size - 1)) = 'A';
     partitionFreeGeneric(genericAllocator.root(), ptr);
@@ -684,7 +686,7 @@
     partitionFreeGeneric(genericAllocator.root(), 0);
 
     // Do we correctly get a null for a failed allocation?
-    EXPECT_EQ(0, partitionAllocGenericFlags(genericAllocator.root(), PartitionAllocReturnNull, 3u * 1024 * 1024 * 1024));
+    EXPECT_EQ(0, partitionAllocGenericFlags(genericAllocator.root(), PartitionAllocReturnNull, 3u * 1024 * 1024 * 1024, kTypeName));
 
     TestShutdown();
 }
@@ -702,7 +704,7 @@
     // Allocate something small.
     requestedSize = 511 - kExtraAllocSize;
     predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedSize);
-    ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize);
+    ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, kTypeName);
     EXPECT_TRUE(ptr);
     actualSize = partitionAllocGetSize(ptr);
     EXPECT_EQ(predictedSize, actualSize);
@@ -713,7 +715,7 @@
     // is an exact power of 2.
     requestedSize = (256 * 1024) - kExtraAllocSize;
     predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedSize);
-    ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize);
+    ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, kTypeName);
     EXPECT_TRUE(ptr);
     actualSize = partitionAllocGetSize(ptr);
     EXPECT_EQ(predictedSize, actualSize);
@@ -724,7 +726,7 @@
     // should return a larger size than we asked for now.
     requestedSize = (256 * 1024) - kSystemPageSize - kExtraAllocSize;
     predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedSize);
-    ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize);
+    ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, kTypeName);
     EXPECT_TRUE(ptr);
     actualSize = partitionAllocGetSize(ptr);
     EXPECT_EQ(predictedSize, actualSize);
@@ -737,7 +739,7 @@
     // Allocate something very large, and uneven.
     requestedSize = 512 * 1024 * 1024 - 1;
     predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedSize);
-    ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize);
+    ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, kTypeName);
     EXPECT_TRUE(ptr);
     actualSize = partitionAllocGetSize(ptr);
     EXPECT_EQ(predictedSize, actualSize);
@@ -758,11 +760,11 @@
     TestSetup();
 
     // realloc(0, size) should be equivalent to malloc().
-    void* ptr = partitionReallocGeneric(genericAllocator.root(), 0, kTestAllocSize);
+    void* ptr = partitionReallocGeneric(genericAllocator.root(), 0, kTestAllocSize, kTypeName);
     memset(ptr, 'A', kTestAllocSize);
     PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
     // realloc(ptr, 0) should be equivalent to free().
-    void* ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, 0);
+    void* ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, 0, kTypeName);
     EXPECT_EQ(0, ptr2);
     EXPECT_EQ(partitionCookieFreePointerAdjust(ptr), page->freelistHead);
 
@@ -770,9 +772,9 @@
     // old allocation.
     size_t size = kSystemPageSize - kExtraAllocSize;
     EXPECT_EQ(size, partitionAllocActualSize(genericAllocator.root(), size));
-    ptr = partitionAllocGeneric(genericAllocator.root(), size);
+    ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     memset(ptr, 'A', size);
-    ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, size + 1);
+    ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, size + 1, kTypeName);
     EXPECT_NE(ptr, ptr2);
     char* charPtr2 = static_cast<char*>(ptr2);
     EXPECT_EQ('A', charPtr2[0]);
@@ -783,7 +785,7 @@
 
     // Test that shrinking an allocation with realloc() also copies everything
     // from the old allocation.
-    ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - 1);
+    ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - 1, kTypeName);
     EXPECT_NE(ptr2, ptr);
     char* charPtr = static_cast<char*>(ptr);
     EXPECT_EQ('A', charPtr[0]);
@@ -796,21 +798,21 @@
 
     // Test that shrinking a direct mapped allocation happens in-place.
     size = kGenericMaxBucketed + 16 * kSystemPageSize;
-    ptr = partitionAllocGeneric(genericAllocator.root(), size);
+    ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     size_t actualSize = partitionAllocGetSize(ptr);
-    ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBucketed + 8 * kSystemPageSize);
+    ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBucketed + 8 * kSystemPageSize, kTypeName);
     EXPECT_EQ(ptr, ptr2);
     EXPECT_EQ(actualSize - 8 * kSystemPageSize, partitionAllocGetSize(ptr2));
 
     // Test that a previously in-place shrunk direct mapped allocation can be
     // expanded up again within its original size.
-    ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - kSystemPageSize);
+    ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - kSystemPageSize, kTypeName);
     EXPECT_EQ(ptr2, ptr);
     EXPECT_EQ(actualSize - kSystemPageSize, partitionAllocGetSize(ptr));
 
     // Test that a direct mapped allocation is performed not in-place when the
     // new size is small enough.
-    ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, kSystemPageSize);
+    ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, kSystemPageSize, kTypeName);
     EXPECT_NE(ptr, ptr2);
 
     partitionFreeGeneric(genericAllocator.root(), ptr2);
@@ -829,7 +831,7 @@
     PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx];
     EXPECT_EQ(0, bucket->emptyPagesHead);
 
-    void* ptr = partitionAlloc(allocator.root(), bigSize);
+    void* ptr = partitionAlloc(allocator.root(), bigSize, kTypeName);
     EXPECT_TRUE(ptr);
 
     PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
@@ -842,25 +844,25 @@
     EXPECT_EQ(1, page->numAllocatedSlots);
     EXPECT_EQ(2, page->numUnprovisionedSlots);
 
-    void* ptr2 = partitionAlloc(allocator.root(), bigSize);
+    void* ptr2 = partitionAlloc(allocator.root(), bigSize, kTypeName);
     EXPECT_TRUE(ptr2);
     EXPECT_FALSE(page->freelistHead);
     EXPECT_EQ(2, page->numAllocatedSlots);
     EXPECT_EQ(2, page->numUnprovisionedSlots);
 
-    void* ptr3 = partitionAlloc(allocator.root(), bigSize);
+    void* ptr3 = partitionAlloc(allocator.root(), bigSize, kTypeName);
     EXPECT_TRUE(ptr3);
     EXPECT_TRUE(page->freelistHead);
     EXPECT_EQ(3, page->numAllocatedSlots);
     EXPECT_EQ(0, page->numUnprovisionedSlots);
 
-    void* ptr4 = partitionAlloc(allocator.root(), bigSize);
+    void* ptr4 = partitionAlloc(allocator.root(), bigSize, kTypeName);
     EXPECT_TRUE(ptr4);
     EXPECT_FALSE(page->freelistHead);
     EXPECT_EQ(4, page->numAllocatedSlots);
     EXPECT_EQ(0, page->numUnprovisionedSlots);
 
-    void* ptr5 = partitionAlloc(allocator.root(), bigSize);
+    void* ptr5 = partitionAlloc(allocator.root(), bigSize, kTypeName);
     EXPECT_TRUE(ptr5);
 
     PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr5));
@@ -868,8 +870,8 @@
 
     // Churn things a little whilst there's a partial page freelist.
     partitionFree(ptr);
-    ptr = partitionAlloc(allocator.root(), bigSize);
-    void* ptr6 = partitionAlloc(allocator.root(), bigSize);
+    ptr = partitionAlloc(allocator.root(), bigSize, kTypeName);
+    void* ptr6 = partitionAlloc(allocator.root(), bigSize, kTypeName);
 
     partitionFree(ptr);
     partitionFree(ptr2);
@@ -888,7 +890,7 @@
     bucket = &allocator.root()->buckets()[bucketIdx];
     EXPECT_EQ(0, bucket->emptyPagesHead);
 
-    ptr = partitionAlloc(allocator.root(), mediumSize);
+    ptr = partitionAlloc(allocator.root(), mediumSize, kTypeName);
     EXPECT_TRUE(ptr);
     page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
     EXPECT_EQ(1, page->numAllocatedSlots);
@@ -904,7 +906,7 @@
     bucket = &allocator.root()->buckets()[bucketIdx];
     EXPECT_EQ(0, bucket->emptyPagesHead);
 
-    ptr = partitionAlloc(allocator.root(), smallSize);
+    ptr = partitionAlloc(allocator.root(), smallSize, kTypeName);
     EXPECT_TRUE(ptr);
     page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
     EXPECT_EQ(1, page->numAllocatedSlots);
@@ -921,7 +923,7 @@
     bucket = &allocator.root()->buckets()[bucketIdx];
     EXPECT_EQ(0, bucket->emptyPagesHead);
 
-    ptr = partitionAlloc(allocator.root(), verySmallSize);
+    ptr = partitionAlloc(allocator.root(), verySmallSize, kTypeName);
     EXPECT_TRUE(ptr);
     page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
     EXPECT_EQ(1, page->numAllocatedSlots);
@@ -936,7 +938,7 @@
     // And try an allocation size (against the generic allocator) that is
     // larger than a system page.
     size_t pageAndAHalfSize = (kSystemPageSize + (kSystemPageSize / 2)) - kExtraAllocSize;
-    ptr = partitionAllocGeneric(genericAllocator.root(), pageAndAHalfSize);
+    ptr = partitionAllocGeneric(genericAllocator.root(), pageAndAHalfSize, kTypeName);
     EXPECT_TRUE(ptr);
     page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
     EXPECT_EQ(1, page->numAllocatedSlots);
@@ -947,7 +949,7 @@
 
     // And then make sure than exactly the page size only faults one page.
     size_t pageSize = kSystemPageSize - kExtraAllocSize;
-    ptr = partitionAllocGeneric(genericAllocator.root(), pageSize);
+    ptr = partitionAllocGeneric(genericAllocator.root(), pageSize, kTypeName);
     EXPECT_TRUE(ptr);
     page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
     EXPECT_EQ(1, page->numAllocatedSlots);
@@ -968,7 +970,7 @@
     // Grab two full pages and a non-full page.
     PartitionPage* page1 = GetFullPage(kTestAllocSize);
     PartitionPage* page2 = GetFullPage(kTestAllocSize);
-    void* ptr = partitionAlloc(allocator.root(), kTestAllocSize);
+    void* ptr = partitionAlloc(allocator.root(), kTestAllocSize, kTypeName);
     EXPECT_TRUE(ptr);
     EXPECT_NE(page1, bucket->activePagesHead);
     EXPECT_NE(page2, bucket->activePagesHead);
@@ -983,8 +985,8 @@
 
     // If we perform two allocations from the same bucket now, we expect to
     // refill both the nearly full pages.
-    (void) partitionAlloc(allocator.root(), kTestAllocSize);
-    (void) partitionAlloc(allocator.root(), kTestAllocSize);
+    (void)partitionAlloc(allocator.root(), kTestAllocSize, kTypeName);
+    (void)partitionAlloc(allocator.root(), kTestAllocSize, kTypeName);
     EXPECT_EQ(1, page->numAllocatedSlots);
 
     FreeFullPage(page2);
@@ -1090,7 +1092,7 @@
     size_t bucketIdx = (bigSize + kExtraAllocSize) >> kBucketShift;
     PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx];
 
-    void* ptr = partitionAlloc(allocator.root(), bigSize);
+    void* ptr = partitionAlloc(allocator.root(), bigSize, kTypeName);
     EXPECT_TRUE(ptr);
     PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
     EXPECT_EQ(0, bucket->emptyPagesHead);
@@ -1112,14 +1114,14 @@
 
     // Check that an allocation works ok whilst in this state (a free'd page
     // as the active pages head).
-    ptr = partitionAlloc(allocator.root(), bigSize);
+    ptr = partitionAlloc(allocator.root(), bigSize, kTypeName);
     EXPECT_FALSE(bucket->emptyPagesHead);
     partitionFree(ptr);
 
     // Also check that a page that is bouncing immediately between empty and
     // used does not get freed.
     for (size_t i = 0; i < kMaxFreeableSpans * 2; ++i) {
-        ptr = partitionAlloc(allocator.root(), bigSize);
+        ptr = partitionAlloc(allocator.root(), bigSize, kTypeName);
         EXPECT_TRUE(page->freelistHead);
         partitionFree(ptr);
         EXPECT_TRUE(page->freelistHead);
@@ -1135,9 +1137,9 @@
 
     size_t size = kPartitionPageSize - kExtraAllocSize;
 
-    void* ptr = partitionAllocGeneric(genericAllocator.root(), size);
+    void* ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr);
-    void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size);
+    void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr2);
 
     PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr));
@@ -1168,7 +1170,7 @@
     EXPECT_EQ(&PartitionRootGeneric::gSeedPage, bucket->activePagesHead);
 
     // At this moment, we have two decommitted pages, on the empty list.
-    ptr = partitionAllocGeneric(genericAllocator.root(), size);
+    ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr);
     partitionFreeGeneric(genericAllocator.root(), ptr);
 
@@ -1181,7 +1183,7 @@
     // We're now set up to trigger a historical bug by scanning over the active
     // pages list. The current code gets into a different state, but we'll keep
     // the test as being an interesting corner case.
-    ptr = partitionAllocGeneric(genericAllocator.root(), size);
+    ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_TRUE(ptr);
     partitionFreeGeneric(genericAllocator.root(), ptr);
 
@@ -1203,15 +1205,15 @@
     // Work out the number of allocations for 6 GB of memory.
     const int numAllocations = (6 * 1024 * 1024) / (allocSize / 1024);
 
-    void** ptrs = reinterpret_cast<void**>(partitionAllocGeneric(genericAllocator.root(), numAllocations * sizeof(void*)));
+    void** ptrs = reinterpret_cast<void**>(partitionAllocGeneric(genericAllocator.root(), numAllocations * sizeof(void*), kTypeName));
     int i;
 
     for (i = 0; i < numAllocations; ++i) {
-        ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionAllocReturnNull, allocSize);
+        ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionAllocReturnNull, allocSize, kTypeName);
         if (!i)
             EXPECT_TRUE(ptrs[0]);
         if (!ptrs[i]) {
-            ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionAllocReturnNull, allocSize);
+            ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionAllocReturnNull, allocSize, kTypeName);
             EXPECT_FALSE(ptrs[i]);
             break;
         }
@@ -1225,7 +1227,7 @@
     // check that freeing memory also works correctly after a failed allocation.
     for (--i; i >= 0; --i) {
         partitionFreeGeneric(genericAllocator.root(), ptrs[i]);
-        ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionAllocReturnNull, allocSize);
+        ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionAllocReturnNull, allocSize, kTypeName);
         EXPECT_TRUE(ptrs[i]);
         partitionFreeGeneric(genericAllocator.root(), ptrs[i]);
     }
@@ -1275,9 +1277,9 @@
 {
     TestSetup();
     // Largest alloc.
-    EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size_t>(-1)), "");
+    EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size_t>(-1), kTypeName), "");
     // And the smallest allocation we expect to die.
-    EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size_t>(INT_MAX) + 1), "");
+    EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size_t>(INT_MAX) + 1, kTypeName), "");
 
     TestShutdown();
 }
@@ -1287,7 +1289,7 @@
 {
     TestSetup();
 
-    void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize);
+    void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize, kTypeName);
     EXPECT_TRUE(ptr);
     partitionFreeGeneric(genericAllocator.root(), ptr);
 
@@ -1301,9 +1303,9 @@
 {
     TestSetup();
 
-    void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize);
+    void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize, kTypeName);
     EXPECT_TRUE(ptr);
-    void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize);
+    void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize, kTypeName);
     EXPECT_TRUE(ptr2);
     partitionFreeGeneric(genericAllocator.root(), ptr);
     partitionFreeGeneric(genericAllocator.root(), ptr2);
@@ -1337,7 +1339,7 @@
 #undef ALIGN
     static_assert(kSize > kGenericMaxBucketed, "allocation not large enough for direct allocation");
     size_t size = kSize - kExtraAllocSize;
-    void* ptr = partitionAllocGeneric(genericAllocator.root(), size);
+    void* ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
 
     EXPECT_TRUE(ptr);
     char* charPtr = reinterpret_cast<char*>(ptr) - kPointerOffset;
@@ -1358,7 +1360,7 @@
 
     // This large size will result in a direct mapped allocation with guard
     // pages at either end.
-    void* ptr = partitionAllocGeneric(genericAllocator.root(), kPartitionPageSize * 2);
+    void* ptr = partitionAllocGeneric(genericAllocator.root(), kPartitionPageSize * 2, kTypeName);
     EXPECT_TRUE(ptr);
     char* badPtr = reinterpret_cast<char*>(ptr) + kPartitionPageSize;
 
@@ -1377,7 +1379,7 @@
 {
     TestSetup();
     {
-        void* ptr = partitionAlloc(allocator.root(), kTestAllocSize);
+        void* ptr = partitionAlloc(allocator.root(), kTestAllocSize, kTypeName);
         MockPartitionStatsDumper mockStatsDumper;
         partitionDumpStats(allocator.root(), "mock_allocator", false /* detailed dump */, &mockStatsDumper);
         EXPECT_TRUE(mockStatsDumper.IsMemoryAllocationRecorded());
@@ -1387,7 +1389,7 @@
 
     // This series of tests checks the active -> empty -> decommitted states.
     {
-        void* genericPtr = partitionAllocGeneric(genericAllocator.root(), 2048 - kExtraAllocSize);
+        void* genericPtr = partitionAllocGeneric(genericAllocator.root(), 2048 - kExtraAllocSize, kTypeName);
         {
             MockPartitionStatsDumper mockStatsDumperGeneric;
             partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_allocator", false /* detailed dump */, &mockStatsDumperGeneric);
@@ -1453,14 +1455,14 @@
     // This test checks for correct empty page list accounting.
     {
         size_t size = kPartitionPageSize - kExtraAllocSize;
-        void* ptr1 = partitionAllocGeneric(genericAllocator.root(), size);
-        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size);
+        void* ptr1 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
+        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
         partitionFreeGeneric(genericAllocator.root(), ptr1);
         partitionFreeGeneric(genericAllocator.root(), ptr2);
 
         CycleGenericFreeCache(kTestAllocSize);
 
-        ptr1 = partitionAllocGeneric(genericAllocator.root(), size);
+        ptr1 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
 
         {
             MockPartitionStatsDumper mockStatsDumperGeneric;
@@ -1489,8 +1491,8 @@
         size_t sizeBigger = (kGenericMaxBucketed * 2) + 1;
         size_t realSizeSmaller = (sizeSmaller + kSystemPageOffsetMask) & kSystemPageBaseMask;
         size_t realSizeBigger = (sizeBigger + kSystemPageOffsetMask) & kSystemPageBaseMask;
-        void* ptr = partitionAllocGeneric(genericAllocator.root(), sizeSmaller);
-        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), sizeBigger);
+        void* ptr = partitionAllocGeneric(genericAllocator.root(), sizeSmaller, kTypeName);
+        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), sizeBigger, kTypeName);
 
         {
             MockPartitionStatsDumper mockStatsDumperGeneric;
@@ -1531,15 +1533,15 @@
 
         // Whilst we're here, allocate again and free with different ordering
         // to give a workout to our linked list code.
-        ptr = partitionAllocGeneric(genericAllocator.root(), sizeSmaller);
-        ptr2 = partitionAllocGeneric(genericAllocator.root(), sizeBigger);
+        ptr = partitionAllocGeneric(genericAllocator.root(), sizeSmaller, kTypeName);
+        ptr2 = partitionAllocGeneric(genericAllocator.root(), sizeBigger, kTypeName);
         partitionFreeGeneric(genericAllocator.root(), ptr);
         partitionFreeGeneric(genericAllocator.root(), ptr2);
     }
 
     // This test checks large-but-not-quite-direct allocations.
     {
-        void* ptr = partitionAllocGeneric(genericAllocator.root(), 65536 + 1);
+        void* ptr = partitionAllocGeneric(genericAllocator.root(), 65536 + 1, kTypeName);
 
         {
             MockPartitionStatsDumper mockStatsDumperGeneric;
@@ -1584,7 +1586,7 @@
             EXPECT_EQ(0u, stats->numDecommittedPages);
         }
 
-        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), 65536 + kSystemPageSize + 1);
+        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), 65536 + kSystemPageSize + 1, kTypeName);
         EXPECT_EQ(ptr, ptr2);
 
         {
@@ -1619,7 +1621,7 @@
 {
     TestSetup();
 
-    char* ptr = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), 2048 - kExtraAllocSize));
+    char* ptr = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), 2048 - kExtraAllocSize, kTypeName));
     partitionFreeGeneric(genericAllocator.root(), ptr);
     {
         MockPartitionStatsDumper mockStatsDumperGeneric;
@@ -1648,7 +1650,7 @@
     // state of the free cache ring.
     partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitEmptyPages);
 
-    char* bigPtr = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), 256 * 1024));
+    char* bigPtr = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), 256 * 1024, kTypeName));
     partitionFreeGeneric(genericAllocator.root(), bigPtr);
     partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitEmptyPages);
 
@@ -1669,12 +1671,12 @@
     // Allocate 3 full slot spans worth of 8192-byte allocations.
     // Each slot span for this size is 16384 bytes, or 1 partition page and 2
     // slots.
-    void* ptr1 = partitionAllocGeneric(genericAllocator.root(), size);
-    void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size);
-    void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size);
-    void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size);
-    void* ptr5 = partitionAllocGeneric(genericAllocator.root(), size);
-    void* ptr6 = partitionAllocGeneric(genericAllocator.root(), size);
+    void* ptr1 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
+    void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
+    void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
+    void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
+    void* ptr5 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
+    void* ptr6 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
 
     PartitionPage* page1 = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr1));
     PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr3));
@@ -1701,7 +1703,7 @@
 
     // A good choice here is to re-fill the third page since the first two are
     // empty. We used to fail that.
-    void* ptr7 = partitionAllocGeneric(genericAllocator.root(), size);
+    void* ptr7 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName);
     EXPECT_EQ(ptr6, ptr7);
     EXPECT_EQ(page3, bucket->activePagesHead);
 
@@ -1718,8 +1720,8 @@
 
     // Free the second of two 4096 byte allocations and then purge.
     {
-        void* ptr1 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
-        char* ptr2 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize));
+        void* ptr1 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
+        char* ptr2 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName));
         partitionFreeGeneric(genericAllocator.root(), ptr2);
         PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr1));
         EXPECT_EQ(2u, page->numUnprovisionedSlots);
@@ -1745,8 +1747,8 @@
     }
     // Free the first of two 4096 byte allocations and then purge.
     {
-        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize));
-        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
+        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName));
+        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
         partitionFreeGeneric(genericAllocator.root(), ptr1);
         {
             MockPartitionStatsDumper mockStatsDumperGeneric;
@@ -1768,10 +1770,10 @@
         partitionFreeGeneric(genericAllocator.root(), ptr2);
     }
     {
-        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), 9216 - kExtraAllocSize));
-        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtraAllocSize);
-        void* ptr3 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtraAllocSize);
-        void* ptr4 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtraAllocSize);
+        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), 9216 - kExtraAllocSize, kTypeName));
+        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtraAllocSize, kTypeName);
+        void* ptr3 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtraAllocSize, kTypeName);
+        void* ptr4 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtraAllocSize, kTypeName);
         memset(ptr1, 'A', 9216 - kExtraAllocSize);
         memset(ptr2, 'A', 9216 - kExtraAllocSize);
         partitionFreeGeneric(genericAllocator.root(), ptr2);
@@ -1805,10 +1807,10 @@
         partitionFreeGeneric(genericAllocator.root(), ptr4);
     }
     {
-        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), (64 * kSystemPageSize) - kExtraAllocSize));
+        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), (64 * kSystemPageSize) - kExtraAllocSize, kTypeName));
         memset(ptr1, 'A', (64 * kSystemPageSize) - kExtraAllocSize);
         partitionFreeGeneric(genericAllocator.root(), ptr1);
-        ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), (61 * kSystemPageSize) - kExtraAllocSize));
+        ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), (61 * kSystemPageSize) - kExtraAllocSize, kTypeName));
         {
             MockPartitionStatsDumper mockStatsDumperGeneric;
             partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_allocator", false /* detailed dump */, &mockStatsDumperGeneric);
@@ -1838,10 +1840,10 @@
     // case where the freelist is rewritten.
     partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitEmptyPages);
     {
-        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize));
-        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
-        void* ptr3 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
-        void* ptr4 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
+        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName));
+        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
+        void* ptr3 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
+        void* ptr4 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
         ptr1[0] = 'A';
         ptr1[kSystemPageSize] = 'A';
         ptr1[kSystemPageSize * 2] = 'A';
@@ -1877,9 +1879,9 @@
         CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 3), false);
 
         // Let's check we didn't brick the freelist.
-        void* ptr1b = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
+        void* ptr1b = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
         EXPECT_EQ(ptr1, ptr1b);
-        void* ptr2b = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
+        void* ptr2b = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
         EXPECT_EQ(ptr2, ptr2b);
         EXPECT_FALSE(page->freelistHead);
 
@@ -1890,10 +1892,10 @@
     // This sub-test is similar, but tests a double-truncation.
     partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitEmptyPages);
     {
-        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize));
-        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
-        void* ptr3 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
-        void* ptr4 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize);
+        char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName));
+        void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
+        void* ptr3 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
+        void* ptr4 = partitionAllocGeneric(genericAllocator.root(), kSystemPageSize - kExtraAllocSize, kTypeName);
         ptr1[0] = 'A';
         ptr1[kSystemPageSize] = 'A';
         ptr1[kSystemPageSize * 2] = 'A';
diff --git a/third_party/WebKit/Source/wtf/PartitionAllocator.cpp b/third_party/WebKit/Source/wtf/PartitionAllocator.cpp
index 2befd34..1c1c3939 100644
--- a/third_party/WebKit/Source/wtf/PartitionAllocator.cpp
+++ b/third_party/WebKit/Source/wtf/PartitionAllocator.cpp
@@ -36,9 +36,9 @@
 
 namespace WTF {
 
-void* PartitionAllocator::allocateBacking(size_t size)
+void* PartitionAllocator::allocateBacking(size_t size, const char* typeName)
 {
-    return Partitions::bufferMalloc(size);
+    return Partitions::bufferMalloc(size, typeName);
 }
 
 void PartitionAllocator::freeVectorBacking(void* address)
diff --git a/third_party/WebKit/Source/wtf/PartitionAllocator.h b/third_party/WebKit/Source/wtf/PartitionAllocator.h
index de84fb7..08f0f43 100644
--- a/third_party/WebKit/Source/wtf/PartitionAllocator.h
+++ b/third_party/WebKit/Source/wtf/PartitionAllocator.h
@@ -60,12 +60,12 @@
     template <typename T>
     static T* allocateVectorBacking(size_t size)
     {
-        return reinterpret_cast<T*>(allocateBacking(size));
+        return reinterpret_cast<T*>(allocateBacking(size, WTF_HEAP_PROFILER_TYPE_NAME(T)));
     }
     template <typename T>
     static T* allocateExpandedVectorBacking(size_t size)
     {
-        return reinterpret_cast<T*>(allocateBacking(size));
+        return reinterpret_cast<T*>(allocateBacking(size, WTF_HEAP_PROFILER_TYPE_NAME(T)));
     }
     static void freeVectorBacking(void* address);
     static inline bool expandVectorBacking(void*, size_t)
@@ -87,21 +87,21 @@
     template <typename T, typename HashTable>
     static T* allocateHashTableBacking(size_t size)
     {
-        return reinterpret_cast<T*>(allocateBacking(size));
+        return reinterpret_cast<T*>(allocateBacking(size, WTF_HEAP_PROFILER_TYPE_NAME(T)));
     }
     template <typename T, typename HashTable>
     static T* allocateZeroedHashTableBacking(size_t size)
     {
-        void* result = allocateBacking(size);
+        void* result = allocateBacking(size, WTF_HEAP_PROFILER_TYPE_NAME(T));
         memset(result, 0, size);
         return reinterpret_cast<T*>(result);
     }
     static void freeHashTableBacking(void* address);
 
     template <typename Return, typename Metadata>
-    static Return malloc(size_t size)
+    static Return malloc(size_t size, const char* typeName)
     {
-        return reinterpret_cast<Return>(Partitions::fastMalloc(size));
+        return reinterpret_cast<Return>(Partitions::fastMalloc(size, typeName));
     }
 
     static inline bool expandHashTableBacking(void*, size_t)
@@ -115,7 +115,7 @@
     template<typename T>
     static void* newArray(size_t bytes)
     {
-        return malloc<void*, void>(bytes);
+        return malloc<void*, void>(bytes, WTF_HEAP_PROFILER_TYPE_NAME(T));
     }
     static void
     deleteArray(void* ptr)
@@ -180,7 +180,7 @@
     static void leaveGCForbiddenScope() { }
 
 private:
-    static void* allocateBacking(size_t);
+    static void* allocateBacking(size_t, const char* typeName);
 };
 
 // The Windows compiler seems to be very eager to instantiate things it won't
@@ -200,7 +200,7 @@
 public: \
     void* operator new(size_t size) \
     { \
-        return Allocator::template malloc<void*, ClassName>(size); \
+        return Allocator::template malloc<void*, ClassName>(size, WTF_HEAP_PROFILER_TYPE_NAME(ClassName)); \
     } \
     void operator delete(void* p) { Allocator::free(p); } \
     void* operator new[](size_t size) { return Allocator::template newArray<ClassName>(size); } \
diff --git a/third_party/WebKit/Source/wtf/Partitions.h b/third_party/WebKit/Source/wtf/Partitions.h
index a36c826b..7b18ef8 100644
--- a/third_party/WebKit/Source/wtf/Partitions.h
+++ b/third_party/WebKit/Source/wtf/Partitions.h
@@ -91,9 +91,9 @@
 
     static void dumpMemoryStats(bool isLightDump, PartitionStatsDumper*);
 
-    ALWAYS_INLINE static void* bufferMalloc(size_t n)
+    ALWAYS_INLINE static void* bufferMalloc(size_t n, const char* typeName)
     {
-        return partitionAllocGeneric(bufferPartition(), n);
+        return partitionAllocGeneric(bufferPartition(), n, typeName);
     }
     ALWAYS_INLINE static void bufferFree(void* p)
     {
@@ -103,19 +103,19 @@
     {
         return partitionAllocActualSize(bufferPartition(), n);
     }
-    static void* fastMalloc(size_t n)
+    static void* fastMalloc(size_t n, const char* typeName)
     {
-        return partitionAllocGeneric(Partitions::fastMallocPartition(), n);
+        return partitionAllocGeneric(Partitions::fastMallocPartition(), n, typeName);
     }
-    static void* fastZeroedMalloc(size_t n)
+    static void* fastZeroedMalloc(size_t n, const char* typeName)
     {
-        void* result = fastMalloc(n);
+        void* result = fastMalloc(n, typeName);
         memset(result, 0, n);
         return result;
     }
-    static void* fastRealloc(void* p, size_t n)
+    static void* fastRealloc(void* p, size_t n, const char* typeName)
     {
-        return partitionReallocGeneric(Partitions::fastMallocPartition(), p, n);
+        return partitionReallocGeneric(Partitions::fastMallocPartition(), p, n, typeName);
     }
     static void fastFree(void* p)
     {
diff --git a/third_party/WebKit/Source/wtf/RefCounted.h b/third_party/WebKit/Source/wtf/RefCounted.h
index cae8123..247962c 100644
--- a/third_party/WebKit/Source/wtf/RefCounted.h
+++ b/third_party/WebKit/Source/wtf/RefCounted.h
@@ -163,7 +163,11 @@
 
 template<typename T> class RefCounted : public RefCountedBase {
     WTF_MAKE_NONCOPYABLE(RefCounted);
-    USING_FAST_MALLOC(RefCounted);
+
+    // Put |T| in here instead of |RefCounted| so the heap profiler reports |T|
+    // instead of |RefCounted<T>|. This does not affect overloading of operator
+    // new.
+    USING_FAST_MALLOC(T);
 
 public:
     void deref()
diff --git a/third_party/WebKit/Source/wtf/TerminatedArray.h b/third_party/WebKit/Source/wtf/TerminatedArray.h
index 9901e2a..5b867143 100644
--- a/third_party/WebKit/Source/wtf/TerminatedArray.h
+++ b/third_party/WebKit/Source/wtf/TerminatedArray.h
@@ -76,12 +76,12 @@
 
         static PassPtr create(size_t capacity)
         {
-            return adoptPtr(static_cast<TerminatedArray*>(WTF::Partitions::fastMalloc(capacity * sizeof(T))));
+            return adoptPtr(static_cast<TerminatedArray*>(WTF::Partitions::fastMalloc(capacity * sizeof(T), WTF_HEAP_PROFILER_TYPE_NAME(T))));
         }
 
         static PassPtr resize(PassPtr ptr, size_t capacity)
         {
-            return adoptPtr(static_cast<TerminatedArray*>(WTF::Partitions::fastRealloc(ptr.leakPtr(), capacity * sizeof(T))));
+            return adoptPtr(static_cast<TerminatedArray*>(WTF::Partitions::fastRealloc(ptr.leakPtr(), capacity * sizeof(T), WTF_HEAP_PROFILER_TYPE_NAME(T))));
         }
     };
 
diff --git a/third_party/WebKit/Source/wtf/ThreadSpecific.h b/third_party/WebKit/Source/wtf/ThreadSpecific.h
index d164280..cbc6b22c 100644
--- a/third_party/WebKit/Source/wtf/ThreadSpecific.h
+++ b/third_party/WebKit/Source/wtf/ThreadSpecific.h
@@ -260,7 +260,7 @@
     if (!ptr) {
         // Set up thread-specific value's memory pointer before invoking constructor, in case any function it calls
         // needs to access the value, to avoid recursion.
-        ptr = static_cast<T*>(Partitions::fastZeroedMalloc(sizeof(T)));
+        ptr = static_cast<T*>(Partitions::fastZeroedMalloc(sizeof(T), WTF_HEAP_PROFILER_TYPE_NAME(T)));
         set(ptr);
         new (NotNull, ptr) T;
     }
diff --git a/third_party/WebKit/Source/wtf/TypeTraits.h b/third_party/WebKit/Source/wtf/TypeTraits.h
index c8ad765e..f91e998 100644
--- a/third_party/WebKit/Source/wtf/TypeTraits.h
+++ b/third_party/WebKit/Source/wtf/TypeTraits.h
@@ -25,8 +25,17 @@
 #include <cstddef>
 #include <utility>
 
+#include "wtf/Compiler.h"
+
 namespace WTF {
 
+// Returns a string that contains the type name of |T| as a substring.
+template<typename T>
+inline const char* getStringWithTypeName()
+{
+    return WTF_PRETTY_FUNCTION;
+}
+
 template<typename T> class RawPtr;
 
 // The following are provided in this file:
diff --git a/third_party/WebKit/Source/wtf/text/CString.cpp b/third_party/WebKit/Source/wtf/text/CString.cpp
index b01893c7..d99a1ee5 100644
--- a/third_party/WebKit/Source/wtf/text/CString.cpp
+++ b/third_party/WebKit/Source/wtf/text/CString.cpp
@@ -41,7 +41,7 @@
 
     // The +1 is for the terminating NUL character.
     size_t size = sizeof(CStringBuffer) + length + 1;
-    CStringBuffer* stringBuffer = static_cast<CStringBuffer*>(Partitions::bufferMalloc(size));
+    CStringBuffer* stringBuffer = static_cast<CStringBuffer*>(Partitions::bufferMalloc(size, WTF_HEAP_PROFILER_TYPE_NAME(CStringBuffer)));
     return adoptRef(new (stringBuffer) CStringBuffer(length));
 }
 
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.cpp b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
index 56b81dab..fc1dc7c 100644
--- a/third_party/WebKit/Source/wtf/text/StringImpl.cpp
+++ b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
@@ -261,7 +261,7 @@
 void* StringImpl::operator new(size_t size)
 {
     ASSERT(size == sizeof(StringImpl));
-    return Partitions::bufferMalloc(size);
+    return Partitions::bufferMalloc(size, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl));
 }
 
 void StringImpl::operator delete(void* ptr)
@@ -295,7 +295,7 @@
     // Allocate a single buffer large enough to contain the StringImpl
     // struct as well as the data which it contains. This removes one
     // heap allocation from this call.
-    StringImpl* string = static_cast<StringImpl*>(Partitions::bufferMalloc(allocationSize<LChar>(length)));
+    StringImpl* string = static_cast<StringImpl*>(Partitions::bufferMalloc(allocationSize<LChar>(length), WTF_HEAP_PROFILER_TYPE_NAME(StringImpl)));
 
     data = reinterpret_cast<LChar*>(string + 1);
     return adoptRef(new (string) StringImpl(length, Force8BitConstructor));
@@ -311,7 +311,7 @@
     // Allocate a single buffer large enough to contain the StringImpl
     // struct as well as the data which it contains. This removes one
     // heap allocation from this call.
-    StringImpl* string = static_cast<StringImpl*>(Partitions::bufferMalloc(allocationSize<UChar>(length)));
+    StringImpl* string = static_cast<StringImpl*>(Partitions::bufferMalloc(allocationSize<UChar>(length), WTF_HEAP_PROFILER_TYPE_NAME(StringImpl)));
 
     data = reinterpret_cast<UChar*>(string + 1);
     return adoptRef(new (string) StringImpl(length));
@@ -362,7 +362,7 @@
     size_t size = sizeof(StringImpl) + length * sizeof(LChar);
 
     WTF_ANNOTATE_SCOPED_MEMORY_LEAK;
-    StringImpl* impl = static_cast<StringImpl*>(Partitions::bufferMalloc(size));
+    StringImpl* impl = static_cast<StringImpl*>(Partitions::bufferMalloc(size, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl)));
 
     LChar* data = reinterpret_cast<LChar*>(impl + 1);
     impl = new (impl) StringImpl(length, hash, StaticString);
diff --git a/third_party/WebKit/Source/wtf/text/StringImplCF.cpp b/third_party/WebKit/Source/wtf/text/StringImplCF.cpp
index 999e2e2d..7528579d 100644
--- a/third_party/WebKit/Source/wtf/text/StringImplCF.cpp
+++ b/third_party/WebKit/Source/wtf/text/StringImplCF.cpp
@@ -62,7 +62,7 @@
             underlyingString->ref(); // Balanced by call to deref in deallocate below.
         }
     }
-    StringImpl** header = static_cast<StringImpl**>(WTF::Partitions::fastMalloc(sizeof(StringImpl*) + size));
+    StringImpl** header = static_cast<StringImpl**>(WTF::Partitions::fastMalloc(sizeof(StringImpl*) + size, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl*)));
     *header = underlyingString;
     return header + 1;
 }
@@ -72,7 +72,7 @@
     size_t newAllocationSize = sizeof(StringImpl*) + newSize;
     StringImpl** header = static_cast<StringImpl**>(pointer) - 1;
     ASSERT(!*header);
-    header = static_cast<StringImpl**>(WTF::Partitions::fastRealloc(header, newAllocationSize));
+    header = static_cast<StringImpl**>(WTF::Partitions::fastRealloc(header, newAllocationSize, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl*)));
     return header + 1;
 }
 
diff --git a/third_party/WebKit/public/blink_headers.gypi b/third_party/WebKit/public/blink_headers.gypi
index cb5ad32..b231d11 100644
--- a/third_party/WebKit/public/blink_headers.gypi
+++ b/third_party/WebKit/public/blink_headers.gypi
@@ -464,6 +464,7 @@
       "web/WebSharedWorker.h",
       "web/WebSharedWorkerClient.h",
       "web/WebSharedWorkerConnector.h",
+      "web/WebWorkerCreationErrors.h",
       "web/WebSharedWorkerRepositoryClient.h",
       "web/WebSocket.h",
       "web/WebSocketClient.h",
diff --git a/third_party/WebKit/public/platform/WebMemoryDumpProvider.h b/third_party/WebKit/public/platform/WebMemoryDumpProvider.h
index 62fbd13e..2cc644db 100644
--- a/third_party/WebKit/public/platform/WebMemoryDumpProvider.h
+++ b/third_party/WebKit/public/platform/WebMemoryDumpProvider.h
@@ -25,7 +25,7 @@
 public:
     // Function types for functions that can be called on alloc and free to do
     // heap profiling.
-    typedef void AllocationHook(void* address, size_t);
+    typedef void AllocationHook(void* address, size_t, const char*);
     typedef void FreeHook(void* address);
 
     virtual ~WebMemoryDumpProvider();
diff --git a/third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h b/third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h
new file mode 100644
index 0000000..19e9bc3
--- /dev/null
+++ b/third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h
@@ -0,0 +1,22 @@
+// 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 WebSharedWorkerCreationErrors_h
+#define WebSharedWorkerCreationErrors_h
+
+#include "../platform/WebCommon.h"
+
+namespace blink {
+
+// Describes errors that can occur while creating a SharedWorker.
+enum WebWorkerCreationError {
+    WebWorkerCreationErrorNone = 0,
+    WebWorkerCreationErrorURLMismatch,
+    WebWorkerCreationErrorSecureContextMismatch,
+    WebWorkerCreationErrorLast = WebWorkerCreationErrorSecureContextMismatch
+};
+
+} // namespace blink
+
+#endif // WebSharedWorkerCreationErrors_h
diff --git a/third_party/WebKit/public/web/WebSharedWorkerRepositoryClient.h b/third_party/WebKit/public/web/WebSharedWorkerRepositoryClient.h
index 45a4a691..119d63a0 100644
--- a/third_party/WebKit/public/web/WebSharedWorkerRepositoryClient.h
+++ b/third_party/WebKit/public/web/WebSharedWorkerRepositoryClient.h
@@ -32,6 +32,7 @@
 #define WebSharedWorkerRepositoryClient_h
 
 #include "WebSharedWorkerConnector.h"
+#include "WebSharedWorkerCreationErrors.h"
 
 namespace blink {
 
@@ -45,8 +46,7 @@
     typedef unsigned long long DocumentID;
 
     // Creates a new shared worker connector. This may return null.
-    virtual WebSharedWorkerConnector* createSharedWorkerConnector(const WebURL& url, const WebString& name, DocumentID id, const WebString& contentSecurityPolicy, WebContentSecurityPolicyType) { return 0; }
-
+    virtual WebSharedWorkerConnector* createSharedWorkerConnector(const WebURL& url, const WebString& name, DocumentID id, const WebString& contentSecurityPolicy, WebContentSecurityPolicyType, WebWorkerCreationError* error) { return 0; }
 
     // Invoked when a document has been detached. DocumentID can be re-used after documentDetached() is invoked.
     virtual void documentDetached(DocumentID) { }
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium
index 1d869b10..3aca540d 100644
--- a/third_party/qcms/README.chromium
+++ b/third_party/qcms/README.chromium
@@ -117,6 +117,8 @@
    - https://code.google.com/p/chromium/issues/detail?id=551568
  - Minimize transform RMS in qcms_transform_data_rgb(a)_out_lut
    - https://code.google.com/p/chromium/issues/detail?id=532910
+ - Allow negative XYZ for display profiles on the APPLE port
+   - https://code.google.com/p/chromium/issues/detail?id=562951
 
 For the Chromium changes, since the import, in a patch format run:
   git diff b8456f38 src
diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c
index b62f127d..0e34bad 100644
--- a/third_party/qcms/src/iccread.c
+++ b/third_party/qcms/src/iccread.c
@@ -253,82 +253,93 @@
 	return index;
 }
 
-// Checks a profile for obvious inconsistencies and returns
-// true if the profile looks bogus and should probably be
-// ignored.
+/* Checks a profile for obvious inconsistencies and return true if the
+ * profile looks bogus and should probably be ignored.
+ */
 qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
 {
-       float sum[3], target[3], tolerance[3];
-       float rX, rY, rZ, gX, gY, gZ, bX, bY, bZ;
-       bool negative;
-       unsigned i;
+        float rX, rY, rZ, gX, gY, gZ, bX, bY, bZ;
+        float target[3], tolerance[3], sum[3];
+        unsigned i;
 
-       // We currently only check the bogosity of RGB profiles
-       if (profile->color_space != RGB_SIGNATURE)
-	       return false;
-
-       if (qcms_supports_iccv4 && (profile->A2B0 || profile->B2A0))
+        // We currently only check the bogosity of RGB profiles.
+        if (profile->color_space != RGB_SIGNATURE)
                return false;
 
-       rX = s15Fixed16Number_to_float(profile->redColorant.X);
-       rY = s15Fixed16Number_to_float(profile->redColorant.Y);
-       rZ = s15Fixed16Number_to_float(profile->redColorant.Z);
+        if (qcms_supports_iccv4 && (profile->A2B0 || profile->B2A0))
+               return false;
 
-       gX = s15Fixed16Number_to_float(profile->greenColorant.X);
-       gY = s15Fixed16Number_to_float(profile->greenColorant.Y);
-       gZ = s15Fixed16Number_to_float(profile->greenColorant.Z);
+        rX = s15Fixed16Number_to_float(profile->redColorant.X);
+        rY = s15Fixed16Number_to_float(profile->redColorant.Y);
+        rZ = s15Fixed16Number_to_float(profile->redColorant.Z);
 
-       bX = s15Fixed16Number_to_float(profile->blueColorant.X);
-       bY = s15Fixed16Number_to_float(profile->blueColorant.Y);
-       bZ = s15Fixed16Number_to_float(profile->blueColorant.Z);
+        gX = s15Fixed16Number_to_float(profile->greenColorant.X);
+        gY = s15Fixed16Number_to_float(profile->greenColorant.Y);
+        gZ = s15Fixed16Number_to_float(profile->greenColorant.Z);
 
-       // Check if any of the XYZ values are negative (see mozilla bug 498245)
-       // CIEXYZ tristimulus values cannot be negative according to the spec.
-       negative =
-	       (rX < 0) || (rY < 0) || (rZ < 0) ||
-	       (gX < 0) || (gY < 0) || (gZ < 0) ||
-	       (bX < 0) || (bY < 0) || (bZ < 0);
+        bX = s15Fixed16Number_to_float(profile->blueColorant.X);
+        bY = s15Fixed16Number_to_float(profile->blueColorant.Y);
+        bZ = s15Fixed16Number_to_float(profile->blueColorant.Z);
 
-       if (negative)
-	       return true;
+        // Build our target vector: CIE D50 white. See also mozilla bug 460629,
+        // and http://www.color.org/whyd50.xalter "Why is the media white point
+        // of a display profile always D50?"
 
+        target[0] = (float) 0.96420;
+        target[1] = (float) 1.00000;
+        target[2] = (float) 0.82491;
 
-       // Sum the values; they should add up to something close to white
-       sum[0] = rX + gX + bX;
-       sum[1] = rY + gY + bY;
-       sum[2] = rZ + gZ + bZ;
+        // Our tolerance vector - Recommended by Chris Murphy [1] based on
+        // conversion from the L*a*b space criterion of no more than 3 in any
+        // one channel. This is similar to, but slightly more tolerant than
+        // Adobe's criterion. [1] https://bugzil.la/460629#c10
 
-#if defined (_MSC_VER)
-#pragma warning(push)
-/* Disable double to float truncation warning 4305 */
-#pragma warning(disable:4305)
+        tolerance[0] = (float) 0.02;
+        tolerance[1] = (float) 0.02;
+        tolerance[2] = (float) 0.04;
+
+        // Sum the XYZ values: they should add to D50 white, within tolerance.
+
+        // FIXME: this test assumes the TRC RGB curves equal 1.0 for the white
+        // input (255,255,255) RGB test color. For user display profiles, that
+        // is the normal case. Profiles with abnormal TRC exist. A better test
+        // would transform 255,255,255 white through the profile to either XYZ
+        // or L*a*b color and compare the result to D50 in XYZ or L*a*b color.
+
+        sum[0] = rX + gX + bX;
+        sum[1] = rY + gY + bY;
+        sum[2] = rZ + gZ + bZ;
+
+        for (i = 0; i < 3; ++i) {
+            if (!(((sum[i] - tolerance[i]) <= target[i]) &&
+                  ((sum[i] + tolerance[i]) >= target[i]))) {
+                return true; // out of tolerance: bogus
+            }
+        }
+
+#ifndef __APPLE__
+
+        // Check if any of the XYZ values are negative (see mozilla bug 498245)
+        // CIEXYZ tristimulus values cannot be negative according to the spec.
+
+        bool negative =
+            (rX < 0) || (rY < 0) || (rZ < 0) ||
+            (gX < 0) || (gY < 0) || (gZ < 0) ||
+            (bX < 0) || (bY < 0) || (bZ < 0);
+
+        if (negative)
+            return true; // bogus
+#else
+        // Chromatic adaption to D50 can result in negative XYZ, but the white
+        // point D50 tolerance test has passed. Accept negative values herein.
+        // See https://bugzilla.mozilla.org/show_bug.cgi?id=498245#c18 onwards
+        // for discussion about whether profile XYZ can or cannot be negative,
+        // per the spec. Also the https://bugzil.la/450923 user report.
+
+        // FIXME: allow this relaxation on all ports?
 #endif
-       // Build our target vector (see mozilla bug 460629)
-       target[0] = 0.96420;
-       target[1] = 1.00000;
-       target[2] = 0.82491;
-
-       // Our tolerance vector - Recommended by Chris Murphy based on
-       // conversion from the LAB space criterion of no more than 3 in any one
-       // channel. This is similar to, but slightly more tolerant than Adobe's
-       // criterion.
-       tolerance[0] = 0.02;
-       tolerance[1] = 0.02;
-       tolerance[2] = 0.04;
-
-#if defined (_MSC_VER)
-/* Restore warnings */
-#pragma warning(pop)
-#endif
-       // Compare with our tolerance
-       for (i = 0; i < 3; ++i) {
-           if (!(((sum[i] - tolerance[i]) <= target[i]) &&
-                 ((sum[i] + tolerance[i]) >= target[i])))
-               return true;
-       }
-
-       // All Good
-       return false;
+        // All good.
+        return false;
 }
 
 #define TAG_bXYZ 0x6258595a
diff --git a/tools/gn/c_include_iterator.cc b/tools/gn/c_include_iterator.cc
index 120295e..bb43803 100644
--- a/tools/gn/c_include_iterator.cc
+++ b/tools/gn/c_include_iterator.cc
@@ -17,12 +17,6 @@
   INCLUDE_USER     // #include "..."
 };
 
-// Returns true if str starts with the prefix.
-bool StartsWith(const base::StringPiece& str, const base::StringPiece& prefix) {
-  base::StringPiece extracted = str.substr(0, prefix.size());
-  return extracted == prefix;
-}
-
 // Returns a new string piece referencing the same buffer as the argument, but
 // with leading space trimmed. This only checks for space and tab characters
 // since we're dealing with lines in C source files.
@@ -46,11 +40,12 @@
 // We assume the line has leading whitespace trimmed. We also assume that empty
 // lines have already been filtered out.
 bool ShouldCountTowardNonIncludeLines(const base::StringPiece& line) {
-  if (StartsWith(line, "//"))
+  if (base::StartsWith(line, "//", base::CompareCase::SENSITIVE))
     return false;  // Don't count comments.
-  if (StartsWith(line, "/*") || StartsWith(line, " *"))
+  if (base::StartsWith(line, "/*", base::CompareCase::SENSITIVE) ||
+      base::StartsWith(line, " *", base::CompareCase::SENSITIVE))
     return false;  // C-style comment blocks with stars along the left side.
-  if (StartsWith(line, "#"))
+  if (base::StartsWith(line, "#", base::CompareCase::SENSITIVE))
     return false;  // Don't count preprocessor.
   if (base::ContainsOnlyChars(line, base::kWhitespaceASCII))
     return false;  // Don't count whitespace lines.
@@ -76,9 +71,11 @@
     return INCLUDE_NONE;
 
   base::StringPiece contents;
-  if (StartsWith(trimmed, base::StringPiece(kInclude, kIncludeLen)))
+  if (base::StartsWith(trimmed, base::StringPiece(kInclude, kIncludeLen),
+                       base::CompareCase::SENSITIVE))
     contents = TrimLeadingWhitespace(trimmed.substr(kIncludeLen));
-  else if (StartsWith(trimmed, base::StringPiece(kImport, kImportLen)))
+  else if (base::StartsWith(trimmed, base::StringPiece(kImport, kImportLen),
+                            base::CompareCase::SENSITIVE))
     contents = TrimLeadingWhitespace(trimmed.substr(kImportLen));
 
   if (contents.empty())
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 78eb00ef..4159044 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -530,11 +530,11 @@
     'tryserver.chromium.perf': {
       'android_perf_bisect_builder': 'gyp_official_goma_minimal_symbols_android',
       'android_arm64_perf_bisect_builder': 'gyp_official_goma_minimal_symbols_android_arm64',
-      'linux_perf_bisect_builder': 'gyp_official_goma',
+      'linux_perf_bisect_builder': 'gn_official_goma',
       'mac_perf_bisect_builder': 'gyp_official_goma',
       'win_perf_bisect_builder': 'gyp_official_goma_minimal_symbols_x86',
       'winx64_bisect_builder': 'gyp_official_goma_minimal_symbols_x64',
-      'linux_perf_bisect': 'gyp_official_goma',
+      'linux_perf_bisect': 'gn_official_goma',
       'mac_10_11_perf_bisect': 'gyp_official_goma',
       'mac_10_10_perf_bisect': 'gyp_official_goma',
       'mac_retina_perf_bisect': 'gyp_official_goma',
@@ -552,6 +552,9 @@
       'android_nexus6_perf_bisect': 'gyp_official_goma_minimal_symbols_android',
       'android_nexus7_perf_bisect': 'gyp_official_goma_minimal_symbols_android',
       'android_nexus9_perf_bisect': 'gyp_official_goma_minimal_symbols_android_arm64',
+      'linux_fyi_perf_bisect': 'gn_official_goma',
+      'mac_fyi_perf_bisect': 'gyp_official_goma',
+      'win_fyi_perf_bisect': 'gyp_official_goma_minimal_symbols_x86',
     },
     'tryserver.chromium.win': {
       'win_chromium_gn_x64_dbg': 'gn_debug_bot_minimal_symbols',
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 0de8014..f5ff69f 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -47690,6 +47690,18 @@
   </summary>
 </histogram>
 
+<histogram name="Sync.InitialState" enum="SyncInitialState">
+  <owner>maxbogue@chromium.org</owner>
+  <summary>
+    An approximate state of sync at startup. Logs a few reasons sync definitely
+    wouldn't be able to start, or that it probably can start. The user having
+    turned off sync on mobile will be logged as &quot;turned off by user&quot;.
+    A dashboard stop and clear will fall under &quot;turned off and setup not
+    completed&quot;. See the SyncInitialState enum in profile_sync_service.h for
+    more information.
+  </summary>
+</histogram>
+
 <histogram name="Sync.InvalidationSessionsAndroid" enum="BooleanHit">
   <owner>pkotwicz@chromium.org</owner>
   <summary>
@@ -68967,6 +68979,7 @@
 <enum name="MediaSessionActionSource" type="int">
   <int value="0" label="Media Notification"/>
   <int value="1" label="MediaSession (Android)"/>
+  <int value="2" label="Headset Unplugged"/>
 </enum>
 
 <enum name="MediaSessionSuspendedSource" type="int">
@@ -76855,6 +76868,15 @@
   <int value="3" label="Disabled"/>
 </enum>
 
+<enum name="SyncInitialState" type="int">
+  <int value="0" label="Can attempt to start"/>
+  <int value="1" label="No signed in user"/>
+  <int value="2" label="Turned off by user"/>
+  <int value="3" label="Turned off and setup not completed"/>
+  <int value="4" label="Must confirm sync settings"/>
+  <int value="5" label="Disallowed by enterprise policy"/>
+</enum>
+
 <enum name="SyncKeystoreDecryptionFailure" type="int">
   <int value="0" label="No keystore key"/>
   <int value="1" label="Unknown reason"/>
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index 03384a1..a790b1b 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -154,6 +154,10 @@
     path = os.path.join(BLINK_PERF_BASE_DIR, 'Bindings')
     return CreateStorySetFromPath(path, SKIPPED_FILE)
 
+  @classmethod
+  def ShouldDisable(cls, possible_browser):
+    return cls.IsSvelte(possible_browser)  # http://crbug.com/563979
+
 
 @benchmark.Enabled('content-shell')
 class BlinkPerfBlinkGC(perf_benchmark.PerfBenchmark):
diff --git a/tools/perf/benchmarks/power.py b/tools/perf/benchmarks/power.py
index dc5fbd9..677e082 100644
--- a/tools/perf/benchmarks/power.py
+++ b/tools/perf/benchmarks/power.py
@@ -68,6 +68,11 @@
   def Name(cls):
     return 'power.gpu_rasterization.typical_10_mobile'
 
+  @classmethod
+  def ShouldDisable(cls, possible_browser):
+    return cls.IsSvelte(possible_browser)  # http://crbug.com/563968
+
+
 @benchmark.Enabled('mac')
 class PowerTop10(perf_benchmark.PerfBenchmark):
   """Top 10 quiescent power test."""
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py
index 3987fa61..5be0ee8 100644
--- a/tools/perf/benchmarks/smoothness.py
+++ b/tools/perf/benchmarks/smoothness.py
@@ -125,6 +125,7 @@
     return 'smoothness.key_mobile_sites_smooth'
 
 
+@benchmark.Disabled('mac')  # crbug.com/563615
 class SmoothnessToughAnimationCases(_Smoothness):
   test = smoothness.SmoothnessWithRestart
   page_set = page_sets.ToughAnimationCasesPageSet
@@ -272,6 +273,10 @@
   def Name(cls):
     return 'smoothness.tough_pinch_zoom_cases'
 
+  @classmethod
+  def ShouldDisable(cls, possible_browser):
+    return cls.IsSvelte(possible_browser)  # http://crbug.com/564008
+
 
 @benchmark.Enabled('chromeos', 'mac')
 class SmoothnessDesktopToughPinchZoomCases(_Smoothness):
@@ -301,6 +306,10 @@
   def Name(cls):
     return 'smoothness.gpu_rasterization.tough_pinch_zoom_cases'
 
+  @classmethod
+  def ShouldDisable(cls, possible_browser):
+    return cls.IsSvelte(possible_browser)  # http://crbug.com/564008
+
 
 @benchmark.Enabled('chromeos', 'mac')
 class SmoothnessGpuRasterizationDesktopToughPinchZoomCases(_Smoothness):
@@ -407,6 +416,10 @@
   def Name(cls):
     return 'smoothness.image_decoding_cases'
 
+  @classmethod
+  def ShouldDisable(cls, possible_browser):
+    return cls.IsSvelte(possible_browser)  # http://crbug.com/563974
+
 
 @benchmark.Disabled('android')  # http://crbug.com/513699
 class SmoothnessGpuImageDecodingCases(_Smoothness):
diff --git a/tools/valgrind/drmemory/suppressions.txt b/tools/valgrind/drmemory/suppressions.txt
index 9d7acf7b..d1f1d269 100644
--- a/tools/valgrind/drmemory/suppressions.txt
+++ b/tools/valgrind/drmemory/suppressions.txt
@@ -740,14 +740,6 @@
 *!blink::SecurityOriginTest_Suborigins_Test::TestBody
 *!testing::internal::HandleExceptionsInMethodIfSupported<>
 
-UNADDRESSABLE ACCESS
-name=bug_554520
-*!gl::Program::release
-*!gl::State::reset
-*!gl::State::~State
-*!`anonymous namespace'::ValidationESTest_DrawElementsWithMaxIndexGivesError_Test::TestBody
-*!testing::internal::HandleExceptionsInMethodIfSupported<>
-
 HANDLE LEAK
 name=bug_555058_a
 system call NtCreateUserProcess
diff --git a/tools/valgrind/gtest_exclude/content_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/content_unittests.gtest-drmemory_win32.txt
index 570acc3..4cc5686 100644
--- a/tools/valgrind/gtest_exclude/content_unittests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/content_unittests.gtest-drmemory_win32.txt
@@ -4,10 +4,6 @@
 # http://crbug.com/391513
 GamepadServiceTest.ConnectionsTest
 
-# http://crbug.com/418748
-DownloadFile/DownloadFileTestWithRename.RenameWithErrorRetry/0
-DownloadFile/DownloadFileTestWithRename.RenameWithErrorRetry/1
-
 # http://crbug.com/522049
 RenderWidgetCompositorOutputSurfaceTest.SucceedTwice
 RenderWidgetCompositorOutputSurfaceTest.FallbackSuccessNormalSuccess
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index 412f4d79..c4beefd 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -158,6 +158,7 @@
   ]
   deps = [
     ":android",
+    ":ui_java",
     "//base",
     "//base/test:test_support",
     "//cc",
@@ -169,5 +170,4 @@
     "//ui/gfx",
     "//ui/resources:ui_test_pak",
   ]
-  apk_deps = [ ":ui_java" ]
 }
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index a17bc1116..a5d46e52 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -815,7 +815,7 @@
   }
 
   if (is_android) {
-    apk_deps = [
+    deps += [
       "//chrome:resources",
       "//ui/android:ui_java",
     ]
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index c70843d..d50f412 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -708,7 +708,7 @@
   }
 
   if (is_android) {
-    apk_deps = [ "//ui/android:ui_java" ]
+    deps += [ "//ui/android:ui_java" ]
 
     sources -= [
       # Do not run display_change_notifier_unittest.cc on Android because it
diff --git a/ui/gl/android/scoped_java_surface.cc b/ui/gl/android/scoped_java_surface.cc
index ae4f81a4..37118ae 100644
--- a/ui/gl/android/scoped_java_surface.cc
+++ b/ui/gl/android/scoped_java_surface.cc
@@ -48,12 +48,12 @@
   j_surface_.Reset(tmp);
 }
 
-ScopedJavaSurface::ScopedJavaSurface(RValue rvalue) {
-  MoveFrom(*rvalue.object);
+ScopedJavaSurface::ScopedJavaSurface(ScopedJavaSurface&& rvalue) {
+  MoveFrom(rvalue);
 }
 
-ScopedJavaSurface& ScopedJavaSurface::operator=(RValue rhs) {
-  MoveFrom(*rhs.object);
+ScopedJavaSurface& ScopedJavaSurface::operator=(ScopedJavaSurface&& rhs) {
+  MoveFrom(rhs);
   return *this;
 }
 
diff --git a/ui/gl/android/scoped_java_surface.h b/ui/gl/android/scoped_java_surface.h
index 641df64..c955cc2 100644
--- a/ui/gl/android/scoped_java_surface.h
+++ b/ui/gl/android/scoped_java_surface.h
@@ -19,7 +19,7 @@
 // When going out of scope, Surface.release() is called on the Java object to
 // make sure server-side references (esp. wrt graphics memory) are released.
 class GL_EXPORT ScopedJavaSurface {
-  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedJavaSurface, RValue);
+  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedJavaSurface);
 
  public:
   ScopedJavaSurface();
@@ -33,8 +33,8 @@
 
   // Move constructor. Take the surface from another ScopedJavaSurface object,
   // the latter no longer owns the surface afterwards.
-  ScopedJavaSurface(RValue rvalue);
-  ScopedJavaSurface& operator=(RValue rhs);
+  ScopedJavaSurface(ScopedJavaSurface&& rvalue);
+  ScopedJavaSurface& operator=(ScopedJavaSurface&& rhs);
 
   // Creates a ScopedJavaSurface that is owned externally, i.e.,
   // someone else is responsible to call Surface.release().
diff --git a/ui/gl/gl_bindings.h b/ui/gl/gl_bindings.h
index 453437a..b712d64 100644
--- a/ui/gl/gl_bindings.h
+++ b/ui/gl/gl_bindings.h
@@ -264,6 +264,12 @@
 #define GL_PATH_STENCIL_VALUE_MASK_CHROMIUM 0x90B9
 #endif
 
+#ifndef GL_EXT_multisample_compatibility
+#define GL_EXT_multisample_compatibility 1
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#endif /* GL_EXT_multisample_compatibility */
+
 #ifndef GL_KHR_blend_equation_advanced
 #define GL_KHR_blend_equation_advanced 1
 #define GL_COLORBURN_KHR                  0x929A
diff --git a/ui/gl/gl_enums_implementation_autogen.h b/ui/gl/gl_enums_implementation_autogen.h
index 967f67ab..a4812cb 100644
--- a/ui/gl/gl_enums_implementation_autogen.h
+++ b/ui/gl/gl_enums_implementation_autogen.h
@@ -403,7 +403,7 @@
         0x821A, "GL_DEPTH_STENCIL_ATTACHMENT",
     },
     {
-        0x8A40, "GL_UNIFORM_BLOCK_DATA_SIZE",
+        0x809D, "GL_MULTISAMPLE_EXT",
     },
     {
         0x821D, "GL_NUM_EXTENSIONS",
@@ -1843,6 +1843,9 @@
         0x8C1D, "GL_TEXTURE_BINDING_2D_ARRAY",
     },
     {
+        0x809F, "GL_SAMPLE_ALPHA_TO_ONE_EXT",
+    },
+    {
         0x8DDF, "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT",
     },
     {
@@ -2833,6 +2836,9 @@
         0x8051, "GL_RGB8_OES",
     },
     {
+        0x8A40, "GL_UNIFORM_BLOCK_DATA_SIZE",
+    },
+    {
         0x8CAD, "GL_DEPTH32F_STENCIL8",
     },
     {