Update from chromium a8e7c94b1b79a0948d05a1fcfff53391d22ce37a

Review URL: https://codereview.chromium.org/664803003
diff --git a/DEPS b/DEPS
index 6740daf..de6d2fe 100644
--- a/DEPS
+++ b/DEPS
@@ -30,16 +30,16 @@
   'skia_git': 'https://skia.googlesource.com',
   'boringssl_git': 'https://boringssl.googlesource.com',
   'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac',
-  'skia_revision': 'dd5a1e094c19fa10202c37c50a1f799e5af5dac0',
+  'skia_revision': '22b5ab644e0381e672c6fcf8aff26bf82ee71989',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and V8 without interference from each other.
   'v8_branch': 'trunk',
-  'v8_revision': '233fccf1872781e1f8ac2314511de15ca7a232ad', # from svn revision 24772
+  'v8_revision': 'b404893cc89fe7419e614abccb1fddf69d308abc', # from svn revision 24791
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  "angle_revision": "8e92923010c568a445c0f22e1a36f462fcabc8f3",
+  "angle_revision": "d2f756be4fd198d630b64dc6c3568184363e6d14",
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -79,7 +79,7 @@
    Var('chromium_git') + '/angle/angle.git' + '@' +  Var('angle_revision'),
 
   'src/third_party/icu':
-   Var('chromium_git') + '/chromium/deps/icu52.git' + '@' + '8ac906faf7b66180f2208380c35ae1e07136c5cc', # from svn revision 292317
+   Var('chromium_git') + '/chromium/deps/icu52.git' + '@' + 'd8b2a9d7b0039a4950ee008c5b1d998902c44c60', # from svn revision 292476
 
   'src/third_party/libc++/trunk':
    Var('chromium_git') + '/chromium/llvm-project/libcxx.git' + '@' +  Var('libcxx_revision'),
diff --git a/base/PRESUBMIT.py b/base/PRESUBMIT.py
index 758a790..4e9e64b 100644
--- a/base/PRESUBMIT.py
+++ b/base/PRESUBMIT.py
@@ -8,10 +8,6 @@
 for more details on the presubmit API built into gcl.
 """
 
-import re
-
-BASE_SOURCE_FILES=(r'^base/.*\.(cc|h|mm)$',)
-
 def _CheckNoInterfacesInBase(input_api, output_api):
   """Checks to make sure no files in libbase.a have |@interface|."""
   pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE)
@@ -40,45 +36,8 @@
   results.extend(_CheckNoInterfacesInBase(input_api, output_api))
   return results
 
-def _CheckOverrideFinal(input_api, output_api,
-                       whitelist=BASE_SOURCE_FILES, blacklist=None):
-  """Make sure new lines of code don't use the OVERRIDE or FINAL macros."""
-
-  # TODO(mostynb): remove this check once the macros are removed
-  # from base/compiler_specific.h.
-
-  errors = []
-
-  source_file_filter = lambda x: input_api.FilterSourceFile(
-    x, white_list=BASE_SOURCE_FILES, black_list=None)
-
-  override_files = []
-  final_files = []
-
-  for f in input_api.AffectedSourceFiles(source_file_filter):
-    contents = input_api.ReadFile(f, 'rb')
-
-    # "override" and "final" should be used instead of OVERRIDE/FINAL now.
-    if re.search(r"\bOVERRIDE\b", contents):
-      override_files.append(f.LocalPath())
-
-    if re.search(r"\bFINAL\b", contents):
-      final_files.append(f.LocalPath())
-
-  if override_files:
-    return [output_api.PresubmitError(
-      'These files use OVERRIDE instead of using override:',
-      items=override_files)]
-  if final_files:
-    return [output_api.PresubmitError(
-      'These files use FINAL instead of using final:',
-      items=final_files)]
-
-  return []
-
 def CheckChangeOnUpload(input_api, output_api):
   results = []
-  results.extend(_CheckOverrideFinal(input_api, output_api))
   results.extend(_CommonChecks(input_api, output_api))
   return results
 
@@ -92,12 +51,12 @@
 def GetPreferredTryMasters(project, change):
   return {
     'tryserver.chromium.linux': {
-      'linux_chromium_rel_swarming': set(['defaulttests']),
+      'linux_chromium_rel': set(['defaulttests']),
     },
     'tryserver.chromium.mac': {
-      'mac_chromium_rel_swarming': set(['defaulttests']),
+      'mac_chromium_rel': set(['defaulttests']),
     },
     'tryserver.chromium.win': {
-      'win_chromium_rel_swarming': set(['defaulttests']),
+      'win_chromium_rel': set(['defaulttests']),
     }
   }
diff --git a/base/basictypes.h b/base/basictypes.h
index 12d4c97..bf75e67 100644
--- a/base/basictypes.h
+++ b/base/basictypes.h
@@ -22,24 +22,11 @@
 typedef int8_t int8;
 typedef uint8_t uint8;
 typedef int16_t int16;
-typedef int32_t int32;
 typedef uint16_t uint16;
+typedef int32_t int32;
 typedef uint32_t uint32;
-
-// TODO(vtl): Figure what's up with the 64-bit types. Can we just define them as
-// |int64_t|/|uint64_t|?
-// The NSPR system headers define 64-bit as |long| when possible, except on
-// Mac OS X.  In order to not have typedef mismatches, we do the same on LP64.
-//
-// On Mac OS X, |long long| is used for 64-bit types for compatibility with
-// <inttypes.h> format macros even in the LP64 model.
-#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
-typedef long int64;
-typedef unsigned long uint64;
-#else
-typedef long long int64;
-typedef unsigned long long uint64;
-#endif
+typedef int64_t int64;
+typedef uint64_t uint64;
 
 // DEPRECATED: Please use std::numeric_limits (from <limits>) instead.
 const uint8  kuint8max  =  0xFF;
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index 6210d1a..47ca977 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -139,12 +139,6 @@
 #define ALIGNOF(type) __alignof__(type)
 #endif
 
-// Annotate a virtual method indicating it must be overriding a virtual
-// method in the parent class.
-// Use like:
-//   virtual void foo() OVERRIDE;
-#define OVERRIDE override
-
 // Annotate a function indicating the caller must examine the return value.
 // Use like:
 //   int foo() WARN_UNUSED_RESULT;
diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc
index fb5ba62..4078920 100644
--- a/base/files/file_path_watcher_linux.cc
+++ b/base/files/file_path_watcher_linux.cc
@@ -105,25 +105,25 @@
                          bool is_dir);
 
  protected:
-  virtual ~FilePathWatcherImpl() {}
+  ~FilePathWatcherImpl() override {}
 
  private:
   // Start watching |path| for changes and notify |delegate| on each change.
   // Returns true if watch for |path| has been added successfully.
-  virtual bool Watch(const FilePath& path,
-                     bool recursive,
-                     const FilePathWatcher::Callback& callback) override;
+  bool Watch(const FilePath& path,
+             bool recursive,
+             const FilePathWatcher::Callback& callback) override;
 
   // Cancel the watch. This unregisters the instance with InotifyReader.
-  virtual void Cancel() override;
+  void Cancel() override;
 
   // Cleans up and stops observing the message_loop() thread.
-  virtual void CancelOnMessageLoopThread() override;
+  void CancelOnMessageLoopThread() override;
 
   // Deletion of the FilePathWatcher will call Cancel() to dispose of this
   // object in the right thread. This also observes destruction of the required
   // cleanup thread, in case it quits before Cancel() is called.
-  virtual void WillDestroyCurrentMessageLoop() override;
+  void WillDestroyCurrentMessageLoop() override;
 
   // Inotify watches are installed for all directory components of |target_|. A
   // WatchEntry instance holds the watch descriptor for a component and the
diff --git a/base/i18n/icu_string_conversions_unittest.cc b/base/i18n/icu_string_conversions_unittest.cc
index 107e240..d4d3251 100644
--- a/base/i18n/icu_string_conversions_unittest.cc
+++ b/base/i18n/icu_string_conversions_unittest.cc
@@ -343,7 +343,8 @@
   {"foo-\xe4.html", "iso-8859-1", true, "foo-\xc3\xa4.html"},
   {"foo-\xe4.html", "iso-8859-7", true, "foo-\xce\xb4.html"},
   {"foo-\xe4.html", "foo-bar", false, ""},
-  {"foo-\xff.html", "ascii", false, ""},
+  // HTML Encoding spec treats US-ASCII as synonymous with windows-1252
+  {"foo-\xff.html", "ascii", true, "foo-\xc3\xbf.html"},
   {"foo.html", "ascii", true, "foo.html"},
   {"foo-a\xcc\x88.html", "utf-8", true, "foo-\xc3\xa4.html"},
   {"\x95\x32\x82\x36\xD2\xBB", "gb18030", true, "\xF0\xA0\x80\x80\xE4\xB8\x80"},
diff --git a/base/memory/scoped_ptr.h b/base/memory/scoped_ptr.h
index f3bbd12..ae9eb0f 100644
--- a/base/memory/scoped_ptr.h
+++ b/base/memory/scoped_ptr.h
@@ -73,16 +73,6 @@
 //
 //   scoped_ptr<Foo> foo(new Foo());
 //   scoped_ptr<FooParent> parent(foo.Pass());
-//
-// PassAs<>() should be used to upcast return value in return statement:
-//
-//   scoped_ptr<Foo> CreateFoo() {
-//     scoped_ptr<FooChild> result(new FooChild());
-//     return result.PassAs<Foo>();
-//   }
-//
-// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for
-// scoped_ptr<T[]>. This is because casting array pointers may not be safe.
 
 #ifndef BASE_MEMORY_SCOPED_PTR_H_
 #define BASE_MEMORY_SCOPED_PTR_H_
@@ -436,17 +426,6 @@
     return impl_.release();
   }
 
-  // C++98 doesn't support functions templates with default parameters which
-  // makes it hard to write a PassAs() that understands converting the deleter
-  // while preserving simple calling semantics.
-  //
-  // Until there is a use case for PassAs() with custom deleters, just ignore
-  // the custom deleter.
-  template <typename PassAsType>
-  scoped_ptr<PassAsType> PassAs() {
-    return scoped_ptr<PassAsType>(Pass());
-  }
-
  private:
   // Needed to reach into |impl_| in the constructor.
   template <typename U, typename V> friend class scoped_ptr;
diff --git a/base/memory/scoped_ptr_unittest.cc b/base/memory/scoped_ptr_unittest.cc
index 6af19b6..3f169a7 100644
--- a/base/memory/scoped_ptr_unittest.cc
+++ b/base/memory/scoped_ptr_unittest.cc
@@ -94,11 +94,6 @@
   return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed));
 }
 
-scoped_ptr<ConDecLoggerParent> UpcastUsingPassAs(
-    scoped_ptr<ConDecLogger> object) {
-  return object.PassAs<ConDecLoggerParent>();
-}
-
 }  // namespace
 
 TEST(ScopedPtrTest, ScopedPtr) {
@@ -462,22 +457,6 @@
   EXPECT_EQ(0, constructed);
 }
 
-TEST(ScopedPtrTest, PassAs) {
-  int constructed = 0;
-  {
-    scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
-    EXPECT_EQ(1, constructed);
-    EXPECT_TRUE(scoper.get());
-
-    scoped_ptr<ConDecLoggerParent> scoper_parent;
-    scoper_parent = UpcastUsingPassAs(scoper.Pass());
-    EXPECT_EQ(1, constructed);
-    EXPECT_TRUE(scoper_parent.get());
-    EXPECT_FALSE(scoper.get());
-  }
-  EXPECT_EQ(0, constructed);
-}
-
 TEST(ScopedPtrTest, CustomDeleter) {
   double dummy_value;  // Custom deleter never touches this value.
   int deletes = 0;
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h
index f6001e2..8a43392 100644
--- a/base/memory/weak_ptr.h
+++ b/base/memory/weak_ptr.h
@@ -48,17 +48,18 @@
 // ------------------------- IMPORTANT: Thread-safety -------------------------
 
 // Weak pointers may be passed safely between threads, but must always be
-// dereferenced and invalidated on the same thread otherwise checking the
-// pointer would be racey.
+// dereferenced and invalidated on the same SequencedTaskRunner otherwise
+// checking the pointer would be racey.
 //
 // To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory
 // is dereferenced, the factory and its WeakPtrs become bound to the calling
-// thread, and cannot be dereferenced or invalidated on any other thread. Bound
-// WeakPtrs can still be handed off to other threads, e.g. to use to post tasks
-// back to object on the bound thread.
+// thread or current SequencedWorkerPool token, and cannot be dereferenced or
+// invalidated on any other task runner. Bound WeakPtrs can still be handed
+// off to other task runners, e.g. to use to post tasks back to object on the
+// bound sequence.
 //
-// Invalidating the factory's WeakPtrs un-binds it from the thread, allowing it
-// to be passed for a different thread to use or delete it.
+// Invalidating the factory's WeakPtrs un-binds it from the sequence, allowing
+// it to be passed for a different sequence to use or delete it.
 
 #ifndef BASE_MEMORY_WEAK_PTR_H_
 #define BASE_MEMORY_WEAK_PTR_H_
@@ -81,8 +82,8 @@
 
 class BASE_EXPORT WeakReference {
  public:
-  // Although Flag is bound to a specific thread, it may be deleted from another
-  // via base::WeakPtr::~WeakPtr().
+  // Although Flag is bound to a specific SequencedTaskRunner, it may be
+  // deleted from another via base::WeakPtr::~WeakPtr().
   class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> {
    public:
     Flag();
diff --git a/base/message_loop/message_pump_glib.h b/base/message_loop/message_pump_glib.h
index 0f797c5..9f44571 100644
--- a/base/message_loop/message_pump_glib.h
+++ b/base/message_loop/message_pump_glib.h
@@ -22,7 +22,7 @@
 class BASE_EXPORT MessagePumpGlib : public MessagePump {
  public:
   MessagePumpGlib();
-  virtual ~MessagePumpGlib();
+  ~MessagePumpGlib() override;
 
   // Internal methods used for processing the pump callbacks.  They are
   // public for simplicity but should not be used directly.  HandlePrepare
@@ -35,10 +35,10 @@
   void HandleDispatch();
 
   // Overridden from MessagePump:
-  virtual void Run(Delegate* delegate) override;
-  virtual void Quit() override;
-  virtual void ScheduleWork() override;
-  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
+  void Run(Delegate* delegate) override;
+  void Quit() override;
+  void ScheduleWork() override;
+  void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
 
  private:
   bool ShouldQuit() const;
diff --git a/base/process/kill_posix.cc b/base/process/kill_posix.cc
index bff7be4..b02453c 100644
--- a/base/process/kill_posix.cc
+++ b/base/process/kill_posix.cc
@@ -415,7 +415,7 @@
   }
 
   // Overridden from PlatformThread::Delegate:
-  virtual void ThreadMain() override {
+  void ThreadMain() override {
     WaitForChildToDie();
     delete this;
   }
diff --git a/base/win/pe_image.h b/base/win/pe_image.h
index 878ef52..d93e99d 100644
--- a/base/win/pe_image.h
+++ b/base/win/pe_image.h
@@ -23,7 +23,7 @@
 namespace win {
 
 // This class is a wrapper for the Portable Executable File Format (PE).
-// It's main purpose is to provide an easy way to work with imports and exports
+// Its main purpose is to provide an easy way to work with imports and exports
 // from a file, mapped in memory as image.
 class PEImage {
  public:
@@ -84,6 +84,8 @@
     module_ = reinterpret_cast<HMODULE>(const_cast<void*>(module));
   }
 
+  virtual ~PEImage() {}
+
   // Gets the HMODULE for this object.
   HMODULE module() const;
 
diff --git a/build/android/buildbot/OWNERS b/build/android/buildbot/OWNERS
index 425f1d9..f289720 100644
--- a/build/android/buildbot/OWNERS
+++ b/build/android/buildbot/OWNERS
@@ -1,9 +1,6 @@
 set noparent
 
 cmp@chromium.org
-craigdh@chromium.org
-frankf@chromium.org
+jbudorick@chromium.org
 navabi@chromium.org
 
-# backup
-ilevy@chromium.org
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py
index 2eb3626..6d736a1 100755
--- a/build/android/buildbot/bb_device_status_check.py
+++ b/build/android/buildbot/bb_device_status_check.py
@@ -252,7 +252,7 @@
       try:
         if 'adb' in p.name:
           yield p
-      except (psutil.error.NoSuchProcess, psutil.error.AccessDenied):
+      except (psutil.NoSuchProcess, psutil.AccessDenied):
         pass
 
   for sig in [signal.SIGTERM, signal.SIGQUIT, signal.SIGKILL]:
@@ -261,12 +261,12 @@
         print 'kill %d %d (%s [%s])' % (sig, p.pid, p.name,
             ' '.join(p.cmdline))
         p.send_signal(sig)
-      except (psutil.error.NoSuchProcess, psutil.error.AccessDenied):
+      except (psutil.NoSuchProcess, psutil.AccessDenied):
         pass
   for p in GetAllAdb():
     try:
       print 'Unable to kill %d (%s [%s])' % (p.pid, p.name, ' '.join(p.cmdline))
-    except (psutil.error.NoSuchProcess, psutil.error.AccessDenied):
+    except (psutil.NoSuchProcess, psutil.AccessDenied):
       pass
 
 
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index c0f9fe7..e95a552 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -145,6 +145,9 @@
     args.append('--tool=asan')
   if options.gtest_filter:
     args.append('--gtest-filter=%s' % options.gtest_filter)
+  if options.flakiness_server:
+    args.append('--flakiness-dashboard-server=%s' %
+                options.flakiness_server)
 
   for suite in suites:
     bb_annotations.PrintNamedStep(suite)
@@ -186,7 +189,7 @@
   test = I('ChromeSyncShell',
            'ChromeSyncShell.apk',
            'org.chromium.chrome.browser.sync',
-           'ChromeSyncShellTest.apk',
+           'ChromeSyncShellTest',
            'chrome:chrome/test/data/android/device_files')
   RunInstrumentationSuite(options, test)
 
diff --git a/build/android/pylib/OWNERS b/build/android/pylib/OWNERS
index 3899fa3..dbbbba7 100644
--- a/build/android/pylib/OWNERS
+++ b/build/android/pylib/OWNERS
@@ -1,4 +1,4 @@
-frankf@chromium.org
 jbudorick@chromium.org
+klundberg@chromium.org
 navabi@chromium.org
 skyostil@chromium.org
diff --git a/build/android/pylib/base/test_dispatcher.py b/build/android/pylib/base/test_dispatcher.py
index cb789de..677a908 100644
--- a/build/android/pylib/base/test_dispatcher.py
+++ b/build/android/pylib/base/test_dispatcher.py
@@ -272,7 +272,6 @@
           #                 for the above are switched or wrapped.
           android_commands.errors.DeviceUnresponsiveError) as e:
     logging.error(e)
-    exit_code = constants.WARNING_EXIT_CODE
 
   if not all((len(tc) == 0 for tc in test_collections)):
     logging.error('Only ran %d tests (all devices are likely offline).' %
diff --git a/build/android/pylib/utils/json_results_generator.py b/build/android/pylib/utils/json_results_generator.py
index 52446b1..d40860d 100644
--- a/build/android/pylib/utils/json_results_generator.py
+++ b/build/android/pylib/utils/json_results_generator.py
@@ -516,7 +516,7 @@
       this_test = this_test[segment]
 
     if not len(this_test):
-      self._PopulateResutlsAndTimesJSON(this_test)
+      self._PopulateResultsAndTimesJSON(this_test)
 
     if self.RESULTS in this_test:
       self._InsertItemRunLengthEncoded(result, this_test[self.RESULTS])
@@ -558,7 +558,7 @@
 
     results[self.TESTS] = test_results_trie
 
-  def _PopulateResutlsAndTimesJSON(self, results_and_times):
+  def _PopulateResultsAndTimesJSON(self, results_and_times):
     results_and_times[self.RESULTS] = []
     results_and_times[self.TIMES] = []
     return results_and_times
diff --git a/build/android/pylib/utils/report_results.py b/build/android/pylib/utils/report_results.py
index b13b9bc..9841dc6 100644
--- a/build/android/pylib/utils/report_results.py
+++ b/build/android/pylib/utils/report_results.py
@@ -39,24 +39,28 @@
   logging.info('Upload results for test type "%s", test package "%s" to %s' %
                (test_type, test_package, flakiness_server))
 
-  # TODO(frankf): Enable uploading for gtests.
-  if test_type != 'Instrumentation':
-    logging.warning('Invalid test type.')
-    return
-
   try:
-    if flakiness_server == constants.UPSTREAM_FLAKINESS_SERVER:
-      assert test_package in ['ContentShellTest',
+    if test_type == 'Instrumentation':
+      if flakiness_server == constants.UPSTREAM_FLAKINESS_SERVER:
+        assert test_package in ['ContentShellTest',
                                 'ChromeShellTest',
-                              'AndroidWebViewTest']
-      dashboard_test_type = ('%s_instrumentation_tests' %
-                             test_package.lower().rstrip('test'))
-    # Downstream server.
+                                'AndroidWebViewTest']
+        dashboard_test_type = ('%s_instrumentation_tests' %
+                               test_package.lower().rstrip('test'))
+      # Downstream server.
+      else:
+        dashboard_test_type = 'Chromium_Android_Instrumentation'
+
+    elif test_type == 'Unit test':
+      dashboard_test_type = test_package
+
     else:
-      dashboard_test_type = 'Chromium_Android_Instrumentation'
+      logging.warning('Invalid test type')
+      return
 
     flakiness_dashboard_results_uploader.Upload(
         results, flakiness_server, dashboard_test_type)
+
   except Exception as e:
     logging.error(e)
 
diff --git a/build/common.gypi b/build/common.gypi
index 0ad62ee..8f9cb38 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -903,7 +903,7 @@
           'use_allocator%': 'none',
           # sysroot needs to be an absolute path otherwise it generates
           # incorrect results when passed to pkg-config
-          'sysroot%': '<!(cd <(DEPTH) && pwd -P)/arm-sysroot',
+          'sysroot%': '<!(cd <(DEPTH) && pwd -P)/chrome/installer/linux/debian_wheezy_arm-sysroot',
         }], # OS=="linux" and target_arch=="arm" and chromeos==0
 
         ['OS=="linux" and branding=="Chrome" and buildtype=="Official" and chromeos==0', {
diff --git a/build/go/rules.gni b/build/go/rules.gni
index 79453d1..ab703d6 100644
--- a/build/go/rules.gni
+++ b/build/go/rules.gni
@@ -53,8 +53,9 @@
       rebase_path("//", root_build_dir),
       "-I" + rebase_path("//"),
       " -L" + rebase_path(target_out_dir) +
+      " -L" + rebase_path(root_build_dir + "/obj/third_party/libevent") +
       " -l" + static_library_name +
-      " -lstdc++ -lpthread -lm -lglib-2.0",
+      " -lstdc++ -lpthread -lm -lglib-2.0 -levent",
       "test", "-c",
     ] + rebase_path(invoker.sources, build_dir)
   }
diff --git a/build/linux/install-arm-sysroot.py b/build/linux/install-arm-sysroot.py
index 4d593cc..495fc75 100755
--- a/build/linux/install-arm-sysroot.py
+++ b/build/linux/install-arm-sysroot.py
@@ -3,103 +3,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-"""Script to install ARM root image for cross building of ARM chrome on linux.
-This script can be run manually but is more often run as part of gclient
-hooks. When run from hooks this script should be a no-op on non-linux
-platforms.
-
-The sysroot image could be constructed from scratch based on the current
-state or precise/arm but for consistency we currently use a pre-built root
-image which was originally designed for building trusted NaCl code. The image
-will normally need to be rebuilt every time chrome's build dependancies are
-changed.
-
-Steps to rebuild the arm sysroot image:
-
-- cd $SRC/native_client
-- ./tools/trusted_cross_toolchains/trusted-toolchain-creator.armel.precise.sh \
-    UpdatePackageLists
-- ./tools/trusted_cross_toolchains/trusted-toolchain-creator.armel.precise.sh \
-    BuildJail $SRC/out/arm-sysroot.tar.gz
-- gsutil cp -a public-read $SRC/out/arm-sysroot.tar.gz \
-    nativeclient-archive2/toolchain/$NACL_REV/sysroot-arm-trusted.tgz
-"""
-
-# TODO(sbc): merge this script into:
-#  chrome/installer/linux/sysroot_scripts/install-debian.wheezy.sysroot.py
-
-import hashlib
-import os
-import shutil
-import subprocess
 import sys
 
-
-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
-URL_PREFIX = 'https://storage.googleapis.com'
-URL_PATH = 'chrome-linux-sysroot/toolchain'
-REVISION = 285950
-TARBALL = 'debian_wheezy_arm_sysroot.tgz'
-TARBALL_SHA1SUM = 'fc2f54db168887c5190c4c6686c869bedf668b4e'
-
-
-def get_sha1(filename):
-  sha1 = hashlib.sha1()
-  with open(filename, 'rb') as f:
-    while True:
-      # Read in 1mb chunks, so it doesn't all have to be loaded into memory.
-      chunk = f.read(1024*1024)
-      if not chunk:
-        break
-      sha1.update(chunk)
-  return sha1.hexdigest()
-
-
-def main(args):
-  if '--linux-only' in args:
-    # This argument is passed when run from the gclient hooks.
-    # In this case we return early on non-linux platforms
-    # or if GYP_DEFINES doesn't include target_arch=arm
-    if not sys.platform.startswith('linux'):
-      return 0
-
-    if "target_arch=arm" not in os.environ.get('GYP_DEFINES', ''):
-      return 0
-
-  src_root = os.path.dirname(os.path.dirname(SCRIPT_DIR))
-  sysroot = os.path.join(src_root, 'arm-sysroot')
-  url = "%s/%s/%s/%s" % (URL_PREFIX, URL_PATH, REVISION, TARBALL)
-
-  stamp = os.path.join(sysroot, ".stamp")
-  if os.path.exists(stamp):
-    with open(stamp) as s:
-      if s.read() == url:
-        print "ARM root image already up-to-date: %s" % sysroot
-        return 0
-
-  print "Installing ARM root image: %s" % sysroot
-  if os.path.isdir(sysroot):
-    shutil.rmtree(sysroot)
-  os.mkdir(sysroot)
-  tarball = os.path.join(sysroot, TARBALL)
-  curl = ['curl', '--fail', '-L', url, '-o', tarball]
-  if os.isatty(sys.stdout.fileno()):
-    curl.append('--progress')
-  else:
-    curl.append('--silent')
-  subprocess.check_call(curl)
-  sha1sum = get_sha1(tarball)
-  if sha1sum != TARBALL_SHA1SUM:
-    print 'Tarball sha1sum is wrong.'
-    print 'Expected %s, actual: %s' % (TARBALL_SHA1SUM, sha1sum)
-    return 1
-  subprocess.check_call(['tar', 'xf', tarball, '-C', sysroot])
-  os.remove(tarball)
-
-  with open(stamp, 'w') as s:
-    s.write(url)
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv[1:]))
+msg = '''\
+ERROR: This script has merged with install-debian.wheezy.sysroot.py.
+Please use that instead (with --arch=arm).
+'''
+sys.stderr.write(msg)
diff --git a/build/linux/install-chromeos-fonts.py b/build/linux/install-chromeos-fonts.py
index 98c3a57..a24adc9 100755
--- a/build/linux/install-chromeos-fonts.py
+++ b/build/linux/install-chromeos-fonts.py
@@ -12,16 +12,12 @@
 import subprocess
 import sys
 
-URL_PREFIX = 'https://commondatastorage.googleapis.com'
-URL_DIR = 'chromeos-localmirror/distfiles'
-URL_FILE = 'notofonts-20121206.tar.gz'
+# Taken from the media-fonts/notofonts ebuild in chromiumos-overlay.
+VERSION = '20140815'
+URL = ('https://commondatastorage.googleapis.com/chromeos-localmirror/'
+       'distfiles/notofonts-%s.tar.bz2') % (VERSION)
 FONTS_DIR = '/usr/local/share/fonts'
 
-# The URL matches the URL in the ebuild script in chromiumos. See:
-#  /path/to/chromiumos/src/
-#  third_party/chromiumos-overlay/media-fonts/notofonts/
-#  notofonts-20121206.ebuild
-
 def main(args):
   if not sys.platform.startswith('linux'):
     print "Error: %s must be run on Linux." % __file__
@@ -37,12 +33,10 @@
 
   dest_dir = os.path.join(FONTS_DIR, 'chromeos')
 
-  url = "%s/%s/%s" % (URL_PREFIX, URL_DIR, URL_FILE)
-
   stamp = os.path.join(dest_dir, ".stamp02")
   if os.path.exists(stamp):
     with open(stamp) as s:
-      if s.read() == url:
+      if s.read() == URL:
         print "Chrome OS fonts already up-to-date in %s." % dest_dir
         return 0
 
@@ -52,8 +46,8 @@
   os.chmod(dest_dir, 0755)
 
   print "Installing Chrome OS fonts to %s." % dest_dir
-  tarball = os.path.join(dest_dir, URL_FILE)
-  subprocess.check_call(['curl', '-L', url, '-o', tarball])
+  tarball = os.path.join(dest_dir, os.path.basename(URL))
+  subprocess.check_call(['curl', '-L', URL, '-o', tarball])
   subprocess.check_call(['tar', '--no-same-owner', '--no-same-permissions',
                          '-xf', tarball, '-C', dest_dir])
   os.remove(tarball)
@@ -65,7 +59,7 @@
     s.write("Script: %s\n" % __file__)
 
   with open(stamp, 'w') as s:
-    s.write(url)
+    s.write(URL)
 
   for base, dirs, files in os.walk(dest_dir):
     for dir in dirs:
diff --git a/build/whitespace_file.txt b/build/whitespace_file.txt
index 4e9bf38..f11fa16 100644
--- a/build/whitespace_file.txt
+++ b/build/whitespace_file.txt
@@ -141,3 +141,5 @@
 It was love at first sight.  The moment Yossarian first laid eyes on the chaplain, he fell madly in love with him.
 
 Cool whitespace change for git-cl land
+
+Oh god the bots are red! I'm blind! Mmmm, donuts.
diff --git a/cc/PRESUBMIT.py b/cc/PRESUBMIT.py
index 1aa48f3..46c3a54 100644
--- a/cc/PRESUBMIT.py
+++ b/cc/PRESUBMIT.py
@@ -191,12 +191,6 @@
         errors.append(output_api.PresubmitError(
           '%s:%d uses scoped_ptr<T>(). Use nullptr instead.' %
           (f.LocalPath(), line_number)))
-      # Disallow:
-      # foo.PassAs<T>();
-      if re.search(r'\bPassAs<.*?>\(\)', line):
-        errors.append(output_api.PresubmitError(
-          '%s:%d uses PassAs<T>(). Use Pass() instead.' %
-          (f.LocalPath(), line_number)))
   return errors
 
 def FindUnquotedQuote(contents, pos):
@@ -332,42 +326,6 @@
   else:
     return []
 
-def CheckOverrideFinal(input_api, output_api,
-                       whitelist=CC_SOURCE_FILES, blacklist=None):
-  """Make sure new lines of code don't use the OVERRIDE or FINAL macros."""
-
-  # TODO(mostynb): remove this check once the macros are removed
-  # from base/compiler_specific.h.
-
-  errors = []
-
-  source_file_filter = lambda x: input_api.FilterSourceFile(
-    x, white_list=CC_SOURCE_FILES, black_list=None)
-
-  override_files = []
-  final_files = []
-
-  for f in input_api.AffectedSourceFiles(source_file_filter):
-    contents = input_api.ReadFile(f, 'rb')
-
-    # "override" and "final" should be used instead of OVERRIDE/FINAL now.
-    if re.search(r"\bOVERRIDE\b", contents):
-      override_files.append(f.LocalPath())
-
-    if re.search(r"\bFINAL\b", contents):
-      final_files.append(f.LocalPath())
-
-  if override_files:
-    return [output_api.PresubmitError(
-      'These files use OVERRIDE instead of using override:',
-      items=override_files)]
-  if final_files:
-    return [output_api.PresubmitError(
-      'These files use FINAL instead of using final:',
-      items=final_files)]
-
-  return []
-
 def CheckChangeOnUpload(input_api, output_api):
   results = []
   results += CheckAsserts(input_api, output_api)
@@ -380,7 +338,6 @@
   results += CheckNamespace(input_api, output_api)
   results += CheckForUseOfWrongClock(input_api, output_api)
   results += FindUselessIfdefs(input_api, output_api)
-  results += CheckOverrideFinal(input_api, output_api)
   results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   return results
 
diff --git a/cc/debug/rasterize_and_record_benchmark_impl.cc b/cc/debug/rasterize_and_record_benchmark_impl.cc
index 77bc259..57e7f15 100644
--- a/cc/debug/rasterize_and_record_benchmark_impl.cc
+++ b/cc/debug/rasterize_and_record_benchmark_impl.cc
@@ -211,9 +211,10 @@
 
   FixedInvalidationPictureLayerTilingClient client(
       layer, gfx::Rect(layer->content_bounds()));
-  PictureLayerTilingSet tiling_set(&client, layer->content_bounds());
+  PictureLayerTilingSet tiling_set(&client);
 
-  PictureLayerTiling* tiling = tiling_set.AddTiling(layer->contents_scale_x());
+  PictureLayerTiling* tiling =
+      tiling_set.AddTiling(layer->contents_scale_x(), layer->bounds());
   tiling->CreateAllTilesForTesting();
   for (PictureLayerTiling::CoverageIterator it(
            tiling, layer->contents_scale_x(), layer->visible_content_rect());
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc
index e66cc76..3fb1c48 100644
--- a/cc/layers/delegated_renderer_layer_impl_unittest.cc
+++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -1416,7 +1416,12 @@
                                         pass1_id,
                                         gfx::Rect(layer_size),
                                         gfx::Transform());
-  AddRenderPassQuad(pass1, pass2, 0, FilterOperations(), transform);
+  AddRenderPassQuad(pass1,
+                    pass2,
+                    0,
+                    FilterOperations(),
+                    transform,
+                    SkXfermode::kSrcOver_Mode);
   delegated_renderer_layer_impl->SetFrameDataForRenderPasses(
       1.f, &delegated_render_passes);
 
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 4c16da7..2973519 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -625,6 +625,13 @@
   float scale = layer_tree_impl()->page_scale_factor();
 
   gfx::Vector2dF delta_from_scroll = scroll_clip_layer_->bounds_delta();
+
+  // In virtual-viewport mode, we don't need to compensate for pinch zoom or
+  // scale since the fixed container is the outer viewport, which sits below
+  // the page scale.
+  if (layer_tree_impl()->settings().use_pinch_virtual_viewport)
+    return delta_from_scroll;
+
   delta_from_scroll.Scale(1.f / scale);
 
   // The delta-from-pinch component requires some explanation: A viewport of
diff --git a/cc/layers/picture_image_layer_impl_unittest.cc b/cc/layers/picture_image_layer_impl_unittest.cc
index 2851392..6ae23a7 100644
--- a/cc/layers/picture_image_layer_impl_unittest.cc
+++ b/cc/layers/picture_image_layer_impl_unittest.cc
@@ -63,8 +63,7 @@
         new TestablePictureImageLayerImpl(tree, id);
     layer->SetBounds(gfx::Size(100, 200));
     layer->SetContentBounds(gfx::Size(100, 200));
-    layer->tilings_.reset(new PictureLayerTilingSet(&tiling_client_,
-                                                    layer->bounds()));
+    layer->tilings_.reset(new PictureLayerTilingSet(&tiling_client_));
     layer->pile_ = tiling_client_.GetPile();
     return make_scoped_ptr(layer);
   }
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index c0344e2..2599852 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -483,6 +483,9 @@
   was_screen_space_transform_animating_ =
       draw_properties().screen_space_transform_is_animating;
 
+  if (draw_transform_is_animating())
+    pile_->set_likely_to_be_used_for_transform_animation();
+
   should_update_tile_priorities_ = true;
 
   UpdateTilePriorities(occlusion_in_content_space);
@@ -790,7 +793,7 @@
     const PictureLayerTiling* tiling) {
   if (!CanHaveTilingWithScale(tiling->contents_scale()))
     return;
-  tilings_->AddTiling(tiling->contents_scale());
+  tilings_->AddTiling(tiling->contents_scale(), bounds());
 
   // If this tree needs update draw properties, then the tiling will
   // get updated prior to drawing or activation.  If this tree does not
@@ -840,7 +843,7 @@
   DCHECK(layer_tree_impl()->IsPendingTree());
 
   if (!tilings_)
-    tilings_.reset(new PictureLayerTilingSet(this, bounds()));
+    tilings_ = make_scoped_ptr(new PictureLayerTilingSet(this));
 
   DCHECK(!twin_layer_);
   twin_layer_ = static_cast<PictureLayerImpl*>(
@@ -861,7 +864,7 @@
   DCHECK(CanHaveTilingWithScale(contents_scale)) <<
       "contents_scale: " << contents_scale;
 
-  PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale);
+  PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale, bounds());
 
   DCHECK(pile_->HasRecordings());
 
@@ -1239,19 +1242,7 @@
 }
 
 bool PictureLayerImpl::ShouldAdjustRasterScaleDuringScaleAnimations() const {
-  if (!layer_tree_impl()->use_gpu_rasterization())
-    return false;
-
-  // Re-rastering text at different scales using GPU rasterization causes
-  // texture uploads for glyphs at each scale (see crbug.com/366225). To
-  // workaround this performance issue, we don't re-rasterize layers with
-  // text during scale animations.
-  // TODO(ajuma): Remove this workaround once text can be efficiently
-  // re-rastered at different scales (e.g. by using distance-field fonts).
-  if (pile_->has_text())
-    return false;
-
-  return true;
+  return layer_tree_impl()->use_gpu_rasterization();
 }
 
 float PictureLayerImpl::MaximumTilingContentsScale() const {
@@ -1450,7 +1441,7 @@
           PictureLayerTiling::TilingRasterTileIterator(tiling);
     }
 
-    if (tiling->resolution() == LOW_RESOLUTION) {
+    if (prioritize_low_res && tiling->resolution() == LOW_RESOLUTION) {
       iterators_[LOW_RES] =
           PictureLayerTiling::TilingRasterTileIterator(tiling);
     }
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 73906af..038dc2a 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -2194,16 +2194,20 @@
 
   SetupDrawPropertiesAndUpdateTiles(
       active_layer_, 0.5f, 0.5f, 0.5f, 0.5f, false);
+  pending_layer_->tilings()->RemoveAllTilings();
   active_layer_->tilings()->RemoveAllTilings();
-  PictureLayerTiling* tiling = active_layer_->tilings()->AddTiling(0.5f);
-  active_layer_->tilings()->AddTiling(1.5f);
-  active_layer_->tilings()->AddTiling(0.25f);
+  PictureLayerTiling* tiling = active_layer_->AddTiling(0.5f);
+  active_layer_->AddTiling(1.5f);
+  active_layer_->AddTiling(0.25f);
   tiling->set_resolution(HIGH_RESOLUTION);
 
   // Sanity checks.
   ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
   ASSERT_EQ(tiling, active_layer_->tilings()->TilingAtScale(0.5f));
 
+  pending_layer_->tilings()->RemoveAllTilings();
+  ASSERT_EQ(0u, pending_layer_->tilings()->num_tilings());
+
   // Now, set the bounds to be 1x1 (so that minimum contents scale becomes
   // 1.0f). Note that we should also ensure that the pending layer needs post
   // commit initialization, since this is what would happen during commit. In
@@ -2602,8 +2606,9 @@
   static_cast<FakePicturePileImpl*>(pending_layer_->pile())->set_has_text(true);
   static_cast<FakePicturePileImpl*>(active_layer_->pile())->set_has_text(true);
 
-  // Since we're GPU-rasterizing but have text, starting an animation should
-  // cause tiling resolution to get set to the maximum animation scale.
+  // When we're GPU-rasterizing, even if we have text, starting an animation
+  // should cause tiling resolution to get set to the content scale, since we
+  // render animating text at content scale using distance fields.
   animating_transform = true;
   contents_scale = 2.f;
   maximum_animation_scale = 3.f;
@@ -2613,10 +2618,10 @@
                                page_scale,
                                maximum_animation_scale,
                                animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
 
-  // Further changes to scale during the animation should not cause a new
-  // high-res tiling to get created.
+  // Further changes to scale during the animation should still cause a new
+  // high-res tiling to get created at content scale.
   contents_scale = 4.f;
   maximum_animation_scale = 5.f;
 
@@ -2625,7 +2630,7 @@
                                page_scale,
                                maximum_animation_scale,
                                animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
 
   // Once we stop animating, a new high-res tiling should be created.
   animating_transform = false;
@@ -2704,7 +2709,7 @@
 
   EXPECT_TRUE(reached_prepaint);
   EXPECT_EQ(0u, non_ideal_tile_count);
-  EXPECT_EQ(1u, low_res_tile_count);
+  EXPECT_EQ(0u, low_res_tile_count);
   EXPECT_EQ(16u, high_res_tile_count);
   EXPECT_EQ(low_res_tile_count + high_res_tile_count + non_ideal_tile_count,
             unique_tiles.size());
@@ -2761,8 +2766,7 @@
   non_ideal_tile_count = 0;
   low_res_tile_count = 0;
   high_res_tile_count = 0;
-  for (it = PictureLayerImpl::LayerRasterTileIterator(pending_layer_, false);
-       it;
+  for (it = PictureLayerImpl::LayerRasterTileIterator(pending_layer_, true); it;
        ++it) {
     Tile* tile = *it;
     TilePriority priority = tile->priority(PENDING_TREE);
@@ -3794,7 +3798,7 @@
     if (tile_is_visible)
       unoccluded_tile_count++;
   }
-  EXPECT_EQ(unoccluded_tile_count, 25 + 4);
+  EXPECT_EQ(unoccluded_tile_count, 25);
 
   // Partial occlusion.
   pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1));
@@ -3824,7 +3828,7 @@
     if (tile_is_visible)
       unoccluded_tile_count++;
   }
-  EXPECT_EQ(20 + 2, unoccluded_tile_count);
+  EXPECT_EQ(20, unoccluded_tile_count);
 
   // Full occlusion.
   layer1->SetPosition(gfx::Point(0, 0));
@@ -4490,6 +4494,65 @@
   EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
 }
 
+TEST_F(PictureLayerImplTest, ChangeInViewportAllowsTilingUpdates) {
+  base::TimeTicks time_ticks;
+  time_ticks += base::TimeDelta::FromMilliseconds(1);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+
+  gfx::Size tile_size(100, 100);
+  gfx::Size layer_bounds(400, 4000);
+
+  scoped_refptr<FakePicturePileImpl> pending_pile =
+      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+  scoped_refptr<FakePicturePileImpl> active_pile =
+      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+  SetupTrees(pending_pile, active_pile);
+
+  Region invalidation;
+  gfx::Rect viewport = gfx::Rect(0, 0, 100, 100);
+  gfx::Transform transform;
+
+  host_impl_.SetRequiresHighResToDraw();
+
+  // Update tiles.
+  pending_layer_->draw_properties().visible_content_rect = viewport;
+  pending_layer_->draw_properties().screen_space_transform = transform;
+  SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
+  pending_layer_->HighResTiling()->UpdateAllTilePrioritiesForTesting();
+
+  // Ensure we can't activate.
+  EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+
+  // Now in the same frame, move the viewport (this can happen during
+  // animation).
+  viewport = gfx::Rect(0, 2000, 100, 100);
+
+  // Update tiles.
+  pending_layer_->draw_properties().visible_content_rect = viewport;
+  pending_layer_->draw_properties().screen_space_transform = transform;
+  SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
+  pending_layer_->HighResTiling()->UpdateAllTilePrioritiesForTesting();
+
+  // Make sure all viewport tiles (viewport from the tiling) are ready to draw.
+  std::vector<Tile*> tiles;
+  for (PictureLayerTiling::CoverageIterator iter(
+           pending_layer_->HighResTiling(),
+           1.f,
+           pending_layer_->HighResTiling()->GetCurrentVisibleRectForTesting());
+       iter;
+       ++iter) {
+    if (*iter)
+      tiles.push_back(*iter);
+  }
+
+  host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
+
+  // Ensure we can activate.
+  EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+}
+
 class TileSizeSettings : public ImplSidePaintingSettings {
  public:
   TileSizeSettings() {
diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc
index 925cdc8..862ff1f 100644
--- a/cc/layers/tiled_layer_unittest.cc
+++ b/cc/layers/tiled_layer_unittest.cc
@@ -128,8 +128,7 @@
                                                   nullptr,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false);
+                                                  1);
     host_impl_ = make_scoped_ptr(
         new FakeLayerTreeHostImpl(proxy_, shared_bitmap_manager_.get()));
   }
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 6b15faf..24e9f30 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -123,6 +123,44 @@
   }
 }
 
+BlendMode BlendModeFromSkXfermode(SkXfermode::Mode mode) {
+  switch (mode) {
+    case SkXfermode::kSrcOver_Mode:
+      return BlendModeNormal;
+    case SkXfermode::kOverlay_Mode:
+      return BlendModeOverlay;
+    case SkXfermode::kDarken_Mode:
+      return BlendModeDarken;
+    case SkXfermode::kLighten_Mode:
+      return BlendModeLighten;
+    case SkXfermode::kColorDodge_Mode:
+      return BlendModeColorDodge;
+    case SkXfermode::kColorBurn_Mode:
+      return BlendModeColorBurn;
+    case SkXfermode::kHardLight_Mode:
+      return BlendModeHardLight;
+    case SkXfermode::kSoftLight_Mode:
+      return BlendModeSoftLight;
+    case SkXfermode::kDifference_Mode:
+      return BlendModeDifference;
+    case SkXfermode::kExclusion_Mode:
+      return BlendModeExclusion;
+    case SkXfermode::kMultiply_Mode:
+      return BlendModeMultiply;
+    case SkXfermode::kHue_Mode:
+      return BlendModeHue;
+    case SkXfermode::kSaturation_Mode:
+      return BlendModeSaturation;
+    case SkXfermode::kColor_Mode:
+      return BlendModeColor;
+    case SkXfermode::kLuminosity_Mode:
+      return BlendModeLuminosity;
+    default:
+      NOTREACHED();
+      return BlendModeNormal;
+  }
+}
+
 // Smallest unit that impact anti-aliasing output. We use this to
 // determine when anti-aliasing is unnecessary.
 const float kAntiAliasingEpsilon = 1.0f / 1024.0f;
@@ -723,140 +761,6 @@
     GLC(gl_, gl_->BlendEquation(GL_FUNC_ADD));
 }
 
-static skia::RefPtr<SkImage> ApplyBlendModeWithBackdrop(
-    scoped_ptr<GLRenderer::ScopedUseGrContext> use_gr_context,
-    ResourceProvider* resource_provider,
-    skia::RefPtr<SkImage> source_bitmap_with_filters,
-    ScopedResource* source_texture_resource,
-    ScopedResource* background_texture_resource,
-    SkXfermode::Mode blend_mode) {
-  if (!use_gr_context)
-    return source_bitmap_with_filters;
-
-  DCHECK(background_texture_resource);
-  DCHECK(source_texture_resource);
-
-  gfx::Size source_size = source_texture_resource->size();
-  gfx::Size background_size = background_texture_resource->size();
-
-  DCHECK_LE(background_size.width(), source_size.width());
-  DCHECK_LE(background_size.height(), source_size.height());
-
-  int source_texture_with_filters_id;
-  scoped_ptr<ResourceProvider::ScopedReadLockGL> lock;
-  if (source_bitmap_with_filters) {
-    DCHECK_EQ(source_size.width(), source_bitmap_with_filters->width());
-    DCHECK_EQ(source_size.height(), source_bitmap_with_filters->height());
-    GrTexture* texture =
-        reinterpret_cast<GrTexture*>(source_bitmap_with_filters->getTexture());
-    source_texture_with_filters_id = texture->getTextureHandle();
-  } else {
-    lock.reset(new ResourceProvider::ScopedReadLockGL(
-        resource_provider, source_texture_resource->id()));
-    source_texture_with_filters_id = lock->texture_id();
-  }
-
-  ResourceProvider::ScopedReadLockGL lock_background(
-      resource_provider, background_texture_resource->id());
-
-  // Wrap the source texture in a Ganesh platform texture.
-  GrBackendTextureDesc backend_texture_description;
-  backend_texture_description.fConfig = kSkia8888_GrPixelConfig;
-  backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin;
-
-  backend_texture_description.fWidth = source_size.width();
-  backend_texture_description.fHeight = source_size.height();
-  backend_texture_description.fTextureHandle = source_texture_with_filters_id;
-  skia::RefPtr<GrTexture> source_texture =
-      skia::AdoptRef(use_gr_context->context()->wrapBackendTexture(
-          backend_texture_description));
-  if (!source_texture) {
-    TRACE_EVENT_INSTANT0(
-        "cc",
-        "ApplyBlendModeWithBackdrop wrap source texture failed",
-        TRACE_EVENT_SCOPE_THREAD);
-    return skia::RefPtr<SkImage>();
-  }
-
-  backend_texture_description.fWidth = background_size.width();
-  backend_texture_description.fHeight = background_size.height();
-  backend_texture_description.fTextureHandle = lock_background.texture_id();
-  skia::RefPtr<GrTexture> background_texture =
-      skia::AdoptRef(use_gr_context->context()->wrapBackendTexture(
-          backend_texture_description));
-  if (!background_texture) {
-    TRACE_EVENT_INSTANT0(
-        "cc",
-        "ApplyBlendModeWithBackdrop wrap background texture failed",
-        TRACE_EVENT_SCOPE_THREAD);
-    return skia::RefPtr<SkImage>();
-  }
-
-  SkImageInfo source_info =
-      SkImageInfo::MakeN32Premul(source_size.width(), source_size.height());
-  // Place the platform texture inside an SkBitmap.
-  SkBitmap source;
-  source.setInfo(source_info);
-  skia::RefPtr<SkGrPixelRef> source_pixel_ref =
-      skia::AdoptRef(new SkGrPixelRef(source_info, source_texture.get()));
-  source.setPixelRef(source_pixel_ref.get());
-
-  SkImageInfo background_info = SkImageInfo::MakeN32Premul(
-      background_size.width(), background_size.height());
-
-  SkBitmap background;
-  background.setInfo(background_info);
-  skia::RefPtr<SkGrPixelRef> background_pixel_ref =
-      skia::AdoptRef(new SkGrPixelRef(
-          background_info, background_texture.get()));
-  background.setPixelRef(background_pixel_ref.get());
-
-  // Create a scratch texture for backing store.
-  GrTextureDesc desc;
-  desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
-  desc.fSampleCnt = 0;
-  desc.fWidth = source.width();
-  desc.fHeight = source.height();
-  desc.fConfig = kSkia8888_GrPixelConfig;
-  desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
-  skia::RefPtr<GrTexture> backing_store =
-      skia::AdoptRef(use_gr_context->context()->refScratchTexture(
-          desc, GrContext::kExact_ScratchTexMatch));
-  if (!backing_store) {
-    TRACE_EVENT_INSTANT0(
-        "cc",
-        "ApplyBlendModeWithBackdrop scratch texture allocation failed",
-        TRACE_EVENT_SCOPE_THREAD);
-    return source_bitmap_with_filters;
-  }
-
-  // Create a device and canvas using that backing store.
-  skia::RefPtr<SkSurface> surface = skia::AdoptRef(
-      SkSurface::NewRenderTargetDirect(backing_store->asRenderTarget()));
-  if (!surface)
-    return skia::RefPtr<SkImage>();
-  skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas());
-
-  // Draw the source bitmap through the filter to the canvas.
-  canvas->clear(SK_ColorTRANSPARENT);
-  canvas->drawSprite(background, 0, 0);
-  SkPaint paint;
-  paint.setXfermodeMode(blend_mode);
-  canvas->drawSprite(source, 0, 0, &paint);
-
-  skia::RefPtr<SkImage> image = skia::AdoptRef(surface->newImageSnapshot());
-  if (!image || !image->getTexture()) {
-    return skia::RefPtr<SkImage>();
-  }
-
-  // Flush the GrContext to ensure all buffered GL calls are drawn to the
-  // backing store before we access and return it, and have cc begin using the
-  // GL context again.
-  canvas->flush();
-
-  return image;
-}
-
 bool GLRenderer::ShouldApplyBackgroundFilters(DrawingFrame* frame,
                                               const RenderPassDrawQuad* quad) {
   if (quad->background_filters.IsEmpty())
@@ -878,7 +782,8 @@
 gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad(
     DrawingFrame* frame,
     const RenderPassDrawQuad* quad,
-    const gfx::Transform& contents_device_transform) {
+    const gfx::Transform& contents_device_transform,
+    bool use_aa) {
   gfx::Rect backdrop_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
       contents_device_transform, SharedGeometryQuad().BoundingBox()));
 
@@ -888,6 +793,11 @@
     backdrop_rect.Inset(-left, -top, -right, -bottom);
   }
 
+  if (!backdrop_rect.IsEmpty() && use_aa) {
+    const int kOutsetForAntialiasing = 1;
+    backdrop_rect.Inset(-kOutsetForAntialiasing, -kOutsetForAntialiasing);
+  }
+
   backdrop_rect.Intersect(
       MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect));
   return backdrop_rect;
@@ -932,7 +842,6 @@
     DrawingFrame* frame,
     const RenderPassDrawQuad* quad,
     const gfx::Transform& contents_device_transform_inverse,
-    ScopedResource* device_background_texture,
     skia::RefPtr<SkImage> filtered_device_background,
     const gfx::Rect& backdrop_bounding_rect) {
   // This method draws a background filter, which applies a filter to any pixels
@@ -959,18 +868,9 @@
   // TODO(danakj): When this algorithm changes, update
   // LayerTreeHost::PrioritizeTextures() accordingly.
 
-  DCHECK(device_background_texture);
+  DCHECK(filtered_device_background);
 
-  int filtered_device_background_texture_id = 0;
-  scoped_ptr<ResourceProvider::ScopedReadLockGL> lock;
-  if (filtered_device_background) {
-    GrTexture* texture = filtered_device_background->getTexture();
-    filtered_device_background_texture_id = texture->getTextureHandle();
-  } else {
-    lock.reset(new ResourceProvider::ScopedReadLockGL(
-        resource_provider_, device_background_texture->id()));
-    filtered_device_background_texture_id = lock->texture_id();
-  }
+  GrTexture* texture = filtered_device_background->getTexture();
 
   scoped_ptr<ScopedResource> background_texture =
       ScopedResource::Create(resource_provider_);
@@ -1004,7 +904,7 @@
     bool flip_vertically = false;
 
     CopyTextureToFramebuffer(frame,
-                             filtered_device_background_texture_id,
+                             texture->getTextureHandle(),
                              backdrop_bounding_rect,
                              device_to_framebuffer_transform,
                              flip_vertically);
@@ -1020,9 +920,9 @@
 void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
                                     const RenderPassDrawQuad* quad) {
   SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode;
-  SetBlendEnabled(quad->ShouldDrawWithBlending() ||
-                  (!IsDefaultBlendMode(blend_mode) &&
-                   CanApplyBlendModeUsingBlendFunc(blend_mode)));
+  SetBlendEnabled(
+      CanApplyBlendModeUsingBlendFunc(blend_mode) &&
+      (quad->ShouldDrawWithBlending() || !IsDefaultBlendMode(blend_mode)));
 
   ScopedResource* contents_texture =
       render_pass_textures_.get(quad->render_pass_id);
@@ -1041,44 +941,70 @@
   if (!contents_device_transform.GetInverse(&contents_device_transform_inverse))
     return;
 
+  bool clipped = false;
+  gfx::QuadF device_quad = MathUtil::MapQuad(
+      contents_device_transform, SharedGeometryQuad(), &clipped);
+  // Use anti-aliasing programs only when necessary.
+  bool use_aa =
+      !clipped &&
+      (settings_->force_antialiasing || !device_quad.IsRectilinear() ||
+       !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(),
+                                         kAntiAliasingEpsilon));
+
   bool need_background_texture = !CanApplyBlendModeUsingBlendFunc(blend_mode) ||
                                  ShouldApplyBackgroundFilters(frame, quad);
 
   scoped_ptr<ScopedResource> background_texture;
+  skia::RefPtr<SkImage> background_image;
+  gfx::Rect background_rect;
   if (need_background_texture) {
+    // Compute a bounding box around the pixels that will be visible through
+    // the quad.
+    background_rect = GetBackdropBoundingBoxForRenderPassQuad(
+        frame, quad, contents_device_transform, use_aa);
+  }
+
+  if (!background_rect.IsEmpty()) {
     // The pixels from the filtered background should completely replace the
     // current pixel values.
     bool disable_blending = blend_enabled();
     if (disable_blending)
       SetBlendEnabled(false);
 
-    // Compute a bounding box around the pixels that will be visible through
-    // the quad.
-    gfx::Rect backdrop_rect = GetBackdropBoundingBoxForRenderPassQuad(
-        frame, quad, contents_device_transform);
-
     // Read the pixels in the bounding box into a buffer R.
     scoped_ptr<ScopedResource> scoped_background_texture =
-        GetBackdropTexture(backdrop_rect);
+        GetBackdropTexture(background_rect);
 
     skia::RefPtr<SkImage> background_with_filters;
-    if (ShouldApplyBackgroundFilters(frame, quad)) {
+    if (ShouldApplyBackgroundFilters(frame, quad) &&
+        scoped_background_texture) {
       // Apply the background filters to R, so that it is applied in the pixels'
       // coordinate space.
       background_with_filters =
           ApplyBackgroundFilters(frame, quad, scoped_background_texture.get());
     }
-    // Apply the quad's inverse transform to map the pixels in R into the
-    // quad's content space. This implicitly clips R by the content bounds of
-    // the quad since the destination texture has bounds matching the quad's
-    // content.
-    background_texture = ApplyInverseTransformForBackgroundFilters(
-        frame,
-        quad,
-        contents_device_transform_inverse,
-        scoped_background_texture.get(),
-        background_with_filters,
-        backdrop_rect);
+
+    if (CanApplyBlendModeUsingBlendFunc(blend_mode) &&
+        background_with_filters) {
+      // The background with filters will be copied to the frame buffer.
+      // Apply the quad's inverse transform to map the pixels in R into the
+      // quad's content space. This implicitly clips R by the content bounds of
+      // the quad since the destination texture has bounds matching the quad's
+      // content.
+      background_texture = ApplyInverseTransformForBackgroundFilters(
+          frame,
+          quad,
+          contents_device_transform_inverse,
+          background_with_filters,
+          background_rect);
+    } else if (!CanApplyBlendModeUsingBlendFunc(blend_mode)) {
+      if (background_with_filters) {
+        // The background with filters will be used as backdrop for blending.
+        background_image = background_with_filters;
+      } else {
+        background_texture = scoped_background_texture.Pass();
+      }
+    }
 
     if (disable_blending)
       SetBlendEnabled(true);
@@ -1116,49 +1042,27 @@
     }
   }
 
-  if (background_texture) {
-    if (CanApplyBlendModeUsingBlendFunc(blend_mode)) {
-      // Draw the background texture if it has some filters applied.
-      DCHECK(ShouldApplyBackgroundFilters(frame, quad));
-      DCHECK(background_texture->size() == quad->rect.size());
-      ResourceProvider::ScopedReadLockGL lock(resource_provider_,
-                                              background_texture->id());
+  if (background_texture && ShouldApplyBackgroundFilters(frame, quad)) {
+    // Draw the background texture if it has some filters applied.
+    DCHECK(CanApplyBlendModeUsingBlendFunc(blend_mode));
+    DCHECK(background_texture->size() == quad->rect.size());
+    ResourceProvider::ScopedReadLockGL lock(resource_provider_,
+                                            background_texture->id());
 
-      // The background_texture is oriented the same as the frame buffer. The
-      // transform we are copying with has a vertical flip, so flip the contents
-      // in the shader to maintain orientation
-      bool flip_vertically = true;
+    // The background_texture is oriented the same as the frame buffer. The
+    // transform we are copying with has a vertical flip, so flip the contents
+    // in the shader to maintain orientation
+    bool flip_vertically = true;
 
-      CopyTextureToFramebuffer(frame,
-                               lock.texture_id(),
-                               quad->rect,
-                               quad->quadTransform(),
-                               flip_vertically);
-    } else {
-      // If blending is applied using shaders, the background texture with
-      // filters will be used as backdrop for blending operation, so we don't
-      // need to copy it to the frame buffer.
-      filter_image =
-          ApplyBlendModeWithBackdrop(ScopedUseGrContext::Create(this, frame),
-                                     resource_provider_,
-                                     filter_image,
-                                     contents_texture,
-                                     background_texture.get(),
-                                     quad->shared_quad_state->blend_mode);
-    }
+    CopyTextureToFramebuffer(frame,
+                             lock.texture_id(),
+                             quad->rect,
+                             quad->quadTransform(),
+                             flip_vertically);
   }
 
-  bool clipped = false;
-  gfx::QuadF device_quad = MathUtil::MapQuad(
-      contents_device_transform, SharedGeometryQuad(), &clipped);
   LayerQuad device_layer_bounds(gfx::QuadF(device_quad.BoundingBox()));
   LayerQuad device_layer_edges(device_quad);
-
-  // Use anti-aliasing programs only when necessary.
-  bool use_aa =
-      !clipped && (!device_quad.IsRectilinear() ||
-                   !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(),
-                                                     kAntiAliasingEpsilon));
   if (use_aa) {
     device_layer_bounds.InflateAntiAliasingDistance();
     device_layer_edges.InflateAntiAliasingDistance();
@@ -1210,10 +1114,17 @@
   int shader_color_matrix_location = -1;
   int shader_color_offset_location = -1;
   int shader_tex_transform_location = -1;
+  int shader_backdrop_location = -1;
+  int shader_backdrop_rect_location = -1;
+
+  BlendMode shader_blend_mode = ((background_texture || background_image) &&
+                                 !CanApplyBlendModeUsingBlendFunc(blend_mode))
+                                    ? BlendModeFromSkXfermode(blend_mode)
+                                    : BlendModeNormal;
 
   if (use_aa && mask_texture_id && !use_color_matrix) {
     const RenderPassMaskProgramAA* program =
-        GetRenderPassMaskProgramAA(tex_coord_precision);
+        GetRenderPassMaskProgramAA(tex_coord_precision, shader_blend_mode);
     SetUseProgram(program->program());
     GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
 
@@ -1230,9 +1141,12 @@
     shader_alpha_location = program->fragment_shader().alpha_location();
     shader_tex_transform_location =
         program->vertex_shader().tex_transform_location();
+    shader_backdrop_location = program->fragment_shader().backdrop_location();
+    shader_backdrop_rect_location =
+        program->fragment_shader().backdrop_rect_location();
   } else if (!use_aa && mask_texture_id && !use_color_matrix) {
     const RenderPassMaskProgram* program =
-        GetRenderPassMaskProgram(tex_coord_precision);
+        GetRenderPassMaskProgram(tex_coord_precision, shader_blend_mode);
     SetUseProgram(program->program());
     GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
 
@@ -1246,9 +1160,12 @@
     shader_alpha_location = program->fragment_shader().alpha_location();
     shader_tex_transform_location =
         program->vertex_shader().tex_transform_location();
+    shader_backdrop_location = program->fragment_shader().backdrop_location();
+    shader_backdrop_rect_location =
+        program->fragment_shader().backdrop_rect_location();
   } else if (use_aa && !mask_texture_id && !use_color_matrix) {
     const RenderPassProgramAA* program =
-        GetRenderPassProgramAA(tex_coord_precision);
+        GetRenderPassProgramAA(tex_coord_precision, shader_blend_mode);
     SetUseProgram(program->program());
     GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
 
@@ -1259,9 +1176,13 @@
     shader_alpha_location = program->fragment_shader().alpha_location();
     shader_tex_transform_location =
         program->vertex_shader().tex_transform_location();
+    shader_backdrop_location = program->fragment_shader().backdrop_location();
+    shader_backdrop_rect_location =
+        program->fragment_shader().backdrop_rect_location();
   } else if (use_aa && mask_texture_id && use_color_matrix) {
     const RenderPassMaskColorMatrixProgramAA* program =
-        GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision);
+        GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision,
+                                              shader_blend_mode);
     SetUseProgram(program->program());
     GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
 
@@ -1282,9 +1203,13 @@
         program->fragment_shader().color_matrix_location();
     shader_color_offset_location =
         program->fragment_shader().color_offset_location();
+    shader_backdrop_location = program->fragment_shader().backdrop_location();
+    shader_backdrop_rect_location =
+        program->fragment_shader().backdrop_rect_location();
   } else if (use_aa && !mask_texture_id && use_color_matrix) {
     const RenderPassColorMatrixProgramAA* program =
-        GetRenderPassColorMatrixProgramAA(tex_coord_precision);
+        GetRenderPassColorMatrixProgramAA(tex_coord_precision,
+                                          shader_blend_mode);
     SetUseProgram(program->program());
     GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
 
@@ -1299,9 +1224,13 @@
         program->fragment_shader().color_matrix_location();
     shader_color_offset_location =
         program->fragment_shader().color_offset_location();
+    shader_backdrop_location = program->fragment_shader().backdrop_location();
+    shader_backdrop_rect_location =
+        program->fragment_shader().backdrop_rect_location();
   } else if (!use_aa && mask_texture_id && use_color_matrix) {
     const RenderPassMaskColorMatrixProgram* program =
-        GetRenderPassMaskColorMatrixProgram(tex_coord_precision);
+        GetRenderPassMaskColorMatrixProgram(tex_coord_precision,
+                                            shader_blend_mode);
     SetUseProgram(program->program());
     GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
 
@@ -1319,9 +1248,12 @@
         program->fragment_shader().color_matrix_location();
     shader_color_offset_location =
         program->fragment_shader().color_offset_location();
+    shader_backdrop_location = program->fragment_shader().backdrop_location();
+    shader_backdrop_rect_location =
+        program->fragment_shader().backdrop_rect_location();
   } else if (!use_aa && !mask_texture_id && use_color_matrix) {
     const RenderPassColorMatrixProgram* program =
-        GetRenderPassColorMatrixProgram(tex_coord_precision);
+        GetRenderPassColorMatrixProgram(tex_coord_precision, shader_blend_mode);
     SetUseProgram(program->program());
     GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
 
@@ -1333,9 +1265,12 @@
         program->fragment_shader().color_matrix_location();
     shader_color_offset_location =
         program->fragment_shader().color_offset_location();
+    shader_backdrop_location = program->fragment_shader().backdrop_location();
+    shader_backdrop_rect_location =
+        program->fragment_shader().backdrop_rect_location();
   } else {
     const RenderPassProgram* program =
-        GetRenderPassProgram(tex_coord_precision);
+        GetRenderPassProgram(tex_coord_precision, shader_blend_mode);
     SetUseProgram(program->program());
     GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
 
@@ -1343,6 +1278,9 @@
     shader_alpha_location = program->fragment_shader().alpha_location();
     shader_tex_transform_location =
         program->vertex_shader().tex_transform_location();
+    shader_backdrop_location = program->fragment_shader().backdrop_location();
+    shader_backdrop_rect_location =
+        program->fragment_shader().backdrop_rect_location();
   }
   float tex_scale_x =
       quad->rect.width() / static_cast<float>(contents_texture->size().width());
@@ -1362,6 +1300,7 @@
                      tex_scale_x,
                      -tex_scale_y));
 
+  GLint last_texture_unit = 0;
   scoped_ptr<ResourceProvider::ScopedSamplerGL> shader_mask_sampler_lock;
   if (shader_mask_sampler_location != -1) {
     DCHECK_NE(shader_mask_tex_coord_scale_location, 1);
@@ -1382,6 +1321,8 @@
         gl_->Uniform2f(shader_mask_tex_coord_scale_location,
                        mask_uv_rect.width() / tex_scale_x,
                        -mask_uv_rect.height() / tex_scale_y));
+
+    last_texture_unit = 1;
   }
 
   if (shader_edge_location != -1) {
@@ -1417,6 +1358,37 @@
     GLC(gl_, gl_->Uniform4fv(shader_color_offset_location, 1, offset));
   }
 
+  scoped_ptr<ResourceProvider::ScopedSamplerGL> shader_background_sampler_lock;
+  if (shader_backdrop_location != -1) {
+    DCHECK(background_texture || background_image);
+    DCHECK_NE(shader_backdrop_location, 0);
+    DCHECK_NE(shader_backdrop_rect_location, 0);
+
+    GLC(gl_, gl_->Uniform1i(shader_backdrop_location, ++last_texture_unit));
+
+    GLC(gl_,
+        gl_->Uniform4f(shader_backdrop_rect_location,
+                       background_rect.x(),
+                       background_rect.y(),
+                       background_rect.width(),
+                       background_rect.height()));
+
+    if (background_image) {
+      GrTexture* texture = background_image->getTexture();
+      GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0 + last_texture_unit));
+      gl_->BindTexture(GL_TEXTURE_2D, texture->getTextureHandle());
+      GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
+    } else {
+      shader_background_sampler_lock = make_scoped_ptr(
+          new ResourceProvider::ScopedSamplerGL(resource_provider_,
+                                                background_texture->id(),
+                                                GL_TEXTURE0 + last_texture_unit,
+                                                GL_LINEAR));
+      DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
+                shader_background_sampler_lock->target());
+    }
+  }
+
   // Map device space quad to surface space. contents_device_transform has no 3d
   // component since it was flattened, so we don't need to project.
   gfx::QuadF surface_quad = MathUtil::MapQuad(contents_device_transform_inverse,
@@ -2352,7 +2324,8 @@
   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
       gl_, &highp_threshold_cache_, highp_threshold_min_, rect.bottom_right());
 
-  const RenderPassProgram* program = GetRenderPassProgram(tex_coord_precision);
+  const RenderPassProgram* program =
+      GetRenderPassProgram(tex_coord_precision, BlendModeNormal);
   SetUseProgram(program->program());
 
   GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
@@ -2831,112 +2804,155 @@
 }
 
 const GLRenderer::RenderPassProgram* GLRenderer::GetRenderPassProgram(
-    TexCoordPrecision precision) {
+    TexCoordPrecision precision,
+    BlendMode blend_mode) {
   DCHECK_GE(precision, 0);
   DCHECK_LT(precision, NumTexCoordPrecisions);
-  RenderPassProgram* program = &render_pass_program_[precision];
+  DCHECK_GE(blend_mode, 0);
+  DCHECK_LT(blend_mode, NumBlendModes);
+  RenderPassProgram* program = &render_pass_program_[precision][blend_mode];
   if (!program->initialized()) {
     TRACE_EVENT0("cc", "GLRenderer::renderPassProgram::initialize");
-    program->Initialize(
-        output_surface_->context_provider(), precision, SamplerType2D);
+    program->Initialize(output_surface_->context_provider(),
+                        precision,
+                        SamplerType2D,
+                        blend_mode);
   }
   return program;
 }
 
 const GLRenderer::RenderPassProgramAA* GLRenderer::GetRenderPassProgramAA(
-    TexCoordPrecision precision) {
+    TexCoordPrecision precision,
+    BlendMode blend_mode) {
   DCHECK_GE(precision, 0);
   DCHECK_LT(precision, NumTexCoordPrecisions);
-  RenderPassProgramAA* program = &render_pass_program_aa_[precision];
+  DCHECK_GE(blend_mode, 0);
+  DCHECK_LT(blend_mode, NumBlendModes);
+  RenderPassProgramAA* program =
+      &render_pass_program_aa_[precision][blend_mode];
   if (!program->initialized()) {
     TRACE_EVENT0("cc", "GLRenderer::renderPassProgramAA::initialize");
-    program->Initialize(
-        output_surface_->context_provider(), precision, SamplerType2D);
+    program->Initialize(output_surface_->context_provider(),
+                        precision,
+                        SamplerType2D,
+                        blend_mode);
   }
   return program;
 }
 
 const GLRenderer::RenderPassMaskProgram* GLRenderer::GetRenderPassMaskProgram(
-    TexCoordPrecision precision) {
+    TexCoordPrecision precision,
+    BlendMode blend_mode) {
   DCHECK_GE(precision, 0);
   DCHECK_LT(precision, NumTexCoordPrecisions);
-  RenderPassMaskProgram* program = &render_pass_mask_program_[precision];
+  DCHECK_GE(blend_mode, 0);
+  DCHECK_LT(blend_mode, NumBlendModes);
+  RenderPassMaskProgram* program =
+      &render_pass_mask_program_[precision][blend_mode];
   if (!program->initialized()) {
     TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize");
-    program->Initialize(
-        output_surface_->context_provider(), precision, SamplerType2D);
+    program->Initialize(output_surface_->context_provider(),
+                        precision,
+                        SamplerType2D,
+                        blend_mode);
   }
   return program;
 }
 
 const GLRenderer::RenderPassMaskProgramAA*
-GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision) {
+GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision,
+                                       BlendMode blend_mode) {
   DCHECK_GE(precision, 0);
   DCHECK_LT(precision, NumTexCoordPrecisions);
-  RenderPassMaskProgramAA* program = &render_pass_mask_program_aa_[precision];
+  DCHECK_GE(blend_mode, 0);
+  DCHECK_LT(blend_mode, NumBlendModes);
+  RenderPassMaskProgramAA* program =
+      &render_pass_mask_program_aa_[precision][blend_mode];
   if (!program->initialized()) {
     TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize");
-    program->Initialize(
-        output_surface_->context_provider(), precision, SamplerType2D);
+    program->Initialize(output_surface_->context_provider(),
+                        precision,
+                        SamplerType2D,
+                        blend_mode);
   }
   return program;
 }
 
 const GLRenderer::RenderPassColorMatrixProgram*
-GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision) {
+GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision,
+                                            BlendMode blend_mode) {
   DCHECK_GE(precision, 0);
   DCHECK_LT(precision, NumTexCoordPrecisions);
+  DCHECK_GE(blend_mode, 0);
+  DCHECK_LT(blend_mode, NumBlendModes);
   RenderPassColorMatrixProgram* program =
-      &render_pass_color_matrix_program_[precision];
+      &render_pass_color_matrix_program_[precision][blend_mode];
   if (!program->initialized()) {
     TRACE_EVENT0("cc", "GLRenderer::renderPassColorMatrixProgram::initialize");
-    program->Initialize(
-        output_surface_->context_provider(), precision, SamplerType2D);
+    program->Initialize(output_surface_->context_provider(),
+                        precision,
+                        SamplerType2D,
+                        blend_mode);
   }
   return program;
 }
 
 const GLRenderer::RenderPassColorMatrixProgramAA*
-GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision) {
+GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision,
+                                              BlendMode blend_mode) {
   DCHECK_GE(precision, 0);
   DCHECK_LT(precision, NumTexCoordPrecisions);
+  DCHECK_GE(blend_mode, 0);
+  DCHECK_LT(blend_mode, NumBlendModes);
   RenderPassColorMatrixProgramAA* program =
-      &render_pass_color_matrix_program_aa_[precision];
+      &render_pass_color_matrix_program_aa_[precision][blend_mode];
   if (!program->initialized()) {
     TRACE_EVENT0("cc",
                  "GLRenderer::renderPassColorMatrixProgramAA::initialize");
-    program->Initialize(
-        output_surface_->context_provider(), precision, SamplerType2D);
+    program->Initialize(output_surface_->context_provider(),
+                        precision,
+                        SamplerType2D,
+                        blend_mode);
   }
   return program;
 }
 
 const GLRenderer::RenderPassMaskColorMatrixProgram*
-GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision) {
+GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision,
+                                                BlendMode blend_mode) {
   DCHECK_GE(precision, 0);
   DCHECK_LT(precision, NumTexCoordPrecisions);
+  DCHECK_GE(blend_mode, 0);
+  DCHECK_LT(blend_mode, NumBlendModes);
   RenderPassMaskColorMatrixProgram* program =
-      &render_pass_mask_color_matrix_program_[precision];
+      &render_pass_mask_color_matrix_program_[precision][blend_mode];
   if (!program->initialized()) {
     TRACE_EVENT0("cc",
                  "GLRenderer::renderPassMaskColorMatrixProgram::initialize");
-    program->Initialize(
-        output_surface_->context_provider(), precision, SamplerType2D);
+    program->Initialize(output_surface_->context_provider(),
+                        precision,
+                        SamplerType2D,
+                        blend_mode);
   }
   return program;
 }
 
 const GLRenderer::RenderPassMaskColorMatrixProgramAA*
-GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision) {
+GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision,
+                                                  BlendMode blend_mode) {
   DCHECK_GE(precision, 0);
   DCHECK_LT(precision, NumTexCoordPrecisions);
+  DCHECK_GE(blend_mode, 0);
+  DCHECK_LT(blend_mode, NumBlendModes);
   RenderPassMaskColorMatrixProgramAA* program =
-      &render_pass_mask_color_matrix_program_aa_[precision];
+      &render_pass_mask_color_matrix_program_aa_[precision][blend_mode];
   if (!program->initialized()) {
     TRACE_EVENT0("cc",
                  "GLRenderer::renderPassMaskColorMatrixProgramAA::initialize");
-    program->Initialize(
-        output_surface_->context_provider(), precision, SamplerType2D);
+    program->Initialize(output_surface_->context_provider(),
+                        precision,
+                        SamplerType2D,
+                        blend_mode);
   }
   return program;
 }
@@ -3162,15 +3178,16 @@
       tile_program_aa_[i][j].Cleanup(gl_);
       tile_program_swizzle_aa_[i][j].Cleanup(gl_);
     }
-
-    render_pass_mask_program_[i].Cleanup(gl_);
-    render_pass_program_[i].Cleanup(gl_);
-    render_pass_mask_program_aa_[i].Cleanup(gl_);
-    render_pass_program_aa_[i].Cleanup(gl_);
-    render_pass_color_matrix_program_[i].Cleanup(gl_);
-    render_pass_mask_color_matrix_program_aa_[i].Cleanup(gl_);
-    render_pass_color_matrix_program_aa_[i].Cleanup(gl_);
-    render_pass_mask_color_matrix_program_[i].Cleanup(gl_);
+    for (int j = 0; j < NumBlendModes; j++) {
+      render_pass_mask_program_[i][j].Cleanup(gl_);
+      render_pass_program_[i][j].Cleanup(gl_);
+      render_pass_mask_program_aa_[i][j].Cleanup(gl_);
+      render_pass_program_aa_[i][j].Cleanup(gl_);
+      render_pass_color_matrix_program_[i][j].Cleanup(gl_);
+      render_pass_mask_color_matrix_program_aa_[i][j].Cleanup(gl_);
+      render_pass_color_matrix_program_aa_[i][j].Cleanup(gl_);
+      render_pass_mask_color_matrix_program_[i][j].Cleanup(gl_);
+    }
 
     texture_program_[i].Cleanup(gl_);
     nonpremultiplied_texture_program_[i].Cleanup(gl_);
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index a379dc0..676e7b7 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -153,7 +153,8 @@
   gfx::Rect GetBackdropBoundingBoxForRenderPassQuad(
       DrawingFrame* frame,
       const RenderPassDrawQuad* quad,
-      const gfx::Transform& contents_device_transform);
+      const gfx::Transform& contents_device_transform,
+      bool use_aa);
   scoped_ptr<ScopedResource> GetBackdropTexture(const gfx::Rect& bounding_rect);
 
   static bool ShouldApplyBackgroundFilters(DrawingFrame* frame,
@@ -166,7 +167,6 @@
       DrawingFrame* frame,
       const RenderPassDrawQuad* quad,
       const gfx::Transform& contents_device_transform_inverse,
-      ScopedResource* background_texture,
       skia::RefPtr<SkImage> backdrop_bitmap,
       const gfx::Rect& backdrop_bounding_rect);
 
@@ -328,22 +328,28 @@
 
   const TileCheckerboardProgram* GetTileCheckerboardProgram();
 
-  const RenderPassProgram* GetRenderPassProgram(
-      TexCoordPrecision precision);
-  const RenderPassProgramAA* GetRenderPassProgramAA(
-      TexCoordPrecision precision);
+  const RenderPassProgram* GetRenderPassProgram(TexCoordPrecision precision,
+                                                BlendMode blend_mode);
+  const RenderPassProgramAA* GetRenderPassProgramAA(TexCoordPrecision precision,
+                                                    BlendMode blend_mode);
   const RenderPassMaskProgram* GetRenderPassMaskProgram(
-      TexCoordPrecision precision);
+      TexCoordPrecision precision,
+      BlendMode blend_mode);
   const RenderPassMaskProgramAA* GetRenderPassMaskProgramAA(
-      TexCoordPrecision precision);
+      TexCoordPrecision precision,
+      BlendMode blend_mode);
   const RenderPassColorMatrixProgram* GetRenderPassColorMatrixProgram(
-      TexCoordPrecision precision);
+      TexCoordPrecision precision,
+      BlendMode blend_mode);
   const RenderPassColorMatrixProgramAA* GetRenderPassColorMatrixProgramAA(
-      TexCoordPrecision precision);
+      TexCoordPrecision precision,
+      BlendMode blend_mode);
   const RenderPassMaskColorMatrixProgram* GetRenderPassMaskColorMatrixProgram(
-      TexCoordPrecision precision);
+      TexCoordPrecision precision,
+      BlendMode blend_mode);
   const RenderPassMaskColorMatrixProgramAA*
-      GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision);
+  GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision,
+                                        BlendMode blend_mode);
 
   const TextureProgram* GetTextureProgram(
       TexCoordPrecision precision);
@@ -388,18 +394,21 @@
       nonpremultiplied_texture_background_program_[NumTexCoordPrecisions];
   TextureProgram texture_io_surface_program_[NumTexCoordPrecisions];
 
-  RenderPassProgram render_pass_program_[NumTexCoordPrecisions];
-  RenderPassProgramAA render_pass_program_aa_[NumTexCoordPrecisions];
-  RenderPassMaskProgram render_pass_mask_program_[NumTexCoordPrecisions];
-  RenderPassMaskProgramAA render_pass_mask_program_aa_[NumTexCoordPrecisions];
+  RenderPassProgram render_pass_program_[NumTexCoordPrecisions][NumBlendModes];
+  RenderPassProgramAA
+      render_pass_program_aa_[NumTexCoordPrecisions][NumBlendModes];
+  RenderPassMaskProgram
+      render_pass_mask_program_[NumTexCoordPrecisions][NumBlendModes];
+  RenderPassMaskProgramAA
+      render_pass_mask_program_aa_[NumTexCoordPrecisions][NumBlendModes];
   RenderPassColorMatrixProgram
-      render_pass_color_matrix_program_[NumTexCoordPrecisions];
-  RenderPassColorMatrixProgramAA
-      render_pass_color_matrix_program_aa_[NumTexCoordPrecisions];
-  RenderPassMaskColorMatrixProgram
-      render_pass_mask_color_matrix_program_[NumTexCoordPrecisions];
-  RenderPassMaskColorMatrixProgramAA
-      render_pass_mask_color_matrix_program_aa_[NumTexCoordPrecisions];
+      render_pass_color_matrix_program_[NumTexCoordPrecisions][NumBlendModes];
+  RenderPassColorMatrixProgramAA render_pass_color_matrix_program_aa_
+      [NumTexCoordPrecisions][NumBlendModes];
+  RenderPassMaskColorMatrixProgram render_pass_mask_color_matrix_program_
+      [NumTexCoordPrecisions][NumBlendModes];
+  RenderPassMaskColorMatrixProgramAA render_pass_mask_color_matrix_program_aa_
+      [NumTexCoordPrecisions][NumBlendModes];
 
   VideoYUVProgram video_yuv_program_[NumTexCoordPrecisions];
   VideoYUVAProgram video_yuva_program_[NumTexCoordPrecisions];
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 42e4b5e..8de90c4 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -55,6 +55,44 @@
     EXPECT_TRUE((program_binding)->initialized()); \
   } while (false)
 
+static inline SkXfermode::Mode BlendModeToSkXfermode(BlendMode blend_mode) {
+  switch (blend_mode) {
+    case BlendModeNormal:
+      return SkXfermode::kSrcOver_Mode;
+    case BlendModeOverlay:
+      return SkXfermode::kOverlay_Mode;
+    case BlendModeDarken:
+      return SkXfermode::kDarken_Mode;
+    case BlendModeLighten:
+      return SkXfermode::kLighten_Mode;
+    case BlendModeColorDodge:
+      return SkXfermode::kColorDodge_Mode;
+    case BlendModeColorBurn:
+      return SkXfermode::kColorBurn_Mode;
+    case BlendModeHardLight:
+      return SkXfermode::kHardLight_Mode;
+    case BlendModeSoftLight:
+      return SkXfermode::kSoftLight_Mode;
+    case BlendModeDifference:
+      return SkXfermode::kDifference_Mode;
+    case BlendModeExclusion:
+      return SkXfermode::kExclusion_Mode;
+    case BlendModeMultiply:
+      return SkXfermode::kMultiply_Mode;
+    case BlendModeHue:
+      return SkXfermode::kHue_Mode;
+    case BlendModeSaturation:
+      return SkXfermode::kSaturation_Mode;
+    case BlendModeColor:
+      return SkXfermode::kColor_Mode;
+    case BlendModeLuminosity:
+      return SkXfermode::kLuminosity_Mode;
+    case NumBlendModes:
+      NOTREACHED();
+  }
+  return SkXfermode::kSrcOver_Mode;
+}
+
 // Explicitly named to be a friend in GLRenderer for shader access.
 class GLRendererShaderPixelTest : public GLRendererPixelTest {
  public:
@@ -70,18 +108,25 @@
   }
 
   void TestShadersWithTexCoordPrecision(TexCoordPrecision precision) {
-    EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgram(precision));
-    EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgramAA(precision));
-    EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgram(precision));
-    EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgramAA(precision));
-    EXPECT_PROGRAM_VALID(
-        renderer()->GetRenderPassColorMatrixProgram(precision));
-    EXPECT_PROGRAM_VALID(
-        renderer()->GetRenderPassMaskColorMatrixProgramAA(precision));
-    EXPECT_PROGRAM_VALID(
-        renderer()->GetRenderPassColorMatrixProgramAA(precision));
-    EXPECT_PROGRAM_VALID(
-        renderer()->GetRenderPassMaskColorMatrixProgram(precision));
+    for (int i = 0; i < NumBlendModes; ++i) {
+      BlendMode blend_mode = static_cast<BlendMode>(i);
+      EXPECT_PROGRAM_VALID(
+          renderer()->GetRenderPassProgram(precision, blend_mode));
+      EXPECT_PROGRAM_VALID(
+          renderer()->GetRenderPassProgramAA(precision, blend_mode));
+      EXPECT_PROGRAM_VALID(
+          renderer()->GetRenderPassMaskProgram(precision, blend_mode));
+      EXPECT_PROGRAM_VALID(
+          renderer()->GetRenderPassMaskProgramAA(precision, blend_mode));
+      EXPECT_PROGRAM_VALID(
+          renderer()->GetRenderPassColorMatrixProgram(precision, blend_mode));
+      EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgramAA(
+          precision, blend_mode));
+      EXPECT_PROGRAM_VALID(
+          renderer()->GetRenderPassColorMatrixProgramAA(precision, blend_mode));
+      EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgram(
+          precision, blend_mode));
+    }
     EXPECT_PROGRAM_VALID(renderer()->GetTextureProgram(precision));
     EXPECT_PROGRAM_VALID(
         renderer()->GetNonPremultipliedTextureProgram(precision));
@@ -159,8 +204,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false).Pass();
+                                                  1).Pass();
     renderer_ = make_scoped_ptr(new FakeRendererGL(&renderer_client_,
                                                    &settings_,
                                                    output_surface_.get(),
@@ -196,69 +240,91 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false).Pass();
+                                                  1).Pass();
     renderer_.reset(new FakeRendererGL(&renderer_client_,
                                        &settings_,
                                        output_surface_.get(),
                                        resource_provider_.get()));
   }
 
-  void TestRenderPassProgram(TexCoordPrecision precision) {
-    EXPECT_PROGRAM_VALID(&renderer_->render_pass_program_[precision]);
-    EXPECT_EQ(renderer_->render_pass_program_[precision].program(),
-              renderer_->program_shadow_);
-  }
-
-  void TestRenderPassColorMatrixProgram(TexCoordPrecision precision) {
+  void TestRenderPassProgram(TexCoordPrecision precision,
+                             BlendMode blend_mode) {
     EXPECT_PROGRAM_VALID(
-        &renderer_->render_pass_color_matrix_program_[precision]);
-    EXPECT_EQ(renderer_->render_pass_color_matrix_program_[precision].program(),
+        &renderer_->render_pass_program_[precision][blend_mode]);
+    EXPECT_EQ(renderer_->render_pass_program_[precision][blend_mode].program(),
               renderer_->program_shadow_);
   }
 
-  void TestRenderPassMaskProgram(TexCoordPrecision precision) {
-    EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_program_[precision]);
-    EXPECT_EQ(renderer_->render_pass_mask_program_[precision].program(),
-              renderer_->program_shadow_);
-  }
-
-  void TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision) {
+  void TestRenderPassColorMatrixProgram(TexCoordPrecision precision,
+                                        BlendMode blend_mode) {
     EXPECT_PROGRAM_VALID(
-        &renderer_->render_pass_mask_color_matrix_program_[precision]);
+        &renderer_->render_pass_color_matrix_program_[precision][blend_mode]);
     EXPECT_EQ(
-        renderer_->render_pass_mask_color_matrix_program_[precision].program(),
+        renderer_->render_pass_color_matrix_program_[precision][blend_mode]
+            .program(),
         renderer_->program_shadow_);
   }
 
-  void TestRenderPassProgramAA(TexCoordPrecision precision) {
-    EXPECT_PROGRAM_VALID(&renderer_->render_pass_program_aa_[precision]);
-    EXPECT_EQ(renderer_->render_pass_program_aa_[precision].program(),
-              renderer_->program_shadow_);
-  }
-
-  void TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision) {
+  void TestRenderPassMaskProgram(TexCoordPrecision precision,
+                                 BlendMode blend_mode) {
     EXPECT_PROGRAM_VALID(
-        &renderer_->render_pass_color_matrix_program_aa_[precision]);
+        &renderer_->render_pass_mask_program_[precision][blend_mode]);
     EXPECT_EQ(
-        renderer_->render_pass_color_matrix_program_aa_[precision].program(),
+        renderer_->render_pass_mask_program_[precision][blend_mode].program(),
         renderer_->program_shadow_);
   }
 
-  void TestRenderPassMaskProgramAA(TexCoordPrecision precision) {
-    EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_program_aa_[precision]);
-    EXPECT_EQ(renderer_->render_pass_mask_program_aa_[precision].program(),
-              renderer_->program_shadow_);
+  void TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision,
+                                            BlendMode blend_mode) {
+    EXPECT_PROGRAM_VALID(
+        &renderer_
+             ->render_pass_mask_color_matrix_program_[precision][blend_mode]);
+    EXPECT_EQ(
+        renderer_->render_pass_mask_color_matrix_program_[precision][blend_mode]
+            .program(),
+        renderer_->program_shadow_);
   }
 
-  void TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision) {
+  void TestRenderPassProgramAA(TexCoordPrecision precision,
+                               BlendMode blend_mode) {
     EXPECT_PROGRAM_VALID(
-        &renderer_->render_pass_mask_color_matrix_program_aa_[precision]);
-    EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_aa_[precision]
+        &renderer_->render_pass_program_aa_[precision][blend_mode]);
+    EXPECT_EQ(
+        renderer_->render_pass_program_aa_[precision][blend_mode].program(),
+        renderer_->program_shadow_);
+  }
+
+  void TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision,
+                                          BlendMode blend_mode) {
+    EXPECT_PROGRAM_VALID(
+        &renderer_
+             ->render_pass_color_matrix_program_aa_[precision][blend_mode]);
+    EXPECT_EQ(
+        renderer_->render_pass_color_matrix_program_aa_[precision][blend_mode]
+            .program(),
+        renderer_->program_shadow_);
+  }
+
+  void TestRenderPassMaskProgramAA(TexCoordPrecision precision,
+                                   BlendMode blend_mode) {
+    EXPECT_PROGRAM_VALID(
+        &renderer_->render_pass_mask_program_aa_[precision][blend_mode]);
+    EXPECT_EQ(renderer_->render_pass_mask_program_aa_[precision][blend_mode]
                   .program(),
               renderer_->program_shadow_);
   }
 
+  void TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision,
+                                              BlendMode blend_mode) {
+    EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_color_matrix_program_aa_
+                              [precision][blend_mode]);
+    EXPECT_EQ(
+        renderer_
+            ->render_pass_mask_color_matrix_program_aa_[precision][blend_mode]
+            .program(),
+        renderer_->program_shadow_);
+  }
+
   void TestSolidColorProgramAA() {
     EXPECT_PROGRAM_VALID(&renderer_->solid_color_program_aa_);
     EXPECT_EQ(renderer_->solid_color_program_aa_.program(),
@@ -470,8 +536,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -511,8 +576,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -551,8 +615,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -604,8 +667,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -650,8 +712,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -736,8 +797,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -808,8 +868,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -900,8 +959,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   settings.should_clear_root_render_pass = false;
@@ -999,8 +1057,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -1098,8 +1155,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   settings.partial_swap_enabled = true;
@@ -1288,8 +1344,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -1361,191 +1416,224 @@
   gfx::Transform transform_causing_aa;
   transform_causing_aa.Rotate(20.0);
 
-  // RenderPassProgram
-  child_pass = AddRenderPass(&render_passes_in_draw_order_,
-                             child_pass_id,
-                             child_rect,
-                             gfx::Transform());
+  for (int i = 0; i < NumBlendModes; ++i) {
+    BlendMode blend_mode = static_cast<BlendMode>(i);
+    SkXfermode::Mode xfer_mode = BlendModeToSkXfermode(blend_mode);
+    // RenderPassProgram
+    render_passes_in_draw_order_.clear();
+    child_pass = AddRenderPass(&render_passes_in_draw_order_,
+                               child_pass_id,
+                               child_rect,
+                               gfx::Transform());
 
-  root_pass = AddRenderPass(&render_passes_in_draw_order_,
-                            root_pass_id,
-                            viewport_rect,
-                            gfx::Transform());
+    root_pass = AddRenderPass(&render_passes_in_draw_order_,
+                              root_pass_id,
+                              viewport_rect,
+                              gfx::Transform());
 
-  AddRenderPassQuad(
-      root_pass, child_pass, 0, FilterOperations(), gfx::Transform());
+    AddRenderPassQuad(root_pass,
+                      child_pass,
+                      0,
+                      FilterOperations(),
+                      gfx::Transform(),
+                      xfer_mode);
 
-  renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
-  renderer_->DrawFrame(&render_passes_in_draw_order_,
-                       1.f,
-                       viewport_rect,
-                       viewport_rect,
-                       false);
-  TestRenderPassProgram(TexCoordPrecisionMedium);
+    renderer_->DecideRenderPassAllocationsForFrame(
+        render_passes_in_draw_order_);
+    renderer_->DrawFrame(&render_passes_in_draw_order_,
+                         1.f,
+                         viewport_rect,
+                         viewport_rect,
+                         false);
+    TestRenderPassProgram(TexCoordPrecisionMedium, blend_mode);
 
-  // RenderPassColorMatrixProgram
-  render_passes_in_draw_order_.clear();
+    // RenderPassColorMatrixProgram
+    render_passes_in_draw_order_.clear();
 
-  child_pass = AddRenderPass(&render_passes_in_draw_order_,
-                             child_pass_id,
-                             child_rect,
-                             transform_causing_aa);
+    child_pass = AddRenderPass(&render_passes_in_draw_order_,
+                               child_pass_id,
+                               child_rect,
+                               transform_causing_aa);
 
-  root_pass = AddRenderPass(&render_passes_in_draw_order_,
-                            root_pass_id,
-                            viewport_rect,
-                            gfx::Transform());
+    root_pass = AddRenderPass(&render_passes_in_draw_order_,
+                              root_pass_id,
+                              viewport_rect,
+                              gfx::Transform());
 
-  AddRenderPassQuad(root_pass, child_pass, 0, filters, gfx::Transform());
+    AddRenderPassQuad(
+        root_pass, child_pass, 0, filters, gfx::Transform(), xfer_mode);
 
-  renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
-  renderer_->DrawFrame(&render_passes_in_draw_order_,
-                       1.f,
-                       viewport_rect,
-                       viewport_rect,
-                       false);
-  TestRenderPassColorMatrixProgram(TexCoordPrecisionMedium);
+    renderer_->DecideRenderPassAllocationsForFrame(
+        render_passes_in_draw_order_);
+    renderer_->DrawFrame(&render_passes_in_draw_order_,
+                         1.f,
+                         viewport_rect,
+                         viewport_rect,
+                         false);
+    TestRenderPassColorMatrixProgram(TexCoordPrecisionMedium, blend_mode);
 
-  // RenderPassMaskProgram
-  render_passes_in_draw_order_.clear();
+    // RenderPassMaskProgram
+    render_passes_in_draw_order_.clear();
 
-  child_pass = AddRenderPass(&render_passes_in_draw_order_,
-                             child_pass_id,
-                             child_rect,
-                             gfx::Transform());
+    child_pass = AddRenderPass(&render_passes_in_draw_order_,
+                               child_pass_id,
+                               child_rect,
+                               gfx::Transform());
 
-  root_pass = AddRenderPass(&render_passes_in_draw_order_,
-                            root_pass_id,
-                            viewport_rect,
-                            gfx::Transform());
+    root_pass = AddRenderPass(&render_passes_in_draw_order_,
+                              root_pass_id,
+                              viewport_rect,
+                              gfx::Transform());
 
-  AddRenderPassQuad(
-      root_pass, child_pass, mask, FilterOperations(), gfx::Transform());
+    AddRenderPassQuad(root_pass,
+                      child_pass,
+                      mask,
+                      FilterOperations(),
+                      gfx::Transform(),
+                      xfer_mode);
 
-  renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
-  renderer_->DrawFrame(&render_passes_in_draw_order_,
-                       1.f,
-                       viewport_rect,
-                       viewport_rect,
-                       false);
-  TestRenderPassMaskProgram(TexCoordPrecisionMedium);
+    renderer_->DecideRenderPassAllocationsForFrame(
+        render_passes_in_draw_order_);
+    renderer_->DrawFrame(&render_passes_in_draw_order_,
+                         1.f,
+                         viewport_rect,
+                         viewport_rect,
+                         false);
+    TestRenderPassMaskProgram(TexCoordPrecisionMedium, blend_mode);
 
-  // RenderPassMaskColorMatrixProgram
-  render_passes_in_draw_order_.clear();
+    // RenderPassMaskColorMatrixProgram
+    render_passes_in_draw_order_.clear();
 
-  child_pass = AddRenderPass(&render_passes_in_draw_order_,
-                             child_pass_id,
-                             child_rect,
-                             gfx::Transform());
+    child_pass = AddRenderPass(&render_passes_in_draw_order_,
+                               child_pass_id,
+                               child_rect,
+                               gfx::Transform());
 
-  root_pass = AddRenderPass(&render_passes_in_draw_order_,
-                            root_pass_id,
-                            viewport_rect,
-                            gfx::Transform());
+    root_pass = AddRenderPass(&render_passes_in_draw_order_,
+                              root_pass_id,
+                              viewport_rect,
+                              gfx::Transform());
 
-  AddRenderPassQuad(root_pass, child_pass, mask, filters, gfx::Transform());
+    AddRenderPassQuad(
+        root_pass, child_pass, mask, filters, gfx::Transform(), xfer_mode);
 
-  renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
-  renderer_->DrawFrame(&render_passes_in_draw_order_,
-                       1.f,
-                       viewport_rect,
-                       viewport_rect,
-                       false);
-  TestRenderPassMaskColorMatrixProgram(TexCoordPrecisionMedium);
+    renderer_->DecideRenderPassAllocationsForFrame(
+        render_passes_in_draw_order_);
+    renderer_->DrawFrame(&render_passes_in_draw_order_,
+                         1.f,
+                         viewport_rect,
+                         viewport_rect,
+                         false);
+    TestRenderPassMaskColorMatrixProgram(TexCoordPrecisionMedium, blend_mode);
 
-  // RenderPassProgramAA
-  render_passes_in_draw_order_.clear();
+    // RenderPassProgramAA
+    render_passes_in_draw_order_.clear();
 
-  child_pass = AddRenderPass(&render_passes_in_draw_order_,
-                             child_pass_id,
-                             child_rect,
-                             transform_causing_aa);
+    child_pass = AddRenderPass(&render_passes_in_draw_order_,
+                               child_pass_id,
+                               child_rect,
+                               transform_causing_aa);
 
-  root_pass = AddRenderPass(&render_passes_in_draw_order_,
-                            root_pass_id,
-                            viewport_rect,
-                            gfx::Transform());
+    root_pass = AddRenderPass(&render_passes_in_draw_order_,
+                              root_pass_id,
+                              viewport_rect,
+                              gfx::Transform());
 
-  AddRenderPassQuad(
-      root_pass, child_pass, 0, FilterOperations(), transform_causing_aa);
+    AddRenderPassQuad(root_pass,
+                      child_pass,
+                      0,
+                      FilterOperations(),
+                      transform_causing_aa,
+                      xfer_mode);
 
-  renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
-  renderer_->DrawFrame(&render_passes_in_draw_order_,
-                       1.f,
-                       viewport_rect,
-                       viewport_rect,
-                       false);
-  TestRenderPassProgramAA(TexCoordPrecisionMedium);
+    renderer_->DecideRenderPassAllocationsForFrame(
+        render_passes_in_draw_order_);
+    renderer_->DrawFrame(&render_passes_in_draw_order_,
+                         1.f,
+                         viewport_rect,
+                         viewport_rect,
+                         false);
+    TestRenderPassProgramAA(TexCoordPrecisionMedium, blend_mode);
 
-  // RenderPassColorMatrixProgramAA
-  render_passes_in_draw_order_.clear();
+    // RenderPassColorMatrixProgramAA
+    render_passes_in_draw_order_.clear();
 
-  child_pass = AddRenderPass(&render_passes_in_draw_order_,
-                             child_pass_id,
-                             child_rect,
-                             transform_causing_aa);
+    child_pass = AddRenderPass(&render_passes_in_draw_order_,
+                               child_pass_id,
+                               child_rect,
+                               transform_causing_aa);
 
-  root_pass = AddRenderPass(&render_passes_in_draw_order_,
-                            root_pass_id,
-                            viewport_rect,
-                            gfx::Transform());
+    root_pass = AddRenderPass(&render_passes_in_draw_order_,
+                              root_pass_id,
+                              viewport_rect,
+                              gfx::Transform());
 
-  AddRenderPassQuad(root_pass, child_pass, 0, filters, transform_causing_aa);
+    AddRenderPassQuad(
+        root_pass, child_pass, 0, filters, transform_causing_aa, xfer_mode);
 
-  renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
-  renderer_->DrawFrame(&render_passes_in_draw_order_,
-                       1.f,
-                       viewport_rect,
-                       viewport_rect,
-                       false);
-  TestRenderPassColorMatrixProgramAA(TexCoordPrecisionMedium);
+    renderer_->DecideRenderPassAllocationsForFrame(
+        render_passes_in_draw_order_);
+    renderer_->DrawFrame(&render_passes_in_draw_order_,
+                         1.f,
+                         viewport_rect,
+                         viewport_rect,
+                         false);
+    TestRenderPassColorMatrixProgramAA(TexCoordPrecisionMedium, blend_mode);
 
-  // RenderPassMaskProgramAA
-  render_passes_in_draw_order_.clear();
+    // RenderPassMaskProgramAA
+    render_passes_in_draw_order_.clear();
 
-  child_pass = AddRenderPass(&render_passes_in_draw_order_,
-                             child_pass_id,
-                             child_rect,
-                             transform_causing_aa);
+    child_pass = AddRenderPass(&render_passes_in_draw_order_,
+                               child_pass_id,
+                               child_rect,
+                               transform_causing_aa);
 
-  root_pass = AddRenderPass(&render_passes_in_draw_order_,
-                            root_pass_id,
-                            viewport_rect,
-                            gfx::Transform());
+    root_pass = AddRenderPass(&render_passes_in_draw_order_,
+                              root_pass_id,
+                              viewport_rect,
+                              gfx::Transform());
 
-  AddRenderPassQuad(
-      root_pass, child_pass, mask, FilterOperations(), transform_causing_aa);
+    AddRenderPassQuad(root_pass,
+                      child_pass,
+                      mask,
+                      FilterOperations(),
+                      transform_causing_aa,
+                      xfer_mode);
 
-  renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
-  renderer_->DrawFrame(&render_passes_in_draw_order_,
-                       1.f,
-                       viewport_rect,
-                       viewport_rect,
-                       false);
-  TestRenderPassMaskProgramAA(TexCoordPrecisionMedium);
+    renderer_->DecideRenderPassAllocationsForFrame(
+        render_passes_in_draw_order_);
+    renderer_->DrawFrame(&render_passes_in_draw_order_,
+                         1.f,
+                         viewport_rect,
+                         viewport_rect,
+                         false);
+    TestRenderPassMaskProgramAA(TexCoordPrecisionMedium, blend_mode);
 
-  // RenderPassMaskColorMatrixProgramAA
-  render_passes_in_draw_order_.clear();
+    // RenderPassMaskColorMatrixProgramAA
+    render_passes_in_draw_order_.clear();
 
-  child_pass = AddRenderPass(&render_passes_in_draw_order_,
-                             child_pass_id,
-                             child_rect,
-                             transform_causing_aa);
+    child_pass = AddRenderPass(&render_passes_in_draw_order_,
+                               child_pass_id,
+                               child_rect,
+                               transform_causing_aa);
 
-  root_pass = AddRenderPass(&render_passes_in_draw_order_,
-                            root_pass_id,
-                            viewport_rect,
-                            transform_causing_aa);
+    root_pass = AddRenderPass(&render_passes_in_draw_order_,
+                              root_pass_id,
+                              viewport_rect,
+                              transform_causing_aa);
 
-  AddRenderPassQuad(root_pass, child_pass, mask, filters, transform_causing_aa);
+    AddRenderPassQuad(
+        root_pass, child_pass, mask, filters, transform_causing_aa, xfer_mode);
 
-  renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
-  renderer_->DrawFrame(&render_passes_in_draw_order_,
-                       1.f,
-                       viewport_rect,
-                       viewport_rect,
-                       false);
-  TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecisionMedium);
+    renderer_->DecideRenderPassAllocationsForFrame(
+        render_passes_in_draw_order_);
+    renderer_->DrawFrame(&render_passes_in_draw_order_,
+                         1.f,
+                         viewport_rect,
+                         viewport_rect,
+                         false);
+    TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecisionMedium, blend_mode);
+  }
 }
 
 // At this time, the AA code path cannot be taken if the surface's rect would
@@ -1580,8 +1668,12 @@
                             viewport_rect,
                             gfx::Transform());
 
-  AddRenderPassQuad(
-      root_pass, child_pass, 0, FilterOperations(), transform_preventing_aa);
+  AddRenderPassQuad(root_pass,
+                    child_pass,
+                    0,
+                    FilterOperations(),
+                    transform_preventing_aa,
+                    SkXfermode::kSrcOver_Mode);
 
   renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
   renderer_->DrawFrame(&render_passes_in_draw_order_,
@@ -1592,7 +1684,7 @@
 
   // If use_aa incorrectly ignores clipping, it will use the
   // RenderPassProgramAA shader instead of the RenderPassProgram.
-  TestRenderPassProgram(TexCoordPrecisionMedium);
+  TestRenderPassProgram(TexCoordPrecisionMedium, BlendModeNormal);
 }
 
 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
@@ -1668,8 +1760,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false).Pass();
+                                                  1).Pass();
 
     renderer_.reset(new FakeRendererGL(&renderer_client_,
                                        &settings_,
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index 92b19c7..8b7dc2a 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -244,15 +244,8 @@
 
   scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
       new TestSharedBitmapManager());
-  scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(&output_surface,
-                               shared_bitmap_manager.get(),
-                               NULL,
-                               NULL,
-                               0,
-                               false,
-                               1,
-                               false));
+  scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
+      &output_surface, shared_bitmap_manager.get(), NULL, NULL, 0, false, 1));
 
   scoped_ptr<DefaultOverlayProcessor> overlay_processor(
       new DefaultOverlayProcessor(&output_surface, resource_provider.get()));
@@ -276,8 +269,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false);
+                                                  1);
 
     overlay_processor_.reset(new SingleOverlayProcessor(
         output_surface_.get(), resource_provider_.get()));
@@ -588,7 +580,7 @@
     output_surface_.reset(new OverlayOutputSurface(provider_));
     CHECK(output_surface_->BindToClient(&output_surface_client_));
     resource_provider_ = ResourceProvider::Create(
-        output_surface_.get(), NULL, NULL, NULL, 0, false, 1, false);
+        output_surface_.get(), NULL, NULL, NULL, 0, false, 1);
 
     provider_->support()->SetScheduleOverlayPlaneCallback(base::Bind(
         &MockOverlayScheduler::Schedule, base::Unretained(&scheduler_)));
diff --git a/cc/output/program_binding.h b/cc/output/program_binding.h
index 912329e..722c782 100644
--- a/cc/output/program_binding.h
+++ b/cc/output/program_binding.h
@@ -58,13 +58,16 @@
 
   void Initialize(ContextProvider* context_provider,
                   TexCoordPrecision precision,
-                  SamplerType sampler) {
+                  SamplerType sampler,
+                  BlendMode blend_mode = BlendModeNormal) {
     DCHECK(context_provider);
     DCHECK(!initialized_);
 
     if (context_provider->IsContextLost())
       return;
 
+    fragment_shader_.set_blend_mode(blend_mode);
+
     if (!ProgramBindingBase::Init(
             context_provider->ContextGL(),
             vertex_shader_.GetShaderString(),
diff --git a/cc/output/renderer_unittest.cc b/cc/output/renderer_unittest.cc
index 229558d..6e43cc0 100644
--- a/cc/output/renderer_unittest.cc
+++ b/cc/output/renderer_unittest.cc
@@ -83,7 +83,7 @@
     output_surface_.reset(new TestOutputSurface(context_provider_));
     output_surface_->BindToClient(&output_surface_client_);
     resource_provider_ = ResourceProvider::Create(
-        output_surface_.get(), NULL, NULL, NULL, 0, false, 1, false);
+        output_surface_.get(), NULL, NULL, NULL, 0, false, 1);
     renderer_ = CreateRenderer<T>(&renderer_client_,
                                   &tree_settings_,
                                   output_surface_.get(),
diff --git a/cc/output/shader.cc b/cc/output/shader.cc
index 8a25214..98bde8d 100644
--- a/cc/output/shader.cc
+++ b/cc/output/shader.cc
@@ -13,9 +13,10 @@
 
 #define SHADER0(Src) #Src
 #define VERTEX_SHADER(Src) SetVertexTexCoordPrecision(SHADER0(Src))
-#define FRAGMENT_SHADER(Src)              \
-  SetFragmentTexCoordPrecision(precision, \
-                               SetFragmentSamplerType(sampler, SHADER0(Src)))
+#define FRAGMENT_SHADER(Src)    \
+  SetFragmentTexCoordPrecision( \
+      precision,                \
+      SetFragmentSamplerType(sampler, SetBlendModeFunctions(SHADER0(Src))))
 
 using gpu::gles2::GLES2Interface;
 
@@ -666,6 +667,308 @@
   // clang-format on
 }
 
+#define BLEND_MODE_UNIFORMS "s_backdropTexture", "backdropRect"
+#define UNUSED_BLEND_MODE_UNIFORMS (is_default_blend_mode() ? 2 : 0)
+#define BLEND_MODE_SET_LOCATIONS(X, POS)                   \
+  if (!is_default_blend_mode()) {                          \
+    DCHECK_LT(static_cast<size_t>(POS) + 1, arraysize(X)); \
+    backdrop_location_ = locations[POS];                   \
+    backdrop_rect_location_ = locations[POS + 1];          \
+  }
+
+FragmentTexBlendMode::FragmentTexBlendMode()
+    : backdrop_location_(-1),
+      backdrop_rect_location_(-1),
+      blend_mode_(BlendModeNormal) {
+}
+
+std::string FragmentTexBlendMode::SetBlendModeFunctions(
+    std::string shader_string) const {
+  if (shader_string.find("ApplyBlendMode") == std::string::npos)
+    return shader_string;
+
+  if (is_default_blend_mode()) {
+    return "#define ApplyBlendMode(X) (X)\n" + shader_string;
+  }
+
+  // clang-format off
+  static const std::string kFunctionApplyBlendMode = SHADER0(
+      // clang-format on
+      uniform SamplerType s_backdropTexture;
+      uniform TexCoordPrecision vec4 backdropRect;
+
+      vec4 GetBackdropColor() {
+        TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
+        bgTexCoord.x /= backdropRect.z;
+        bgTexCoord.y /= backdropRect.w;
+        return TextureLookup(s_backdropTexture, bgTexCoord);
+      }
+
+      vec4 ApplyBlendMode(vec4 src) {
+        vec4 dst = GetBackdropColor();
+        return Blend(src, dst);
+      }
+      // clang-format off
+  );
+  // clang-format on
+
+  return "precision mediump float;" + GetHelperFunctions() +
+         GetBlendFunction() + kFunctionApplyBlendMode + shader_string;
+}
+
+std::string FragmentTexBlendMode::GetHelperFunctions() const {
+  // clang-format off
+  static const std::string kFunctionHardLight = SHADER0(
+      // clang-format on
+      vec3 hardLight(vec4 src, vec4 dst) {
+        vec3 result;
+        result.r =
+            (2.0 * src.r <= src.a)
+                ? (2.0 * src.r * dst.r)
+                : (src.a * dst.a - 2.0 * (dst.a - dst.r) * (src.a - src.r));
+        result.g =
+            (2.0 * src.g <= src.a)
+                ? (2.0 * src.g * dst.g)
+                : (src.a * dst.a - 2.0 * (dst.a - dst.g) * (src.a - src.g));
+        result.b =
+            (2.0 * src.b <= src.a)
+                ? (2.0 * src.b * dst.b)
+                : (src.a * dst.a - 2.0 * (dst.a - dst.b) * (src.a - src.b));
+        result.rgb += src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
+        return result;
+      }
+      // clang-format off
+  );
+
+  static const std::string kFunctionColorDodgeComponent = SHADER0(
+      // clang-format on
+      float getColorDodgeComponent(
+          float srcc, float srca, float dstc, float dsta) {
+        if (0.0 == dstc)
+          return srcc * (1.0 - dsta);
+        float d = srca - srcc;
+        if (0.0 == d)
+          return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
+        d = min(dsta, dstc * srca / d);
+        return d * srca + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
+      }
+      // clang-format off
+  );
+
+  static const std::string kFunctionColorBurnComponent = SHADER0(
+      // clang-format on
+      float getColorBurnComponent(
+          float srcc, float srca, float dstc, float dsta) {
+        if (dsta == dstc)
+          return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
+        if (0.0 == srcc)
+          return dstc * (1.0 - srca);
+        float d = max(0.0, dsta - (dsta - dstc) * srca / srcc);
+        return srca * d + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
+      }
+      // clang-format off
+  );
+
+  static const std::string kFunctionSoftLightComponentPosDstAlpha = SHADER0(
+      // clang-format on
+      float getSoftLightComponent(
+          float srcc, float srca, float dstc, float dsta) {
+        if (2.0 * srcc <= srca) {
+          return (dstc * dstc * (srca - 2.0 * srcc)) / dsta +
+                 (1.0 - dsta) * srcc + dstc * (-srca + 2.0 * srcc + 1.0);
+        } else if (4.0 * dstc <= dsta) {
+          float DSqd = dstc * dstc;
+          float DCub = DSqd * dstc;
+          float DaSqd = dsta * dsta;
+          float DaCub = DaSqd * dsta;
+          return (-DaCub * srcc +
+                  DaSqd * (srcc - dstc * (3.0 * srca - 6.0 * srcc - 1.0)) +
+                  12.0 * dsta * DSqd * (srca - 2.0 * srcc) -
+                  16.0 * DCub * (srca - 2.0 * srcc)) /
+                 DaSqd;
+        } else {
+          return -sqrt(dsta * dstc) * (srca - 2.0 * srcc) - dsta * srcc +
+                 dstc * (srca - 2.0 * srcc + 1.0) + srcc;
+        }
+      }
+      // clang-format off
+  );
+
+  static const std::string kFunctionLum = SHADER0(
+      // clang-format on
+      float luminance(vec3 color) { return dot(vec3(0.3, 0.59, 0.11), color); }
+
+      vec3 set_luminance(vec3 hueSat, float alpha, vec3 lumColor) {
+        float diff = luminance(lumColor - hueSat);
+        vec3 outColor = hueSat + diff;
+        float outLum = luminance(outColor);
+        float minComp = min(min(outColor.r, outColor.g), outColor.b);
+        float maxComp = max(max(outColor.r, outColor.g), outColor.b);
+        if (minComp < 0.0) {
+          outColor = outLum +
+                     ((outColor - vec3(outLum, outLum, outLum)) * outLum) /
+                         (outLum - minComp);
+        }
+        if (maxComp > alpha) {
+          outColor =
+              outLum +
+              ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) /
+                  (maxComp - outLum);
+        }
+        return outColor;
+      }
+      // clang-format off
+  );
+
+  static const std::string kFunctionSat = SHADER0(
+      // clang-format on
+      float saturation(vec3 color) {
+        return max(max(color.r, color.g), color.b) -
+               min(min(color.r, color.g), color.b);
+      }
+
+      vec3 set_saturation_helper(
+          float minComp, float midComp, float maxComp, float sat) {
+        if (minComp < maxComp) {
+          vec3 result;
+          result.r = 0.0;
+          result.g = sat * (midComp - minComp) / (maxComp - minComp);
+          result.b = sat;
+          return result;
+        } else {
+          return vec3(0, 0, 0);
+        }
+      }
+
+      vec3 set_saturation(vec3 hueLumColor, vec3 satColor) {
+        float sat = saturation(satColor);
+        if (hueLumColor.r <= hueLumColor.g) {
+          if (hueLumColor.g <= hueLumColor.b) {
+            hueLumColor.rgb = set_saturation_helper(
+                hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);
+          } else if (hueLumColor.r <= hueLumColor.b) {
+            hueLumColor.rbg = set_saturation_helper(
+                hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);
+          } else {
+            hueLumColor.brg = set_saturation_helper(
+                hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);
+          }
+        } else if (hueLumColor.r <= hueLumColor.b) {
+          hueLumColor.grb = set_saturation_helper(
+              hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);
+        } else if (hueLumColor.g <= hueLumColor.b) {
+          hueLumColor.gbr = set_saturation_helper(
+              hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);
+        } else {
+          hueLumColor.bgr = set_saturation_helper(
+              hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);
+        }
+        return hueLumColor;
+      }
+      // clang-format off
+  );
+  // clang-format on
+
+  switch (blend_mode_) {
+    case BlendModeOverlay:
+    case BlendModeHardLight:
+      return kFunctionHardLight;
+    case BlendModeColorDodge:
+      return kFunctionColorDodgeComponent;
+    case BlendModeColorBurn:
+      return kFunctionColorBurnComponent;
+    case BlendModeSoftLight:
+      return kFunctionSoftLightComponentPosDstAlpha;
+    case BlendModeHue:
+    case BlendModeSaturation:
+      return kFunctionLum + kFunctionSat;
+    case BlendModeColor:
+    case BlendModeLuminosity:
+      return kFunctionLum;
+    default:
+      return std::string();
+  }
+}
+
+std::string FragmentTexBlendMode::GetBlendFunction() const {
+  return "vec4 Blend(vec4 src, vec4 dst) {"
+         "    vec4 result;"
+         "    result.a = src.a + (1.0 - src.a) * dst.a;" +
+         GetBlendFunctionBodyForRGB() +
+         "    return result;"
+         "}";
+}
+
+std::string FragmentTexBlendMode::GetBlendFunctionBodyForRGB() const {
+  switch (blend_mode_) {
+    case BlendModeLighten:
+      return "result.rgb = max((1.0 - src.a) * dst.rgb + src.rgb,"
+             "                 (1.0 - dst.a) * src.rgb + dst.rgb);";
+    case BlendModeOverlay:
+      return "result.rgb = hardLight(dst, src);";
+    case BlendModeDarken:
+      return "result.rgb = min((1.0 - src.a) * dst.rgb + src.rgb,"
+             "                 (1.0 - dst.a) * src.rgb + dst.rgb);";
+    case BlendModeColorDodge:
+      return "result.r = getColorDodgeComponent(src.r, src.a, dst.r, dst.a);"
+             "result.g = getColorDodgeComponent(src.g, src.a, dst.g, dst.a);"
+             "result.b = getColorDodgeComponent(src.b, src.a, dst.b, dst.a);";
+    case BlendModeColorBurn:
+      return "result.r = getColorBurnComponent(src.r, src.a, dst.r, dst.a);"
+             "result.g = getColorBurnComponent(src.g, src.a, dst.g, dst.a);"
+             "result.b = getColorBurnComponent(src.b, src.a, dst.b, dst.a);";
+    case BlendModeHardLight:
+      return "result.rgb = hardLight(src, dst);";
+    case BlendModeSoftLight:
+      return "if (0.0 == dst.a) {"
+             "  result.rgb = src.rgb;"
+             "} else {"
+             "  result.r = getSoftLightComponent(src.r, src.a, dst.r, dst.a);"
+             "  result.g = getSoftLightComponent(src.g, src.a, dst.g, dst.a);"
+             "  result.b = getSoftLightComponent(src.b, src.a, dst.b, dst.a);"
+             "}";
+    case BlendModeDifference:
+      return "result.rgb = src.rgb + dst.rgb -"
+             "    2.0 * min(src.rgb * dst.a, dst.rgb * src.a);";
+    case BlendModeExclusion:
+      return "result.rgb = dst.rgb + src.rgb - 2.0 * dst.rgb * src.rgb;";
+    case BlendModeMultiply:
+      return "result.rgb = (1.0 - src.a) * dst.rgb +"
+             "    (1.0 - dst.a) * src.rgb + src.rgb * dst.rgb;";
+    case BlendModeHue:
+      return "vec4 dstSrcAlpha = dst * src.a;"
+             "result.rgb ="
+             "    set_luminance(set_saturation(src.rgb * dst.a,"
+             "                                 dstSrcAlpha.rgb),"
+             "                  dstSrcAlpha.a,"
+             "                  dstSrcAlpha.rgb);"
+             "result.rgb += (1.0 - src.a) * dst.rgb + (1.0 - dst.a) * src.rgb;";
+    case BlendModeSaturation:
+      return "vec4 dstSrcAlpha = dst * src.a;"
+             "result.rgb = set_luminance(set_saturation(dstSrcAlpha.rgb,"
+             "                                          src.rgb * dst.a),"
+             "                           dstSrcAlpha.a,"
+             "                           dstSrcAlpha.rgb);"
+             "result.rgb += (1.0 - src.a) * dst.rgb + (1.0 - dst.a) * src.rgb;";
+    case BlendModeColor:
+      return "vec4 srcDstAlpha = src * dst.a;"
+             "result.rgb = set_luminance(srcDstAlpha.rgb,"
+             "                           srcDstAlpha.a,"
+             "                           dst.rgb * src.a);"
+             "result.rgb += (1.0 - src.a) * dst.rgb + (1.0 - dst.a) * src.rgb;";
+    case BlendModeLuminosity:
+      return "vec4 srcDstAlpha = src * dst.a;"
+             "result.rgb = set_luminance(dst.rgb * src.a,"
+             "                           srcDstAlpha.a,"
+             "                           srcDstAlpha.rgb);"
+             "result.rgb += (1.0 - src.a) * dst.rgb + (1.0 - dst.a) * src.rgb;";
+    default:
+      NOTREACHED();
+      // simple alpha compositing
+      return "result.rgb = src.rgb * src.a + dst.rgb * dst.a * (1 - src.a)";
+  }
+}
+
 FragmentTexAlphaBinding::FragmentTexAlphaBinding()
     : sampler_location_(-1), alpha_location_(-1) {
 }
@@ -674,18 +977,19 @@
                                    unsigned program,
                                    int* base_uniform_index) {
   static const char* uniforms[] = {
-      "s_texture", "alpha",
+      "s_texture", "alpha", BLEND_MODE_UNIFORMS,
   };
   int locations[arraysize(uniforms)];
 
   GetProgramUniformLocations(context,
                              program,
-                             arraysize(uniforms),
+                             arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
                              uniforms,
                              locations,
                              base_uniform_index);
   sampler_location_ = locations[0];
   alpha_location_ = locations[1];
+  BLEND_MODE_SET_LOCATIONS(locations, 2);
 }
 
 FragmentTexColorMatrixAlphaBinding::FragmentTexColorMatrixAlphaBinding()
@@ -699,13 +1003,13 @@
                                               unsigned program,
                                               int* base_uniform_index) {
   static const char* uniforms[] = {
-      "s_texture", "alpha", "colorMatrix", "colorOffset",
+      "s_texture", "alpha", "colorMatrix", "colorOffset", BLEND_MODE_UNIFORMS,
   };
   int locations[arraysize(uniforms)];
 
   GetProgramUniformLocations(context,
                              program,
-                             arraysize(uniforms),
+                             arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
                              uniforms,
                              locations,
                              base_uniform_index);
@@ -713,6 +1017,7 @@
   alpha_location_ = locations[1];
   color_matrix_location_ = locations[2];
   color_offset_location_ = locations[3];
+  BLEND_MODE_SET_LOCATIONS(locations, 4);
 }
 
 FragmentTexOpaqueBinding::FragmentTexOpaqueBinding() : sampler_location_(-1) {
@@ -747,7 +1052,7 @@
       uniform float alpha;
       void main() {
         vec4 texColor = TextureLookup(s_texture, v_texCoord);
-        gl_FragColor = texColor * alpha;
+        gl_FragColor = ApplyBlendMode(texColor * alpha);
       }
       // clang-format off
   );  // NOLINT(whitespace/parens)
@@ -773,7 +1078,7 @@
         texColor = colorMatrix * texColor + colorOffset;
         texColor.rgb *= texColor.a;
         texColor = clamp(texColor, 0.0, 1.0);
-        gl_FragColor = texColor * alpha;
+        gl_FragColor = ApplyBlendMode(texColor * alpha);
       }
       // clang-format off
   );  // NOLINT(whitespace/parens)
@@ -966,18 +1271,19 @@
                                         unsigned program,
                                         int* base_uniform_index) {
   static const char* uniforms[] = {
-      "s_texture", "alpha",
+      "s_texture", "alpha", BLEND_MODE_UNIFORMS,
   };
   int locations[arraysize(uniforms)];
 
   GetProgramUniformLocations(context,
                              program,
-                             arraysize(uniforms),
+                             arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
                              uniforms,
                              locations,
                              base_uniform_index);
   sampler_location_ = locations[0];
   alpha_location_ = locations[1];
+  BLEND_MODE_SET_LOCATIONS(locations, 2);
 }
 
 std::string FragmentShaderRGBATexAlphaAA::GetShaderString(
@@ -997,7 +1303,7 @@
         vec4 d4 = min(edge_dist[0], edge_dist[1]);
         vec2 d2 = min(d4.xz, d4.yw);
         float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
-        gl_FragColor = texColor * alpha * aa;
+        gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
       }
       // clang-format off
   );  // NOLINT(whitespace/parens)
@@ -1097,13 +1403,18 @@
                                           unsigned program,
                                           int* base_uniform_index) {
   static const char* uniforms[] = {
-      "s_texture", "s_mask", "alpha", "maskTexCoordScale", "maskTexCoordOffset",
+      "s_texture",
+      "s_mask",
+      "alpha",
+      "maskTexCoordScale",
+      "maskTexCoordOffset",
+      BLEND_MODE_UNIFORMS,
   };
   int locations[arraysize(uniforms)];
 
   GetProgramUniformLocations(context,
                              program,
-                             arraysize(uniforms),
+                             arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
                              uniforms,
                              locations,
                              base_uniform_index);
@@ -1112,6 +1423,7 @@
   alpha_location_ = locations[2];
   mask_tex_coord_scale_location_ = locations[3];
   mask_tex_coord_offset_location_ = locations[4];
+  BLEND_MODE_SET_LOCATIONS(locations, 5);
 }
 
 std::string FragmentShaderRGBATexAlphaMask::GetShaderString(
@@ -1133,7 +1445,7 @@
             vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
                  maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
         vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
-        gl_FragColor = texColor * alpha * maskColor.w;
+        gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
       }
       // clang-format off
   );  // NOLINT(whitespace/parens)
@@ -1152,13 +1464,18 @@
                                             unsigned program,
                                             int* base_uniform_index) {
   static const char* uniforms[] = {
-      "s_texture", "s_mask", "alpha", "maskTexCoordScale", "maskTexCoordOffset",
+      "s_texture",
+      "s_mask",
+      "alpha",
+      "maskTexCoordScale",
+      "maskTexCoordOffset",
+      BLEND_MODE_UNIFORMS,
   };
   int locations[arraysize(uniforms)];
 
   GetProgramUniformLocations(context,
                              program,
-                             arraysize(uniforms),
+                             arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
                              uniforms,
                              locations,
                              base_uniform_index);
@@ -1167,6 +1484,7 @@
   alpha_location_ = locations[2];
   mask_tex_coord_scale_location_ = locations[3];
   mask_tex_coord_offset_location_ = locations[4];
+  BLEND_MODE_SET_LOCATIONS(locations, 5);
 }
 
 std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderString(
@@ -1193,7 +1511,7 @@
         vec4 d4 = min(edge_dist[0], edge_dist[1]);
         vec2 d2 = min(d4.xz, d4.yw);
         float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
-        gl_FragColor = texColor * alpha * maskColor.w * aa;
+        gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
       }
       // clang-format off
   );  // NOLINT(whitespace/parens)
@@ -1222,12 +1540,13 @@
       "maskTexCoordOffset",
       "colorMatrix",
       "colorOffset",
+      BLEND_MODE_UNIFORMS,
   };
   int locations[arraysize(uniforms)];
 
   GetProgramUniformLocations(context,
                              program,
-                             arraysize(uniforms),
+                             arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
                              uniforms,
                              locations,
                              base_uniform_index);
@@ -1238,6 +1557,7 @@
   mask_tex_coord_offset_location_ = locations[4];
   color_matrix_location_ = locations[5];
   color_offset_location_ = locations[6];
+  BLEND_MODE_SET_LOCATIONS(locations, 7);
 }
 
 std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderString(
@@ -1271,7 +1591,7 @@
         vec4 d4 = min(edge_dist[0], edge_dist[1]);
         vec2 d2 = min(d4.xz, d4.yw);
         float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
-        gl_FragColor = texColor * alpha * maskColor.w * aa;
+        gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
       }
       // clang-format off
   );  // NOLINT(whitespace/parens)
@@ -1290,13 +1610,13 @@
                                                    unsigned program,
                                                    int* base_uniform_index) {
   static const char* uniforms[] = {
-      "s_texture", "alpha", "colorMatrix", "colorOffset",
+      "s_texture", "alpha", "colorMatrix", "colorOffset", BLEND_MODE_UNIFORMS,
   };
   int locations[arraysize(uniforms)];
 
   GetProgramUniformLocations(context,
                              program,
-                             arraysize(uniforms),
+                             arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
                              uniforms,
                              locations,
                              base_uniform_index);
@@ -1304,6 +1624,7 @@
   alpha_location_ = locations[1];
   color_matrix_location_ = locations[2];
   color_offset_location_ = locations[3];
+  BLEND_MODE_SET_LOCATIONS(locations, 4);
 }
 
 std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderString(
@@ -1330,7 +1651,7 @@
         vec4 d4 = min(edge_dist[0], edge_dist[1]);
         vec2 d2 = min(d4.xz, d4.yw);
         float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
-        gl_FragColor = texColor * alpha * aa;
+        gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
       }
       // clang-format off
   );  // NOLINT(whitespace/parens)
@@ -1356,12 +1677,13 @@
       "maskTexCoordOffset",
       "colorMatrix",
       "colorOffset",
+      BLEND_MODE_UNIFORMS,
   };
   int locations[arraysize(uniforms)];
 
   GetProgramUniformLocations(context,
                              program,
-                             arraysize(uniforms),
+                             arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
                              uniforms,
                              locations,
                              base_uniform_index);
@@ -1372,6 +1694,7 @@
   mask_tex_coord_offset_location_ = locations[4];
   color_matrix_location_ = locations[5];
   color_offset_location_ = locations[6];
+  BLEND_MODE_SET_LOCATIONS(locations, 7);
 }
 
 std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderString(
@@ -1400,7 +1723,7 @@
             vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
                  maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
         vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
-        gl_FragColor = texColor * alpha * maskColor.w;
+        gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
       }
       // clang-format off
   );  // NOLINT(whitespace/parens)
diff --git a/cc/output/shader.h b/cc/output/shader.h
index 3039c80..0384366 100644
--- a/cc/output/shader.h
+++ b/cc/output/shader.h
@@ -38,6 +38,25 @@
   NumSamplerTypes = 4
 };
 
+enum BlendMode {
+  BlendModeNormal,
+  BlendModeOverlay,
+  BlendModeDarken,
+  BlendModeLighten,
+  BlendModeColorDodge,
+  BlendModeColorBurn,
+  BlendModeHardLight,
+  BlendModeSoftLight,
+  BlendModeDifference,
+  BlendModeExclusion,
+  BlendModeMultiply,
+  BlendModeHue,
+  BlendModeSaturation,
+  BlendModeColor,
+  BlendModeLuminosity,
+  NumBlendModes
+};
+
 // Note: The highp_threshold_cache must be provided by the caller to make
 // the caching multi-thread/context safe in an easy low-overhead manner.
 // The caller must make sure to clear highp_threshold_cache to 0, so it can be
@@ -279,7 +298,32 @@
   DISALLOW_COPY_AND_ASSIGN(VertexShaderVideoTransform);
 };
 
-class FragmentTexAlphaBinding {
+class FragmentTexBlendMode {
+ public:
+  int backdrop_location() const { return backdrop_location_; }
+  int backdrop_rect_location() const { return backdrop_rect_location_; }
+
+  BlendMode blend_mode() const { return blend_mode_; }
+  void set_blend_mode(BlendMode blend_mode) { blend_mode_ = blend_mode; }
+  bool is_default_blend_mode() const { return blend_mode_ == BlendModeNormal; }
+
+ protected:
+  FragmentTexBlendMode();
+
+  std::string SetBlendModeFunctions(std::string shader_string) const;
+
+  int backdrop_location_;
+  int backdrop_rect_location_;
+
+ private:
+  BlendMode blend_mode_;
+
+  std::string GetHelperFunctions() const;
+  std::string GetBlendFunction() const;
+  std::string GetBlendFunctionBodyForRGB() const;
+};
+
+class FragmentTexAlphaBinding : public FragmentTexBlendMode {
  public:
   FragmentTexAlphaBinding();
 
@@ -297,7 +341,7 @@
   DISALLOW_COPY_AND_ASSIGN(FragmentTexAlphaBinding);
 };
 
-class FragmentTexColorMatrixAlphaBinding {
+class FragmentTexColorMatrixAlphaBinding : public FragmentTexBlendMode {
  public:
     FragmentTexColorMatrixAlphaBinding();
 
@@ -317,7 +361,7 @@
     int color_offset_location_;
 };
 
-class FragmentTexOpaqueBinding {
+class FragmentTexOpaqueBinding : public FragmentTexBlendMode {
  public:
   FragmentTexOpaqueBinding();
 
@@ -335,7 +379,7 @@
   DISALLOW_COPY_AND_ASSIGN(FragmentTexOpaqueBinding);
 };
 
-class FragmentTexBackgroundBinding {
+class FragmentTexBackgroundBinding : public FragmentTexBlendMode {
  public:
   FragmentTexBackgroundBinding();
 
@@ -417,7 +461,7 @@
       TexCoordPrecision precision, SamplerType sampler) const;
 };
 
-class FragmentShaderRGBATexAlphaAA {
+class FragmentShaderRGBATexAlphaAA : public FragmentTexBlendMode {
  public:
   FragmentShaderRGBATexAlphaAA();
 
@@ -437,7 +481,7 @@
   DISALLOW_COPY_AND_ASSIGN(FragmentShaderRGBATexAlphaAA);
 };
 
-class FragmentTexClampAlphaAABinding {
+class FragmentTexClampAlphaAABinding : public FragmentTexBlendMode {
  public:
   FragmentTexClampAlphaAABinding();
 
@@ -473,7 +517,7 @@
       TexCoordPrecision precision, SamplerType sampler) const;
 };
 
-class FragmentShaderRGBATexAlphaMask {
+class FragmentShaderRGBATexAlphaMask : public FragmentTexBlendMode {
  public:
   FragmentShaderRGBATexAlphaMask();
   std::string GetShaderString(
@@ -502,7 +546,7 @@
   DISALLOW_COPY_AND_ASSIGN(FragmentShaderRGBATexAlphaMask);
 };
 
-class FragmentShaderRGBATexAlphaMaskAA {
+class FragmentShaderRGBATexAlphaMaskAA : public FragmentTexBlendMode {
  public:
   FragmentShaderRGBATexAlphaMaskAA();
   std::string GetShaderString(
@@ -531,7 +575,8 @@
   DISALLOW_COPY_AND_ASSIGN(FragmentShaderRGBATexAlphaMaskAA);
 };
 
-class FragmentShaderRGBATexAlphaMaskColorMatrixAA {
+class FragmentShaderRGBATexAlphaMaskColorMatrixAA
+    : public FragmentTexBlendMode {
  public:
   FragmentShaderRGBATexAlphaMaskColorMatrixAA();
   std::string GetShaderString(
@@ -562,7 +607,7 @@
   int color_offset_location_;
 };
 
-class FragmentShaderRGBATexAlphaColorMatrixAA {
+class FragmentShaderRGBATexAlphaColorMatrixAA : public FragmentTexBlendMode {
  public:
   FragmentShaderRGBATexAlphaColorMatrixAA();
   std::string GetShaderString(
@@ -583,7 +628,7 @@
   int color_offset_location_;
 };
 
-class FragmentShaderRGBATexAlphaMaskColorMatrix {
+class FragmentShaderRGBATexAlphaMaskColorMatrix : public FragmentTexBlendMode {
  public:
   FragmentShaderRGBATexAlphaMaskColorMatrix();
   std::string GetShaderString(
@@ -614,7 +659,7 @@
   int color_offset_location_;
 };
 
-class FragmentShaderYUVVideo {
+class FragmentShaderYUVVideo : public FragmentTexBlendMode {
  public:
   FragmentShaderYUVVideo();
   std::string GetShaderString(
@@ -641,8 +686,7 @@
   DISALLOW_COPY_AND_ASSIGN(FragmentShaderYUVVideo);
 };
 
-
-class FragmentShaderYUVAVideo {
+class FragmentShaderYUVAVideo : public FragmentTexBlendMode {
  public:
   FragmentShaderYUVAVideo();
   std::string GetShaderString(
@@ -672,7 +716,7 @@
   DISALLOW_COPY_AND_ASSIGN(FragmentShaderYUVAVideo);
 };
 
-class FragmentShaderColor {
+class FragmentShaderColor : public FragmentTexBlendMode {
  public:
   FragmentShaderColor();
   std::string GetShaderString(
@@ -689,7 +733,7 @@
   DISALLOW_COPY_AND_ASSIGN(FragmentShaderColor);
 };
 
-class FragmentShaderColorAA {
+class FragmentShaderColorAA : public FragmentTexBlendMode {
  public:
   FragmentShaderColorAA();
   std::string GetShaderString(
@@ -706,7 +750,7 @@
   DISALLOW_COPY_AND_ASSIGN(FragmentShaderColorAA);
 };
 
-class FragmentShaderCheckerboard {
+class FragmentShaderCheckerboard : public FragmentTexBlendMode {
  public:
   FragmentShaderCheckerboard();
   std::string GetShaderString(
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index c3cb828..acc897f 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -239,14 +239,16 @@
   current_canvas_->setMatrix(sk_device_matrix);
 
   current_paint_.reset();
-  if (!IsScaleAndIntegerTranslate(sk_device_matrix)) {
+  if (settings_->force_antialiasing ||
+      !IsScaleAndIntegerTranslate(sk_device_matrix)) {
     // TODO(danakj): Until we can enable AA only on exterior edges of the
     // layer, disable AA if any interior edges are present. crbug.com/248175
     bool all_four_edges_are_exterior = quad->IsTopEdge() &&
                                        quad->IsLeftEdge() &&
                                        quad->IsBottomEdge() &&
                                        quad->IsRightEdge();
-    if (settings_->allow_antialiasing && all_four_edges_are_exterior)
+    if (settings_->allow_antialiasing &&
+        (settings_->force_antialiasing || all_four_edges_are_exterior))
       current_paint_.setAntiAlias(true);
     current_paint_.setFilterLevel(SkPaint::kLow_FilterLevel);
   }
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc
index 1e373b2..60f75d9 100644
--- a/cc/output/software_renderer_unittest.cc
+++ b/cc/output/software_renderer_unittest.cc
@@ -42,8 +42,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false);
+                                                  1);
     renderer_ = SoftwareRenderer::Create(
         this, &settings_, output_surface_.get(), resource_provider());
   }
diff --git a/cc/resources/gpu_raster_worker_pool.cc b/cc/resources/gpu_raster_worker_pool.cc
index a0bc86f..cba427e 100644
--- a/cc/resources/gpu_raster_worker_pool.cc
+++ b/cc/resources/gpu_raster_worker_pool.cc
@@ -26,17 +26,25 @@
  public:
   RasterBufferImpl(ResourceProvider* resource_provider,
                    const Resource* resource,
-                   SkMultiPictureDraw* multi_picture_draw)
+                   SkMultiPictureDraw* multi_picture_draw,
+                   bool use_distance_field_text)
       : lock_(resource_provider, resource->id()),
         resource_(resource),
-        multi_picture_draw_(multi_picture_draw) {}
+        multi_picture_draw_(multi_picture_draw),
+        use_distance_field_text_(use_distance_field_text) {}
 
   // Overridden from RasterBuffer:
   void Playback(const PicturePileImpl* picture_pile,
                 const gfx::Rect& rect,
                 float scale,
                 RenderingStatsInstrumentation* stats) override {
-    if (!lock_.sk_surface())
+    // Turn on distance fields for layers that have ever animated.
+    bool use_distance_field_text =
+        use_distance_field_text_ ||
+        picture_pile->likely_to_be_used_for_transform_animation();
+    SkSurface* sk_surface = lock_.GetSkSurface(use_distance_field_text);
+
+    if (!sk_surface)
       return;
 
     SkPictureRecorder recorder;
@@ -50,13 +58,14 @@
 
     // Add the canvas and recorded picture to |multi_picture_draw_|.
     skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
-    multi_picture_draw_->add(lock_.sk_surface()->getCanvas(), picture.get());
+    multi_picture_draw_->add(sk_surface->getCanvas(), picture.get());
   }
 
  private:
   ResourceProvider::ScopedWriteLockGr lock_;
   const Resource* resource_;
   SkMultiPictureDraw* multi_picture_draw_;
+  bool use_distance_field_text_;
 
   DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
 };
@@ -67,20 +76,26 @@
 scoped_ptr<RasterWorkerPool> GpuRasterWorkerPool::Create(
     base::SequencedTaskRunner* task_runner,
     ContextProvider* context_provider,
-    ResourceProvider* resource_provider) {
-  return make_scoped_ptr<RasterWorkerPool>(new GpuRasterWorkerPool(
-      task_runner, context_provider, resource_provider));
+    ResourceProvider* resource_provider,
+    bool use_distance_field_text) {
+  return make_scoped_ptr<RasterWorkerPool>(
+      new GpuRasterWorkerPool(task_runner,
+                              context_provider,
+                              resource_provider,
+                              use_distance_field_text));
 }
 
 GpuRasterWorkerPool::GpuRasterWorkerPool(base::SequencedTaskRunner* task_runner,
                                          ContextProvider* context_provider,
-                                         ResourceProvider* resource_provider)
+                                         ResourceProvider* resource_provider,
+                                         bool use_distance_field_text)
     : task_runner_(task_runner),
       task_graph_runner_(new TaskGraphRunner),
       namespace_token_(task_graph_runner_->GetNamespaceToken()),
       context_provider_(context_provider),
       resource_provider_(resource_provider),
       run_tasks_on_origin_thread_pending_(false),
+      use_distance_field_text_(use_distance_field_text),
       raster_finished_weak_ptr_factory_(this),
       weak_ptr_factory_(this) {
   DCHECK(context_provider_);
@@ -190,7 +205,10 @@
 scoped_ptr<RasterBuffer> GpuRasterWorkerPool::AcquireBufferForRaster(
     const Resource* resource) {
   return make_scoped_ptr<RasterBuffer>(
-      new RasterBufferImpl(resource_provider_, resource, &multi_picture_draw_));
+      new RasterBufferImpl(resource_provider_,
+                           resource,
+                           &multi_picture_draw_,
+                           use_distance_field_text_));
 }
 
 void GpuRasterWorkerPool::ReleaseBufferForRaster(
diff --git a/cc/resources/gpu_raster_worker_pool.h b/cc/resources/gpu_raster_worker_pool.h
index a4e4197..c5ff13f 100644
--- a/cc/resources/gpu_raster_worker_pool.h
+++ b/cc/resources/gpu_raster_worker_pool.h
@@ -23,7 +23,8 @@
   static scoped_ptr<RasterWorkerPool> Create(
       base::SequencedTaskRunner* task_runner,
       ContextProvider* context_provider,
-      ResourceProvider* resource_provider);
+      ResourceProvider* resource_provider,
+      bool use_distance_field_text);
 
   // Overridden from RasterWorkerPool:
   Rasterizer* AsRasterizer() override;
@@ -42,7 +43,8 @@
  private:
   GpuRasterWorkerPool(base::SequencedTaskRunner* task_runner,
                       ContextProvider* context_provider,
-                      ResourceProvider* resource_provider);
+                      ResourceProvider* resource_provider,
+                      bool use_distance_field_text);
 
   void OnRasterFinished(TaskSet task_set);
   void ScheduleRunTasksOnOriginThread();
@@ -58,6 +60,7 @@
   SkMultiPictureDraw multi_picture_draw_;
 
   bool run_tasks_on_origin_thread_pending_;
+  bool use_distance_field_text_;
 
   TaskSetCollection raster_pending_;
 
diff --git a/cc/resources/picture_layer_tiling_perftest.cc b/cc/resources/picture_layer_tiling_perftest.cc
index 9cc3a59..8f91763 100644
--- a/cc/resources/picture_layer_tiling_perftest.cc
+++ b/cc/resources/picture_layer_tiling_perftest.cc
@@ -40,8 +40,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false).Pass();
+                                                  1).Pass();
   }
 
   virtual void SetUp() override {
diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc
index 1806ebc..96b47a6 100644
--- a/cc/resources/picture_layer_tiling_set.cc
+++ b/cc/resources/picture_layer_tiling_set.cc
@@ -19,12 +19,8 @@
 
 }  // namespace
 
-
-PictureLayerTilingSet::PictureLayerTilingSet(
-    PictureLayerTilingClient* client,
-    const gfx::Size& layer_bounds)
-    : client_(client),
-      layer_bounds_(layer_bounds) {
+PictureLayerTilingSet::PictureLayerTilingSet(PictureLayerTilingClient* client)
+    : client_(client) {
 }
 
 PictureLayerTilingSet::~PictureLayerTilingSet() {
@@ -47,7 +43,6 @@
                                         float minimum_contents_scale) {
   if (new_layer_bounds.IsEmpty()) {
     RemoveAllTilings();
-    layer_bounds_ = new_layer_bounds;
     return false;
   }
 
@@ -99,17 +94,17 @@
   }
   tilings_.sort(LargestToSmallestScaleFunctor());
 
-  layer_bounds_ = new_layer_bounds;
   return have_high_res_tiling;
 }
 
-PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
+PictureLayerTiling* PictureLayerTilingSet::AddTiling(
+    float contents_scale,
+    const gfx::Size& layer_bounds) {
   for (size_t i = 0; i < tilings_.size(); ++i)
     DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
 
-  tilings_.push_back(PictureLayerTiling::Create(contents_scale,
-                                                layer_bounds_,
-                                                client_));
+  tilings_.push_back(
+      PictureLayerTiling::Create(contents_scale, layer_bounds, client_));
   PictureLayerTiling* appended = tilings_.back();
 
   tilings_.sort(LargestToSmallestScaleFunctor());
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h
index 63f3110..6f61243 100644
--- a/cc/resources/picture_layer_tiling_set.h
+++ b/cc/resources/picture_layer_tiling_set.h
@@ -34,8 +34,7 @@
     size_t end;
   };
 
-  PictureLayerTilingSet(PictureLayerTilingClient* client,
-                        const gfx::Size& layer_bounds);
+  explicit PictureLayerTilingSet(PictureLayerTilingClient* client);
   ~PictureLayerTilingSet();
 
   void SetClient(PictureLayerTilingClient* client);
@@ -53,9 +52,8 @@
                    const Region& layer_invalidation,
                    float minimum_contents_scale);
 
-  gfx::Size layer_bounds() const { return layer_bounds_; }
-
-  PictureLayerTiling* AddTiling(float contents_scale);
+  PictureLayerTiling* AddTiling(float contents_scale,
+                                const gfx::Size& layer_bounds);
   size_t num_tilings() const { return tilings_.size(); }
   int NumHighResTilings() const;
   PictureLayerTiling* tiling_at(size_t idx) { return tilings_[idx]; }
@@ -126,7 +124,6 @@
 
  private:
   PictureLayerTilingClient* client_;
-  gfx::Size layer_bounds_;
   ScopedPtrVector<PictureLayerTiling> tilings_;
 
   friend class Iterator;
diff --git a/cc/resources/picture_layer_tiling_set_unittest.cc b/cc/resources/picture_layer_tiling_set_unittest.cc
index f4059e4..3d249f3 100644
--- a/cc/resources/picture_layer_tiling_set_unittest.cc
+++ b/cc/resources/picture_layer_tiling_set_unittest.cc
@@ -23,12 +23,12 @@
 TEST(PictureLayerTilingSetTest, NoResources) {
   FakePictureLayerTilingClient client;
   gfx::Size layer_bounds(1000, 800);
-  PictureLayerTilingSet set(&client, layer_bounds);
+  PictureLayerTilingSet set(&client);
   client.SetTileSize(gfx::Size(256, 256));
 
-  set.AddTiling(1.0);
-  set.AddTiling(1.5);
-  set.AddTiling(2.0);
+  set.AddTiling(1.0, layer_bounds);
+  set.AddTiling(1.5, layer_bounds);
+  set.AddTiling(2.0, layer_bounds);
 
   float contents_scale = 2.0;
   gfx::Size content_bounds(
@@ -64,14 +64,14 @@
   PictureLayerTiling* high_res_tiling;
   PictureLayerTiling* low_res_tiling;
 
-  PictureLayerTilingSet set(&client, layer_bounds);
-  set.AddTiling(2.0);
-  high_res_tiling = set.AddTiling(1.0);
+  PictureLayerTilingSet set(&client);
+  set.AddTiling(2.0, layer_bounds);
+  high_res_tiling = set.AddTiling(1.0, layer_bounds);
   high_res_tiling->set_resolution(HIGH_RESOLUTION);
-  set.AddTiling(0.5);
-  low_res_tiling = set.AddTiling(0.25);
+  set.AddTiling(0.5, layer_bounds);
+  low_res_tiling = set.AddTiling(0.25, layer_bounds);
   low_res_tiling->set_resolution(LOW_RESOLUTION);
-  set.AddTiling(0.125);
+  set.AddTiling(0.125, layer_bounds);
 
   higher_than_high_res_range =
       set.GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
@@ -96,12 +96,12 @@
   EXPECT_EQ(4u, lower_than_low_res_range.start);
   EXPECT_EQ(5u, lower_than_low_res_range.end);
 
-  PictureLayerTilingSet set_without_low_res(&client, layer_bounds);
-  set_without_low_res.AddTiling(2.0);
-  high_res_tiling = set_without_low_res.AddTiling(1.0);
+  PictureLayerTilingSet set_without_low_res(&client);
+  set_without_low_res.AddTiling(2.0, layer_bounds);
+  high_res_tiling = set_without_low_res.AddTiling(1.0, layer_bounds);
   high_res_tiling->set_resolution(HIGH_RESOLUTION);
-  set_without_low_res.AddTiling(0.5);
-  set_without_low_res.AddTiling(0.25);
+  set_without_low_res.AddTiling(0.5, layer_bounds);
+  set_without_low_res.AddTiling(0.25, layer_bounds);
 
   higher_than_high_res_range = set_without_low_res.GetTilingRange(
       PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
@@ -126,10 +126,10 @@
       PictureLayerTilingSet::LOWER_THAN_LOW_RES);
   EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start);
 
-  PictureLayerTilingSet set_with_only_high_and_low_res(&client, layer_bounds);
-  high_res_tiling = set_with_only_high_and_low_res.AddTiling(1.0);
+  PictureLayerTilingSet set_with_only_high_and_low_res(&client);
+  high_res_tiling = set_with_only_high_and_low_res.AddTiling(1.0, layer_bounds);
   high_res_tiling->set_resolution(HIGH_RESOLUTION);
-  low_res_tiling = set_with_only_high_and_low_res.AddTiling(0.5);
+  low_res_tiling = set_with_only_high_and_low_res.AddTiling(0.5, layer_bounds);
   low_res_tiling->set_resolution(LOW_RESOLUTION);
 
   higher_than_high_res_range = set_with_only_high_and_low_res.GetTilingRange(
@@ -158,8 +158,8 @@
       PictureLayerTilingSet::LOWER_THAN_LOW_RES);
   EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start);
 
-  PictureLayerTilingSet set_with_only_high_res(&client, layer_bounds);
-  high_res_tiling = set_with_only_high_res.AddTiling(1.0);
+  PictureLayerTilingSet set_with_only_high_res(&client);
+  high_res_tiling = set_with_only_high_res.AddTiling(1.0, layer_bounds);
   high_res_tiling->set_resolution(HIGH_RESOLUTION);
 
   higher_than_high_res_range = set_with_only_high_res.GetTilingRange(
@@ -209,18 +209,17 @@
                                  NULL,
                                  0,
                                  false,
-                                 1,
-                                 false);
+                                 1);
 
     FakePictureLayerTilingClient client(resource_provider.get());
     client.SetTileSize(gfx::Size(256, 256));
     client.set_tree(PENDING_TREE);
     gfx::Size layer_bounds(1000, 800);
-    PictureLayerTilingSet set(&client, layer_bounds);
+    PictureLayerTilingSet set(&client);
 
     float scale = min_scale;
     for (int i = 0; i < num_tilings; ++i, scale += scale_increment) {
-      PictureLayerTiling* tiling = set.AddTiling(scale);
+      PictureLayerTiling* tiling = set.AddTiling(scale, layer_bounds);
       tiling->CreateAllTilesForTesting();
       std::vector<Tile*> tiles = tiling->AllTilesForTesting();
       client.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
@@ -298,8 +297,8 @@
     source_client_.set_tree(PENDING_TREE);
     target_client_.SetTileSize(tile_size_);
     target_client_.set_tree(PENDING_TREE);
-    source_.reset(new PictureLayerTilingSet(&source_client_, source_bounds_));
-    target_.reset(new PictureLayerTilingSet(&target_client_, target_bounds_));
+    source_.reset(new PictureLayerTilingSet(&source_client_));
+    target_.reset(new PictureLayerTilingSet(&target_client_));
   }
 
   // Sync from source to target.
@@ -329,7 +328,6 @@
   void VerifyTargetEqualsSource(const gfx::Size& new_bounds) {
     ASSERT_FALSE(new_bounds.IsEmpty());
     EXPECT_EQ(target_->num_tilings(), source_->num_tilings());
-    EXPECT_EQ(target_->layer_bounds().ToString(), new_bounds.ToString());
 
     for (size_t i = 0; i < target_->num_tilings(); ++i) {
       ASSERT_GT(source_->num_tilings(), i);
@@ -404,21 +402,20 @@
 TEST_F(PictureLayerTilingSetSyncTest, EmptyBounds) {
   float source_scales[] = {1.f, 1.2f};
   for (size_t i = 0; i < arraysize(source_scales); ++i)
-    source_->AddTiling(source_scales[i]);
+    source_->AddTiling(source_scales[i], source_bounds_);
 
-  gfx::Size new_bounds;
-  SyncTilings(new_bounds);
+  gfx::Size empty_bounds;
+  SyncTilings(empty_bounds);
   EXPECT_EQ(target_->num_tilings(), 0u);
-  EXPECT_EQ(target_->layer_bounds().ToString(), new_bounds.ToString());
 }
 
 TEST_F(PictureLayerTilingSetSyncTest, AllNew) {
   float source_scales[] = {0.5f, 1.f, 1.2f};
   for (size_t i = 0; i < arraysize(source_scales); ++i)
-    source_->AddTiling(source_scales[i]);
+    source_->AddTiling(source_scales[i], source_bounds_);
   float target_scales[] = {0.75f, 1.4f, 3.f};
   for (size_t i = 0; i < arraysize(target_scales); ++i)
-    target_->AddTiling(target_scales[i]);
+    target_->AddTiling(target_scales[i], target_bounds_);
 
   gfx::Size new_bounds(15, 40);
   SyncTilings(new_bounds);
@@ -437,10 +434,10 @@
 TEST_F(PictureLayerTilingSetSyncTest, KeepExisting) {
   float source_scales[] = {0.7f, 1.f, 1.1f, 2.f};
   for (size_t i = 0; i < arraysize(source_scales); ++i)
-    source_->AddTiling(source_scales[i]);
+    source_->AddTiling(source_scales[i], source_bounds_);
   float target_scales[] = {0.5f, 1.f, 2.f};
   for (size_t i = 0; i < arraysize(target_scales); ++i)
-    target_->AddTiling(target_scales[i]);
+    target_->AddTiling(target_scales[i], target_bounds_);
 
   PictureLayerTiling* tiling1 = source_->TilingAtScale(1.f);
   ASSERT_TRUE(tiling1);
@@ -472,7 +469,7 @@
 TEST_F(PictureLayerTilingSetSyncTest, EmptySet) {
   float target_scales[] = {0.2f, 1.f};
   for (size_t i = 0; i < arraysize(target_scales); ++i)
-    target_->AddTiling(target_scales[i]);
+    target_->AddTiling(target_scales[i], target_bounds_);
 
   gfx::Size new_bounds(15, 40);
   SyncTilings(new_bounds);
@@ -482,10 +479,10 @@
 TEST_F(PictureLayerTilingSetSyncTest, MinimumScale) {
   float source_scales[] = {0.7f, 1.f, 1.1f, 2.f};
   for (size_t i = 0; i < arraysize(source_scales); ++i)
-    source_->AddTiling(source_scales[i]);
+    source_->AddTiling(source_scales[i], source_bounds_);
   float target_scales[] = {0.5f, 0.7f, 1.f, 1.1f, 2.f};
   for (size_t i = 0; i < arraysize(target_scales); ++i)
-    target_->AddTiling(target_scales[i]);
+    target_->AddTiling(target_scales[i], target_bounds_);
 
   gfx::Size new_bounds(15, 40);
   float minimum_scale = 1.5f;
@@ -497,8 +494,8 @@
 }
 
 TEST_F(PictureLayerTilingSetSyncTest, Invalidation) {
-  source_->AddTiling(2.f);
-  target_->AddTiling(2.f);
+  source_->AddTiling(2.f, source_bounds_);
+  target_->AddTiling(2.f, target_bounds_);
   target_->tiling_at(0)->CreateAllTilesForTesting();
 
   Region layer_invalidation;
@@ -535,8 +532,8 @@
 }
 
 TEST_F(PictureLayerTilingSetSyncTest, TileSizeChange) {
-  source_->AddTiling(1.f);
-  target_->AddTiling(1.f);
+  source_->AddTiling(1.f, source_bounds_);
+  target_->AddTiling(1.f, target_bounds_);
 
   target_->tiling_at(0)->CreateAllTilesForTesting();
   std::vector<Tile*> original_tiles =
diff --git a/cc/resources/picture_layer_tiling_unittest.cc b/cc/resources/picture_layer_tiling_unittest.cc
index c871da4..07da353 100644
--- a/cc/resources/picture_layer_tiling_unittest.cc
+++ b/cc/resources/picture_layer_tiling_unittest.cc
@@ -1262,15 +1262,8 @@
   scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
   CHECK(output_surface->BindToClient(&output_surface_client));
   TestSharedBitmapManager shared_bitmap_manager;
-  scoped_ptr<ResourceProvider> resource_provider =
-      ResourceProvider::Create(output_surface.get(),
-                               &shared_bitmap_manager,
-                               NULL,
-                               NULL,
-                               0,
-                               false,
-                               1,
-                               false);
+  scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
+      output_surface.get(), &shared_bitmap_manager, NULL, NULL, 0, false, 1);
 
   FakePictureLayerTilingClient client(resource_provider.get());
   scoped_ptr<TestablePictureLayerTiling> tiling;
@@ -1463,9 +1456,9 @@
   client_.SetTileSize(tile_size);
   client_.set_tree(PENDING_TREE);
 
-  PictureLayerTilingSet active_set(&client_, layer_bounds);
+  PictureLayerTilingSet active_set(&client_);
 
-  active_set.AddTiling(1.f);
+  active_set.AddTiling(1.f, layer_bounds);
 
   VerifyTiles(active_set.tiling_at(0),
               1.f,
@@ -1485,7 +1478,7 @@
               base::Bind(&TileExists, true));
 
   // Add the same tilings to the pending set.
-  PictureLayerTilingSet pending_set(&client_, layer_bounds);
+  PictureLayerTilingSet pending_set(&client_);
   Region invalidation;
   pending_set.SyncTilings(active_set, layer_bounds, invalidation, 0.f);
 
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc
index f4fbdf2..e19dd2c 100644
--- a/cc/resources/picture_pile_impl.cc
+++ b/cc/resources/picture_pile_impl.cc
@@ -28,11 +28,13 @@
   return make_scoped_refptr(new PicturePileImpl(other));
 }
 
-PicturePileImpl::PicturePileImpl() {
+PicturePileImpl::PicturePileImpl()
+    : likely_to_be_used_for_transform_animation_(false) {
 }
 
 PicturePileImpl::PicturePileImpl(const PicturePileBase* other)
-    : PicturePileBase(other) {
+    : PicturePileBase(other),
+      likely_to_be_used_for_transform_animation_(false) {
 }
 
 PicturePileImpl::~PicturePileImpl() {
diff --git a/cc/resources/picture_pile_impl.h b/cc/resources/picture_pile_impl.h
index a9bef0c..243601e 100644
--- a/cc/resources/picture_pile_impl.h
+++ b/cc/resources/picture_pile_impl.h
@@ -58,6 +58,13 @@
 
   skia::RefPtr<SkPicture> GetFlattenedPicture();
 
+  bool likely_to_be_used_for_transform_animation() const {
+    return likely_to_be_used_for_transform_animation_;
+  }
+  void set_likely_to_be_used_for_transform_animation() {
+    likely_to_be_used_for_transform_animation_ = true;
+  }
+
   struct CC_EXPORT Analysis {
     Analysis();
     ~Analysis();
@@ -124,6 +131,8 @@
       RenderingStatsInstrumentation* rendering_stats_instrumentation,
       bool is_analysis) const;
 
+  bool likely_to_be_used_for_transform_animation_;
+
   DISALLOW_COPY_AND_ASSIGN(PicturePileImpl);
 };
 
diff --git a/cc/resources/prioritized_resource_unittest.cc b/cc/resources/prioritized_resource_unittest.cc
index 5109a60..8869e70 100644
--- a/cc/resources/prioritized_resource_unittest.cc
+++ b/cc/resources/prioritized_resource_unittest.cc
@@ -34,8 +34,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false);
+                                                  1);
   }
 
   virtual ~PrioritizedResourceTest() {
diff --git a/cc/resources/raster_worker_pool_perftest.cc b/cc/resources/raster_worker_pool_perftest.cc
index 4264373..0f7a845 100644
--- a/cc/resources/raster_worker_pool_perftest.cc
+++ b/cc/resources/raster_worker_pool_perftest.cc
@@ -262,7 +262,8 @@
         raster_worker_pool_ =
             GpuRasterWorkerPool::Create(task_runner_.get(),
                                         context_provider_.get(),
-                                        resource_provider_.get());
+                                        resource_provider_.get(),
+                                        false);
         break;
       case RASTER_WORKER_POOL_TYPE_BITMAP:
         CreateSoftwareOutputSurfaceAndResourceProvider();
@@ -406,8 +407,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false).Pass();
+                                                  1).Pass();
   }
 
   void CreateSoftwareOutputSurfaceAndResourceProvider() {
@@ -420,8 +420,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false).Pass();
+                                                  1).Pass();
   }
 
   std::string TestModifierString() const {
@@ -491,7 +490,7 @@
     CHECK(output_surface_->BindToClient(&output_surface_client_));
     resource_provider_ =
         ResourceProvider::Create(
-            output_surface_.get(), NULL, NULL, NULL, 0, false, 1, false).Pass();
+            output_surface_.get(), NULL, NULL, NULL, 0, false, 1).Pass();
   }
 
   void RunBuildRasterTaskQueueTest(const std::string& test_name,
diff --git a/cc/resources/raster_worker_pool_unittest.cc b/cc/resources/raster_worker_pool_unittest.cc
index 2227128..a6d6c65 100644
--- a/cc/resources/raster_worker_pool_unittest.cc
+++ b/cc/resources/raster_worker_pool_unittest.cc
@@ -164,7 +164,8 @@
         raster_worker_pool_ =
             GpuRasterWorkerPool::Create(base::MessageLoopProxy::current().get(),
                                         context_provider_.get(),
-                                        resource_provider_.get());
+                                        resource_provider_.get(),
+                                        false);
         break;
       case RASTER_WORKER_POOL_TYPE_BITMAP:
         CreateSoftwareOutputSurfaceAndResourceProvider();
@@ -279,8 +280,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false).Pass();
+                                                  1).Pass();
   }
 
   void CreateSoftwareOutputSurfaceAndResourceProvider() {
@@ -293,8 +293,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false).Pass();
+                                                  1).Pass();
   }
 
   void OnTaskCompleted(scoped_ptr<ScopedResource> resource,
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 1697ac2..550475b 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -411,8 +411,7 @@
     BlockingTaskRunner* blocking_main_thread_task_runner,
     int highp_threshold_min,
     bool use_rgba_4444_texture_format,
-    size_t id_allocation_chunk_size,
-    bool use_distance_field_text) {
+    size_t id_allocation_chunk_size) {
   scoped_ptr<ResourceProvider> resource_provider(
       new ResourceProvider(output_surface,
                            shared_bitmap_manager,
@@ -420,8 +419,7 @@
                            blocking_main_thread_task_runner,
                            highp_threshold_min,
                            use_rgba_4444_texture_format,
-                           id_allocation_chunk_size,
-                           use_distance_field_text));
+                           id_allocation_chunk_size));
 
   if (resource_provider->ContextGL())
     resource_provider->InitializeGL();
@@ -995,38 +993,12 @@
   resource->read_lock_fences_enabled = true;
 }
 
-const ResourceProvider::Resource* ResourceProvider::LockForWriteToSkSurface(
-    ResourceId id) {
+void ResourceProvider::LockForWriteToSkSurface(ResourceId id) {
   Resource* resource = GetResource(id);
   DCHECK_EQ(GLTexture, resource->type);
   DCHECK(CanLockForWrite(id));
 
   resource->locked_for_write = true;
-  if (!resource->sk_surface) {
-    class GrContext* gr_context = GrContext();
-    // TODO(alokp): Implement TestContextProvider::GrContext().
-    if (!gr_context)
-      return resource;
-
-    LazyAllocate(resource);
-
-    GrBackendTextureDesc desc;
-    desc.fFlags = kRenderTarget_GrBackendTextureFlag;
-    desc.fWidth = resource->size.width();
-    desc.fHeight = resource->size.height();
-    desc.fConfig = ToGrPixelConfig(resource->format);
-    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
-    desc.fTextureHandle = resource->gl_id;
-    skia::RefPtr<GrTexture> gr_texture =
-        skia::AdoptRef(gr_context->wrapBackendTexture(desc));
-    SkSurface::TextRenderMode text_render_mode =
-        use_distance_field_text_ ? SkSurface::kDistanceField_TextRenderMode
-                                 : SkSurface::kStandard_TextRenderMode;
-    resource->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
-        gr_texture->asRenderTarget(), text_render_mode));
-  }
-
-  return resource;
 }
 
 void ResourceProvider::UnlockForWriteToSkSurface(ResourceId id) {
@@ -1141,16 +1113,49 @@
 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
     ResourceProvider* resource_provider,
     ResourceProvider::ResourceId resource_id)
-    : resource_provider_(resource_provider),
-      resource_id_(resource_id),
-      sk_surface_(resource_provider->LockForWriteToSkSurface(resource_id)
-                      ->sk_surface.get()) {
+    : resource_provider_(resource_provider), resource_id_(resource_id) {
+  resource_provider->LockForWriteToSkSurface(resource_id);
 }
 
 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
   resource_provider_->UnlockForWriteToSkSurface(resource_id_);
 }
 
+SkSurface* ResourceProvider::ScopedWriteLockGr::GetSkSurface(
+    bool use_distance_field_text) {
+  Resource* resource = resource_provider_->GetResource(resource_id_);
+  DCHECK(resource->locked_for_write);
+
+  // If the surface doesn't exist, or doesn't have the correct dff setting,
+  // recreate the surface within the resource.
+  if (!resource->sk_surface ||
+      use_distance_field_text !=
+          resource->sk_surface->props().isUseDistanceFieldFonts()) {
+    class GrContext* gr_context = resource_provider_->GrContext();
+    // TODO(alokp): Implement TestContextProvider::GrContext().
+    if (!gr_context)
+      return nullptr;
+
+    resource_provider_->LazyAllocate(resource);
+
+    GrBackendTextureDesc desc;
+    desc.fFlags = kRenderTarget_GrBackendTextureFlag;
+    desc.fWidth = resource->size.width();
+    desc.fHeight = resource->size.height();
+    desc.fConfig = ToGrPixelConfig(resource->format);
+    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
+    desc.fTextureHandle = resource->gl_id;
+    skia::RefPtr<GrTexture> gr_texture =
+        skia::AdoptRef(gr_context->wrapBackendTexture(desc));
+    SkSurface::TextRenderMode text_render_mode =
+        use_distance_field_text ? SkSurface::kDistanceField_TextRenderMode
+                                : SkSurface::kStandard_TextRenderMode;
+    resource->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
+        gr_texture->asRenderTarget(), text_render_mode));
+  }
+  return resource->sk_surface.get();
+}
+
 ResourceProvider::ResourceProvider(
     OutputSurface* output_surface,
     SharedBitmapManager* shared_bitmap_manager,
@@ -1158,8 +1163,7 @@
     BlockingTaskRunner* blocking_main_thread_task_runner,
     int highp_threshold_min,
     bool use_rgba_4444_texture_format,
-    size_t id_allocation_chunk_size,
-    bool use_distance_field_text)
+    size_t id_allocation_chunk_size)
     : output_surface_(output_surface),
       shared_bitmap_manager_(shared_bitmap_manager),
       gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
@@ -1177,8 +1181,7 @@
       best_texture_format_(RGBA_8888),
       use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
       id_allocation_chunk_size_(id_allocation_chunk_size),
-      use_sync_query_(false),
-      use_distance_field_text_(use_distance_field_text) {
+      use_sync_query_(false) {
   DCHECK(output_surface_->HasClient());
   DCHECK(id_allocation_chunk_size_);
 }
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index 1e70132..fbec8d1 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -83,8 +83,7 @@
       BlockingTaskRunner* blocking_main_thread_task_runner,
       int highp_threshold_min,
       bool use_rgba_4444_texture_format,
-      size_t id_allocation_chunk_size,
-      bool use_distance_field_text);
+      size_t id_allocation_chunk_size);
   virtual ~ResourceProvider();
 
   void InitializeSoftware();
@@ -328,12 +327,11 @@
                       ResourceProvider::ResourceId resource_id);
     ~ScopedWriteLockGr();
 
-    SkSurface* sk_surface() { return sk_surface_; }
+    SkSurface* GetSkSurface(bool use_distance_field_text);
 
    private:
     ResourceProvider* resource_provider_;
     ResourceProvider::ResourceId resource_id_;
-    SkSurface* sk_surface_;
 
     DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGr);
   };
@@ -488,8 +486,7 @@
                    BlockingTaskRunner* blocking_main_thread_task_runner,
                    int highp_threshold_min,
                    bool use_rgba_4444_texture_format,
-                   size_t id_allocation_chunk_size,
-                   bool use_distance_field_text);
+                   size_t id_allocation_chunk_size);
 
   void CleanUpGLIfNeeded();
 
@@ -500,7 +497,7 @@
   void UnlockForWrite(ResourceId id);
   const Resource* LockForWriteToGpuMemoryBuffer(ResourceId id);
   void UnlockForWriteToGpuMemoryBuffer(ResourceId id);
-  const Resource* LockForWriteToSkSurface(ResourceId id);
+  void LockForWriteToSkSurface(ResourceId id);
   void UnlockForWriteToSkSurface(ResourceId id);
 
   static void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
@@ -562,8 +559,6 @@
 
   bool use_sync_query_;
 
-  bool use_distance_field_text_;
-
   DISALLOW_COPY_AND_ASSIGN(ResourceProvider);
 };
 
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index 3aea34f..2c585c4 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -423,8 +423,7 @@
                                  main_thread_task_runner_.get(),
                                  0,
                                  false,
-                                 1,
-                                 false);
+                                 1);
     child_resource_provider_ =
         ResourceProvider::Create(child_output_surface_.get(),
                                  shared_bitmap_manager_.get(),
@@ -432,8 +431,7 @@
                                  main_thread_task_runner_.get(),
                                  0,
                                  false,
-                                 1,
-                                 false);
+                                 1);
   }
 
   static void CollectResources(ReturnedResourceArray* array,
@@ -1168,8 +1166,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
@@ -1651,8 +1648,7 @@
                                  NULL,
                                  0,
                                  false,
-                                 1,
-                                 false));
+                                 1));
 
     scoped_ptr<TextureStateTrackingContext> parent_context_owned(
         new TextureStateTrackingContext);
@@ -1670,8 +1666,7 @@
                                  NULL,
                                  0,
                                  false,
-                                 1,
-                                 false));
+                                 1));
 
     gfx::Size size(1, 1);
     ResourceFormat format = RGBA_8888;
@@ -2303,8 +2298,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
@@ -2391,8 +2385,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
@@ -2447,8 +2440,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
@@ -2507,8 +2499,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
@@ -2581,8 +2572,7 @@
                                main_thread_task_runner_.get(),
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   uint32 release_sync_point = 0;
   bool lost_resource = false;
@@ -2634,8 +2624,7 @@
                                main_thread_task_runner_.get(),
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   unsigned texture_id = 1;
   uint32 sync_point = 30;
@@ -2720,8 +2709,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   unsigned texture_id = 1;
   uint32 sync_point = 30;
@@ -2796,8 +2784,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   uint32 sync_point = 30;
   unsigned target = GL_TEXTURE_2D;
@@ -2856,8 +2843,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   uint32 sync_point = 0;
   unsigned target = GL_TEXTURE_2D;
@@ -2983,8 +2969,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   gfx::Size size(2, 2);
   gfx::Vector2d offset(0, 0);
@@ -3064,8 +3049,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   gfx::Size size(2, 2);
 
@@ -3125,8 +3109,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   gfx::Size size(2, 2);
   const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
@@ -3185,8 +3168,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   id = resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
@@ -3233,8 +3215,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   id = resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
@@ -3281,8 +3262,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
 
@@ -3327,8 +3307,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   id = resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
@@ -3415,8 +3394,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   source_id = resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
@@ -3498,8 +3476,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
 
   CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
 
@@ -3538,8 +3515,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
   int texture_id = 123;
 
   ResourceProvider::ResourceId id = resource_provider->CreateResource(
@@ -3575,8 +3551,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
   int texture_id = 123;
   uint8_t pixels[8];
 
@@ -3637,8 +3612,7 @@
                                  NULL,
                                  0,
                                  false,
-                                 kTextureAllocationChunkSize,
-                                 false));
+                                 kTextureAllocationChunkSize));
 
     ResourceProvider::ResourceId id = resource_provider->CreateResource(
         size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
@@ -3658,8 +3632,7 @@
                                  NULL,
                                  0,
                                  false,
-                                 kTextureAllocationChunkSize,
-                                 false));
+                                 kTextureAllocationChunkSize));
 
     ResourceProvider::ResourceId id = resource_provider->CreateResource(
         size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
diff --git a/cc/resources/resource_update_controller_unittest.cc b/cc/resources/resource_update_controller_unittest.cc
index 49f7b47..d6b4f39 100644
--- a/cc/resources/resource_update_controller_unittest.cc
+++ b/cc/resources/resource_update_controller_unittest.cc
@@ -130,8 +130,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false);
+                                                  1);
   }
 
   void AppendFullUploadsOfIndexedTextureToUpdateQueue(int count,
diff --git a/cc/resources/scoped_resource_unittest.cc b/cc/resources/scoped_resource_unittest.cc
index 7c7e055..a141218 100644
--- a/cc/resources/scoped_resource_unittest.cc
+++ b/cc/resources/scoped_resource_unittest.cc
@@ -28,8 +28,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
   scoped_ptr<ScopedResource> texture =
       ScopedResource::Create(resource_provider.get());
 
@@ -55,8 +54,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
   scoped_ptr<ScopedResource> texture =
       ScopedResource::Create(resource_provider.get());
   texture->Allocate(
@@ -85,8 +83,7 @@
                                NULL,
                                0,
                                false,
-                               1,
-                               false));
+                               1));
   {
     scoped_ptr<ScopedResource> texture =
         ScopedResource::Create(resource_provider.get());
diff --git a/cc/resources/tile_manager_unittest.cc b/cc/resources/tile_manager_unittest.cc
index 46f2e14..3671081 100644
--- a/cc/resources/tile_manager_unittest.cc
+++ b/cc/resources/tile_manager_unittest.cc
@@ -157,21 +157,26 @@
   }
 
   EXPECT_EQ(tile_count, all_tiles.size());
-  EXPECT_EQ(17u, tile_count);
+  EXPECT_EQ(16u, tile_count);
 
   // Sanity check, all tiles should be visible.
   std::set<Tile*> smoothness_tiles;
   queue.Reset();
   host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
+  bool had_low_res = false;
   while (!queue.IsEmpty()) {
     Tile* tile = queue.Top();
     EXPECT_TRUE(tile);
     EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin);
     EXPECT_EQ(TilePriority::NOW, tile->priority(PENDING_TREE).priority_bin);
-    smoothness_tiles.insert(tile);
+    if (tile->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION)
+      had_low_res = true;
+    else
+      smoothness_tiles.insert(tile);
     queue.Pop();
   }
   EXPECT_EQ(all_tiles, smoothness_tiles);
+  EXPECT_TRUE(had_low_res);
 
   Region invalidation(gfx::Rect(0, 0, 500, 500));
 
@@ -198,10 +203,13 @@
 
   // Populate all tiles directly from the tilings.
   all_tiles.clear();
+  std::set<Tile*> high_res_tiles;
   std::vector<Tile*> pending_high_res_tiles =
       pending_layer_->HighResTiling()->AllTilesForTesting();
-  for (size_t i = 0; i < pending_high_res_tiles.size(); ++i)
+  for (size_t i = 0; i < pending_high_res_tiles.size(); ++i) {
     all_tiles.insert(pending_high_res_tiles[i]);
+    high_res_tiles.insert(pending_high_res_tiles[i]);
+  }
 
   std::vector<Tile*> pending_low_res_tiles =
       pending_layer_->LowResTiling()->AllTilesForTesting();
@@ -210,8 +218,10 @@
 
   std::vector<Tile*> active_high_res_tiles =
       active_layer_->HighResTiling()->AllTilesForTesting();
-  for (size_t i = 0; i < active_high_res_tiles.size(); ++i)
+  for (size_t i = 0; i < active_high_res_tiles.size(); ++i) {
     all_tiles.insert(active_high_res_tiles[i]);
+    high_res_tiles.insert(active_high_res_tiles[i]);
+  }
 
   std::vector<Tile*> active_low_res_tiles =
       active_layer_->LowResTiling()->AllTilesForTesting();
@@ -275,6 +285,7 @@
   // Here we expect to get increasing PENDING_TREE priority_bin.
   queue.Reset();
   host_impl_.BuildRasterQueue(&queue, NEW_CONTENT_TAKES_PRIORITY);
+  tile_count = 0;
   while (!queue.IsEmpty()) {
     Tile* tile = queue.Top();
     EXPECT_TRUE(tile);
@@ -300,14 +311,15 @@
 
     last_tile = tile;
     new_content_tiles.insert(tile);
+    ++tile_count;
     queue.Pop();
   }
 
   EXPECT_EQ(tile_count, new_content_tiles.size());
-  EXPECT_EQ(all_tiles, new_content_tiles);
+  EXPECT_EQ(high_res_tiles, new_content_tiles);
   // Since we don't guarantee increasing distance due to spiral iterator, we
   // should check that we're _mostly_ right.
-  EXPECT_GT(increasing_distance_tiles, 3 * tile_count / 4);
+  EXPECT_GE(increasing_distance_tiles, 3 * tile_count / 4);
 }
 
 TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
@@ -332,7 +344,7 @@
   }
 
   EXPECT_EQ(tile_count, all_tiles.size());
-  EXPECT_EQ(17u, tile_count);
+  EXPECT_EQ(16u, tile_count);
 
   tile_manager()->InitializeTilesWithResourcesForTesting(
       std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
@@ -507,7 +519,7 @@
     raster_queue.Pop();
   }
   EXPECT_EQ(tile_count, all_tiles.size());
-  EXPECT_EQ(34u, tile_count);
+  EXPECT_EQ(32u, tile_count);
 
   pending_layer_->ResetAllTilesPriorities();
 
@@ -609,7 +621,7 @@
   }
 
   EXPECT_EQ(tile_count, all_tiles.size());
-  EXPECT_EQ(17u, tile_count);
+  EXPECT_EQ(16u, tile_count);
 
   queue.Reset();
   for (int i = 1; i < 10; ++i) {
@@ -633,7 +645,7 @@
     queue.Pop();
   }
   EXPECT_EQ(tile_count, all_tiles.size());
-  EXPECT_EQ(17u, tile_count);
+  EXPECT_EQ(16u, tile_count);
 }
 
 TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueueEmptyLayers) {
@@ -655,7 +667,7 @@
     raster_queue.Pop();
   }
   EXPECT_EQ(tile_count, all_tiles.size());
-  EXPECT_EQ(17u, tile_count);
+  EXPECT_EQ(16u, tile_count);
 
   std::vector<Tile*> tiles(all_tiles.begin(), all_tiles.end());
   host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
@@ -682,7 +694,7 @@
     queue.Pop();
   }
   EXPECT_EQ(tile_count, all_tiles.size());
-  EXPECT_EQ(17u, tile_count);
+  EXPECT_EQ(16u, tile_count);
 }
 
 }  // namespace
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc
index bb6238c..c0a4af4 100644
--- a/cc/resources/video_resource_updater_unittest.cc
+++ b/cc/resources/video_resource_updater_unittest.cc
@@ -35,8 +35,7 @@
                                  NULL,
                                  0,
                                  false,
-                                 1,
-                                 false);
+                                 1);
   }
 
   scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() {
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc
index a395f5c..29b0f8e 100644
--- a/cc/surfaces/display.cc
+++ b/cc/surfaces/display.cc
@@ -58,7 +58,6 @@
   int highp_threshold_min = 0;
   bool use_rgba_4444_texture_format = false;
   size_t id_allocation_chunk_size = 1;
-  bool use_distance_field_text = false;
   scoped_ptr<ResourceProvider> resource_provider =
       ResourceProvider::Create(output_surface_.get(),
                                bitmap_manager_,
@@ -66,8 +65,7 @@
                                blocking_main_thread_task_runner_.get(),
                                highp_threshold_min,
                                use_rgba_4444_texture_format,
-                               id_allocation_chunk_size,
-                               use_distance_field_text);
+                               id_allocation_chunk_size);
   if (!resource_provider)
     return;
 
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc
index ef369f4..cea06ea 100644
--- a/cc/surfaces/surface_aggregator_unittest.cc
+++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -1127,8 +1127,7 @@
                                                   NULL,
                                                   0,
                                                   false,
-                                                  1,
-                                                  false);
+                                                  1);
 
     aggregator_.reset(
         new SurfaceAggregator(&manager_, resource_provider_.get()));
diff --git a/cc/test/data/background_filter_blur_off_axis.png b/cc/test/data/background_filter_blur_off_axis.png
index b5777f4..050ec54 100644
--- a/cc/test/data/background_filter_blur_off_axis.png
+++ b/cc/test/data/background_filter_blur_off_axis.png
Binary files differ
diff --git a/cc/test/data/blending_render_pass.png b/cc/test/data/blending_render_pass.png
new file mode 100644
index 0000000..76fe369
--- /dev/null
+++ b/cc/test/data/blending_render_pass.png
Binary files differ
diff --git a/cc/test/data/blending_render_pass_cm.png b/cc/test/data/blending_render_pass_cm.png
new file mode 100644
index 0000000..9a72d44
--- /dev/null
+++ b/cc/test/data/blending_render_pass_cm.png
Binary files differ
diff --git a/cc/test/data/blending_render_pass_mask.png b/cc/test/data/blending_render_pass_mask.png
new file mode 100644
index 0000000..8b63f35
--- /dev/null
+++ b/cc/test/data/blending_render_pass_mask.png
Binary files differ
diff --git a/cc/test/data/blending_render_pass_mask_cm.png b/cc/test/data/blending_render_pass_mask_cm.png
new file mode 100644
index 0000000..4e210aa
--- /dev/null
+++ b/cc/test/data/blending_render_pass_mask_cm.png
Binary files differ
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index c47a083..1565b8a 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -124,8 +124,7 @@
                                main_thread_task_runner_.get(),
                                0,
                                false,
-                               1,
-                               false);
+                               1);
 
   texture_mailbox_deleter_ = make_scoped_ptr(
       new TextureMailboxDeleter(base::MessageLoopProxy::current()));
@@ -173,8 +172,7 @@
                                main_thread_task_runner_.get(),
                                0,
                                false,
-                               1,
-                               false);
+                               1);
   renderer_ = SoftwareRenderer::Create(
       this, &settings_, output_surface_.get(), resource_provider_.get());
 }
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc
index 519c74a..c923b63 100644
--- a/cc/test/render_pass_test_utils.cc
+++ b/cc/test/render_pass_test_utils.cc
@@ -111,7 +111,8 @@
                        TestRenderPass* contributing_pass,
                        ResourceProvider::ResourceId mask_resource_id,
                        const FilterOperations& filters,
-                       gfx::Transform transform) {
+                       gfx::Transform transform,
+                       SkXfermode::Mode blend_mode) {
   gfx::Rect output_rect = contributing_pass->output_rect;
   SharedQuadState* shared_state = to_pass->CreateAndAppendSharedQuadState();
   shared_state->SetAll(transform,
@@ -120,7 +121,7 @@
                        output_rect,
                        false,
                        1,
-                       SkXfermode::kSrcOver_Mode,
+                       blend_mode,
                        0);
   RenderPassDrawQuad* quad =
       to_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
diff --git a/cc/test/render_pass_test_utils.h b/cc/test/render_pass_test_utils.h
index 7bf026c..49ea113 100644
--- a/cc/test/render_pass_test_utils.h
+++ b/cc/test/render_pass_test_utils.h
@@ -53,7 +53,8 @@
                        TestRenderPass* contributing_pass,
                        ResourceProvider::ResourceId mask_resource_id,
                        const FilterOperations& filters,
-                       gfx::Transform transform);
+                       gfx::Transform transform,
+                       SkXfermode::Mode blend_mode);
 
 }  // namespace cc
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index ddb315f..4ccc5fe 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2028,8 +2028,11 @@
                              GL_TEXTURE_2D,
                              resource_provider_->best_texture_format());
 
-    raster_worker_pool_ = GpuRasterWorkerPool::Create(
-        task_runner, context_provider, resource_provider_.get());
+    raster_worker_pool_ =
+        GpuRasterWorkerPool::Create(task_runner,
+                                    context_provider,
+                                    resource_provider_.get(),
+                                    settings_.use_distance_field_text);
   } else if (UseZeroCopyRasterizer()) {
     resource_pool_ = ResourcePool::Create(
         resource_provider_.get(),
@@ -2135,8 +2138,7 @@
                                proxy_->blocking_main_thread_task_runner(),
                                settings_.highp_threshold_min,
                                settings_.use_rgba_4444_textures,
-                               settings_.texture_id_allocation_chunk_size,
-                               settings_.use_distance_field_text);
+                               settings_.texture_id_allocation_chunk_size);
 
   if (output_surface_->capabilities().deferred_gl_initialization)
     EnforceZeroBudget(true);
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 7b466d0..51d86d3 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -901,19 +901,10 @@
     scroll_layer->SetScrollDelta(gfx::Vector2d());
 
     float page_scale_delta = 2.f;
-    gfx::Vector2dF expected_container_size_delta(
-        container_layer->bounds().width(), container_layer->bounds().height());
-    expected_container_size_delta.Scale((1.f - page_scale_delta) /
-                                        (page_scale_factor * page_scale_delta));
 
     host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
-    // While the gesture is still active, the scroll layer should have a
-    // container size delta = container->bounds() * ((1.f -
-    // page_scale_delta)/())
-    EXPECT_EQ(expected_container_size_delta,
-              scroll_layer->FixedContainerSizeDelta());
     host_impl_->PinchGestureEnd();
     host_impl_->ScrollEnd();
     EXPECT_FALSE(did_request_animate_);
@@ -2244,6 +2235,7 @@
         clip_size_(layer_size_) {
     settings_.calculate_top_controls_position = true;
     settings_.top_controls_height = 50;
+    settings_.use_pinch_virtual_viewport = true;
 
     viewport_size_ =
         gfx::Size(clip_size_.width(),
@@ -2386,8 +2378,8 @@
 }
 
 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
-  CreateHostImpl(settings_, CreateOutputSurface());
-  SetupTopControlsAndScrollLayer();
+  SetupTopControlsAndScrollLayerWithVirtualViewport(
+      gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
   DrawFrame();
 
   EXPECT_EQ(InputHandler::ScrollStarted,
@@ -2409,36 +2401,56 @@
             inner_viewport_scroll_layer->FixedContainerSizeDelta());
 }
 
-TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsWithPageScale) {
-  CreateHostImpl(settings_, CreateOutputSurface());
-  SetupTopControlsAndScrollLayer();
+// Test that the fixed position container delta is appropriately adjusted
+// by the top controls showing/hiding and page scale doesn't affect it.
+TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
+  SetupTopControlsAndScrollLayerWithVirtualViewport(
+      gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
   DrawFrame();
 
+  float page_scale = 1.5f;
+  float top_controls_height = settings_.top_controls_height;
+  LayerImpl* outer_viewport_scroll_layer =
+      host_impl_->active_tree()->OuterViewportScrollLayer();
+
+  // Zoom in, since the fixed container is the outer viewport, the delta should
+  // not be scaled.
+  host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
+
   EXPECT_EQ(InputHandler::ScrollStarted,
             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
 
-  float page_scale = 1.5f;
-  host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
-
-  gfx::Vector2dF top_controls_scroll_delta(0.f, 5.f);
-  gfx::Vector2dF expected_container_size_delta =
-      ScaleVector2d(top_controls_scroll_delta, 1.f / page_scale);
+  // Scroll down, the top controls hiding should expand the viewport size so
+  // the delta should be equal to the scroll distance.
+  gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
   host_impl_->top_controls_manager()->ScrollBegin();
   host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
-  host_impl_->top_controls_manager()->ScrollEnd();
-
-  LayerImpl* inner_viewport_scroll_layer =
-      host_impl_->active_tree()->InnerViewportScrollLayer();
-  DCHECK(inner_viewport_scroll_layer);
+  EXPECT_EQ(top_controls_height - top_controls_scroll_delta.y(),
+            host_impl_->top_controls_manager()->ContentTopOffset());
+  EXPECT_VECTOR_EQ(top_controls_scroll_delta,
+                   outer_viewport_scroll_layer->FixedContainerSizeDelta());
   host_impl_->ScrollEnd();
 
-  // Use a tolerance that requires the container size delta to be within 0.01
-  // pixels.
-  double tolerance = 0.0001;
-  EXPECT_LT(
-      (expected_container_size_delta -
-       inner_viewport_scroll_layer->FixedContainerSizeDelta()).LengthSquared(),
-      tolerance);
+  // Scroll past the maximum extent. The delta shouldn't be greater than the
+  // top controls height.
+  host_impl_->top_controls_manager()->ScrollBegin();
+  host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
+  host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
+  host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
+  EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height),
+                   outer_viewport_scroll_layer->FixedContainerSizeDelta());
+  host_impl_->ScrollEnd();
+
+  // Scroll in the direction to make the top controls show.
+  host_impl_->top_controls_manager()->ScrollBegin();
+  host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
+  EXPECT_EQ(top_controls_scroll_delta.y(),
+            host_impl_->top_controls_manager()->ContentTopOffset());
+  EXPECT_VECTOR_EQ(
+      gfx::Vector2dF(0, top_controls_height - top_controls_scroll_delta.y()),
+      outer_viewport_scroll_layer->FixedContainerSizeDelta());
+  host_impl_->top_controls_manager()->ScrollEnd();
 }
 
 // Ensure setting the top controls position explicitly using the setters on the
diff --git a/cc/trees/layer_tree_host_pixeltest_blending.cc b/cc/trees/layer_tree_host_pixeltest_blending.cc
index f01d426..bebd612 100644
--- a/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "cc/layers/image_layer.h"
 #include "cc/layers/solid_color_layer.h"
-#include "cc/layers/texture_layer.h"
 #include "cc/test/layer_tree_pixel_test.h"
 #include "cc/test/pixel_comparator.h"
 
@@ -22,7 +22,36 @@
     SkXfermode::kHue_Mode,       SkXfermode::kSaturation_Mode,
     SkXfermode::kColor_Mode,     SkXfermode::kLuminosity_Mode};
 
+SkColor kCSSTestColors[] = {
+    0xffff0000,  // red
+    0xff00ff00,  // lime
+    0xff0000ff,  // blue
+    0xff00ffff,  // aqua
+    0xffff00ff,  // fuchsia
+    0xffffff00,  // yellow
+    0xff008000,  // green
+    0xff800000,  // maroon
+    0xff000080,  // navy
+    0xff800080,  // purple
+    0xff808000,  // olive
+    0xff008080,  // teal
+    0xfffa8072,  // salmon
+    0xffc0c0c0,  // silver
+    0xff000000,  // black
+    0xff808080,  // gray
+    0x80000000,  // black with transparency
+    0xffffffff,  // white
+    0x80ffffff,  // white with transparency
+    0x00000000   // transparent
+};
+
 const int kBlendModesCount = arraysize(kBlendModes);
+const int kCSSTestColorsCount = arraysize(kCSSTestColors);
+
+using RenderPassOptions = uint32;
+const uint32 kUseMasks = 1 << 0;
+const uint32 kUseAntialiasing = 1 << 1;
+const uint32 kUseColorMatrix = 1 << 2;
 
 class LayerTreeHostBlendingPixelTest : public LayerTreePixelTest {
  public:
@@ -30,6 +59,10 @@
     pixel_comparator_.reset(new FuzzyPixelOffByOneComparator(true));
   }
 
+  virtual void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->force_antialiasing = force_antialiasing_;
+  }
+
  protected:
   void RunBlendingWithRootPixelTestType(PixelTestType type) {
     const int kLaneWidth = 15;
@@ -82,6 +115,175 @@
                  root,
                  base::FilePath(FILE_PATH_LITERAL("blending_transparent.png")));
   }
+
+  scoped_refptr<Layer> CreateColorfulBackdropLayer(int width, int height) {
+    // Draw the backdrop with horizontal lanes.
+    const int kLaneWidth = width;
+    const int kLaneHeight = height / kCSSTestColorsCount;
+    SkBitmap backing_store;
+    backing_store.allocN32Pixels(width, height);
+    SkCanvas canvas(backing_store);
+    canvas.clear(SK_ColorTRANSPARENT);
+    for (int i = 0; i < kCSSTestColorsCount; ++i) {
+      SkPaint paint;
+      paint.setColor(kCSSTestColors[i]);
+      canvas.drawRect(
+          SkRect::MakeXYWH(0, i * kLaneHeight, kLaneWidth, kLaneHeight), paint);
+    }
+    scoped_refptr<ImageLayer> layer = ImageLayer::Create();
+    layer->SetIsDrawable(true);
+    layer->SetBounds(gfx::Size(width, height));
+    layer->SetBitmap(backing_store);
+    return layer;
+  }
+
+  void SetupMaskLayer(scoped_refptr<Layer> layer) {
+    const int kMaskOffset = 5;
+    gfx::Size bounds = layer->bounds();
+    scoped_refptr<ImageLayer> mask = ImageLayer::Create();
+    mask->SetIsDrawable(true);
+    mask->SetIsMask(true);
+    mask->SetBounds(bounds);
+
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(bounds.width(), bounds.height());
+    SkCanvas canvas(bitmap);
+    SkPaint paint;
+    paint.setColor(SK_ColorWHITE);
+    canvas.clear(SK_ColorTRANSPARENT);
+    canvas.drawRect(SkRect::MakeXYWH(kMaskOffset,
+                                     kMaskOffset,
+                                     bounds.width() - kMaskOffset * 2,
+                                     bounds.height() - kMaskOffset * 2),
+                    paint);
+    mask->SetBitmap(bitmap);
+    layer->SetMaskLayer(mask.get());
+  }
+
+  void SetupColorMatrix(scoped_refptr<Layer> layer) {
+    FilterOperations filter_operations;
+    filter_operations.Append(FilterOperation::CreateSepiaFilter(1.f));
+    layer->SetFilters(filter_operations);
+  }
+
+  void CreateBlendingColorLayers(int width,
+                                 int height,
+                                 scoped_refptr<Layer> background,
+                                 RenderPassOptions flags) {
+    const int kLanesCount = kBlendModesCount + 4;
+    int lane_width = width / kLanesCount;
+    const SkColor kMiscOpaqueColor = 0xffc86464;
+    const SkColor kMiscTransparentColor = 0x80c86464;
+    const SkXfermode::Mode kCoeffBlendMode = SkXfermode::kScreen_Mode;
+    const SkXfermode::Mode kShaderBlendMode = SkXfermode::kColorBurn_Mode;
+    // add vertical lanes with each of the blend modes
+    for (int i = 0; i < kLanesCount; ++i) {
+      gfx::Rect child_rect(i * lane_width, 0, lane_width, height);
+      SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
+      float opacity = 1.f;
+      SkColor color = kMiscOpaqueColor;
+
+      if (i < kBlendModesCount) {
+        blend_mode = kBlendModes[i];
+      } else if (i == kBlendModesCount) {
+        blend_mode = kCoeffBlendMode;
+        opacity = 0.5f;
+      } else if (i == kBlendModesCount + 1) {
+        blend_mode = kCoeffBlendMode;
+        color = kMiscTransparentColor;
+      } else if (i == kBlendModesCount + 2) {
+        blend_mode = kShaderBlendMode;
+        opacity = 0.5f;
+      } else if (i == kBlendModesCount + 3) {
+        blend_mode = kShaderBlendMode;
+        color = kMiscTransparentColor;
+      }
+
+      scoped_refptr<SolidColorLayer> lane =
+          CreateSolidColorLayer(child_rect, color);
+      lane->SetBlendMode(blend_mode);
+      lane->SetOpacity(opacity);
+      lane->SetForceRenderSurface(true);
+      if (flags & kUseMasks)
+        SetupMaskLayer(lane);
+      if (flags & kUseColorMatrix) {
+        SetupColorMatrix(lane);
+      }
+      background->AddChild(lane);
+    }
+  }
+
+  void RunBlendingWithRenderPass(PixelTestType type,
+                                 const base::FilePath::CharType* expected_path,
+                                 RenderPassOptions flags) {
+    const int kRootSize = 400;
+
+    scoped_refptr<SolidColorLayer> root =
+        CreateSolidColorLayer(gfx::Rect(kRootSize, kRootSize), SK_ColorWHITE);
+    scoped_refptr<Layer> background =
+        CreateColorfulBackdropLayer(kRootSize, kRootSize);
+
+    background->SetIsRootForIsolatedGroup(true);
+    root->AddChild(background);
+
+    CreateBlendingColorLayers(kRootSize, kRootSize, background.get(), flags);
+
+    this->impl_side_painting_ = false;
+    this->force_antialiasing_ = (flags & kUseAntialiasing);
+
+    if ((flags & kUseAntialiasing) && (type == GL_WITH_BITMAP)) {
+      // Anti aliasing causes differences up to 7 pixels at the edges.
+      int large_error_allowed = 7;
+      // Blending results might differ with one pixel.
+      int small_error_allowed = 1;
+      // Most of the errors are one pixel errors.
+      float percentage_pixels_small_error = 12.5f;
+      // Because of anti-aliasing, around 3% of pixels (at the edges) have
+      // bigger errors (from small_error_allowed + 1 to large_error_allowed).
+      float percentage_pixels_error = 15.0f;
+      // The average error is still close to 1.
+      float average_error_allowed_in_bad_pixels = 1.3f;
+
+      // The sepia filter generates more small errors, but the number of large
+      // errors remains around 3%.
+      if (flags & kUseColorMatrix) {
+        percentage_pixels_small_error = 26.f;
+        percentage_pixels_error = 29.f;
+      }
+
+      // Anti-aliased pixels in combination with non-separable blend modes and
+      // a white background produces several black pixels (6 for these tests).
+      // Having a mask will hide the black pixels.
+      // TODO(rosca): fix this issue for non-separable blend modes.
+      if (!(flags & kUseMasks))
+        large_error_allowed = 255;
+
+      pixel_comparator_.reset(
+          new FuzzyPixelComparator(false,  // discard_alpha
+                                   percentage_pixels_error,
+                                   percentage_pixels_small_error,
+                                   average_error_allowed_in_bad_pixels,
+                                   large_error_allowed,
+                                   small_error_allowed));
+    } else if ((flags & kUseColorMatrix) && (type == GL_WITH_BITMAP)) {
+      float percentage_pixels_error = 100.f;
+      float percentage_pixels_small_error = 0.f;
+      float average_error_allowed_in_bad_pixels = 1.f;
+      int large_error_allowed = 2;
+      int small_error_allowed = 0;
+      pixel_comparator_.reset(
+          new FuzzyPixelComparator(false,  // discard_alpha
+                                   percentage_pixels_error,
+                                   percentage_pixels_small_error,
+                                   average_error_allowed_in_bad_pixels,
+                                   large_error_allowed,
+                                   small_error_allowed));
+    }
+
+    RunPixelTest(type, root, base::FilePath(expected_path));
+  }
+
+  bool force_antialiasing_ = false;
 };
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRoot_GL) {
@@ -128,6 +330,113 @@
   RunBlendingWithTransparentPixelTestType(SOFTWARE_WITH_BITMAP);
 }
 
+// Tests for render passes
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPass_GL) {
+  RunBlendingWithRenderPass(
+      GL_WITH_BITMAP, FILE_PATH_LITERAL("blending_render_pass.png"), 0);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPass_Software) {
+  RunBlendingWithRenderPass(
+      SOFTWARE_WITH_BITMAP, FILE_PATH_LITERAL("blending_render_pass.png"), 0);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassAA_GL) {
+  RunBlendingWithRenderPass(GL_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass.png"),
+                            kUseAntialiasing);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassAA_Software) {
+  RunBlendingWithRenderPass(SOFTWARE_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass.png"),
+                            kUseAntialiasing);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassWithMask_GL) {
+  RunBlendingWithRenderPass(GL_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass_mask.png"),
+                            kUseMasks);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassWithMask_Software) {
+  RunBlendingWithRenderPass(SOFTWARE_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass_mask.png"),
+                            kUseMasks);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassWithMaskAA_GL) {
+  RunBlendingWithRenderPass(GL_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass_mask.png"),
+                            kUseMasks | kUseAntialiasing);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassWithMaskAA_Software) {
+  RunBlendingWithRenderPass(SOFTWARE_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass_mask.png"),
+                            kUseMasks | kUseAntialiasing);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassColorMatrix_GL) {
+  RunBlendingWithRenderPass(GL_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass_cm.png"),
+                            kUseColorMatrix);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassColorMatrix_Software) {
+  RunBlendingWithRenderPass(SOFTWARE_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass_cm.png"),
+                            kUseColorMatrix);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassColorMatrixAA_GL) {
+  RunBlendingWithRenderPass(GL_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass_cm.png"),
+                            kUseAntialiasing | kUseColorMatrix);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassColorMatrixAA_Software) {
+  RunBlendingWithRenderPass(SOFTWARE_WITH_BITMAP,
+                            FILE_PATH_LITERAL("blending_render_pass_cm.png"),
+                            kUseAntialiasing | kUseColorMatrix);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassWithMaskColorMatrix_GL) {
+  RunBlendingWithRenderPass(
+      GL_WITH_BITMAP,
+      FILE_PATH_LITERAL("blending_render_pass_mask_cm.png"),
+      kUseMasks | kUseColorMatrix);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassWithMaskColorMatrix_Software) {
+  RunBlendingWithRenderPass(
+      SOFTWARE_WITH_BITMAP,
+      FILE_PATH_LITERAL("blending_render_pass_mask_cm.png"),
+      kUseMasks | kUseColorMatrix);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassWithMaskColorMatrixAA_GL) {
+  RunBlendingWithRenderPass(
+      GL_WITH_BITMAP,
+      FILE_PATH_LITERAL("blending_render_pass_mask_cm.png"),
+      kUseMasks | kUseAntialiasing | kUseColorMatrix);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassWithMaskColorMatrixAA_Software) {
+  RunBlendingWithRenderPass(
+      SOFTWARE_WITH_BITMAP,
+      FILE_PATH_LITERAL("blending_render_pass_mask_cm.png"),
+      kUseMasks | kUseAntialiasing | kUseColorMatrix);
+}
+
 }  // namespace
 }  // namespace cc
 
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index b9e15c6..5dafb7f 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -912,8 +912,7 @@
                                  NULL,
                                  0,
                                  false,
-                                 1,
-                                 false);
+                                 1);
   }
 
   static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index 8e11015..e4d5f1d 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -15,6 +15,7 @@
 LayerTreeSettings::LayerTreeSettings()
     : impl_side_painting(false),
       allow_antialiasing(true),
+      force_antialiasing(false),
       throttle_frame_production(true),
       single_thread_proxy_scheduler(true),
       begin_frame_scheduling_enabled(false),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index c0c1453..fff1084 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -20,6 +20,7 @@
 
   bool impl_side_painting;
   bool allow_antialiasing;
+  bool force_antialiasing;
   bool throttle_frame_production;
   bool single_thread_proxy_scheduler;
   bool begin_frame_scheduling_enabled;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 1bc8aad..0b8d68d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -9746,11 +9746,11 @@
     const void* cmd_data) {
   const gles2::cmds::WaitSyncPointCHROMIUM& c =
       *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
-  group_->mailbox_manager()->PullTextureUpdates();
+  uint32 sync_point = c.sync_point;
   if (wait_sync_point_callback_.is_null())
     return error::kNoError;
 
-  return wait_sync_point_callback_.Run(c.sync_point) ?
+  return wait_sync_point_callback_.Run(sync_point) ?
       error::kNoError : error::kDeferCommandUntilLater;
 }
 
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 33e5a2c..1e7cc1f 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -177,11 +177,6 @@
 base::LazyInstance<SyncPointManager> g_sync_point_manager =
     LAZY_INSTANCE_INITIALIZER;
 
-bool WaitSyncPoint(uint32 sync_point) {
-  g_sync_point_manager.Get().WaitSyncPoint(sync_point);
-  return true;
-}
-
 }  // anonyous namespace
 
 InProcessCommandBuffer::Service::Service() {}
@@ -422,7 +417,9 @@
     decoder_->SetResizeCallback(base::Bind(
         &InProcessCommandBuffer::OnResizeView, gpu_thread_weak_ptr_));
   }
-  decoder_->SetWaitSyncPointCallback(base::Bind(&WaitSyncPoint));
+  decoder_->SetWaitSyncPointCallback(
+      base::Bind(&InProcessCommandBuffer::WaitSyncPointOnGpuThread,
+                 base::Unretained(this)));
 
   return true;
 }
@@ -658,7 +655,7 @@
       make_current_success = MakeCurrent();
     }
     if (make_current_success)
-      mailbox_manager->PushTextureUpdates();
+      mailbox_manager->PushTextureUpdates(sync_point);
   }
   g_sync_point_manager.Get().RetireSyncPoint(sync_point);
 }
@@ -672,6 +669,14 @@
                        WrapCallback(callback)));
 }
 
+bool InProcessCommandBuffer::WaitSyncPointOnGpuThread(unsigned sync_point) {
+  g_sync_point_manager.Get().WaitSyncPoint(sync_point);
+  gles2::MailboxManager* mailbox_manager =
+      decoder_->GetContextGroup()->mailbox_manager();
+  mailbox_manager->PullTextureUpdates(sync_point);
+  return true;
+}
+
 void InProcessCommandBuffer::SignalSyncPointOnGpuThread(
     unsigned sync_point,
     const base::Closure& callback) {
diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h
index ec06ecd..e7b2260 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.h
+++ b/gpu/command_buffer/service/in_process_command_buffer.h
@@ -181,6 +181,7 @@
   void RetireSyncPointOnGpuThread(uint32 sync_point);
   void SignalSyncPointOnGpuThread(uint32 sync_point,
                                   const base::Closure& callback);
+  bool WaitSyncPointOnGpuThread(uint32 sync_point);
   void SignalQueryOnGpuThread(unsigned query_id, const base::Closure& callback);
   void DestroyTransferBufferOnGpuThread(int32 id);
 
diff --git a/gpu/command_buffer/service/mailbox_manager.cc b/gpu/command_buffer/service/mailbox_manager.cc
index e6962df..b4d6e79 100644
--- a/gpu/command_buffer/service/mailbox_manager.cc
+++ b/gpu/command_buffer/service/mailbox_manager.cc
@@ -84,14 +84,14 @@
     sync_->TextureDeleted(texture);
 }
 
-void MailboxManager::PushTextureUpdates() {
+void MailboxManager::PushTextureUpdates(uint32 sync_point) {
   if (sync_)
-    sync_->PushTextureUpdates(this);
+    sync_->PushTextureUpdates(this, sync_point);
 }
 
-void MailboxManager::PullTextureUpdates() {
+void MailboxManager::PullTextureUpdates(uint32 sync_point) {
   if (sync_)
-    sync_->PullTextureUpdates(this);
+    sync_->PullTextureUpdates(this, sync_point);
 }
 
 MailboxManager::TargetName::TargetName(unsigned target, const Mailbox& mailbox)
diff --git a/gpu/command_buffer/service/mailbox_manager.h b/gpu/command_buffer/service/mailbox_manager.h
index e1b36cb..a00b965 100644
--- a/gpu/command_buffer/service/mailbox_manager.h
+++ b/gpu/command_buffer/service/mailbox_manager.h
@@ -41,8 +41,8 @@
 
   // Used with the MailboxSynchronizer to push/pull texture state to/from
   // other manager instances.
-  void PushTextureUpdates();
-  void PullTextureUpdates();
+  void PushTextureUpdates(uint32 sync_point);
+  void PullTextureUpdates(uint32 sync_point);
 
   // Destroy any mailbox that reference the given texture.
   void TextureDeleted(Texture* texture);
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc
index df1cd4e..63ffc6d 100644
--- a/gpu/command_buffer/service/mailbox_manager_unittest.cc
+++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -300,8 +300,8 @@
   EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
 
   // Synchronize
-  manager_->PushTextureUpdates();
-  manager2_->PullTextureUpdates();
+  manager_->PushTextureUpdates(0);
+  manager2_->PullTextureUpdates(0);
 
   DestroyTexture(texture);
   EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
@@ -321,8 +321,8 @@
   EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
 
   // Synchronize
-  manager_->PushTextureUpdates();
-  manager2_->PullTextureUpdates();
+  manager_->PushTextureUpdates(0);
+  manager2_->PullTextureUpdates(0);
 
   EXPECT_CALL(*gl_, GenTextures(1, _))
       .WillOnce(SetArgPointee<1>(kNewTextureId));
@@ -349,10 +349,10 @@
   EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL);
 
   // Synchronize again
-  manager_->PushTextureUpdates();
+  manager_->PushTextureUpdates(0);
   SetupUpdateTexParamExpectations(
       kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
-  manager2_->PullTextureUpdates();
+  manager2_->PullTextureUpdates(0);
   GLsizei width, height;
   new_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
   EXPECT_EQ(16, width);
@@ -382,7 +382,7 @@
 
   // The last change to the texture should be visible without a sync point (i.e.
   // push).
-  manager2_->PullTextureUpdates();
+  manager2_->PullTextureUpdates(0);
   new_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
   EXPECT_EQ(64, width);
   EXPECT_EQ(64, height);
@@ -410,8 +410,8 @@
   manager2_->ProduceTexture(GL_TEXTURE_2D, name2, texture2);
 
   // Make visible.
-  manager_->PushTextureUpdates();
-  manager2_->PushTextureUpdates();
+  manager_->PushTextureUpdates(0);
+  manager2_->PushTextureUpdates(0);
 
   // Create textures in the other manager instances for texture1 and texture2,
   // respectively to create a real sharing scenario. Otherwise, there would
@@ -438,7 +438,7 @@
             SetParameter(texture1, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
 
   // Make sure this does not clobber it with the previous version we pushed.
-  manager_->PullTextureUpdates();
+  manager_->PullTextureUpdates(0);
 
   // Make a change to texture2
   DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), texture2->mag_filter());
@@ -448,16 +448,16 @@
   Mock::VerifyAndClearExpectations(gl_.get());
 
   // Synchronize in both directions
-  manager_->PushTextureUpdates();
-  manager2_->PushTextureUpdates();
+  manager_->PushTextureUpdates(0);
+  manager2_->PushTextureUpdates(0);
   // manager1 should see the change to texture2 mag_filter being applied.
   SetupUpdateTexParamExpectations(
       new_texture2->service_id(), GL_LINEAR, GL_NEAREST, GL_REPEAT, GL_REPEAT);
-  manager_->PullTextureUpdates();
+  manager_->PullTextureUpdates(0);
   // manager2 should see the change to texture1 min_filter being applied.
   SetupUpdateTexParamExpectations(
       new_texture1->service_id(), GL_NEAREST, GL_LINEAR, GL_REPEAT, GL_REPEAT);
-  manager2_->PullTextureUpdates();
+  manager2_->PullTextureUpdates(0);
 
   DestroyTexture(texture1);
   DestroyTexture(texture2);
diff --git a/gpu/command_buffer/service/mailbox_synchronizer.cc b/gpu/command_buffer/service/mailbox_synchronizer.cc
index eac31f9..81a2793 100644
--- a/gpu/command_buffer/service/mailbox_synchronizer.cc
+++ b/gpu/command_buffer/service/mailbox_synchronizer.cc
@@ -7,8 +7,13 @@
 #include "base/bind.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/texture_manager.h"
+#include "ui/gl/gl_fence.h"
 #include "ui/gl/gl_implementation.h"
 
+#if !defined(OS_MACOSX)
+#include "ui/gl/gl_fence_egl.h"
+#endif
+
 namespace gpu {
 namespace gles2 {
 
@@ -136,7 +141,8 @@
   }
 }
 
-void MailboxSynchronizer::PushTextureUpdates(MailboxManager* manager) {
+void MailboxSynchronizer::PushTextureUpdates(MailboxManager* manager,
+                                             uint32 sync_point) {
   base::AutoLock lock(lock_);
   for (MailboxManager::MailboxToTextureMap::const_iterator texture_it =
            manager->mailbox_to_textures_.begin();
@@ -179,6 +185,33 @@
       textures_.insert(std::make_pair(texture, TextureVersion(group)));
     }
   }
+
+  CreateFenceLocked(sync_point);
+}
+
+void MailboxSynchronizer::CreateFenceLocked(uint32 sync_point) {
+  lock_.AssertAcquired();
+  if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL)
+    return;
+
+#if !defined(OS_MACOSX)
+  if (sync_point) {
+    while (!sync_points_.empty() &&
+           sync_points_.front()->second->HasCompleted()) {
+      sync_point_to_fence_.erase(sync_points_.front());
+      sync_points_.pop();
+    }
+    // Need to use EGL fences since we are likely not in a single share group.
+    linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL(true)));
+    if (fence.get()) {
+      std::pair<SyncPointToFenceMap::iterator, bool> result =
+          sync_point_to_fence_.insert(std::make_pair(sync_point, fence));
+      DCHECK(result.second);
+      sync_points_.push(result.first);
+    }
+    DCHECK(sync_points_.size() == sync_point_to_fence_.size());
+  }
+#endif
 }
 
 void MailboxSynchronizer::UpdateTextureLocked(Texture* texture,
@@ -208,8 +241,20 @@
                                         gl_image ? image_buffer : NULL);
 }
 
-void MailboxSynchronizer::PullTextureUpdates(MailboxManager* manager) {
+void MailboxSynchronizer::AcquireFenceLocked(uint32 sync_point) {
+  lock_.AssertAcquired();
+  SyncPointToFenceMap::iterator fence_it =
+      sync_point_to_fence_.find(sync_point);
+  if (fence_it != sync_point_to_fence_.end()) {
+    fence_it->second->ServerWait();
+  }
+}
+
+void MailboxSynchronizer::PullTextureUpdates(MailboxManager* manager,
+                                             uint32 sync_point) {
   base::AutoLock lock(lock_);
+  AcquireFenceLocked(sync_point);
+
   for (MailboxManager::MailboxToTextureMap::const_iterator texture_it =
            manager->mailbox_to_textures_.begin();
        texture_it != manager->mailbox_to_textures_.end();
diff --git a/gpu/command_buffer/service/mailbox_synchronizer.h b/gpu/command_buffer/service/mailbox_synchronizer.h
index a845963..3ddb9d0 100644
--- a/gpu/command_buffer/service/mailbox_synchronizer.h
+++ b/gpu/command_buffer/service/mailbox_synchronizer.h
@@ -8,6 +8,7 @@
 #include "gpu/command_buffer/common/mailbox.h"
 
 #include <map>
+#include <queue>
 #include <set>
 
 #include "base/memory/linked_ptr.h"
@@ -15,6 +16,10 @@
 #include "gpu/command_buffer/service/texture_definition.h"
 #include "gpu/gpu_export.h"
 
+namespace gfx {
+class GLFence;
+}
+
 namespace gpu {
 namespace gles2 {
 
@@ -34,8 +39,8 @@
   // Create a texture from a globally visible mailbox.
   Texture* CreateTextureFromMailbox(unsigned target, const Mailbox& mailbox);
 
-  void PushTextureUpdates(MailboxManager* manager);
-  void PullTextureUpdates(MailboxManager* manager);
+  void PushTextureUpdates(MailboxManager* manager, uint32 sync_point);
+  void PullTextureUpdates(MailboxManager* manager, uint32 sync_point);
 
   void TextureDeleted(Texture* texture);
 
@@ -85,6 +90,12 @@
       const TargetName& target_name,
       TextureGroup* group);
   void UpdateTextureLocked(Texture* texture, TextureVersion& texture_version);
+  void CreateFenceLocked(uint32 sync_point);
+  void AcquireFenceLocked(uint32 sync_point);
+
+  typedef std::map<uint32, linked_ptr<gfx::GLFence> > SyncPointToFenceMap;
+  SyncPointToFenceMap sync_point_to_fence_;
+  std::queue<SyncPointToFenceMap::iterator> sync_points_;
 
   DISALLOW_COPY_AND_ASSIGN(MailboxSynchronizer);
 };
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index 63a64b7..ac7021a 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -81,8 +81,8 @@
   return true;
 }
 
-bool IsBuiltInVarying(const std::string& name) {
-  // Built-in variables.
+bool IsBuiltInFragmentVarying(const std::string& name) {
+  // Built-in variables for fragment shaders.
   const char* kBuiltInVaryings[] = {
       "gl_FragCoord",
       "gl_FrontFacing",
@@ -95,6 +95,14 @@
   return false;
 }
 
+bool IsBuiltInInvariant(
+    const VaryingMap& varyings, const std::string& name) {
+  VaryingMap::const_iterator hit = varyings.find(name);
+  if (hit == varyings.end())
+    return false;
+  return hit->second.isInvariant;
+}
+
 }  // anonymous namespace.
 
 Program::UniformInfo::UniformInfo()
@@ -526,6 +534,11 @@
     set_log_info(ProcessLogInfo(info_log).c_str());
     return false;
   }
+  if (DetectBuiltInInvariantConflicts()) {
+    set_log_info("Invariant settings for certain built-in varyings "
+                 "have to match");
+    return false;
+  }
   if (DetectGlobalNameConflicts(&conflicting_name)) {
     std::string info_log = "Name conflicts between an uniform and an "
                            "attribute: " + conflicting_name;
@@ -1071,7 +1084,7 @@
   for (VaryingMap::const_iterator iter = fragment_varyings->begin();
        iter != fragment_varyings->end(); ++iter) {
     const std::string& name = iter->first;
-    if (IsBuiltInVarying(name))
+    if (IsBuiltInFragmentVarying(name))
       continue;
 
     VaryingMap::const_iterator hit = vertex_varyings->find(name);
@@ -1092,6 +1105,28 @@
   return false;
 }
 
+bool Program::DetectBuiltInInvariantConflicts() const {
+  DCHECK(attached_shaders_[0].get() &&
+         attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
+         attached_shaders_[1].get() &&
+         attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
+  const VaryingMap& vertex_varyings = attached_shaders_[0]->varying_map();
+  const VaryingMap& fragment_varyings = attached_shaders_[1]->varying_map();
+
+  bool gl_position_invariant = IsBuiltInInvariant(
+      vertex_varyings, "gl_Position");
+  bool gl_point_size_invariant = IsBuiltInInvariant(
+      vertex_varyings, "gl_PointSize");
+
+  bool gl_frag_coord_invariant = IsBuiltInInvariant(
+      fragment_varyings, "gl_FragCoord");
+  bool gl_point_coord_invariant = IsBuiltInInvariant(
+      fragment_varyings, "gl_PointCoord");
+
+  return ((gl_frag_coord_invariant && !gl_position_invariant) ||
+          (gl_point_coord_invariant && !gl_point_size_invariant));
+}
+
 bool Program::DetectGlobalNameConflicts(std::string* conflicting_name) const {
   DCHECK(attached_shaders_[0].get() &&
          attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
@@ -1130,7 +1165,7 @@
        iter != fragment_varyings->end(); ++iter) {
     if (!iter->second.staticUse && option == kCountOnlyStaticallyUsed)
       continue;
-    if (!IsBuiltInVarying(iter->first)) {
+    if (!IsBuiltInFragmentVarying(iter->first)) {
       VaryingMap::const_iterator vertex_iter =
           vertex_varyings->find(iter->first);
       if (vertex_iter == vertex_varyings->end() ||
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index 9698fc1..dbe9c14 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -215,6 +215,10 @@
   // is not declared in vertex shader.
   bool DetectVaryingsMismatch(std::string* conflicting_name) const;
 
+  // Return true if any built-in invariant matching rules are broken as in
+  // GLSL ES spec 1.00.17, section 4.6.4, Invariance and Linkage.
+  bool DetectBuiltInInvariantConflicts() const;
+
   // Return true if an uniform and an attribute share the same name.
   bool DetectGlobalNameConflicts(std::string* conflicting_name) const;
 
diff --git a/gpu/command_buffer/service/shader_translator_unittest.cc b/gpu/command_buffer/service/shader_translator_unittest.cc
index 198ea82..40d5be7 100644
--- a/gpu/command_buffer/service/shader_translator_unittest.cc
+++ b/gpu/command_buffer/service/shader_translator_unittest.cc
@@ -69,10 +69,11 @@
   EXPECT_TRUE(info_log.empty());
   // Translated shader must be valid and non-empty.
   ASSERT_FALSE(translated_source.empty());
-  // There should be no attributes, uniforms, varyings.
+  // There should be no attributes, uniforms, and only one built-in
+  // varying: gl_Position.
   EXPECT_TRUE(attrib_map.empty());
   EXPECT_TRUE(uniform_map.empty());
-  EXPECT_TRUE(varying_map.empty());
+  EXPECT_EQ(1u, varying_map.size());
   // There should be no name mapping.
   EXPECT_TRUE(name_map.empty());
 }
diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc
index cf385d2..abde56a 100644
--- a/gpu/command_buffer/service/texture_definition.cc
+++ b/gpu/command_buffer/service/texture_definition.cc
@@ -15,7 +15,6 @@
 #include "ui/gl/scoped_binders.h"
 
 #if !defined(OS_MACOSX)
-#include "ui/gl/gl_fence_egl.h"
 #include "ui/gl/gl_surface_egl.h"
 #endif
 
@@ -88,23 +87,15 @@
 }
 
 void GLImageSync::WillUseTexImage() {
-  if (buffer_.get())
-    buffer_->WillRead(this);
 }
 
 void GLImageSync::DidUseTexImage() {
-  if (buffer_.get())
-    buffer_->DidRead(this);
 }
 
 void GLImageSync::WillModifyTexImage() {
-  if (buffer_.get())
-    buffer_->WillWrite(this);
 }
 
 void GLImageSync::DidModifyTexImage() {
-  if (buffer_.get())
-    buffer_->DidWrite(this);
 }
 
 bool GLImageSync::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
@@ -128,10 +119,6 @@
   virtual void RemoveClient(gfx::GLImage* client) override;
   virtual bool IsClient(gfx::GLImage* client) override;
   virtual void BindToTexture(GLenum target) override;
-  virtual void WillRead(gfx::GLImage* client) override;
-  virtual void WillWrite(gfx::GLImage* client) override;
-  virtual void DidRead(gfx::GLImage* client) override;
-  virtual void DidWrite(gfx::GLImage* client) override;
 
   EGLDisplay egl_display_;
   EGLImageKHR egl_image_;
@@ -144,10 +131,8 @@
 
     gfx::GLImage* client;
     bool needs_wait_before_read;
-    linked_ptr<gfx::GLFence> read_fence;
   };
   std::list<ClientInfo> client_infos_;
-  scoped_ptr<gfx::GLFence> write_fence_;
   gfx::GLImage* write_client_;
 
   DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL);
@@ -164,8 +149,7 @@
 
   DCHECK(gfx::g_driver_egl.ext.b_EGL_KHR_image_base &&
          gfx::g_driver_egl.ext.b_EGL_KHR_gl_texture_2D_image &&
-         gfx::g_driver_gl.ext.b_GL_OES_EGL_image &&
-         gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync);
+         gfx::g_driver_gl.ext.b_GL_OES_EGL_image);
 
   const EGLint egl_attrib_list[] = {
       EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
@@ -191,7 +175,6 @@
     : NativeImageBuffer(),
       egl_display_(display),
       egl_image_(image),
-      write_fence_(new gfx::GLFenceEGL(true)),
       write_client_(NULL) {
   DCHECK(egl_display_ != EGL_NO_DISPLAY);
   DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
@@ -241,64 +224,6 @@
   DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
 }
 
-void NativeImageBufferEGL::WillRead(gfx::GLImage* client) {
-  base::AutoLock lock(lock_);
-  if (!write_fence_.get() || write_client_ == client)
-    return;
-
-  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
-       it != client_infos_.end();
-       it++) {
-    if (it->client == client) {
-      if (it->needs_wait_before_read) {
-        it->needs_wait_before_read = false;
-        write_fence_->ServerWait();
-      }
-      return;
-    }
-  }
-  NOTREACHED();
-}
-
-void NativeImageBufferEGL::WillWrite(gfx::GLImage* client) {
-  base::AutoLock lock(lock_);
-  if (write_client_ != client)
-    write_fence_->ServerWait();
-
-  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
-       it != client_infos_.end();
-       it++) {
-    if (it->read_fence.get() && it->client != client)
-      it->read_fence->ServerWait();
-  }
-}
-
-void NativeImageBufferEGL::DidRead(gfx::GLImage* client) {
-  base::AutoLock lock(lock_);
-  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
-       it != client_infos_.end();
-       it++) {
-    if (it->client == client) {
-      it->read_fence = make_linked_ptr(new gfx::GLFenceEGL(true));
-      return;
-    }
-  }
-  NOTREACHED();
-}
-
-void NativeImageBufferEGL::DidWrite(gfx::GLImage* client) {
-  base::AutoLock lock(lock_);
-  // Sharing semantics require the client to flush in order to make changes
-  // visible to other clients.
-  write_fence_.reset(new gfx::GLFenceEGL(false));
-  write_client_ = client;
-  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
-       it != client_infos_.end();
-       it++) {
-    it->needs_wait_before_read = true;
-  }
-}
-
 #endif
 
 class NativeImageBufferStub : public NativeImageBuffer {
@@ -311,10 +236,6 @@
   void RemoveClient(gfx::GLImage* client) override {}
   bool IsClient(gfx::GLImage* client) override { return true; }
   void BindToTexture(GLenum target) override {}
-  void WillRead(gfx::GLImage* client) override {}
-  void WillWrite(gfx::GLImage* client) override {}
-  void DidRead(gfx::GLImage* client) override {}
-  void DidWrite(gfx::GLImage* client) override {}
 
   DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub);
 };
diff --git a/gpu/command_buffer/service/texture_definition.h b/gpu/command_buffer/service/texture_definition.h
index 6df4b86..cb21abd 100644
--- a/gpu/command_buffer/service/texture_definition.h
+++ b/gpu/command_buffer/service/texture_definition.h
@@ -27,10 +27,6 @@
   virtual void RemoveClient(gfx::GLImage* client) = 0;
   virtual bool IsClient(gfx::GLImage* client) = 0;
   virtual void BindToTexture(GLenum target) = 0;
-  virtual void WillRead(gfx::GLImage* client) = 0;
-  virtual void WillWrite(gfx::GLImage* client) = 0;
-  virtual void DidRead(gfx::GLImage* client) = 0;
-  virtual void DidWrite(gfx::GLImage* client) = 0;
 
  protected:
   friend class base::RefCountedThreadSafe<NativeImageBuffer>;
diff --git a/net/PRESUBMIT.py b/net/PRESUBMIT.py
index e898d99..e82166c 100644
--- a/net/PRESUBMIT.py
+++ b/net/PRESUBMIT.py
@@ -11,13 +11,13 @@
 def GetPreferredTryMasters(project, change):
   masters = {
     'tryserver.chromium.linux': {
-      'linux_chromium_rel_swarming': set(['defaulttests']),
+      'linux_chromium_rel': set(['defaulttests']),
     },
     'tryserver.chromium.mac': {
-      'mac_chromium_rel_swarming': set(['defaulttests']),
+      'mac_chromium_rel': set(['defaulttests']),
     },
     'tryserver.chromium.win': {
-      'win_chromium_rel_swarming': set(['defaulttests']),
+      'win_chromium_rel': set(['defaulttests']),
     }
   }
   # Changes that touch NSS files will likely need a corresponding OpenSSL edit.
diff --git a/net/base/data_url_unittest.cc b/net/base/data_url_unittest.cc
index 3876301..bcb2b49 100644
--- a/net/base/data_url_unittest.cc
+++ b/net/base/data_url_unittest.cc
@@ -184,6 +184,44 @@
       "",
       "" },
 
+    // BiDi control characters should be unescaped and preserved as is, and
+    // should not be replaced with % versions. In the below case, \xE2\x80\x8F
+    // is the RTL mark and the parsed text should preserve it as is.
+    {
+      "data:text/plain;charset=utf-8,\xE2\x80\x8Ftest",
+      true,
+      "text/plain",
+      "utf-8",
+      "\xE2\x80\x8Ftest"},
+
+    // Same as above but with Arabic text after RTL mark.
+    {
+      "data:text/plain;charset=utf-8,"
+          "\xE2\x80\x8F\xD8\xA7\xD8\xAE\xD8\xAA\xD8\xA8\xD8\xA7\xD8\xB1",
+      true,
+      "text/plain",
+      "utf-8",
+      "\xE2\x80\x8F\xD8\xA7\xD8\xAE\xD8\xAA\xD8\xA8\xD8\xA7\xD8\xB1"},
+
+    // RTL mark encoded as %E2%80%8F should be unescaped too. Note that when
+    // wrapped in a GURL, this URL and the next effectively become the same as
+    // the previous two URLs.
+    {
+      "data:text/plain;charset=utf-8,%E2%80%8Ftest",
+      true,
+      "text/plain",
+      "utf-8",
+      "\xE2\x80\x8Ftest"},
+
+    // Same as above but with Arabic text after RTL mark.
+    {
+      "data:text/plain;charset=utf-8,"
+          "%E2%80%8F\xD8\xA7\xD8\xAE\xD8\xAA\xD8\xA8\xD8\xA7\xD8\xB1",
+      true,
+      "text/plain",
+      "utf-8",
+      "\xE2\x80\x8F\xD8\xA7\xD8\xAE\xD8\xAA\xD8\xA8\xD8\xA7\xD8\xB1"}
+
     // TODO(darin): add more interesting tests
   };
 
diff --git a/net/base/escape.cc b/net/base/escape.cc
index 1798b6c..3c8adc6 100644
--- a/net/base/escape.cc
+++ b/net/base/escape.cc
@@ -120,6 +120,44 @@
   return false;
 }
 
+// Returns true if there is an Arabic Language Mark at |index|. |first_byte|
+// is the byte at |index|.
+template<typename STR>
+bool HasArabicLanguageMarkAtIndex(const STR& escaped_text,
+                                  unsigned char first_byte,
+                                  size_t index) {
+  if (first_byte != 0xD8)
+    return false;
+  unsigned char second_byte;
+  if (!UnescapeUnsignedCharAtIndex(escaped_text, index + 3, &second_byte))
+    return false;
+  return second_byte == 0x9c;
+}
+
+// Returns true if there is a BiDi control char at |index|. |first_byte| is the
+// byte at |index|.
+template<typename STR>
+bool HasThreeByteBidiControlCharAtIndex(const STR& escaped_text,
+                                        unsigned char first_byte,
+                                        size_t index) {
+  if (first_byte != 0xE2)
+    return false;
+  unsigned char second_byte;
+  if (!UnescapeUnsignedCharAtIndex(escaped_text, index + 3, &second_byte))
+    return false;
+  if (second_byte != 0x80 && second_byte != 0x81)
+    return false;
+  unsigned char third_byte;
+  if (!UnescapeUnsignedCharAtIndex(escaped_text, index + 6, &third_byte))
+    return false;
+  if (second_byte == 0x80) {
+    return third_byte == 0x8E ||
+           third_byte == 0x8F ||
+           (third_byte >= 0xAA && third_byte <= 0xAE);
+  }
+  return third_byte >= 0xA6 && third_byte <= 0xA9;
+}
+
 // Unescapes |escaped_text| according to |rules|, returning the resulting
 // string.  Fills in an |adjustments| parameter, if non-NULL, so it reflects
 // the alterations done to the string that are not one-character-to-one-
@@ -172,27 +210,21 @@
       // U+2067 RIGHT-TO-LEFT ISOLATE      (%E2%81%A7)
       // U+2068 FIRST STRONG ISOLATE       (%E2%81%A8)
       // U+2069 POP DIRECTIONAL ISOLATE    (%E2%81%A9)
-
-      unsigned char second_byte;
-      // Check for ALM.
-      if ((first_byte == 0xD8) &&
-          UnescapeUnsignedCharAtIndex(escaped_text, i + 3, &second_byte) &&
-          (second_byte == 0x9c)) {
-        result.append(escaped_text, i, 6);
-        i += 5;
-        continue;
-      }
-
-      // Check for other BiDi control characters.
-      if ((first_byte == 0xE2) &&
-          UnescapeUnsignedCharAtIndex(escaped_text, i + 3, &second_byte) &&
-          ((second_byte == 0x80) || (second_byte == 0x81))) {
-        unsigned char third_byte;
-        if (UnescapeUnsignedCharAtIndex(escaped_text, i + 6, &third_byte) &&
-            ((second_byte == 0x80) ?
-             ((third_byte == 0x8E) || (third_byte == 0x8F) ||
-              ((third_byte >= 0xAA) && (third_byte <= 0xAE))) :
-             ((third_byte >= 0xA6) && (third_byte <= 0xA9)))) {
+      //
+      // However, some schemes such as data: and file: need to parse the exact
+      // binary data when loading the URL. For that reason, CONTROL_CHARS allows
+      // unescaping BiDi control characters.
+      // DO NOT use CONTROL_CHARS if the parsed URL is going to be displayed
+      // in the UI.
+      if (!(rules & UnescapeRule::CONTROL_CHARS)) {
+        if (HasArabicLanguageMarkAtIndex(escaped_text, first_byte, i)) {
+          // Keep Arabic Language Mark escaped.
+          result.append(escaped_text, i, 6);
+          i += 5;
+          continue;
+        }
+        if (HasThreeByteBidiControlCharAtIndex(escaped_text, first_byte, i)) {
+          // Keep BiDi control char escaped.
           result.append(escaped_text, i, 9);
           i += 8;
           continue;
diff --git a/net/base/escape.h b/net/base/escape.h
index 1915d24..bc58439 100644
--- a/net/base/escape.h
+++ b/net/base/escape.h
@@ -88,7 +88,10 @@
 
     // Unescapes control characters such as %01. This INCLUDES NULLs. This is
     // used for rare cases such as data: URL decoding where the result is binary
-    // data. You should not use this for normal URLs!
+    // data. This flag also unescapes BiDi control characters.
+    //
+    // DO NOT use CONTROL_CHARS if the URL is going to be displayed in the UI
+    // for security reasons.
     CONTROL_CHARS = 8,
 
     // URL queries use "+" for space. This flag controls that replacement.
diff --git a/net/base/escape_unittest.cc b/net/base/escape_unittest.cc
index 74ae293..1e82239 100644
--- a/net/base/escape_unittest.cc
+++ b/net/base/escape_unittest.cc
@@ -232,7 +232,8 @@
     {L"Some%20random text %25%E2%80%84OK", UnescapeRule::NORMAL,
      L"Some%20random text %25\xE2\x80\x84OK"},
 
-    // BiDi Control characters should not be unescaped.
+    // BiDi Control characters should not be unescaped unless explicity told to
+    // do so with UnescapeRule::CONTROL_CHARS
     {L"Some%20random text %25%D8%9COK", UnescapeRule::NORMAL,
      L"Some%20random text %25%D8%9COK"},
     {L"Some%20random text %25%E2%80%8EOK", UnescapeRule::NORMAL,
@@ -249,6 +250,31 @@
      L"Some%20random text %25%E2%81%A6OK"},
     {L"Some%20random text %25%E2%81%A9OK", UnescapeRule::NORMAL,
      L"Some%20random text %25%E2%81%A9OK"},
+    // UnescapeRule::CONTROL_CHARS should unescape BiDi Control characters.
+    {L"Some%20random text %25%D8%9COK",
+     UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS,
+     L"Some%20random text %25\xD8\x9COK"},
+    {L"Some%20random text %25%E2%80%8EOK",
+     UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS,
+     L"Some%20random text %25\xE2\x80\x8EOK"},
+    {L"Some%20random text %25%E2%80%8FOK",
+     UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS,
+     L"Some%20random text %25\xE2\x80\x8FOK"},
+    {L"Some%20random text %25%E2%80%AAOK",
+     UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS,
+     L"Some%20random text %25\xE2\x80\xAAOK"},
+    {L"Some%20random text %25%E2%80%ABOK",
+     UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS,
+     L"Some%20random text %25\xE2\x80\xABOK"},
+    {L"Some%20random text %25%E2%80%AEOK",
+     UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS,
+     L"Some%20random text %25\xE2\x80\xAEOK"},
+    {L"Some%20random text %25%E2%81%A6OK",
+     UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS,
+     L"Some%20random text %25\xE2\x81\xA6OK"},
+    {L"Some%20random text %25%E2%81%A9OK",
+     UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS,
+     L"Some%20random text %25\xE2\x81\xA9OK"},
 
     {L"Some%20random text %25%2dOK", UnescapeRule::SPACES,
      L"Some random text %25-OK"},
diff --git a/net/base/trace_net_log_observer.cc b/net/base/trace_net_log_observer.cc
index 15960c3..5d98c41 100644
--- a/net/base/trace_net_log_observer.cc
+++ b/net/base/trace_net_log_observer.cc
@@ -19,6 +19,9 @@
 
 namespace {
 
+// TraceLog category for NetLog events.
+const char kNetLogTracingCategory[] = TRACE_DISABLED_BY_DEFAULT("netlog");
+
 class TracedValue : public base::debug::ConvertableToTraceFormat {
  public:
   explicit TracedValue(scoped_ptr<base::Value> value) : value_(value.Pass()) {}
@@ -55,21 +58,24 @@
   switch (entry.phase()) {
     case NetLog::PHASE_BEGIN:
       TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
-          "netlog", NetLog::EventTypeToString(entry.type()), entry.source().id,
+          kNetLogTracingCategory,
+          NetLog::EventTypeToString(entry.type()), entry.source().id,
           "source_type", NetLog::SourceTypeToString(entry.source().type),
           "params", scoped_refptr<base::debug::ConvertableToTraceFormat>(
               new TracedValue(params.Pass())));
       break;
     case NetLog::PHASE_END:
       TRACE_EVENT_NESTABLE_ASYNC_END2(
-          "netlog", NetLog::EventTypeToString(entry.type()), entry.source().id,
+          kNetLogTracingCategory,
+          NetLog::EventTypeToString(entry.type()), entry.source().id,
           "source_type", NetLog::SourceTypeToString(entry.source().type),
           "params", scoped_refptr<base::debug::ConvertableToTraceFormat>(
               new TracedValue(params.Pass())));
       break;
     case NetLog::PHASE_NONE:
       TRACE_EVENT_NESTABLE_ASYNC_INSTANT2(
-          "netlog", NetLog::EventTypeToString(entry.type()), entry.source().id,
+          kNetLogTracingCategory,
+          NetLog::EventTypeToString(entry.type()), entry.source().id,
           "source_type", NetLog::SourceTypeToString(entry.source().type),
           "params", scoped_refptr<base::debug::ConvertableToTraceFormat>(
               new TracedValue(params.Pass())));
diff --git a/net/base/trace_net_log_observer_unittest.cc b/net/base/trace_net_log_observer_unittest.cc
index c1a8803..2e20707 100644
--- a/net/base/trace_net_log_observer_unittest.cc
+++ b/net/base/trace_net_log_observer_unittest.cc
@@ -27,6 +27,9 @@
 
 namespace {
 
+// TraceLog category for NetLog events.
+const char kNetLogTracingCategory[] = TRACE_DISABLED_BY_DEFAULT("netlog");
+
 struct TraceEntryInfo {
   std::string category;
   std::string id;
@@ -86,9 +89,10 @@
   }
 
   static void EnableTraceLog() {
-    TraceLog::GetInstance()->SetEnabled(base::debug::CategoryFilter("netlog"),
-                                        TraceLog::RECORDING_MODE,
-                                        base::debug::TraceOptions());
+    TraceLog::GetInstance()->SetEnabled(
+        base::debug::CategoryFilter(kNetLogTracingCategory),
+        TraceLog::RECORDING_MODE,
+        base::debug::TraceOptions());
   }
 
   void EndTraceAndFlush() {
@@ -120,7 +124,7 @@
             << "Unexpected item without a category field in trace_events";
         continue;
       }
-      if (category != "netlog")
+      if (category != kNetLogTracingCategory)
         continue;
       filtered_trace_events->Append(dict->DeepCopy());
     }
@@ -185,7 +189,7 @@
   TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1);
   TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2);
   TraceEntryInfo actual_item3 = GetTraceEntryInfoFromValue(*item3);
-  EXPECT_EQ("netlog", actual_item1.category);
+  EXPECT_EQ(kNetLogTracingCategory, actual_item1.category);
   EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id);
   EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT),
             actual_item1.phase);
@@ -194,7 +198,7 @@
   EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type),
             actual_item1.source_type);
 
-  EXPECT_EQ("netlog", actual_item2.category);
+  EXPECT_EQ(kNetLogTracingCategory, actual_item2.category);
   EXPECT_EQ(base::StringPrintf("0x%d", entries[1].source.id), actual_item2.id);
   EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN),
             actual_item2.phase);
@@ -203,7 +207,7 @@
   EXPECT_EQ(NetLog::SourceTypeToString(entries[1].source.type),
             actual_item2.source_type);
 
-  EXPECT_EQ("netlog", actual_item3.category);
+  EXPECT_EQ(kNetLogTracingCategory, actual_item3.category);
   EXPECT_EQ(base::StringPrintf("0x%d", entries[2].source.id), actual_item3.id);
   EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END),
             actual_item3.phase);
@@ -236,7 +240,7 @@
 
   TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1);
   TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2);
-  EXPECT_EQ("netlog", actual_item1.category);
+  EXPECT_EQ(kNetLogTracingCategory, actual_item1.category);
   EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id);
   EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT),
             actual_item1.phase);
@@ -245,7 +249,7 @@
   EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type),
             actual_item1.source_type);
 
-  EXPECT_EQ("netlog", actual_item2.category);
+  EXPECT_EQ(kNetLogTracingCategory, actual_item2.category);
   EXPECT_EQ(base::StringPrintf("0x%d", entries[2].source.id), actual_item2.id);
   EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT),
             actual_item2.phase);
@@ -274,7 +278,7 @@
   ASSERT_TRUE(trace_events()->GetDictionary(0, &item1));
 
   TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1);
-  EXPECT_EQ("netlog", actual_item1.category);
+  EXPECT_EQ(kNetLogTracingCategory, actual_item1.category);
   EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id);
   EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT),
             actual_item1.phase);
@@ -342,7 +346,7 @@
 
   TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1);
   TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2);
-  EXPECT_EQ("netlog", actual_item1.category);
+  EXPECT_EQ(kNetLogTracingCategory, actual_item1.category);
   EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id);
   EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT),
             actual_item1.phase);
@@ -351,7 +355,7 @@
   EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type),
             actual_item1.source_type);
 
-  EXPECT_EQ("netlog", actual_item2.category);
+  EXPECT_EQ(kNetLogTracingCategory, actual_item2.category);
   EXPECT_EQ(base::StringPrintf("0x%d", entries[1].source.id), actual_item2.id);
   EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT),
             actual_item2.phase);
diff --git a/net/http/disk_cache_based_quic_server_info.cc b/net/http/disk_cache_based_quic_server_info.cc
index d55349e..44332c9 100644
--- a/net/http/disk_cache_based_quic_server_info.cc
+++ b/net/http/disk_cache_based_quic_server_info.cc
@@ -78,6 +78,7 @@
 void DiskCacheBasedQuicServerInfo::Start() {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(GET_BACKEND, state_);
+  load_start_time_ = base::TimeTicks::Now();
   DoLoop(OK);
 }
 
@@ -312,6 +313,8 @@
   }
   entry_ = NULL;
   Parse(data_);
+  UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheLoadTime",
+                      base::TimeTicks::Now() - load_start_time_);
   return OK;
 }
 
diff --git a/net/http/disk_cache_based_quic_server_info.h b/net/http/disk_cache_based_quic_server_info.h
index e5ced3f..f904042 100644
--- a/net/http/disk_cache_based_quic_server_info.h
+++ b/net/http/disk_cache_based_quic_server_info.h
@@ -10,6 +10,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/non_thread_safe.h"
+#include "base/time/time.h"
 #include "net/base/completion_callback.h"
 #include "net/disk_cache/disk_cache.h"
 #include "net/quic/crypto/quic_server_info.h"
@@ -98,6 +99,7 @@
   scoped_refptr<IOBuffer> read_buffer_;
   scoped_refptr<IOBuffer> write_buffer_;
   std::string data_;
+  base::TimeTicks load_start_time_;
 
   base::WeakPtrFactory<DiskCacheBasedQuicServerInfo> weak_factory_;
 };
diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc
index b5ca18b..27afbea 100644
--- a/net/quic/quic_connection_logger.cc
+++ b/net/quic/quic_connection_logger.cc
@@ -339,6 +339,8 @@
       num_incorrect_connection_ids_(0),
       num_undecryptable_packets_(0),
       num_duplicate_packets_(0),
+      num_blocked_frames_received_(0),
+      num_blocked_frames_sent_(0),
       connection_description_(GetConnectionDescriptionString()) {
 }
 
@@ -355,6 +357,10 @@
                        num_undecryptable_packets_);
   UMA_HISTOGRAM_COUNTS("Net.QuicSession.DuplicatePacketsReceived",
                        num_duplicate_packets_);
+  UMA_HISTOGRAM_COUNTS("Net.QuicSession.BlockedFrames.Received",
+                       num_blocked_frames_received_);
+  UMA_HISTOGRAM_COUNTS("Net.QuicSession.BlockedFrames.Sent",
+                       num_blocked_frames_sent_);
 
   if (num_frames_received_ > 0) {
     int duplicate_stream_frame_per_thousand =
@@ -442,6 +448,7 @@
                      frame.window_update_frame));
       break;
     case BLOCKED_FRAME:
+      ++num_blocked_frames_sent_;
       net_log_.AddEvent(
           NetLog::TYPE_QUIC_SESSION_BLOCKED_FRAME_SENT,
           base::Bind(&NetLogQuicBlockedFrameCallback,
@@ -636,6 +643,7 @@
 }
 
 void QuicConnectionLogger::OnBlockedFrame(const QuicBlockedFrame& frame) {
+  ++num_blocked_frames_received_;
   net_log_.AddEvent(
       NetLog::TYPE_QUIC_SESSION_BLOCKED_FRAME_RECEIVED,
       base::Bind(&NetLogQuicBlockedFrameCallback, &frame));
diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h
index 1d38049..29acfdc 100644
--- a/net/quic/quic_connection_logger.h
+++ b/net/quic/quic_connection_logger.h
@@ -151,6 +151,10 @@
   int num_undecryptable_packets_;
   // Count of the number of duplicate packets received.
   int num_duplicate_packets_;
+  // Count of the number of BLOCKED frames received.
+  int num_blocked_frames_received_;
+  // Count of the number of BLOCKED frames sent.
+  int num_blocked_frames_sent_;
   // Vector of inital packets status' indexed by packet sequence numbers, where
   // false means never received.  Zero is not a valid packet sequence number, so
   // that offset is never used, and we'll track 150 packets.
diff --git a/net/quic/quic_reliable_client_stream.cc b/net/quic/quic_reliable_client_stream.cc
index b1a82d1..e186b03 100644
--- a/net/quic/quic_reliable_client_stream.cc
+++ b/net/quic/quic_reliable_client_stream.cc
@@ -42,12 +42,12 @@
   return data_len;
 }
 
-void QuicReliableClientStream::OnFinRead() {
+void QuicReliableClientStream::OnClose() {
   if (delegate_) {
     delegate_->OnClose(connection_error());
     delegate_ = nullptr;
   }
-  ReliableQuicStream::OnFinRead();
+  ReliableQuicStream::OnClose();
 }
 
 void QuicReliableClientStream::OnCanWrite() {
diff --git a/net/quic/quic_reliable_client_stream.h b/net/quic/quic_reliable_client_stream.h
index 9ed6601..48f5cc9 100644
--- a/net/quic/quic_reliable_client_stream.h
+++ b/net/quic/quic_reliable_client_stream.h
@@ -55,7 +55,7 @@
 
   // QuicDataStream
   uint32 ProcessData(const char* data, uint32 data_len) override;
-  void OnFinRead() override;
+  void OnClose() override;
   void OnCanWrite() override;
   QuicPriority EffectivePriority() const override;
 
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc
index 0a5032e..4712620 100644
--- a/net/quic/quic_session_test.cc
+++ b/net/quic/quic_session_test.cc
@@ -729,23 +729,26 @@
   EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
   QuicStreamId stream_id = 5;
   // Write until the header stream is flow control blocked.
+  SpdyHeaderBlock headers;
   while (!headers_stream->flow_controller()->IsBlocked() && stream_id < 2010) {
     EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
     EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
-    SpdyHeaderBlock headers;
     headers["header"] = base::Uint64ToString(base::RandUint64()) +
         base::Uint64ToString(base::RandUint64()) +
         base::Uint64ToString(base::RandUint64());
     headers_stream->WriteHeaders(stream_id, headers, true, nullptr);
     stream_id += 2;
   }
+  // Write one more to ensure that the headers stream has buffered data. The
+  // random headers may have exactly filled the flow control window.
+  headers_stream->WriteHeaders(stream_id, headers, true, nullptr);
+  EXPECT_TRUE(headers_stream->HasBufferedData());
+
   EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked());
   EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
   EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
   EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
   EXPECT_FALSE(session_.HasDataToWrite());
-  // TODO(rtenneti): crbug.com/423586 headers_stream->HasBufferedData is flaky.
-  // EXPECT_TRUE(headers_stream->HasBufferedData());
 
   // Now complete the crypto handshake, resulting in an increased flow control
   // send window.
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index dac3096..046c0a1 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -312,7 +312,6 @@
 int QuicStreamFactory::Job::DoResolveHost() {
   // Start loading the data now, and wait for it after we resolve the host.
   if (server_info_) {
-    disk_cache_load_start_time_ = base::TimeTicks::Now();
     server_info_->Start();
   }
 
@@ -351,6 +350,7 @@
   if (!server_info_)
     return OK;
 
+  disk_cache_load_start_time_ = base::TimeTicks::Now();
   return server_info_->WaitForDataReady(
       base::Bind(&QuicStreamFactory::Job::OnIOComplete,
                  weak_factory_.GetWeakPtr()));
@@ -358,7 +358,7 @@
 
 int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) {
   if (server_info_) {
-    UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheReadTime",
+    UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime",
                         base::TimeTicks::Now() - disk_cache_load_start_time_);
   }
 
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 13a3863..1dd9fb4 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -1822,7 +1822,7 @@
 
   SynchronousErrorStreamSocket* raw_transport = transport.get();
   scoped_ptr<SSLClientSocket> sock(
-      CreateSSLClientSocket(transport.PassAs<StreamSocket>(),
+      CreateSSLClientSocket(transport.Pass(),
                             test_server.host_port_pair(),
                             kDefaultSSLConfig));
 
@@ -1859,7 +1859,7 @@
 
   SynchronousErrorStreamSocket* raw_transport = transport.get();
   scoped_ptr<SSLClientSocket> sock(
-      CreateSSLClientSocket(transport.PassAs<StreamSocket>(),
+      CreateSSLClientSocket(transport.Pass(),
                             test_server.host_port_pair(),
                             ssl_config));
 
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index 9d7ea87..fae97e8 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -70,6 +70,9 @@
 const size_t kPriorityDependencyPayloadSize = 4;
 const size_t kPriorityWeightPayloadSize = 1;
 
+// Wire size of pad length field.
+const size_t kPadLengthFieldSize = 1;
+
 }  // namespace
 
 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
@@ -379,8 +382,8 @@
       return "READING_COMMON_HEADER";
     case SPDY_CONTROL_FRAME_PAYLOAD:
       return "CONTROL_FRAME_PAYLOAD";
-    case SPDY_READ_PADDING_LENGTH:
-      return "SPDY_READ_PADDING_LENGTH";
+    case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
+      return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
     case SPDY_CONSUME_PADDING:
       return "SPDY_CONSUME_PADDING";
     case SPDY_IGNORE_REMAINING_PAYLOAD:
@@ -601,8 +604,8 @@
         break;
       }
 
-      case SPDY_READ_PADDING_LENGTH: {
-        size_t bytes_read = ProcessFramePaddingLength(data, len);
+      case SPDY_READ_DATA_FRAME_PADDING_LENGTH: {
+        size_t bytes_read = ProcessDataFramePaddingLength(data, len);
         len -= bytes_read;
         data += bytes_read;
         break;
@@ -809,7 +812,7 @@
                                   remaining_data_length_,
                                   current_frame_flags_ & DATA_FLAG_FIN);
       if (remaining_data_length_ > 0) {
-        CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
+        CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH);
       } else {
         // Empty data frame.
         if (current_frame_flags_ & DATA_FLAG_FIN) {
@@ -1083,15 +1086,23 @@
       break;
     case HEADERS:
       frame_size_without_variable_data = GetHeadersMinimumSize();
-      if (protocol_version() > SPDY3 &&
-          current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
+      if (protocol_version() > SPDY3) {
+        if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
+          frame_size_without_variable_data += kPadLengthFieldSize;
+        }
+        if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
         frame_size_without_variable_data +=
             kPriorityDependencyPayloadSize +
             kPriorityWeightPayloadSize;
+        }
       }
       break;
     case PUSH_PROMISE:
       frame_size_without_variable_data = GetPushPromiseMinimumSize();
+      if (protocol_version() > SPDY3 &&
+          current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
+        frame_size_without_variable_data += kPadLengthFieldSize;
+      }
       break;
     case CONTINUATION:
       frame_size_without_variable_data = GetContinuationMinimumSize();
@@ -1457,6 +1468,14 @@
             expect_continuation_ = current_frame_stream_id_;
             end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
           }
+          if (protocol_version() > SPDY3 &&
+              current_frame_flags_ & HEADERS_FLAG_PADDED) {
+            uint8 pad_payload_len = 0;
+            DCHECK_EQ(remaining_padding_payload_length_, 0u);
+            successful_read = reader.ReadUInt8(&pad_payload_len);
+            DCHECK(successful_read);
+            remaining_padding_payload_length_ = pad_payload_len;
+          }
           const bool has_priority =
               (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
           uint32 priority = 0;
@@ -1502,7 +1521,7 @@
                 expect_continuation_ == 0);
           }
         }
-        CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
+        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
         break;
       case PUSH_PROMISE:
         {
@@ -1511,6 +1530,17 @@
             set_error(SPDY_INVALID_CONTROL_FRAME);
             break;
           }
+          bool successful_read = true;
+          if (protocol_version() > SPDY3 &&
+              current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
+            DCHECK_EQ(remaining_padding_payload_length_, 0u);
+            uint8 pad_payload_len = 0;
+            successful_read = reader.ReadUInt8(&pad_payload_len);
+            DCHECK(successful_read);
+            remaining_padding_payload_length_ = pad_payload_len;
+          }
+        }
+        {
           SpdyStreamId promised_stream_id = kInvalidStream;
           bool successful_read = reader.ReadUInt31(&promised_stream_id);
           DCHECK(successful_read);
@@ -1533,7 +1563,7 @@
                                   (current_frame_flags_ &
                                    PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
         }
-        CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
+        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
         break;
       case CONTINUATION:
         {
@@ -2120,11 +2150,10 @@
   return processed_bytes;
 }
 
-// TODO(raullenchai): ProcessFramePaddingLength should be able to deal with
-// HEADERS_FLAG_PADDED and PUSH_PROMISE_FLAG_PADDED as well (see b/15777051).
-size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) {
-  DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_);
-  DCHECK_EQ(remaining_padding_payload_length_, 0u);
+size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) {
+  DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_);
+  DCHECK_EQ(0u, remaining_padding_payload_length_);
+  DCHECK_EQ(DATA, current_frame_type_);
 
   size_t original_len = len;
   if (current_frame_flags_ & DATA_FLAG_PADDED) {
@@ -2149,16 +2178,7 @@
     set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
     return 0;
   }
-  if (current_frame_type_ == DATA) {
-    CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
-  } else {
-    DCHECK(current_frame_type_ == HEADERS ||
-           current_frame_type_ == PUSH_PROMISE ||
-           current_frame_type_ == SYN_STREAM ||
-           current_frame_type_ == SYN_REPLY)
-        << current_frame_type_;
-    CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
-  }
+  CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
   return original_len - len;
 }
 
@@ -2606,11 +2626,20 @@
     if (headers.has_priority()) {
       flags |= HEADERS_FLAG_PRIORITY;
     }
+    if (headers.padded()) {
+      flags |= HEADERS_FLAG_PADDED;
+    }
   }
 
-  // The size of this frame, including variable-length name-value block.
+  // The size of this frame, including padding (if there is any)
+  // and variable-length name-value block.
   size_t size = GetHeadersMinimumSize();
 
+  if (protocol_version() > SPDY3 && headers.padded()) {
+    size += kPadLengthFieldSize;
+    size += headers.padding_payload_len();
+  }
+
   uint32 priority = headers.priority();
   if (headers.has_priority()) {
     if (priority > GetLowestPriority()) {
@@ -2655,6 +2684,11 @@
   DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
 
   if (protocol_version() > SPDY3) {
+    int padding_payload_len = 0;
+    if (headers.padded()) {
+      builder.WriteUInt8(headers.padding_payload_len());
+      padding_payload_len = headers.padding_payload_len();
+    }
     if (headers.has_priority()) {
       // TODO(jgraettinger): Plumb priorities and stream dependencies.
       builder.WriteUInt32(0);  // Non-exclusive bit and root stream ID.
@@ -2663,7 +2697,8 @@
     WritePayloadWithContinuation(&builder,
                                  hpack_encoding,
                                  headers.stream_id(),
-                                 HEADERS);
+                                 HEADERS,
+                                 padding_payload_len);
   } else {
     SerializeNameValueBlock(&builder, headers);
   }
@@ -2717,6 +2752,12 @@
   // The size of this frame, including variable-length name-value block.
   size_t size = GetPushPromiseMinimumSize();
 
+  if (push_promise.padded()) {
+    flags |= PUSH_PROMISE_FLAG_PADDED;
+    size += kPadLengthFieldSize;
+    size += push_promise.padding_payload_len();
+  }
+
   string hpack_encoding;
   if (enable_compression_) {
     GetHpackEncoder()->EncodeHeaderSet(
@@ -2737,13 +2778,24 @@
                         PUSH_PROMISE,
                         flags,
                         push_promise.stream_id());
-  builder.WriteUInt32(push_promise.promised_stream_id());
-  DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
+  int padding_payload_len = 0;
+  if (push_promise.padded()) {
+    builder.WriteUInt8(push_promise.padding_payload_len());
+    builder.WriteUInt32(push_promise.promised_stream_id());
+    DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize,
+              builder.length());
+
+    padding_payload_len = push_promise.padding_payload_len();
+  } else {
+    builder.WriteUInt32(push_promise.promised_stream_id());
+    DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
+  }
 
   WritePayloadWithContinuation(&builder,
                                hpack_encoding,
                                push_promise.stream_id(),
-                               PUSH_PROMISE);
+                               PUSH_PROMISE,
+                               padding_payload_len);
 
   if (debug_visitor_) {
     // SPDY4 uses HPACK for header compression. However, continue to
@@ -2923,32 +2975,34 @@
 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
                                               const string& hpack_encoding,
                                               SpdyStreamId stream_id,
-                                              SpdyFrameType type) {
+                                              SpdyFrameType type,
+                                              int padding_payload_len) {
   const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize();
 
-    // In addition to the prefix, fixed_field_size includes the size of
-    // any fields that come before the variable-length name/value block.
-    size_t fixed_field_size = 0;
     uint8 end_flag = 0;
     uint8 flags = 0;
     if (type == HEADERS) {
-      fixed_field_size = GetHeadersMinimumSize();
       end_flag = HEADERS_FLAG_END_HEADERS;
     } else if (type == PUSH_PROMISE) {
-      fixed_field_size = GetPushPromiseMinimumSize();
       end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
     } else {
       DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
                   << FrameTypeToString(type);
     }
 
-    // Write as much of the payload as possible into the initial frame.
-    size_t bytes_remaining = hpack_encoding.size() -
-        std::min(hpack_encoding.size(),
-                 kMaxControlFrameSize - fixed_field_size);
+    // Write all the padding payload and as much of the data payload as possible
+    // into the initial frame.
+    size_t bytes_remaining = 0;
+    bytes_remaining = hpack_encoding.size() -
+                      std::min(hpack_encoding.size(),
+                               kMaxControlFrameSize - builder->length() -
+                                   padding_payload_len);
     builder->WriteBytes(&hpack_encoding[0],
                         hpack_encoding.size() - bytes_remaining);
-
+    if (padding_payload_len > 0) {
+      string padding = string(padding_payload_len, 0);
+      builder->WriteBytes(padding.data(), padding.length());
+    }
     if (bytes_remaining > 0) {
       builder->OverwriteLength(*this,
           kMaxControlFrameSize - GetControlFrameHeaderSize());
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h
index 42711c2..99db36a 100644
--- a/net/spdy/spdy_framer.h
+++ b/net/spdy/spdy_framer.h
@@ -336,7 +336,7 @@
     SPDY_AUTO_RESET,
     SPDY_READING_COMMON_HEADER,
     SPDY_CONTROL_FRAME_PAYLOAD,
-    SPDY_READ_PADDING_LENGTH,
+    SPDY_READ_DATA_FRAME_PADDING_LENGTH,
     SPDY_CONSUME_PADDING,
     SPDY_IGNORE_REMAINING_PAYLOAD,
     SPDY_FORWARD_STREAM_FRAME,
@@ -601,6 +601,8 @@
                            UnclosedStreamDataCompressorsOneByteAtATime);
   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
                            UncompressLargerThanFrameBufferInitialSize);
+  FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
+                           CreatePushPromiseThenContinuationUncompressed);
   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ReadLargeSettingsFrame);
   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
                            ReadLargeSettingsFrameInSmallChunks);
@@ -634,7 +636,7 @@
   size_t ProcessControlFrameHeaderBlock(const char* data,
                                         size_t len,
                                         bool is_hpack_header_block);
-  size_t ProcessFramePaddingLength(const char* data, size_t len);
+  size_t ProcessDataFramePaddingLength(const char* data, size_t len);
   size_t ProcessFramePadding(const char* data, size_t len);
   size_t ProcessDataFramePayload(const char* data, size_t len);
   size_t ProcessGoAwayFramePayload(const char* data, size_t len);
@@ -672,7 +674,8 @@
   void WritePayloadWithContinuation(SpdyFrameBuilder* builder,
                                     const std::string& hpack_encoding,
                                     SpdyStreamId stream_id,
-                                    SpdyFrameType type);
+                                    SpdyFrameType type,
+                                    int padding_payload_len);
 
  private:
   // Deliver the given control frame's uncompressed headers block to the
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc
index 35b8a46..84ea0d7 100644
--- a/net/spdy/spdy_framer_test.cc
+++ b/net/spdy/spdy_framer_test.cc
@@ -2805,6 +2805,35 @@
       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
     }
   }
+
+  {
+    const char kDescription[] =
+        "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
+
+    const unsigned char kV4FrameData[] = {
+        0x00, 0x00, 0x15, 0x01,  // Headers
+        0x0d, 0x7f, 0xff, 0xff,  // FIN | END_HEADERS | PADDED, Stream
+                                 // 0x7fffffff
+        0xff, 0x05, 0x00, 0x00,  // Pad length field
+        0x03, 0x66, 0x6f, 0x6f,  // .foo
+        0x00, 0x03, 0x66, 0x6f,  // @.fo
+        0x6f, 0x03, 0x62, 0x61,  // o.ba
+        0x72,                    // r
+        // Padding payload
+        0x00, 0x00, 0x00, 0x00, 0x00,
+    };
+    SpdyHeadersIR headers_ir(0x7fffffff);
+    headers_ir.set_fin(true);
+    headers_ir.SetHeader("", "foo");
+    headers_ir.SetHeader("foo", "bar");
+    headers_ir.set_padding_len(6);
+    scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+    if (IsSpdy2() || IsSpdy3()) {
+      // Padding is not supported.
+    } else {
+      CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
+    }
+  }
 }
 
 // TODO(phajdan.jr): Clean up after we no longer need
@@ -2982,27 +3011,98 @@
     return;
   }
 
-  SpdyFramer framer(spdy_version_);
-  framer.set_enable_compression(false);
-  const char kDescription[] = "PUSH_PROMISE frame";
+  {
+    // Test framing PUSH_PROMISE without padding.
+    SpdyFramer framer(spdy_version_);
+    framer.set_enable_compression(false);
+    const char kDescription[] = "PUSH_PROMISE frame without padding";
 
-  const unsigned char kFrameData[] = {
-    0x00, 0x00, 0x16, 0x05, 0x04,  // PUSH_PROMISE: END_HEADERS
-    0x00, 0x00, 0x00, 0x2a,  // Stream 42
-    0x00, 0x00, 0x00, 0x39,  // Promised stream 57
-    0x00, 0x03, 0x62, 0x61,  // @.ba
-    0x72, 0x03, 0x66, 0x6f,  // r.fo
-    0x6f, 0x00, 0x03, 0x66,  // o@.f
-    0x6f, 0x6f, 0x03, 0x62,  // oo.b
-    0x61, 0x72,              // ar
-  };
+    const unsigned char kFrameData[] = {
+        0x00, 0x00, 0x16, 0x05,  // PUSH_PROMISE
+        0x04, 0x00, 0x00, 0x00,  // END_HEADERS
+        0x2a, 0x00, 0x00, 0x00,  // Stream 42
+        0x39, 0x00, 0x03, 0x62,  // Promised stream 57, @.b
+        0x61, 0x72, 0x03, 0x66,  // ar.f
+        0x6f, 0x6f, 0x00, 0x03,  // oo@.
+        0x66, 0x6f, 0x6f, 0x03,  // foo.
+        0x62, 0x61, 0x72,        // bar
+    };
 
-  SpdyPushPromiseIR push_promise(42, 57);
-  push_promise.SetHeader("bar", "foo");
-  push_promise.SetHeader("foo", "bar");
-  scoped_ptr<SpdySerializedFrame> frame(
-    framer.SerializePushPromise(push_promise));
-  CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+    SpdyPushPromiseIR push_promise(42, 57);
+    push_promise.SetHeader("bar", "foo");
+    push_promise.SetHeader("foo", "bar");
+    scoped_ptr<SpdySerializedFrame> frame(
+        framer.SerializePushPromise(push_promise));
+    CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+  }
+
+  {
+    // Test framing PUSH_PROMISE with one byte of padding.
+    SpdyFramer framer(spdy_version_);
+    framer.set_enable_compression(false);
+    const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
+
+    const unsigned char kFrameData[] = {
+        0x00, 0x00, 0x17, 0x05,  // PUSH_PROMISE
+        0x0c, 0x00, 0x00, 0x00,  // END_HEADERS | PADDED
+        0x2a, 0x00, 0x00, 0x00,  // Stream 42, Pad length field
+        0x00, 0x39, 0x00, 0x03,  // Promised stream 57
+        0x62, 0x61, 0x72, 0x03,  // bar.
+        0x66, 0x6f, 0x6f, 0x00,  // foo@
+        0x03, 0x66, 0x6f, 0x6f,  // .foo
+        0x03, 0x62, 0x61, 0x72,  // .bar
+    };
+
+    SpdyPushPromiseIR push_promise(42, 57);
+    push_promise.set_padding_len(1);
+    push_promise.SetHeader("bar", "foo");
+    push_promise.SetHeader("foo", "bar");
+    scoped_ptr<SpdySerializedFrame> frame(
+        framer.SerializePushPromise(push_promise));
+    CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+  }
+
+  {
+    // Test framing PUSH_PROMISE with 177 bytes of padding.
+    SpdyFramer framer(spdy_version_);
+    framer.set_enable_compression(false);
+    const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
+
+    const unsigned char kFrameData[] = {
+        0x00, 0x00, 0xc7, 0x05,  // PUSH_PROMISE
+        0x0c, 0x00, 0x00, 0x00,  // END_HEADERS | PADDED
+        0x2a, 0xb0, 0x00, 0x00,  // Stream 42, Pad length field
+        0x00, 0x39, 0x00, 0x03,  // Promised stream 57
+        0x62, 0x61, 0x72, 0x03,  // bar.
+        0x66, 0x6f, 0x6f, 0x00,  // foo@
+        0x03, 0x66, 0x6f, 0x6f,  // .foo
+        0x03, 0x62, 0x61, 0x72,  // .bar
+        // Padding of 176 0x00(s).
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    };
+
+    SpdyPushPromiseIR push_promise(42, 57);
+    push_promise.set_padding_len(177);
+    push_promise.SetHeader("bar", "foo");
+    push_promise.SetHeader("foo", "bar");
+    scoped_ptr<SpdySerializedFrame> frame(
+        framer.SerializePushPromise(push_promise));
+    CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+  }
 }
 
 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
@@ -3032,6 +3132,107 @@
   CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
 }
 
+TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
+  if (spdy_version_ <= SPDY3) {
+    return;
+  }
+
+  {
+    // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
+    // padding, cannot hold all the data payload, which is overflowed to the
+    // consecutive CONTINUATION frame.
+    SpdyFramer framer(spdy_version_);
+    framer.set_enable_compression(false);
+    const char kDescription[] =
+        "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
+
+    const unsigned char kPartialPushPromiseFrameData[] = {
+        0x00, 0x03, 0xf6, 0x05,  // PUSH_PROMISE
+        0x08, 0x00, 0x00, 0x00,  // PADDED
+        0x2a, 0x00, 0x00, 0x00,  // Stream 42
+        0x00, 0x39, 0x00, 0x03,  // Promised stream 57
+        0x78, 0x78, 0x78, 0x7f,  // xxx.
+        0x80, 0x07, 0x78, 0x78,  // ..xx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78,              // xx
+    };
+
+    const unsigned char kContinuationFrameData[] = {
+        0x00, 0x00, 0x16, 0x09,  // CONTINUATION
+        0x04, 0x00, 0x00, 0x00,  // END_HEADERS
+        0x2a, 0x78, 0x78, 0x78,  // Stream 42, xxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78, 0x78, 0x78,  // xxxx
+        0x78, 0x78,
+    };
+
+    SpdyPushPromiseIR push_promise(42, 57);
+    push_promise.set_padding_len(1);
+    string big_value(framer.GetHeaderFragmentMaxSize(), 'x');
+    push_promise.SetHeader("xxx", big_value);
+    scoped_ptr<SpdySerializedFrame> frame(
+        framer.SerializePushPromise(push_promise));
+
+    // The entire frame should look like below:
+    // Name                     Length in Byte
+    // ------------------------------------------- Begin of PUSH_PROMISE frame
+    // PUSH_PROMISE header      9
+    // Pad length field         1
+    // Promised stream          4
+    // Length field of key      2
+    // Content of key           3
+    // Length field of value    3
+    // Part of big_value        16361
+    // ------------------------------------------- Begin of CONTINUATION frame
+    // CONTINUATION header      9
+    // Remaining of big_value   22
+    // ------------------------------------------- End
+
+    // Length of everything listed above except big_value.
+    int len_non_data_payload = 31;
+    EXPECT_EQ(framer.GetHeaderFragmentMaxSize() + len_non_data_payload,
+              frame->size());
+
+    // Partially compare the PUSH_PROMISE frame against the template.
+    const unsigned char* frame_data =
+        reinterpret_cast<const unsigned char*>(frame->data());
+    CompareCharArraysWithHexError(kDescription,
+                                  frame_data,
+                                  arraysize(kPartialPushPromiseFrameData),
+                                  kPartialPushPromiseFrameData,
+                                  arraysize(kPartialPushPromiseFrameData));
+
+    // Compare the CONTINUATION frame against the template.
+    frame_data += framer.GetHeaderFragmentMaxSize();
+    CompareCharArraysWithHexError(kDescription,
+                                  frame_data,
+                                  arraysize(kContinuationFrameData),
+                                  kContinuationFrameData,
+                                  arraysize(kContinuationFrameData));
+  }
+}
+
 TEST_P(SpdyFramerTest, CreateAltSvc) {
   if (spdy_version_ <= SPDY3) {
     return;
@@ -3263,6 +3464,7 @@
   SpdyFramer framer(spdy_version_);
   framer.set_enable_compression(false);
   SpdyHeadersIR headers(1);
+  headers.set_padding_len(256);
 
   // Exact payload length will change with HPACK, but this should be long
   // enough to cause an overflow.
@@ -3291,6 +3493,7 @@
   SpdyFramer framer(spdy_version_);
   framer.set_enable_compression(false);
   SpdyPushPromiseIR push_promise(1, 2);
+  push_promise.set_padding_len(256);
 
   // Exact payload length will change with HPACK, but this should be long
   // enough to cause an overflow.
@@ -3729,7 +3932,7 @@
   CHECK_EQ(framer.GetDataFrameMinimumSize(),
            framer.ProcessInput(frame->data(),
                                framer.GetDataFrameMinimumSize()));
-  CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_PADDING_LENGTH);
+  CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
   CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
   bytes_consumed += framer.GetDataFrameMinimumSize();
 
@@ -3966,31 +4169,31 @@
   }
 
   const unsigned char kInput[] = {
-    0x00, 0x00, 0x17, 0x05, 0x08,  // PUSH_PROMISE: PADDED
-    0x00, 0x00, 0x00, 0x01,  // Stream 1
-    0x00, 0x00, 0x00, 0x2A,  // Promised stream 42
-    0x02,                    // Padding of 2.
-    0x00, 0x06, 0x63, 0x6f,
-    0x6f, 0x6b, 0x69, 0x65,
-    0x07, 0x66, 0x6f, 0x6f,
-    0x3d, 0x62, 0x61, 0x72,
-    0x00, 0x00,
+    0x00, 0x00, 0x17, 0x05,  // PUSH_PROMISE
+    0x08, 0x00, 0x00, 0x00,  // PADDED
+    0x01, 0x02, 0x00, 0x00,  // Stream 1, Pad length field
+    0x00, 0x2A, 0x00, 0x06,  // Promised stream 42
+    0x63, 0x6f, 0x6f, 0x6b,
+    0x69, 0x65, 0x07, 0x66,
+    0x6f, 0x6f, 0x3d, 0x62,
+    0x61, 0x72, 0x00, 0x00,
 
-    0x00, 0x00, 0x14, 0x09, 0x00,  // CONTINUATION
-    0x00, 0x00, 0x00, 0x01,  // Stream 1
-    0x00, 0x06, 0x63, 0x6f,
-    0x6f, 0x6b, 0x69, 0x65,
-    0x08, 0x62, 0x61, 0x7a,
-    0x3d, 0x62, 0x69, 0x6e,
-    0x67, 0x00, 0x06, 0x63,
-
-    0x00, 0x00, 0x12, 0x09, 0x04,  // CONTINUATION: END_HEADERS
-    0x00, 0x00, 0x00, 0x01,  // Stream 1
+    0x00, 0x00, 0x14, 0x09,  // CONTINUATION
+    0x00, 0x00, 0x00, 0x00,
+    0x01, 0x00, 0x06, 0x63,  // Stream 1
     0x6f, 0x6f, 0x6b, 0x69,
-    0x65, 0x00, 0x00, 0x04,
-    0x6e, 0x61, 0x6d, 0x65,
-    0x05, 0x76, 0x61, 0x6c,
-    0x75, 0x65,
+    0x65, 0x08, 0x62, 0x61,
+    0x7a, 0x3d, 0x62, 0x69,
+    0x6e, 0x67, 0x00, 0x06,
+    0x63,
+
+    0x00, 0x00, 0x12, 0x09,  // CONTINUATION
+    0x04, 0x00, 0x00, 0x00,  // END_HEADERS
+    0x01, 0x6f, 0x6f, 0x6b,  // Stream 1
+    0x69, 0x65, 0x00, 0x00,
+    0x04, 0x6e, 0x61, 0x6d,
+    0x65, 0x05, 0x76, 0x61,
+    0x6c, 0x75, 0x65,
   };
 
   SpdyFramer framer(spdy_version_);
diff --git a/net/spdy/spdy_protocol.h b/net/spdy/spdy_protocol.h
index c408f0a..3a979b9 100644
--- a/net/spdy/spdy_protocol.h
+++ b/net/spdy/spdy_protocol.h
@@ -845,9 +845,11 @@
 class NET_EXPORT_PRIVATE SpdyHeadersIR : public SpdyFrameWithNameValueBlockIR {
  public:
   explicit SpdyHeadersIR(SpdyStreamId stream_id)
-    : SpdyFrameWithNameValueBlockIR(stream_id),
-      has_priority_(false),
-      priority_(0) {}
+      : SpdyFrameWithNameValueBlockIR(stream_id),
+        has_priority_(false),
+        priority_(0),
+        padded_(false),
+        padding_payload_len_(0) {}
 
   void Visit(SpdyFrameVisitor* visitor) const override;
 
@@ -856,10 +858,24 @@
   uint32 priority() const { return priority_; }
   void set_priority(SpdyPriority priority) { priority_ = priority; }
 
+  bool padded() const { return padded_; }
+  int padding_payload_len() const { return padding_payload_len_; }
+  void set_padding_len(int padding_len) {
+    DCHECK_GT(padding_len, 0);
+    DCHECK_LE(padding_len, kPaddingSizePerFrame);
+    padded_ = true;
+    // The pad field takes one octet on the wire.
+    padding_payload_len_ = padding_len - 1;
+  }
+
  private:
   bool has_priority_;
   // 31-bit priority.
   uint32 priority_;
+
+  bool padded_;
+  int padding_payload_len_;
+
   DISALLOW_COPY_AND_ASSIGN(SpdyHeadersIR);
 };
 
@@ -901,14 +917,30 @@
  public:
   SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id)
       : SpdyFrameWithNameValueBlockIR(stream_id),
-        promised_stream_id_(promised_stream_id) {}
+        promised_stream_id_(promised_stream_id),
+        padded_(false),
+        padding_payload_len_(0) {}
   SpdyStreamId promised_stream_id() const { return promised_stream_id_; }
   void set_promised_stream_id(SpdyStreamId id) { promised_stream_id_ = id; }
 
   void Visit(SpdyFrameVisitor* visitor) const override;
 
+  bool padded() const { return padded_; }
+  int padding_payload_len() const { return padding_payload_len_; }
+  void set_padding_len(int padding_len) {
+    DCHECK_GT(padding_len, 0);
+    DCHECK_LE(padding_len, kPaddingSizePerFrame);
+    padded_ = true;
+    // The pad field takes one octet on the wire.
+    padding_payload_len_ = padding_len - 1;
+  }
+
  private:
   SpdyStreamId promised_stream_id_;
+
+  bool padded_;
+  int padding_payload_len_;
+
   DISALLOW_COPY_AND_ASSIGN(SpdyPushPromiseIR);
 };
 
diff --git a/net/ssl/default_channel_id_store.cc b/net/ssl/default_channel_id_store.cc
index b71d7b3..60e06ed 100644
--- a/net/ssl/default_channel_id_store.cc
+++ b/net/ssl/default_channel_id_store.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
+#include "base/profiler/scoped_profile.h"
 #include "net/base/net_errors.h"
 
 namespace net {
@@ -61,6 +62,11 @@
 
 void DefaultChannelIDStore::GetChannelIDTask::Run(
     DefaultChannelIDStore* store) {
+  // TODO(vadimt): Remove ScopedProfile below once crbug.com/425814 is fixed.
+  tracked_objects::ScopedProfile tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "425814 DefaultChannelIDStore::GetChannelIDTask::Run"));
+
   base::Time expiration_time;
   std::string private_key_result;
   std::string cert_result;
@@ -112,6 +118,11 @@
 
 void DefaultChannelIDStore::SetChannelIDTask::Run(
     DefaultChannelIDStore* store) {
+  // TODO(vadimt): Remove ScopedProfile below once crbug.com/425814 is fixed.
+  tracked_objects::ScopedProfile tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "425814 DefaultChannelIDStore::SetChannelIDTask::Run"));
+
   store->SyncSetChannelID(server_identifier_, creation_time_,
                           expiration_time_, private_key_, cert_);
 }
@@ -145,6 +156,11 @@
 
 void DefaultChannelIDStore::DeleteChannelIDTask::Run(
     DefaultChannelIDStore* store) {
+  // TODO(vadimt): Remove ScopedProfile below once crbug.com/425814 is fixed.
+  tracked_objects::ScopedProfile tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "425814 DefaultChannelIDStore::DeleteChannelIDTask::Run"));
+
   store->SyncDeleteChannelID(server_identifier_);
 
   InvokeCallback(callback_);
@@ -183,6 +199,11 @@
 
 void DefaultChannelIDStore::DeleteAllCreatedBetweenTask::Run(
     DefaultChannelIDStore* store) {
+  // TODO(vadimt): Remove ScopedProfile below once crbug.com/425814 is fixed.
+  tracked_objects::ScopedProfile tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "425814 DefaultChannelIDStore::DeleteAllCreatedBetweenTask::Run"));
+
   store->SyncDeleteAllCreatedBetween(delete_begin_, delete_end_);
 
   InvokeCallback(callback_);
@@ -213,6 +234,11 @@
 
 void DefaultChannelIDStore::GetAllChannelIDsTask::Run(
     DefaultChannelIDStore* store) {
+  // TODO(vadimt): Remove ScopedProfile below once crbug.com/425814 is fixed.
+  tracked_objects::ScopedProfile tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "425814 DefaultChannelIDStore::GetAllChannelIDsTask::Run"));
+
   ChannelIDList cert_list;
   store->SyncGetAllChannelIDs(&cert_list);
 
diff --git a/skia/ext/SkDiscardableMemory_chrome.h b/skia/ext/SkDiscardableMemory_chrome.h
index 18088c5..50946e6 100644
--- a/skia/ext/SkDiscardableMemory_chrome.h
+++ b/skia/ext/SkDiscardableMemory_chrome.h
@@ -13,12 +13,12 @@
 // base::DiscardableMemory.
 class SK_API SkDiscardableMemoryChrome : public SkDiscardableMemory {
 public:
-  virtual ~SkDiscardableMemoryChrome();
+ ~SkDiscardableMemoryChrome() override;
 
   // SkDiscardableMemory:
-  virtual bool lock() override;
-  virtual void* data() override;
-  virtual void unlock() override;
+ bool lock() override;
+ void* data() override;
+ void unlock() override;
 
 private:
   friend class SkDiscardableMemory;
diff --git a/skia/ext/analysis_canvas.h b/skia/ext/analysis_canvas.h
index d3d3b80..abedcaf 100644
--- a/skia/ext/analysis_canvas.h
+++ b/skia/ext/analysis_canvas.h
@@ -18,7 +18,7 @@
 class SK_API AnalysisCanvas : public SkCanvas, public SkDrawPictureCallback {
  public:
   AnalysisCanvas(int width, int height);
-  virtual ~AnalysisCanvas();
+  ~AnalysisCanvas() override;
 
   // Returns true when a SkColor can be used to represent result.
   bool GetColorIfSolid(SkColor* color) const;
@@ -27,92 +27,93 @@
   void SetForceNotTransparent(bool flag);
 
   // SkDrawPictureCallback override.
-  virtual bool abortDrawing() override;
+  bool abortDrawing() override;
 
   // SkCanvas overrides.
-  virtual void clear(SkColor) override;
-  virtual void drawPaint(const SkPaint& paint) override;
-  virtual void drawPoints(PointMode,
-                          size_t count,
-                          const SkPoint pts[],
-                          const SkPaint&) override;
-  virtual void drawOval(const SkRect&, const SkPaint&) override;
-  virtual void drawRect(const SkRect&, const SkPaint&) override;
-  virtual void drawRRect(const SkRRect&, const SkPaint&) override;
-  virtual void drawPath(const SkPath& path, const SkPaint&) override;
-  virtual void drawBitmap(const SkBitmap&,
-                          SkScalar left,
-                          SkScalar top,
-                          const SkPaint* paint = NULL) override;
-  virtual void drawBitmapRectToRect(const SkBitmap&,
-                                    const SkRect* src,
-                                    const SkRect& dst,
-                                    const SkPaint* paint,
-                                    DrawBitmapRectFlags flags) override;
-  virtual void drawBitmapMatrix(const SkBitmap&,
-                                const SkMatrix&,
-                                const SkPaint* paint = NULL) override;
-  virtual void drawBitmapNine(const SkBitmap& bitmap,
-                              const SkIRect& center,
-                              const SkRect& dst,
-                              const SkPaint* paint = NULL) override;
-  virtual void drawSprite(const SkBitmap&, int left, int top,
-                          const SkPaint* paint = NULL) override;
-  virtual void drawVertices(VertexMode,
-                            int vertexCount,
-                            const SkPoint vertices[],
-                            const SkPoint texs[],
-                            const SkColor colors[],
-                            SkXfermode*,
-                            const uint16_t indices[],
-                            int indexCount,
-                            const SkPaint&) override;
+  void clear(SkColor) override;
+  void drawPaint(const SkPaint& paint) override;
+  void drawPoints(PointMode,
+                  size_t count,
+                  const SkPoint pts[],
+                  const SkPaint&) override;
+  void drawOval(const SkRect&, const SkPaint&) override;
+  void drawRect(const SkRect&, const SkPaint&) override;
+  void drawRRect(const SkRRect&, const SkPaint&) override;
+  void drawPath(const SkPath& path, const SkPaint&) override;
+  void drawBitmap(const SkBitmap&,
+                  SkScalar left,
+                  SkScalar top,
+                  const SkPaint* paint = NULL) override;
+  void drawBitmapRectToRect(const SkBitmap&,
+                            const SkRect* src,
+                            const SkRect& dst,
+                            const SkPaint* paint,
+                            DrawBitmapRectFlags flags) override;
+  void drawBitmapMatrix(const SkBitmap&,
+                        const SkMatrix&,
+                        const SkPaint* paint = NULL) override;
+  void drawBitmapNine(const SkBitmap& bitmap,
+                      const SkIRect& center,
+                      const SkRect& dst,
+                      const SkPaint* paint = NULL) override;
+  void drawSprite(const SkBitmap&,
+                  int left,
+                  int top,
+                  const SkPaint* paint = NULL) override;
+  void drawVertices(VertexMode,
+                    int vertexCount,
+                    const SkPoint vertices[],
+                    const SkPoint texs[],
+                    const SkColor colors[],
+                    SkXfermode*,
+                    const uint16_t indices[],
+                    int indexCount,
+                    const SkPaint&) override;
 
  protected:
-  virtual void willSave() override;
-  virtual SaveLayerStrategy willSaveLayer(const SkRect*,
-                                          const SkPaint*,
-                                          SaveFlags) override;
-  virtual void willRestore() override;
+  void willSave() override;
+  SaveLayerStrategy willSaveLayer(const SkRect*,
+                                  const SkPaint*,
+                                  SaveFlags) override;
+  void willRestore() override;
 
-  virtual void onClipRect(const SkRect& rect,
-                          SkRegion::Op op,
-                          ClipEdgeStyle edge_style) override;
-  virtual void onClipRRect(const SkRRect& rrect,
-                           SkRegion::Op op,
-                           ClipEdgeStyle edge_style) override;
-  virtual void onClipPath(const SkPath& path,
-                          SkRegion::Op op,
-                          ClipEdgeStyle edge_style) override;
-  virtual void onClipRegion(const SkRegion& deviceRgn,
-                            SkRegion::Op op) override;
+  void onClipRect(const SkRect& rect,
+                  SkRegion::Op op,
+                  ClipEdgeStyle edge_style) override;
+  void onClipRRect(const SkRRect& rrect,
+                   SkRegion::Op op,
+                   ClipEdgeStyle edge_style) override;
+  void onClipPath(const SkPath& path,
+                  SkRegion::Op op,
+                  ClipEdgeStyle edge_style) override;
+  void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) override;
 
-  virtual void onDrawText(const void* text,
-                          size_t byteLength,
-                          SkScalar x,
-                          SkScalar y,
-                          const SkPaint&) override;
-  virtual void onDrawPosText(const void* text,
-                             size_t byteLength,
-                             const SkPoint pos[],
-                             const SkPaint&) override;
-  virtual void onDrawPosTextH(const void* text,
-                              size_t byteLength,
-                              const SkScalar xpos[],
-                              SkScalar constY,
-                              const SkPaint&) override;
-  virtual void onDrawTextOnPath(const void* text,
-                                size_t byteLength,
-                                const SkPath& path,
-                                const SkMatrix* matrix,
-                                const SkPaint&) override;
-  virtual void onDrawTextBlob(const SkTextBlob* blob,
-                              SkScalar x,
-                              SkScalar y,
-                              const SkPaint& paint) override;
-  virtual void onDrawDRRect(const SkRRect& outer,
-                            const SkRRect& inner,
-                            const SkPaint&) override;
+  void onDrawText(const void* text,
+                  size_t byteLength,
+                  SkScalar x,
+                  SkScalar y,
+                  const SkPaint&) override;
+  void onDrawPosText(const void* text,
+                     size_t byteLength,
+                     const SkPoint pos[],
+                     const SkPaint&) override;
+  void onDrawPosTextH(const void* text,
+                      size_t byteLength,
+                      const SkScalar xpos[],
+                      SkScalar constY,
+                      const SkPaint&) override;
+  void onDrawTextOnPath(const void* text,
+                        size_t byteLength,
+                        const SkPath& path,
+                        const SkMatrix* matrix,
+                        const SkPaint&) override;
+  void onDrawTextBlob(const SkTextBlob* blob,
+                      SkScalar x,
+                      SkScalar y,
+                      const SkPaint& paint) override;
+  void onDrawDRRect(const SkRRect& outer,
+                    const SkRRect& inner,
+                    const SkPaint&) override;
 
   void OnComplexClip();
 
diff --git a/skia/ext/benchmarking_canvas.cc b/skia/ext/benchmarking_canvas.cc
index f3f8cc5..64d3f6c 100644
--- a/skia/ext/benchmarking_canvas.cc
+++ b/skia/ext/benchmarking_canvas.cc
@@ -29,8 +29,7 @@
     setProxy(canvas_.get());
   }
 
-  virtual ~TimingCanvas() {
-  }
+  ~TimingCanvas() override {}
 
   double GetTime(size_t index) {
     TimingsMap::const_iterator timing_info = timings_map_.find(index);
@@ -40,149 +39,172 @@
   }
 
   // SkCanvas overrides.
-  virtual void willSave() override {
+  void willSave() override {
     AutoStamper stamper(this);
     SkProxyCanvas::willSave();
   }
 
-  virtual SaveLayerStrategy willSaveLayer(const SkRect* bounds,
-                                          const SkPaint* paint,
-                                          SaveFlags flags) override {
+  SaveLayerStrategy willSaveLayer(const SkRect* bounds,
+                                  const SkPaint* paint,
+                                  SaveFlags flags) override {
     AutoStamper stamper(this);
     return SkProxyCanvas::willSaveLayer(bounds, paint, flags);
   }
 
-  virtual void willRestore() override {
+  void willRestore() override {
     AutoStamper stamper(this);
     SkProxyCanvas::willRestore();
   }
 
-  virtual void drawPaint(const SkPaint& paint) override {
+  void drawPaint(const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawPaint(paint);
   }
 
-  virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
-                          const SkPaint& paint) override {
+  void drawPoints(PointMode mode,
+                  size_t count,
+                  const SkPoint pts[],
+                  const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawPoints(mode, count, pts, paint);
   }
 
-  virtual void drawOval(const SkRect& rect, const SkPaint& paint) override {
+  void drawOval(const SkRect& rect, const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawOval(rect, paint);
   }
 
-  virtual void drawRect(const SkRect& rect, const SkPaint& paint) override {
+  void drawRect(const SkRect& rect, const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawRect(rect, paint);
   }
 
-  virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint) override {
+  void drawRRect(const SkRRect& rrect, const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawRRect(rrect, paint);
   }
 
-  virtual void drawPath(const SkPath& path, const SkPaint& paint) override {
+  void drawPath(const SkPath& path, const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawPath(path, paint);
   }
 
-  virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
-                          const SkPaint* paint = NULL) override {
+  void drawBitmap(const SkBitmap& bitmap,
+                  SkScalar left,
+                  SkScalar top,
+                  const SkPaint* paint = NULL) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawBitmap(bitmap, left, top, paint);
   }
 
-  virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
-                                    const SkRect& dst,
-                                    const SkPaint* paint,
-                                    DrawBitmapRectFlags flags) override {
+  void drawBitmapRectToRect(const SkBitmap& bitmap,
+                            const SkRect* src,
+                            const SkRect& dst,
+                            const SkPaint* paint,
+                            DrawBitmapRectFlags flags) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawBitmapRectToRect(bitmap, src, dst, paint, flags);
   }
 
-  virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
-                                const SkPaint* paint = NULL) override {
+  void drawBitmapMatrix(const SkBitmap& bitmap,
+                        const SkMatrix& m,
+                        const SkPaint* paint = NULL) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawBitmapMatrix(bitmap, m, paint);
   }
 
-  virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
-                          const SkPaint* paint = NULL) override {
+  void drawSprite(const SkBitmap& bitmap,
+                  int left,
+                  int top,
+                  const SkPaint* paint = NULL) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawSprite(bitmap, left, top, paint);
   }
 
-  virtual void drawVertices(VertexMode vmode, int vertexCount,
-                            const SkPoint vertices[], const SkPoint texs[],
-                            const SkColor colors[], SkXfermode* xmode,
-                            const uint16_t indices[], int indexCount,
-                            const SkPaint& paint) override {
+  void drawVertices(VertexMode vmode,
+                    int vertexCount,
+                    const SkPoint vertices[],
+                    const SkPoint texs[],
+                    const SkColor colors[],
+                    SkXfermode* xmode,
+                    const uint16_t indices[],
+                    int indexCount,
+                    const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawVertices(vmode, vertexCount, vertices, texs, colors,
                                 xmode, indices, indexCount, paint);
   }
 
-  virtual void drawData(const void* data, size_t length) override {
+  void drawData(const void* data, size_t length) override {
     AutoStamper stamper(this);
     SkProxyCanvas::drawData(data, length);
   }
 
 protected:
-  virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
-                          SkScalar y, const SkPaint& paint) override {
+ void onDrawText(const void* text,
+                 size_t byteLength,
+                 SkScalar x,
+                 SkScalar y,
+                 const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::onDrawText(text, byteLength, x, y, paint);
   }
 
-  virtual void onDrawPosText(const void* text, size_t byteLength,
-                             const SkPoint pos[],
-                             const SkPaint& paint) override {
+  void onDrawPosText(const void* text,
+                     size_t byteLength,
+                     const SkPoint pos[],
+                     const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::onDrawPosText(text, byteLength, pos, paint);
   }
 
-  virtual void onDrawPosTextH(const void* text, size_t byteLength,
-                              const SkScalar xpos[], SkScalar constY,
-                              const SkPaint& paint) override {
+  void onDrawPosTextH(const void* text,
+                      size_t byteLength,
+                      const SkScalar xpos[],
+                      SkScalar constY,
+                      const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::onDrawPosTextH(text, byteLength, xpos, constY, paint);
   }
 
-  virtual void onDrawTextOnPath(const void* text, size_t byteLength,
-                                const SkPath& path, const SkMatrix* matrix,
-                                const SkPaint& paint) override {
+  void onDrawTextOnPath(const void* text,
+                        size_t byteLength,
+                        const SkPath& path,
+                        const SkMatrix* matrix,
+                        const SkPaint& paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::onDrawTextOnPath(text, byteLength, path, matrix, paint);
   }
 
-  virtual void onClipRect(const SkRect& rect, SkRegion::Op op,
-                          ClipEdgeStyle edge_style) override {
+  void onClipRect(const SkRect& rect,
+                  SkRegion::Op op,
+                  ClipEdgeStyle edge_style) override {
     AutoStamper stamper(this);
     SkProxyCanvas::onClipRect(rect, op, edge_style);
   }
 
-  virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op,
-                          ClipEdgeStyle edge_style) override {
+  void onClipRRect(const SkRRect& rrect,
+                   SkRegion::Op op,
+                   ClipEdgeStyle edge_style) override {
     AutoStamper stamper(this);
     SkProxyCanvas::onClipRRect(rrect, op, edge_style);
   }
 
-  virtual void onClipPath(const SkPath& path, SkRegion::Op op,
-                          ClipEdgeStyle edge_style) override {
+  void onClipPath(const SkPath& path,
+                  SkRegion::Op op,
+                  ClipEdgeStyle edge_style) override {
     AutoStamper stamper(this);
     SkProxyCanvas::onClipPath(path, op, edge_style);
   }
 
-  virtual void onClipRegion(const SkRegion& region,
-                            SkRegion::Op op) override {
+  void onClipRegion(const SkRegion& region, SkRegion::Op op) override {
     AutoStamper stamper(this);
     SkProxyCanvas::onClipRegion(region, op);
   }
 
-  virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
-                             const SkPaint* paint) override {
+  void onDrawPicture(const SkPicture* picture,
+                     const SkMatrix* matrix,
+                     const SkPaint* paint) override {
     AutoStamper stamper(this);
     SkProxyCanvas::onDrawPicture(picture, matrix, paint);
   }
diff --git a/skia/ext/benchmarking_canvas.h b/skia/ext/benchmarking_canvas.h
index 7ef8204..50289a5 100644
--- a/skia/ext/benchmarking_canvas.h
+++ b/skia/ext/benchmarking_canvas.h
@@ -17,7 +17,7 @@
 class SK_API BenchmarkingCanvas : public SkNWayCanvas {
 public:
   BenchmarkingCanvas(int width, int height);
-  virtual ~BenchmarkingCanvas();
+  ~BenchmarkingCanvas() override;
 
   // Returns the number of draw commands executed on this canvas.
   size_t CommandCount() const;
diff --git a/skia/ext/bitmap_platform_device_mac.h b/skia/ext/bitmap_platform_device_mac.h
index eb142e2..dc78562 100644
--- a/skia/ext/bitmap_platform_device_mac.h
+++ b/skia/ext/bitmap_platform_device_mac.h
@@ -48,23 +48,25 @@
                                               int width, int height,
                                               bool is_opaque);
 
-  virtual ~BitmapPlatformDevice();
+  ~BitmapPlatformDevice() override;
 
   // PlatformDevice overrides
-  virtual CGContextRef GetBitmapContext() override;
-  virtual void DrawToNativeContext(CGContextRef context, int x, int y,
-                                   const CGRect* src_rect) override;
+  CGContextRef GetBitmapContext() override;
+  void DrawToNativeContext(CGContextRef context,
+                           int x,
+                           int y,
+                           const CGRect* src_rect) override;
 
   // SkBaseDevice overrides
-  virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region,
-                             const SkClipStack&) override;
+  void setMatrixClip(const SkMatrix& transform,
+                     const SkRegion& region,
+                     const SkClipStack&) override;
 
  protected:
   BitmapPlatformDevice(CGContextRef context,
                        const SkBitmap& bitmap);
 
-  virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info,
-                                       Usage usage) override;
+  SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) override;
 
  private:
   void ReleaseBitmapContext();
diff --git a/skia/ext/event_tracer_impl.cc b/skia/ext/event_tracer_impl.cc
index f5e081d..53ddf2b 100644
--- a/skia/ext/event_tracer_impl.cc
+++ b/skia/ext/event_tracer_impl.cc
@@ -9,23 +9,20 @@
 namespace skia {
 
 class SkChromiumEventTracer: public SkEventTracer {
-  virtual const uint8_t* getCategoryGroupEnabled(const char* name) override;
-  virtual const char* getCategoryGroupName(
-      const uint8_t* categoryEnabledFlag) override;
-  virtual SkEventTracer::Handle
-    addTraceEvent(char phase,
-                  const uint8_t* categoryEnabledFlag,
-                  const char* name,
-                  uint64_t id,
-                  int32_t numArgs,
-                  const char** argNames,
-                  const uint8_t* argTypes,
-                  const uint64_t* argValues,
-                  uint8_t flags) override;
-  virtual void
-    updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
-                             const char *name,
-                             SkEventTracer::Handle handle) override;
+  const uint8_t* getCategoryGroupEnabled(const char* name) override;
+  const char* getCategoryGroupName(const uint8_t* categoryEnabledFlag) override;
+  SkEventTracer::Handle addTraceEvent(char phase,
+                                      const uint8_t* categoryEnabledFlag,
+                                      const char* name,
+                                      uint64_t id,
+                                      int32_t numArgs,
+                                      const char** argNames,
+                                      const uint8_t* argTypes,
+                                      const uint64_t* argValues,
+                                      uint8_t flags) override;
+  void updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
+                                const char* name,
+                                SkEventTracer::Handle handle) override;
 };
 
 const uint8_t*
diff --git a/skia/ext/lazy_pixel_ref.h b/skia/ext/lazy_pixel_ref.h
index b3f704d..2335fdf 100644
--- a/skia/ext/lazy_pixel_ref.h
+++ b/skia/ext/lazy_pixel_ref.h
@@ -15,7 +15,7 @@
 class SK_API LazyPixelRef : public SkPixelRef {
  public:
   explicit LazyPixelRef(const SkImageInfo& info);
-  virtual ~LazyPixelRef();
+  ~LazyPixelRef() override;
 
   struct PrepareParams {
     // Clipping rect for this pixel ref.
diff --git a/skia/ext/opacity_draw_filter.h b/skia/ext/opacity_draw_filter.h
index 9789cc2..7d11d68 100644
--- a/skia/ext/opacity_draw_filter.h
+++ b/skia/ext/opacity_draw_filter.h
@@ -19,8 +19,8 @@
 class SK_API OpacityDrawFilter : public SkDrawFilter {
  public:
   OpacityDrawFilter(float opacity, bool disable_image_filtering);
-  virtual ~OpacityDrawFilter();
-  virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) override;
+  ~OpacityDrawFilter() override;
+  bool filter(SkPaint* paint, SkDrawFilter::Type type) override;
 
  private:
   int alpha_;
diff --git a/skia/ext/pixel_ref_utils.cc b/skia/ext/pixel_ref_utils.cc
index 6eb7361..4e85f7a 100644
--- a/skia/ext/pixel_ref_utils.cc
+++ b/skia/ext/pixel_ref_utils.cc
@@ -51,8 +51,8 @@
                        DiscardablePixelRefSet* pixel_ref_set)
       : SkBitmapDevice(bm), pixel_ref_set_(pixel_ref_set) {}
 
-  virtual void clear(SkColor color) override {}
-  virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) override {
+  void clear(SkColor color) override {}
+  void drawPaint(const SkDraw& draw, const SkPaint& paint) override {
     SkBitmap bitmap;
     if (GetBitmapFromPaint(paint, &bitmap)) {
       SkRect clip_rect = SkRect::Make(draw.fRC->getBounds());
@@ -60,11 +60,11 @@
     }
   }
 
-  virtual void drawPoints(const SkDraw& draw,
-                          SkCanvas::PointMode mode,
-                          size_t count,
-                          const SkPoint points[],
-                          const SkPaint& paint) override {
+  void drawPoints(const SkDraw& draw,
+                  SkCanvas::PointMode mode,
+                  size_t count,
+                  const SkPoint points[],
+                  const SkPaint& paint) override {
     SkBitmap bitmap;
     if (!GetBitmapFromPaint(paint, &bitmap))
       return;
@@ -87,9 +87,9 @@
 
     GatherPixelRefDevice::drawRect(draw, bounds, paint);
   }
-  virtual void drawRect(const SkDraw& draw,
-                        const SkRect& rect,
-                        const SkPaint& paint) override {
+  void drawRect(const SkDraw& draw,
+                const SkRect& rect,
+                const SkPaint& paint) override {
     SkBitmap bitmap;
     if (GetBitmapFromPaint(paint, &bitmap)) {
       SkRect mapped_rect;
@@ -98,21 +98,21 @@
       AddBitmap(bitmap, mapped_rect);
     }
   }
-  virtual void drawOval(const SkDraw& draw,
-                        const SkRect& rect,
-                        const SkPaint& paint) override {
+  void drawOval(const SkDraw& draw,
+                const SkRect& rect,
+                const SkPaint& paint) override {
     GatherPixelRefDevice::drawRect(draw, rect, paint);
   }
-  virtual void drawRRect(const SkDraw& draw,
-                         const SkRRect& rect,
-                         const SkPaint& paint) override {
+  void drawRRect(const SkDraw& draw,
+                 const SkRRect& rect,
+                 const SkPaint& paint) override {
     GatherPixelRefDevice::drawRect(draw, rect.rect(), paint);
   }
-  virtual void drawPath(const SkDraw& draw,
-                        const SkPath& path,
-                        const SkPaint& paint,
-                        const SkMatrix* pre_path_matrix,
-                        bool path_is_mutable) override {
+  void drawPath(const SkDraw& draw,
+                const SkPath& path,
+                const SkPaint& paint,
+                const SkMatrix* pre_path_matrix,
+                bool path_is_mutable) override {
     SkBitmap bitmap;
     if (!GetBitmapFromPaint(paint, &bitmap))
       return;
@@ -126,10 +126,10 @@
 
     GatherPixelRefDevice::drawRect(draw, final_rect, paint);
   }
-  virtual void drawBitmap(const SkDraw& draw,
-                          const SkBitmap& bitmap,
-                          const SkMatrix& matrix,
-                          const SkPaint& paint) override {
+  void drawBitmap(const SkDraw& draw,
+                  const SkBitmap& bitmap,
+                  const SkMatrix& matrix,
+                  const SkPaint& paint) override {
     SkMatrix total_matrix;
     total_matrix.setConcat(*draw.fMatrix, matrix);
 
@@ -142,22 +142,22 @@
     if (GetBitmapFromPaint(paint, &paint_bitmap))
       AddBitmap(paint_bitmap, mapped_rect);
   }
-  virtual void drawBitmapRect(const SkDraw& draw,
-                              const SkBitmap& bitmap,
-                              const SkRect* src_or_null,
-                              const SkRect& dst,
-                              const SkPaint& paint,
-                              SkCanvas::DrawBitmapRectFlags flags) override {
+  void drawBitmapRect(const SkDraw& draw,
+                      const SkBitmap& bitmap,
+                      const SkRect* src_or_null,
+                      const SkRect& dst,
+                      const SkPaint& paint,
+                      SkCanvas::DrawBitmapRectFlags flags) override {
     SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
     SkMatrix matrix;
     matrix.setRectToRect(bitmap_rect, dst, SkMatrix::kFill_ScaleToFit);
     GatherPixelRefDevice::drawBitmap(draw, bitmap, matrix, paint);
   }
-  virtual void drawSprite(const SkDraw& draw,
-                          const SkBitmap& bitmap,
-                          int x,
-                          int y,
-                          const SkPaint& paint) override {
+  void drawSprite(const SkDraw& draw,
+                  const SkBitmap& bitmap,
+                  int x,
+                  int y,
+                  const SkPaint& paint) override {
     // Sprites aren't affected by current matrix, so we can't reuse drawRect.
     SkMatrix matrix;
     matrix.setTranslate(x, y);
@@ -171,12 +171,12 @@
     if (GetBitmapFromPaint(paint, &paint_bitmap))
       AddBitmap(paint_bitmap, mapped_rect);
   }
-  virtual void drawText(const SkDraw& draw,
-                        const void* text,
-                        size_t len,
-                        SkScalar x,
-                        SkScalar y,
-                        const SkPaint& paint) override {
+  void drawText(const SkDraw& draw,
+                const void* text,
+                size_t len,
+                SkScalar x,
+                SkScalar y,
+                const SkPaint& paint) override {
     SkBitmap bitmap;
     if (!GetBitmapFromPaint(paint, &bitmap))
       return;
@@ -218,13 +218,13 @@
 
     GatherPixelRefDevice::drawRect(draw, bounds, paint);
   }
-  virtual void drawPosText(const SkDraw& draw,
-                           const void* text,
-                           size_t len,
-                           const SkScalar pos[],
-                           int scalars_per_pos,
-                           const SkPoint& offset,
-                           const SkPaint& paint) override {
+  void drawPosText(const SkDraw& draw,
+                   const void* text,
+                   size_t len,
+                   const SkScalar pos[],
+                   int scalars_per_pos,
+                   const SkPoint& offset,
+                   const SkPaint& paint) override {
     SkBitmap bitmap;
     if (!GetBitmapFromPaint(paint, &bitmap))
       return;
@@ -263,12 +263,12 @@
 
     GatherPixelRefDevice::drawRect(draw, bounds, paint);
   }
-  virtual void drawTextOnPath(const SkDraw& draw,
-                              const void* text,
-                              size_t len,
-                              const SkPath& path,
-                              const SkMatrix* matrix,
-                              const SkPaint& paint) override {
+  void drawTextOnPath(const SkDraw& draw,
+                      const void* text,
+                      size_t len,
+                      const SkPath& path,
+                      const SkMatrix* matrix,
+                      const SkPaint& paint) override {
     SkBitmap bitmap;
     if (!GetBitmapFromPaint(paint, &bitmap))
       return;
@@ -286,39 +286,39 @@
 
     GatherPixelRefDevice::drawRect(draw, bounds, paint);
   }
-  virtual void drawVertices(const SkDraw& draw,
-                            SkCanvas::VertexMode,
-                            int vertex_count,
-                            const SkPoint verts[],
-                            const SkPoint texs[],
-                            const SkColor colors[],
-                            SkXfermode* xmode,
-                            const uint16_t indices[],
-                            int index_count,
-                            const SkPaint& paint) override {
+  void drawVertices(const SkDraw& draw,
+                    SkCanvas::VertexMode,
+                    int vertex_count,
+                    const SkPoint verts[],
+                    const SkPoint texs[],
+                    const SkColor colors[],
+                    SkXfermode* xmode,
+                    const uint16_t indices[],
+                    int index_count,
+                    const SkPaint& paint) override {
     GatherPixelRefDevice::drawPoints(
         draw, SkCanvas::kPolygon_PointMode, vertex_count, verts, paint);
   }
-  virtual void drawDevice(const SkDraw&,
-                          SkBaseDevice*,
-                          int x,
-                          int y,
-                          const SkPaint&) override {}
+  void drawDevice(const SkDraw&,
+                  SkBaseDevice*,
+                  int x,
+                  int y,
+                  const SkPaint&) override {}
 
  protected:
-  virtual bool onReadPixels(const SkImageInfo& info,
-                            void* pixels,
-                            size_t rowBytes,
-                            int x,
-                            int y) override {
+  bool onReadPixels(const SkImageInfo& info,
+                    void* pixels,
+                    size_t rowBytes,
+                    int x,
+                    int y) override {
     return false;
   }
 
-  virtual bool onWritePixels(const SkImageInfo& info,
-                             const void* pixels,
-                             size_t rowBytes,
-                             int x,
-                             int y) override {
+  bool onWritePixels(const SkImageInfo& info,
+                     const void* pixels,
+                     size_t rowBytes,
+                     int x,
+                     int y) override {
     return false;
   }
 
diff --git a/skia/ext/pixel_ref_utils_unittest.cc b/skia/ext/pixel_ref_utils_unittest.cc
index aef5766..656ef5c 100644
--- a/skia/ext/pixel_ref_utils_unittest.cc
+++ b/skia/ext/pixel_ref_utils_unittest.cc
@@ -34,20 +34,18 @@
     CreateBitmap(gfx::Size(50, 50), "discardable", &bitmap_);
   }
 
-  virtual SkShader::BitmapType asABitmap(SkBitmap* bitmap,
-                                         SkMatrix* matrix,
-                                         TileMode xy[2]) const override {
+  SkShader::BitmapType asABitmap(SkBitmap* bitmap,
+                                 SkMatrix* matrix,
+                                 TileMode xy[2]) const override {
     if (bitmap)
       *bitmap = bitmap_;
     return SkShader::kDefault_BitmapType;
   }
 
   // not indended to return an actual context. Just need to supply this.
-  virtual size_t contextSize() const override {
-    return sizeof(SkShader::Context);
-  }
+  size_t contextSize() const override { return sizeof(SkShader::Context); }
 
-  virtual void flatten(SkWriteBuffer&) const override {}
+  void flatten(SkWriteBuffer&) const override {}
 
   SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(TestDiscardableShader);
 
diff --git a/skia/ext/vector_platform_device_skia.h b/skia/ext/vector_platform_device_skia.h
index fc88904..528eac9 100644
--- a/skia/ext/vector_platform_device_skia.h
+++ b/skia/ext/vector_platform_device_skia.h
@@ -23,24 +23,24 @@
   SK_API VectorPlatformDeviceSkia(const SkISize& pageSize,
                                   const SkISize& contentSize,
                                   const SkMatrix& initialTransform);
-  virtual ~VectorPlatformDeviceSkia();
+  ~VectorPlatformDeviceSkia() override;
 
   // PlatformDevice methods.
-  virtual bool SupportsPlatformPaint() override;
+  bool SupportsPlatformPaint() override;
 
-  virtual PlatformSurface BeginPlatformPaint() override;
-  virtual void EndPlatformPaint() override;
+  PlatformSurface BeginPlatformPaint() override;
+  void EndPlatformPaint() override;
 #if defined(OS_WIN)
   virtual void DrawToNativeContext(HDC dc,
                                    int x,
                                    int y,
                                    const RECT* src_rect) override;
 #elif defined(OS_MACOSX)
-  virtual void DrawToNativeContext(CGContext* context,
-                                   int x,
-                                   int y,
-                                   const CGRect* src_rect) override;
-  virtual CGContextRef GetBitmapContext() override;
+  void DrawToNativeContext(CGContext* context,
+                           int x,
+                           int y,
+                           const CGRect* src_rect) override;
+  CGContextRef GetBitmapContext() override;
 #elif defined(OS_POSIX)
   virtual void DrawToNativeContext(PlatformSurface surface,
                                    int x,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index a0187b9..a184a12 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -42,15 +42,12 @@
       "browser_tests",
       "content_browsertests",
       "mojo_apps_js_unittests",
-      "mojo_clipboard_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
       "mojo_public_bindings_unittests",
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_application_manager_unittests",
-      "mojo_shell_tests",
       "mojo_surfaces_lib_unittests",
       "mojo_system_unittests",
       "nacl_loader_unittests"
@@ -99,15 +96,12 @@
       "browser_tests",
       "content_browsertests",
       "mojo_apps_js_unittests",
-      "mojo_clipboard_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
       "mojo_public_bindings_unittests",
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_application_manager_unittests",
-      "mojo_shell_tests",
       "mojo_surfaces_lib_unittests",
       "mojo_system_unittests",
       "nacl_loader_unittests"
@@ -156,15 +150,12 @@
       "browser_tests",
       "content_browsertests",
       "mojo_apps_js_unittests",
-      "mojo_clipboard_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
       "mojo_public_bindings_unittests",
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_application_manager_unittests",
-      "mojo_shell_tests",
       "mojo_surfaces_lib_unittests",
       "mojo_system_unittests",
       "nacl_loader_unittests"
@@ -213,15 +204,12 @@
       "browser_tests",
       "content_browsertests",
       "mojo_apps_js_unittests",
-      "mojo_clipboard_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
       "mojo_public_bindings_unittests",
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_application_manager_unittests",
-      "mojo_shell_tests",
       "mojo_surfaces_lib_unittests",
       "mojo_system_unittests",
       "nacl_loader_unittests"
@@ -259,15 +247,12 @@
       "media_unittests",
       "message_center_unittests",
       "mojo_apps_js_unittests",
-      "mojo_clipboard_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
       "mojo_public_bindings_unittests",
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_application_manager_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
       "net_unittests",
       "ppapi_unittests",
@@ -341,7 +326,6 @@
       "ipc_tests",
       "jingle_unittests",
       "media_unittests",
-      "mojo_application_manager_unittests",
       "mojo_apps_js_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
@@ -349,7 +333,6 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
       "nacl_loader_unittests",
       "net_unittests",
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 9f814d3..ecce684 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -57,7 +57,6 @@
       "ipc_tests",
       "jingle_unittests",
       "media_unittests",
-      "mojo_application_manager_unittests",
       "mojo_apps_js_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
@@ -65,9 +64,7 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
-      "mojo_view_manager_unittests",
       "nacl_loader_unittests",
       {
         "test": "net_unittests",
@@ -157,7 +154,6 @@
       "ipc_tests",
       "jingle_unittests",
       "media_unittests",
-      "mojo_application_manager_unittests",
       "mojo_apps_js_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
@@ -165,9 +161,7 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
-      "mojo_view_manager_unittests",
       "nacl_loader_unittests",
       {
         "test": "net_unittests",
@@ -258,7 +252,6 @@
       "ipc_tests",
       "jingle_unittests",
       "media_unittests",
-      "mojo_application_manager_unittests",
       "mojo_apps_js_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
@@ -266,9 +259,7 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
-      "mojo_view_manager_unittests",
       "nacl_loader_unittests",
       {
         "test": "net_unittests",
@@ -317,7 +308,6 @@
       "google_apis_unittests",
       "ipc_mojo_unittests",
       "ipc_tests",
-      "mojo_application_manager_unittests",
       "mojo_apps_js_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
@@ -325,9 +315,7 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
-      "mojo_view_manager_unittests",
       "nacl_loader_unittests",
       "sandbox_linux_unittests",
       "sql_unittests",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index ef5867d..018a2e3 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -56,8 +56,6 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_application_manager_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
       {
         "test": "net_unittests",
@@ -144,8 +142,6 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_application_manager_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
       {
         "test": "net_unittests",
@@ -232,8 +228,6 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_application_manager_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
       {
         "test": "net_unittests",
@@ -321,8 +315,6 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_application_manager_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
       {
         "test": "net_unittests",
diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json
index c2e560e..3f9acc0 100644
--- a/testing/buildbot/chromium.memory.fyi.json
+++ b/testing/buildbot/chromium.memory.fyi.json
@@ -28,7 +28,6 @@
       "ipc_tests",
       "jingle_unittests",
       "media_unittests",
-      "mojo_application_manager_unittests",
       "mojo_apps_js_unittests",
       "mojo_common_unittests",
       "mojo_js_unittests",
@@ -36,7 +35,6 @@
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
-      "mojo_shell_tests",
       "mojo_system_unittests",
       "nacl_loader_unittests",
       "net_unittests",
diff --git a/third_party/android_testrunner/LICENSE b/third_party/android_testrunner/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/third_party/android_testrunner/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/third_party/android_testrunner/OWNERS b/third_party/android_testrunner/OWNERS
new file mode 100644
index 0000000..9281d8a
--- /dev/null
+++ b/third_party/android_testrunner/OWNERS
@@ -0,0 +1,3 @@
+craigdh@chromium.org
+frankf@chromium.org
+jbudorick@chromium.org
diff --git a/third_party/android_testrunner/README.chromium b/third_party/android_testrunner/README.chromium
new file mode 100644
index 0000000..7d382a1
--- /dev/null
+++ b/third_party/android_testrunner/README.chromium
@@ -0,0 +1,34 @@
+Name: Android Test runner script
+URL: http://source.android.com
+Version: 3.1.4
+License: Apache Version 2.0
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+This package is the scripts used to run the unit test for Android and from
+Android Gingerbread.
+
+Local Modifications:
+1. Added |silent_log| argument to |StartInstrumentation| so that output can be
+  suppressed.
+2. Changed error message handling in |StartInstrumentation| from |shortMsg| to
+  |longMsg| to provide more information when debugging.
+3. Applied the patch file patch.diff to fix a race condition and subproccess
+   bugs in run_command.py.
+4. Fixed a bug where wait_time wasn't properly respected in
+    _WaitForShellCommandContents.
+
+Here is the detail steps
+1. Checkout Android source code
+
+$ repo init -u git://android.git.kernel.org/platform/manifest.git -b gingerbread
+$ repo sync
+$ cd development
+$ git reset --hard 76f63551d36b1de63c63f357e5f0646ed8c306bb
+
+2. Copy the related files from
+   <android_gingerbread_tree>/development/testrunner/
+
+More information can be found in
+http://source.android.com/source/downloading.html
diff --git a/third_party/android_testrunner/adb_interface.py b/third_party/android_testrunner/adb_interface.py
new file mode 100644
index 0000000..93e1963
--- /dev/null
+++ b/third_party/android_testrunner/adb_interface.py
@@ -0,0 +1,514 @@
+#!/usr/bin/python2.4
+#
+#
+# Copyright 2008, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Provides an interface to communicate with the device via the adb command.
+
+Assumes adb binary is currently on system path.
+"""
+# Python imports
+import os
+import string
+import time
+
+# local imports
+import am_instrument_parser
+import errors
+import logger
+import run_command
+
+
+class AdbInterface:
+  """Helper class for communicating with Android device via adb."""
+
+  # argument to pass to adb, to direct command to specific device
+  _target_arg = ""
+
+  DEVICE_TRACE_DIR = "/data/test_results/"
+
+  def SetEmulatorTarget(self):
+    """Direct all future commands to the only running emulator."""
+    self._target_arg = "-e"
+
+  def SetDeviceTarget(self):
+    """Direct all future commands to the only connected USB device."""
+    self._target_arg = "-d"
+
+  def SetTargetSerial(self, serial):
+    """Direct all future commands to Android target with the given serial."""
+    self._target_arg = "-s %s" % serial
+
+  def SendCommand(self, command_string, timeout_time=20, retry_count=3):
+    """Send a command via adb.
+
+    Args:
+      command_string: adb command to run
+      timeout_time: number of seconds to wait for command to respond before
+        retrying
+      retry_count: number of times to retry command before raising
+        WaitForResponseTimedOutError
+    Returns:
+      string output of command
+
+    Raises:
+      WaitForResponseTimedOutError if device does not respond to command within time
+    """
+    adb_cmd = "adb %s %s" % (self._target_arg, command_string)
+    logger.SilentLog("about to run %s" % adb_cmd)
+    return run_command.RunCommand(adb_cmd, timeout_time=timeout_time,
+                                  retry_count=retry_count)
+
+  def SendShellCommand(self, cmd, timeout_time=20, retry_count=3):
+    """Send a adb shell command.
+
+    Args:
+      cmd: adb shell command to run
+      timeout_time: number of seconds to wait for command to respond before
+        retrying
+      retry_count: number of times to retry command before raising
+        WaitForResponseTimedOutError
+
+    Returns:
+      string output of command
+
+    Raises:
+      WaitForResponseTimedOutError: if device does not respond to command
+    """
+    return self.SendCommand("shell %s" % cmd, timeout_time=timeout_time,
+                            retry_count=retry_count)
+
+  def BugReport(self, path):
+    """Dumps adb bugreport to the file specified by the path.
+
+    Args:
+      path: Path of the file where adb bugreport is dumped to.
+    """
+    bug_output = self.SendShellCommand("bugreport", timeout_time=60)
+    bugreport_file = open(path, "w")
+    bugreport_file.write(bug_output)
+    bugreport_file.close()
+
+  def Push(self, src, dest):
+    """Pushes the file src onto the device at dest.
+
+    Args:
+      src: file path of host file to push
+      dest: destination absolute file path on device
+    """
+    self.SendCommand("push %s %s" % (src, dest), timeout_time=60)
+
+  def Pull(self, src, dest):
+    """Pulls the file src on the device onto dest on the host.
+
+    Args:
+      src: absolute file path of file on device to pull
+      dest: destination file path on host
+
+    Returns:
+      True if success and False otherwise.
+    """
+    # Create the base dir if it doesn't exist already
+    if not os.path.exists(os.path.dirname(dest)):
+      os.makedirs(os.path.dirname(dest))
+
+    if self.DoesFileExist(src):
+      self.SendCommand("pull %s %s" % (src, dest), timeout_time=60)
+      return True
+    else:
+      logger.Log("ADB Pull Failed: Source file %s does not exist." % src)
+      return False
+
+  def DoesFileExist(self, src):
+    """Checks if the given path exists on device target.
+
+    Args:
+      src: file path to be checked.
+
+    Returns:
+      True if file exists
+    """
+
+    output = self.SendShellCommand("ls %s" % src)
+    error = "No such file or directory"
+
+    if error in output:
+      return False
+    return True
+
+  def EnableAdbRoot(self):
+    """Enable adb root on device."""
+    output = self.SendCommand("root")
+    if "adbd is already running as root" in output:
+      return True
+    elif "restarting adbd as root" in output:
+      # device will disappear from adb, wait for it to come back
+      self.SendCommand("wait-for-device")
+      return True
+    else:
+      logger.Log("Unrecognized output from adb root: %s" % output)
+      return False
+
+  def StartInstrumentationForPackage(
+      self, package_name, runner_name, timeout_time=60*10,
+      no_window_animation=False, instrumentation_args={}):
+    """Run instrumentation test for given package and runner.
+
+    Equivalent to StartInstrumentation, except instrumentation path is
+    separated into its package and runner components.
+    """
+    instrumentation_path = "%s/%s" % (package_name, runner_name)
+    return self.StartInstrumentation(instrumentation_path, timeout_time=timeout_time,
+                                     no_window_animation=no_window_animation,
+                                     instrumentation_args=instrumentation_args)
+
+  def StartInstrumentation(
+      self, instrumentation_path, timeout_time=60*10, no_window_animation=False,
+      profile=False, instrumentation_args={}, silent_log=False):
+
+    """Runs an instrumentation class on the target.
+
+    Returns a dictionary containing the key value pairs from the
+    instrumentations result bundle and a list of TestResults. Also handles the
+    interpreting of error output from the device and raises the necessary
+    exceptions.
+
+    Args:
+      instrumentation_path: string. It should be the fully classified package
+      name, and instrumentation test runner, separated by "/"
+        e.g. com.android.globaltimelaunch/.GlobalTimeLaunch
+      timeout_time: Timeout value for the am command.
+      no_window_animation: boolean, Whether you want window animations enabled
+        or disabled
+      profile: If True, profiling will be turned on for the instrumentation.
+      instrumentation_args: Dictionary of key value bundle arguments to pass to
+      instrumentation.
+      silent_log: If True, the invocation of the instrumentation test runner
+        will not be logged.
+
+    Returns:
+      (test_results, inst_finished_bundle)
+
+      test_results: a list of TestResults
+      inst_finished_bundle (dict): Key/value pairs contained in the bundle that
+        is passed into ActivityManager.finishInstrumentation(). Included in this
+        bundle is the return code of the Instrumentation process, any error
+        codes reported by the activity manager, and any results explicitly added
+        by the instrumentation code.
+
+     Raises:
+       WaitForResponseTimedOutError: if timeout occurred while waiting for
+         response to adb instrument command
+       DeviceUnresponsiveError: if device system process is not responding
+       InstrumentationError: if instrumentation failed to run
+    """
+
+    command_string = self._BuildInstrumentationCommandPath(
+        instrumentation_path, no_window_animation=no_window_animation,
+        profile=profile, raw_mode=True,
+        instrumentation_args=instrumentation_args)
+    if silent_log:
+      logger.SilentLog(command_string)
+    else:
+      logger.Log(command_string)
+    (test_results, inst_finished_bundle) = (
+        am_instrument_parser.ParseAmInstrumentOutput(
+            self.SendShellCommand(command_string, timeout_time=timeout_time,
+                                  retry_count=2)))
+    if "code" not in inst_finished_bundle:
+      logger.Log('No code available. inst_finished_bundle contains: %s '
+                 % inst_finished_bundle)
+      raise errors.InstrumentationError("no test results... device setup "
+                                        "correctly?")
+
+    if inst_finished_bundle["code"] == "0":
+      long_msg_result = "no error message"
+      if "longMsg" in inst_finished_bundle:
+        long_msg_result = inst_finished_bundle["longMsg"]
+        logger.Log("Error! Test run failed: %s" % long_msg_result)
+      raise errors.InstrumentationError(long_msg_result)
+
+    if "INSTRUMENTATION_ABORTED" in inst_finished_bundle:
+      logger.Log("INSTRUMENTATION ABORTED!")
+      raise errors.DeviceUnresponsiveError
+
+    return (test_results, inst_finished_bundle)
+
+  def StartInstrumentationNoResults(
+      self, package_name, runner_name, no_window_animation=False,
+      raw_mode=False, instrumentation_args={}):
+    """Runs instrumentation and dumps output to stdout.
+
+    Equivalent to StartInstrumentation, but will dump instrumentation
+    'normal' output to stdout, instead of parsing return results. Command will
+    never timeout.
+    """
+    adb_command_string = self.PreviewInstrumentationCommand(
+        package_name, runner_name, no_window_animation=no_window_animation,
+        raw_mode=raw_mode, instrumentation_args=instrumentation_args)
+    logger.Log(adb_command_string)
+    run_command.RunCommand(adb_command_string, return_output=False)
+
+  def PreviewInstrumentationCommand(
+      self, package_name, runner_name, no_window_animation=False,
+      raw_mode=False, instrumentation_args={}):
+    """Returns a string of adb command that will be executed."""
+    inst_command_string = self._BuildInstrumentationCommand(
+        package_name, runner_name, no_window_animation=no_window_animation,
+        raw_mode=raw_mode, instrumentation_args=instrumentation_args)
+    command_string = "adb %s shell %s" % (self._target_arg, inst_command_string)
+    return command_string
+
+  def _BuildInstrumentationCommand(
+      self, package, runner_name, no_window_animation=False, profile=False,
+      raw_mode=True, instrumentation_args={}):
+    instrumentation_path = "%s/%s" % (package, runner_name)
+
+    return self._BuildInstrumentationCommandPath(
+        instrumentation_path, no_window_animation=no_window_animation,
+        profile=profile, raw_mode=raw_mode,
+        instrumentation_args=instrumentation_args)
+
+  def _BuildInstrumentationCommandPath(
+      self, instrumentation_path, no_window_animation=False, profile=False,
+      raw_mode=True, instrumentation_args={}):
+    command_string = "am instrument"
+    if no_window_animation:
+      command_string += " --no_window_animation"
+    if profile:
+      self._CreateTraceDir()
+      command_string += (
+          " -p %s/%s.dmtrace" %
+          (self.DEVICE_TRACE_DIR, instrumentation_path.split(".")[-1]))
+
+    for key, value in instrumentation_args.items():
+      command_string += " -e %s '%s'" % (key, value)
+    if raw_mode:
+      command_string += " -r"
+    command_string += " -w %s" % instrumentation_path
+    return command_string
+
+  def _CreateTraceDir(self):
+    ls_response = self.SendShellCommand("ls /data/trace")
+    if ls_response.strip("#").strip(string.whitespace) != "":
+      self.SendShellCommand("create /data/trace", "mkdir /data/trace")
+      self.SendShellCommand("make /data/trace world writeable",
+                            "chmod 777 /data/trace")
+
+  def WaitForDevicePm(self, wait_time=120):
+    """Waits for targeted device's package manager to be up.
+
+    Args:
+      wait_time: time in seconds to wait
+
+    Raises:
+      WaitForResponseTimedOutError if wait_time elapses and pm still does not
+      respond.
+    """
+    logger.Log("Waiting for device package manager...")
+    self.SendCommand("wait-for-device", timeout_time=wait_time, retry_count=0)
+    # Now the device is there, but may not be running.
+    # Query the package manager with a basic command
+    try:
+      self._WaitForShellCommandContents("pm path android", "package:",
+                                        wait_time)
+    except errors.WaitForResponseTimedOutError:
+      raise errors.WaitForResponseTimedOutError(
+          "Package manager did not respond after %s seconds" % wait_time)
+
+  def WaitForInstrumentation(self, package_name, runner_name, wait_time=120):
+    """Waits for given instrumentation to be present on device
+
+    Args:
+      wait_time: time in seconds to wait
+
+    Raises:
+      WaitForResponseTimedOutError if wait_time elapses and instrumentation
+      still not present.
+    """
+    instrumentation_path = "%s/%s" % (package_name, runner_name)
+    logger.Log("Waiting for instrumentation to be present")
+    # Query the package manager
+    try:
+      command = "pm list instrumentation | grep %s" % instrumentation_path
+      self._WaitForShellCommandContents(command, "instrumentation:", wait_time,
+                                        raise_abort=False)
+    except errors.WaitForResponseTimedOutError :
+      logger.Log(
+          "Could not find instrumentation %s on device. Does the "
+          "instrumentation in test's AndroidManifest.xml match definition"
+          "in test_defs.xml?" % instrumentation_path)
+      raise
+
+  def WaitForProcess(self, name, wait_time=120):
+    """Wait until a process is running on the device.
+
+    Args:
+      name: the process name as it appears in `ps`
+      wait_time: time in seconds to wait
+
+    Raises:
+      WaitForResponseTimedOutError if wait_time elapses and the process is
+          still not running
+    """
+    logger.Log("Waiting for process %s" % name)
+    self.SendCommand("wait-for-device")
+    self._WaitForShellCommandContents("ps", name, wait_time)
+
+  def WaitForProcessEnd(self, name, wait_time=120):
+    """Wait until a process is no longer running on the device.
+
+    Args:
+      name: the process name as it appears in `ps`
+      wait_time: time in seconds to wait
+
+    Raises:
+      WaitForResponseTimedOutError if wait_time elapses and the process is
+          still running
+    """
+    logger.Log("Waiting for process %s to end" % name)
+    self._WaitForShellCommandContents("ps", name, wait_time, invert=True)
+
+  def _WaitForShellCommandContents(self, command, expected, wait_time,
+                                   raise_abort=True, invert=False):
+    """Wait until the response to a command contains a given output.
+
+    Assumes that a only successful execution of "adb shell <command>" contains
+    the substring expected. Assumes that a device is present.
+
+    Args:
+      command: adb shell command to execute
+      expected: the string that should appear to consider the
+          command successful.
+      wait_time: time in seconds to wait
+      raise_abort: if False, retry when executing the command raises an
+          AbortError, rather than failing.
+      invert: if True, wait until the command output no longer contains the
+          expected contents.
+
+    Raises:
+      WaitForResponseTimedOutError: If wait_time elapses and the command has not
+          returned an output containing expected yet.
+    """
+    # Query the device with the command
+    success = False
+    attempts = 0
+    wait_period = 5
+    while not success and (attempts*wait_period) < wait_time:
+      # assume the command will always contain expected in the success case
+      try:
+        output = self.SendShellCommand(command, retry_count=1,
+                                       timeout_time=wait_time)
+        if ((not invert and expected in output)
+            or (invert and expected not in output)):
+          success = True
+      except errors.AbortError, e:
+        if raise_abort:
+          raise
+        # ignore otherwise
+
+      if not success:
+        time.sleep(wait_period)
+        attempts += 1
+
+    if not success:
+      raise errors.WaitForResponseTimedOutError()
+
+  def WaitForBootComplete(self, wait_time=120):
+    """Waits for targeted device's bootcomplete flag to be set.
+
+    Args:
+      wait_time: time in seconds to wait
+
+    Raises:
+      WaitForResponseTimedOutError if wait_time elapses and pm still does not
+      respond.
+    """
+    logger.Log("Waiting for boot complete...")
+    self.SendCommand("wait-for-device")
+    # Now the device is there, but may not be running.
+    # Query the package manager with a basic command
+    boot_complete = False
+    attempts = 0
+    wait_period = 5
+    while not boot_complete and (attempts*wait_period) < wait_time:
+      output = self.SendShellCommand("getprop dev.bootcomplete", retry_count=1)
+      output = output.strip()
+      if output == "1":
+        boot_complete = True
+      else:
+        time.sleep(wait_period)
+        attempts += 1
+    if not boot_complete:
+      raise errors.WaitForResponseTimedOutError(
+          "dev.bootcomplete flag was not set after %s seconds" % wait_time)
+
+  def Sync(self, retry_count=3, runtime_restart=False):
+    """Perform a adb sync.
+
+    Blocks until device package manager is responding.
+
+    Args:
+      retry_count: number of times to retry sync before failing
+      runtime_restart: stop runtime during sync and restart afterwards, useful
+        for syncing system libraries (core, framework etc)
+
+    Raises:
+      WaitForResponseTimedOutError if package manager does not respond
+      AbortError if unrecoverable error occurred
+    """
+    output = ""
+    error = None
+    if runtime_restart:
+      self.SendShellCommand("setprop ro.monkey 1", retry_count=retry_count)
+      # manual rest bootcomplete flag
+      self.SendShellCommand("setprop dev.bootcomplete 0",
+                            retry_count=retry_count)
+      self.SendShellCommand("stop", retry_count=retry_count)
+
+    try:
+      output = self.SendCommand("sync", retry_count=retry_count)
+    except errors.AbortError, e:
+      error = e
+      output = e.msg
+    if "Read-only file system" in output:
+      logger.SilentLog(output)
+      logger.Log("Remounting read-only filesystem")
+      self.SendCommand("remount")
+      output = self.SendCommand("sync", retry_count=retry_count)
+    elif "No space left on device" in output:
+      logger.SilentLog(output)
+      logger.Log("Restarting device runtime")
+      self.SendShellCommand("stop", retry_count=retry_count)
+      output = self.SendCommand("sync", retry_count=retry_count)
+      self.SendShellCommand("start", retry_count=retry_count)
+    elif error is not None:
+      # exception occurred that cannot be recovered from
+      raise error
+    logger.SilentLog(output)
+    if runtime_restart:
+      # start runtime and wait till boot complete flag is set
+      self.SendShellCommand("start", retry_count=retry_count)
+      self.WaitForBootComplete()
+      # press the MENU key, this will disable key guard if runtime is started
+      # with ro.monkey set to 1
+      self.SendShellCommand("input keyevent 82", retry_count=retry_count)
+    else:
+      self.WaitForDevicePm()
+    return output
+
+  def GetSerialNumber(self):
+    """Returns the serial number of the targeted device."""
+    return self.SendCommand("get-serialno").strip()
diff --git a/third_party/android_testrunner/am_instrument_parser.py b/third_party/android_testrunner/am_instrument_parser.py
new file mode 100644
index 0000000..4554c4d
--- /dev/null
+++ b/third_party/android_testrunner/am_instrument_parser.py
@@ -0,0 +1,169 @@
+#!/usr/bin/python2.4
+#
+#
+# Copyright 2008, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Module that assists in parsing the output of "am instrument" commands run on
+the device."""
+
+import re
+import string
+
+
+def ParseAmInstrumentOutput(result):
+  """Given the raw output of an "am instrument" command that targets and
+  InstrumentationTestRunner, return structured data.
+
+  Args:
+    result (string): Raw output of "am instrument"
+
+  Return
+  (test_results, inst_finished_bundle)
+  
+  test_results (list of am_output_parser.TestResult)
+  inst_finished_bundle (dict): Key/value pairs contained in the bundle that is
+    passed into ActivityManager.finishInstrumentation(). Included in this bundle is the return
+    code of the Instrumentation process, any error codes reported by the
+    activity manager, and any results explicity added by the instrumentation
+    code.
+  """
+
+  re_status_code = re.compile(r'INSTRUMENTATION_STATUS_CODE: (?P<status_code>-?\d)$')
+  test_results = []
+  inst_finished_bundle = {}
+
+  result_block_string = ""
+  for line in result.splitlines():
+    result_block_string += line + '\n'
+
+    if "INSTRUMENTATION_STATUS_CODE:" in line:
+      test_result = TestResult(result_block_string)
+      if test_result.GetStatusCode() == 1: # The test started
+        pass
+      elif test_result.GetStatusCode() in [0, -1, -2]:
+        test_results.append(test_result)
+      else:
+        pass
+      result_block_string = ""
+    if "INSTRUMENTATION_CODE:" in line:
+      inst_finished_bundle = _ParseInstrumentationFinishedBundle(result_block_string)
+      result_block_string = ""
+
+  return (test_results, inst_finished_bundle)
+
+
+def _ParseInstrumentationFinishedBundle(result):
+  """Given the raw output of "am instrument" returns a dictionary of the
+  key/value pairs from the bundle passed into 
+  ActivityManager.finishInstrumentation().
+
+  Args:
+    result (string): Raw output of "am instrument"
+
+  Return:
+  inst_finished_bundle (dict): Key/value pairs contained in the bundle that is
+    passed into ActivityManager.finishInstrumentation(). Included in this bundle is the return
+    code of the Instrumentation process, any error codes reported by the
+    activity manager, and any results explicity added by the instrumentation
+    code.
+  """
+
+  re_result = re.compile(r'INSTRUMENTATION_RESULT: ([^=]+)=(.*)$')
+  re_code = re.compile(r'INSTRUMENTATION_CODE: (\-?\d)$')
+  result_dict = {}
+  key = ''
+  val = ''
+  last_tag = ''
+
+  for line in result.split('\n'):
+    line = line.strip(string.whitespace)
+    if re_result.match(line):
+      last_tag = 'INSTRUMENTATION_RESULT'
+      key = re_result.search(line).group(1).strip(string.whitespace)
+      if key.startswith('performance.'):
+        key = key[len('performance.'):]
+      val = re_result.search(line).group(2).strip(string.whitespace)
+      try:
+        result_dict[key] = float(val)
+      except ValueError:
+        result_dict[key] = val
+      except TypeError:
+        result_dict[key] = val
+    elif re_code.match(line):
+      last_tag = 'INSTRUMENTATION_CODE'
+      key = 'code'
+      val = re_code.search(line).group(1).strip(string.whitespace)
+      result_dict[key] = val
+    elif 'INSTRUMENTATION_ABORTED:' in line:
+      last_tag = 'INSTRUMENTATION_ABORTED'
+      key = 'INSTRUMENTATION_ABORTED'
+      val = ''
+      result_dict[key] = val
+    elif last_tag == 'INSTRUMENTATION_RESULT':
+      result_dict[key] += '\n' + line
+
+  if not result_dict.has_key('code'):
+    result_dict['code'] = '0'
+    result_dict['shortMsg'] = "No result returned from instrumentation"
+
+  return result_dict
+
+
+class TestResult(object):
+  """A class that contains information about a single test result."""
+
+  def __init__(self, result_block_string):
+    """
+    Args:
+      result_block_string (string): Is a single "block" of output. A single
+      "block" would be either a "test started" status report, or a "test
+      finished" status report.
+    """
+
+    self._test_name = None
+    self._status_code = None
+    self._failure_reason = None
+    self._fields_map = {}
+
+    re_status_code = re.search(r'INSTRUMENTATION_STATUS_CODE: '
+        '(?P<status_code>1|0|-1|-2)', result_block_string)
+    re_fields = re.compile(r'INSTRUMENTATION_STATUS: '
+        '(?P<key>[\w.]+)=(?P<value>.*?)(?=\nINSTRUMENTATION_STATUS)', re.DOTALL)
+
+    for field in re_fields.finditer(result_block_string):
+      key, value = (field.group('key').strip(), field.group('value').strip())
+      if key.startswith('performance.'):
+        key = key[len('performance.'):]
+      self._fields_map[key] = value
+    self._fields_map.setdefault('class')
+    self._fields_map.setdefault('test')
+
+    self._test_name = '%s:%s' % (self._fields_map['class'],
+                                 self._fields_map['test'])
+    self._status_code = int(re_status_code.group('status_code'))
+    if 'stack' in self._fields_map:
+      self._failure_reason = self._fields_map['stack']
+
+  def GetTestName(self):
+    return self._test_name
+
+  def GetStatusCode(self):
+    return self._status_code
+
+  def GetFailureReason(self):
+    return self._failure_reason
+
+  def GetResultFields(self):
+    return self._fields_map
diff --git a/third_party/android_testrunner/errors.py b/third_party/android_testrunner/errors.py
new file mode 100644
index 0000000..e163dd4
--- /dev/null
+++ b/third_party/android_testrunner/errors.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python2.4
+#
+#
+# Copyright 2008, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Defines common exception classes for this package."""
+
+
+class MsgException(Exception):
+  """Generic exception with an optional string msg."""
+  def __init__(self, msg=""):
+    self.msg = msg
+
+
+class WaitForResponseTimedOutError(Exception):
+  """We sent a command and had to wait too long for response."""
+
+
+class DeviceUnresponsiveError(Exception):
+  """Device is unresponsive to command."""
+
+
+class InstrumentationError(Exception):
+  """Failed to run instrumentation."""
+
+
+class AbortError(MsgException):
+  """Generic exception that indicates a fatal error has occurred and program
+  execution should be aborted."""
+
+
+class ParseError(MsgException):
+  """Raised when xml data to parse has unrecognized format."""
+
diff --git a/third_party/android_testrunner/logger.py b/third_party/android_testrunner/logger.py
new file mode 100644
index 0000000..61463a1
--- /dev/null
+++ b/third_party/android_testrunner/logger.py
@@ -0,0 +1,96 @@
+#!/usr/bin/python2.4
+#
+#
+# Copyright 2007, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Simple logging utility. Dumps log messages to stdout, and optionally, to a
+log file.
+
+Init(path) must be called to enable logging to a file
+"""
+
+import datetime
+
+_LOG_FILE = None
+_verbose = False
+_log_time = True
+
+def Init(log_file_path):
+  """Set the path to the log file"""
+  global _LOG_FILE
+  _LOG_FILE = log_file_path
+  print "Using log file: %s" % _LOG_FILE
+
+def GetLogFilePath():
+  """Returns the path and name of the Log file"""
+  global _LOG_FILE
+  return _LOG_FILE
+
+def Log(new_str):
+  """Appends new_str to the end of _LOG_FILE and prints it to stdout.
+
+  Args:
+    # new_str is a string.
+    new_str: 'some message to log'
+  """
+  msg = _PrependTimeStamp(new_str)
+  print msg
+  _WriteLog(msg)
+
+def _WriteLog(msg):
+  global _LOG_FILE
+  if _LOG_FILE is not None:
+    file_handle = file(_LOG_FILE, 'a')
+    file_handle.write('\n' + str(msg))
+    file_handle.close()
+
+def _PrependTimeStamp(log_string):
+  """Returns the log_string prepended with current timestamp """
+  global _log_time
+  if _log_time:
+    return "# %s: %s" % (datetime.datetime.now().strftime("%m/%d/%y %H:%M:%S"),
+        log_string)
+  else:
+    # timestamp logging disabled
+    return log_string  
+
+def SilentLog(new_str):
+  """Silently log new_str. Unless verbose mode is enabled, will log new_str
+    only to the log file
+  Args:
+    # new_str is a string.
+    new_str: 'some message to log'
+  """
+  global _verbose
+  msg = _PrependTimeStamp(new_str)
+  if _verbose:
+    print msg
+  _WriteLog(msg)
+
+def SetVerbose(new_verbose=True):
+  """ Enable or disable verbose logging"""
+  global _verbose
+  _verbose = new_verbose
+  
+def SetTimestampLogging(new_timestamp=True):
+  """ Enable or disable outputting a timestamp with each log entry"""
+  global _log_time
+  _log_time = new_timestamp
+    
+def main():
+  pass
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/android_testrunner/patch.diff b/third_party/android_testrunner/patch.diff
new file mode 100644
index 0000000..9b067cd
--- /dev/null
+++ b/third_party/android_testrunner/patch.diff
@@ -0,0 +1,104 @@
+diff --git a/third_party/android_testrunner/run_command.py b/third_party/android_testrunner/run_command.py
+index d398daa..6b84156 100644
+--- a/third_party/android_testrunner/run_command.py
++++ b/third_party/android_testrunner/run_command.py
+@@ -19,6 +19,7 @@
+ import os
+ import signal
+ import subprocess
++import tempfile
+ import threading
+ import time
+ 
+@@ -80,31 +81,36 @@ def RunOnce(cmd, timeout_time=None, return_output=True, stdin_input=None):
+   """
+   start_time = time.time()
+   so = []
+-  pid = []
+   global _abort_on_error, error_occurred
+   error_occurred = False
+ 
++  if return_output:
++    output_dest = tempfile.TemporaryFile(bufsize=0)
++  else:
++    # None means direct to stdout
++    output_dest = None
++  if stdin_input:
++    stdin_dest = subprocess.PIPE
++  else:
++    stdin_dest = None
++  pipe = subprocess.Popen(
++      cmd,
++      executable='/bin/bash',
++      stdin=stdin_dest,
++      stdout=output_dest,
++      stderr=subprocess.STDOUT,
++      shell=True, close_fds=True,
++      preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL))
++
+   def Run():
+     global error_occurred
+-    if return_output:
+-      output_dest = subprocess.PIPE
+-    else:
+-      # None means direct to stdout
+-      output_dest = None
+-    if stdin_input:
+-      stdin_dest = subprocess.PIPE
+-    else:
+-      stdin_dest = None
+-    pipe = subprocess.Popen(
+-        cmd,
+-        executable='/bin/bash',
+-        stdin=stdin_dest,
+-        stdout=output_dest,
+-        stderr=subprocess.STDOUT,
+-        shell=True)
+-    pid.append(pipe.pid)
+     try:
+-      output = pipe.communicate(input=stdin_input)[0]
++      pipe.communicate(input=stdin_input)
++      output = None
++      if return_output:
++        output_dest.seek(0)
++        output = output_dest.read()
++        output_dest.close()
+       if output is not None and len(output) > 0:
+         so.append(output)
+     except OSError, e:
+@@ -119,27 +125,17 @@ def RunOnce(cmd, timeout_time=None, return_output=True, stdin_input=None):
+ 
+   t = threading.Thread(target=Run)
+   t.start()
+-
+-  break_loop = False
+-  while not break_loop:
+-    if not t.isAlive():
+-      break_loop = True
+-
+-    # Check the timeout
+-    if (not break_loop and timeout_time is not None
+-        and time.time() > start_time + timeout_time):
+-      try:
+-        os.kill(pid[0], signal.SIGKILL)
+-      except OSError:
+-        # process already dead. No action required.
+-        pass
+-
++  t.join(timeout_time)
++  if t.isAlive():
++    try:
++      pipe.kill()
++    except OSError:
++      # Can't kill a dead process.
++      pass
++    finally:
+       logger.SilentLog("about to raise a timeout for: %s" % cmd)
+       raise errors.WaitForResponseTimedOutError
+-    if not break_loop:
+-      time.sleep(0.1)
+ 
+-  t.join()
+   output = "".join(so)
+   if _abort_on_error and error_occurred:
+     raise errors.AbortError(msg=output)
diff --git a/third_party/android_testrunner/run_command.py b/third_party/android_testrunner/run_command.py
new file mode 100644
index 0000000..6b84156
--- /dev/null
+++ b/third_party/android_testrunner/run_command.py
@@ -0,0 +1,192 @@
+#!/usr/bin/python2.4
+#
+#
+# Copyright 2007, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# System imports
+import os
+import signal
+import subprocess
+import tempfile
+import threading
+import time
+
+# local imports
+import errors
+import logger
+
+_abort_on_error = False
+
+def SetAbortOnError(abort=True):
+  """Sets behavior of RunCommand to throw AbortError if command process returns
+  a negative error code"""
+  global _abort_on_error
+  _abort_on_error = abort
+
+def RunCommand(cmd, timeout_time=None, retry_count=3, return_output=True,
+               stdin_input=None):
+  """Spawn and retry a subprocess to run the given shell command.
+
+  Args:
+    cmd: shell command to run
+    timeout_time: time in seconds to wait for command to run before aborting.
+    retry_count: number of times to retry command
+    return_output: if True return output of command as string. Otherwise,
+      direct output of command to stdout.
+    stdin_input: data to feed to stdin
+  Returns:
+    output of command
+  """
+  result = None
+  while True:
+    try:
+      result = RunOnce(cmd, timeout_time=timeout_time,
+                       return_output=return_output, stdin_input=stdin_input)
+    except errors.WaitForResponseTimedOutError:
+      if retry_count == 0:
+        raise
+      retry_count -= 1
+      logger.Log("No response for %s, retrying" % cmd)
+    else:
+      # Success
+      return result
+
+def RunOnce(cmd, timeout_time=None, return_output=True, stdin_input=None):
+  """Spawns a subprocess to run the given shell command.
+
+  Args:
+    cmd: shell command to run
+    timeout_time: time in seconds to wait for command to run before aborting.
+    return_output: if True return output of command as string. Otherwise,
+      direct output of command to stdout.
+    stdin_input: data to feed to stdin
+  Returns:
+    output of command
+  Raises:
+    errors.WaitForResponseTimedOutError if command did not complete within
+      timeout_time seconds.
+    errors.AbortError is command returned error code and SetAbortOnError is on.
+  """
+  start_time = time.time()
+  so = []
+  global _abort_on_error, error_occurred
+  error_occurred = False
+
+  if return_output:
+    output_dest = tempfile.TemporaryFile(bufsize=0)
+  else:
+    # None means direct to stdout
+    output_dest = None
+  if stdin_input:
+    stdin_dest = subprocess.PIPE
+  else:
+    stdin_dest = None
+  pipe = subprocess.Popen(
+      cmd,
+      executable='/bin/bash',
+      stdin=stdin_dest,
+      stdout=output_dest,
+      stderr=subprocess.STDOUT,
+      shell=True, close_fds=True,
+      preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL))
+
+  def Run():
+    global error_occurred
+    try:
+      pipe.communicate(input=stdin_input)
+      output = None
+      if return_output:
+        output_dest.seek(0)
+        output = output_dest.read()
+        output_dest.close()
+      if output is not None and len(output) > 0:
+        so.append(output)
+    except OSError, e:
+      logger.SilentLog("failed to retrieve stdout from: %s" % cmd)
+      logger.Log(e)
+      so.append("ERROR")
+      error_occurred = True
+    if pipe.returncode:
+      logger.SilentLog("Error: %s returned %d error code" %(cmd,
+          pipe.returncode))
+      error_occurred = True
+
+  t = threading.Thread(target=Run)
+  t.start()
+  t.join(timeout_time)
+  if t.isAlive():
+    try:
+      pipe.kill()
+    except OSError:
+      # Can't kill a dead process.
+      pass
+    finally:
+      logger.SilentLog("about to raise a timeout for: %s" % cmd)
+      raise errors.WaitForResponseTimedOutError
+
+  output = "".join(so)
+  if _abort_on_error and error_occurred:
+    raise errors.AbortError(msg=output)
+
+  return "".join(so)
+
+
+def RunHostCommand(binary, valgrind=False):
+  """Run a command on the host (opt using valgrind).
+
+  Runs the host binary and returns the exit code.
+  If successfull, the output (stdout and stderr) are discarded,
+  but printed in case of error.
+  The command can be run under valgrind in which case all the
+  output are always discarded.
+
+  Args:
+    binary: full path of the file to be run.
+    valgrind: If True the command will be run under valgrind.
+
+  Returns:
+    The command exit code (int)
+  """
+  if not valgrind:
+    subproc = subprocess.Popen(binary, stdout=subprocess.PIPE,
+                               stderr=subprocess.STDOUT)
+    subproc.wait()
+    if subproc.returncode != 0:         # In case of error print the output
+      print subproc.communicate()[0]
+    return subproc.returncode
+  else:
+    # Need the full path to valgrind to avoid other versions on the system.
+    subproc = subprocess.Popen(["/usr/bin/valgrind", "--tool=memcheck",
+                                "--leak-check=yes", "-q", binary],
+                               stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    # Cannot rely on the retcode of valgrind. Instead look for an empty output.
+    valgrind_out = subproc.communicate()[0].strip()
+    if valgrind_out:
+      print valgrind_out
+      return 1
+    else:
+      return 0
+
+
+def HasValgrind():
+  """Check that /usr/bin/valgrind exists.
+
+  We look for the fullpath to avoid picking up 'alternative' valgrind
+  on the system.
+
+  Returns:
+    True if a system valgrind was found.
+  """
+  return os.path.exists("/usr/bin/valgrind")
diff --git a/third_party/libevent/BUILD.gn b/third_party/libevent/BUILD.gn
index a1bd0c5..648dae3 100644
--- a/third_party/libevent/BUILD.gn
+++ b/third_party/libevent/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("libevent") {
+static_library("libevent") {
   sources = [
     "buffer.c",
     "evbuffer.c",
diff --git a/third_party/modp_b64/BUILD.gn b/third_party/modp_b64/BUILD.gn
index 2ec992b..539abe1 100644
--- a/third_party/modp_b64/BUILD.gn
+++ b/third_party/modp_b64/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("modp_b64") {
+static_library("modp_b64") {
   sources = [
     "modp_b64.cc",
     "modp_b64.h",
diff --git a/third_party/pymock/LICENSE.txt b/third_party/pymock/LICENSE.txt
new file mode 100644
index 0000000..7891703
--- /dev/null
+++ b/third_party/pymock/LICENSE.txt
@@ -0,0 +1,26 @@
+Copyright (c) 2003-2012, Michael Foord
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/pymock/OWNERS b/third_party/pymock/OWNERS
new file mode 100644
index 0000000..9946560
--- /dev/null
+++ b/third_party/pymock/OWNERS
@@ -0,0 +1 @@
+sbc@chromium.org
diff --git a/third_party/pymock/README.chromium b/third_party/pymock/README.chromium
new file mode 100644
index 0000000..aaf355d
--- /dev/null
+++ b/third_party/pymock/README.chromium
@@ -0,0 +1,10 @@
+Name: mock
+URL: http://pypi.python.org/pypi/mock
+Version: 1.0.1
+Security Critical: no
+License: BSD
+License File: LICENSE.txt
+Description:
+Python mock library, currently used by native_client_sdk.  This is the
+same mock library that is now part of python 3.3 where it is know as
+unittest.mock.
diff --git a/third_party/pymock/mock.py b/third_party/pymock/mock.py
new file mode 100644
index 0000000..c8fc5d1
--- /dev/null
+++ b/third_party/pymock/mock.py
@@ -0,0 +1,2367 @@
+# mock.py
+# Test tools for mocking and patching.
+# Copyright (C) 2007-2012 Michael Foord & the mock team
+# E-mail: fuzzyman AT voidspace DOT org DOT uk
+
+# mock 1.0
+# http://www.voidspace.org.uk/python/mock/
+
+# Released subject to the BSD License
+# Please see http://www.voidspace.org.uk/python/license.shtml
+
+# Scripts maintained at http://www.voidspace.org.uk/python/index.shtml
+# Comments, suggestions and bug reports welcome.
+
+
+__all__ = (
+    'Mock',
+    'MagicMock',
+    'patch',
+    'sentinel',
+    'DEFAULT',
+    'ANY',
+    'call',
+    'create_autospec',
+    'FILTER_DIR',
+    'NonCallableMock',
+    'NonCallableMagicMock',
+    'mock_open',
+    'PropertyMock',
+)
+
+
+__version__ = '1.0.1'
+
+
+import pprint
+import sys
+
+try:
+    import inspect
+except ImportError:
+    # for alternative platforms that
+    # may not have inspect
+    inspect = None
+
+try:
+    from functools import wraps as original_wraps
+except ImportError:
+    # Python 2.4 compatibility
+    def wraps(original):
+        def inner(f):
+            f.__name__ = original.__name__
+            f.__doc__ = original.__doc__
+            f.__module__ = original.__module__
+            f.__wrapped__ = original
+            return f
+        return inner
+else:
+    if sys.version_info[:2] >= (3, 3):
+        wraps = original_wraps
+    else:
+        def wraps(func):
+            def inner(f):
+                f = original_wraps(func)(f)
+                f.__wrapped__ = func
+                return f
+            return inner
+
+try:
+    unicode
+except NameError:
+    # Python 3
+    basestring = unicode = str
+
+try:
+    long
+except NameError:
+    # Python 3
+    long = int
+
+try:
+    BaseException
+except NameError:
+    # Python 2.4 compatibility
+    BaseException = Exception
+
+try:
+    next
+except NameError:
+    def next(obj):
+        return obj.next()
+
+
+BaseExceptions = (BaseException,)
+if 'java' in sys.platform:
+    # jython
+    import java
+    BaseExceptions = (BaseException, java.lang.Throwable)
+
+try:
+    _isidentifier = str.isidentifier
+except AttributeError:
+    # Python 2.X
+    import keyword
+    import re
+    regex = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
+    def _isidentifier(string):
+        if string in keyword.kwlist:
+            return False
+        return regex.match(string)
+
+
+inPy3k = sys.version_info[0] == 3
+
+# Needed to work around Python 3 bug where use of "super" interferes with
+# defining __class__ as a descriptor
+_super = super
+
+self = 'im_self'
+builtin = '__builtin__'
+if inPy3k:
+    self = '__self__'
+    builtin = 'builtins'
+
+FILTER_DIR = True
+
+
+def _is_instance_mock(obj):
+    # can't use isinstance on Mock objects because they override __class__
+    # The base class for all mocks is NonCallableMock
+    return issubclass(type(obj), NonCallableMock)
+
+
+def _is_exception(obj):
+    return (
+        isinstance(obj, BaseExceptions) or
+        isinstance(obj, ClassTypes) and issubclass(obj, BaseExceptions)
+    )
+
+
+class _slotted(object):
+    __slots__ = ['a']
+
+
+DescriptorTypes = (
+    type(_slotted.a),
+    property,
+)
+
+
+def _getsignature(func, skipfirst, instance=False):
+    if inspect is None:
+        raise ImportError('inspect module not available')
+
+    if isinstance(func, ClassTypes) and not instance:
+        try:
+            func = func.__init__
+        except AttributeError:
+            return
+        skipfirst = True
+    elif not isinstance(func, FunctionTypes):
+        # for classes where instance is True we end up here too
+        try:
+            func = func.__call__
+        except AttributeError:
+            return
+
+    if inPy3k:
+        try:
+            argspec = inspect.getfullargspec(func)
+        except TypeError:
+            # C function / method, possibly inherited object().__init__
+            return
+        regargs, varargs, varkw, defaults, kwonly, kwonlydef, ann = argspec
+    else:
+        try:
+            regargs, varargs, varkwargs, defaults = inspect.getargspec(func)
+        except TypeError:
+            # C function / method, possibly inherited object().__init__
+            return
+
+    # instance methods and classmethods need to lose the self argument
+    if getattr(func, self, None) is not None:
+        regargs = regargs[1:]
+    if skipfirst:
+        # this condition and the above one are never both True - why?
+        regargs = regargs[1:]
+
+    if inPy3k:
+        signature = inspect.formatargspec(
+            regargs, varargs, varkw, defaults,
+            kwonly, kwonlydef, ann, formatvalue=lambda value: "")
+    else:
+        signature = inspect.formatargspec(
+            regargs, varargs, varkwargs, defaults,
+            formatvalue=lambda value: "")
+    return signature[1:-1], func
+
+
+def _check_signature(func, mock, skipfirst, instance=False):
+    if not _callable(func):
+        return
+
+    result = _getsignature(func, skipfirst, instance)
+    if result is None:
+        return
+    signature, func = result
+
+    # can't use self because "self" is common as an argument name
+    # unfortunately even not in the first place
+    src = "lambda _mock_self, %s: None" % signature
+    checksig = eval(src, {})
+    _copy_func_details(func, checksig)
+    type(mock)._mock_check_sig = checksig
+
+
+def _copy_func_details(func, funcopy):
+    funcopy.__name__ = func.__name__
+    funcopy.__doc__ = func.__doc__
+    #funcopy.__dict__.update(func.__dict__)
+    funcopy.__module__ = func.__module__
+    if not inPy3k:
+        funcopy.func_defaults = func.func_defaults
+        return
+    funcopy.__defaults__ = func.__defaults__
+    funcopy.__kwdefaults__ = func.__kwdefaults__
+
+
+def _callable(obj):
+    if isinstance(obj, ClassTypes):
+        return True
+    if getattr(obj, '__call__', None) is not None:
+        return True
+    return False
+
+
+def _is_list(obj):
+    # checks for list or tuples
+    # XXXX badly named!
+    return type(obj) in (list, tuple)
+
+
+def _instance_callable(obj):
+    """Given an object, return True if the object is callable.
+    For classes, return True if instances would be callable."""
+    if not isinstance(obj, ClassTypes):
+        # already an instance
+        return getattr(obj, '__call__', None) is not None
+
+    klass = obj
+    # uses __bases__ instead of __mro__ so that we work with old style classes
+    if klass.__dict__.get('__call__') is not None:
+        return True
+
+    for base in klass.__bases__:
+        if _instance_callable(base):
+            return True
+    return False
+
+
+def _set_signature(mock, original, instance=False):
+    # creates a function with signature (*args, **kwargs) that delegates to a
+    # mock. It still does signature checking by calling a lambda with the same
+    # signature as the original.
+    if not _callable(original):
+        return
+
+    skipfirst = isinstance(original, ClassTypes)
+    result = _getsignature(original, skipfirst, instance)
+    if result is None:
+        # was a C function (e.g. object().__init__ ) that can't be mocked
+        return
+
+    signature, func = result
+
+    src = "lambda %s: None" % signature
+    checksig = eval(src, {})
+    _copy_func_details(func, checksig)
+
+    name = original.__name__
+    if not _isidentifier(name):
+        name = 'funcopy'
+    context = {'_checksig_': checksig, 'mock': mock}
+    src = """def %s(*args, **kwargs):
+    _checksig_(*args, **kwargs)
+    return mock(*args, **kwargs)""" % name
+    exec (src, context)
+    funcopy = context[name]
+    _setup_func(funcopy, mock)
+    return funcopy
+
+
+def _setup_func(funcopy, mock):
+    funcopy.mock = mock
+
+    # can't use isinstance with mocks
+    if not _is_instance_mock(mock):
+        return
+
+    def assert_called_with(*args, **kwargs):
+        return mock.assert_called_with(*args, **kwargs)
+    def assert_called_once_with(*args, **kwargs):
+        return mock.assert_called_once_with(*args, **kwargs)
+    def assert_has_calls(*args, **kwargs):
+        return mock.assert_has_calls(*args, **kwargs)
+    def assert_any_call(*args, **kwargs):
+        return mock.assert_any_call(*args, **kwargs)
+    def reset_mock():
+        funcopy.method_calls = _CallList()
+        funcopy.mock_calls = _CallList()
+        mock.reset_mock()
+        ret = funcopy.return_value
+        if _is_instance_mock(ret) and not ret is mock:
+            ret.reset_mock()
+
+    funcopy.called = False
+    funcopy.call_count = 0
+    funcopy.call_args = None
+    funcopy.call_args_list = _CallList()
+    funcopy.method_calls = _CallList()
+    funcopy.mock_calls = _CallList()
+
+    funcopy.return_value = mock.return_value
+    funcopy.side_effect = mock.side_effect
+    funcopy._mock_children = mock._mock_children
+
+    funcopy.assert_called_with = assert_called_with
+    funcopy.assert_called_once_with = assert_called_once_with
+    funcopy.assert_has_calls = assert_has_calls
+    funcopy.assert_any_call = assert_any_call
+    funcopy.reset_mock = reset_mock
+
+    mock._mock_delegate = funcopy
+
+
+def _is_magic(name):
+    return '__%s__' % name[2:-2] == name
+
+
+class _SentinelObject(object):
+    "A unique, named, sentinel object."
+    def __init__(self, name):
+        self.name = name
+
+    def __repr__(self):
+        return 'sentinel.%s' % self.name
+
+
+class _Sentinel(object):
+    """Access attributes to return a named object, usable as a sentinel."""
+    def __init__(self):
+        self._sentinels = {}
+
+    def __getattr__(self, name):
+        if name == '__bases__':
+            # Without this help(mock) raises an exception
+            raise AttributeError
+        return self._sentinels.setdefault(name, _SentinelObject(name))
+
+
+sentinel = _Sentinel()
+
+DEFAULT = sentinel.DEFAULT
+_missing = sentinel.MISSING
+_deleted = sentinel.DELETED
+
+
+class OldStyleClass:
+    pass
+ClassType = type(OldStyleClass)
+
+
+def _copy(value):
+    if type(value) in (dict, list, tuple, set):
+        return type(value)(value)
+    return value
+
+
+ClassTypes = (type,)
+if not inPy3k:
+    ClassTypes = (type, ClassType)
+
+_allowed_names = set(
+    [
+        'return_value', '_mock_return_value', 'side_effect',
+        '_mock_side_effect', '_mock_parent', '_mock_new_parent',
+        '_mock_name', '_mock_new_name'
+    ]
+)
+
+
+def _delegating_property(name):
+    _allowed_names.add(name)
+    _the_name = '_mock_' + name
+    def _get(self, name=name, _the_name=_the_name):
+        sig = self._mock_delegate
+        if sig is None:
+            return getattr(self, _the_name)
+        return getattr(sig, name)
+    def _set(self, value, name=name, _the_name=_the_name):
+        sig = self._mock_delegate
+        if sig is None:
+            self.__dict__[_the_name] = value
+        else:
+            setattr(sig, name, value)
+
+    return property(_get, _set)
+
+
+
+class _CallList(list):
+
+    def __contains__(self, value):
+        if not isinstance(value, list):
+            return list.__contains__(self, value)
+        len_value = len(value)
+        len_self = len(self)
+        if len_value > len_self:
+            return False
+
+        for i in range(0, len_self - len_value + 1):
+            sub_list = self[i:i+len_value]
+            if sub_list == value:
+                return True
+        return False
+
+    def __repr__(self):
+        return pprint.pformat(list(self))
+
+
+def _check_and_set_parent(parent, value, name, new_name):
+    if not _is_instance_mock(value):
+        return False
+    if ((value._mock_name or value._mock_new_name) or
+        (value._mock_parent is not None) or
+        (value._mock_new_parent is not None)):
+        return False
+
+    _parent = parent
+    while _parent is not None:
+        # setting a mock (value) as a child or return value of itself
+        # should not modify the mock
+        if _parent is value:
+            return False
+        _parent = _parent._mock_new_parent
+
+    if new_name:
+        value._mock_new_parent = parent
+        value._mock_new_name = new_name
+    if name:
+        value._mock_parent = parent
+        value._mock_name = name
+    return True
+
+
+
+class Base(object):
+    _mock_return_value = DEFAULT
+    _mock_side_effect = None
+    def __init__(self, *args, **kwargs):
+        pass
+
+
+
+class NonCallableMock(Base):
+    """A non-callable version of `Mock`"""
+
+    def __new__(cls, *args, **kw):
+        # every instance has its own class
+        # so we can create magic methods on the
+        # class without stomping on other mocks
+        new = type(cls.__name__, (cls,), {'__doc__': cls.__doc__})
+        instance = object.__new__(new)
+        return instance
+
+
+    def __init__(
+            self, spec=None, wraps=None, name=None, spec_set=None,
+            parent=None, _spec_state=None, _new_name='', _new_parent=None,
+            **kwargs
+        ):
+        if _new_parent is None:
+            _new_parent = parent
+
+        __dict__ = self.__dict__
+        __dict__['_mock_parent'] = parent
+        __dict__['_mock_name'] = name
+        __dict__['_mock_new_name'] = _new_name
+        __dict__['_mock_new_parent'] = _new_parent
+
+        if spec_set is not None:
+            spec = spec_set
+            spec_set = True
+
+        self._mock_add_spec(spec, spec_set)
+
+        __dict__['_mock_children'] = {}
+        __dict__['_mock_wraps'] = wraps
+        __dict__['_mock_delegate'] = None
+
+        __dict__['_mock_called'] = False
+        __dict__['_mock_call_args'] = None
+        __dict__['_mock_call_count'] = 0
+        __dict__['_mock_call_args_list'] = _CallList()
+        __dict__['_mock_mock_calls'] = _CallList()
+
+        __dict__['method_calls'] = _CallList()
+
+        if kwargs:
+            self.configure_mock(**kwargs)
+
+        _super(NonCallableMock, self).__init__(
+            spec, wraps, name, spec_set, parent,
+            _spec_state
+        )
+
+
+    def attach_mock(self, mock, attribute):
+        """
+        Attach a mock as an attribute of this one, replacing its name and
+        parent. Calls to the attached mock will be recorded in the
+        `method_calls` and `mock_calls` attributes of this one."""
+        mock._mock_parent = None
+        mock._mock_new_parent = None
+        mock._mock_name = ''
+        mock._mock_new_name = None
+
+        setattr(self, attribute, mock)
+
+
+    def mock_add_spec(self, spec, spec_set=False):
+        """Add a spec to a mock. `spec` can either be an object or a
+        list of strings. Only attributes on the `spec` can be fetched as
+        attributes from the mock.
+
+        If `spec_set` is True then only attributes on the spec can be set."""
+        self._mock_add_spec(spec, spec_set)
+
+
+    def _mock_add_spec(self, spec, spec_set):
+        _spec_class = None
+
+        if spec is not None and not _is_list(spec):
+            if isinstance(spec, ClassTypes):
+                _spec_class = spec
+            else:
+                _spec_class = _get_class(spec)
+
+            spec = dir(spec)
+
+        __dict__ = self.__dict__
+        __dict__['_spec_class'] = _spec_class
+        __dict__['_spec_set'] = spec_set
+        __dict__['_mock_methods'] = spec
+
+
+    def __get_return_value(self):
+        ret = self._mock_return_value
+        if self._mock_delegate is not None:
+            ret = self._mock_delegate.return_value
+
+        if ret is DEFAULT:
+            ret = self._get_child_mock(
+                _new_parent=self, _new_name='()'
+            )
+            self.return_value = ret
+        return ret
+
+
+    def __set_return_value(self, value):
+        if self._mock_delegate is not None:
+            self._mock_delegate.return_value = value
+        else:
+            self._mock_return_value = value
+            _check_and_set_parent(self, value, None, '()')
+
+    __return_value_doc = "The value to be returned when the mock is called."
+    return_value = property(__get_return_value, __set_return_value,
+                            __return_value_doc)
+
+
+    @property
+    def __class__(self):
+        if self._spec_class is None:
+            return type(self)
+        return self._spec_class
+
+    called = _delegating_property('called')
+    call_count = _delegating_property('call_count')
+    call_args = _delegating_property('call_args')
+    call_args_list = _delegating_property('call_args_list')
+    mock_calls = _delegating_property('mock_calls')
+
+
+    def __get_side_effect(self):
+        sig = self._mock_delegate
+        if sig is None:
+            return self._mock_side_effect
+        return sig.side_effect
+
+    def __set_side_effect(self, value):
+        value = _try_iter(value)
+        sig = self._mock_delegate
+        if sig is None:
+            self._mock_side_effect = value
+        else:
+            sig.side_effect = value
+
+    side_effect = property(__get_side_effect, __set_side_effect)
+
+
+    def reset_mock(self):
+        "Restore the mock object to its initial state."
+        self.called = False
+        self.call_args = None
+        self.call_count = 0
+        self.mock_calls = _CallList()
+        self.call_args_list = _CallList()
+        self.method_calls = _CallList()
+
+        for child in self._mock_children.values():
+            if isinstance(child, _SpecState):
+                continue
+            child.reset_mock()
+
+        ret = self._mock_return_value
+        if _is_instance_mock(ret) and ret is not self:
+            ret.reset_mock()
+
+
+    def configure_mock(self, **kwargs):
+        """Set attributes on the mock through keyword arguments.
+
+        Attributes plus return values and side effects can be set on child
+        mocks using standard dot notation and unpacking a dictionary in the
+        method call:
+
+        >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
+        >>> mock.configure_mock(**attrs)"""
+        for arg, val in sorted(kwargs.items(),
+                               # we sort on the number of dots so that
+                               # attributes are set before we set attributes on
+                               # attributes
+                               key=lambda entry: entry[0].count('.')):
+            args = arg.split('.')
+            final = args.pop()
+            obj = self
+            for entry in args:
+                obj = getattr(obj, entry)
+            setattr(obj, final, val)
+
+
+    def __getattr__(self, name):
+        if name == '_mock_methods':
+            raise AttributeError(name)
+        elif self._mock_methods is not None:
+            if name not in self._mock_methods or name in _all_magics:
+                raise AttributeError("Mock object has no attribute %r" % name)
+        elif _is_magic(name):
+            raise AttributeError(name)
+
+        result = self._mock_children.get(name)
+        if result is _deleted:
+            raise AttributeError(name)
+        elif result is None:
+            wraps = None
+            if self._mock_wraps is not None:
+                # XXXX should we get the attribute without triggering code
+                # execution?
+                wraps = getattr(self._mock_wraps, name)
+
+            result = self._get_child_mock(
+                parent=self, name=name, wraps=wraps, _new_name=name,
+                _new_parent=self
+            )
+            self._mock_children[name]  = result
+
+        elif isinstance(result, _SpecState):
+            result = create_autospec(
+                result.spec, result.spec_set, result.instance,
+                result.parent, result.name
+            )
+            self._mock_children[name]  = result
+
+        return result
+
+
+    def __repr__(self):
+        _name_list = [self._mock_new_name]
+        _parent = self._mock_new_parent
+        last = self
+
+        dot = '.'
+        if _name_list == ['()']:
+            dot = ''
+        seen = set()
+        while _parent is not None:
+            last = _parent
+
+            _name_list.append(_parent._mock_new_name + dot)
+            dot = '.'
+            if _parent._mock_new_name == '()':
+                dot = ''
+
+            _parent = _parent._mock_new_parent
+
+            # use ids here so as not to call __hash__ on the mocks
+            if id(_parent) in seen:
+                break
+            seen.add(id(_parent))
+
+        _name_list = list(reversed(_name_list))
+        _first = last._mock_name or 'mock'
+        if len(_name_list) > 1:
+            if _name_list[1] not in ('()', '().'):
+                _first += '.'
+        _name_list[0] = _first
+        name = ''.join(_name_list)
+
+        name_string = ''
+        if name not in ('mock', 'mock.'):
+            name_string = ' name=%r' % name
+
+        spec_string = ''
+        if self._spec_class is not None:
+            spec_string = ' spec=%r'
+            if self._spec_set:
+                spec_string = ' spec_set=%r'
+            spec_string = spec_string % self._spec_class.__name__
+        return "<%s%s%s id='%s'>" % (
+            type(self).__name__,
+            name_string,
+            spec_string,
+            id(self)
+        )
+
+
+    def __dir__(self):
+        """Filter the output of `dir(mock)` to only useful members.
+        XXXX
+        """
+        extras = self._mock_methods or []
+        from_type = dir(type(self))
+        from_dict = list(self.__dict__)
+
+        if FILTER_DIR:
+            from_type = [e for e in from_type if not e.startswith('_')]
+            from_dict = [e for e in from_dict if not e.startswith('_') or
+                         _is_magic(e)]
+        return sorted(set(extras + from_type + from_dict +
+                          list(self._mock_children)))
+
+
+    def __setattr__(self, name, value):
+        if name in _allowed_names:
+            # property setters go through here
+            return object.__setattr__(self, name, value)
+        elif (self._spec_set and self._mock_methods is not None and
+            name not in self._mock_methods and
+            name not in self.__dict__):
+            raise AttributeError("Mock object has no attribute '%s'" % name)
+        elif name in _unsupported_magics:
+            msg = 'Attempting to set unsupported magic method %r.' % name
+            raise AttributeError(msg)
+        elif name in _all_magics:
+            if self._mock_methods is not None and name not in self._mock_methods:
+                raise AttributeError("Mock object has no attribute '%s'" % name)
+
+            if not _is_instance_mock(value):
+                setattr(type(self), name, _get_method(name, value))
+                original = value
+                value = lambda *args, **kw: original(self, *args, **kw)
+            else:
+                # only set _new_name and not name so that mock_calls is tracked
+                # but not method calls
+                _check_and_set_parent(self, value, None, name)
+                setattr(type(self), name, value)
+                self._mock_children[name] = value
+        elif name == '__class__':
+            self._spec_class = value
+            return
+        else:
+            if _check_and_set_parent(self, value, name, name):
+                self._mock_children[name] = value
+        return object.__setattr__(self, name, value)
+
+
+    def __delattr__(self, name):
+        if name in _all_magics and name in type(self).__dict__:
+            delattr(type(self), name)
+            if name not in self.__dict__:
+                # for magic methods that are still MagicProxy objects and
+                # not set on the instance itself
+                return
+
+        if name in self.__dict__:
+            object.__delattr__(self, name)
+
+        obj = self._mock_children.get(name, _missing)
+        if obj is _deleted:
+            raise AttributeError(name)
+        if obj is not _missing:
+            del self._mock_children[name]
+        self._mock_children[name] = _deleted
+
+
+
+    def _format_mock_call_signature(self, args, kwargs):
+        name = self._mock_name or 'mock'
+        return _format_call_signature(name, args, kwargs)
+
+
+    def _format_mock_failure_message(self, args, kwargs):
+        message = 'Expected call: %s\nActual call: %s'
+        expected_string = self._format_mock_call_signature(args, kwargs)
+        call_args = self.call_args
+        if len(call_args) == 3:
+            call_args = call_args[1:]
+        actual_string = self._format_mock_call_signature(*call_args)
+        return message % (expected_string, actual_string)
+
+
+    def assert_called_with(_mock_self, *args, **kwargs):
+        """assert that the mock was called with the specified arguments.
+
+        Raises an AssertionError if the args and keyword args passed in are
+        different to the last call to the mock."""
+        self = _mock_self
+        if self.call_args is None:
+            expected = self._format_mock_call_signature(args, kwargs)
+            raise AssertionError('Expected call: %s\nNot called' % (expected,))
+
+        if self.call_args != (args, kwargs):
+            msg = self._format_mock_failure_message(args, kwargs)
+            raise AssertionError(msg)
+
+
+    def assert_called_once_with(_mock_self, *args, **kwargs):
+        """assert that the mock was called exactly once and with the specified
+        arguments."""
+        self = _mock_self
+        if not self.call_count == 1:
+            msg = ("Expected to be called once. Called %s times." %
+                   self.call_count)
+            raise AssertionError(msg)
+        return self.assert_called_with(*args, **kwargs)
+
+
+    def assert_has_calls(self, calls, any_order=False):
+        """assert the mock has been called with the specified calls.
+        The `mock_calls` list is checked for the calls.
+
+        If `any_order` is False (the default) then the calls must be
+        sequential. There can be extra calls before or after the
+        specified calls.
+
+        If `any_order` is True then the calls can be in any order, but
+        they must all appear in `mock_calls`."""
+        if not any_order:
+            if calls not in self.mock_calls:
+                raise AssertionError(
+                    'Calls not found.\nExpected: %r\n'
+                    'Actual: %r' % (calls, self.mock_calls)
+                )
+            return
+
+        all_calls = list(self.mock_calls)
+
+        not_found = []
+        for kall in calls:
+            try:
+                all_calls.remove(kall)
+            except ValueError:
+                not_found.append(kall)
+        if not_found:
+            raise AssertionError(
+                '%r not all found in call list' % (tuple(not_found),)
+            )
+
+
+    def assert_any_call(self, *args, **kwargs):
+        """assert the mock has been called with the specified arguments.
+
+        The assert passes if the mock has *ever* been called, unlike
+        `assert_called_with` and `assert_called_once_with` that only pass if
+        the call is the most recent one."""
+        kall = call(*args, **kwargs)
+        if kall not in self.call_args_list:
+            expected_string = self._format_mock_call_signature(args, kwargs)
+            raise AssertionError(
+                '%s call not found' % expected_string
+            )
+
+
+    def _get_child_mock(self, **kw):
+        """Create the child mocks for attributes and return value.
+        By default child mocks will be the same type as the parent.
+        Subclasses of Mock may want to override this to customize the way
+        child mocks are made.
+
+        For non-callable mocks the callable variant will be used (rather than
+        any custom subclass)."""
+        _type = type(self)
+        if not issubclass(_type, CallableMixin):
+            if issubclass(_type, NonCallableMagicMock):
+                klass = MagicMock
+            elif issubclass(_type, NonCallableMock) :
+                klass = Mock
+        else:
+            klass = _type.__mro__[1]
+        return klass(**kw)
+
+
+
+def _try_iter(obj):
+    if obj is None:
+        return obj
+    if _is_exception(obj):
+        return obj
+    if _callable(obj):
+        return obj
+    try:
+        return iter(obj)
+    except TypeError:
+        # XXXX backwards compatibility
+        # but this will blow up on first call - so maybe we should fail early?
+        return obj
+
+
+
+class CallableMixin(Base):
+
+    def __init__(self, spec=None, side_effect=None, return_value=DEFAULT,
+                 wraps=None, name=None, spec_set=None, parent=None,
+                 _spec_state=None, _new_name='', _new_parent=None, **kwargs):
+        self.__dict__['_mock_return_value'] = return_value
+
+        _super(CallableMixin, self).__init__(
+            spec, wraps, name, spec_set, parent,
+            _spec_state, _new_name, _new_parent, **kwargs
+        )
+
+        self.side_effect = side_effect
+
+
+    def _mock_check_sig(self, *args, **kwargs):
+        # stub method that can be replaced with one with a specific signature
+        pass
+
+
+    def __call__(_mock_self, *args, **kwargs):
+        # can't use self in-case a function / method we are mocking uses self
+        # in the signature
+        _mock_self._mock_check_sig(*args, **kwargs)
+        return _mock_self._mock_call(*args, **kwargs)
+
+
+    def _mock_call(_mock_self, *args, **kwargs):
+        self = _mock_self
+        self.called = True
+        self.call_count += 1
+        self.call_args = _Call((args, kwargs), two=True)
+        self.call_args_list.append(_Call((args, kwargs), two=True))
+
+        _new_name = self._mock_new_name
+        _new_parent = self._mock_new_parent
+        self.mock_calls.append(_Call(('', args, kwargs)))
+
+        seen = set()
+        skip_next_dot = _new_name == '()'
+        do_method_calls = self._mock_parent is not None
+        name = self._mock_name
+        while _new_parent is not None:
+            this_mock_call = _Call((_new_name, args, kwargs))
+            if _new_parent._mock_new_name:
+                dot = '.'
+                if skip_next_dot:
+                    dot = ''
+
+                skip_next_dot = False
+                if _new_parent._mock_new_name == '()':
+                    skip_next_dot = True
+
+                _new_name = _new_parent._mock_new_name + dot + _new_name
+
+            if do_method_calls:
+                if _new_name == name:
+                    this_method_call = this_mock_call
+                else:
+                    this_method_call = _Call((name, args, kwargs))
+                _new_parent.method_calls.append(this_method_call)
+
+                do_method_calls = _new_parent._mock_parent is not None
+                if do_method_calls:
+                    name = _new_parent._mock_name + '.' + name
+
+            _new_parent.mock_calls.append(this_mock_call)
+            _new_parent = _new_parent._mock_new_parent
+
+            # use ids here so as not to call __hash__ on the mocks
+            _new_parent_id = id(_new_parent)
+            if _new_parent_id in seen:
+                break
+            seen.add(_new_parent_id)
+
+        ret_val = DEFAULT
+        effect = self.side_effect
+        if effect is not None:
+            if _is_exception(effect):
+                raise effect
+
+            if not _callable(effect):
+                result = next(effect)
+                if _is_exception(result):
+                    raise result
+                return result
+
+            ret_val = effect(*args, **kwargs)
+            if ret_val is DEFAULT:
+                ret_val = self.return_value
+
+        if (self._mock_wraps is not None and
+             self._mock_return_value is DEFAULT):
+            return self._mock_wraps(*args, **kwargs)
+        if ret_val is DEFAULT:
+            ret_val = self.return_value
+        return ret_val
+
+
+
+class Mock(CallableMixin, NonCallableMock):
+    """
+    Create a new `Mock` object. `Mock` takes several optional arguments
+    that specify the behaviour of the Mock object:
+
+    * `spec`: This can be either a list of strings or an existing object (a
+      class or instance) that acts as the specification for the mock object. If
+      you pass in an object then a list of strings is formed by calling dir on
+      the object (excluding unsupported magic attributes and methods). Accessing
+      any attribute not in this list will raise an `AttributeError`.
+
+      If `spec` is an object (rather than a list of strings) then
+      `mock.__class__` returns the class of the spec object. This allows mocks
+      to pass `isinstance` tests.
+
+    * `spec_set`: A stricter variant of `spec`. If used, attempting to *set*
+      or get an attribute on the mock that isn't on the object passed as
+      `spec_set` will raise an `AttributeError`.
+
+    * `side_effect`: A function to be called whenever the Mock is called. See
+      the `side_effect` attribute. Useful for raising exceptions or
+      dynamically changing return values. The function is called with the same
+      arguments as the mock, and unless it returns `DEFAULT`, the return
+      value of this function is used as the return value.
+
+      Alternatively `side_effect` can be an exception class or instance. In
+      this case the exception will be raised when the mock is called.
+
+      If `side_effect` is an iterable then each call to the mock will return
+      the next value from the iterable. If any of the members of the iterable
+      are exceptions they will be raised instead of returned.
+
+    * `return_value`: The value returned when the mock is called. By default
+      this is a new Mock (created on first access). See the
+      `return_value` attribute.
+
+    * `wraps`: Item for the mock object to wrap. If `wraps` is not None then
+      calling the Mock will pass the call through to the wrapped object
+      (returning the real result). Attribute access on the mock will return a
+      Mock object that wraps the corresponding attribute of the wrapped object
+      (so attempting to access an attribute that doesn't exist will raise an
+      `AttributeError`).
+
+      If the mock has an explicit `return_value` set then calls are not passed
+      to the wrapped object and the `return_value` is returned instead.
+
+    * `name`: If the mock has a name then it will be used in the repr of the
+      mock. This can be useful for debugging. The name is propagated to child
+      mocks.
+
+    Mocks can also be called with arbitrary keyword arguments. These will be
+    used to set attributes on the mock after it is created.
+    """
+
+
+
+def _dot_lookup(thing, comp, import_path):
+    try:
+        return getattr(thing, comp)
+    except AttributeError:
+        __import__(import_path)
+        return getattr(thing, comp)
+
+
+def _importer(target):
+    components = target.split('.')
+    import_path = components.pop(0)
+    thing = __import__(import_path)
+
+    for comp in components:
+        import_path += ".%s" % comp
+        thing = _dot_lookup(thing, comp, import_path)
+    return thing
+
+
+def _is_started(patcher):
+    # XXXX horrible
+    return hasattr(patcher, 'is_local')
+
+
+class _patch(object):
+
+    attribute_name = None
+    _active_patches = set()
+
+    def __init__(
+            self, getter, attribute, new, spec, create,
+            spec_set, autospec, new_callable, kwargs
+        ):
+        if new_callable is not None:
+            if new is not DEFAULT:
+                raise ValueError(
+                    "Cannot use 'new' and 'new_callable' together"
+                )
+            if autospec is not None:
+                raise ValueError(
+                    "Cannot use 'autospec' and 'new_callable' together"
+                )
+
+        self.getter = getter
+        self.attribute = attribute
+        self.new = new
+        self.new_callable = new_callable
+        self.spec = spec
+        self.create = create
+        self.has_local = False
+        self.spec_set = spec_set
+        self.autospec = autospec
+        self.kwargs = kwargs
+        self.additional_patchers = []
+
+
+    def copy(self):
+        patcher = _patch(
+            self.getter, self.attribute, self.new, self.spec,
+            self.create, self.spec_set,
+            self.autospec, self.new_callable, self.kwargs
+        )
+        patcher.attribute_name = self.attribute_name
+        patcher.additional_patchers = [
+            p.copy() for p in self.additional_patchers
+        ]
+        return patcher
+
+
+    def __call__(self, func):
+        if isinstance(func, ClassTypes):
+            return self.decorate_class(func)
+        return self.decorate_callable(func)
+
+
+    def decorate_class(self, klass):
+        for attr in dir(klass):
+            if not attr.startswith(patch.TEST_PREFIX):
+                continue
+
+            attr_value = getattr(klass, attr)
+            if not hasattr(attr_value, "__call__"):
+                continue
+
+            patcher = self.copy()
+            setattr(klass, attr, patcher(attr_value))
+        return klass
+
+
+    def decorate_callable(self, func):
+        if hasattr(func, 'patchings'):
+            func.patchings.append(self)
+            return func
+
+        @wraps(func)
+        def patched(*args, **keywargs):
+            # don't use a with here (backwards compatability with Python 2.4)
+            extra_args = []
+            entered_patchers = []
+
+            # can't use try...except...finally because of Python 2.4
+            # compatibility
+            exc_info = tuple()
+            try:
+                try:
+                    for patching in patched.patchings:
+                        arg = patching.__enter__()
+                        entered_patchers.append(patching)
+                        if patching.attribute_name is not None:
+                            keywargs.update(arg)
+                        elif patching.new is DEFAULT:
+                            extra_args.append(arg)
+
+                    args += tuple(extra_args)
+                    return func(*args, **keywargs)
+                except:
+                    if (patching not in entered_patchers and
+                        _is_started(patching)):
+                        # the patcher may have been started, but an exception
+                        # raised whilst entering one of its additional_patchers
+                        entered_patchers.append(patching)
+                    # Pass the exception to __exit__
+                    exc_info = sys.exc_info()
+                    # re-raise the exception
+                    raise
+            finally:
+                for patching in reversed(entered_patchers):
+                    patching.__exit__(*exc_info)
+
+        patched.patchings = [self]
+        if hasattr(func, 'func_code'):
+            # not in Python 3
+            patched.compat_co_firstlineno = getattr(
+                func, "compat_co_firstlineno",
+                func.func_code.co_firstlineno
+            )
+        return patched
+
+
+    def get_original(self):
+        target = self.getter()
+        name = self.attribute
+
+        original = DEFAULT
+        local = False
+
+        try:
+            original = target.__dict__[name]
+        except (AttributeError, KeyError):
+            original = getattr(target, name, DEFAULT)
+        else:
+            local = True
+
+        if not self.create and original is DEFAULT:
+            raise AttributeError(
+                "%s does not have the attribute %r" % (target, name)
+            )
+        return original, local
+
+
+    def __enter__(self):
+        """Perform the patch."""
+        new, spec, spec_set = self.new, self.spec, self.spec_set
+        autospec, kwargs = self.autospec, self.kwargs
+        new_callable = self.new_callable
+        self.target = self.getter()
+
+        # normalise False to None
+        if spec is False:
+            spec = None
+        if spec_set is False:
+            spec_set = None
+        if autospec is False:
+            autospec = None
+
+        if spec is not None and autospec is not None:
+            raise TypeError("Can't specify spec and autospec")
+        if ((spec is not None or autospec is not None) and
+            spec_set not in (True, None)):
+            raise TypeError("Can't provide explicit spec_set *and* spec or autospec")
+
+        original, local = self.get_original()
+
+        if new is DEFAULT and autospec is None:
+            inherit = False
+            if spec is True:
+                # set spec to the object we are replacing
+                spec = original
+                if spec_set is True:
+                    spec_set = original
+                    spec = None
+            elif spec is not None:
+                if spec_set is True:
+                    spec_set = spec
+                    spec = None
+            elif spec_set is True:
+                spec_set = original
+
+            if spec is not None or spec_set is not None:
+                if original is DEFAULT:
+                    raise TypeError("Can't use 'spec' with create=True")
+                if isinstance(original, ClassTypes):
+                    # If we're patching out a class and there is a spec
+                    inherit = True
+
+            Klass = MagicMock
+            _kwargs = {}
+            if new_callable is not None:
+                Klass = new_callable
+            elif spec is not None or spec_set is not None:
+                this_spec = spec
+                if spec_set is not None:
+                    this_spec = spec_set
+                if _is_list(this_spec):
+                    not_callable = '__call__' not in this_spec
+                else:
+                    not_callable = not _callable(this_spec)
+                if not_callable:
+                    Klass = NonCallableMagicMock
+
+            if spec is not None:
+                _kwargs['spec'] = spec
+            if spec_set is not None:
+                _kwargs['spec_set'] = spec_set
+
+            # add a name to mocks
+            if (isinstance(Klass, type) and
+                issubclass(Klass, NonCallableMock) and self.attribute):
+                _kwargs['name'] = self.attribute
+
+            _kwargs.update(kwargs)
+            new = Klass(**_kwargs)
+
+            if inherit and _is_instance_mock(new):
+                # we can only tell if the instance should be callable if the
+                # spec is not a list
+                this_spec = spec
+                if spec_set is not None:
+                    this_spec = spec_set
+                if (not _is_list(this_spec) and not
+                    _instance_callable(this_spec)):
+                    Klass = NonCallableMagicMock
+
+                _kwargs.pop('name')
+                new.return_value = Klass(_new_parent=new, _new_name='()',
+                                         **_kwargs)
+        elif autospec is not None:
+            # spec is ignored, new *must* be default, spec_set is treated
+            # as a boolean. Should we check spec is not None and that spec_set
+            # is a bool?
+            if new is not DEFAULT:
+                raise TypeError(
+                    "autospec creates the mock for you. Can't specify "
+                    "autospec and new."
+                )
+            if original is DEFAULT:
+                raise TypeError("Can't use 'autospec' with create=True")
+            spec_set = bool(spec_set)
+            if autospec is True:
+                autospec = original
+
+            new = create_autospec(autospec, spec_set=spec_set,
+                                  _name=self.attribute, **kwargs)
+        elif kwargs:
+            # can't set keyword args when we aren't creating the mock
+            # XXXX If new is a Mock we could call new.configure_mock(**kwargs)
+            raise TypeError("Can't pass kwargs to a mock we aren't creating")
+
+        new_attr = new
+
+        self.temp_original = original
+        self.is_local = local
+        setattr(self.target, self.attribute, new_attr)
+        if self.attribute_name is not None:
+            extra_args = {}
+            if self.new is DEFAULT:
+                extra_args[self.attribute_name] =  new
+            for patching in self.additional_patchers:
+                arg = patching.__enter__()
+                if patching.new is DEFAULT:
+                    extra_args.update(arg)
+            return extra_args
+
+        return new
+
+
+    def __exit__(self, *exc_info):
+        """Undo the patch."""
+        if not _is_started(self):
+            raise RuntimeError('stop called on unstarted patcher')
+
+        if self.is_local and self.temp_original is not DEFAULT:
+            setattr(self.target, self.attribute, self.temp_original)
+        else:
+            delattr(self.target, self.attribute)
+            if not self.create and not hasattr(self.target, self.attribute):
+                # needed for proxy objects like django settings
+                setattr(self.target, self.attribute, self.temp_original)
+
+        del self.temp_original
+        del self.is_local
+        del self.target
+        for patcher in reversed(self.additional_patchers):
+            if _is_started(patcher):
+                patcher.__exit__(*exc_info)
+
+
+    def start(self):
+        """Activate a patch, returning any created mock."""
+        result = self.__enter__()
+        self._active_patches.add(self)
+        return result
+
+
+    def stop(self):
+        """Stop an active patch."""
+        self._active_patches.discard(self)
+        return self.__exit__()
+
+
+
+def _get_target(target):
+    try:
+        target, attribute = target.rsplit('.', 1)
+    except (TypeError, ValueError):
+        raise TypeError("Need a valid target to patch. You supplied: %r" %
+                        (target,))
+    getter = lambda: _importer(target)
+    return getter, attribute
+
+
+def _patch_object(
+        target, attribute, new=DEFAULT, spec=None,
+        create=False, spec_set=None, autospec=None,
+        new_callable=None, **kwargs
+    ):
+    """
+    patch.object(target, attribute, new=DEFAULT, spec=None, create=False,
+                 spec_set=None, autospec=None, new_callable=None, **kwargs)
+
+    patch the named member (`attribute`) on an object (`target`) with a mock
+    object.
+
+    `patch.object` can be used as a decorator, class decorator or a context
+    manager. Arguments `new`, `spec`, `create`, `spec_set`,
+    `autospec` and `new_callable` have the same meaning as for `patch`. Like
+    `patch`, `patch.object` takes arbitrary keyword arguments for configuring
+    the mock object it creates.
+
+    When used as a class decorator `patch.object` honours `patch.TEST_PREFIX`
+    for choosing which methods to wrap.
+    """
+    getter = lambda: target
+    return _patch(
+        getter, attribute, new, spec, create,
+        spec_set, autospec, new_callable, kwargs
+    )
+
+
+def _patch_multiple(target, spec=None, create=False, spec_set=None,
+                    autospec=None, new_callable=None, **kwargs):
+    """Perform multiple patches in a single call. It takes the object to be
+    patched (either as an object or a string to fetch the object by importing)
+    and keyword arguments for the patches::
+
+        with patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two'):
+            ...
+
+    Use `DEFAULT` as the value if you want `patch.multiple` to create
+    mocks for you. In this case the created mocks are passed into a decorated
+    function by keyword, and a dictionary is returned when `patch.multiple` is
+    used as a context manager.
+
+    `patch.multiple` can be used as a decorator, class decorator or a context
+    manager. The arguments `spec`, `spec_set`, `create`,
+    `autospec` and `new_callable` have the same meaning as for `patch`. These
+    arguments will be applied to *all* patches done by `patch.multiple`.
+
+    When used as a class decorator `patch.multiple` honours `patch.TEST_PREFIX`
+    for choosing which methods to wrap.
+    """
+    if type(target) in (unicode, str):
+        getter = lambda: _importer(target)
+    else:
+        getter = lambda: target
+
+    if not kwargs:
+        raise ValueError(
+            'Must supply at least one keyword argument with patch.multiple'
+        )
+    # need to wrap in a list for python 3, where items is a view
+    items = list(kwargs.items())
+    attribute, new = items[0]
+    patcher = _patch(
+        getter, attribute, new, spec, create, spec_set,
+        autospec, new_callable, {}
+    )
+    patcher.attribute_name = attribute
+    for attribute, new in items[1:]:
+        this_patcher = _patch(
+            getter, attribute, new, spec, create, spec_set,
+            autospec, new_callable, {}
+        )
+        this_patcher.attribute_name = attribute
+        patcher.additional_patchers.append(this_patcher)
+    return patcher
+
+
+def patch(
+        target, new=DEFAULT, spec=None, create=False,
+        spec_set=None, autospec=None, new_callable=None, **kwargs
+    ):
+    """
+    `patch` acts as a function decorator, class decorator or a context
+    manager. Inside the body of the function or with statement, the `target`
+    is patched with a `new` object. When the function/with statement exits
+    the patch is undone.
+
+    If `new` is omitted, then the target is replaced with a
+    `MagicMock`. If `patch` is used as a decorator and `new` is
+    omitted, the created mock is passed in as an extra argument to the
+    decorated function. If `patch` is used as a context manager the created
+    mock is returned by the context manager.
+
+    `target` should be a string in the form `'package.module.ClassName'`. The
+    `target` is imported and the specified object replaced with the `new`
+    object, so the `target` must be importable from the environment you are
+    calling `patch` from. The target is imported when the decorated function
+    is executed, not at decoration time.
+
+    The `spec` and `spec_set` keyword arguments are passed to the `MagicMock`
+    if patch is creating one for you.
+
+    In addition you can pass `spec=True` or `spec_set=True`, which causes
+    patch to pass in the object being mocked as the spec/spec_set object.
+
+    `new_callable` allows you to specify a different class, or callable object,
+    that will be called to create the `new` object. By default `MagicMock` is
+    used.
+
+    A more powerful form of `spec` is `autospec`. If you set `autospec=True`
+    then the mock with be created with a spec from the object being replaced.
+    All attributes of the mock will also have the spec of the corresponding
+    attribute of the object being replaced. Methods and functions being
+    mocked will have their arguments checked and will raise a `TypeError` if
+    they are called with the wrong signature. For mocks replacing a class,
+    their return value (the 'instance') will have the same spec as the class.
+
+    Instead of `autospec=True` you can pass `autospec=some_object` to use an
+    arbitrary object as the spec instead of the one being replaced.
+
+    By default `patch` will fail to replace attributes that don't exist. If
+    you pass in `create=True`, and the attribute doesn't exist, patch will
+    create the attribute for you when the patched function is called, and
+    delete it again afterwards. This is useful for writing tests against
+    attributes that your production code creates at runtime. It is off by by
+    default because it can be dangerous. With it switched on you can write
+    passing tests against APIs that don't actually exist!
+
+    Patch can be used as a `TestCase` class decorator. It works by
+    decorating each test method in the class. This reduces the boilerplate
+    code when your test methods share a common patchings set. `patch` finds
+    tests by looking for method names that start with `patch.TEST_PREFIX`.
+    By default this is `test`, which matches the way `unittest` finds tests.
+    You can specify an alternative prefix by setting `patch.TEST_PREFIX`.
+
+    Patch can be used as a context manager, with the with statement. Here the
+    patching applies to the indented block after the with statement. If you
+    use "as" then the patched object will be bound to the name after the
+    "as"; very useful if `patch` is creating a mock object for you.
+
+    `patch` takes arbitrary keyword arguments. These will be passed to
+    the `Mock` (or `new_callable`) on construction.
+
+    `patch.dict(...)`, `patch.multiple(...)` and `patch.object(...)` are
+    available for alternate use-cases.
+    """
+    getter, attribute = _get_target(target)
+    return _patch(
+        getter, attribute, new, spec, create,
+        spec_set, autospec, new_callable, kwargs
+    )
+
+
+class _patch_dict(object):
+    """
+    Patch a dictionary, or dictionary like object, and restore the dictionary
+    to its original state after the test.
+
+    `in_dict` can be a dictionary or a mapping like container. If it is a
+    mapping then it must at least support getting, setting and deleting items
+    plus iterating over keys.
+
+    `in_dict` can also be a string specifying the name of the dictionary, which
+    will then be fetched by importing it.
+
+    `values` can be a dictionary of values to set in the dictionary. `values`
+    can also be an iterable of `(key, value)` pairs.
+
+    If `clear` is True then the dictionary will be cleared before the new
+    values are set.
+
+    `patch.dict` can also be called with arbitrary keyword arguments to set
+    values in the dictionary::
+
+        with patch.dict('sys.modules', mymodule=Mock(), other_module=Mock()):
+            ...
+
+    `patch.dict` can be used as a context manager, decorator or class
+    decorator. When used as a class decorator `patch.dict` honours
+    `patch.TEST_PREFIX` for choosing which methods to wrap.
+    """
+
+    def __init__(self, in_dict, values=(), clear=False, **kwargs):
+        if isinstance(in_dict, basestring):
+            in_dict = _importer(in_dict)
+        self.in_dict = in_dict
+        # support any argument supported by dict(...) constructor
+        self.values = dict(values)
+        self.values.update(kwargs)
+        self.clear = clear
+        self._original = None
+
+
+    def __call__(self, f):
+        if isinstance(f, ClassTypes):
+            return self.decorate_class(f)
+        @wraps(f)
+        def _inner(*args, **kw):
+            self._patch_dict()
+            try:
+                return f(*args, **kw)
+            finally:
+                self._unpatch_dict()
+
+        return _inner
+
+
+    def decorate_class(self, klass):
+        for attr in dir(klass):
+            attr_value = getattr(klass, attr)
+            if (attr.startswith(patch.TEST_PREFIX) and
+                 hasattr(attr_value, "__call__")):
+                decorator = _patch_dict(self.in_dict, self.values, self.clear)
+                decorated = decorator(attr_value)
+                setattr(klass, attr, decorated)
+        return klass
+
+
+    def __enter__(self):
+        """Patch the dict."""
+        self._patch_dict()
+
+
+    def _patch_dict(self):
+        values = self.values
+        in_dict = self.in_dict
+        clear = self.clear
+
+        try:
+            original = in_dict.copy()
+        except AttributeError:
+            # dict like object with no copy method
+            # must support iteration over keys
+            original = {}
+            for key in in_dict:
+                original[key] = in_dict[key]
+        self._original = original
+
+        if clear:
+            _clear_dict(in_dict)
+
+        try:
+            in_dict.update(values)
+        except AttributeError:
+            # dict like object with no update method
+            for key in values:
+                in_dict[key] = values[key]
+
+
+    def _unpatch_dict(self):
+        in_dict = self.in_dict
+        original = self._original
+
+        _clear_dict(in_dict)
+
+        try:
+            in_dict.update(original)
+        except AttributeError:
+            for key in original:
+                in_dict[key] = original[key]
+
+
+    def __exit__(self, *args):
+        """Unpatch the dict."""
+        self._unpatch_dict()
+        return False
+
+    start = __enter__
+    stop = __exit__
+
+
+def _clear_dict(in_dict):
+    try:
+        in_dict.clear()
+    except AttributeError:
+        keys = list(in_dict)
+        for key in keys:
+            del in_dict[key]
+
+
+def _patch_stopall():
+    """Stop all active patches."""
+    for patch in list(_patch._active_patches):
+        patch.stop()
+
+
+patch.object = _patch_object
+patch.dict = _patch_dict
+patch.multiple = _patch_multiple
+patch.stopall = _patch_stopall
+patch.TEST_PREFIX = 'test'
+
+magic_methods = (
+    "lt le gt ge eq ne "
+    "getitem setitem delitem "
+    "len contains iter "
+    "hash str sizeof "
+    "enter exit "
+    "divmod neg pos abs invert "
+    "complex int float index "
+    "trunc floor ceil "
+)
+
+numerics = "add sub mul div floordiv mod lshift rshift and xor or pow "
+inplace = ' '.join('i%s' % n for n in numerics.split())
+right = ' '.join('r%s' % n for n in numerics.split())
+extra = ''
+if inPy3k:
+    extra = 'bool next '
+else:
+    extra = 'unicode long nonzero oct hex truediv rtruediv '
+
+# not including __prepare__, __instancecheck__, __subclasscheck__
+# (as they are metaclass methods)
+# __del__ is not supported at all as it causes problems if it exists
+
+_non_defaults = set('__%s__' % method for method in [
+    'cmp', 'getslice', 'setslice', 'coerce', 'subclasses',
+    'format', 'get', 'set', 'delete', 'reversed',
+    'missing', 'reduce', 'reduce_ex', 'getinitargs',
+    'getnewargs', 'getstate', 'setstate', 'getformat',
+    'setformat', 'repr', 'dir'
+])
+
+
+def _get_method(name, func):
+    "Turns a callable object (like a mock) into a real function"
+    def method(self, *args, **kw):
+        return func(self, *args, **kw)
+    method.__name__ = name
+    return method
+
+
+_magics = set(
+    '__%s__' % method for method in
+    ' '.join([magic_methods, numerics, inplace, right, extra]).split()
+)
+
+_all_magics = _magics | _non_defaults
+
+_unsupported_magics = set([
+    '__getattr__', '__setattr__',
+    '__init__', '__new__', '__prepare__'
+    '__instancecheck__', '__subclasscheck__',
+    '__del__'
+])
+
+_calculate_return_value = {
+    '__hash__': lambda self: object.__hash__(self),
+    '__str__': lambda self: object.__str__(self),
+    '__sizeof__': lambda self: object.__sizeof__(self),
+    '__unicode__': lambda self: unicode(object.__str__(self)),
+}
+
+_return_values = {
+    '__lt__': NotImplemented,
+    '__gt__': NotImplemented,
+    '__le__': NotImplemented,
+    '__ge__': NotImplemented,
+    '__int__': 1,
+    '__contains__': False,
+    '__len__': 0,
+    '__exit__': False,
+    '__complex__': 1j,
+    '__float__': 1.0,
+    '__bool__': True,
+    '__nonzero__': True,
+    '__oct__': '1',
+    '__hex__': '0x1',
+    '__long__': long(1),
+    '__index__': 1,
+}
+
+
+def _get_eq(self):
+    def __eq__(other):
+        ret_val = self.__eq__._mock_return_value
+        if ret_val is not DEFAULT:
+            return ret_val
+        return self is other
+    return __eq__
+
+def _get_ne(self):
+    def __ne__(other):
+        if self.__ne__._mock_return_value is not DEFAULT:
+            return DEFAULT
+        return self is not other
+    return __ne__
+
+def _get_iter(self):
+    def __iter__():
+        ret_val = self.__iter__._mock_return_value
+        if ret_val is DEFAULT:
+            return iter([])
+        # if ret_val was already an iterator, then calling iter on it should
+        # return the iterator unchanged
+        return iter(ret_val)
+    return __iter__
+
+_side_effect_methods = {
+    '__eq__': _get_eq,
+    '__ne__': _get_ne,
+    '__iter__': _get_iter,
+}
+
+
+
+def _set_return_value(mock, method, name):
+    fixed = _return_values.get(name, DEFAULT)
+    if fixed is not DEFAULT:
+        method.return_value = fixed
+        return
+
+    return_calulator = _calculate_return_value.get(name)
+    if return_calulator is not None:
+        try:
+            return_value = return_calulator(mock)
+        except AttributeError:
+            # XXXX why do we return AttributeError here?
+            #      set it as a side_effect instead?
+            return_value = AttributeError(name)
+        method.return_value = return_value
+        return
+
+    side_effector = _side_effect_methods.get(name)
+    if side_effector is not None:
+        method.side_effect = side_effector(mock)
+
+
+
+class MagicMixin(object):
+    def __init__(self, *args, **kw):
+        _super(MagicMixin, self).__init__(*args, **kw)
+        self._mock_set_magics()
+
+
+    def _mock_set_magics(self):
+        these_magics = _magics
+
+        if self._mock_methods is not None:
+            these_magics = _magics.intersection(self._mock_methods)
+
+            remove_magics = set()
+            remove_magics = _magics - these_magics
+
+            for entry in remove_magics:
+                if entry in type(self).__dict__:
+                    # remove unneeded magic methods
+                    delattr(self, entry)
+
+        # don't overwrite existing attributes if called a second time
+        these_magics = these_magics - set(type(self).__dict__)
+
+        _type = type(self)
+        for entry in these_magics:
+            setattr(_type, entry, MagicProxy(entry, self))
+
+
+
+class NonCallableMagicMock(MagicMixin, NonCallableMock):
+    """A version of `MagicMock` that isn't callable."""
+    def mock_add_spec(self, spec, spec_set=False):
+        """Add a spec to a mock. `spec` can either be an object or a
+        list of strings. Only attributes on the `spec` can be fetched as
+        attributes from the mock.
+
+        If `spec_set` is True then only attributes on the spec can be set."""
+        self._mock_add_spec(spec, spec_set)
+        self._mock_set_magics()
+
+
+
+class MagicMock(MagicMixin, Mock):
+    """
+    MagicMock is a subclass of Mock with default implementations
+    of most of the magic methods. You can use MagicMock without having to
+    configure the magic methods yourself.
+
+    If you use the `spec` or `spec_set` arguments then *only* magic
+    methods that exist in the spec will be created.
+
+    Attributes and the return value of a `MagicMock` will also be `MagicMocks`.
+    """
+    def mock_add_spec(self, spec, spec_set=False):
+        """Add a spec to a mock. `spec` can either be an object or a
+        list of strings. Only attributes on the `spec` can be fetched as
+        attributes from the mock.
+
+        If `spec_set` is True then only attributes on the spec can be set."""
+        self._mock_add_spec(spec, spec_set)
+        self._mock_set_magics()
+
+
+
+class MagicProxy(object):
+    def __init__(self, name, parent):
+        self.name = name
+        self.parent = parent
+
+    def __call__(self, *args, **kwargs):
+        m = self.create_mock()
+        return m(*args, **kwargs)
+
+    def create_mock(self):
+        entry = self.name
+        parent = self.parent
+        m = parent._get_child_mock(name=entry, _new_name=entry,
+                                   _new_parent=parent)
+        setattr(parent, entry, m)
+        _set_return_value(parent, m, entry)
+        return m
+
+    def __get__(self, obj, _type=None):
+        return self.create_mock()
+
+
+
+class _ANY(object):
+    "A helper object that compares equal to everything."
+
+    def __eq__(self, other):
+        return True
+
+    def __ne__(self, other):
+        return False
+
+    def __repr__(self):
+        return '<ANY>'
+
+ANY = _ANY()
+
+
+
+def _format_call_signature(name, args, kwargs):
+    message = '%s(%%s)' % name
+    formatted_args = ''
+    args_string = ', '.join([repr(arg) for arg in args])
+    kwargs_string = ', '.join([
+        '%s=%r' % (key, value) for key, value in kwargs.items()
+    ])
+    if args_string:
+        formatted_args = args_string
+    if kwargs_string:
+        if formatted_args:
+            formatted_args += ', '
+        formatted_args += kwargs_string
+
+    return message % formatted_args
+
+
+
+class _Call(tuple):
+    """
+    A tuple for holding the results of a call to a mock, either in the form
+    `(args, kwargs)` or `(name, args, kwargs)`.
+
+    If args or kwargs are empty then a call tuple will compare equal to
+    a tuple without those values. This makes comparisons less verbose::
+
+        _Call(('name', (), {})) == ('name',)
+        _Call(('name', (1,), {})) == ('name', (1,))
+        _Call(((), {'a': 'b'})) == ({'a': 'b'},)
+
+    The `_Call` object provides a useful shortcut for comparing with call::
+
+        _Call(((1, 2), {'a': 3})) == call(1, 2, a=3)
+        _Call(('foo', (1, 2), {'a': 3})) == call.foo(1, 2, a=3)
+
+    If the _Call has no name then it will match any name.
+    """
+    def __new__(cls, value=(), name=None, parent=None, two=False,
+                from_kall=True):
+        name = ''
+        args = ()
+        kwargs = {}
+        _len = len(value)
+        if _len == 3:
+            name, args, kwargs = value
+        elif _len == 2:
+            first, second = value
+            if isinstance(first, basestring):
+                name = first
+                if isinstance(second, tuple):
+                    args = second
+                else:
+                    kwargs = second
+            else:
+                args, kwargs = first, second
+        elif _len == 1:
+            value, = value
+            if isinstance(value, basestring):
+                name = value
+            elif isinstance(value, tuple):
+                args = value
+            else:
+                kwargs = value
+
+        if two:
+            return tuple.__new__(cls, (args, kwargs))
+
+        return tuple.__new__(cls, (name, args, kwargs))
+
+
+    def __init__(self, value=(), name=None, parent=None, two=False,
+                 from_kall=True):
+        self.name = name
+        self.parent = parent
+        self.from_kall = from_kall
+
+
+    def __eq__(self, other):
+        if other is ANY:
+            return True
+        try:
+            len_other = len(other)
+        except TypeError:
+            return False
+
+        self_name = ''
+        if len(self) == 2:
+            self_args, self_kwargs = self
+        else:
+            self_name, self_args, self_kwargs = self
+
+        other_name = ''
+        if len_other == 0:
+            other_args, other_kwargs = (), {}
+        elif len_other == 3:
+            other_name, other_args, other_kwargs = other
+        elif len_other == 1:
+            value, = other
+            if isinstance(value, tuple):
+                other_args = value
+                other_kwargs = {}
+            elif isinstance(value, basestring):
+                other_name = value
+                other_args, other_kwargs = (), {}
+            else:
+                other_args = ()
+                other_kwargs = value
+        else:
+            # len 2
+            # could be (name, args) or (name, kwargs) or (args, kwargs)
+            first, second = other
+            if isinstance(first, basestring):
+                other_name = first
+                if isinstance(second, tuple):
+                    other_args, other_kwargs = second, {}
+                else:
+                    other_args, other_kwargs = (), second
+            else:
+                other_args, other_kwargs = first, second
+
+        if self_name and other_name != self_name:
+            return False
+
+        # this order is important for ANY to work!
+        return (other_args, other_kwargs) == (self_args, self_kwargs)
+
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+
+    def __call__(self, *args, **kwargs):
+        if self.name is None:
+            return _Call(('', args, kwargs), name='()')
+
+        name = self.name + '()'
+        return _Call((self.name, args, kwargs), name=name, parent=self)
+
+
+    def __getattr__(self, attr):
+        if self.name is None:
+            return _Call(name=attr, from_kall=False)
+        name = '%s.%s' % (self.name, attr)
+        return _Call(name=name, parent=self, from_kall=False)
+
+
+    def __repr__(self):
+        if not self.from_kall:
+            name = self.name or 'call'
+            if name.startswith('()'):
+                name = 'call%s' % name
+            return name
+
+        if len(self) == 2:
+            name = 'call'
+            args, kwargs = self
+        else:
+            name, args, kwargs = self
+            if not name:
+                name = 'call'
+            elif not name.startswith('()'):
+                name = 'call.%s' % name
+            else:
+                name = 'call%s' % name
+        return _format_call_signature(name, args, kwargs)
+
+
+    def call_list(self):
+        """For a call object that represents multiple calls, `call_list`
+        returns a list of all the intermediate calls as well as the
+        final call."""
+        vals = []
+        thing = self
+        while thing is not None:
+            if thing.from_kall:
+                vals.append(thing)
+            thing = thing.parent
+        return _CallList(reversed(vals))
+
+
+call = _Call(from_kall=False)
+
+
+
+def create_autospec(spec, spec_set=False, instance=False, _parent=None,
+                    _name=None, **kwargs):
+    """Create a mock object using another object as a spec. Attributes on the
+    mock will use the corresponding attribute on the `spec` object as their
+    spec.
+
+    Functions or methods being mocked will have their arguments checked
+    to check that they are called with the correct signature.
+
+    If `spec_set` is True then attempting to set attributes that don't exist
+    on the spec object will raise an `AttributeError`.
+
+    If a class is used as a spec then the return value of the mock (the
+    instance of the class) will have the same spec. You can use a class as the
+    spec for an instance object by passing `instance=True`. The returned mock
+    will only be callable if instances of the mock are callable.
+
+    `create_autospec` also takes arbitrary keyword arguments that are passed to
+    the constructor of the created mock."""
+    if _is_list(spec):
+        # can't pass a list instance to the mock constructor as it will be
+        # interpreted as a list of strings
+        spec = type(spec)
+
+    is_type = isinstance(spec, ClassTypes)
+
+    _kwargs = {'spec': spec}
+    if spec_set:
+        _kwargs = {'spec_set': spec}
+    elif spec is None:
+        # None we mock with a normal mock without a spec
+        _kwargs = {}
+
+    _kwargs.update(kwargs)
+
+    Klass = MagicMock
+    if type(spec) in DescriptorTypes:
+        # descriptors don't have a spec
+        # because we don't know what type they return
+        _kwargs = {}
+    elif not _callable(spec):
+        Klass = NonCallableMagicMock
+    elif is_type and instance and not _instance_callable(spec):
+        Klass = NonCallableMagicMock
+
+    _new_name = _name
+    if _parent is None:
+        # for a top level object no _new_name should be set
+        _new_name = ''
+
+    mock = Klass(parent=_parent, _new_parent=_parent, _new_name=_new_name,
+                 name=_name, **_kwargs)
+
+    if isinstance(spec, FunctionTypes):
+        # should only happen at the top level because we don't
+        # recurse for functions
+        mock = _set_signature(mock, spec)
+    else:
+        _check_signature(spec, mock, is_type, instance)
+
+    if _parent is not None and not instance:
+        _parent._mock_children[_name] = mock
+
+    if is_type and not instance and 'return_value' not in kwargs:
+        mock.return_value = create_autospec(spec, spec_set, instance=True,
+                                            _name='()', _parent=mock)
+
+    for entry in dir(spec):
+        if _is_magic(entry):
+            # MagicMock already does the useful magic methods for us
+            continue
+
+        if isinstance(spec, FunctionTypes) and entry in FunctionAttributes:
+            # allow a mock to actually be a function
+            continue
+
+        # XXXX do we need a better way of getting attributes without
+        # triggering code execution (?) Probably not - we need the actual
+        # object to mock it so we would rather trigger a property than mock
+        # the property descriptor. Likewise we want to mock out dynamically
+        # provided attributes.
+        # XXXX what about attributes that raise exceptions other than
+        # AttributeError on being fetched?
+        # we could be resilient against it, or catch and propagate the
+        # exception when the attribute is fetched from the mock
+        try:
+            original = getattr(spec, entry)
+        except AttributeError:
+            continue
+
+        kwargs = {'spec': original}
+        if spec_set:
+            kwargs = {'spec_set': original}
+
+        if not isinstance(original, FunctionTypes):
+            new = _SpecState(original, spec_set, mock, entry, instance)
+            mock._mock_children[entry] = new
+        else:
+            parent = mock
+            if isinstance(spec, FunctionTypes):
+                parent = mock.mock
+
+            new = MagicMock(parent=parent, name=entry, _new_name=entry,
+                            _new_parent=parent, **kwargs)
+            mock._mock_children[entry] = new
+            skipfirst = _must_skip(spec, entry, is_type)
+            _check_signature(original, new, skipfirst=skipfirst)
+
+        # so functions created with _set_signature become instance attributes,
+        # *plus* their underlying mock exists in _mock_children of the parent
+        # mock. Adding to _mock_children may be unnecessary where we are also
+        # setting as an instance attribute?
+        if isinstance(new, FunctionTypes):
+            setattr(mock, entry, new)
+
+    return mock
+
+
+def _must_skip(spec, entry, is_type):
+    if not isinstance(spec, ClassTypes):
+        if entry in getattr(spec, '__dict__', {}):
+            # instance attribute - shouldn't skip
+            return False
+        spec = spec.__class__
+    if not hasattr(spec, '__mro__'):
+        # old style class: can't have descriptors anyway
+        return is_type
+
+    for klass in spec.__mro__:
+        result = klass.__dict__.get(entry, DEFAULT)
+        if result is DEFAULT:
+            continue
+        if isinstance(result, (staticmethod, classmethod)):
+            return False
+        return is_type
+
+    # shouldn't get here unless function is a dynamically provided attribute
+    # XXXX untested behaviour
+    return is_type
+
+
+def _get_class(obj):
+    try:
+        return obj.__class__
+    except AttributeError:
+        # in Python 2, _sre.SRE_Pattern objects have no __class__
+        return type(obj)
+
+
+class _SpecState(object):
+
+    def __init__(self, spec, spec_set=False, parent=None,
+                 name=None, ids=None, instance=False):
+        self.spec = spec
+        self.ids = ids
+        self.spec_set = spec_set
+        self.parent = parent
+        self.instance = instance
+        self.name = name
+
+
+FunctionTypes = (
+    # python function
+    type(create_autospec),
+    # instance method
+    type(ANY.__eq__),
+    # unbound method
+    type(_ANY.__eq__),
+)
+
+FunctionAttributes = set([
+    'func_closure',
+    'func_code',
+    'func_defaults',
+    'func_dict',
+    'func_doc',
+    'func_globals',
+    'func_name',
+])
+
+
+file_spec = None
+
+
+def mock_open(mock=None, read_data=''):
+    """
+    A helper function to create a mock to replace the use of `open`. It works
+    for `open` called directly or used as a context manager.
+
+    The `mock` argument is the mock object to configure. If `None` (the
+    default) then a `MagicMock` will be created for you, with the API limited
+    to methods or attributes available on standard file handles.
+
+    `read_data` is a string for the `read` method of the file handle to return.
+    This is an empty string by default.
+    """
+    global file_spec
+    if file_spec is None:
+        # set on first use
+        if inPy3k:
+            import _io
+            file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
+        else:
+            file_spec = file
+
+    if mock is None:
+        mock = MagicMock(name='open', spec=open)
+
+    handle = MagicMock(spec=file_spec)
+    handle.write.return_value = None
+    handle.__enter__.return_value = handle
+    handle.read.return_value = read_data
+
+    mock.return_value = handle
+    return mock
+
+
+class PropertyMock(Mock):
+    """
+    A mock intended to be used as a property, or other descriptor, on a class.
+    `PropertyMock` provides `__get__` and `__set__` methods so you can specify
+    a return value when it is fetched.
+
+    Fetching a `PropertyMock` instance from an object calls the mock, with
+    no args. Setting it calls the mock with the value being set.
+    """
+    def _get_child_mock(self, **kwargs):
+        return MagicMock(**kwargs)
+
+    def __get__(self, obj, obj_type):
+        return self()
+    def __set__(self, obj, val):
+        self(val)
diff --git a/tools/android/checkstyle/chromium-style-5.0.xml b/tools/android/checkstyle/chromium-style-5.0.xml
index 17b44b4..351b5b3 100644
--- a/tools/android/checkstyle/chromium-style-5.0.xml
+++ b/tools/android/checkstyle/chromium-style-5.0.xml
@@ -164,6 +164,17 @@
       <property name="throwsIndent" value="8"/>
       <property name="lineWrappingIndentation" value="8"/>
     </module>
+    <!-- TODO(aurimas): make OperatorWrap into an error once all the warnings are fixed. -->
+    <module name="OperatorWrap">
+      <property name="severity" value="warning"/>
+      <property name="option" value="NL" />
+      <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR " />
+    </module>
+    <module name="OperatorWrap">
+     <property name="severity" value="warning"/>
+     <property name="option" value="eol"/>
+     <property name="tokens" value="ASSIGN"/>
+    </module>
   </module>
   <module name="FileTabCharacter">
     <property name="severity" value="error"/>
diff --git a/tools/android/forwarder2/device_forwarder_main.cc b/tools/android/forwarder2/device_forwarder_main.cc
index cad46f4..aeb2853 100644
--- a/tools/android/forwarder2/device_forwarder_main.cc
+++ b/tools/android/forwarder2/device_forwarder_main.cc
@@ -68,7 +68,7 @@
   }
 
   // Daemon::ServerDelegate:
-  virtual void Init() OVERRIDE {
+  virtual void Init() override {
     DCHECK(!g_notifier);
     g_notifier = new forwarder2::PipeNotifier();
     signal(SIGTERM, KillHandler);
@@ -77,7 +77,7 @@
     controller_thread_->Start();
   }
 
-  virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE {
+  virtual void OnClientConnected(scoped_ptr<Socket> client_socket) override {
     if (initialized_) {
       client_socket->WriteString("OK");
       return;
@@ -119,7 +119,7 @@
   bool has_failed() const { return has_failed_; }
 
   // Daemon::ClientDelegate:
-  virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE {
+  virtual void OnDaemonReady(Socket* daemon_socket) override {
     char buf[kBufSize];
     const int bytes_read = daemon_socket->Read(
         buf, sizeof(buf) - 1 /* leave space for null terminator */);
diff --git a/tools/android/forwarder2/host_forwarder_main.cc b/tools/android/forwarder2/host_forwarder_main.cc
index 59571b6..514ad93 100644
--- a/tools/android/forwarder2/host_forwarder_main.cc
+++ b/tools/android/forwarder2/host_forwarder_main.cc
@@ -311,7 +311,7 @@
   }
 
   // Daemon::ServerDelegate:
-  virtual void Init() OVERRIDE {
+  virtual void Init() override {
     LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")";
     DCHECK(!g_notifier);
     g_notifier = new PipeNotifier();
@@ -319,7 +319,7 @@
     signal(SIGINT, KillHandler);
   }
 
-  virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE {
+  virtual void OnClientConnected(scoped_ptr<Socket> client_socket) override {
     char buf[kBufSize];
     const int bytes_read = client_socket->Read(buf, sizeof(buf));
     if (bytes_read <= 0) {
@@ -362,7 +362,7 @@
   bool has_failed() const { return has_failed_; }
 
   // Daemon::ClientDelegate:
-  virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE {
+  virtual void OnDaemonReady(Socket* daemon_socket) override {
     // Send the forward command to the daemon.
     CHECK_EQ(command_pickle_.size(),
              daemon_socket->WriteNumBytes(command_pickle_.data(),
diff --git a/tools/android/heap_profiler/heap_profiler_unittest.cc b/tools/android/heap_profiler/heap_profiler_unittest.cc
index 65c2700..d69af5f 100644
--- a/tools/android/heap_profiler/heap_profiler_unittest.cc
+++ b/tools/android/heap_profiler/heap_profiler_unittest.cc
@@ -14,9 +14,9 @@
 
 class HeapProfilerTest : public testing::Test {
  public:
-  virtual void SetUp() OVERRIDE { heap_profiler_init(&stats_); }
+  virtual void SetUp() override { heap_profiler_init(&stats_); }
 
-  virtual void TearDown() OVERRIDE {
+  virtual void TearDown() override {
     CheckAllocVsStacktaceConsistency();
     heap_profiler_cleanup();
   }
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py
index d5f3d18..9b0b52f 100755
--- a/tools/valgrind/chrome_tests.py
+++ b/tools/valgrind/chrome_tests.py
@@ -475,6 +475,9 @@
       return 0;
     return self.SimpleTest("chrome", "unit_tests")
 
+  def TestUIBaseUnit(self):
+    return self.SimpleTest("chrome", "ui_base_unittests")
+
   def TestUIUnit(self):
     return self.SimpleTest("chrome", "ui_unittests")
 
@@ -723,6 +726,7 @@
     "sync": TestSync,            "sync_unit_tests": TestSync,
     "sync_integration_tests": TestSyncIntegration,
     "sync_integration": TestSyncIntegration,
+    "ui_base_unit": TestUIBaseUnit,       "ui_base_unittests": TestUIBaseUnit,
     "ui_unit": TestUIUnit,       "ui_unittests": TestUIUnit,
     "unit": TestUnit,            "unit_tests": TestUnit,
     "url": TestURL,              "url_unittests": TestURL,
diff --git a/url/url_canon_icu.h b/url/url_canon_icu.h
index 18b1f09..80d7953 100644
--- a/url/url_canon_icu.h
+++ b/url/url_canon_icu.h
@@ -24,11 +24,11 @@
   // be managed by the creator such that it is alive as long as this is.
   ICUCharsetConverter(UConverter* converter);
 
-  virtual ~ICUCharsetConverter();
+  ~ICUCharsetConverter() override;
 
-  virtual void ConvertFromUTF16(const base::char16* input,
-                                int input_len,
-                                CanonOutput* output) override;
+  void ConvertFromUTF16(const base::char16* input,
+                        int input_len,
+                        CanonOutput* output) override;
 
  private:
   // The ICU converter, not owned by this class.
diff --git a/url/url_canon_stdstring.h b/url/url_canon_stdstring.h
index 62622b4..c3d8ba1 100644
--- a/url/url_canon_stdstring.h
+++ b/url/url_canon_stdstring.h
@@ -36,12 +36,12 @@
 class URL_EXPORT StdStringCanonOutput : public CanonOutput {
  public:
   StdStringCanonOutput(std::string* str);
-  virtual ~StdStringCanonOutput();
+  ~StdStringCanonOutput() override;
 
   // Must be called after writing has completed but before the string is used.
   void Complete();
 
-  virtual void Resize(int sz) override;
+  void Resize(int sz) override;
 
  protected:
   std::string* str_;