Update from https://crrev.com/305340

Added a few #includes of base/compiler_specific.h for upstream cleanup.

Changed callers for cc::BeginFrameArgs and cc::RendererSettings API
changes.

Review URL: https://codereview.chromium.org/754433003
diff --git a/.clang-format b/.clang-format
index a7d210d..53f0da3 100644
--- a/.clang-format
+++ b/.clang-format
@@ -16,5 +16,7 @@
 AllowShortBlocksOnASingleLine: false
 AllowShortFunctionsOnASingleLine: None
 AllowShortIfStatementsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
 BreakBeforeBinaryOperators: NonAssignment
 Cpp11BracedListStyle: false  # but see http://llvm.org/PR21457
diff --git a/base/allocator/allocator.gyp b/base/allocator/allocator.gyp
index 323d79e..de3b273 100644
--- a/base/allocator/allocator.gyp
+++ b/base/allocator/allocator.gyp
@@ -8,7 +8,7 @@
       # This code gets run a lot and debugged rarely, so it should be fast
       # by default. See http://crbug.com/388949.
       'debug_optimize': '2',
-      'win_debug_Optimization': '2',
+      'win_debug_Optimization': '0',
       # Run time checks are incompatible with any level of optimizations.
       'win_debug_RuntimeChecks': '0',
     },
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
index 2af146b..8b2438c 100644
--- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -7,7 +7,6 @@
 import android.animation.ValueAnimator;
 import android.annotation.TargetApi;
 import android.app.ActivityOptions;
-import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -27,9 +26,6 @@
  * Utility class to use new APIs that were added after ICS (API level 14).
  */
 public class ApiCompatibilityUtils {
-
-    private static final String TAG = "ApiCompatibilityUtils";
-
     private ApiCompatibilityUtils() {
     }
 
@@ -369,18 +365,6 @@
     }
 
     /**
-     * @see android.app.Notification.Builder#setLocalOnly(boolean)
-     */
-    @SuppressWarnings("deprecation")
-    public static Notification build(Notification.Builder builder) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            return builder.build();
-        } else {
-            return builder.getNotification();
-        }
-    }
-
-    /**
      * @see android.provider.Settings.Global#DEVICE_PROVISIONED
      */
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
diff --git a/base/android/java/src/org/chromium/base/CommandLine.java b/base/android/java/src/org/chromium/base/CommandLine.java
index b353ec4..406f36b 100644
--- a/base/android/java/src/org/chromium/base/CommandLine.java
+++ b/base/android/java/src/org/chromium/base/CommandLine.java
@@ -86,7 +86,7 @@
     }
 
     private static final AtomicReference<CommandLine> sCommandLine =
-        new AtomicReference<CommandLine>();
+            new AtomicReference<CommandLine>();
 
     /**
      * @returns true if the command line has already been initialized.
@@ -149,8 +149,8 @@
         char currentQuote = noQuote;
         for (char c : buffer) {
             // Detect start or end of quote block.
-            if ((currentQuote == noQuote && (c == singleQuote || c == doubleQuote)) ||
-                c == currentQuote) {
+            if ((currentQuote == noQuote && (c == singleQuote || c == doubleQuote))
+                    || c == currentQuote) {
                 if (arg != null && arg.length() > 0 && arg.charAt(arg.length() - 1) == '\\') {
                     // Last char was a backslash; pop it, and treat c as a literal.
                     arg.setCharAt(arg.length() - 1, c);
diff --git a/base/android/java/src/org/chromium/base/LocaleUtils.java b/base/android/java/src/org/chromium/base/LocaleUtils.java
index 4f97d3a..82b2c8f 100644
--- a/base/android/java/src/org/chromium/base/LocaleUtils.java
+++ b/base/android/java/src/org/chromium/base/LocaleUtils.java
@@ -47,9 +47,9 @@
     @CalledByNative
     private static String getDefaultCountryCode() {
         CommandLine commandLine = CommandLine.getInstance();
-        return commandLine.hasSwitch(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL) ?
-                commandLine.getSwitchValue(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL) :
-                Locale.getDefault().getCountry();
+        return commandLine.hasSwitch(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL)
+                ? commandLine.getSwitchValue(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL)
+                : Locale.getDefault().getCountry();
     }
 
 }
diff --git a/base/android/java/src/org/chromium/base/MemoryPressureListener.java b/base/android/java/src/org/chromium/base/MemoryPressureListener.java
index 28d9651..e7c2030 100644
--- a/base/android/java/src/org/chromium/base/MemoryPressureListener.java
+++ b/base/android/java/src/org/chromium/base/MemoryPressureListener.java
@@ -86,8 +86,8 @@
     public static void maybeNotifyMemoryPresure(int level) {
         if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
             nativeOnMemoryPressure(MemoryPressureLevel.CRITICAL);
-        } else if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND ||
-                level == ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) {
+        } else if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
+                || level == ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) {
             // Don't notifiy on TRIM_MEMORY_UI_HIDDEN, since this class only
             // dispatches actionable memory pressure signals to native.
             nativeOnMemoryPressure(MemoryPressureLevel.MODERATE);
diff --git a/base/android/java/src/org/chromium/base/ObserverList.java b/base/android/java/src/org/chromium/base/ObserverList.java
index c2bb902..e812b0d 100644
--- a/base/android/java/src/org/chromium/base/ObserverList.java
+++ b/base/android/java/src/org/chromium/base/ObserverList.java
@@ -204,8 +204,8 @@
         @Override
         public boolean hasNext() {
             int lookupIndex = mIndex;
-            while (lookupIndex < mListEndMarker &&
-                    ObserverList.this.getObserverAt(lookupIndex) == null) {
+            while (lookupIndex < mListEndMarker
+                    && ObserverList.this.getObserverAt(lookupIndex) == null) {
                 lookupIndex++;
             }
             if (lookupIndex < mListEndMarker) return true;
diff --git a/base/android/java/src/org/chromium/base/PathUtils.java b/base/android/java/src/org/chromium/base/PathUtils.java
index b2c860f..d70c0cc 100644
--- a/base/android/java/src/org/chromium/base/PathUtils.java
+++ b/base/android/java/src/org/chromium/base/PathUtils.java
@@ -75,8 +75,8 @@
     @CalledByNative
     private static String getNativeLibraryDirectory(Context appContext) {
         ApplicationInfo ai = appContext.getApplicationInfo();
-        if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ||
-            (ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+        if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0
+                || (ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
             return ai.nativeLibraryDir;
         }
 
diff --git a/base/android/java/src/org/chromium/base/PowerMonitor.java b/base/android/java/src/org/chromium/base/PowerMonitor.java
index 316d6cc..3d0ed48 100644
--- a/base/android/java/src/org/chromium/base/PowerMonitor.java
+++ b/base/android/java/src/org/chromium/base/PowerMonitor.java
@@ -31,11 +31,11 @@
     // would be too aggressive. An Android activity can be in the "paused" state quite often. This
     // can happen when a dialog window shows up for instance.
     private static final Runnable sSuspendTask = new Runnable() {
-            @Override
-            public void run() {
-                nativeOnMainActivitySuspended();
-            }
-        };
+        @Override
+        public void run() {
+            nativeOnMainActivitySuspended();
+        }
+    };
 
     public static void createForTests(Context context) {
         // Applications will create this once the JNI side has been fully wired up both sides. For
@@ -71,8 +71,8 @@
         }
         int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
         // If we're not plugged, assume we're running on battery power.
-        sInstance.mIsBatteryPower = chargePlug != BatteryManager.BATTERY_PLUGGED_USB &&
-                                    chargePlug != BatteryManager.BATTERY_PLUGGED_AC;
+        sInstance.mIsBatteryPower = chargePlug != BatteryManager.BATTERY_PLUGGED_USB
+                && chargePlug != BatteryManager.BATTERY_PLUGGED_AC;
         nativeOnBatteryChargingChanged();
     }
 
diff --git a/base/android/java/src/org/chromium/base/ThreadUtils.java b/base/android/java/src/org/chromium/base/ThreadUtils.java
index 8813a6c..2a8deeb 100644
--- a/base/android/java/src/org/chromium/base/ThreadUtils.java
+++ b/base/android/java/src/org/chromium/base/ThreadUtils.java
@@ -32,9 +32,9 @@
     public static void setUiThread(Looper looper) {
         synchronized (sLock) {
             if (sUiThreadHandler != null && sUiThreadHandler.getLooper() != looper) {
-                throw new RuntimeException("UI thread looper is already set to " +
-                        sUiThreadHandler.getLooper() + " (Main thread looper is " +
-                        Looper.getMainLooper() + "), cannot set to new looper " + looper);
+                throw new RuntimeException("UI thread looper is already set to "
+                        + sUiThreadHandler.getLooper() + " (Main thread looper is "
+                        + Looper.getMainLooper() + "), cannot set to new looper " + looper);
             } else {
                 sUiThreadHandler = new Handler(looper);
             }
diff --git a/base/android/java/src/org/chromium/base/TraceEvent.java b/base/android/java/src/org/chromium/base/TraceEvent.java
index b67d32d..1c7e534 100644
--- a/base/android/java/src/org/chromium/base/TraceEvent.java
+++ b/base/android/java/src/org/chromium/base/TraceEvent.java
@@ -158,8 +158,8 @@
     // Holder for monitor avoids unnecessary construction on non-debug runs
     private static final class LooperMonitorHolder {
         private static final BasicLooperMonitor sInstance =
-                CommandLine.getInstance().hasSwitch(BaseSwitches.ENABLE_IDLE_TRACING) ?
-                        new IdleTracingLooperMonitor() : new BasicLooperMonitor();
+                CommandLine.getInstance().hasSwitch(BaseSwitches.ENABLE_IDLE_TRACING)
+                ? new IdleTracingLooperMonitor() : new BasicLooperMonitor();
     }
 
 
diff --git a/base/android/javatests/src/org/chromium/base/CommandLineTest.java b/base/android/javatests/src/org/chromium/base/CommandLineTest.java
index 4300467..2b1a967 100644
--- a/base/android/javatests/src/org/chromium/base/CommandLineTest.java
+++ b/base/android/javatests/src/org/chromium/base/CommandLineTest.java
@@ -113,8 +113,8 @@
         toParse = " \t\n";
         checkTokenizer(expected, toParse);
 
-        toParse = " \"a'b\" 'c\"d' \"e\\\"f\" 'g\\'h' \"i\\'j\" 'k\\\"l'" +
-                  " m\"n\\'o\"p q'r\\\"s't";
+        toParse = " \"a'b\" 'c\"d' \"e\\\"f\" 'g\\'h' \"i\\'j\" 'k\\\"l'"
+                + " m\"n\\'o\"p q'r\\\"s't";
         expected = new String[] { "a'b",
                                   "c\"d",
                                   "e\"f",
diff --git a/base/bind_internal.h b/base/bind_internal.h
index ae17ebf..2142797 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -51,18 +51,15 @@
 // Types:
 //  RunnableAdapter<> -- Wraps the various "function" pointer types into an
 //                       object that adheres to the Runnable interface.
-//                       There are |3*ARITY| RunnableAdapter types.
 //  FunctionTraits<> -- Type traits that unwrap a function signature into a
 //                      a set of easier to use typedefs.  Used mainly for
 //                      compile time asserts.
 //                      There are |ARITY| FunctionTraits types.
 //  ForceVoidReturn<> -- Helper class for translating function signatures to
 //                       equivalent forms with a "void" return type.
-//                    There are |ARITY| ForceVoidReturn types.
 //  FunctorTraits<> -- Type traits used determine the correct RunType and
 //                     RunnableType for a Functor.  This is where function
 //                     signature adapters are applied.
-//                    There are |ARITY| ForceVoidReturn types.
 //  MakeRunnable<> -- Takes a Functor and returns an object in the Runnable
 //                    type class that represents the underlying Functor.
 //                    There are |O(1)| MakeRunnable types.
@@ -71,7 +68,6 @@
 //                    and for ignoring return values.  This is separate from
 //                    Invoker to avoid creating multiple version of Invoker<>
 //                    which grows at O(n^2) with the arity.
-//                    There are |k*ARITY| InvokeHelper types.
 //  Invoker<> -- Unwraps the curried parameters and executes the Runnable.
 //               There are |(ARITY^2 + ARITY)/2| Invoketypes.
 //  BindState<> -- Stores the curried parameters, and is the main entry point
@@ -101,550 +97,64 @@
 template <typename Functor>
 class RunnableAdapter;
 
-// Function: Arity 0.
-template <typename R>
-class RunnableAdapter<R(*)()> {
+// Function.
+template <typename R, typename... Args>
+class RunnableAdapter<R(*)(Args...)> {
  public:
-  typedef R (RunType)();
+  typedef R (RunType)(Args...);
 
-  explicit RunnableAdapter(R(*function)())
+  explicit RunnableAdapter(R(*function)(Args...))
       : function_(function) {
   }
 
-  R Run() {
-    return function_();
+  R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
+    return function_(CallbackForward(args)...);
   }
 
  private:
-  R (*function_)();
+  R (*function_)(Args...);
 };
 
-// Method: Arity 0.
-template <typename R, typename T>
-class RunnableAdapter<R(T::*)()> {
+// Method.
+template <typename R, typename T, typename... Args>
+class RunnableAdapter<R(T::*)(Args...)> {
  public:
-  typedef R (RunType)(T*);
+  typedef R (RunType)(T*, Args...);
   typedef true_type IsMethod;
 
-  explicit RunnableAdapter(R(T::*method)())
+  explicit RunnableAdapter(R(T::*method)(Args...))
       : method_(method) {
   }
 
-  R Run(T* object) {
-    return (object->*method_)();
+  R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) {
+    return (object->*method_)(CallbackForward(args)...);
   }
 
  private:
-  R (T::*method_)();
+  R (T::*method_)(Args...);
 };
 
-// Const Method: Arity 0.
-template <typename R, typename T>
-class RunnableAdapter<R(T::*)() const> {
+// Const Method.
+template <typename R, typename T, typename... Args>
+class RunnableAdapter<R(T::*)(Args...) const> {
  public:
-  typedef R (RunType)(const T*);
+  typedef R (RunType)(const T*, Args...);
   typedef true_type IsMethod;
 
-  explicit RunnableAdapter(R(T::*method)() const)
+  explicit RunnableAdapter(R(T::*method)(Args...) const)
       : method_(method) {
   }
 
-  R Run(const T* object) {
-    return (object->*method_)();
+  R Run(const T* object,
+        typename CallbackParamTraits<Args>::ForwardType... args) {
+    return (object->*method_)(CallbackForward(args)...);
   }
 
  private:
-  R (T::*method_)() const;
+  R (T::*method_)(Args...) const;
 };
 
-// Function: Arity 1.
-template <typename R, typename A1>
-class RunnableAdapter<R(*)(A1)> {
- public:
-  typedef R (RunType)(A1);
-
-  explicit RunnableAdapter(R(*function)(A1))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1) {
-    return function_(CallbackForward(a1));
-  }
-
- private:
-  R (*function_)(A1);
-};
-
-// Method: Arity 1.
-template <typename R, typename T, typename A1>
-class RunnableAdapter<R(T::*)(A1)> {
- public:
-  typedef R (RunType)(T*, A1);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1))
-      : method_(method) {
-  }
-
-  R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1) {
-    return (object->*method_)(CallbackForward(a1));
-  }
-
- private:
-  R (T::*method_)(A1);
-};
-
-// Const Method: Arity 1.
-template <typename R, typename T, typename A1>
-class RunnableAdapter<R(T::*)(A1) const> {
- public:
-  typedef R (RunType)(const T*, A1);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1) const)
-      : method_(method) {
-  }
-
-  R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1) {
-    return (object->*method_)(CallbackForward(a1));
-  }
-
- private:
-  R (T::*method_)(A1) const;
-};
-
-// Function: Arity 2.
-template <typename R, typename A1, typename A2>
-class RunnableAdapter<R(*)(A1, A2)> {
- public:
-  typedef R (RunType)(A1, A2);
-
-  explicit RunnableAdapter(R(*function)(A1, A2))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2) {
-    return function_(CallbackForward(a1), CallbackForward(a2));
-  }
-
- private:
-  R (*function_)(A1, A2);
-};
-
-// Method: Arity 2.
-template <typename R, typename T, typename A1, typename A2>
-class RunnableAdapter<R(T::*)(A1, A2)> {
- public:
-  typedef R (RunType)(T*, A1, A2);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2))
-      : method_(method) {
-  }
-
-  R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2));
-  }
-
- private:
-  R (T::*method_)(A1, A2);
-};
-
-// Const Method: Arity 2.
-template <typename R, typename T, typename A1, typename A2>
-class RunnableAdapter<R(T::*)(A1, A2) const> {
- public:
-  typedef R (RunType)(const T*, A1, A2);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2) const)
-      : method_(method) {
-  }
-
-  R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2));
-  }
-
- private:
-  R (T::*method_)(A1, A2) const;
-};
-
-// Function: Arity 3.
-template <typename R, typename A1, typename A2, typename A3>
-class RunnableAdapter<R(*)(A1, A2, A3)> {
- public:
-  typedef R (RunType)(A1, A2, A3);
-
-  explicit RunnableAdapter(R(*function)(A1, A2, A3))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3));
-  }
-
- private:
-  R (*function_)(A1, A2, A3);
-};
-
-// Method: Arity 3.
-template <typename R, typename T, typename A1, typename A2, typename A3>
-class RunnableAdapter<R(T::*)(A1, A2, A3)> {
- public:
-  typedef R (RunType)(T*, A1, A2, A3);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3))
-      : method_(method) {
-  }
-
-  R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3);
-};
-
-// Const Method: Arity 3.
-template <typename R, typename T, typename A1, typename A2, typename A3>
-class RunnableAdapter<R(T::*)(A1, A2, A3) const> {
- public:
-  typedef R (RunType)(const T*, A1, A2, A3);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3) const)
-      : method_(method) {
-  }
-
-  R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3) const;
-};
-
-// Function: Arity 4.
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class RunnableAdapter<R(*)(A1, A2, A3, A4)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4);
-
-  explicit RunnableAdapter(R(*function)(A1, A2, A3, A4))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4));
-  }
-
- private:
-  R (*function_)(A1, A2, A3, A4);
-};
-
-// Method: Arity 4.
-template <typename R, typename T, typename A1, typename A2, typename A3,
-    typename A4>
-class RunnableAdapter<R(T::*)(A1, A2, A3, A4)> {
- public:
-  typedef R (RunType)(T*, A1, A2, A3, A4);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4))
-      : method_(method) {
-  }
-
-  R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4);
-};
-
-// Const Method: Arity 4.
-template <typename R, typename T, typename A1, typename A2, typename A3,
-    typename A4>
-class RunnableAdapter<R(T::*)(A1, A2, A3, A4) const> {
- public:
-  typedef R (RunType)(const T*, A1, A2, A3, A4);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4) const)
-      : method_(method) {
-  }
-
-  R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4) const;
-};
-
-// Function: Arity 5.
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5>
-class RunnableAdapter<R(*)(A1, A2, A3, A4, A5)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4, A5);
-
-  explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5));
-  }
-
- private:
-  R (*function_)(A1, A2, A3, A4, A5);
-};
-
-// Method: Arity 5.
-template <typename R, typename T, typename A1, typename A2, typename A3,
-    typename A4, typename A5>
-class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5)> {
- public:
-  typedef R (RunType)(T*, A1, A2, A3, A4, A5);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5))
-      : method_(method) {
-  }
-
-  R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5);
-};
-
-// Const Method: Arity 5.
-template <typename R, typename T, typename A1, typename A2, typename A3,
-    typename A4, typename A5>
-class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5) const> {
- public:
-  typedef R (RunType)(const T*, A1, A2, A3, A4, A5);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5) const)
-      : method_(method) {
-  }
-
-  R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5) const;
-};
-
-// Function: Arity 6.
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6>
-class RunnableAdapter<R(*)(A1, A2, A3, A4, A5, A6)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4, A5, A6);
-
-  explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5, A6))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
-        CallbackForward(a6));
-  }
-
- private:
-  R (*function_)(A1, A2, A3, A4, A5, A6);
-};
-
-// Method: Arity 6.
-template <typename R, typename T, typename A1, typename A2, typename A3,
-    typename A4, typename A5, typename A6>
-class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6)> {
- public:
-  typedef R (RunType)(T*, A1, A2, A3, A4, A5, A6);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6))
-      : method_(method) {
-  }
-
-  R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
-        CallbackForward(a6));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5, A6);
-};
-
-// Const Method: Arity 6.
-template <typename R, typename T, typename A1, typename A2, typename A3,
-    typename A4, typename A5, typename A6>
-class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6) const> {
- public:
-  typedef R (RunType)(const T*, A1, A2, A3, A4, A5, A6);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6) const)
-      : method_(method) {
-  }
-
-  R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
-        CallbackForward(a6));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5, A6) const;
-};
-
-// Function: Arity 7.
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6, typename A7>
-class RunnableAdapter<R(*)(A1, A2, A3, A4, A5, A6, A7)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7);
-
-  explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5, A6, A7))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6,
-      typename CallbackParamTraits<A7>::ForwardType a7) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
-        CallbackForward(a6), CallbackForward(a7));
-  }
-
- private:
-  R (*function_)(A1, A2, A3, A4, A5, A6, A7);
-};
-
-// Method: Arity 7.
-template <typename R, typename T, typename A1, typename A2, typename A3,
-    typename A4, typename A5, typename A6, typename A7>
-class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6, A7)> {
- public:
-  typedef R (RunType)(T*, A1, A2, A3, A4, A5, A6, A7);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6, A7))
-      : method_(method) {
-  }
-
-  R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6,
-      typename CallbackParamTraits<A7>::ForwardType a7) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
-        CallbackForward(a6), CallbackForward(a7));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5, A6, A7);
-};
-
-// Const Method: Arity 7.
-template <typename R, typename T, typename A1, typename A2, typename A3,
-    typename A4, typename A5, typename A6, typename A7>
-class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6, A7) const> {
- public:
-  typedef R (RunType)(const T*, A1, A2, A3, A4, A5, A6, A7);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6, A7) const)
-      : method_(method) {
-  }
-
-  R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6,
-      typename CallbackParamTraits<A7>::ForwardType a7) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
-        CallbackForward(a6), CallbackForward(a7));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5, A6, A7) const;
-};
-
-
+// TODO(tzik): Remove FunctionTraits after we finish removing bind.pump.
 // FunctionTraits<>
 //
 // Breaks a function signature apart into typedefs for easier introspection.
@@ -729,47 +239,9 @@
 template <typename Sig>
 struct ForceVoidReturn;
 
-template <typename R>
-struct ForceVoidReturn<R()> {
-  typedef void(RunType)();
-};
-
-template <typename R, typename A1>
-struct ForceVoidReturn<R(A1)> {
-  typedef void(RunType)(A1);
-};
-
-template <typename R, typename A1, typename A2>
-struct ForceVoidReturn<R(A1, A2)> {
-  typedef void(RunType)(A1, A2);
-};
-
-template <typename R, typename A1, typename A2, typename A3>
-struct ForceVoidReturn<R(A1, A2, A3)> {
-  typedef void(RunType)(A1, A2, A3);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-struct ForceVoidReturn<R(A1, A2, A3, A4)> {
-  typedef void(RunType)(A1, A2, A3, A4);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5>
-struct ForceVoidReturn<R(A1, A2, A3, A4, A5)> {
-  typedef void(RunType)(A1, A2, A3, A4, A5);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6>
-struct ForceVoidReturn<R(A1, A2, A3, A4, A5, A6)> {
-  typedef void(RunType)(A1, A2, A3, A4, A5, A6);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6, typename A7>
-struct ForceVoidReturn<R(A1, A2, A3, A4, A5, A6, A7)> {
-  typedef void(RunType)(A1, A2, A3, A4, A5, A6, A7);
+template <typename R, typename... Args>
+struct ForceVoidReturn<R(Args...)> {
+  typedef void(RunType)(Args...);
 };
 
 
@@ -840,246 +312,28 @@
           typename ArgsType>
 struct InvokeHelper;
 
-template <typename ReturnType, typename Runnable>
+template <typename ReturnType, typename Runnable, typename... Args>
 struct InvokeHelper<false, ReturnType, Runnable,
-    void()>  {
-  static ReturnType MakeItSo(Runnable runnable) {
-    return runnable.Run();
+    void(Args...)>  {
+  static ReturnType MakeItSo(Runnable runnable, Args... args) {
+    return runnable.Run(CallbackForward(args)...);
   }
 };
 
-template <typename Runnable>
-struct InvokeHelper<false, void, Runnable,
-    void()>  {
-  static void MakeItSo(Runnable runnable) {
-    runnable.Run();
+template <typename Runnable, typename... Args>
+struct InvokeHelper<false, void, Runnable, void(Args...)>  {
+  static void MakeItSo(Runnable runnable, Args... args) {
+    runnable.Run(CallbackForward(args)...);
   }
 };
 
-template <typename ReturnType, typename Runnable,typename A1>
-struct InvokeHelper<false, ReturnType, Runnable,
-    void(A1)>  {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1) {
-    return runnable.Run(CallbackForward(a1));
-  }
-};
-
-template <typename Runnable,typename A1>
-struct InvokeHelper<false, void, Runnable,
-    void(A1)>  {
-  static void MakeItSo(Runnable runnable, A1 a1) {
-    runnable.Run(CallbackForward(a1));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr>
-struct InvokeHelper<true, void, Runnable,
-    void(BoundWeakPtr)>  {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr) {
+template <typename Runnable, typename BoundWeakPtr, typename... Args>
+struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, Args...)>  {
+  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
     if (!weak_ptr.get()) {
       return;
     }
-    runnable.Run(weak_ptr.get());
-  }
-};
-
-template <typename ReturnType, typename Runnable,typename A1, typename A2>
-struct InvokeHelper<false, ReturnType, Runnable,
-    void(A1, A2)>  {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2));
-  }
-};
-
-template <typename Runnable,typename A1, typename A2>
-struct InvokeHelper<false, void, Runnable,
-    void(A1, A2)>  {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename A2>
-struct InvokeHelper<true, void, Runnable,
-    void(BoundWeakPtr, A2)>  {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2));
-  }
-};
-
-template <typename ReturnType, typename Runnable,typename A1, typename A2,
-    typename A3>
-struct InvokeHelper<false, ReturnType, Runnable,
-    void(A1, A2, A3)>  {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3));
-  }
-};
-
-template <typename Runnable,typename A1, typename A2, typename A3>
-struct InvokeHelper<false, void, Runnable,
-    void(A1, A2, A3)>  {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename A2, typename A3>
-struct InvokeHelper<true, void, Runnable,
-    void(BoundWeakPtr, A2, A3)>  {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3));
-  }
-};
-
-template <typename ReturnType, typename Runnable,typename A1, typename A2,
-    typename A3, typename A4>
-struct InvokeHelper<false, ReturnType, Runnable,
-    void(A1, A2, A3, A4)>  {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4));
-  }
-};
-
-template <typename Runnable,typename A1, typename A2, typename A3, typename A4>
-struct InvokeHelper<false, void, Runnable,
-    void(A1, A2, A3, A4)>  {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3),
-        CallbackForward(a4));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename A2, typename A3,
-    typename A4>
-struct InvokeHelper<true, void, Runnable,
-    void(BoundWeakPtr, A2, A3, A4)>  {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3,
-      A4 a4) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3),
-        CallbackForward(a4));
-  }
-};
-
-template <typename ReturnType, typename Runnable,typename A1, typename A2,
-    typename A3, typename A4, typename A5>
-struct InvokeHelper<false, ReturnType, Runnable,
-    void(A1, A2, A3, A4, A5)>  {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4,
-      A5 a5) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5));
-  }
-};
-
-template <typename Runnable,typename A1, typename A2, typename A3, typename A4,
-    typename A5>
-struct InvokeHelper<false, void, Runnable,
-    void(A1, A2, A3, A4, A5)>  {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3),
-        CallbackForward(a4), CallbackForward(a5));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename A2, typename A3,
-    typename A4, typename A5>
-struct InvokeHelper<true, void, Runnable,
-    void(BoundWeakPtr, A2, A3, A4, A5)>  {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3,
-      A4 a4, A5 a5) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3),
-        CallbackForward(a4), CallbackForward(a5));
-  }
-};
-
-template <typename ReturnType, typename Runnable,typename A1, typename A2,
-    typename A3, typename A4, typename A5, typename A6>
-struct InvokeHelper<false, ReturnType, Runnable,
-    void(A1, A2, A3, A4, A5, A6)>  {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4,
-      A5 a5, A6 a6) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
-        CallbackForward(a6));
-  }
-};
-
-template <typename Runnable,typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6>
-struct InvokeHelper<false, void, Runnable,
-    void(A1, A2, A3, A4, A5, A6)>  {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5,
-      A6 a6) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3),
-        CallbackForward(a4), CallbackForward(a5), CallbackForward(a6));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename A2, typename A3,
-    typename A4, typename A5, typename A6>
-struct InvokeHelper<true, void, Runnable,
-    void(BoundWeakPtr, A2, A3, A4, A5, A6)>  {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3,
-      A4 a4, A5 a5, A6 a6) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3),
-        CallbackForward(a4), CallbackForward(a5), CallbackForward(a6));
-  }
-};
-
-template <typename ReturnType, typename Runnable,typename A1, typename A2,
-    typename A3, typename A4, typename A5, typename A6, typename A7>
-struct InvokeHelper<false, ReturnType, Runnable,
-    void(A1, A2, A3, A4, A5, A6, A7)>  {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4,
-      A5 a5, A6 a6, A7 a7) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
-        CallbackForward(a6), CallbackForward(a7));
-  }
-};
-
-template <typename Runnable,typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6, typename A7>
-struct InvokeHelper<false, void, Runnable,
-    void(A1, A2, A3, A4, A5, A6, A7)>  {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5,
-      A6 a6, A7 a7) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3),
-        CallbackForward(a4), CallbackForward(a5), CallbackForward(a6),
-        CallbackForward(a7));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename A2, typename A3,
-    typename A4, typename A5, typename A6, typename A7>
-struct InvokeHelper<true, void, Runnable,
-    void(BoundWeakPtr, A2, A3, A4, A5, A6, A7)>  {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3,
-      A4 a4, A5 a5, A6 a6, A7 a7) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3),
-        CallbackForward(a4), CallbackForward(a5), CallbackForward(a6),
-        CallbackForward(a7));
+    runnable.Run(weak_ptr.get(), CallbackForward(args)...);
   }
 };
 
diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump
index f632b99..9ddca47 100644
--- a/base/bind_internal.h.pump
+++ b/base/bind_internal.h.pump
@@ -57,18 +57,15 @@
 // Types:
 //  RunnableAdapter<> -- Wraps the various "function" pointer types into an
 //                       object that adheres to the Runnable interface.
-//                       There are |3*ARITY| RunnableAdapter types.
 //  FunctionTraits<> -- Type traits that unwrap a function signature into a
 //                      a set of easier to use typedefs.  Used mainly for
 //                      compile time asserts.
 //                      There are |ARITY| FunctionTraits types.
 //  ForceVoidReturn<> -- Helper class for translating function signatures to
 //                       equivalent forms with a "void" return type.
-//                    There are |ARITY| ForceVoidReturn types.
 //  FunctorTraits<> -- Type traits used determine the correct RunType and
 //                     RunnableType for a Functor.  This is where function
 //                     signature adapters are applied.
-//                    There are |ARITY| ForceVoidReturn types.
 //  MakeRunnable<> -- Takes a Functor and returns an object in the Runnable
 //                    type class that represents the underlying Functor.
 //                    There are |O(1)| MakeRunnable types.
@@ -77,7 +74,6 @@
 //                    and for ignoring return values.  This is separate from
 //                    Invoker to avoid creating multiple version of Invoker<>
 //                    which grows at O(n^2) with the arity.
-//                    There are |k*ARITY| InvokeHelper types.
 //  Invoker<> -- Unwraps the curried parameters and executes the Runnable.
 //               There are |(ARITY^2 + ARITY)/2| Invoketypes.
 //  BindState<> -- Stores the curried parameters, and is the main entry point
@@ -107,75 +103,64 @@
 template <typename Functor>
 class RunnableAdapter;
 
-$for ARITY [[
-$range ARG 1..ARITY
-
-// Function: Arity $(ARITY).
-template <typename R[[]]
-$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
-class RunnableAdapter<R(*)($for ARG , [[A$(ARG)]])> {
+// Function.
+template <typename R, typename... Args>
+class RunnableAdapter<R(*)(Args...)> {
  public:
-  typedef R (RunType)($for ARG , [[A$(ARG)]]);
+  typedef R (RunType)(Args...);
 
-  explicit RunnableAdapter(R(*function)($for ARG , [[A$(ARG)]]))
+  explicit RunnableAdapter(R(*function)(Args...))
       : function_(function) {
   }
 
-  R Run($for ARG , [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
-    return function_($for ARG , [[CallbackForward(a$(ARG))]]);
+  R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
+    return function_(CallbackForward(args)...);
   }
 
  private:
-  R (*function_)($for ARG , [[A$(ARG)]]);
+  R (*function_)(Args...);
 };
 
-// Method: Arity $(ARITY).
-template <typename R, typename T[[]]
-$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
-class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]])> {
+// Method.
+template <typename R, typename T, typename... Args>
+class RunnableAdapter<R(T::*)(Args...)> {
  public:
-  typedef R (RunType)(T*[[]]
-$if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]);
+  typedef R (RunType)(T*, Args...);
   typedef true_type IsMethod;
 
-  explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]]))
+  explicit RunnableAdapter(R(T::*method)(Args...))
       : method_(method) {
   }
 
-  R Run(T* object[[]]
-$if ARITY > 0[[, ]]  $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
-    return (object->*method_)($for ARG , [[CallbackForward(a$(ARG))]]);
+  R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) {
+    return (object->*method_)(CallbackForward(args)...);
   }
 
  private:
-  R (T::*method_)($for ARG , [[A$(ARG)]]);
+  R (T::*method_)(Args...);
 };
 
-// Const Method: Arity $(ARITY).
-template <typename R, typename T[[]]
-$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
-class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]]) const> {
+// Const Method.
+template <typename R, typename T, typename... Args>
+class RunnableAdapter<R(T::*)(Args...) const> {
  public:
-  typedef R (RunType)(const T*[[]]
-$if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]);
+  typedef R (RunType)(const T*, Args...);
   typedef true_type IsMethod;
 
-  explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]]) const)
+  explicit RunnableAdapter(R(T::*method)(Args...) const)
       : method_(method) {
   }
 
-  R Run(const T* object[[]]
-$if ARITY > 0[[, ]]  $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
-    return (object->*method_)($for ARG , [[CallbackForward(a$(ARG))]]);
+  R Run(const T* object,
+        typename CallbackParamTraits<Args>::ForwardType... args) {
+    return (object->*method_)(CallbackForward(args)...);
   }
 
  private:
-  R (T::*method_)($for ARG , [[A$(ARG)]]) const;
+  R (T::*method_)(Args...) const;
 };
 
-]]  $$ for ARITY
-
-
+// TODO(tzik): Remove FunctionTraits after we finish removing bind.pump.
 // FunctionTraits<>
 //
 // Breaks a function signature apart into typedefs for easier introspection.
@@ -205,17 +190,11 @@
 template <typename Sig>
 struct ForceVoidReturn;
 
-$for ARITY [[
-$range ARG 1..ARITY
-
-template <typename R[[]]
-$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
-struct ForceVoidReturn<R($for ARG , [[A$(ARG)]])> {
-  typedef void(RunType)($for ARG , [[A$(ARG)]]);
+template <typename R, typename... Args>
+struct ForceVoidReturn<R(Args...)> {
+  typedef void(RunType)(Args...);
 };
 
-]]  $$ for ARITY
-
 
 // FunctorTraits<>
 //
@@ -284,51 +263,31 @@
           typename ArgsType>
 struct InvokeHelper;
 
-$for ARITY [[
-$range ARG 1..ARITY
-$range WEAKCALL_ARG 2..ARITY
-
-template <typename ReturnType, typename Runnable[[]]
-$if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]>
+template <typename ReturnType, typename Runnable, typename... Args>
 struct InvokeHelper<false, ReturnType, Runnable,
-    void($for ARG , [[A$(ARG)]])>  {
-  static ReturnType MakeItSo(Runnable runnable[[]]
-$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) {
-    return runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]);
+    void(Args...)>  {
+  static ReturnType MakeItSo(Runnable runnable, Args... args) {
+    return runnable.Run(CallbackForward(args)...);
   }
 };
 
-template <typename Runnable[[]]
-$if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]>
-struct InvokeHelper<false, void, Runnable,
-    void($for ARG , [[A$(ARG)]])>  {
-  static void MakeItSo(Runnable runnable[[]]
-$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) {
-    runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]);
+template <typename Runnable, typename... Args>
+struct InvokeHelper<false, void, Runnable, void(Args...)>  {
+  static void MakeItSo(Runnable runnable, Args... args) {
+    runnable.Run(CallbackForward(args)...);
   }
 };
 
-$if ARITY > 0 [[
-
-template <typename Runnable[[]], typename BoundWeakPtr
-$if ARITY > 1[[, ]] $for WEAKCALL_ARG , [[typename A$(WEAKCALL_ARG)]]>
-struct InvokeHelper<true, void, Runnable,
-    void(BoundWeakPtr
-$if ARITY > 1[[, ]] $for WEAKCALL_ARG , [[A$(WEAKCALL_ARG)]])>  {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr
-$if ARITY > 1[[, ]] $for WEAKCALL_ARG , [[A$(WEAKCALL_ARG) a$(WEAKCALL_ARG)]]) {
+template <typename Runnable, typename BoundWeakPtr, typename... Args>
+struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, Args...)>  {
+  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
     if (!weak_ptr.get()) {
       return;
     }
-    runnable.Run(weak_ptr.get()
-$if ARITY > 1[[, ]] $for WEAKCALL_ARG , [[CallbackForward(a$(WEAKCALL_ARG))]]);
+    runnable.Run(weak_ptr.get(), CallbackForward(args)...);
   }
 };
 
-]]
-
-]] $$ for ARITY
-
 #if !defined(_MSC_VER)
 
 template <typename ReturnType, typename Runnable, typename ArgsType>
diff --git a/base/callback.h b/base/callback.h
index 364f506..00669dd 100644
--- a/base/callback.h
+++ b/base/callback.h
@@ -1,8 +1,3 @@
-// This file was GENERATED by command:
-//     pump.py callback.h.pump
-// DO NOT EDIT BY HAND!!!
-
-
 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
@@ -367,10 +362,10 @@
 struct BindState;
 }  // namespace internal
 
-template <typename R>
-class Callback<R(void)> : public internal::CallbackBase {
+template <typename R, typename... Args>
+class Callback<R(Args...)> : public internal::CallbackBase {
  public:
-  typedef R(RunType)();
+  typedef R(RunType)(Args...);
 
   Callback() : CallbackBase(NULL) { }
 
@@ -380,7 +375,6 @@
   Callback(internal::BindState<Runnable, BindRunType,
            BoundArgsType>* bind_state)
       : CallbackBase(bind_state) {
-
     // Force the assignment to a local variable of PolymorphicInvoke
     // so the compiler will typecheck that the passed in Run() method has
     // the correct type.
@@ -394,377 +388,24 @@
     return CallbackBase::Equals(other);
   }
 
-  R Run() const {
+  R Run(typename internal::CallbackParamTraits<Args>::ForwardType... args)
+      const {
     PolymorphicInvoke f =
         reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
 
-    return f(bind_state_.get());
-  }
-
- private:
-  typedef R(*PolymorphicInvoke)(
-      internal::BindStateBase*);
-
-};
-
-template <typename R, typename A1>
-class Callback<R(A1)> : public internal::CallbackBase {
- public:
-  typedef R(RunType)(A1);
-
-  Callback() : CallbackBase(NULL) { }
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(internal::BindState<Runnable, BindRunType,
-           BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &internal::BindState<Runnable, BindRunType, BoundArgsType>
-            ::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), internal::CallbackForward(a1));
+    return f(bind_state_.get(), internal::CallbackForward(args)...);
   }
 
  private:
   typedef R(*PolymorphicInvoke)(
       internal::BindStateBase*,
-          typename internal::CallbackParamTraits<A1>::ForwardType);
-
+      typename internal::CallbackParamTraits<Args>::ForwardType...);
 };
 
-template <typename R, typename A1, typename A2>
-class Callback<R(A1, A2)> : public internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2);
-
-  Callback() : CallbackBase(NULL) { }
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(internal::BindState<Runnable, BindRunType,
-           BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &internal::BindState<Runnable, BindRunType, BoundArgsType>
-            ::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename internal::CallbackParamTraits<A2>::ForwardType a2) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), internal::CallbackForward(a1),
-             internal::CallbackForward(a2));
-  }
-
- private:
-  typedef R(*PolymorphicInvoke)(
-      internal::BindStateBase*,
-          typename internal::CallbackParamTraits<A1>::ForwardType,
-          typename internal::CallbackParamTraits<A2>::ForwardType);
-
-};
-
-template <typename R, typename A1, typename A2, typename A3>
-class Callback<R(A1, A2, A3)> : public internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3);
-
-  Callback() : CallbackBase(NULL) { }
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(internal::BindState<Runnable, BindRunType,
-           BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &internal::BindState<Runnable, BindRunType, BoundArgsType>
-            ::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename internal::CallbackParamTraits<A3>::ForwardType a3) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), internal::CallbackForward(a1),
-             internal::CallbackForward(a2),
-             internal::CallbackForward(a3));
-  }
-
- private:
-  typedef R(*PolymorphicInvoke)(
-      internal::BindStateBase*,
-          typename internal::CallbackParamTraits<A1>::ForwardType,
-          typename internal::CallbackParamTraits<A2>::ForwardType,
-          typename internal::CallbackParamTraits<A3>::ForwardType);
-
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3, A4);
-
-  Callback() : CallbackBase(NULL) { }
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(internal::BindState<Runnable, BindRunType,
-           BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &internal::BindState<Runnable, BindRunType, BoundArgsType>
-            ::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename internal::CallbackParamTraits<A3>::ForwardType a3,
-        typename internal::CallbackParamTraits<A4>::ForwardType a4) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), internal::CallbackForward(a1),
-             internal::CallbackForward(a2),
-             internal::CallbackForward(a3),
-             internal::CallbackForward(a4));
-  }
-
- private:
-  typedef R(*PolymorphicInvoke)(
-      internal::BindStateBase*,
-          typename internal::CallbackParamTraits<A1>::ForwardType,
-          typename internal::CallbackParamTraits<A2>::ForwardType,
-          typename internal::CallbackParamTraits<A3>::ForwardType,
-          typename internal::CallbackParamTraits<A4>::ForwardType);
-
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5>
-class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5);
-
-  Callback() : CallbackBase(NULL) { }
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(internal::BindState<Runnable, BindRunType,
-           BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &internal::BindState<Runnable, BindRunType, BoundArgsType>
-            ::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename internal::CallbackParamTraits<A3>::ForwardType a3,
-        typename internal::CallbackParamTraits<A4>::ForwardType a4,
-        typename internal::CallbackParamTraits<A5>::ForwardType a5) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), internal::CallbackForward(a1),
-             internal::CallbackForward(a2),
-             internal::CallbackForward(a3),
-             internal::CallbackForward(a4),
-             internal::CallbackForward(a5));
-  }
-
- private:
-  typedef R(*PolymorphicInvoke)(
-      internal::BindStateBase*,
-          typename internal::CallbackParamTraits<A1>::ForwardType,
-          typename internal::CallbackParamTraits<A2>::ForwardType,
-          typename internal::CallbackParamTraits<A3>::ForwardType,
-          typename internal::CallbackParamTraits<A4>::ForwardType,
-          typename internal::CallbackParamTraits<A5>::ForwardType);
-
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6>
-class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6);
-
-  Callback() : CallbackBase(NULL) { }
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(internal::BindState<Runnable, BindRunType,
-           BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &internal::BindState<Runnable, BindRunType, BoundArgsType>
-            ::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename internal::CallbackParamTraits<A3>::ForwardType a3,
-        typename internal::CallbackParamTraits<A4>::ForwardType a4,
-        typename internal::CallbackParamTraits<A5>::ForwardType a5,
-        typename internal::CallbackParamTraits<A6>::ForwardType a6) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), internal::CallbackForward(a1),
-             internal::CallbackForward(a2),
-             internal::CallbackForward(a3),
-             internal::CallbackForward(a4),
-             internal::CallbackForward(a5),
-             internal::CallbackForward(a6));
-  }
-
- private:
-  typedef R(*PolymorphicInvoke)(
-      internal::BindStateBase*,
-          typename internal::CallbackParamTraits<A1>::ForwardType,
-          typename internal::CallbackParamTraits<A2>::ForwardType,
-          typename internal::CallbackParamTraits<A3>::ForwardType,
-          typename internal::CallbackParamTraits<A4>::ForwardType,
-          typename internal::CallbackParamTraits<A5>::ForwardType,
-          typename internal::CallbackParamTraits<A6>::ForwardType);
-
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6, typename A7>
-class Callback<R(A1, A2, A3, A4, A5, A6, A7)> : public internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7);
-
-  Callback() : CallbackBase(NULL) { }
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(internal::BindState<Runnable, BindRunType,
-           BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &internal::BindState<Runnable, BindRunType, BoundArgsType>
-            ::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename internal::CallbackParamTraits<A3>::ForwardType a3,
-        typename internal::CallbackParamTraits<A4>::ForwardType a4,
-        typename internal::CallbackParamTraits<A5>::ForwardType a5,
-        typename internal::CallbackParamTraits<A6>::ForwardType a6,
-        typename internal::CallbackParamTraits<A7>::ForwardType a7) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), internal::CallbackForward(a1),
-             internal::CallbackForward(a2),
-             internal::CallbackForward(a3),
-             internal::CallbackForward(a4),
-             internal::CallbackForward(a5),
-             internal::CallbackForward(a6),
-             internal::CallbackForward(a7));
-  }
-
- private:
-  typedef R(*PolymorphicInvoke)(
-      internal::BindStateBase*,
-          typename internal::CallbackParamTraits<A1>::ForwardType,
-          typename internal::CallbackParamTraits<A2>::ForwardType,
-          typename internal::CallbackParamTraits<A3>::ForwardType,
-          typename internal::CallbackParamTraits<A4>::ForwardType,
-          typename internal::CallbackParamTraits<A5>::ForwardType,
-          typename internal::CallbackParamTraits<A6>::ForwardType,
-          typename internal::CallbackParamTraits<A7>::ForwardType);
-
-};
-
-
 // Syntactic sugar to make Callback<void(void)> easier to declare since it
 // will be used in a lot of APIs with delayed execution.
 typedef Callback<void(void)> Closure;
 
 }  // namespace base
 
-#endif  // BASE_CALLBACK_H
+#endif  // BASE_CALLBACK_H_
diff --git a/base/callback.h.pump b/base/callback.h.pump
deleted file mode 100644
index 686196d..0000000
--- a/base/callback.h.pump
+++ /dev/null
@@ -1,436 +0,0 @@
-$$ This is a pump file for generating file templates.  Pump is a python
-$$ script that is part of the Google Test suite of utilities.  Description
-$$ can be found here:
-$$
-$$ http://code.google.com/p/googletest/wiki/PumpManual
-$$
-
-$$ See comment for MAX_ARITY in base/bind.h.pump.
-$var MAX_ARITY = 7
-
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_CALLBACK_H_
-#define BASE_CALLBACK_H_
-
-#include "base/callback_forward.h"
-#include "base/callback_internal.h"
-#include "base/template_util.h"
-
-// NOTE: Header files that do not require the full definition of Callback or
-// Closure should #include "base/callback_forward.h" instead of this file.
-
-// -----------------------------------------------------------------------------
-// Introduction
-// -----------------------------------------------------------------------------
-//
-// The templated Callback class is a generalized function object. Together
-// with the Bind() function in bind.h, they provide a type-safe method for
-// performing partial application of functions.
-//
-// Partial application (or "currying") is the process of binding a subset of
-// a function's arguments to produce another function that takes fewer
-// arguments. This can be used to pass around a unit of delayed execution,
-// much like lexical closures are used in other languages. For example, it
-// is used in Chromium code to schedule tasks on different MessageLoops.
-//
-// A callback with no unbound input parameters (base::Callback<void(void)>)
-// is called a base::Closure. Note that this is NOT the same as what other
-// languages refer to as a closure -- it does not retain a reference to its
-// enclosing environment.
-//
-// MEMORY MANAGEMENT AND PASSING
-//
-// The Callback objects themselves should be passed by const-reference, and
-// stored by copy. They internally store their state via a refcounted class
-// and thus do not need to be deleted.
-//
-// The reason to pass via a const-reference is to avoid unnecessary
-// AddRef/Release pairs to the internal state.
-//
-//
-// -----------------------------------------------------------------------------
-// Quick reference for basic stuff
-// -----------------------------------------------------------------------------
-//
-// BINDING A BARE FUNCTION
-//
-//   int Return5() { return 5; }
-//   base::Callback<int(void)> func_cb = base::Bind(&Return5);
-//   LOG(INFO) << func_cb.Run();  // Prints 5.
-//
-// BINDING A CLASS METHOD
-//
-//   The first argument to bind is the member function to call, the second is
-//   the object on which to call it.
-//
-//   class Ref : public base::RefCountedThreadSafe<Ref> {
-//    public:
-//     int Foo() { return 3; }
-//     void PrintBye() { LOG(INFO) << "bye."; }
-//   };
-//   scoped_refptr<Ref> ref = new Ref();
-//   base::Callback<void(void)> ref_cb = base::Bind(&Ref::Foo, ref);
-//   LOG(INFO) << ref_cb.Run();  // Prints out 3.
-//
-//   By default the object must support RefCounted or you will get a compiler
-//   error. If you're passing between threads, be sure it's
-//   RefCountedThreadSafe! See "Advanced binding of member functions" below if
-//   you don't want to use reference counting.
-//
-// RUNNING A CALLBACK
-//
-//   Callbacks can be run with their "Run" method, which has the same
-//   signature as the template argument to the callback.
-//
-//   void DoSomething(const base::Callback<void(int, std::string)>& callback) {
-//     callback.Run(5, "hello");
-//   }
-//
-//   Callbacks can be run more than once (they don't get deleted or marked when
-//   run). However, this precludes using base::Passed (see below).
-//
-//   void DoSomething(const base::Callback<double(double)>& callback) {
-//     double myresult = callback.Run(3.14159);
-//     myresult += callback.Run(2.71828);
-//   }
-//
-// PASSING UNBOUND INPUT PARAMETERS
-//
-//   Unbound parameters are specified at the time a callback is Run(). They are
-//   specified in the Callback template type:
-//
-//   void MyFunc(int i, const std::string& str) {}
-//   base::Callback<void(int, const std::string&)> cb = base::Bind(&MyFunc);
-//   cb.Run(23, "hello, world");
-//
-// PASSING BOUND INPUT PARAMETERS
-//
-//   Bound parameters are specified when you create thee callback as arguments
-//   to Bind(). They will be passed to the function and the Run()ner of the
-//   callback doesn't see those values or even know that the function it's
-//   calling.
-//
-//   void MyFunc(int i, const std::string& str) {}
-//   base::Callback<void(void)> cb = base::Bind(&MyFunc, 23, "hello world");
-//   cb.Run();
-//
-//   A callback with no unbound input parameters (base::Callback<void(void)>)
-//   is called a base::Closure. So we could have also written:
-//
-//   base::Closure cb = base::Bind(&MyFunc, 23, "hello world");
-//
-//   When calling member functions, bound parameters just go after the object
-//   pointer.
-//
-//   base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world");
-//
-// PARTIAL BINDING OF PARAMETERS
-//
-//   You can specify some parameters when you create the callback, and specify
-//   the rest when you execute the callback.
-//
-//   void MyFunc(int i, const std::string& str) {}
-//   base::Callback<void(const std::string&)> cb = base::Bind(&MyFunc, 23);
-//   cb.Run("hello world");
-//
-//   When calling a function bound parameters are first, followed by unbound
-//   parameters.
-//
-//
-// -----------------------------------------------------------------------------
-// Quick reference for advanced binding
-// -----------------------------------------------------------------------------
-//
-// BINDING A CLASS METHOD WITH WEAK POINTERS
-//
-//   base::Bind(&MyClass::Foo, GetWeakPtr());
-//
-//   The callback will not be run if the object has already been destroyed.
-//   DANGER: weak pointers are not threadsafe, so don't use this
-//   when passing between threads!
-//
-// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT
-//
-//   base::Bind(&MyClass::Foo, base::Unretained(this));
-//
-//   This disables all lifetime management on the object. You're responsible
-//   for making sure the object is alive at the time of the call. You break it,
-//   you own it!
-//
-// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS
-//
-//   MyClass* myclass = new MyClass;
-//   base::Bind(&MyClass::Foo, base::Owned(myclass));
-//
-//   The object will be deleted when the callback is destroyed, even if it's
-//   not run (like if you post a task during shutdown). Potentially useful for
-//   "fire and forget" cases.
-//
-// IGNORING RETURN VALUES
-//
-//   Sometimes you want to call a function that returns a value in a callback
-//   that doesn't expect a return value.
-//
-//   int DoSomething(int arg) { cout << arg << endl; }
-//   base::Callback<void<int>) cb =
-//       base::Bind(base::IgnoreResult(&DoSomething));
-//
-//
-// -----------------------------------------------------------------------------
-// Quick reference for binding parameters to Bind()
-// -----------------------------------------------------------------------------
-//
-// Bound parameters are specified as arguments to Bind() and are passed to the
-// function. A callback with no parameters or no unbound parameters is called a
-// Closure (base::Callback<void(void)> and base::Closure are the same thing).
-//
-// PASSING PARAMETERS OWNED BY THE CALLBACK
-//
-//   void Foo(int* arg) { cout << *arg << endl; }
-//   int* pn = new int(1);
-//   base::Closure foo_callback = base::Bind(&foo, base::Owned(pn));
-//
-//   The parameter will be deleted when the callback is destroyed, even if it's
-//   not run (like if you post a task during shutdown).
-//
-// PASSING PARAMETERS AS A scoped_ptr
-//
-//   void TakesOwnership(scoped_ptr<Foo> arg) {}
-//   scoped_ptr<Foo> f(new Foo);
-//   // f becomes null during the following call.
-//   base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f));
-//
-//   Ownership of the parameter will be with the callback until the it is run,
-//   when ownership is passed to the callback function. This means the callback
-//   can only be run once. If the callback is never run, it will delete the
-//   object when it's destroyed.
-//
-// PASSING PARAMETERS AS A scoped_refptr
-//
-//   void TakesOneRef(scoped_refptr<Foo> arg) {}
-//   scoped_refptr<Foo> f(new Foo)
-//   base::Closure cb = base::Bind(&TakesOneRef, f);
-//
-//   This should "just work." The closure will take a reference as long as it
-//   is alive, and another reference will be taken for the called function.
-//
-// PASSING PARAMETERS BY REFERENCE
-//
-//   void foo(int arg) { cout << arg << endl }
-//   int n = 1;
-//   base::Closure has_ref = base::Bind(&foo, base::ConstRef(n));
-//   n = 2;
-//   has_ref.Run();  // Prints "2"
-//
-//   Normally parameters are copied in the closure. DANGER: ConstRef stores a
-//   const reference instead, referencing the original parameter. This means
-//   that you must ensure the object outlives the callback!
-//
-//
-// -----------------------------------------------------------------------------
-// Implementation notes
-// -----------------------------------------------------------------------------
-//
-// WHERE IS THIS DESIGN FROM:
-//
-// The design Callback and Bind is heavily influenced by C++'s
-// tr1::function/tr1::bind, and by the "Google Callback" system used inside
-// Google.
-//
-//
-// HOW THE IMPLEMENTATION WORKS:
-//
-// There are three main components to the system:
-//   1) The Callback classes.
-//   2) The Bind() functions.
-//   3) The arguments wrappers (e.g., Unretained() and ConstRef()).
-//
-// The Callback classes represent a generic function pointer. Internally,
-// it stores a refcounted piece of state that represents the target function
-// and all its bound parameters.  Each Callback specialization has a templated
-// constructor that takes an BindState<>*.  In the context of the constructor,
-// the static type of this BindState<> pointer uniquely identifies the
-// function it is representing, all its bound parameters, and a Run() method
-// that is capable of invoking the target.
-//
-// Callback's constructor takes the BindState<>* that has the full static type
-// and erases the target function type as well as the types of the bound
-// parameters.  It does this by storing a pointer to the specific Run()
-// function, and upcasting the state of BindState<>* to a
-// BindStateBase*. This is safe as long as this BindStateBase pointer
-// is only used with the stored Run() pointer.
-//
-// To BindState<> objects are created inside the Bind() functions.
-// These functions, along with a set of internal templates, are responsible for
-//
-//  - Unwrapping the function signature into return type, and parameters
-//  - Determining the number of parameters that are bound
-//  - Creating the BindState storing the bound parameters
-//  - Performing compile-time asserts to avoid error-prone behavior
-//  - Returning an Callback<> with an arity matching the number of unbound
-//    parameters and that knows the correct refcounting semantics for the
-//    target object if we are binding a method.
-//
-// The Bind functions do the above using type-inference, and template
-// specializations.
-//
-// By default Bind() will store copies of all bound parameters, and attempt
-// to refcount a target object if the function being bound is a class method.
-// These copies are created even if the function takes parameters as const
-// references. (Binding to non-const references is forbidden, see bind.h.)
-//
-// To change this behavior, we introduce a set of argument wrappers
-// (e.g., Unretained(), and ConstRef()).  These are simple container templates
-// that are passed by value, and wrap a pointer to argument.  See the
-// file-level comment in base/bind_helpers.h for more info.
-//
-// These types are passed to the Unwrap() functions, and the MaybeRefcount()
-// functions respectively to modify the behavior of Bind().  The Unwrap()
-// and MaybeRefcount() functions change behavior by doing partial
-// specialization based on whether or not a parameter is a wrapper type.
-//
-// ConstRef() is similar to tr1::cref.  Unretained() is specific to Chromium.
-//
-//
-// WHY NOT TR1 FUNCTION/BIND?
-//
-// Direct use of tr1::function and tr1::bind was considered, but ultimately
-// rejected because of the number of copy constructors invocations involved
-// in the binding of arguments during construction, and the forwarding of
-// arguments during invocation.  These copies will no longer be an issue in
-// C++0x because C++0x will support rvalue reference allowing for the compiler
-// to avoid these copies.  However, waiting for C++0x is not an option.
-//
-// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
-// tr1::bind call itself will invoke a non-trivial copy constructor three times
-// for each bound parameter.  Also, each when passing a tr1::function, each
-// bound argument will be copied again.
-//
-// In addition to the copies taken at binding and invocation, copying a
-// tr1::function causes a copy to be made of all the bound parameters and
-// state.
-//
-// Furthermore, in Chromium, it is desirable for the Callback to take a
-// reference on a target object when representing a class method call.  This
-// is not supported by tr1.
-//
-// Lastly, tr1::function and tr1::bind has a more general and flexible API.
-// This includes things like argument reordering by use of
-// tr1::bind::placeholder, support for non-const reference parameters, and some
-// limited amount of subtyping of the tr1::function object (e.g.,
-// tr1::function<int(int)> is convertible to tr1::function<void(int)>).
-//
-// These are not features that are required in Chromium. Some of them, such as
-// allowing for reference parameters, and subtyping of functions, may actually
-// become a source of errors. Removing support for these features actually
-// allows for a simpler implementation, and a terser Currying API.
-//
-//
-// WHY NOT GOOGLE CALLBACKS?
-//
-// The Google callback system also does not support refcounting.  Furthermore,
-// its implementation has a number of strange edge cases with respect to type
-// conversion of its arguments.  In particular, the argument's constness must
-// at times match exactly the function signature, or the type-inference might
-// break.  Given the above, writing a custom solution was easier.
-//
-//
-// MISSING FUNCTIONALITY
-//  - Invoking the return of Bind.  Bind(&foo).Run() does not work;
-//  - Binding arrays to functions that take a non-const pointer.
-//    Example:
-//      void Foo(const char* ptr);
-//      void Bar(char* ptr);
-//      Bind(&Foo, "test");
-//      Bind(&Bar, "test");  // This fails because ptr is not const.
-
-namespace base {
-
-// First, we forward declare the Callback class template. This informs the
-// compiler that the template only has 1 type parameter which is the function
-// signature that the Callback is representing.
-//
-// After this, create template specializations for 0-$(MAX_ARITY) parameters. Note that
-// even though the template typelist grows, the specialization still
-// only has one type: the function signature.
-//
-// If you are thinking of forward declaring Callback in your own header file,
-// please include "base/callback_forward.h" instead.
-template <typename Sig>
-class Callback;
-
-namespace internal {
-template <typename Runnable, typename RunType, typename BoundArgsType>
-struct BindState;
-}  // namespace internal
-
-
-$range ARITY 0..MAX_ARITY
-$for ARITY [[
-$range ARG 1..ARITY
-
-$if ARITY == 0 [[
-template <typename R>
-class Callback<R(void)> : public internal::CallbackBase {
-]] $else [[
-template <typename R, $for ARG , [[typename A$(ARG)]]>
-class Callback<R($for ARG , [[A$(ARG)]])> : public internal::CallbackBase {
-]]
-
- public:
-  typedef R(RunType)($for ARG , [[A$(ARG)]]);
-
-  Callback() : CallbackBase(NULL) { }
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(internal::BindState<Runnable, BindRunType,
-           BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &internal::BindState<Runnable, BindRunType, BoundArgsType>
-            ::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run($for ARG ,
-        [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get()[[]]
-$if ARITY != 0 [[, ]]
-$for ARG ,
-             [[internal::CallbackForward(a$(ARG))]]);
-  }
-
- private:
-  typedef R(*PolymorphicInvoke)(
-      internal::BindStateBase*[[]]
-$if ARITY != 0 [[, ]]
-$for ARG , [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType]]);
-
-};
-
-
-]]  $$ for ARITY
-
-// Syntactic sugar to make Callback<void(void)> easier to declare since it
-// will be used in a lot of APIs with delayed execution.
-typedef Callback<void(void)> Closure;
-
-}  // namespace base
-
-#endif  // BASE_CALLBACK_H
diff --git a/base/callback_internal.h b/base/callback_internal.h
index b85973d..9dca023 100644
--- a/base/callback_internal.h
+++ b/base/callback_internal.h
@@ -81,6 +81,28 @@
                             !is_const<T>::value;
 };
 
+// Returns |Then| as SelectType::Type if |condition| is true. Otherwise returns
+// |Else|.
+template <bool condition, typename Then, typename Else>
+struct SelectType {
+  typedef Then Type;
+};
+
+template <typename Then, typename Else>
+struct SelectType<false, Then, Else> {
+  typedef Else Type;
+};
+
+template <typename>
+struct CallbackParamTraitsForMoveOnlyType;
+
+template <typename>
+struct CallbackParamTraitsForNonMoveOnlyType;
+
+// TODO(tzik): Use a default parameter once MSVS supports variadic templates
+// with default values.
+// http://connect.microsoft.com/VisualStudio/feedbackdetail/view/957801/compilation-error-with-variadic-templates
+//
 // This is a typetraits object that's used to take an argument type, and
 // extract a suitable type for storing and forwarding arguments.
 //
@@ -92,8 +114,15 @@
 // parameters by const reference. In this case, we end up passing an actual
 // array type in the initializer list which C++ does not allow.  This will
 // break passing of C-string literals.
-template <typename T, bool is_move_only = IsMoveOnlyType<T>::value>
-struct CallbackParamTraits {
+template <typename T>
+struct CallbackParamTraits
+    : SelectType<IsMoveOnlyType<T>::value,
+         CallbackParamTraitsForMoveOnlyType<T>,
+         CallbackParamTraitsForNonMoveOnlyType<T> >::Type {
+};
+
+template <typename T>
+struct CallbackParamTraitsForNonMoveOnlyType {
   typedef const T& ForwardType;
   typedef T StorageType;
 };
@@ -104,7 +133,7 @@
 //
 // The ForwardType should only be used for unbound arguments.
 template <typename T>
-struct CallbackParamTraits<T&, false> {
+struct CallbackParamTraitsForNonMoveOnlyType<T&> {
   typedef T& ForwardType;
   typedef T StorageType;
 };
@@ -115,14 +144,14 @@
 // T[n]" does not seem to match correctly, so we are stuck with this
 // restriction.
 template <typename T, size_t n>
-struct CallbackParamTraits<T[n], false> {
+struct CallbackParamTraitsForNonMoveOnlyType<T[n]> {
   typedef const T* ForwardType;
   typedef const T* StorageType;
 };
 
 // See comment for CallbackParamTraits<T[n]>.
 template <typename T>
-struct CallbackParamTraits<T[], false> {
+struct CallbackParamTraitsForNonMoveOnlyType<T[]> {
   typedef const T* ForwardType;
   typedef const T* StorageType;
 };
@@ -141,7 +170,7 @@
 // reference cannot be used with temporaries which means the result of a
 // function or a cast would not be usable with Callback<> or Bind().
 template <typename T>
-struct CallbackParamTraits<T, true> {
+struct CallbackParamTraitsForMoveOnlyType {
   typedef T ForwardType;
   typedef T StorageType;
 };
diff --git a/base/callback_list.h b/base/callback_list.h
index 5b911fd..aeed5f1 100644
--- a/base/callback_list.h
+++ b/base/callback_list.h
@@ -1,8 +1,3 @@
-// This file was GENERATED by command:
-//     pump.py callback_list.h.pump
-// DO NOT EDIT BY HAND!!!
-
-
 // Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
@@ -208,192 +203,21 @@
 
 template <typename Sig> class CallbackList;
 
-template <>
-class CallbackList<void(void)>
-    : public internal::CallbackListBase<Callback<void(void)> > {
+template <typename... Args>
+class CallbackList<void(Args...)>
+    : public internal::CallbackListBase<Callback<void(Args...)> > {
  public:
-  typedef Callback<void(void)> CallbackType;
+  typedef Callback<void(Args...)> CallbackType;
 
   CallbackList() {}
 
-  void Notify() {
-    internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run();
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1>
-class CallbackList<void(A1)>
-    : public internal::CallbackListBase<Callback<void(A1)> > {
- public:
-  typedef Callback<void(A1)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1) {
+  void Notify(
+      typename internal::CallbackParamTraits<Args>::ForwardType... args) {
     typename internal::CallbackListBase<CallbackType>::Iterator it =
         this->GetIterator();
     CallbackType* cb;
     while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1, typename A2>
-class CallbackList<void(A1, A2)>
-    : public internal::CallbackListBase<Callback<void(A1, A2)> > {
- public:
-  typedef Callback<void(A1, A2)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename internal::CallbackParamTraits<A2>::ForwardType a2) {
-    typename internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1, typename A2, typename A3>
-class CallbackList<void(A1, A2, A3)>
-    : public internal::CallbackListBase<Callback<void(A1, A2, A3)> > {
- public:
-  typedef Callback<void(A1, A2, A3)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename internal::CallbackParamTraits<A3>::ForwardType a3) {
-    typename internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1, typename A2, typename A3, typename A4>
-class CallbackList<void(A1, A2, A3, A4)>
-    : public internal::CallbackListBase<Callback<void(A1, A2, A3, A4)> > {
- public:
-  typedef Callback<void(A1, A2, A3, A4)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename internal::CallbackParamTraits<A3>::ForwardType a3,
-              typename internal::CallbackParamTraits<A4>::ForwardType a4) {
-    typename internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3, a4);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1, typename A2, typename A3, typename A4, typename A5>
-class CallbackList<void(A1, A2, A3, A4, A5)>
-    : public internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5)> > {
- public:
-  typedef Callback<void(A1, A2, A3, A4, A5)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename internal::CallbackParamTraits<A3>::ForwardType a3,
-              typename internal::CallbackParamTraits<A4>::ForwardType a4,
-              typename internal::CallbackParamTraits<A5>::ForwardType a5) {
-    typename internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3, a4, a5);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1, typename A2, typename A3, typename A4, typename A5,
-    typename A6>
-class CallbackList<void(A1, A2, A3, A4, A5, A6)>
-    : public internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5,
-        A6)> > {
- public:
-  typedef Callback<void(A1, A2, A3, A4, A5, A6)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename internal::CallbackParamTraits<A3>::ForwardType a3,
-              typename internal::CallbackParamTraits<A4>::ForwardType a4,
-              typename internal::CallbackParamTraits<A5>::ForwardType a5,
-              typename internal::CallbackParamTraits<A6>::ForwardType a6) {
-    typename internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3, a4, a5, a6);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1, typename A2, typename A3, typename A4, typename A5,
-    typename A6, typename A7>
-class CallbackList<void(A1, A2, A3, A4, A5, A6, A7)>
-    : public internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5, A6,
-        A7)> > {
- public:
-  typedef Callback<void(A1, A2, A3, A4, A5, A6, A7)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename internal::CallbackParamTraits<A3>::ForwardType a3,
-              typename internal::CallbackParamTraits<A4>::ForwardType a4,
-              typename internal::CallbackParamTraits<A5>::ForwardType a5,
-              typename internal::CallbackParamTraits<A6>::ForwardType a6,
-              typename internal::CallbackParamTraits<A7>::ForwardType a7) {
-    typename internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3, a4, a5, a6, a7);
+      cb->Run(args...);
     }
   }
 
diff --git a/base/callback_list.h.pump b/base/callback_list.h.pump
deleted file mode 100644
index d7f8473..0000000
--- a/base/callback_list.h.pump
+++ /dev/null
@@ -1,269 +0,0 @@
-$$ This is a pump file for generating file templates.  Pump is a python
-$$ script that is part of the Google Test suite of utilities.  Description
-$$ can be found here:
-$$
-$$ http://code.google.com/p/googletest/wiki/PumpManual
-$$
-
-$$ See comment for MAX_ARITY in base/bind.h.pump.
-$var MAX_ARITY = 7
-
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_CALLBACK_LIST_H_
-#define BASE_CALLBACK_LIST_H_
-
-#include <list>
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/callback_internal.h"
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-
-// OVERVIEW:
-//
-// A container for a list of callbacks.  Unlike a normal STL vector or list,
-// this container can be modified during iteration without invalidating the
-// iterator. It safely handles the case of a callback removing itself
-// or another callback from the list while callbacks are being run.
-//
-// TYPICAL USAGE:
-//
-// class MyWidget {
-//  public:
-//   ...
-//
-//   typedef base::Callback<void(const Foo&)> OnFooCallback;
-//
-//   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
-//   RegisterCallback(const OnFooCallback& cb) {
-//     return callback_list_.Add(cb);
-//   }
-//
-//  private:
-//   void NotifyFoo(const Foo& foo) {
-//      callback_list_.Notify(foo);
-//   }
-//
-//   base::CallbackList<void(const Foo&)> callback_list_;
-//
-//   DISALLOW_COPY_AND_ASSIGN(MyWidget);
-// };
-//
-//
-// class MyWidgetListener {
-//  public:
-//   MyWidgetListener::MyWidgetListener() {
-//     foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
-//             base::Bind(&MyWidgetListener::OnFoo, this)));
-//   }
-//
-//   MyWidgetListener::~MyWidgetListener() {
-//      // Subscription gets deleted automatically and will deregister
-//      // the callback in the process.
-//   }
-//
-//  private:
-//   void OnFoo(const Foo& foo) {
-//     // Do something.
-//   }
-//
-//   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
-//       foo_subscription_;
-//
-//   DISALLOW_COPY_AND_ASSIGN(MyWidgetListener);
-// };
-
-namespace base {
-
-namespace internal {
-
-template <typename CallbackType>
-class CallbackListBase {
- public:
-  class Subscription {
-   public:
-    Subscription(CallbackListBase<CallbackType>* list,
-                 typename std::list<CallbackType>::iterator iter)
-        : list_(list),
-          iter_(iter) {
-    }
-
-    ~Subscription() {
-      if (list_->active_iterator_count_) {
-        iter_->Reset();
-      } else {
-        list_->callbacks_.erase(iter_);
-        if (!list_->removal_callback_.is_null())
-          list_->removal_callback_.Run();
-      }
-    }
-
-   private:
-    CallbackListBase<CallbackType>* list_;
-    typename std::list<CallbackType>::iterator iter_;
-
-    DISALLOW_COPY_AND_ASSIGN(Subscription);
-  };
-
-  // Add a callback to the list. The callback will remain registered until the
-  // returned Subscription is destroyed, which must occur before the
-  // CallbackList is destroyed.
-  scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
-    DCHECK(!cb.is_null());
-    return scoped_ptr<Subscription>(
-        new Subscription(this, callbacks_.insert(callbacks_.end(), cb)));
-  }
-
-  // Sets a callback which will be run when a subscription list is changed.
-  void set_removal_callback(const Closure& callback) {
-    removal_callback_ = callback;
-  }
-
-  // Returns true if there are no subscriptions. This is only valid to call when
-  // not looping through the list.
-  bool empty() {
-    DCHECK_EQ(0, active_iterator_count_);
-    return callbacks_.empty();
-  }
-
- protected:
-  // An iterator class that can be used to access the list of callbacks.
-  class Iterator {
-   public:
-    explicit Iterator(CallbackListBase<CallbackType>* list)
-        : list_(list),
-          list_iter_(list_->callbacks_.begin()) {
-      ++list_->active_iterator_count_;
-    }
-
-    Iterator(const Iterator& iter)
-        : list_(iter.list_),
-          list_iter_(iter.list_iter_) {
-      ++list_->active_iterator_count_;
-    }
-
-    ~Iterator() {
-      if (list_ && --list_->active_iterator_count_ == 0) {
-        list_->Compact();
-      }
-    }
-
-    CallbackType* GetNext() {
-      while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
-        ++list_iter_;
-
-      CallbackType* cb = NULL;
-      if (list_iter_ != list_->callbacks_.end()) {
-        cb = &(*list_iter_);
-        ++list_iter_;
-      }
-      return cb;
-    }
-
-   private:
-    CallbackListBase<CallbackType>* list_;
-    typename std::list<CallbackType>::iterator list_iter_;
-  };
-
-  CallbackListBase() : active_iterator_count_(0) {}
-
-  ~CallbackListBase() {
-    DCHECK_EQ(0, active_iterator_count_);
-    DCHECK_EQ(0U, callbacks_.size());
-  }
-
-  // Returns an instance of a CallbackListBase::Iterator which can be used
-  // to run callbacks.
-  Iterator GetIterator() {
-    return Iterator(this);
-  }
-
-  // Compact the list: remove any entries which were NULLed out during
-  // iteration.
-  void Compact() {
-    typename std::list<CallbackType>::iterator it = callbacks_.begin();
-    bool updated = false;
-    while (it != callbacks_.end()) {
-      if ((*it).is_null()) {
-        updated = true;
-        it = callbacks_.erase(it);
-      } else {
-        ++it;
-      }
-
-      if (updated && !removal_callback_.is_null())
-        removal_callback_.Run();
-    }
-  }
-
- private:
-  std::list<CallbackType> callbacks_;
-  int active_iterator_count_;
-  Closure removal_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
-};
-
-}  // namespace internal
-
-template <typename Sig> class CallbackList;
-
-
-$range ARITY 0..MAX_ARITY
-$for ARITY [[
-$range ARG 1..ARITY
-
-$if ARITY == 0 [[
-template <>
-class CallbackList<void(void)>
-    : public internal::CallbackListBase<Callback<void(void)> > {
-]] $else [[
-template <$for ARG , [[typename A$(ARG)]]>
-class CallbackList<void($for ARG , [[A$(ARG)]])>
-    : public internal::CallbackListBase<Callback<void($for ARG , [[A$(ARG)]])> > {
-]]
-
- public:
-$if ARITY == 0 [[
-
-  typedef Callback<void(void)> CallbackType;
-]] $else [[
-
-  typedef Callback<void($for ARG , [[A$(ARG)]])> CallbackType;
-]]
-
-
-  CallbackList() {}
-
-  void Notify($for ARG ,
-              [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
-$if ARITY == 0 [[
-
-    internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-]] $else [[
-
-    typename internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-]]
-
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run($for ARG , [[a$(ARG)]]);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-
-]]  $$ for ARITY
-}  // namespace base
-
-#endif  // BASE_CALLBACK_LIST_H_
diff --git a/base/debug/proc_maps_linux_unittest.cc b/base/debug/proc_maps_linux_unittest.cc
index d5d1b83..142f891 100644
--- a/base/debug/proc_maps_linux_unittest.cc
+++ b/base/debug/proc_maps_linux_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+#include "base/threading/platform_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
@@ -197,6 +198,14 @@
   bool found_exe = false;
   bool found_stack = false;
   bool found_address = false;
+
+  // Valgrind uses its own allocated stacks instead of the kernel-provided stack
+  // without letting the kernel know via prctl(PR_SET_MM_START_STACK). This
+  // causes the kernel to use [stack:TID] format. See http://crbug.com/431702
+  // for details.
+  std::string stack_with_tid =
+      StringPrintf("[stack:%d]", PlatformThread::CurrentId());
+
   for (size_t i = 0; i < regions.size(); ++i) {
     if (regions[i].path == exe_path.value()) {
       // It's OK to find the executable mapped multiple times as there'll be
@@ -204,17 +213,23 @@
       found_exe = true;
     }
 
+    bool is_correct_stack = false;
     if (regions[i].path == "[stack]") {
-      // Only check if |address| lies within the real stack when not running
-      // Valgrind, otherwise |address| will be on a stack that Valgrind creates.
-      if (!RunningOnValgrind()) {
-        EXPECT_GE(address, regions[i].start);
-        EXPECT_LT(address, regions[i].end);
-      }
+      is_correct_stack = true;
+      EXPECT_FALSE(RunningOnValgrind());
+      EXPECT_GE(address, regions[i].start);
+      EXPECT_LT(address, regions[i].end);
+    } else if (regions[i].path == stack_with_tid) {
+      is_correct_stack = true;
+      EXPECT_TRUE(RunningOnValgrind());
+    }
 
+    if (is_correct_stack) {
+      // Note that the stack is executable when it is created by Valgrind.
       EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::READ);
       EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::WRITE);
-      EXPECT_FALSE(regions[i].permissions & MappedMemoryRegion::EXECUTE);
+      EXPECT_EQ(RunningOnValgrind(),
+                (regions[i].permissions & MappedMemoryRegion::EXECUTE) != 0);
       EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::PRIVATE);
       EXPECT_FALSE(found_stack) << "Found duplicate stacks";
       found_stack = true;
diff --git a/base/files/file_path.h b/base/files/file_path.h
index ad42b95..6890866 100644
--- a/base/files/file_path.h
+++ b/base/files/file_path.h
@@ -107,6 +107,7 @@
 #include <vector>
 
 #include "base/base_export.h"
+#include "base/compiler_specific.h"
 #include "base/containers/hash_tables.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_piece.h"  // For implicit conversions.
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index 95a16f2..6ee4e76 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/basictypes.h"
+#include "base/compiler_specific.h"
 #include "base/logging.h"
 
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/base/mac/scoped_mach_port.cc b/base/mac/scoped_mach_port.cc
index de94602..13307f2 100644
--- a/base/mac/scoped_mach_port.cc
+++ b/base/mac/scoped_mach_port.cc
@@ -25,6 +25,14 @@
       << "ScopedMachReceiveRight mach_port_mod_refs";
 }
 
+// static
+void PortSetTraits::Free(mach_port_t port) {
+  kern_return_t kr =
+      mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_PORT_SET, -1);
+  MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr)
+      << "ScopedMachPortSet mach_port_mod_refs";
+}
+
 }  // namespace internal
 }  // namespace mac
 }  // namespace base
diff --git a/base/mac/scoped_mach_port.h b/base/mac/scoped_mach_port.h
index 36087c9..9ef90d6 100644
--- a/base/mac/scoped_mach_port.h
+++ b/base/mac/scoped_mach_port.h
@@ -31,6 +31,14 @@
   static void Free(mach_port_t port);
 };
 
+struct PortSetTraits {
+  static mach_port_t InvalidValue() {
+    return MACH_PORT_NULL;
+  }
+
+  static void Free(mach_port_t port);
+};
+
 }  // namespace internal
 
 // A scoper for handling a Mach port that names a send right. Send rights are
@@ -59,6 +67,19 @@
   operator mach_port_t() const { return get(); }
 };
 
+// A scoper for handling a Mach port set. A port set can have only one
+// reference. This takes ownership of that single reference on construction and
+// destroys the port set on destruction. Destroying a port set does not destroy
+// the receive rights that are members of the port set.
+class BASE_EXPORT ScopedMachPortSet :
+    public ScopedGeneric<mach_port_t, internal::PortSetTraits> {
+ public:
+  explicit ScopedMachPortSet(mach_port_t port = traits_type::InvalidValue())
+      : ScopedGeneric(port) {}
+
+  operator mach_port_t() const { return get(); }
+};
+
 }  // namespace mac
 }  // namespace base
 
diff --git a/base/macros.h b/base/macros.h
index b6240da..15408bc 100644
--- a/base/macros.h
+++ b/base/macros.h
@@ -13,8 +13,6 @@
 #include <stddef.h>  // For size_t.
 #include <string.h>  // For memcpy.
 
-#include "base/compiler_specific.h"  // For ALLOW_UNUSED.
-
 // Put this in the private: declarations for a class to be uncopyable.
 #define DISALLOW_COPY(TypeName) \
   TypeName(const TypeName&)
diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc
index 62617c5..23c28d4 100644
--- a/base/metrics/statistics_recorder.cc
+++ b/base/metrics/statistics_recorder.cc
@@ -289,9 +289,8 @@
 void StatisticsRecorder::DumpHistogramsToVlog(void* instance) {
   DCHECK(VLOG_IS_ON(1));
 
-  StatisticsRecorder* me = reinterpret_cast<StatisticsRecorder*>(instance);
   string output;
-  me->WriteGraph(std::string(), &output);
+  StatisticsRecorder::WriteGraph(std::string(), &output);
   VLOG(1) << output;
 }
 
diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h
index 3eb3604..ca23ac8 100644
--- a/base/process/process_metrics.h
+++ b/base/process/process_metrics.h
@@ -234,7 +234,7 @@
 #if defined(OS_POSIX)
 // Returns the maximum number of file descriptors that can be open by a process
 // at once. If the number is unavailable, a conservative best guess is returned.
-size_t GetMaxFds();
+BASE_EXPORT size_t GetMaxFds();
 
 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard
 // limit, whichever is lower.
diff --git a/base/profiler/scoped_tracker.cc b/base/profiler/scoped_tracker.cc
index 26b17c0..d15b7de 100644
--- a/base/profiler/scoped_tracker.cc
+++ b/base/profiler/scoped_tracker.cc
@@ -12,13 +12,6 @@
 
 ScopedProfile::Mode g_scoped_profile_mode = ScopedProfile::DISABLED;
 
-// Executes |callback|, augmenting it with provided |location|.
-void ExecuteAndTrackCallback(const Location& location,
-                             const base::Closure& callback) {
-  ScopedProfile tracking_profile(location, ScopedProfile::ENABLED);
-  callback.Run();
-}
-
 }  // namespace
 
 // static
@@ -26,15 +19,6 @@
   g_scoped_profile_mode = ScopedProfile::ENABLED;
 }
 
-// static
-base::Closure ScopedTracker::TrackCallback(const Location& location,
-                                           const base::Closure& callback) {
-  if (g_scoped_profile_mode != ScopedProfile::ENABLED)
-    return callback;
-
-  return base::Bind(ExecuteAndTrackCallback, location, callback);
-}
-
 ScopedTracker::ScopedTracker(const Location& location)
     : scoped_profile_(location, g_scoped_profile_mode) {
 }
diff --git a/base/profiler/scoped_tracker.h b/base/profiler/scoped_tracker.h
index f83654e..23e2f07 100644
--- a/base/profiler/scoped_tracker.h
+++ b/base/profiler/scoped_tracker.h
@@ -10,6 +10,7 @@
 // found using profiler data.
 
 #include "base/base_export.h"
+#include "base/bind.h"
 #include "base/callback_forward.h"
 #include "base/location.h"
 #include "base/profiler/scoped_profile.h"
@@ -47,10 +48,24 @@
   // many possible callbacks, but they come from a relatively small number of
   // places. We can instrument these few places and at least know which one
   // passes the janky callback.
-  static base::Closure TrackCallback(const Location& location,
-                                     const base::Closure& callback);
+  template <typename P1>
+  static base::Callback<void(P1)> TrackCallback(
+      const Location& location,
+      const base::Callback<void(P1)>& callback) {
+    return base::Bind(&ScopedTracker::ExecuteAndTrackCallback<P1>, location,
+                      callback);
+  }
 
  private:
+  // Executes |callback|, augmenting it with provided |location|.
+  template <typename P1>
+  static void ExecuteAndTrackCallback(const Location& location,
+                                      const base::Callback<void(P1)>& callback,
+                                      P1 p1) {
+    ScopedTracker tracking_profile(location);
+    callback.Run(p1);
+  }
+
   const ScopedProfile scoped_profile_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedTracker);
diff --git a/base/security_unittest.cc b/base/security_unittest.cc
index a6d3480..d786273 100644
--- a/base/security_unittest.cc
+++ b/base/security_unittest.cc
@@ -194,7 +194,9 @@
   }
   // On windows, the compiler prevents static array sizes of more than
   // 0x7fffffff (error C2148).
-#if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
+#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
+  ALLOW_UNUSED_LOCAL(kDynamicArraySize);
+#else
   {
     scoped_ptr<char[][kArraySize2]> array_pointer(new (nothrow)
         char[kDynamicArraySize][kArraySize2]);
diff --git a/base/test/test_shortcut_win.cc b/base/test/test_shortcut_win.cc
index c772d87..eb074a3 100644
--- a/base/test/test_shortcut_win.cc
+++ b/base/test/test_shortcut_win.cc
@@ -67,7 +67,7 @@
   if (FAILED(hr))
     return;
 
-  EXPECT_TRUE(SUCCEEDED(hr = i_persist_file.QueryFrom(i_shell_link)));
+  EXPECT_TRUE(SUCCEEDED(hr = i_persist_file.QueryFrom(i_shell_link.get())));
   if (FAILED(hr))
     return;
 
@@ -112,7 +112,7 @@
 
   if (GetVersion() >= VERSION_WIN7) {
     ScopedComPtr<IPropertyStore> property_store;
-    EXPECT_TRUE(SUCCEEDED(hr = property_store.QueryFrom(i_shell_link)));
+    EXPECT_TRUE(SUCCEEDED(hr = property_store.QueryFrom(i_shell_link.get())));
     if (FAILED(hr))
       return;
 
diff --git a/base/tracked_objects.h b/base/tracked_objects.h
index 723fb91..eb38df6 100644
--- a/base/tracked_objects.h
+++ b/base/tracked_objects.h
@@ -43,7 +43,7 @@
 // computational cost is associated with obtaining start and stop times for
 // instances as they are created and destroyed.
 //
-// The following describes the lifecycle of tracking an instance.
+// The following describes the life cycle of tracking an instance.
 //
 // First off, when the instance is created, the FROM_HERE macro is expanded
 // to specify the birth place (file, line, function) where the instance was
@@ -96,9 +96,9 @@
 // lock such DeathData instances. (i.e., these accumulated stats in a DeathData
 // instance are exclusively updated by the singular owning thread).
 //
-// With the above lifecycle description complete, the major remaining detail is
-// explaining how each thread maintains a list of DeathData instances, and of
-// Births instances, and is able to avoid additional (redundant/unnecessary)
+// With the above life cycle description complete, the major remaining detail
+// is explaining how each thread maintains a list of DeathData instances, and
+// of Births instances, and is able to avoid additional (redundant/unnecessary)
 // allocations.
 //
 // Each thread maintains a list of data items specific to that thread in a
@@ -119,7 +119,7 @@
 // which ensures that any prior acquisition of the list is valid (i.e., the
 // holder can iterate over it without fear of it changing, or the necessity of
 // using an additional lock.  Iterations are actually pretty rare (used
-// primarilly for cleanup, or snapshotting data for display), so this lock has
+// primarily for cleanup, or snapshotting data for display), so this lock has
 // very little global performance impact.
 //
 // The above description tries to define the high performance (run time)
@@ -156,7 +156,7 @@
 // example, match with the number of durations we accumulated).  The advantage
 // to having fast (non-atomic) updates of the data outweighs the minimal risk of
 // a singular corrupt statistic snapshot (only the snapshot could be corrupt,
-// not the underlying and ongoing statistic).  In constrast, pointer data that
+// not the underlying and ongoing statistic).  In contrast, pointer data that
 // is accessed during snapshotting is completely invariant, and hence is
 // perfectly acquired (i.e., no potential corruption, and no risk of a bad
 // memory reference).
@@ -167,9 +167,9 @@
 // them will continue to be asynchronous).  We had an implementation of this in
 // the past, but the difficulty is dealing with message loops being terminated.
 // We can *try* to spam the available threads via some message loop proxy to
-// achieve this feat, and it *might* be valuable when we are colecting data for
-// upload via UMA (where correctness of data may be more significant than for a
-// single screen of about:profiler).
+// achieve this feat, and it *might* be valuable when we are collecting data
+// for upload via UMA (where correctness of data may be more significant than
+// for a single screen of about:profiler).
 //
 // TODO(jar): We should support (optionally) the recording of parent-child
 // relationships for tasks.  This should be done by detecting what tasks are
@@ -181,7 +181,7 @@
 // TODO(jar): We need to store DataCollections, and provide facilities for
 // taking the difference between two gathered DataCollections.  For now, we're
 // just adding a hack that Reset()s to zero all counts and stats.  This is also
-// done in a slighly thread-unsafe fashion, as the resetting is done
+// done in a slightly thread-unsafe fashion, as the resetting is done
 // asynchronously relative to ongoing updates (but all data is 32 bit in size).
 // For basic profiling, this will work "most of the time," and should be
 // sufficient... but storing away DataCollections is the "right way" to do this.
@@ -361,7 +361,7 @@
   enum Status {
     UNINITIALIZED,              // PRistine, link-time state before running.
     DORMANT_DURING_TESTS,       // Only used during testing.
-    DEACTIVATED,                // No longer recording profling.
+    DEACTIVATED,                // No longer recording profiling.
     PROFILING_ACTIVE,           // Recording profiles (no parent-child links).
     PROFILING_CHILDREN_ACTIVE,  // Fully active, recording parent-child links.
     STATUS_LAST = PROFILING_CHILDREN_ACTIVE
@@ -551,7 +551,7 @@
 
   // Using our lock, make a copy of the specified maps.  This call may be made
   // on  non-local threads, which necessitate the use of the lock to prevent
-  // the map(s) from being reallocaed while they are copied. If |reset_max| is
+  // the map(s) from being reallocated while they are copied. If |reset_max| is
   // true, then, just after we copy the DeathMap, we will set the max values to
   // zero in the active DeathMap (not the snapshot).
   void SnapshotMaps(bool reset_max,
@@ -593,7 +593,7 @@
   static base::ThreadLocalStorage::StaticSlot tls_index_;
 
   // List of ThreadData instances for use with worker threads. When a worker
-  // thread is done (terminated), we push it onto this llist.  When a new worker
+  // thread is done (terminated), we push it onto this list.  When a new worker
   // thread is created, we first try to re-use a ThreadData instance from the
   // list, and if none are available, construct a new one.
   // This is only accessed while list_lock_ is held.
@@ -676,7 +676,7 @@
   // not yet concluded with a NowForEndOfRun().  Usually this stack is one deep,
   // but if a scoped region is profiled, or <sigh> a task runs a nested-message
   // loop, then the stack can grow larger.  Note that we don't try to deduct
-  // time in nested porfiles, as our current timer is based on wall-clock time,
+  // time in nested profiles, as our current timer is based on wall-clock time,
   // and not CPU time (and we're hopeful that nested timing won't be a
   // significant additional cost).
   ParentStack parent_stack_;
diff --git a/base/win/shortcut.cc b/base/win/shortcut.cc
index eef299b..eb26cea 100644
--- a/base/win/shortcut.cc
+++ b/base/win/shortcut.cc
@@ -33,7 +33,7 @@
   i_persist_file->Release();
   if (FAILED(i_shell_link->CreateInstance(CLSID_ShellLink, NULL,
                                           CLSCTX_INPROC_SERVER)) ||
-      FAILED(i_persist_file->QueryFrom(*i_shell_link)) ||
+      FAILED(i_persist_file->QueryFrom(i_shell_link->get())) ||
       (shortcut && FAILED((*i_persist_file)->Load(shortcut, STGM_READWRITE)))) {
     i_shell_link->Release();
     i_persist_file->Release();
@@ -129,15 +129,17 @@
   if ((has_app_id || has_dual_mode) &&
       GetVersion() >= VERSION_WIN7) {
     ScopedComPtr<IPropertyStore> property_store;
-    if (FAILED(property_store.QueryFrom(i_shell_link)) || !property_store.get())
+    if (FAILED(property_store.QueryFrom(i_shell_link.get())) ||
+        !property_store.get())
       return false;
 
     if (has_app_id &&
-        !SetAppIdForPropertyStore(property_store, properties.app_id.c_str())) {
+        !SetAppIdForPropertyStore(property_store.get(),
+                                  properties.app_id.c_str())) {
       return false;
     }
     if (has_dual_mode &&
-        !SetBooleanValueForPropertyStore(property_store,
+        !SetBooleanValueForPropertyStore(property_store.get(),
                                          PKEY_AppUserModel_IsDualMode,
                                          properties.dual_mode)) {
       return false;
@@ -192,7 +194,7 @@
 
   ScopedComPtr<IPersistFile> persist;
   // Query IShellLink for the IPersistFile interface.
-  if (FAILED(persist.QueryFrom(i_shell_link)))
+  if (FAILED(persist.QueryFrom(i_shell_link.get())))
     return false;
 
   // Load the shell link.
@@ -239,7 +241,7 @@
   if ((options & ShortcutProperties::PROPERTIES_WIN7) &&
       GetVersion() >= VERSION_WIN7) {
     ScopedComPtr<IPropertyStore> property_store;
-    if (FAILED(property_store.QueryFrom(i_shell_link)))
+    if (FAILED(property_store.QueryFrom(i_shell_link.get())))
       return false;
 
     if (options & ShortcutProperties::PROPERTIES_APP_ID) {
diff --git a/build/all.gyp b/build/all.gyp
index c3443f9..5fe54d7 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -42,13 +42,13 @@
             # NOTE: This list of targets is present because
             # mojo_base.gyp:mojo_base cannot be built on iOS, as
             # javascript-related targets cause v8 to be built.
-            '../mojo/edk/mojo_edk.gyp:mojo_public_bindings_unittests',
-            '../mojo/edk/mojo_edk.gyp:mojo_public_environment_unittests',
-            '../mojo/edk/mojo_edk.gyp:mojo_public_system_perftests',
-            '../mojo/edk/mojo_edk.gyp:mojo_public_system_unittests',
-            '../mojo/edk/mojo_edk.gyp:mojo_public_utility_unittests',
+            '../mojo/edk/mojo_edk_tests.gyp:mojo_public_bindings_unittests',
+            '../mojo/edk/mojo_edk_tests.gyp:mojo_public_environment_unittests',
+            '../mojo/edk/mojo_edk_tests.gyp:mojo_public_system_perftests',
+            '../mojo/edk/mojo_edk_tests.gyp:mojo_public_system_unittests',
+            '../mojo/edk/mojo_edk_tests.gyp:mojo_public_utility_unittests',
             '../mojo/edk/mojo_edk.gyp:mojo_system_impl',
-            '../mojo/edk/mojo_edk.gyp:mojo_system_unittests',
+            '../mojo/edk/mojo_edk_tests.gyp:mojo_system_unittests',
             '../mojo/mojo_base.gyp:mojo_common_lib',
             '../mojo/mojo_base.gyp:mojo_common_unittests',
             '../mojo/public/mojo_public.gyp:mojo_cpp_bindings',
@@ -405,6 +405,11 @@
             }],
           ],
         }],
+        ['chromeos==1', {
+          'dependencies': [
+            '../ui/chromeos/ui_chromeos.gyp:ui_chromeos_unittests',
+          ],
+        }],
         ['OS=="linux"', {
           'dependencies': [
             '../dbus/dbus.gyp:dbus_unittests',
@@ -738,6 +743,11 @@
                 '../skia/tools/clusterfuzz-data/fuzzers/filter_fuzzer/filter_fuzzer.gyp:filter_fuzzer',
               ],
             }], # internal_filter_fuzzer
+            ['clang==1', {
+              'dependencies': [
+                'sanitizers/sanitizers.gyp:llvm-symbolizer',
+              ],
+            }],
             ['OS=="win" and fastbuild==0 and target_arch=="ia32" and syzyasan==1', {
               'dependencies': [
                 '../chrome/chrome_syzygy.gyp:chrome_dll_syzygy',
@@ -856,6 +866,7 @@
             ['enable_webrtc==1 and "<(libpeer_target_type)"=="static_library"', {
               'dependencies': [
                 '../components/devtools_bridge.gyp:devtools_bridge_tests_apk',
+                '../components/devtools_bridge.gyp:libdevtools_bridge_browsertests',
               ],
             }],
           ],
@@ -871,6 +882,7 @@
             '../tools/android/android_tools.gyp:memconsumer',
             # Unit test bundles packaged as an apk.
             '../components/devtools_bridge.gyp:devtools_bridge_tests_apk',
+            '../components/devtools_bridge.gyp:libdevtools_bridge_browsertests',
             '../content/content_shell_and_tests.gyp:content_browsertests_apk',
           ],
         },  # target_name: android_builder_chromium_webrtc
@@ -1294,8 +1306,9 @@
             }],
             ['chromeos==1', {
               'dependencies': [
-                '../chromeos/chromeos.gyp:chromeos_unittests',
                 '../athena/main/athena_main.gyp:*',
+                '../chromeos/chromeos.gyp:chromeos_unittests',
+                '../ui/chromeos/ui_chromeos.gyp:ui_chromeos_unittests',
               ],
             }],
             ['use_ozone==1', {
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index bb57e54..f226b37 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -64,6 +64,7 @@
           J('pylib', 'device', 'device_utils_test.py'),
           J('pylib', 'gtest', 'test_package_test.py'),
           J('pylib', 'instrumentation', 'test_runner_test.py'),
+          J('pylib', 'utils', 'md5sum_test.py'),
       ],
       env=pylib_test_env))
   output.extend(_CheckDeletionsOnlyFiles(input_api, output_api))
diff --git a/build/android/adb_logcat_monitor.py b/build/android/adb_logcat_monitor.py
index a5ae785..d3cc67d 100755
--- a/build/android/adb_logcat_monitor.py
+++ b/build/android/adb_logcat_monitor.py
@@ -83,7 +83,7 @@
                                 stderr=subprocess.PIPE).communicate()
     if err:
       logging.warning('adb device error %s', err.strip())
-    return re.findall('^(\S+)\tdevice$', out, re.MULTILINE)
+    return re.findall('^(\\S+)\tdevice$', out, re.MULTILINE)
   except TimeoutException:
     logging.warning('"adb devices" command timed out')
     return []
@@ -136,7 +136,7 @@
       time.sleep(5)
   except SigtermError:
     logging.info('Received SIGTERM, shutting down')
-  except:
+  except: # pylint: disable=bare-except
     logging.exception('Unexpected exception in main.')
   finally:
     for process, _ in devices.itervalues():
diff --git a/build/android/adb_reverse_forwarder.py b/build/android/adb_reverse_forwarder.py
index c1d9551..1958fdd 100755
--- a/build/android/adb_reverse_forwarder.py
+++ b/build/android/adb_reverse_forwarder.py
@@ -61,7 +61,7 @@
   else:
     if not devices:
       raise Exception('Error: no connected devices')
-    print("No device specified. Defaulting to " + devices[0])
+    print "No device specified. Defaulting to " + devices[0]
 
   device = device_utils.DeviceUtils(devices[0])
   constants.SetBuildType(options.build_type)
diff --git a/build/android/avd.py b/build/android/avd.py
index ddff11a..c45544f 100755
--- a/build/android/avd.py
+++ b/build/android/avd.py
@@ -70,8 +70,8 @@
     android = os.path.join(constants.EMULATOR_SDK_ROOT, 'sdk', 'tools',
                            'android')
     avds_output = cmd_helper.GetCmdOutput([android, 'list', 'avd'])
-    names = re.findall('Name: (\w+)', avds_output)
-    api_levels = re.findall('API level (\d+)', avds_output)
+    names = re.findall(r'Name: (\w+)', avds_output)
+    api_levels = re.findall(r'API level (\d+)', avds_output)
     try:
       avd_index = names.index(options.name)
     except ValueError:
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py
index d98c1dd..a72a0c7 100755
--- a/build/android/buildbot/bb_device_status_check.py
+++ b/build/android/buildbot/bb_device_status_check.py
@@ -57,7 +57,7 @@
     battery_info = {}
     logging.error('Unable to obtain battery info for %s, %s', serial, e)
 
-  def _GetData(re_expression, line, lambda_function=lambda x:x):
+  def _GetData(re_expression, line, lambda_function=lambda x: x):
     if not line:
       return 'Unknown'
     found = re.findall(re_expression, line)
@@ -66,7 +66,7 @@
     return 'Unknown'
 
   battery_level = int(battery_info.get('level', 100))
-  imei_slice = _GetData('Device ID = (\d+)',
+  imei_slice = _GetData(r'Device ID = (\d+)',
                         device_adb.old_interface.GetSubscriberInfo(),
                         lambda x: x[-6:])
   report = ['Device %s (%s)' % (serial, device_type),
@@ -151,7 +151,7 @@
       os.environ.get('BUILDBOT_BUILDERNAME'),
       os.environ.get('BUILDBOT_BUILDNUMBER'))
     msg = ('Please reboot the following devices:\n%s' %
-           '\n'.join(map(str,new_missing_devs)))
+           '\n'.join(map(str, new_missing_devs)))
     SendEmail(from_address, to_addresses, cc_addresses, subject, msg)
 
   all_known_devices = list(set(adb_online_devs) | set(last_devices))
@@ -216,10 +216,10 @@
   lsusb_proc = bb_utils.SpawnCmd(['lsusb'], stdout=subprocess.PIPE)
   lsusb_output, _ = lsusb_proc.communicate()
   if lsusb_proc.returncode:
-    print ('Error: Could not get list of USB ports (i.e. lsusb).')
+    print 'Error: Could not get list of USB ports (i.e. lsusb).'
     return lsusb_proc.returncode
 
-  usb_devices = [re.findall('Bus (\d\d\d) Device (\d\d\d)', lsusb_line)[0]
+  usb_devices = [re.findall(r'Bus (\d\d\d) Device (\d\d\d)', lsusb_line)[0]
                  for lsusb_line in lsusb_output.strip().split('\n')]
 
   all_restarted = True
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index 530512a..3142b23 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -81,8 +81,8 @@
     ])
 
 VALID_TESTS = set(['chromedriver', 'chrome_proxy', 'gpu',
-                   'telemetry_perf_unittests', 'ui', 'unit', 'webkit',
-                   'webkit_layout', 'python_unittests'])
+                   'telemetry_unittests', 'telemetry_perf_unittests', 'ui',
+                   'unit', 'webkit', 'webkit_layout', 'python_unittests'])
 
 RunCmd = bb_utils.RunCmd
 
@@ -190,19 +190,23 @@
   RunCmd(['tools/chrome_proxy/run_tests'] + args)
 
 
-def RunTelemetryPerfUnitTests(options):
-  """Runs the telemetry perf unit tests.
+def RunTelemetryTests(options, step_name, run_tests_path):
+  """Runs either telemetry_perf_unittests or telemetry_unittests.
 
   Args:
     options: options object.
+    step_name: either 'telemetry_unittests' or 'telemetry_perf_unittests'
+    run_tests_path: path to run_tests script (tools/perf/run_tests for
+                    perf_unittests and tools/telemetry/run_tests for
+                    telemetry_unittests)
   """
   InstallApk(options, INSTRUMENTATION_TESTS['ChromeShell'], False)
   args = ['--browser', 'android-chrome-shell']
   devices = android_commands.GetAttachedDevices()
   if devices:
     args = args + ['--device', devices[0]]
-  bb_annotations.PrintNamedStep('telemetry_perf_unittests')
-  RunCmd(['tools/perf/run_tests'] + args)
+  bb_annotations.PrintNamedStep(step_name)
+  RunCmd([run_tests_path] + args)
 
 
 def InstallApk(options, test, print_step=False):
@@ -472,6 +476,14 @@
   RunTestSuites(options, suites)
 
 
+def RunTelemetryUnitTests(options):
+  RunTelemetryTests(options, 'telemetry_unittests', 'tools/telemetry/run_tests')
+
+
+def RunTelemetryPerfUnitTests(options):
+  RunTelemetryTests(options, 'telemetry_perf_unittests', 'tools/perf/run_tests')
+
+
 def RunInstrumentationTests(options):
   for test in INSTRUMENTATION_TESTS.itervalues():
     RunInstrumentationSuite(options, test)
@@ -529,6 +541,7 @@
       ('chrome_proxy', RunChromeProxyTests),
       ('gpu', RunGPUTests),
       ('python_unittests', RunPythonUnitTests),
+      ('telemetry_unittests', RunTelemetryUnitTests),
       ('telemetry_perf_unittests', RunTelemetryPerfUnitTests),
       ('ui', RunInstrumentationTests),
       ('unit', RunUnitTests),
@@ -582,7 +595,7 @@
   # Print logcat, kill logcat monitor
   bb_annotations.PrintNamedStep('logcat_dump')
   logcat_file = os.path.join(CHROME_OUT_DIR, options.target, 'full_log.txt')
-  RunCmd([SrcPath('build' , 'android', 'adb_logcat_printer.py'),
+  RunCmd([SrcPath('build', 'android', 'adb_logcat_printer.py'),
           '--output-path', logcat_file, LOGCAT_DIR])
   gs_path = MakeGSPath(options, 'chromium-android/logcat_dumps')
   RunCmd([bb_utils.GSUTIL_PATH, 'cp', '-z', 'txt', logcat_file,
@@ -693,9 +706,9 @@
       '--chrome-output-dir',
       help='Chrome output directory to be used while bisecting.')
 
-  parser.add_option('--disable-stack-tool',  action='store_true',
+  parser.add_option('--disable-stack-tool', action='store_true',
       help='Do not run stack tool.')
-  parser.add_option('--asan-symbolize',  action='store_true',
+  parser.add_option('--asan-symbolize', action='store_true',
       help='Run stack tool for ASAN')
   parser.add_option('--cleanup', action='store_true',
       help='Delete out/<target> directory at the end of the run.')
diff --git a/build/android/buildbot/bb_run_bot.py b/build/android/buildbot/bb_run_bot.py
index 8c853e7..abdd2be 100755
--- a/build/android/buildbot/bb_run_bot.py
+++ b/build/android/buildbot/bb_run_bot.py
@@ -132,10 +132,10 @@
       os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir,
                    os.pardir, 'bisect', 'src', 'out'))
   B = BotConfig
-  H = (lambda steps, extra_args=None, extra_gyp=None, target_arch=None :
+  H = (lambda steps, extra_args=None, extra_gyp=None, target_arch=None:
        HostConfig('build/android/buildbot/bb_host_steps.py', steps, extra_args,
                   extra_gyp, target_arch))
-  T = (lambda tests, extra_args=None :
+  T = (lambda tests, extra_args=None:
        TestConfig('build/android/buildbot/bb_device_steps.py', tests,
                   extra_args))
 
@@ -150,7 +150,7 @@
         T(std_tests + telemetry_tests + chrome_proxy_tests,
           ['--cleanup', flakiness_server])),
       B('main-tests', H(std_test_steps),
-        T(std_tests,['--cleanup', flakiness_server])),
+        T(std_tests, ['--cleanup', flakiness_server])),
 
       # Other waterfalls
       B('asan-builder-tests', H(compile_step,
@@ -167,7 +167,7 @@
           extra_gyp='emma_coverage=1')),
       B('x86-builder-dbg',
         H(compile_step + std_host_tests, target_arch='ia32')),
-      B('fyi-builder-rel', H(std_build_steps,  experimental)),
+      B('fyi-builder-rel', H(std_build_steps, experimental)),
       B('fyi-tests', H(std_test_steps),
         T(std_tests + python_unittests,
                       ['--experimental', flakiness_server,
@@ -234,7 +234,7 @@
 def GetBestMatch(id_map, id):
   config = id_map.get(id)
   if not config:
-    substring_matches = filter(lambda x: x in id, id_map.iterkeys())
+    substring_matches = [x for x in id_map.iterkeys() if x in id]
     if substring_matches:
       max_id = max(substring_matches, key=len)
       print 'Using config from id="%s" (substring match).' % max_id
diff --git a/build/android/envsetup.sh b/build/android/envsetup.sh
index 26960ac..0545330 100755
--- a/build/android/envsetup.sh
+++ b/build/android/envsetup.sh
@@ -43,6 +43,9 @@
   # Add Android SDK tools to system path.
   export PATH=$PATH:${ANDROID_SDK_ROOT}/platform-tools
 
+  # Add Android utility tools to the system path.
+  export PATH=$PATH:${ANDROID_SDK_ROOT}/tools/
+
   # Add Chromium Android development scripts to system path.
   # Must be after CHROME_SRC is set.
   export PATH=$PATH:${CHROME_SRC}/build/android
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index d26e6d3..ed68e6c 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -78,6 +78,8 @@
       help='Whether this library supports running on the Android platform.')
   parser.add_option('--requires-android', action='store_true',
       help='Whether this library requires running on the Android platform.')
+  parser.add_option('--bypass-platform-checks', action='store_true',
+      help='Bypass checks for support/require Android platform.')
 
   # android library options
   parser.add_option('--dex-path', help='Path to target\'s dex output.')
@@ -149,14 +151,14 @@
   deps_info = config['deps_info']
 
 
-  if options.type == 'java_library':
+  if options.type == 'java_library' and not options.bypass_platform_checks:
     deps_info['requires_android'] = options.requires_android
     deps_info['supports_android'] = options.supports_android
 
     deps_require_android = (all_resources_deps +
-        [d['name'] for d in direct_library_deps if d['requires_android']])
+        [d['name'] for d in all_library_deps if d['requires_android']])
     deps_not_support_android = (
-        [d['name'] for d in direct_library_deps if not d['supports_android']])
+        [d['name'] for d in all_library_deps if not d['supports_android']])
 
     if deps_require_android and not options.requires_android:
       raise Exception('Some deps require building for the Android platform: ' +
diff --git a/build/android/install_emulator_deps.py b/build/android/install_emulator_deps.py
index d980c2c..82d1c75 100755
--- a/build/android/install_emulator_deps.py
+++ b/build/android/install_emulator_deps.py
@@ -30,7 +30,7 @@
 SDK_BASE_URL = 'http://dl.google.com/android/adt'
 SDK_ZIP = 'adt-bundle-linux-x86_64-20131030.zip'
 
-# pylint: disable=C0301
+# pylint: disable=line-too-long
 # Android x86 system image from the Intel website:
 # http://software.intel.com/en-us/articles/intel-eula-x86-android-4-2-jelly-bean-bin
 # These don't exist prior to Android-15.
@@ -41,7 +41,7 @@
   17: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-17_r01.zip',
   18: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-18_r01.zip',
   19: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-19_r01.zip'}
-#pylint: enable=C0301
+#pylint: enable=line-too-long
 
 def CheckSDK():
   """Check if SDK is already installed.
@@ -194,8 +194,8 @@
   """
   android_binary = os.path.join(constants.EMULATOR_SDK_ROOT,
                                 'sdk', 'tools', 'android')
-  pattern = re.compile('\s*([0-9]+)- SDK Platform Android [\.,0-9]+, API %d.*' %
-                       api_level)
+  pattern = re.compile(
+      r'\s*([0-9]+)- SDK Platform Android [\.,0-9]+, API %d.*' % api_level)
   # Example:
   #   2- SDK Platform Android 4.3, API 18, revision 2
   exit_code, stdout = cmd_helper.GetCmdStatusAndOutput(
@@ -206,7 +206,7 @@
     match = pattern.match(line)
     if match:
       index = match.group(1)
-      print('package %s corresponds to platform level %d' % (index, api_level))
+      print 'package %s corresponds to platform level %d' % (index, api_level)
       # update sdk --no-ui --filter $INDEX
       update_command = [android_binary,
                         'update', 'sdk', '--no-ui', '--filter', index]
@@ -218,7 +218,7 @@
         raise Exception('License agreement check failed')
       update_process.sendline('y')
       if update_process.expect('Done. 1 package installed.') == 0:
-        print('Successfully installed platform for API level %d' % api_level)
+        print 'Successfully installed platform for API level %d' % api_level
         return
       else:
         raise Exception('Failed to install platform update')
@@ -238,7 +238,7 @@
   # run_tests_helper will set logging to INFO or DEBUG
   # We achieve verbose output by configuring it with 2 (==DEBUG)
   verbosity = 1
-  if (options.verbose):
+  if options.verbose:
     verbosity = 2
   logging.basicConfig(level=logging.INFO,
                       format='# %(asctime)-15s: %(message)s')
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py
index 560d1d0..0dc8c81 100755
--- a/build/android/provision_devices.py
+++ b/build/android/provision_devices.py
@@ -31,12 +31,12 @@
 import errors
 
 def KillHostHeartbeat():
-  ps = subprocess.Popen(['ps', 'aux'], stdout = subprocess.PIPE)
+  ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   stdout, _ = ps.communicate()
   matches = re.findall('\\n.*host_heartbeat.*', stdout)
   for match in matches:
     logging.info('An instance of host heart beart running... will kill')
-    pid = re.findall('(\S+)', match)[1]
+    pid = re.findall(r'(\S+)', match)[1]
     subprocess.call(['kill', str(pid)])
 
 
@@ -190,8 +190,9 @@
                      battery_info.get('level', 0))
         time.sleep(60)
         battery_info = device.old_interface.GetBatteryInfo()
-    # TODO(jbudorick): Tune the timeout per OS version.
-    device.Reboot(True, timeout=600, retries=0)
+    if not options.skip_wipe:
+      # TODO(jbudorick): Tune the timeout per OS version.
+      device.Reboot(True, timeout=600, retries=0)
     device.RunShellCommand('date -s %s' % time.strftime('%Y%m%d.%H%M%S',
                                                         time.gmtime()),
                            as_root=True)
@@ -206,7 +207,7 @@
                  str(device))
     # Device black list is reset by bb_device_status_check.py per build.
     device_blacklist.ExtendBlacklist([str(device)])
-  except (device_errors.CommandFailedError):
+  except device_errors.CommandFailedError:
     logging.exception('Failed to provision device %s. Adding to blacklist.',
                       str(device))
     device_blacklist.ExtendBlacklist([str(device)])
diff --git a/build/android/pylib/android_commands.py b/build/android/pylib/android_commands.py
index 6981afc..8d7866d 100644
--- a/build/android/pylib/android_commands.py
+++ b/build/android/pylib/android_commands.py
@@ -6,7 +6,7 @@
 
 Assumes adb binary is currently on system path.
 """
-# pylint: disable-all
+# pylint: skip-file
 
 import collections
 import datetime
@@ -314,11 +314,7 @@
       device: If given, adb commands are only send to the device of this ID.
           Otherwise commands are sent to all attached devices.
     """
-    adb_dir = os.path.dirname(constants.GetAdbPath())
-    if adb_dir and adb_dir not in os.environ['PATH'].split(os.pathsep):
-      # Required by third_party/android_testrunner to call directly 'adb'.
-      os.environ['PATH'] += os.pathsep + adb_dir
-    self._adb = adb_interface.AdbInterface()
+    self._adb = adb_interface.AdbInterface(constants.GetAdbPath())
     if device:
       self._adb.SetTargetSerial(device)
     self._device = device
diff --git a/build/android/pylib/base/base_setup.py b/build/android/pylib/base/base_setup.py
new file mode 100644
index 0000000..c276822
--- /dev/null
+++ b/build/android/pylib/base/base_setup.py
@@ -0,0 +1,62 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Base script for doing test setup."""
+
+import logging
+import os
+
+from pylib import constants
+from pylib import valgrind_tools
+from pylib.utils import isolator
+
+def GenerateDepsDirUsingIsolate(suite_name, isolate_file_path,
+                                isolate_file_paths, deps_exclusion_list):
+  """Generate the dependency dir for the test suite using isolate.
+
+  Args:
+    suite_name: Name of the test suite (e.g. base_unittests).
+    isolate_file_path: .isolate file path to use. If there is a default .isolate
+                       file path for the suite_name, this will override it.
+    isolate_file_paths: Dictionary with the default .isolate file paths for
+                        the test suites.
+    deps_exclusion_list: A list of files that are listed as dependencies in the
+                         .isolate files but should not be pushed to the device.
+  """
+  if isolate_file_path:
+    if os.path.isabs(isolate_file_path):
+      isolate_abs_path = isolate_file_path
+    else:
+      isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT,
+                                      isolate_file_path)
+  else:
+    isolate_rel_path = isolate_file_paths.get(suite_name)
+    if not isolate_rel_path:
+      logging.info('Did not find an isolate file for the test suite.')
+      return
+    isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT, isolate_rel_path)
+
+  isolated_abs_path = os.path.join(
+      constants.GetOutDirectory(), '%s.isolated' % suite_name)
+  assert os.path.exists(isolate_abs_path), 'Cannot find %s' % isolate_abs_path
+
+  i = isolator.Isolator(constants.ISOLATE_DEPS_DIR)
+  i.Clear()
+  i.Remap(isolate_abs_path, isolated_abs_path)
+  # We're relying on the fact that timestamps are preserved
+  # by the remap command (hardlinked). Otherwise, all the data
+  # will be pushed to the device once we move to using time diff
+  # instead of md5sum. Perform a sanity check here.
+  i.VerifyHardlinks()
+  i.PurgeExcluded(deps_exclusion_list)
+  i.MoveOutputDeps()
+
+
+def PushDataDeps(device, device_dir, test_options):
+  valgrind_tools.PushFilesForTool(test_options.tool, device)
+  if os.path.exists(constants.ISOLATE_DEPS_DIR):
+    device.PushChangedFiles([
+        (os.path.join(constants.ISOLATE_DEPS_DIR, p),
+         '%s/%s' % (device_dir, p))
+        for p in os.listdir(constants.ISOLATE_DEPS_DIR)])
diff --git a/build/android/pylib/base/base_test_result.py b/build/android/pylib/base/base_test_result.py
index f9e61a9..f55be02 100644
--- a/build/android/pylib/base/base_test_result.py
+++ b/build/android/pylib/base/base_test_result.py
@@ -203,5 +203,5 @@
 
   def DidRunPass(self):
     """Return whether the test run was successful."""
-    return not (self.GetNotPass() - self.GetSkip())
+    return not self.GetNotPass() - self.GetSkip()
 
diff --git a/build/android/pylib/base/base_test_runner.py b/build/android/pylib/base/base_test_runner.py
index 6e51b43..4e2eae7 100644
--- a/build/android/pylib/base/base_test_runner.py
+++ b/build/android/pylib/base/base_test_runner.py
@@ -70,14 +70,9 @@
     """Installs the test package once before all tests are run."""
     pass
 
-  def PushDataDeps(self):
-    """Push all data deps to device once before all tests are run."""
-    pass
-
   def SetUp(self):
     """Run once before all tests are run."""
     self.InstallTestPackage()
-    self.PushDataDeps()
 
   def TearDown(self):
     """Run once after all tests are run."""
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py
index 29da601..e89a298 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants.py
@@ -187,6 +187,7 @@
     'path': os.path.join(DIR_SOURCE_ROOT, 'build', 'android'),
     'test_modules': [
       'pylib.device.device_utils_test',
+      'pylib.utils.md5sum_test',
     ]
   },
   'gyp_py_unittests': {
@@ -246,8 +247,21 @@
   return Wrapper
 
 
-@_Memoize
+def SetAdbPath(adb_path):
+  os.environ['ADB_PATH'] = adb_path
+
+
 def GetAdbPath():
+  # Check if a custom adb path as been set. If not, try to find adb
+  # on the system.
+  if os.environ.get('ADB_PATH'):
+    return os.environ.get('ADB_PATH')
+  else:
+    return _FindAdbPath()
+
+
+@_Memoize
+def _FindAdbPath():
   if os.environ.get('ANDROID_SDK_ROOT'):
     return 'adb'
   # If envsetup.sh hasn't been sourced and there's no adb in the path,
@@ -260,7 +274,6 @@
     logging.debug('No adb found in $PATH, fallback to checked in binary.')
     return os.path.join(ANDROID_SDK_ROOT, 'platform-tools', 'adb')
 
-
 # Exit codes
 ERROR_EXIT_CODE = 1
 WARNING_EXIT_CODE = 88
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
index e7a8418..c7ea310 100644
--- a/build/android/pylib/device/adb_wrapper.py
+++ b/build/android/pylib/device/adb_wrapper.py
@@ -12,6 +12,7 @@
 import os
 
 from pylib import cmd_helper
+from pylib import constants
 from pylib.device import decorators
 from pylib.device import device_errors
 from pylib.utils import timeout_retry
@@ -45,11 +46,11 @@
     """
     self._device_serial = str(device_serial)
 
-  # pylint: disable=W0613
+  # pylint: disable=unused-argument
   @classmethod
   @decorators.WithTimeoutAndRetries
   def _RunAdbCmd(cls, arg_list, timeout=None, retries=None, check_error=True):
-    cmd = ['adb'] + arg_list
+    cmd = [constants.GetAdbPath()] + arg_list
     exit_code, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
       cmd, timeout_retry.CurrentTimeoutThread().GetRemainingTime())
     if exit_code != 0:
@@ -62,7 +63,7 @@
     if check_error and output[:len('error:')] == 'error:':
       raise device_errors.AdbCommandFailedError(arg_list, output)
     return output
-  # pylint: enable=W0613
+  # pylint: enable=unused-argument
 
   def _DeviceAdbCmd(self, arg_list, timeout, retries, check_error=True):
     """Runs an adb command on the device associated with this object.
diff --git a/build/android/pylib/device/commands/install_commands.py b/build/android/pylib/device/commands/install_commands.py
index 35b11e3..58c56cc 100644
--- a/build/android/pylib/device/commands/install_commands.py
+++ b/build/android/pylib/device/commands/install_commands.py
@@ -41,7 +41,7 @@
     shell_command = _SHELL_COMMAND_FORMAT % (
         constants.TEST_EXECUTABLE_DIR, main_class)
     shell_file = '%s/%s' % (BIN_DIR, command)
-    device.WriteTextFile(shell_file, shell_command)
+    device.WriteFile(shell_file, shell_command)
     device.RunShellCommand(
         ['chmod', '755', shell_file], check_return=True)
 
diff --git a/build/android/pylib/device/decorators_test.py b/build/android/pylib/device/decorators_test.py
index 1ae8cb9..b75618b 100644
--- a/build/android/pylib/device/decorators_test.py
+++ b/build/android/pylib/device/decorators_test.py
@@ -280,7 +280,7 @@
       self.function_call_counters['alwaysRaisesCommandFailedError'] += 1
       raise device_errors.CommandFailedError('testCommand failed')
 
-    # pylint: disable=R0201
+    # pylint: disable=no-self-use
 
     @decorators.WithTimeoutAndRetriesFromInstance(
         'default_timeout', 'default_retries')
@@ -298,7 +298,7 @@
                                       retries=None):
       raise exception
 
-    # pylint: enable=R0201
+    # pylint: enable=no-self-use
 
 
   def testMethodDecoratorDoesTimeout(self):
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index 334b74c..845d580 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -24,7 +24,9 @@
 from pylib.device import device_errors
 from pylib.device.commands import install_commands
 from pylib.utils import apk_helper
+from pylib.utils import device_temp_file
 from pylib.utils import host_utils
+from pylib.utils import md5sum
 from pylib.utils import parallelizer
 from pylib.utils import timeout_retry
 
@@ -92,8 +94,8 @@
     self._default_timeout = default_timeout
     self._default_retries = default_retries
     self._cache = {}
-    assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR))
-    assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR))
+    assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)
+    assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR)
 
   @decorators.WithTimeoutAndRetriesFromInstance()
   def IsOnline(self, timeout=None, retries=None):
@@ -429,13 +431,14 @@
 
     if not isinstance(cmd, basestring):
       cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd)
-    if as_root and self.NeedsSU():
-      cmd = 'su -c %s' % cmd
     if env:
       env = ' '.join(env_quote(k, v) for k, v in env.iteritems())
       cmd = '%s %s' % (env, cmd)
     if cwd:
       cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd)
+    if as_root and self.NeedsSU():
+      # "su -c sh -c" allows using shell features in |cmd|
+      cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd)
     if timeout is None:
       timeout = self._default_timeout
 
@@ -699,12 +702,13 @@
     if not real_device_path:
       return [(host_path, device_path)]
 
-    # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base
-    # this function on mtime.
-    # pylint: disable=W0212
-    host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum(
-        real_host_path, real_device_path)
-    # pylint: enable=W0212
+    host_hash_tuples = md5sum.CalculateHostMd5Sums([real_host_path])
+    device_paths_to_md5 = (
+        real_device_path if os.path.isfile(real_host_path)
+        else ('%s/%s' % (real_device_path, os.path.relpath(p, real_host_path))
+              for _, p in host_hash_tuples))
+    device_hash_tuples = md5sum.CalculateDeviceMd5Sums(
+        device_paths_to_md5, self)
 
     if os.path.isfile(host_path):
       if (not device_hash_tuples
@@ -765,7 +769,7 @@
     else:
       zip_time = 0
       transfer_time = byte_count / TRANSFER_RATE
-    return (adb_call_time + adb_push_setup_time + zip_time + transfer_time)
+    return adb_call_time + adb_push_setup_time + zip_time + transfer_time
 
   def _PushChangedFilesIndividually(self, files):
     for h, d in files:
@@ -882,16 +886,19 @@
       return self.old_interface.GetFileContents(device_path)
 
   @decorators.WithTimeoutAndRetriesFromInstance()
-  def WriteFile(self, device_path, contents, as_root=False, timeout=None,
-                retries=None):
+  def WriteFile(self, device_path, contents, as_root=False, force_push=False,
+                timeout=None, retries=None):
     """Writes |contents| to a file on the device.
 
     Args:
       device_path: A string containing the absolute path to the file to write
-                   on the device.
+          on the device.
       contents: A string containing the data to write to the device.
       as_root: A boolean indicating whether the write should be executed with
-               root privileges.
+          root privileges (if available).
+      force_push: A boolean indicating whether to force the operation to be
+          performed by pushing a file to the device. The default is, when the
+          contents are short, to pass the contents using a shell script instead.
       timeout: timeout in seconds
       retries: number of retries
 
@@ -900,39 +907,24 @@
       CommandTimeoutError on timeout.
       DeviceUnreachableError on missing device.
     """
-    if as_root:
-      if not self.old_interface.CanAccessProtectedFileContents():
-        raise device_errors.CommandFailedError(
-            'Cannot write to %s with root privileges.' % device_path)
-      self.old_interface.SetProtectedFileContents(device_path, contents)
+    if len(contents) < 512 and not force_push:
+      cmd = 'echo -n %s > %s' % (cmd_helper.SingleQuote(contents),
+                                 cmd_helper.SingleQuote(device_path))
+      self.RunShellCommand(cmd, as_root=as_root, check_return=True)
     else:
-      self.old_interface.SetFileContents(device_path, contents)
-
-  @decorators.WithTimeoutAndRetriesFromInstance()
-  def WriteTextFile(self, device_path, text, as_root=False, timeout=None,
-                    retries=None):
-    """Writes |text| to a file on the device.
-
-    Assuming that |text| is a small string, this is typically more efficient
-    than |WriteFile|, as no files are pushed into the device.
-
-    Args:
-      device_path: A string containing the absolute path to the file to write
-                   on the device.
-      text: A short string of text to write to the file on the device.
-      as_root: A boolean indicating whether the write should be executed with
-               root privileges.
-      timeout: timeout in seconds
-      retries: number of retries
-
-    Raises:
-      CommandFailedError if the file could not be written on the device.
-      CommandTimeoutError on timeout.
-      DeviceUnreachableError on missing device.
-    """
-    cmd = 'echo %s > %s' % (cmd_helper.SingleQuote(text),
-                            cmd_helper.SingleQuote(device_path))
-    self.RunShellCommand(cmd, as_root=as_root, check_return=True)
+      with tempfile.NamedTemporaryFile() as host_temp:
+        host_temp.write(contents)
+        host_temp.flush()
+        if as_root and self.NeedsSU():
+          with device_temp_file.DeviceTempFile(self) as device_temp:
+            self.adb.Push(host_temp.name, device_temp.name)
+            # Here we need 'cp' rather than 'mv' because the temp and
+            # destination files might be on different file systems (e.g.
+            # on internal storage and an external sd card)
+            self.RunShellCommand(['cp', device_temp.name, device_path],
+                                 as_root=True, check_return=True)
+        else:
+          self.adb.Push(host_temp.name, device_path)
 
   @decorators.WithTimeoutAndRetriesFromInstance()
   def Ls(self, device_path, timeout=None, retries=None):
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 65547d4..8d78b2d 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -67,6 +67,19 @@
     self.assertIsNone(d.old_interface.GetDevice())
 
 
+class MockTempFile(object):
+
+  def __init__(self, name='/tmp/some/file'):
+    self.file = mock.MagicMock(spec=file)
+    self.file.name = name
+
+  def __enter__(self):
+    return self.file
+
+  def __exit__(self, exc_type, exc_val, exc_tb):
+    pass
+
+
 class _PatchedFunction(object):
   def __init__(self, patched=None, mocked=None):
     self.patched = patched
@@ -215,9 +228,14 @@
     return type(self).AndroidCommandsCalls(self, cmd_ret, comp)
 
   def setUp(self):
+    self._get_adb_path_patch = mock.patch('pylib.constants.GetAdbPath',
+                                          mock.Mock(return_value='adb'))
+    self._get_adb_path_patch.start()
     self.device = device_utils.DeviceUtils(
         '0123456789abcdef', default_timeout=1, default_retries=0)
 
+  def tearDown(self):
+    self._get_adb_path_patch.stop()
 
 class DeviceUtilsNewImplTest(mock_calls.TestCase):
 
@@ -497,9 +515,6 @@
     def mockGetFilesChanged(host_path, device_path, ignore_filenames):
       return [(host_path, device_path)]
 
-    # Pylint raises a false positive "operator not preceded by a space"
-    # warning below.
-    # pylint: disable=C0322
     with mock.patch('os.path.isfile', return_value=True), (
          mock.patch('os.path.exists', return_value=True)), (
          mock.patch('pylib.utils.apk_helper.GetPackageName',
@@ -508,7 +523,6 @@
                     return_value='/fake/test/out')), (
          mock.patch('pylib.android_commands.AndroidCommands.GetFilesChanged',
                     side_effect=mockGetFilesChanged)):
-    # pylint: enable=C0322
       with self.assertCallsSequence([
           ("adb -s 0123456789abcdef shell 'pm path this.is.a.test.package'",
            'package:/fake/data/app/this.is.a.test.package.apk\r\n'),
@@ -523,9 +537,6 @@
     def mockGetFilesChanged(host_path, device_path, ignore_filenames):
       return [(host_path, device_path)]
 
-    # Pylint raises a false positive "operator not preceded by a space"
-    # warning below.
-    # pylint: disable=C0322
     with mock.patch('os.path.isfile', return_value=True), (
          mock.patch('pylib.utils.apk_helper.GetPackageName',
                     return_value='this.is.a.test.package')), (
@@ -533,7 +544,6 @@
                     return_value='/fake/test/out')), (
          mock.patch('pylib.android_commands.AndroidCommands.GetFilesChanged',
                     side_effect=mockGetFilesChanged)):
-    # pylint: enable=C0322
       with self.assertCallsSequence([
           ("adb -s 0123456789abcdef shell 'pm path this.is.a.test.package'",
            'package:/fake/data/app/this.is.a.test.package.apk\r\n'),
@@ -614,7 +624,7 @@
   def testRunShellCommand_withSu(self):
     with self.assertCalls(
         (self.call.device.NeedsSU(), True),
-        (self.call.adb.Shell('su -c setprop service.adb.root 0'), '')):
+        (self.call.adb.Shell("su -c sh -c 'setprop service.adb.root 0'"), '')):
       self.device.RunShellCommand('setprop service.adb.root 0', as_root=True)
 
   def testRunShellCommand_manyLines(self):
@@ -714,7 +724,7 @@
          'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
          'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
         (self.call.device.NeedsSU(), True),
-        (self.call.adb.Shell('su -c kill -9 1234'), '')):
+        (self.call.adb.Shell("su -c sh -c 'kill -9 1234'"), '')):
       self.assertEquals(1,
           self.device.KillAll('some.process', as_root=True))
 
@@ -1190,134 +1200,67 @@
                            as_root=True)
 
 
-class DeviceUtilsWriteFileTest(DeviceUtilsOldImplTest):
+class DeviceUtilsWriteFileTest(DeviceUtilsNewImplTest):
 
-  def testWriteFile_basic(self):
-    mock_file = mock.MagicMock(spec=file)
-    mock_file.name = '/tmp/file/to.be.pushed'
-    mock_file.__enter__.return_value = mock_file
-    with mock.patch('tempfile.NamedTemporaryFile',
-                    return_value=mock_file):
-      with self.assertCalls(
-          'adb -s 0123456789abcdef push '
-              '/tmp/file/to.be.pushed /test/file/written.to.device',
-          '100 B/s (100 bytes in 1.000s)\r\n'):
-        self.device.WriteFile('/test/file/written.to.device',
-                              'new test file contents')
-    mock_file.write.assert_called_once_with('new test file contents')
+  def testWriteFile_withPush(self):
+    tmp_host = MockTempFile('/tmp/file/on.host')
+    contents = 'some large contents ' * 26 # 20 * 26 = 520 chars
+    with self.assertCalls(
+        (mock.call.tempfile.NamedTemporaryFile(), tmp_host),
+        self.call.adb.Push('/tmp/file/on.host', '/path/to/device/file')):
+      self.device.WriteFile('/path/to/device/file', contents)
+      tmp_host.file.write.assert_called_once_with(contents)
 
-  def testWriteFile_asRoot_withRoot(self):
-    self.device.old_interface._external_storage = '/fake/storage/path'
-    self.device.old_interface._privileged_command_runner = (
-        self.device.old_interface.RunShellCommand)
-    self.device.old_interface._protected_file_access_method_initialized = True
+  def testWriteFile_withPushForced(self):
+    tmp_host = MockTempFile('/tmp/file/on.host')
+    contents = 'tiny contents'
+    with self.assertCalls(
+        (mock.call.tempfile.NamedTemporaryFile(), tmp_host),
+        self.call.adb.Push('/tmp/file/on.host', '/path/to/device/file')):
+      self.device.WriteFile('/path/to/device/file', contents, force_push=True)
+      tmp_host.file.write.assert_called_once_with(contents)
 
-    mock_file = mock.MagicMock(spec=file)
-    mock_file.name = '/tmp/file/to.be.pushed'
-    mock_file.__enter__.return_value = mock_file
-    with mock.patch('tempfile.NamedTemporaryFile',
-                    return_value=mock_file):
-      with self.assertCallsSequence(
-          cmd_ret=[
-              # Create temporary contents file
-              (r"adb -s 0123456789abcdef shell "
-                  "'test -e \"/fake/storage/path/temp_file-\d+-\d+\"; "
-                  "echo \$\?'",
-               '1\r\n'),
-              # Create temporary script file
-              (r"adb -s 0123456789abcdef shell "
-                  "'test -e \"/fake/storage/path/temp_file-\d+-\d+\.sh\"; "
-                  "echo \$\?'",
-               '1\r\n'),
-              # Set contents file
-              (r'adb -s 0123456789abcdef push /tmp/file/to\.be\.pushed '
-                  '/fake/storage/path/temp_file-\d+\d+',
-               '100 B/s (100 bytes in 1.000s)\r\n'),
-              # Set script file
-              (r'adb -s 0123456789abcdef push /tmp/file/to\.be\.pushed '
-                  '/fake/storage/path/temp_file-\d+\d+',
-               '100 B/s (100 bytes in 1.000s)\r\n'),
-              # Call script
-              (r"adb -s 0123456789abcdef shell "
-                  "'sh /fake/storage/path/temp_file-\d+-\d+\.sh'", ''),
-              # Remove device temporaries
-              (r"adb -s 0123456789abcdef shell "
-                  "'rm /fake/storage/path/temp_file-\d+-\d+\.sh'", ''),
-              (r"adb -s 0123456789abcdef shell "
-                  "'rm /fake/storage/path/temp_file-\d+-\d+'", '')],
-          comp=re.match):
-        self.device.WriteFile('/test/file/written.to.device',
-                              'new test file contents', as_root=True)
+  def testWriteFile_withPushAndSU(self):
+    tmp_host = MockTempFile('/tmp/file/on.host')
+    contents = 'some large contents ' * 26 # 20 * 26 = 520 chars
+    with self.assertCalls(
+        (mock.call.tempfile.NamedTemporaryFile(), tmp_host),
+        (self.call.device.NeedsSU(), True),
+        (mock.call.pylib.utils.device_temp_file.DeviceTempFile(self.device),
+         MockTempFile('/external/path/tmp/on.device')),
+        self.call.adb.Push('/tmp/file/on.host', '/external/path/tmp/on.device'),
+        self.call.device.RunShellCommand(
+            ['cp', '/external/path/tmp/on.device', '/path/to/device/file'],
+            as_root=True, check_return=True)):
+      self.device.WriteFile('/path/to/device/file', contents, as_root=True)
+      tmp_host.file.write.assert_called_once_with(contents)
 
-  def testWriteFile_asRoot_withSu(self):
-    self.device.old_interface._external_storage = '/fake/storage/path'
-    self.device.old_interface._privileged_command_runner = (
-        self.device.old_interface.RunShellCommandWithSU)
-    self.device.old_interface._protected_file_access_method_initialized = True
+  def testWriteFile_withPush_rejected(self):
+    tmp_host = MockTempFile('/tmp/file/on.host')
+    contents = 'some large contents ' * 26 # 20 * 26 = 520 chars
+    with self.assertCalls(
+        (mock.call.tempfile.NamedTemporaryFile(), tmp_host),
+        (self.call.adb.Push('/tmp/file/on.host', '/path/to/device/file'),
+         self.CommandError())):
+      with self.assertRaises(device_errors.CommandFailedError):
+        self.device.WriteFile('/path/to/device/file', contents)
 
-    mock_file = mock.MagicMock(spec=file)
-    mock_file.name = '/tmp/file/to.be.pushed'
-    mock_file.__enter__.return_value = mock_file
-    with mock.patch('tempfile.NamedTemporaryFile',
-                    return_value=mock_file):
-      with self.assertCallsSequence(
-          cmd_ret=[
-              # Create temporary contents file
-              (r"adb -s 0123456789abcdef shell "
-                  "'test -e \"/fake/storage/path/temp_file-\d+-\d+\"; "
-                  "echo \$\?'",
-               '1\r\n'),
-              # Create temporary script file
-              (r"adb -s 0123456789abcdef shell "
-                  "'test -e \"/fake/storage/path/temp_file-\d+-\d+\.sh\"; "
-                  "echo \$\?'",
-               '1\r\n'),
-              # Set contents file
-              (r'adb -s 0123456789abcdef push /tmp/file/to\.be\.pushed '
-                  '/fake/storage/path/temp_file-\d+\d+',
-               '100 B/s (100 bytes in 1.000s)\r\n'),
-              # Set script file
-              (r'adb -s 0123456789abcdef push /tmp/file/to\.be\.pushed '
-                  '/fake/storage/path/temp_file-\d+\d+',
-               '100 B/s (100 bytes in 1.000s)\r\n'),
-              # Call script
-              (r"adb -s 0123456789abcdef shell "
-                  "'su -c sh /fake/storage/path/temp_file-\d+-\d+\.sh'", ''),
-              # Remove device temporaries
-              (r"adb -s 0123456789abcdef shell "
-                  "'rm /fake/storage/path/temp_file-\d+-\d+\.sh'", ''),
-              (r"adb -s 0123456789abcdef shell "
-                  "'rm /fake/storage/path/temp_file-\d+-\d+'", '')],
-          comp=re.match):
-        self.device.WriteFile('/test/file/written.to.device',
-                              'new test file contents', as_root=True)
+  def testWriteFile_withEcho(self):
+    with self.assertCall(self.call.adb.Shell(
+        "echo -n the.contents > /test/file/to.write"), ''):
+      self.device.WriteFile('/test/file/to.write', 'the.contents')
 
-  def testWriteFile_asRoot_rejected(self):
-    self.device.old_interface._privileged_command_runner = None
-    self.device.old_interface._protected_file_access_method_initialized = True
-    with self.assertRaises(device_errors.CommandFailedError):
-      self.device.WriteFile('/test/file/no.permissions.to.write',
-                            'new test file contents', as_root=True)
+  def testWriteFile_withEchoAndQuotes(self):
+    with self.assertCall(self.call.adb.Shell(
+        "echo -n 'the contents' > '/test/file/to write'"), ''):
+      self.device.WriteFile('/test/file/to write', 'the contents')
 
-
-class DeviceUtilsWriteTextFileTest(DeviceUtilsNewImplTest):
-
-  def testWriteTextFileTest_basic(self):
-    with self.assertCall(
-        self.call.adb.Shell('echo some.string > /test/file/to.write'), ''):
-      self.device.WriteTextFile('/test/file/to.write', 'some.string')
-
-  def testWriteTextFileTest_quoted(self):
-    with self.assertCall(
-        self.call.adb.Shell("echo 'some other string' > '/test/file/to write'"),
-        ''):
-      self.device.WriteTextFile('/test/file/to write', 'some other string')
-
-  def testWriteTextFileTest_withSU(self):
+  def testWriteFile_withEchoAndSU(self):
     with self.assertCalls(
         (self.call.device.NeedsSU(), True),
-        (self.call.adb.Shell('su -c echo string > /test/file'), '')):
-      self.device.WriteTextFile('/test/file', 'string', as_root=True)
+        (self.call.adb.Shell("su -c sh -c 'echo -n contents > /test/file'"),
+         '')):
+      self.device.WriteFile('/test/file', 'contents', as_root=True)
 
 
 class DeviceUtilsLsTest(DeviceUtilsOldImplTest):
diff --git a/build/android/pylib/device_settings.py b/build/android/pylib/device_settings.py
index 4050694..0580fcf 100644
--- a/build/android/pylib/device_settings.py
+++ b/build/android/pylib/device_settings.py
@@ -8,6 +8,8 @@
 from pylib import content_settings
 
 _LOCK_SCREEN_SETTINGS_PATH = '/data/system/locksettings.db'
+_ALTERNATE_LOCK_SCREEN_SETTINGS_PATH = (
+    '/data/data/com.android.providers.settings/databases/settings.db')
 PASSWORD_QUALITY_UNSPECIFIED = '0'
 
 
@@ -66,16 +68,26 @@
   Raises:
     Exception if the setting was not properly set.
   """
-  if (not device.old_interface.FileExistsOnDevice(_LOCK_SCREEN_SETTINGS_PATH) or
-      device.GetProp('ro.build.type') != 'userdebug'):
+  if device.GetProp('ro.build.type') != 'userdebug':
+    logging.warning('Unable to disable lockscreen on user builds.')
     return
 
-  db = _LOCK_SCREEN_SETTINGS_PATH
-  locksettings = [('locksettings', 'lockscreen.disabled', '1'),
-                  ('locksettings', 'lockscreen.password_type',
-                   PASSWORD_QUALITY_UNSPECIFIED),
-                  ('locksettings', 'lockscreen.password_type_alternate',
-                   PASSWORD_QUALITY_UNSPECIFIED)]
+  def get_lock_settings(table):
+    return [(table, 'lockscreen.disabled', '1'),
+            (table, 'lockscreen.password_type', PASSWORD_QUALITY_UNSPECIFIED),
+            (table, 'lockscreen.password_type_alternate',
+             PASSWORD_QUALITY_UNSPECIFIED)]
+
+  if device.FileExists(_LOCK_SCREEN_SETTINGS_PATH):
+    db = _LOCK_SCREEN_SETTINGS_PATH
+    locksettings = get_lock_settings('locksettings')
+  elif device.FileExists(_ALTERNATE_LOCK_SCREEN_SETTINGS_PATH):
+    db = _ALTERNATE_LOCK_SCREEN_SETTINGS_PATH
+    locksettings = get_lock_settings('secure') + get_lock_settings('system')
+  else:
+    logging.warning('Unable to find database file to set lock screen settings.')
+    return
+
   for table, key, value in locksettings:
     # Set the lockscreen setting for default user '0'
     columns = ['name', 'user', 'value']
@@ -91,9 +103,10 @@
       'columns': ', '.join(columns),
       'values': ', '.join(["'%s'" % value for value in values])
     }
-    output_msg = device.RunShellCommand('sqlite3 %s "%s"' % (db, cmd))
+    output_msg = device.RunShellCommand('sqlite3 %s "%s"' % (db, cmd),
+                                        as_root=True)
     if output_msg:
-      print ' '.join(output_msg)
+      logging.info(' '.join(output_msg))
 
 
 ENABLE_LOCATION_SETTINGS = [
diff --git a/build/android/pylib/gtest/filter/net_unittests_disabled b/build/android/pylib/gtest/filter/net_unittests_disabled
index 28e1db1..2632e7c 100644
--- a/build/android/pylib/gtest/filter/net_unittests_disabled
+++ b/build/android/pylib/gtest/filter/net_unittests_disabled
@@ -7,7 +7,6 @@
 SSLServerSocketTest.Handshake
 
 PythonUtils.PythonRunTime
-URLRequestTestHTTP.HTTPSToHTTPRedirectNoRefererTest
 VerifyEndEntity/CertVerifyProcWeakDigestTest.Verify/0
 VerifyEndEntity/CertVerifyProcWeakDigestTest.Verify/1
 VerifyEndEntity/CertVerifyProcWeakDigestTest.Verify/2
@@ -26,6 +25,13 @@
 VerifyRoot/CertVerifyProcWeakDigestTest.Verify/0
 VerifyRoot/CertVerifyProcWeakDigestTest.Verify/1
 VerifyRoot/CertVerifyProcWeakDigestTest.Verify/2
+
+# Can't spin up more than one SpawnedTestServer on Android.
+URLRequestTestReferrerPolicy.HTTPToCrossOriginHTTP
+URLRequestTestReferrerPolicy.HTTPSToCrossOriginHTTPS
+URLRequestTestReferrerPolicy.HTTPToHTTPS
+URLRequestTestReferrerPolicy.HTTPSToHTTP
+
 # Fail only on bots.
 HttpCache.RangeGET_Cancel
 HttpCache.RangeGET_Cancel2
diff --git a/build/android/pylib/gtest/gtest_config.py b/build/android/pylib/gtest/gtest_config.py
index e671e0a..0cb8b35 100644
--- a/build/android/pylib/gtest/gtest_config.py
+++ b/build/android/pylib/gtest/gtest_config.py
@@ -11,6 +11,10 @@
     'devtools_bridge_tests',
 ]
 
+TELEMETRY_EXPERIMENTAL_TEST_SUITES = [
+    'telemetry_unittests',
+]
+
 # Do not modify this list without approval of an android owner.
 # This list determines which suites are run by default, both for local
 # testing and on android trybots running on commit-queue.
diff --git a/build/android/pylib/gtest/setup.py b/build/android/pylib/gtest/setup.py
index e3df9c7..72c4b05 100644
--- a/build/android/pylib/gtest/setup.py
+++ b/build/android/pylib/gtest/setup.py
@@ -10,15 +10,14 @@
 import sys
 
 from pylib import constants
-from pylib import valgrind_tools
 
+from pylib.base import base_setup
 from pylib.base import base_test_result
 from pylib.base import test_dispatcher
 from pylib.device import device_utils
 from pylib.gtest import test_package_apk
 from pylib.gtest import test_package_exe
 from pylib.gtest import test_runner
-from pylib.utils import isolator
 
 sys.path.insert(0,
                 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib',
@@ -26,7 +25,7 @@
 import unittest_util # pylint: disable=F0401
 
 
-_ISOLATE_FILE_PATHS = {
+ISOLATE_FILE_PATHS = {
     'base_unittests': 'base/base_unittests.isolate',
     'blink_heap_unittests':
       'third_party/WebKit/Source/platform/heap/BlinkHeapUnitTests.isolate',
@@ -48,7 +47,7 @@
 # Used for filtering large data deps at a finer grain than what's allowed in
 # isolate files since pushing deps to devices is expensive.
 # Wildcards are allowed.
-_DEPS_EXCLUSION_LIST = [
+DEPS_EXCLUSION_LIST = [
     'chrome/test/data/extensions/api_test',
     'chrome/test/data/extensions/secure_shell',
     'chrome/test/data/firefox*',
@@ -68,43 +67,6 @@
 ]
 
 
-def _GenerateDepsDirUsingIsolate(suite_name, isolate_file_path=None):
-  """Generate the dependency dir for the test suite using isolate.
-
-  Args:
-    suite_name: Name of the test suite (e.g. base_unittests).
-    isolate_file_path: .isolate file path to use. If there is a default .isolate
-                       file path for the suite_name, this will override it.
-  """
-  if isolate_file_path:
-    if os.path.isabs(isolate_file_path):
-      isolate_abs_path = isolate_file_path
-    else:
-      isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT,
-                                      isolate_file_path)
-  else:
-    isolate_rel_path = _ISOLATE_FILE_PATHS.get(suite_name)
-    if not isolate_rel_path:
-      logging.info('Did not find an isolate file for the test suite.')
-      return
-    isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT, isolate_rel_path)
-
-  isolated_abs_path = os.path.join(
-      constants.GetOutDirectory(), '%s.isolated' % suite_name)
-  assert os.path.exists(isolate_abs_path), 'Cannot find %s' % isolate_abs_path
-
-  i = isolator.Isolator(constants.ISOLATE_DEPS_DIR)
-  i.Clear()
-  i.Remap(isolate_abs_path, isolated_abs_path)
-  # We're relying on the fact that timestamps are preserved
-  # by the remap command (hardlinked). Otherwise, all the data
-  # will be pushed to the device once we move to using time diff
-  # instead of md5sum. Perform a sanity check here.
-  i.VerifyHardlinks()
-  i.PurgeExcluded(_DEPS_EXCLUSION_LIST)
-  i.MoveOutputDeps()
-
-
 def _GetDisabledTestsFilterFromFile(suite_name):
   """Returns a gtest filter based on the *_disabled file.
 
@@ -218,19 +180,6 @@
   return tests
 
 
-def PushDataDeps(device, test_options, test_package):
-  valgrind_tools.PushFilesForTool(test_options.tool, device)
-  if os.path.exists(constants.ISOLATE_DEPS_DIR):
-    device_dir = (
-        constants.TEST_EXECUTABLE_DIR
-        if test_package.suite_name == 'breakpad_unittests'
-        else device.GetExternalStoragePath())
-    device.PushChangedFiles([
-        (os.path.join(constants.ISOLATE_DEPS_DIR, p),
-         '%s/%s' % (device_dir, p))
-        for p in os.listdir(constants.ISOLATE_DEPS_DIR)])
-
-
 def Setup(test_options, devices):
   """Create the test runner factory and tests.
 
@@ -255,11 +204,16 @@
     test_package = exe_test_package
   logging.warning('Found target %s', test_package.suite_path)
 
-  _GenerateDepsDirUsingIsolate(test_options.suite_name,
-                               test_options.isolate_file_path)
-
-  device_utils.DeviceUtils.parallel(devices).pMap(
-      PushDataDeps, test_options, test_package)
+  base_setup.GenerateDepsDirUsingIsolate(test_options.suite_name,
+                                         test_options.isolate_file_path,
+                                         ISOLATE_FILE_PATHS,
+                                         DEPS_EXCLUSION_LIST)
+  def push_data_deps_to_device_dir(device):
+    device_dir = (constants.TEST_EXECUTABLE_DIR
+        if test_package.suite_name == 'breakpad_unittests'
+        else device.GetExternalStoragePath())
+    base_setup.PushDataDeps(device, device_dir, test_options)
+  device_utils.DeviceUtils.parallel(devices).pMap(push_data_deps_to_device_dir)
 
   tests = _GetTests(test_options, test_package, devices)
 
diff --git a/build/android/pylib/gtest/test_runner.py b/build/android/pylib/gtest/test_runner.py
index 66feea6..fa38c4f 100644
--- a/build/android/pylib/gtest/test_runner.py
+++ b/build/android/pylib/gtest/test_runner.py
@@ -78,16 +78,16 @@
     results = base_test_result.TestRunResults()
 
     # Test case statuses.
-    re_run = re.compile('\[ RUN      \] ?(.*)\r\n')
-    re_fail = re.compile('\[  FAILED  \] ?(.*?)( \((\d+) ms\))?\r\r\n')
-    re_ok = re.compile('\[       OK \] ?(.*?)( \((\d+) ms\))?\r\r\n')
+    re_run = re.compile('\\[ RUN      \\] ?(.*)\r\n')
+    re_fail = re.compile('\\[  FAILED  \\] ?(.*?)( \\((\\d+) ms\\))?\r\r\n')
+    re_ok = re.compile('\\[       OK \\] ?(.*?)( \\((\\d+) ms\\))?\r\r\n')
 
     # Test run statuses.
-    re_passed = re.compile('\[  PASSED  \] ?(.*)\r\n')
-    re_runner_fail = re.compile('\[ RUNNER_FAILED \] ?(.*)\r\n')
+    re_passed = re.compile('\\[  PASSED  \\] ?(.*)\r\n')
+    re_runner_fail = re.compile('\\[ RUNNER_FAILED \\] ?(.*)\r\n')
     # Signal handlers are installed before starting tests
     # to output the CRASHED marker when a crash happens.
-    re_crash = re.compile('\[ CRASHED      \](.*)\r\n')
+    re_crash = re.compile('\\[ CRASHED      \\](.*)\r\n')
 
     log = ''
     try:
diff --git a/build/android/pylib/instrumentation/setup.py b/build/android/pylib/instrumentation/setup.py
index 57286e2..8dacc3d 100644
--- a/build/android/pylib/instrumentation/setup.py
+++ b/build/android/pylib/instrumentation/setup.py
@@ -7,11 +7,63 @@
 import logging
 import os
 
+from pylib import constants
+from pylib import valgrind_tools
+
+from pylib.base import base_setup
+from pylib.device import device_utils
 from pylib.instrumentation import test_package
 from pylib.instrumentation import test_runner
 
+DEVICE_DATA_DIR = 'chrome/test/data'
 
-def Setup(test_options):
+ISOLATE_FILE_PATHS = {
+    'AndroidWebViewTest': 'android_webview/android_webview_test_apk.isolate',
+    'ChromeShellTest': 'chrome/chrome_shell_test_apk.isolate',
+    'ContentShellTest': 'content/content_shell_test_apk.isolate',
+}
+
+DEPS_EXCLUSION_LIST = []
+
+# TODO(mikecase): Remove this function and the constant DEVICE_DATA_DIR
+# once all data deps are pushed to the same location on the device.
+def _PushExtraSuiteDataDeps(device, test_apk):
+  """Pushes some extra data files/dirs needed by some test suite.
+
+  Args:
+    test_apk: The test suite basename for which to return file paths.
+  """
+  if test_apk in ['ChromeTest', 'ContentShellTest']:
+    test_files = 'net/data/ssl/certificates'
+    host_device_file_tuple = [
+        (os.path.join(constants.DIR_SOURCE_ROOT, test_files),
+         os.path.join(device.GetExternalStoragePath(), test_files))]
+    device.PushChangedFiles(host_device_file_tuple)
+
+
+# TODO(mikecase): Remove this function once everything uses
+# base_setup.PushDataDeps to push data deps to the device.
+def _PushDataDeps(device, test_options):
+  valgrind_tools.PushFilesForTool(test_options.tool, device)
+
+  host_device_file_tuples = []
+  for dest_host_pair in test_options.test_data:
+    dst_src = dest_host_pair.split(':', 1)
+    dst_layer = dst_src[0]
+    host_src = dst_src[1]
+    host_test_files_path = os.path.join(constants.DIR_SOURCE_ROOT, host_src)
+    if os.path.exists(host_test_files_path):
+      host_device_file_tuples += [(
+          host_test_files_path,
+          '%s/%s/%s' % (
+              device.GetExternalStoragePath(),
+              DEVICE_DATA_DIR,
+              dst_layer))]
+  if host_device_file_tuples:
+    device.PushChangedFiles(host_device_file_tuples)
+
+
+def Setup(test_options, devices):
   """Create and return the test runner factory and tests.
 
   Args:
@@ -34,6 +86,24 @@
   if not tests:
     logging.error('No instrumentation tests to run with current args.')
 
+  if test_options.test_data:
+    device_utils.DeviceUtils.parallel(devices).pMap(
+        _PushDataDeps, test_options)
+  else:
+    base_setup.GenerateDepsDirUsingIsolate(test_options.test_apk,
+                                           test_options.isolate_file_path,
+                                           ISOLATE_FILE_PATHS,
+                                           DEPS_EXCLUSION_LIST)
+    def push_data_deps_to_device_dir(device):
+      device_dir = os.path.join(device.GetExternalStoragePath(),
+                                DEVICE_DATA_DIR)
+      base_setup.PushDataDeps(device, device_dir, test_options)
+    device_utils.DeviceUtils.parallel(devices).pMap(
+        push_data_deps_to_device_dir)
+
+  device_utils.DeviceUtils.parallel(devices).pMap(
+      _PushExtraSuiteDataDeps, test_options.test_apk)
+
   def TestRunnerFactory(device, shard_index):
     return test_runner.TestRunner(test_options, device, shard_index,
                                   test_pkg)
diff --git a/build/android/pylib/instrumentation/test_jar.py b/build/android/pylib/instrumentation/test_jar.py
index 7b97e59..4473810 100644
--- a/build/android/pylib/instrumentation/test_jar.py
+++ b/build/android/pylib/instrumentation/test_jar.py
@@ -14,6 +14,7 @@
 from pylib import cmd_helper
 from pylib import constants
 from pylib.device import device_utils
+from pylib.utils import md5sum
 from pylib.utils import proguard
 
 sys.path.insert(0,
@@ -55,16 +56,6 @@
     if not self._GetCachedProguardData():
       self._GetProguardData()
 
-  @staticmethod
-  def _CalculateMd5(path):
-    # TODO(jbudorick): Move MD5sum calculations out of here and
-    # AndroidCommands to their own module.
-    out = cmd_helper.GetCmdOutput(
-        [os.path.join(constants.GetOutDirectory(),
-                      'md5sum_bin_host'),
-        path])
-    return out
-
   def _GetCachedProguardData(self):
     if (os.path.exists(self._pickled_proguard_name) and
         (os.path.getmtime(self._pickled_proguard_name) >
@@ -74,7 +65,7 @@
       try:
         with open(self._pickled_proguard_name, 'r') as r:
           d = pickle.loads(r.read())
-        jar_md5 = self._CalculateMd5(self._jar_path)
+        jar_md5 = md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash
         if (d['JAR_MD5SUM'] == jar_md5 and
             d['VERSION'] == PICKLE_FORMAT_VERSION):
           self._test_methods = d['TEST_METHODS']
@@ -114,7 +105,7 @@
     logging.info('Storing proguard output to %s', self._pickled_proguard_name)
     d = {'VERSION': PICKLE_FORMAT_VERSION,
          'TEST_METHODS': self._test_methods,
-         'JAR_MD5SUM': self._CalculateMd5(self._jar_path)}
+         'JAR_MD5SUM': md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash}
     with open(self._pickled_proguard_name, 'w') as f:
       f.write(pickle.dumps(d))
 
@@ -228,9 +219,8 @@
         int(v) for v in
         device_utils.DeviceUtils.parallel().GetProp(
             'ro.build.version.sdk').pGet(None)]
-    tests = filter(
-        lambda t: self._IsTestValidForSdkRange(t, min(sdk_versions)),
-        tests)
+    tests = [t for t in tests
+             if self._IsTestValidForSdkRange(t, min(sdk_versions))]
 
     return tests
 
diff --git a/build/android/pylib/instrumentation/test_options.py b/build/android/pylib/instrumentation/test_options.py
index d6a56de..639ca86 100644
--- a/build/android/pylib/instrumentation/test_options.py
+++ b/build/android/pylib/instrumentation/test_options.py
@@ -22,4 +22,5 @@
     'test_apk_jar_path',
     'test_runner',
     'test_support_apk_path',
-    'device_flags'])
+    'device_flags',
+    'isolate_file_path'])
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py
index f2808da..92d80f97 100644
--- a/build/android/pylib/instrumentation/test_runner.py
+++ b/build/android/pylib/instrumentation/test_runner.py
@@ -27,32 +27,13 @@
 _PERF_TEST_ANNOTATION = 'PerfTest'
 
 
-def _GetDataFilesForTestSuite(suite_basename):
-  """Returns a list of data files/dirs needed by the test suite.
-
-  Args:
-    suite_basename: The test suite basename for which to return file paths.
-
-  Returns:
-    A list of test file and directory paths.
-  """
-  test_files = []
-  if suite_basename in ['ChromeTest', 'ContentShellTest']:
-    test_files += [
-        'net/data/ssl/certificates/',
-    ]
-  return test_files
-
-
 class TestRunner(base_test_runner.BaseTestRunner):
   """Responsible for running a series of tests connected to a single device."""
 
-  _DEVICE_DATA_DIR = 'chrome/test/data'
   _DEVICE_COVERAGE_DIR = 'chrome/test/coverage'
   _HOSTMACHINE_PERF_OUTPUT_FILE = '/tmp/chrome-profile'
   _DEVICE_PERF_OUTPUT_SEARCH_PREFIX = (constants.DEVICE_PERF_OUTPUT_DIR +
                                        '/chrome-profile*')
-  _DEVICE_HAS_TEST_FILES = {}
 
   def __init__(self, test_options, device, shard_index, test_pkg,
                additional_flags=None):
@@ -89,45 +70,6 @@
   def InstallTestPackage(self):
     self.test_pkg.Install(self.device)
 
-  #override
-  def PushDataDeps(self):
-    # TODO(frankf): Implement a general approach for copying/installing
-    # once across test runners.
-    if TestRunner._DEVICE_HAS_TEST_FILES.get(self.device, False):
-      logging.warning('Already copied test files to device %s, skipping.',
-                      str(self.device))
-      return
-
-    host_device_file_tuples = []
-    test_data = _GetDataFilesForTestSuite(self.test_pkg.GetApkName())
-    if test_data:
-      # Make sure SD card is ready.
-      self.device.WaitUntilFullyBooted(timeout=20)
-      host_device_file_tuples += [
-          (os.path.join(constants.DIR_SOURCE_ROOT, p),
-           os.path.join(self.device.GetExternalStoragePath(), p))
-          for p in test_data]
-
-    # TODO(frankf): Specify test data in this file as opposed to passing
-    # as command-line.
-    for dest_host_pair in self.options.test_data:
-      dst_src = dest_host_pair.split(':', 1)
-      dst_layer = dst_src[0]
-      host_src = dst_src[1]
-      host_test_files_path = os.path.join(constants.DIR_SOURCE_ROOT,
-                                          host_src)
-      if os.path.exists(host_test_files_path):
-        host_device_file_tuples += [(
-            host_test_files_path,
-            '%s/%s/%s' % (
-                self.device.GetExternalStoragePath(),
-                TestRunner._DEVICE_DATA_DIR,
-                dst_layer))]
-    if host_device_file_tuples:
-      self.device.PushChangedFiles(host_device_file_tuples)
-    self.tool.CopyFiles(self.device)
-    TestRunner._DEVICE_HAS_TEST_FILES[str(self.device)] = True
-
   def _GetInstrumentationArgs(self):
     ret = {}
     if self.options.wait_for_debugger:
@@ -209,7 +151,7 @@
       Whether the feature being tested is FirstRunExperience.
     """
     annotations = self.test_pkg.GetTestAnnotations(test)
-    return ('FirstRunExperience' == annotations.get('Feature', None))
+    return 'FirstRunExperience' == annotations.get('Feature', None)
 
   def _IsPerfTest(self, test):
     """Determines whether a test is a performance test.
@@ -276,7 +218,8 @@
 
     # Wait and grab annotation data so we can figure out which traces to parse
     regex = self.device.old_interface.WaitForLogMatch(
-        re.compile('\*\*PERFANNOTATION\(' + raw_test_name + '\)\:(.*)'), None)
+        re.compile(r'\*\*PERFANNOTATION\(' + raw_test_name + r'\)\:(.*)'),
+        None)
 
     # If the test is set to run on a specific device type only (IE: only
     # tablet or phone) and it is being run on the wrong device, the test
diff --git a/build/android/pylib/linker/setup.py b/build/android/pylib/linker/setup.py
index 72bb131..ebfac87 100644
--- a/build/android/pylib/linker/setup.py
+++ b/build/android/pylib/linker/setup.py
@@ -25,13 +25,13 @@
   test_cases = [
       test_case.LinkerLibraryAddressTest,
       test_case.LinkerSharedRelroTest,
-      test_case.LinkerRandomizationTest ]
+      test_case.LinkerRandomizationTest]
 
   low_memory_modes = [False, True]
   all_tests = [t(is_low_memory=m) for t in test_cases for m in low_memory_modes]
 
   if options.test_filter:
-    all_test_names = [ test.qualified_name for test in all_tests ]
+    all_test_names = [test.qualified_name for test in all_tests]
     filtered_test_names = unittest_util.FilterTestNames(all_test_names,
                                                         options.test_filter)
     all_tests = [t for t in all_tests \
diff --git a/build/android/pylib/linker/test_case.py b/build/android/pylib/linker/test_case.py
index f64a58b..13f68cb 100644
--- a/build/android/pylib/linker/test_case.py
+++ b/build/android/pylib/linker/test_case.py
@@ -59,15 +59,15 @@
 # from the Java source file above.
 _RE_LINKER_BROWSER_CONFIG = re.compile(
     r'.*BROWSER_SHARED_RELRO_CONFIG\s+=\s+' +
-        'BROWSER_SHARED_RELRO_CONFIG_(\S+)\s*;.*',
+        r'BROWSER_SHARED_RELRO_CONFIG_(\S+)\s*;.*',
     re.MULTILINE | re.DOTALL)
 
 # Logcat filters used during each test. Only the 'chromium' one is really
 # needed, but the logs are added to the TestResult in case of error, and
 # it is handy to have the 'chromium_android_linker' ones as well when
 # troubleshooting.
-_LOGCAT_FILTERS = [ '*:s', 'chromium:v', 'chromium_android_linker:v' ]
-#_LOGCAT_FILTERS = [ '*:v' ]  ## DEBUG
+_LOGCAT_FILTERS = ['*:s', 'chromium:v', 'chromium_android_linker:v']
+#_LOGCAT_FILTERS = ['*:v']  ## DEBUG
 
 # Regular expression used to match status lines in logcat.
 re_status_line = re.compile(r'(BROWSER|RENDERER)_LINKER_TEST: (FAIL|SUCCESS)')
diff --git a/build/android/pylib/linker/test_runner.py b/build/android/pylib/linker/test_runner.py
index 35eff19..3680f83 100644
--- a/build/android/pylib/linker/test_runner.py
+++ b/build/android/pylib/linker/test_runner.py
@@ -38,7 +38,7 @@
     super(LinkerExceptionTestResult, self).__init__(
         test_name,
         base_test_result.ResultType.FAIL,
-        log = "%s %s" % (exc_type, log_msg))
+        log="%s %s" % (exc_type, log_msg))
 
 
 class LinkerTestRunner(base_test_runner.BaseTestRunner):
diff --git a/build/android/pylib/perf/perf_control.py b/build/android/pylib/perf/perf_control.py
index ede1317..73cf95c 100644
--- a/build/android/pylib/perf/perf_control.py
+++ b/build/android/pylib/perf/perf_control.py
@@ -10,9 +10,7 @@
 
 class PerfControl(object):
   """Provides methods for setting the performance mode of a device."""
-  _SCALING_GOVERNOR_FMT = (
-      '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor')
-  _CPU_ONLINE_FMT = '/sys/devices/system/cpu/cpu%d/online'
+  _CPU_PATH = '/sys/devices/system/cpu'
   _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max'
 
   def __init__(self, device):
@@ -20,11 +18,12 @@
     if isinstance(device, android_commands.AndroidCommands):
       device = device_utils.DeviceUtils(device)
     self._device = device
-    cpu_files = self._device.RunShellCommand(
-      'ls -d /sys/devices/system/cpu/cpu[0-9]*')
-    self._num_cpu_cores = len(cpu_files)
-    assert self._num_cpu_cores > 0, 'Failed to detect CPUs.'
-    logging.info('Number of CPUs: %d', self._num_cpu_cores)
+    # this will raise an AdbShellCommandFailedError if no CPU files are found
+    self._cpu_files = self._device.RunShellCommand(
+        'ls -d cpu[0-9]*', cwd=self._CPU_PATH, check_return=True, as_root=True)
+    assert self._cpu_files, 'Failed to detect CPUs.'
+    self._cpu_file_list = ' '.join(self._cpu_files)
+    logging.info('CPUs found: %s', self._cpu_file_list)
     self._have_mpdecision = self._device.FileExists('/system/bin/mpdecision')
 
   def SetHighPerfMode(self):
@@ -84,22 +83,41 @@
     self._SetScalingGovernorInternal(governor_mode)
     self._ForceAllCpusOnline(False)
 
+  def GetCpuInfo(self):
+    online = (output.rstrip() == '1' and status == 0
+              for (_, output, status) in self._ForEachCpu('cat "$CPU/online"'))
+    governor = (output.rstrip() if status == 0 else None
+                for (_, output, status)
+                in self._ForEachCpu('cat "$CPU/cpufreq/scaling_governor"'))
+    return zip(self._cpu_files, online, governor)
+
+  def _ForEachCpu(self, cmd):
+    script = '; '.join([
+        'for CPU in %s' % self._cpu_file_list,
+        'do %s' % cmd,
+        'echo -n "%~%$?%~%"',
+        'done'
+    ])
+    output = self._device.RunShellCommand(
+        script, cwd=self._CPU_PATH, check_return=True, as_root=True)
+    output = '\n'.join(output).split('%~%')
+    return zip(self._cpu_files, output[0::2], (int(c) for c in output[1::2]))
+
+  def _WriteEachCpuFile(self, path, value):
+    results = self._ForEachCpu(
+        'test -e "$CPU/{path}" && echo {value} > "$CPU/{path}"'.format(
+            path=path, value=value))
+    cpus = ' '.join(cpu for (cpu, _, status) in results if status == 0)
+    if cpus:
+      logging.info('Successfully set %s to %r on: %s', path, value, cpus)
+    else:
+      logging.warning('Failed to set %s to %r on any cpus')
+
   def _SetScalingGovernorInternal(self, value):
-    cpu_cores = ' '.join([str(x) for x in range(self._num_cpu_cores)])
-    script = ('for CPU in %s; do\n'
-        '  FILE="/sys/devices/system/cpu/cpu$CPU/cpufreq/scaling_governor"\n'
-        '  test -e $FILE && echo %s > $FILE\n'
-        'done\n') % (cpu_cores, value)
-    logging.info('Setting scaling governor mode: %s', value)
-    self._device.RunShellCommand(script, as_root=True)
+    self._WriteEachCpuFile('cpufreq/scaling_governor', value)
 
   def _SetScalingMaxFreq(self, value):
-    cpu_cores = ' '.join([str(x) for x in range(self._num_cpu_cores)])
-    script = ('for CPU in %s; do\n'
-        '  FILE="/sys/devices/system/cpu/cpu$CPU/cpufreq/scaling_max_freq"\n'
-        '  test -e $FILE && echo %d > $FILE\n'
-        'done\n') % (cpu_cores, value)
-    self._device.RunShellCommand(script, as_root=True)
+    self._WriteEachCpuFile('cpufreq/scaling_max_freq', '%d' % value)
 
   def _SetMaxGpuClock(self, value):
     self._device.WriteFile('/sys/class/kgsl/kgsl-3d0/max_gpuclk',
@@ -107,14 +125,12 @@
                            as_root=True)
 
   def _AllCpusAreOnline(self):
-    for cpu in range(1, self._num_cpu_cores):
-      online_path = PerfControl._CPU_ONLINE_FMT % cpu
-      # TODO(epenner): Investigate why file may be missing
-      # (http://crbug.com/397118)
-      if not self._device.FileExists(online_path) or \
-            self._device.ReadFile(online_path)[0] == '0':
-        return False
-    return True
+    results = self._ForEachCpu('cat "$CPU/online"')
+    # TODO(epenner): Investigate why file may be missing
+    # (http://crbug.com/397118)
+    return all(output.rstrip() == '1' and status == 0
+               for (cpu, output, status) in results
+               if cpu != 'cpu0')
 
   def _ForceAllCpusOnline(self, force_online):
     """Enable all CPUs on a device.
@@ -132,15 +148,10 @@
     """
     if self._have_mpdecision:
       script = 'stop mpdecision' if force_online else 'start mpdecision'
-      self._device.RunShellCommand(script, as_root=True)
+      self._device.RunShellCommand(script, check_return=True, as_root=True)
 
     if not self._have_mpdecision and not self._AllCpusAreOnline():
       logging.warning('Unexpected cpu hot plugging detected.')
 
-    if not force_online:
-      return
-
-    for cpu in range(self._num_cpu_cores):
-      online_path = PerfControl._CPU_ONLINE_FMT % cpu
-      self._device.WriteFile(online_path, '1', as_root=True)
-
+    if force_online:
+      self._ForEachCpu('echo 1 > "$CPU/online"')
diff --git a/build/android/pylib/perf/perf_control_unittest.py b/build/android/pylib/perf/perf_control_unittest.py
index aa31f68..dd7cb88 100644
--- a/build/android/pylib/perf/perf_control_unittest.py
+++ b/build/android/pylib/perf/perf_control_unittest.py
@@ -27,13 +27,11 @@
     perf = perf_control.PerfControl(self._device)
     try:
       perf.SetPerfProfilingMode()
-      for cpu in range(perf._num_cpu_cores):
-        path = perf_control.PerfControl._CPU_ONLINE_FMT % cpu
-        self.assertEquals('1',
-                          self._device.ReadFile(path)[0])
-        path = perf_control.PerfControl._SCALING_GOVERNOR_FMT % cpu
-        self.assertEquals('performance',
-                          self._device.ReadFile(path)[0])
+      cpu_info = perf.GetCpuInfo()
+      self.assertEquals(len(perf._cpu_files), len(cpu_info))
+      for _, online, governor in cpu_info:
+        self.assertTrue(online)
+        self.assertEquals('performance', governor)
     finally:
       perf.SetDefaultPerfMode()
 
diff --git a/build/android/pylib/perf/surface_stats_collector.py b/build/android/pylib/perf/surface_stats_collector.py
index a34d87d..499b0c6 100644
--- a/build/android/pylib/perf/surface_stats_collector.py
+++ b/build/android/pylib/perf/surface_stats_collector.py
@@ -13,7 +13,7 @@
 
 # Log marker containing SurfaceTexture timestamps.
 _SURFACE_TEXTURE_TIMESTAMPS_MESSAGE = 'SurfaceTexture update timestamps'
-_SURFACE_TEXTURE_TIMESTAMP_RE = '\d+'
+_SURFACE_TEXTURE_TIMESTAMP_RE = r'\d+'
 
 _MIN_NORMALIZED_FRAME_LENGTH = 0.5
 
@@ -90,8 +90,8 @@
   def _GetNormalizedDeltas(data, refresh_period, min_normalized_delta=None):
     deltas = [t2 - t1 for t1, t2 in zip(data, data[1:])]
     if min_normalized_delta != None:
-      deltas = filter(lambda d: d / refresh_period >= min_normalized_delta,
-                      deltas)
+      deltas = [d for d in deltas
+                if d / refresh_period >= min_normalized_delta]
     return (deltas, [delta / refresh_period for delta in deltas])
 
   @staticmethod
@@ -297,7 +297,7 @@
     """
     results = self._device.RunShellCommand('service call SurfaceFlinger 1013')
     assert len(results) == 1
-    match = re.search('^Result: Parcel\((\w+)', results[0])
+    match = re.search(r'^Result: Parcel\((\w+)', results[0])
     cur_surface = 0
     if match:
       try:
diff --git a/build/android/pylib/uiautomator/test_runner.py b/build/android/pylib/uiautomator/test_runner.py
index b47a236..1ab9545 100644
--- a/build/android/pylib/uiautomator/test_runner.py
+++ b/build/android/pylib/uiautomator/test_runner.py
@@ -40,7 +40,8 @@
         test_apk_jar_path=None,
         test_runner=None,
         test_support_apk_path=None,
-        device_flags=None)
+        device_flags=None,
+        isolate_file_path=None)
     super(TestRunner, self).__init__(instrumentation_options, device,
                                      shard_index, test_pkg)
 
@@ -56,15 +57,11 @@
     self.test_pkg.Install(self.device)
 
   #override
-  def PushDataDeps(self):
-    pass
-
-  #override
   def _RunTest(self, test, timeout):
     self.device.ClearApplicationState(self._package)
     if self.flags:
       annotations = self.test_pkg.GetTestAnnotations(test)
-      if ('FirstRunExperience' == annotations.get('Feature', None)):
+      if 'FirstRunExperience' == annotations.get('Feature', None):
         self.flags.RemoveFlags(['--disable-fre'])
       else:
         self.flags.AddFlags(['--disable-fre'])
diff --git a/build/android/pylib/utils/host_path_finder.py b/build/android/pylib/utils/host_path_finder.py
index aea51a9..389ac43 100644
--- a/build/android/pylib/utils/host_path_finder.py
+++ b/build/android/pylib/utils/host_path_finder.py
@@ -14,9 +14,8 @@
   """
   out_dir = os.path.join(
       constants.DIR_SOURCE_ROOT, os.environ.get('CHROMIUM_OUT_DIR', 'out'))
-  candidate_paths = map(
-      lambda build_type: os.path.join(out_dir, build_type, file_name),
-      ['Debug', 'Release'])
+  candidate_paths = [os.path.join(out_dir, build_type, file_name)
+                     for build_type in ['Debug', 'Release']]
   candidate_paths = filter(os.path.exists, candidate_paths)
   candidate_paths = sorted(candidate_paths, key=os.path.getmtime, reverse=True)
   candidate_paths.append('')
diff --git a/build/android/pylib/utils/json_results_generator.py b/build/android/pylib/utils/json_results_generator.py
index d40860d..e5c433d 100644
--- a/build/android/pylib/utils/json_results_generator.py
+++ b/build/android/pylib/utils/json_results_generator.py
@@ -157,10 +157,10 @@
   TIMES_MS_FILENAME = 'times_ms.json'
   INCREMENTAL_RESULTS_FILENAME = 'incremental_results.json'
 
-  # line too long pylint: disable=C0301
+  # line too long pylint: disable=line-too-long
   URL_FOR_TEST_LIST_JSON = (
       'http://%s/testfile?builder=%s&name=%s&testlistjson=1&testtype=%s&master=%s')
-  # pylint: enable=C0301
+  # pylint: enable=line-too-long
 
   def __init__(self, builder_name, build_name, build_number,
                results_file_base_path, builder_base_url,
@@ -387,7 +387,7 @@
     except urllib2.HTTPError, http_error:
       # A non-4xx status code means the bot is hosed for some reason
       # and we can't grab the results.json file off of it.
-      if (http_error.code < 400 and http_error.code >= 500):
+      if http_error.code < 400 and http_error.code >= 500:
         error = http_error
     except urllib2.URLError, url_error:
       error = url_error
diff --git a/build/android/pylib/utils/md5sum.py b/build/android/pylib/utils/md5sum.py
new file mode 100644
index 0000000..8c10bb0
--- /dev/null
+++ b/build/android/pylib/utils/md5sum.py
@@ -0,0 +1,72 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import logging
+import os
+import tempfile
+import types
+
+from pylib import cmd_helper
+from pylib import constants
+from pylib.utils import device_temp_file
+
+HashAndPath = collections.namedtuple('HashAndPath', ['hash', 'path'])
+
+MD5SUM_DEVICE_LIB_PATH = '/data/local/tmp/md5sum/'
+MD5SUM_DEVICE_BIN_PATH = MD5SUM_DEVICE_LIB_PATH + 'md5sum_bin'
+
+MD5SUM_DEVICE_SCRIPT_FORMAT = (
+    'test -f {path} -o -d {path} '
+    '&& LD_LIBRARY_PATH={md5sum_lib} {md5sum_bin} {path}')
+
+
+def CalculateHostMd5Sums(paths):
+  """Calculates the MD5 sum value for all items in |paths|.
+
+  Args:
+    paths: A list of host paths to md5sum.
+  Returns:
+    A list of named tuples with 'hash' and 'path' attributes.
+  """
+  if isinstance(paths, basestring):
+    paths = [paths]
+
+  out = cmd_helper.GetCmdOutput(
+      [os.path.join(constants.GetOutDirectory(), 'md5sum_bin_host')] +
+          [p for p in paths])
+  return [HashAndPath(*l.split(None, 1)) for l in out.splitlines()]
+
+
+def CalculateDeviceMd5Sums(paths, device):
+  """Calculates the MD5 sum value for all items in |paths|.
+
+  Args:
+    paths: A list of device paths to md5sum.
+  Returns:
+    A list of named tuples with 'hash' and 'path' attributes.
+  """
+  if isinstance(paths, basestring):
+    paths = [paths]
+
+  if not device.FileExists(MD5SUM_DEVICE_BIN_PATH):
+    device.adb.Push(
+        os.path.join(constants.GetOutDirectory(), 'md5sum_dist'),
+        MD5SUM_DEVICE_LIB_PATH)
+
+  out = []
+  with tempfile.NamedTemporaryFile() as md5sum_script_file:
+    with device_temp_file.DeviceTempFile(device) as md5sum_device_script_file:
+      md5sum_script = (
+          MD5SUM_DEVICE_SCRIPT_FORMAT.format(
+              path=p, md5sum_lib=MD5SUM_DEVICE_LIB_PATH,
+              md5sum_bin=MD5SUM_DEVICE_BIN_PATH)
+          for p in paths)
+      md5sum_script_file.write('; '.join(md5sum_script))
+      md5sum_script_file.flush()
+      device.adb.Push(md5sum_script_file.name, md5sum_device_script_file.name)
+      out = device.RunShellCommand(['sh', md5sum_device_script_file.name])
+
+  return [HashAndPath(*l.split(None, 1)) for l in out]
+
diff --git a/build/android/pylib/utils/md5sum_test.py b/build/android/pylib/utils/md5sum_test.py
new file mode 100755
index 0000000..6c689fb
--- /dev/null
+++ b/build/android/pylib/utils/md5sum_test.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+import unittest
+
+from pylib import cmd_helper
+from pylib import constants
+from pylib.utils import md5sum
+
+sys.path.append(
+    os.path.join(constants.DIR_SOURCE_ROOT, 'third_party', 'pymock'))
+import mock
+
+TEST_OUT_DIR = os.path.join('test', 'out', 'directory')
+HOST_MD5_EXECUTABLE = os.path.join(TEST_OUT_DIR, 'md5sum_bin_host')
+
+class Md5SumTest(unittest.TestCase):
+
+  def setUp(self):
+    self._patchers = [
+        mock.patch('pylib.constants.GetOutDirectory',
+                   new=mock.Mock(return_value=TEST_OUT_DIR)),
+    ]
+    for p in self._patchers:
+      p.start()
+
+  def tearDown(self):
+    for p in self._patchers:
+      p.stop()
+
+  def testCalculateHostMd5Sums_singlePath(self):
+    test_path = '/test/host/file.dat'
+    mock_get_cmd_output = mock.Mock(
+        return_value='0123456789abcdeffedcba9876543210 /test/host/file.dat')
+    with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
+      out = md5sum.CalculateHostMd5Sums(test_path)
+      self.assertEquals(1, len(out))
+      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
+      self.assertEquals('/test/host/file.dat', out[0].path)
+      mock_get_cmd_output.assert_called_once_with(
+          [HOST_MD5_EXECUTABLE, '/test/host/file.dat'])
+
+  def testCalculateHostMd5Sums_list(self):
+    test_paths = ['/test/host/file0.dat', '/test/host/file1.dat']
+    mock_get_cmd_output = mock.Mock(
+        return_value='0123456789abcdeffedcba9876543210 /test/host/file0.dat\n'
+                     '123456789abcdef00fedcba987654321 /test/host/file1.dat\n')
+    with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
+      out = md5sum.CalculateHostMd5Sums(test_paths)
+      self.assertEquals(2, len(out))
+      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
+      self.assertEquals('/test/host/file0.dat', out[0].path)
+      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
+      self.assertEquals('/test/host/file1.dat', out[1].path)
+      mock_get_cmd_output.assert_called_once_with(
+          [HOST_MD5_EXECUTABLE, '/test/host/file0.dat',
+           '/test/host/file1.dat'])
+
+  def testCalculateHostMd5Sums_generator(self):
+    test_paths = ('/test/host/' + p for p in ['file0.dat', 'file1.dat'])
+    mock_get_cmd_output = mock.Mock(
+        return_value='0123456789abcdeffedcba9876543210 /test/host/file0.dat\n'
+                     '123456789abcdef00fedcba987654321 /test/host/file1.dat\n')
+    with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
+      out = md5sum.CalculateHostMd5Sums(test_paths)
+      self.assertEquals(2, len(out))
+      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
+      self.assertEquals('/test/host/file0.dat', out[0].path)
+      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
+      self.assertEquals('/test/host/file1.dat', out[1].path)
+      mock_get_cmd_output.assert_called_once_with(
+          [HOST_MD5_EXECUTABLE, '/test/host/file0.dat', '/test/host/file1.dat'])
+
+  def testCalculateDeviceMd5Sums_singlePath(self):
+    test_path = '/storage/emulated/legacy/test/file.dat'
+
+    device = mock.NonCallableMock()
+    device.adb = mock.NonCallableMock()
+    device.adb.Push = mock.Mock()
+    device_md5sum_output = [
+        '0123456789abcdeffedcba9876543210 '
+            '/storage/emulated/legacy/test/file.dat',
+    ]
+    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
+
+    mock_temp_file = mock.mock_open()
+    mock_temp_file.return_value.name = '/tmp/test/script/file.sh'
+
+    mock_device_temp_file = mock.mock_open()
+    mock_device_temp_file.return_value.name = (
+        '/data/local/tmp/test/script/file.sh')
+
+    with mock.patch('tempfile.NamedTemporaryFile', new=mock_temp_file), (
+         mock.patch('pylib.utils.device_temp_file.DeviceTempFile',
+                    new=mock_device_temp_file)):
+      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
+      self.assertEquals(1, len(out))
+      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
+      self.assertEquals('/storage/emulated/legacy/test/file.dat', out[0].path)
+      device.adb.Push.assert_called_once_with(
+          '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
+      device.RunShellCommand.assert_called_once_with(
+          ['sh', '/data/local/tmp/test/script/file.sh'])
+
+  def testCalculateDeviceMd5Sums_list(self):
+    test_path = ['/storage/emulated/legacy/test/file0.dat',
+                 '/storage/emulated/legacy/test/file1.dat']
+    device = mock.NonCallableMock()
+    device.adb = mock.NonCallableMock()
+    device.adb.Push = mock.Mock()
+    device_md5sum_output = [
+        '0123456789abcdeffedcba9876543210 '
+            '/storage/emulated/legacy/test/file0.dat',
+        '123456789abcdef00fedcba987654321 '
+            '/storage/emulated/legacy/test/file1.dat',
+    ]
+    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
+
+    mock_temp_file = mock.mock_open()
+    mock_temp_file.return_value.name = '/tmp/test/script/file.sh'
+
+    mock_device_temp_file = mock.mock_open()
+    mock_device_temp_file.return_value.name = (
+        '/data/local/tmp/test/script/file.sh')
+
+    with mock.patch('tempfile.NamedTemporaryFile', new=mock_temp_file), (
+         mock.patch('pylib.utils.device_temp_file.DeviceTempFile',
+                    new=mock_device_temp_file)):
+      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
+      self.assertEquals(2, len(out))
+      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
+      self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path)
+      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
+      self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path)
+      device.adb.Push.assert_called_once_with(
+          '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
+      device.RunShellCommand.assert_called_once_with(
+          ['sh', '/data/local/tmp/test/script/file.sh'])
+
+  def testCalculateDeviceMd5Sums_generator(self):
+    test_path = ('/storage/emulated/legacy/test/file%d.dat' % n
+                 for n in xrange(0, 2))
+
+    device = mock.NonCallableMock()
+    device.adb = mock.NonCallableMock()
+    device.adb.Push = mock.Mock()
+    device_md5sum_output = [
+        '0123456789abcdeffedcba9876543210 '
+            '/storage/emulated/legacy/test/file0.dat',
+        '123456789abcdef00fedcba987654321 '
+            '/storage/emulated/legacy/test/file1.dat',
+    ]
+    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
+
+    mock_temp_file = mock.mock_open()
+    mock_temp_file.return_value.name = '/tmp/test/script/file.sh'
+
+    mock_device_temp_file = mock.mock_open()
+    mock_device_temp_file.return_value.name = (
+        '/data/local/tmp/test/script/file.sh')
+
+    with mock.patch('tempfile.NamedTemporaryFile', new=mock_temp_file), (
+         mock.patch('pylib.utils.device_temp_file.DeviceTempFile',
+                    new=mock_device_temp_file)):
+      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
+      self.assertEquals(2, len(out))
+      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
+      self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path)
+      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
+      self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path)
+      device.adb.Push.assert_called_once_with(
+          '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
+      device.RunShellCommand.assert_called_once_with(
+          ['sh', '/data/local/tmp/test/script/file.sh'])
+
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
+
diff --git a/build/android/pylib/utils/mock_calls.py b/build/android/pylib/utils/mock_calls.py
old mode 100755
new mode 100644
index 1f9d8e3..b10ebc6
--- a/build/android/pylib/utils/mock_calls.py
+++ b/build/android/pylib/utils/mock_calls.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright 2014 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
diff --git a/build/android/pylib/utils/parallelizer.py b/build/android/pylib/utils/parallelizer.py
index 9323c21..9a85b54 100644
--- a/build/android/pylib/utils/parallelizer.py
+++ b/build/android/pylib/utils/parallelizer.py
@@ -52,7 +52,7 @@
 penalty.
 
 """
-# pylint: disable=W0613
+# pylint: disable=protected-access
 
 from pylib.utils import reraiser_thread
 from pylib.utils import watchdog_timer
@@ -194,11 +194,11 @@
       or '_assertNoShadow'.
     """
     if isinstance(self._objs, reraiser_thread.ReraiserThreadGroup):
-      assert(not hasattr(self._objs, '_assertNoShadow'))
-      assert(not hasattr(self._objs, 'pGet'))
+      assert not hasattr(self._objs, '_assertNoShadow')
+      assert not hasattr(self._objs, attr_name)
     else:
-      assert(not any(hasattr(o, '_assertNoShadow') for o in self._objs))
-      assert(not any(hasattr(o, 'pGet') for o in self._objs))
+      assert not any(hasattr(o, '_assertNoShadow') for o in self._objs)
+      assert not any(hasattr(o, attr_name) for o in self._objs)
 
 
 class SyncParallelizer(Parallelizer):
diff --git a/build/android/pylib/utils/report_results.py b/build/android/pylib/utils/report_results.py
index 9841dc6..8f81c95 100644
--- a/build/android/pylib/utils/report_results.py
+++ b/build/android/pylib/utils/report_results.py
@@ -18,7 +18,7 @@
   if not os.path.exists(log_file_path):
     os.mkdir(log_file_path)
   full_file_name = os.path.join(
-      log_file_path, re.sub('\W', '_', test_type).lower() + '.log')
+      log_file_path, re.sub(r'\W', '_', test_type).lower() + '.log')
   if not os.path.exists(full_file_name):
     with open(full_file_name, 'w') as log_file:
       print >> log_file, '\n%s results for %s build %s:' % (
diff --git a/build/android/rezip/RezipApk.java b/build/android/rezip/RezipApk.java
index fcb0703..b4285cd 100644
--- a/build/android/rezip/RezipApk.java
+++ b/build/android/rezip/RezipApk.java
@@ -39,8 +39,8 @@
     // Files matching this pattern are not copied to the output when adding alignment.
     // When reordering and verifying the APK they are copied to the end of the file.
     private static Pattern sMetaFilePattern =
-            Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA)|com/android/otacert))|(" +
-                            Pattern.quote(JarFile.MANIFEST_NAME) + ")$");
+            Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA)|com/android/otacert))|("
+                    + Pattern.quote(JarFile.MANIFEST_NAME) + ")$");
 
     // Pattern for matching a shared library in the APK
     private static Pattern sLibraryPattern = Pattern.compile("^lib/[^/]*/lib.*[.]so$");
@@ -48,12 +48,11 @@
     private static Pattern sCrazyLinkerPattern =
             Pattern.compile("^lib/[^/]*/libchromium_android_linker.so$");
     // Pattern for matching a crazy loaded shared library in the APK
-    private static Pattern sCrazyLibraryPattern =
-            Pattern.compile("^lib/[^/]*/crazy.lib.*[.]so$");
+    private static Pattern sCrazyLibraryPattern = Pattern.compile("^lib/[^/]*/crazy.lib.*[.]so$");
 
     private static boolean isLibraryFilename(String filename) {
-        return sLibraryPattern.matcher(filename).matches() &&
-                !sCrazyLinkerPattern.matcher(filename).matches();
+        return sLibraryPattern.matcher(filename).matches()
+                && !sCrazyLinkerPattern.matcher(filename).matches();
     }
 
     private static boolean isCrazyLibraryFilename(String filename) {
@@ -150,8 +149,7 @@
             if (entry.isDirectory()) {
                 continue;
             }
-            if (omitMetaFiles &&
-                sMetaFilePattern.matcher(entry.getName()).matches()) {
+            if (omitMetaFiles && sMetaFilePattern.matcher(entry.getName()).matches()) {
                 continue;
             }
             entries.add(entry);
@@ -394,16 +392,12 @@
     }
 
     private static void usage() {
-        System.err.println(
-                "Usage: prealignapk (addalignment|reorder) input.apk output.apk");
-        System.err.println(
-                "\"crazy\" libraries are always inflated in the output");
+        System.err.println("Usage: prealignapk (addalignment|reorder) input.apk output.apk");
+        System.err.println("\"crazy\" libraries are always inflated in the output");
         System.err.println(
                 "  renamealign  - rename libraries with \"crazy.\" prefix and add alignment file");
-        System.err.println(
-                "  align        - add alignment file");
-        System.err.println(
-                "  reorder      - re-creates canonical ordering and checks alignment");
+        System.err.println("  align        - add alignment file");
+        System.err.println("  reorder      - re-creates canonical ordering and checks alignment");
         System.exit(2);
     }
 
diff --git a/build/android/surface_stats.py b/build/android/surface_stats.py
index 74bfdce..911dd2e 100755
--- a/build/android/surface_stats.py
+++ b/build/android/surface_stats.py
@@ -13,6 +13,8 @@
 import sys
 import time
 
+from pylib.device import adb_wrapper
+from pylib.device import device_errors
 from pylib.device import device_utils
 from pylib.perf import surface_stats_collector
 from pylib.utils import run_tests_helper
@@ -98,7 +100,14 @@
   options, _ = parser.parse_args(argv)
   run_tests_helper.SetLogLevel(options.verbose_count)
 
-  device = device_utils.DeviceUtils(options.device)
+  if options.device:
+    device = device_utils.DeviceUtils(options.device)
+  else:
+    devices = adb_wrapper.AdbWrapper.GetDevices()
+    if not devices:
+      raise device_errors.NoDevicesError
+    device = device_utils.DeviceUtils(devices[0])
+
   collector = surface_stats_collector.SurfaceStatsCollector(device)
   collector.DisableWarningAboutEmptyData()
 
diff --git a/build/android/symbolize.py b/build/android/symbolize.py
index cb5d475..56d3b19 100755
--- a/build/android/symbolize.py
+++ b/build/android/symbolize.py
@@ -24,8 +24,8 @@
 
 # Sample output from base/debug/stack_trace_android.cc
 #00 0x693cd34f /path/to/some/libfoo.so+0x0007434f
-TRACE_LINE = re.compile('(?P<frame>\#[0-9]+ 0x[0-9a-f]{8,8}) '
-                        '(?P<lib>[^+]+)\+0x(?P<addr>[0-9a-f]{8,8})')
+TRACE_LINE = re.compile(r'(?P<frame>\#[0-9]+ 0x[0-9a-f]{8,8}) '
+                        r'(?P<lib>[^+]+)\+0x(?P<addr>[0-9a-f]{8,8})')
 
 class Symbolizer(object):
   def __init__(self, output):
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index d5c9b35..b483d2b 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -91,6 +91,9 @@
   group.add_option('-e', '--environment', default='local',
                    help=('Test environment to run in. Must be one of: %s' %
                          ', '.join(constants.VALID_ENVIRONMENTS)))
+  group.add_option('--adb-path',
+                   help=('Specify the absolute path of the adb binary that '
+                         'should be used.'))
   option_parser.add_option_group(group)
 
 
@@ -102,6 +105,12 @@
     constants.SetBuildDirectory(options.build_directory)
   if options.output_directory:
     constants.SetOutputDirectort(options.output_directory)
+  if options.adb_path:
+    constants.SetAdbPath(options.adb_path)
+  # Some things such as Forwarder require ADB to be in the environment path.
+  adb_dir = os.path.dirname(constants.GetAdbPath())
+  if adb_dir and adb_dir not in os.environ['PATH'].split(os.pathsep):
+    os.environ['PATH'] = adb_dir + os.pathsep + os.environ['PATH']
   if options.environment not in constants.VALID_ENVIRONMENTS:
     error_func('--environment must be one of: %s' %
                ', '.join(constants.VALID_ENVIRONMENTS))
@@ -272,6 +281,11 @@
   option_parser.add_option('--device-flags', dest='device_flags', default='',
                            help='The relative filepath to a file containing '
                                 'command-line flags to set on the device')
+  option_parser.add_option('--isolate_file_path',
+                           '--isolate-file-path',
+                           dest='isolate_file_path',
+                           help='.isolate file path to override the default '
+                                'path')
 
 
 def ProcessInstrumentationOptions(options, error_func):
@@ -334,7 +348,8 @@
       options.test_apk_jar_path,
       options.test_runner,
       options.test_support_apk_path,
-      options.device_flags
+      options.device_flags,
+      options.isolate_file_path
       )
 
 
@@ -657,7 +672,8 @@
   exit_code = 0
 
   if options.run_java_tests:
-    runner_factory, tests = instrumentation_setup.Setup(instrumentation_options)
+    runner_factory, tests = instrumentation_setup.Setup(
+        instrumentation_options, devices)
 
     test_results, exit_code = test_dispatcher.RunTests(
         tests, runner_factory, devices, shard=True, test_timeout=None,
diff --git a/build/android/tests/multiple_proguards/src/dummy/DummyActivity.java b/build/android/tests/multiple_proguards/src/dummy/DummyActivity.java
index 72f20f4..e138acc 100644
--- a/build/android/tests/multiple_proguards/src/dummy/DummyActivity.java
+++ b/build/android/tests/multiple_proguards/src/dummy/DummyActivity.java
@@ -22,5 +22,5 @@
 
     private static void doBadThings2() {
         sun.reflect.Reflection.getCallerClass(2);
-  }
+    }
 }
diff --git a/build/common.gypi b/build/common.gypi
index 0d7d385..77939be 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -41,7 +41,7 @@
 
             'conditions': [
               # Compute the architecture that we're building on.
-              ['OS=="win" or OS=="mac" or OS=="ios"', {
+              ['OS=="win" or OS=="ios"', {
                 'host_arch%': 'ia32',
               }, {
                 'host_arch%': '<!pymod_do_main(detect_host_arch)',
@@ -997,8 +997,8 @@
 
         # TODO(baixo): Enable v8_use_external_startup_data
         # http://crbug.com/421063
-        ['android_webview_build==0 and android_webview_telemetry_build==0 and chromecast==0', {
-          'v8_use_external_startup_data': 0,
+        ['android_webview_build==0 and android_webview_telemetry_build==0 and chromecast==0 and OS=="android"', {
+          'v8_use_external_startup_data': 1,
         }, {
           'v8_use_external_startup_data': 0,
         }],
@@ -2275,6 +2275,11 @@
         'arm_thumb%': 1,
       }],
 
+      # Set default compiler flags depending on MIPS architecture variant.
+      ['target_arch=="mipsel" and mips_arch_variant=="r2" and android_webview_build==0', {
+        'mips_fpu_mode%': 'fp32',
+      }],
+
       ['android_webview_build==1', {
         # The WebView build gets its cpu-specific flags from the Android build system.
         'arm_arch%': '',
@@ -2282,6 +2287,7 @@
         'arm_fpu%': '',
         'arm_float_abi%': '',
         'arm_thumb%': 0,
+        'mips_fpu_mode%': '',
       }],
 
       # Enable brlapi by default for chromeos.
@@ -3164,6 +3170,12 @@
               'credui.lib',
               'netapi32.lib',
             ],
+            'AdditionalOptions': [
+              # Suggested by Microsoft Devrel to avoid
+              #   LINK : fatal error LNK1248: image size (80000000) exceeds maximum allowable size (80000000)
+              # which started happening more regularly after VS2013 Update 4.
+              '/maxilksize:2147483647',
+            ],
           },
         },
       },
@@ -5405,7 +5417,6 @@
           # removed as code is fixed.
           4100, # Unreferenced formal parameter
           4121, # Alignment of a member was sensitive to packing
-          4189, # Local variable is initialized but not referenced
           4244, # Conversion from 'type1' to 'type2', possible loss of data
           4481, # Nonstandard extension used: override specifier 'keyword'
           4505, # Unreferenced local function has been removed
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 7120bac..0568527 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -213,6 +213,10 @@
     if (requires_android) {
       args += [ "--requires-android" ]
     }
+    if (defined(invoker.bypass_platform_checks) &&
+        invoker.bypass_platform_checks) {
+      args += [ "--bypass-platform-checks" ]
+    }
 
     if (is_android_resources || is_apk) {
       assert(defined(invoker.resources_zip))
@@ -634,12 +638,6 @@
       args += [ "--chromium-code=1" ]
     }
 
-    if (defined(invoker.main_class)) {
-      args += [
-        "--main-class", invoker.main_class
-      ]
-    }
-
     args += rebase_path(_java_files, root_build_dir)
   }
 
@@ -699,6 +697,8 @@
       type = "java_library"
       supports_android = _supports_android
       requires_android = _requires_android
+      bypass_platform_checks = (defined(invoker.bypass_platform_checks) &&
+        invoker.bypass_platform_checks)
 
       deps = []
       if (defined(invoker.deps)) {
@@ -764,7 +764,6 @@
     android = _requires_android
 
     if (defined(invoker.jar_excluded_patterns)) { jar_excluded_patterns = invoker.jar_excluded_patterns }
-    if (defined(invoker.main_class)) { main_class = invoker.main_class }
     if (defined(invoker.proguard_preprocess)) { proguard_preprocess = invoker.proguard_preprocess }
     if (defined(invoker.proguard_config)) { proguard_config = invoker.proguard_config }
     if (defined(invoker.dist_jar_path)) { dist_jar_path = invoker.dist_jar_path }
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 3f54c43..938a090 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -655,6 +655,10 @@
 #   srcjars: List of srcjars to be included in this library, together with the
 #     ones obtained from srcjar_deps.
 #
+#   bypass_platform_checks: Disables checks about cross-platform (Java/Android)
+#     dependencies for this target. This will allow depending on an
+#     android_library target, for example.
+#
 #   chromium_code: If true, extra analysis warning/errors will be enabled.
 #
 #   datadeps, testonly
@@ -676,6 +680,7 @@
     if (defined(invoker.java_files)) { java_files = invoker.java_files }
     if (defined(invoker.srcjar_deps)) { srcjar_deps = invoker.srcjar_deps }
     if (defined(invoker.srcjars)) { srcjars = invoker.srcjars }
+    if (defined(invoker.bypass_platform_checks)) { bypass_platform_checks = invoker.bypass_platform_checks }
     if (defined(invoker.testonly)) { testonly = invoker.testonly }
 
     main_class = invoker.main_class
@@ -709,10 +714,9 @@
 #   supports_android: If true, Android targets (android_library, android_apk)
 #     may depend on this target. Note: if true, this target must only use the
 #     subset of Java available on Android.
-#   requires_android_platform: If true, this library may depend on
-#     android-specific targets. If this is the case, there should be some
-#     android-platform-like implementation available at runtime (Android,
-#     robolectric, etc).
+#   bypass_platform_checks: Disables checks about cross-platform (Java/Android)
+#     dependencies for this target. This will allow depending on an
+#     android_library target, for example.
 #
 #   datadeps, testonly
 #
@@ -745,17 +749,13 @@
     if (defined(invoker.proguard_preprocess)) { proguard_preprocess = invoker.proguard_preprocess }
     if (defined(invoker.srcjar_deps)) { srcjar_deps = invoker.srcjar_deps }
     if (defined(invoker.srcjars)) { srcjars = invoker.srcjars }
+    if (defined(invoker.bypass_platform_checks)) { bypass_platform_checks = invoker.bypass_platform_checks }
     if (defined(invoker.testonly)) { testonly = invoker.testonly }
     if (defined(invoker.jar_path)) { jar_path = invoker.jar_path }
 
     if (defined(invoker.supports_android) && invoker.supports_android) {
       supports_android = true
     }
-    if (defined(invoker.requires_android_platform)
-        && invoker.requires_android_platform) {
-      supports_android = true
-      requires_android = true
-    }
   }
 }
 
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 0d9e501..ae12eda 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -691,7 +691,6 @@
 
       "/wd4100",  # Unreferenced formal function parameter.
       "/wd4121",  # Alignment of a member was sensitive to packing.
-      "/wd4189",  # A variable was declared and initialized but never used.
       "/wd4244",  # Conversion: possible loss of data.
       "/wd4481",  # Nonstandard extension: override specifier.
       "/wd4505",  # Unreferenced local function has been removed.
diff --git a/build/config/features.gni b/build/config/features.gni
index 82247b9..9953a0d 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -94,9 +94,7 @@
 # disables it, 1 enables it fully, and 2 enables only UI and reporting features
 # without enabling phishing and malware detection. This is useful to integrate
 # a third party phishing/malware detection to existing safe browsing logic.
-if (is_android) {
-  safe_browsing_mode = 2
-} else if (is_ios) {
+if (is_ios) {
   safe_browsing_mode = 0
 } else {
   safe_browsing_mode = 1
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index 58e310f..f623064 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -16,19 +16,10 @@
     "NTDDI_VERSION=0x06030000",
     "PSAPI_VERSION=1",
     "WIN32",
+    "_SECURE_ATL",
   ]
 
   include_dirs = system_include_dirs
-
-  if (is_visual_studio_express) {
-    # https://code.google.com/p/chromium/issues/detail?id=372451#c20
-    # Warning 4702 ("Unreachable code") should be re-enabled once Express users
-    # are updated to VS2013 Update 2.
-    cflags = [ "/wd4702" ]
-  } else {
-    # Only supported on non-Express versions.
-    defines += [ "_SECURE_ATL" ]
-  }
 }
 
 # Sets the default Windows build version. This is separated because some
@@ -49,9 +40,6 @@
       "$visual_studio_path\VC\lib\amd64",
       "$visual_studio_path\VC\atlmfc\lib\amd64",
     ]
-    if (is_visual_studio_express) {
-      lib_dirs += [ "$wdk_path/lib/ATL/amd64" ]
-    }
   } else {
     ldflags = [
       "/MACHINE:X86",
@@ -62,26 +50,10 @@
       "$visual_studio_path\VC\lib",
       "$visual_studio_path\VC\atlmfc\lib",
     ]
-    if (is_visual_studio_express) {
-      lib_dirs += [ "$wdk_path/lib/ATL/i386" ]
-    }
     if (!is_asan) {
       ldflags += [ "/largeaddressaware" ]
     }
   }
-
-  if (is_visual_studio_express) {
-    # Explicitly required when using the ATL with express.
-    libs = [ "atlthunk.lib" ]
-
-    # ATL 8.0 included in WDK 7.1 makes the linker to generate almost eight
-    # hundred LNK4254 and LNK4078 warnings:
-    #   - warning LNK4254: section 'ATL' (50000040) merged into '.rdata'
-    #     (40000040) with different attributes
-    #   - warning LNK4078: multiple 'ATL' sections found with different
-    #     attributes
-    ldflags += [ "/ignore:4254", "/ignore:4078" ]
-  }
 }
 
 # This default linker setup is provided separately from the SDK setup so
diff --git a/build/config/win/visual_studio_version.gni b/build/config/win/visual_studio_version.gni
index c0b18c7..24c00cd 100644
--- a/build/config/win/visual_studio_version.gni
+++ b/build/config/win/visual_studio_version.gni
@@ -19,7 +19,7 @@
   # Full path to the Windows SDK, not including a backslash at the end.
   # This value is the default location, override if you have a different
   # installation location.
-  windows_sdk_path = "C:\Program Files (x86)\Windows Kits\8.0"
+  windows_sdk_path = "C:\Program Files (x86)\Windows Kits\8.1"
 
   # The list of include directories that are treated as "system" include
   # directories. TODO(scottmg): These are incorrectly put on the command line
@@ -34,17 +34,15 @@
   windows_sdk_path = toolchain_data.sdk_path
   visual_studio_version = toolchain_data.vs_version
   wdk_path = toolchain_data.wdk_dir
+  visual_studio_runtime_dirs = toolchain_data.runtime_dirs
 } else {
   assert(visual_studio_version != "",
          "You must set the visual_studio_version if you set the path")
   assert(wdk_path != "",
          "You must set the wdk_path if you set the visual studio path")
+  visual_studio_runtime_dirs = []
 }
 
-# Set when using the "Express" version of a Visual Studio version we support.
-is_visual_studio_express = (visual_studio_version == "2013e")
-
-
 # The Windows SDK include directories must be first. They both have a sal.h,
 # and the SDK one is newer and the SDK uses some newer features from it not
 # present in the Visual Studio one.
@@ -55,10 +53,3 @@
   "$visual_studio_path\VC\include",
   "$visual_studio_path\VC\atlmfc\include",
 ]
-
-if (is_visual_studio_express) {
-  system_include_dirs += [
-    "$wdk_path/inc/atl71",
-    "$wdk_path/inc/mfc42",
-  ]
-}
diff --git a/build/download_nacl_toolchains.py b/build/download_nacl_toolchains.py
index 3d6c64f..7402689 100755
--- a/build/download_nacl_toolchains.py
+++ b/build/download_nacl_toolchains.py
@@ -50,6 +50,7 @@
   if 'target_arch=arm' not in os.environ.get('GYP_DEFINES', ''):
       args.extend(['--exclude', 'nacl_arm_newlib'])
 
+  args.extend(['--mode', 'nacl_core_sdk'])
   args.append('sync')
   package_version.main(args)
 
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh
index f28409b..3093505 100755
--- a/build/install-build-deps.sh
+++ b/build/install-build-deps.sh
@@ -105,10 +105,10 @@
           libpulse-dev libsctp-dev libspeechd-dev libsqlite3-dev libssl-dev
           libudev-dev libwww-perl libxslt1-dev libxss-dev libxt-dev libxtst-dev
           mesa-common-dev openbox patch perl php5-cgi pkg-config python
-          python-cherrypy3 python-crypto python-dev python-opencv python-openssl
-          python-psutil rpm ruby subversion ttf-dejavu-core ttf-indic-fonts
-          ttf-kochi-gothic ttf-kochi-mincho wdiff xfonts-mathml zip
-          $chromeos_dev_list"
+          python-cherrypy3 python-crypto python-dev python-numpy python-opencv
+          python-openssl python-psutil rpm ruby subversion ttf-dejavu-core
+          ttf-indic-fonts ttf-kochi-gothic ttf-kochi-mincho wdiff xfonts-mathml
+          zip $chromeos_dev_list"
 
 # 64-bit systems need a minimum set of 32-bit compat packages for the pre-built
 # NaCl binaries.
diff --git a/build/precompile.h b/build/precompile.h
index 20ca73c..32c2f11 100644
--- a/build/precompile.h
+++ b/build/precompile.h
@@ -27,7 +27,6 @@
 #include <Windows.h>
 #include <dwmapi.h>
 #include <shellapi.h>
-#include <wincrypt.h>  // 4
 #include <wtypes.h>  // 2
 
 // Defines in atlbase.h cause conflicts; if we could figure out how
diff --git a/build/sanitizers/sanitizers.gyp b/build/sanitizers/sanitizers.gyp
index d971d6d..64f7cdf 100644
--- a/build/sanitizers/sanitizers.gyp
+++ b/build/sanitizers/sanitizers.gyp
@@ -56,6 +56,27 @@
         ],
       },
     },
+    {
+      # Copy llvm-symbolizer to the product dir so that LKGR bots can package it.
+      'target_name': 'llvm-symbolizer',
+      'type': 'none',
+      'variables': {
+
+       # Path is relative to this GYP file.
+       'llvm_symbolizer_path':
+           '../../third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer<(EXECUTABLE_SUFFIX)',
+      },
+      'conditions': [
+        ['clang==1', {
+          'copies': [{
+            'destination': '<(PRODUCT_DIR)',
+            'files': [
+              '<(llvm_symbolizer_path)',
+            ],
+          }],
+        }],
+      ],
+    },
   ],
 }
 
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index 8ee6083..09cf522 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -310,6 +310,10 @@
 // https://crbug.com/433993
 "deadlock:content::WebRtcAudioDeviceImpl\n"
 
+// http://crbug.com/417193
+// Suppressing both AudioContext.{cpp,h}.
+"race:modules/webaudio/AudioContext\n"
+
 // End of suppressions.
 ;  // Please keep this semicolon.
 
diff --git a/build/secondary/third_party/leveldatabase/BUILD.gn b/build/secondary/third_party/leveldatabase/BUILD.gn
index ffe9fa6..3653a98 100644
--- a/build/secondary/third_party/leveldatabase/BUILD.gn
+++ b/build/secondary/third_party/leveldatabase/BUILD.gn
@@ -23,8 +23,6 @@
   sources = [
     "env_chromium.cc",
     "env_chromium.h",
-    "env_chromium_stdio.cc",
-    "env_chromium_stdio.h",
     "env_idb.h",
     "port/port_chromium.cc",
     "port/port_chromium.h",
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index 988683d..87bd254 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -16,7 +16,12 @@
 gyp_win_tool_path = rebase_path("//tools/gyp/pylib/gyp/win_tool.py",
                                 root_build_dir)
 exec_script("setup_toolchain.py",
-            [ visual_studio_path, gyp_win_tool_path, windows_sdk_path ])
+            [
+              visual_studio_path,
+              gyp_win_tool_path,
+              windows_sdk_path,
+              visual_studio_runtime_dirs
+            ])
 
 # This value will be inherited in the toolchain below.
 concurrent_links = exec_script("../get_concurrent_links.py", [], "value")
diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py
index 5e292ab..42c3af1 100644
--- a/build/toolchain/win/setup_toolchain.py
+++ b/build/toolchain/win/setup_toolchain.py
@@ -19,39 +19,59 @@
 """
 
 
-def ExtractImportantEnvironment():
-  """Extracts environment variables required for the toolchain from the
-  current environment."""
+def _ExtractImportantEnvironment(output_of_set):
+  """Extracts environment variables required for the toolchain to run from
+  a textual dump output by the cmd.exe 'set' command."""
   envvars_to_save = (
-      'goma_.*',  # TODO(scottmg): This is ugly, but needed for goma.
-      'include',  # Needed by midl compiler.
+      'goma_.*', # TODO(scottmg): This is ugly, but needed for goma.
+      'include',
+      'lib',
+      'libpath',
       'path',
       'pathext',
       'systemroot',
       'temp',
       'tmp',
       )
-  result = {}
-  for envvar in envvars_to_save:
-    if envvar in os.environ:
-      envvar = envvar.lower()
-      if envvar == 'path':
-        # Our own rules (for running gyp-win-tool) and other actions in
-        # Chromium rely on python being in the path. Add the path to this
-        # python here so that if it's not in the path when ninja is run
-        # later, python will still be found.
-        result[envvar.upper()] = os.path.dirname(sys.executable) + \
-            os.pathsep + os.environ[envvar]
-      else:
-        result[envvar.upper()] = os.environ[envvar]
+  env = {}
+  for line in output_of_set.splitlines():
+    for envvar in envvars_to_save:
+      if re.match(envvar + '=', line.lower()):
+        var, setting = line.split('=', 1)
+        if envvar == 'path':
+          # Our own rules (for running gyp-win-tool) and other actions in
+          # Chromium rely on python being in the path. Add the path to this
+          # python here so that if it's not in the path when ninja is run
+          # later, python will still be found.
+          setting = os.path.dirname(sys.executable) + os.pathsep + setting
+        env[var.upper()] = setting
+        break
   for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
-    if required not in result:
+    if required not in env:
       raise Exception('Environment variable "%s" '
                       'required to be set to valid path' % required)
-  return result
+  return env
 
 
-def FormatAsEnvironmentBlock(envvar_dict):
+def _SetupScript(target_arch, sdk_dir):
+  """Returns a command (with arguments) to be used to set up the
+  environment."""
+  # Check if we are running in the SDK command line environment and use
+  # the setup script from the SDK if so. |target_arch| should be either
+  # 'x86' or 'x64'.
+  assert target_arch in ('x86', 'x64')
+  if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and sdk_dir:
+    return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')),
+            '/' + target_arch]
+  else:
+    # We only support x64-hosted tools.
+    # TODO(scottmg|dpranke): Non-depot_tools toolchain: need to get Visual
+    # Studio install location from registry.
+    return [os.path.normpath(os.path.join(FIND_VS_IN_REG, 'VC/vcvarsall.bat')),
+            'amd64_x86' if target_arch == 'x86' else 'amd64']
+
+
+def _FormatAsEnvironmentBlock(envvar_dict):
   """Format as an 'environment block' directly suitable for CreateProcess.
   Briefly this is a list of key=value\0, terminated by an additional \0. See
   CreateProcess documentation for more details."""
@@ -63,7 +83,7 @@
   return block
 
 
-def CopyTool(source_path):
+def _CopyTool(source_path):
   """Copies the given tool to the current directory, including a warning not
   to edit it."""
   with open(source_path) as source_file:
@@ -76,33 +96,39 @@
                              '# Generated by setup_toolchain.py do not edit.\n']
                             + tool_source[1:]))
 
-if len(sys.argv) != 4:
-  print('Usage setup_toolchain.py '
-        '<visual studio path> <win tool path> <win sdk path>')
-  sys.exit(2)
-vs_path = sys.argv[1]
-tool_source = sys.argv[2]
-win_sdk_path = sys.argv[3]
 
-CopyTool(tool_source)
+def main():
+  if len(sys.argv) != 5:
+    print('Usage setup_toolchain.py '
+          '<visual studio path> <win tool path> <win sdk path> <runtime dirs>')
+    sys.exit(2)
+  vs_path = sys.argv[1]
+  tool_source = sys.argv[2]
+  win_sdk_path = sys.argv[3]
+  runtime_dirs = sys.argv[4]
 
-important_env_vars = ExtractImportantEnvironment()
-path = important_env_vars["PATH"].split(";")
+  _CopyTool(tool_source)
 
-# Add 32-bit compiler path to the beginning and write the block.
-path32 = [os.path.join(vs_path, "VC\\BIN")] + \
-         [os.path.join(win_sdk_path, "bin\\x86")] + \
-         path
-important_env_vars["PATH"] = ";".join(path32)
-environ = FormatAsEnvironmentBlock(important_env_vars)
-with open('environment.x86', 'wb') as env_file:
-  env_file.write(environ)
+  archs = ('x86', 'x64')
+  # TODO(scottmg|goma): Do we need an equivalent of
+  # ninja_use_custom_environment_files?
+  for arch in archs:
+    # Extract environment variables for subprocesses.
+    args = _SetupScript(arch, win_sdk_path)
+    args.extend(('&&', 'set'))
+    popen = subprocess.Popen(
+        args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    variables, _ = popen.communicate()
+    env = _ExtractImportantEnvironment(variables)
+    env['PATH'] = runtime_dirs + ';' + env['PATH']
 
-# Add 64-bit compiler path to the beginning and write the block.
-path64 = [os.path.join(vs_path, "VC\\BIN\\amd64")] + \
-         [os.path.join(win_sdk_path, "bin\\x64")] + \
-         path
-important_env_vars["PATH"] = ";".join(path64)
-environ = FormatAsEnvironmentBlock(important_env_vars)
-with open('environment.x64', 'wb') as env_file:
-  env_file.write(environ)
+    # TODO(scottmg|thakis|dpranke): Is there an equivalent to
+    # msvs_system_include_dirs that we need to inject into INCLUDE here?
+
+    env_block = _FormatAsEnvironmentBlock(env)
+    with open('environment.' + arch, 'wb') as f:
+      f.write(env_block)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index a490a2c..fb7e142 100644
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -184,11 +184,11 @@
 def GetToolchainDir():
   """Gets location information about the current toolchain (must have been
   previously updated by 'update'). This is used for the GN build."""
-  SetEnvironmentAndGetRuntimeDllDirs()
+  runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
 
   # If WINDOWSSDKDIR is not set, search the default SDK path and set it.
   if not 'WINDOWSSDKDIR' in os.environ:
-    default_sdk_path = 'C:\\Program Files (x86)\\Windows Kits\\8.0'
+    default_sdk_path = 'C:\\Program Files (x86)\\Windows Kits\\8.1'
     if os.path.isdir(default_sdk_path):
       os.environ['WINDOWSSDKDIR'] = default_sdk_path
 
@@ -196,11 +196,13 @@
 sdk_path = "%s"
 vs_version = "%s"
 wdk_dir = "%s"
+runtime_dirs = "%s"
 ''' % (
       os.environ['GYP_MSVS_OVERRIDE_PATH'],
       os.environ['WINDOWSSDKDIR'],
       os.environ['GYP_MSVS_VERSION'],
-      os.environ.get('WDK_DIR', ''))
+      os.environ.get('WDK_DIR', ''),
+      ';'.join(runtime_dll_dirs))
 
 
 def main():
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index ab3aab4..6d5fec4 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -266,6 +266,8 @@
     "output/render_surface_filters.h",
     "output/renderer.cc",
     "output/renderer.h",
+    "output/renderer_settings.cc",
+    "output/renderer_settings.h",
     "output/shader.cc",
     "output/shader.h",
     "output/software_frame_data.cc",
diff --git a/cc/blink/BUILD.gn b/cc/blink/BUILD.gn
index 9fd2f33..fac991b 100644
--- a/cc/blink/BUILD.gn
+++ b/cc/blink/BUILD.gn
@@ -65,22 +65,25 @@
 }
 
 # GYP version: //cc/blink/cc_blink_tests.gyp:cc_blink_unittests
-test("cc_blink_unittests") {
-  deps = [
-    ":blink",
-    "//base/test:run_all_unittests",
-    "//base/third_party/dynamic_annotations",
-    "//skia",
-    "//testing/gtest",
-    "//ui/gfx/geometry",
-    "//ui/gfx:test_support",
-    "//cc",
-    "//cc:test_support",
-  ]
+# TODO(GYP): make linking work on the mac.
+if (!is_mac) {
+  test("cc_blink_unittests") {
+    deps = [
+      ":blink",
+      "//base/test:run_all_unittests",
+      "//base/third_party/dynamic_annotations",
+      "//skia",
+      "//testing/gtest",
+      "//ui/gfx/geometry",
+      "//ui/gfx:test_support",
+      "//cc",
+      "//cc:test_support",
+    ]
 
-  sources = [
-    "web_animation_unittest.cc",
-    "web_float_animation_curve_unittest.cc",
-    "web_layer_impl_fixed_bounds_unittest.cc",
-  ]
+    sources = [
+      "web_animation_unittest.cc",
+      "web_float_animation_curve_unittest.cc",
+      "web_layer_impl_fixed_bounds_unittest.cc",
+    ]
+  }
 }
diff --git a/cc/cc.gyp b/cc/cc.gyp
index fac01a7..046d43c 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -301,6 +301,8 @@
         'output/render_surface_filters.h',
         'output/renderer.cc',
         'output/renderer.h',
+        'output/renderer_settings.cc',
+        'output/renderer_settings.h',
         'output/shader.cc',
         'output/shader.h',
         'output/software_frame_data.cc',
diff --git a/cc/debug/rasterize_and_record_benchmark_impl.cc b/cc/debug/rasterize_and_record_benchmark_impl.cc
index 7009c4a..e276a41 100644
--- a/cc/debug/rasterize_and_record_benchmark_impl.cc
+++ b/cc/debug/rasterize_and_record_benchmark_impl.cc
@@ -196,7 +196,7 @@
 
 void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
   rasterize_results_.total_picture_layers++;
-  if (!layer->DrawsContent()) {
+  if (!layer->CanHaveTilings()) {
     rasterize_results_.total_picture_layers_with_no_content++;
     return;
   }
diff --git a/cc/input/page_scale_animation.h b/cc/input/page_scale_animation.h
index ce13dcf..0e430c2 100644
--- a/cc/input/page_scale_animation.h
+++ b/cc/input/page_scale_animation.h
@@ -10,12 +10,31 @@
 #include "base/time/time.h"
 #include "cc/base/cc_export.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
 namespace cc {
 
 class TimingFunction;
 
+// Used in the CC to pass around a scale animation that hasn't yet been
+// initialized.
+struct PendingPageScaleAnimation {
+  PendingPageScaleAnimation(
+      const gfx::Vector2d _target_offset,
+      bool _use_anchor,
+      float _scale,
+      const base::TimeDelta& _duration)
+      : target_offset(_target_offset),
+        use_anchor(_use_anchor),
+        scale(_scale),
+        duration(_duration) {}
+  gfx::Vector2d target_offset;
+  bool use_anchor;
+  float scale;
+  base::TimeDelta duration;
+};
+
 // A small helper class that does the math for zoom animations, primarily for
 // double-tap zoom. Initialize it with starting and ending scroll/page scale
 // positions and an animation length time, then call ...AtTime() at every frame
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 937aa77..0eb9621 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -125,6 +125,7 @@
   twin_layer_ = layer_impl;
   layer_impl->twin_layer_ = this;
 
+  layer_impl->set_is_mask(is_mask_);
   layer_impl->UpdateRasterSource(raster_source_);
 
   DCHECK_IMPLIES(raster_source_->IsSolidColor(), tilings_->num_tilings() == 0);
@@ -885,16 +886,6 @@
   return tiling;
 }
 
-void PictureLayerImpl::RemoveTiling(float contents_scale) {
-  if (!tilings_ || tilings_->num_tilings() == 0)
-    return;
-
-  tilings_->RemoveTilingWithScale(contents_scale);
-  if (tilings_->num_tilings() == 0)
-    ResetRasterScale();
-  SanityCheckTilingState();
-}
-
 void PictureLayerImpl::RemoveAllTilings() {
   if (tilings_)
     tilings_->RemoveAllTilings();
@@ -1096,7 +1087,6 @@
       raster_contents_scale_, ideal_contents_scale_);
   float max_acceptable_high_res_scale = std::max(
       raster_contents_scale_, ideal_contents_scale_);
-  float twin_low_res_scale = 0.f;
 
   PictureLayerImpl* twin = GetPendingOrActiveTwinLayer();
   if (twin && twin->CanHaveTilings()) {
@@ -1106,63 +1096,23 @@
     max_acceptable_high_res_scale = std::max(
         max_acceptable_high_res_scale,
         std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_));
-
-    // TODO(danakj): Remove the tilings_ check when we create them in the
-    // constructor.
-    if (twin->tilings_) {
-      PictureLayerTiling* tiling =
-          twin->tilings_->FindTilingWithResolution(LOW_RESOLUTION);
-      if (tiling)
-        twin_low_res_scale = tiling->contents_scale();
-    }
   }
 
-  // TODO(vmpstr): Put this logic into PictureLayerTilingSet.
-  std::vector<PictureLayerTiling*> to_remove;
-  for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
-    PictureLayerTiling* tiling = tilings_->tiling_at(i);
-
-    // Keep multiple high resolution tilings even if not used to help
-    // activate earlier at non-ideal resolutions.
-    if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
-        tiling->contents_scale() <= max_acceptable_high_res_scale)
-      continue;
-
-    // Keep low resolution tilings, if the layer should have them.
-    if (layer_tree_impl()->create_low_res_tiling()) {
-      if (tiling->resolution() == LOW_RESOLUTION ||
-          tiling->contents_scale() == twin_low_res_scale)
-        continue;
-    }
-
-    // Don't remove tilings that are being used (and thus would cause a flash.)
-    if (std::find(used_tilings.begin(), used_tilings.end(), tiling) !=
-        used_tilings.end())
-      continue;
-
-    to_remove.push_back(tiling);
-  }
-
-  if (to_remove.empty())
-    return;
-
+  PictureLayerTilingSet* twin_set = twin ? twin->tilings_.get() : nullptr;
   PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
-  // Remove tilings on this tree and the twin tree.
-  for (size_t i = 0; i < to_remove.size(); ++i) {
-    const PictureLayerTiling* twin_tiling =
-        GetPendingOrActiveTwinTiling(to_remove[i]);
-    // Only remove tilings from the twin layer if they have
-    // NON_IDEAL_RESOLUTION.
-    if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
-      twin->RemoveTiling(to_remove[i]->contents_scale());
-    // Remove the tiling from the recycle tree. Note that we ignore resolution,
-    // since we don't need to maintain high/low res on the recycle tree.
-    if (recycled_twin)
-      recycled_twin->RemoveTiling(to_remove[i]->contents_scale());
-    // TODO(enne): temporary sanity CHECK for http://crbug.com/358350
-    CHECK_NE(HIGH_RESOLUTION, to_remove[i]->resolution());
-    tilings_->Remove(to_remove[i]);
-  }
+  PictureLayerTilingSet* recycled_twin_set =
+      recycled_twin ? recycled_twin->tilings_.get() : nullptr;
+
+  tilings_->CleanUpTilings(min_acceptable_high_res_scale,
+                           max_acceptable_high_res_scale, used_tilings,
+                           layer_tree_impl()->create_low_res_tiling(), twin_set,
+                           recycled_twin_set);
+
+  if (twin_set && twin_set->num_tilings() == 0)
+    twin->ResetRasterScale();
+
+  if (recycled_twin_set && recycled_twin_set->num_tilings() == 0)
+    recycled_twin->ResetRasterScale();
 
   DCHECK_GT(tilings_->num_tilings(), 0u);
   SanityCheckTilingState();
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 12209a8..9a77546 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -144,6 +144,8 @@
 
   void RunMicroBenchmark(MicroBenchmarkImpl* benchmark) override;
 
+  bool CanHaveTilings() const;
+
   // Functions used by tile manager.
   PictureLayerImpl* GetPendingOrActiveTwinLayer() const;
   bool IsOnActiveOrPendingTree() const;
@@ -158,7 +160,6 @@
 
   PictureLayerImpl(LayerTreeImpl* tree_impl, int id);
   PictureLayerTiling* AddTiling(float contents_scale);
-  void RemoveTiling(float contents_scale);
   void RemoveAllTilings();
   void SyncFromActiveLayer(const PictureLayerImpl* other);
   void AddTilingsForRasterScale();
@@ -179,7 +180,6 @@
   }
   void DoPostCommitInitialization();
 
-  bool CanHaveTilings() const;
   bool CanHaveTilingWithScale(float contents_scale) const;
   void SanityCheckTilingState() const;
   // Checks if all tiles required for a certain action (e.g. activation) are
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 931e979..246e625 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -1226,6 +1226,15 @@
   EXPECT_NE(0u, mask_resource_id);
   EXPECT_EQ(mask_texture_size, active_layer_->bounds());
 
+  // Drop resources and recreate them, still the same.
+  old_pending_layer_->ReleaseResources();
+  active_layer_->ReleaseResources();
+  SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
+  active_layer_->HighResTiling()->CreateAllTilesForTesting();
+  EXPECT_EQ(1u, active_layer_->HighResTiling()->AllTilesForTesting().size());
+  EXPECT_NE(0u, mask_resource_id);
+  EXPECT_EQ(mask_texture_size, active_layer_->bounds());
+
   // Resize larger than the max texture size.
   int max_texture_size = host_impl_.GetRendererCapabilities().max_texture_size;
   scoped_refptr<FakePicturePileImpl> huge_pile =
@@ -1249,6 +1258,15 @@
   // The mask resource is empty.
   active_layer_->GetContentsResourceId(&mask_resource_id, &mask_texture_size);
   EXPECT_EQ(0u, mask_resource_id);
+
+  // Drop resources and recreate them, still the same.
+  old_pending_layer_->ReleaseResources();
+  active_layer_->ReleaseResources();
+  SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
+  active_layer_->HighResTiling()->CreateAllTilesForTesting();
+  EXPECT_EQ(0u, active_layer_->HighResTiling()->AllTilesForTesting().size());
+  active_layer_->GetContentsResourceId(&mask_resource_id, &mask_texture_size);
+  EXPECT_EQ(0u, mask_resource_id);
 }
 
 TEST_F(PictureLayerImplTest, ScaledMaskLayer) {
diff --git a/cc/layers/ui_resource_layer.cc b/cc/layers/ui_resource_layer.cc
index 944cf7d..9d711fe 100644
--- a/cc/layers/ui_resource_layer.cc
+++ b/cc/layers/ui_resource_layer.cc
@@ -107,23 +107,26 @@
 
   Layer::SetLayerTreeHost(host);
 
-  // Recreate the resource hold against the new LTH.
+  // Recreate the resource held against the new LTH.
   RecreateUIResourceHolder();
+
+  UpdateDrawsContent(HasDrawableContent());
 }
 
 void UIResourceLayer::RecreateUIResourceHolder() {
-  ui_resource_holder_ = nullptr;
-  if (layer_tree_host() && !bitmap_.empty()) {
-    ui_resource_holder_ =
-        ScopedUIResourceHolder::Create(layer_tree_host(), bitmap_);
-  }
-  UpdateDrawsContent(HasDrawableContent());
+  if (!bitmap_.empty())
+    SetBitmap(bitmap_);
 }
 
 void UIResourceLayer::SetBitmap(const SkBitmap& skbitmap) {
   bitmap_ = skbitmap;
-
-  RecreateUIResourceHolder();
+  if (layer_tree_host() && !bitmap_.empty()) {
+    ui_resource_holder_ =
+        ScopedUIResourceHolder::Create(layer_tree_host(), bitmap_);
+  } else {
+    ui_resource_holder_ = nullptr;
+  }
+  UpdateDrawsContent(HasDrawableContent());
   SetNeedsCommit();
 }
 
diff --git a/cc/layers/ui_resource_layer.h b/cc/layers/ui_resource_layer.h
index 3bfd9b2..dc2006e 100644
--- a/cc/layers/ui_resource_layer.h
+++ b/cc/layers/ui_resource_layer.h
@@ -26,7 +26,9 @@
 
   void SetBitmap(const SkBitmap& skbitmap);
 
-  // An alternative way of setting the resource to allow for sharing.
+  // An alternative way of setting the resource to allow for sharing. If you use
+  // this method, you are responsible for updating the ID if the layer moves
+  // between compositors.
   void SetUIResourceId(UIResourceId resource_id);
 
   // Sets a UV transform to be used at draw time. Defaults to (0, 0) and (1, 1).
@@ -62,8 +64,6 @@
   scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
   void RecreateUIResourceHolder();
 
-
-
   DISALLOW_COPY_AND_ASSIGN(UIResourceLayer);
 };
 
diff --git a/cc/layers/ui_resource_layer_unittest.cc b/cc/layers/ui_resource_layer_unittest.cc
index 09d57a9..239efb8 100644
--- a/cc/layers/ui_resource_layer_unittest.cc
+++ b/cc/layers/ui_resource_layer_unittest.cc
@@ -28,12 +28,29 @@
 namespace cc {
 namespace {
 
+class TestUIResourceLayer : public UIResourceLayer {
+ public:
+  static scoped_refptr<TestUIResourceLayer> Create() {
+    return make_scoped_refptr(new TestUIResourceLayer());
+  }
+
+  UIResourceId GetUIResourceId() {
+    if (ui_resource_holder_)
+      return ui_resource_holder_->id();
+    return 0;
+  }
+
+ protected:
+  TestUIResourceLayer() : UIResourceLayer() { SetIsDrawable(true); }
+  ~TestUIResourceLayer() override {}
+};
+
 class UIResourceLayerTest : public testing::Test {
  public:
   UIResourceLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
 
  protected:
-  virtual void SetUp() {
+  void SetUp() override {
     layer_tree_host_ = FakeLayerTreeHost::Create(&fake_client_);
     layer_tree_host_->InitializeSingleThreaded(
         &fake_client_,
@@ -41,7 +58,7 @@
         nullptr);
   }
 
-  virtual void TearDown() {
+  void TearDown() override {
     Mock::VerifyAndClearExpectations(layer_tree_host_.get());
   }
 
@@ -50,9 +67,8 @@
 };
 
 TEST_F(UIResourceLayerTest, SetBitmap) {
-  scoped_refptr<UIResourceLayer> test_layer = UIResourceLayer::Create();
+  scoped_refptr<UIResourceLayer> test_layer = TestUIResourceLayer::Create();
   ASSERT_TRUE(test_layer.get());
-  test_layer->SetIsDrawable(true);
   test_layer->SetBounds(gfx::Size(100, 100));
 
   layer_tree_host_->SetRootLayer(test_layer);
@@ -78,9 +94,8 @@
 }
 
 TEST_F(UIResourceLayerTest, SetUIResourceId) {
-  scoped_refptr<UIResourceLayer> test_layer = UIResourceLayer::Create();
+  scoped_refptr<TestUIResourceLayer> test_layer = TestUIResourceLayer::Create();
   ASSERT_TRUE(test_layer.get());
-  test_layer->SetIsDrawable(true);
   test_layer->SetBounds(gfx::Size(100, 100));
 
   layer_tree_host_->SetRootLayer(test_layer);
@@ -102,6 +117,15 @@
   test_layer->Update(&queue, &occlusion_tracker);
 
   EXPECT_TRUE(test_layer->DrawsContent());
+
+  // ID is preserved even when you set ID first and attach it to the tree.
+  layer_tree_host_->SetRootLayer(nullptr);
+  scoped_ptr<ScopedUIResource> shared_resource = ScopedUIResource::Create(
+      layer_tree_host_.get(), UIResourceBitmap(gfx::Size(5, 5), is_opaque));
+  test_layer->SetUIResourceId(shared_resource->id());
+  layer_tree_host_->SetRootLayer(test_layer);
+  EXPECT_EQ(shared_resource->id(), test_layer->GetUIResourceId());
+  EXPECT_TRUE(test_layer->DrawsContent());
 }
 
 }  // namespace
diff --git a/cc/output/begin_frame_args.cc b/cc/output/begin_frame_args.cc
index fc7098f..0be9318 100644
--- a/cc/output/begin_frame_args.cc
+++ b/cc/output/begin_frame_args.cc
@@ -9,6 +9,21 @@
 
 namespace cc {
 
+const char* BeginFrameArgs::TypeToString(BeginFrameArgsType type) {
+  switch (type) {
+    case BeginFrameArgs::INVALID:
+      return "INVALID";
+    case BeginFrameArgs::NORMAL:
+      return "NORMAL";
+    case BeginFrameArgs::SYNCHRONOUS:
+      return "SYNCHRONOUS";
+    case BeginFrameArgs::MISSED:
+      return "MISSED";
+  }
+  NOTREACHED();
+  return "???";
+}
+
 BeginFrameArgs::BeginFrameArgs()
     : frame_time(base::TimeTicks()),
       deadline(base::TimeTicks()),
@@ -26,19 +41,12 @@
       type(type) {
 }
 
-BeginFrameArgs BeginFrameArgs::CreateTyped(
-    base::TimeTicks frame_time,
-    base::TimeTicks deadline,
-    base::TimeDelta interval,
-    BeginFrameArgs::BeginFrameArgsType type) {
-  DCHECK_NE(type, BeginFrameArgs::INVALID);
-  return BeginFrameArgs(frame_time, deadline, interval, type);
-}
-
 BeginFrameArgs BeginFrameArgs::Create(base::TimeTicks frame_time,
                                       base::TimeTicks deadline,
-                                      base::TimeDelta interval) {
-  return CreateTyped(frame_time, deadline, interval, BeginFrameArgs::NORMAL);
+                                      base::TimeDelta interval,
+                                      BeginFrameArgs::BeginFrameArgsType type) {
+  DCHECK_NE(type, BeginFrameArgs::INVALID);
+  return BeginFrameArgs(frame_time, deadline, interval, type);
 }
 
 scoped_refptr<base::debug::ConvertableToTraceFormat> BeginFrameArgs::AsValue()
@@ -51,35 +59,12 @@
 
 void BeginFrameArgs::AsValueInto(base::debug::TracedValue* state) const {
   state->SetString("type", "BeginFrameArgs");
-  switch (type) {
-    case BeginFrameArgs::INVALID:
-      state->SetString("subtype", "INVALID");
-      break;
-    case BeginFrameArgs::NORMAL:
-      state->SetString("subtype", "NORMAL");
-      break;
-    case BeginFrameArgs::SYNCHRONOUS:
-      state->SetString("subtype", "SYNCHRONOUS");
-      break;
-    case BeginFrameArgs::MISSED:
-      state->SetString("subtype", "MISSED");
-      break;
-  }
+  state->SetString("subtype", TypeToString(type));
   state->SetDouble("frame_time_us", frame_time.ToInternalValue());
   state->SetDouble("deadline_us", deadline.ToInternalValue());
   state->SetDouble("interval_us", interval.InMicroseconds());
 }
 
-BeginFrameArgs BeginFrameArgs::CreateForSynchronousCompositor(
-    base::TimeTicks now) {
-  // For WebView/SynchronousCompositor, we always want to draw immediately,
-  // so we set the deadline to 0 and guess that the interval is 16 milliseconds.
-  if (now.is_null())
-    now = gfx::FrameTime::Now();
-  return CreateTyped(
-      now, base::TimeTicks(), DefaultInterval(), BeginFrameArgs::SYNCHRONOUS);
-}
-
 // This is a hard-coded deadline adjustment that assumes 60Hz, to be used in
 // cases where a good estimated draw time is not known. Using 1/3 of the vsync
 // as the default adjustment gives the Browser the last 1/3 of a frame to
diff --git a/cc/output/begin_frame_args.h b/cc/output/begin_frame_args.h
index c35a500..0be5241 100644
--- a/cc/output/begin_frame_args.h
+++ b/cc/output/begin_frame_args.h
@@ -26,6 +26,7 @@
     SYNCHRONOUS,
     MISSED,
   };
+  static const char* TypeToString(BeginFrameArgsType type);
 
   // Creates an invalid set of values.
   BeginFrameArgs();
@@ -34,13 +35,8 @@
   // created by searching for "BeginFrameArgs::Create".
   static BeginFrameArgs Create(base::TimeTicks frame_time,
                                base::TimeTicks deadline,
-                               base::TimeDelta interval);
-  static BeginFrameArgs CreateTyped(base::TimeTicks frame_time,
-                                    base::TimeTicks deadline,
-                                    base::TimeDelta interval,
-                                    BeginFrameArgsType type);
-  static BeginFrameArgs CreateForSynchronousCompositor(
-      base::TimeTicks now = base::TimeTicks());
+                               base::TimeDelta interval,
+                               BeginFrameArgsType type);
 
   // This is the default delta that will be used to adjust the deadline when
   // proper draw-time estimations are not yet available.
diff --git a/cc/output/begin_frame_args_unittest.cc b/cc/output/begin_frame_args_unittest.cc
index e0c8b3e..9d77a45 100644
--- a/cc/output/begin_frame_args_unittest.cc
+++ b/cc/output/begin_frame_args_unittest.cc
@@ -26,15 +26,29 @@
   EXPECT_EQ(1, args2.frame_time.ToInternalValue());
   EXPECT_EQ(2, args2.deadline.ToInternalValue());
   EXPECT_EQ(3, args2.interval.ToInternalValue());
+  EXPECT_EQ(BeginFrameArgs::NORMAL, args2.type);
 
   BeginFrameArgs args3 = CreateExpiredBeginFrameArgsForTesting();
   EXPECT_TRUE(args3.IsValid()) << args3;
   EXPECT_GT(gfx::FrameTime::Now(), args3.deadline);
+  EXPECT_EQ(BeginFrameArgs::NORMAL, args3.type);
+
+  BeginFrameArgs args4 =
+      CreateBeginFrameArgsForTesting(1, 2, 3, BeginFrameArgs::MISSED);
+  EXPECT_TRUE(args4.IsValid()) << args4;
+  EXPECT_EQ(1, args4.frame_time.ToInternalValue());
+  EXPECT_EQ(2, args4.deadline.ToInternalValue());
+  EXPECT_EQ(3, args4.interval.ToInternalValue());
+  EXPECT_EQ(BeginFrameArgs::MISSED, args4.type);
 
   // operator==
   EXPECT_EQ(CreateBeginFrameArgsForTesting(4, 5, 6),
             CreateBeginFrameArgsForTesting(4, 5, 6));
 
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_EQ(CreateBeginFrameArgsForTesting(7, 8, 9, BeginFrameArgs::MISSED),
+                CreateBeginFrameArgsForTesting(7, 8, 9)),
+      "");
   EXPECT_NONFATAL_FAILURE(EXPECT_EQ(CreateBeginFrameArgsForTesting(4, 5, 6),
                                     CreateBeginFrameArgsForTesting(7, 8, 9)),
                           "");
@@ -42,15 +56,15 @@
   // operator<<
   std::stringstream out1;
   out1 << args1;
-  EXPECT_EQ("BeginFrameArgs(0, 0, -1us)", out1.str());
+  EXPECT_EQ("BeginFrameArgs(NORMAL, 0, 0, -1us)", out1.str());
   std::stringstream out2;
   out2 << args2;
-  EXPECT_EQ("BeginFrameArgs(1, 2, 3us)", out2.str());
+  EXPECT_EQ("BeginFrameArgs(NORMAL, 1, 2, 3us)", out2.str());
 
   // PrintTo
-  EXPECT_EQ(std::string("BeginFrameArgs(0, 0, -1us)"),
+  EXPECT_EQ(std::string("BeginFrameArgs(NORMAL, 0, 0, -1us)"),
             ::testing::PrintToString(args1));
-  EXPECT_EQ(std::string("BeginFrameArgs(1, 2, 3us)"),
+  EXPECT_EQ(std::string("BeginFrameArgs(NORMAL, 1, 2, 3us)"),
             ::testing::PrintToString(args2));
 }
 
@@ -59,18 +73,15 @@
   BeginFrameArgs args1;
   EXPECT_FALSE(args1.IsValid()) << args1;
 
-  BeginFrameArgs args2 =
-      BeginFrameArgs::Create(base::TimeTicks::FromInternalValue(1),
-                             base::TimeTicks::FromInternalValue(2),
-                             base::TimeDelta::FromInternalValue(3));
+  BeginFrameArgs args2 = BeginFrameArgs::Create(
+      base::TimeTicks::FromInternalValue(1),
+      base::TimeTicks::FromInternalValue(2),
+      base::TimeDelta::FromInternalValue(3), BeginFrameArgs::NORMAL);
   EXPECT_TRUE(args2.IsValid()) << args2;
   EXPECT_EQ(1, args2.frame_time.ToInternalValue()) << args2;
   EXPECT_EQ(2, args2.deadline.ToInternalValue()) << args2;
   EXPECT_EQ(3, args2.interval.ToInternalValue()) << args2;
-
-  base::TimeTicks now = base::TimeTicks::FromInternalValue(1);
-  EXPECT_EQ(CreateBeginFrameArgsForTesting(1, 0, 16666),
-            BeginFrameArgs::CreateForSynchronousCompositor(now));
+  EXPECT_EQ(BeginFrameArgs::NORMAL, args2.type) << args2;
 }
 
 }  // namespace
diff --git a/cc/output/delegating_renderer.cc b/cc/output/delegating_renderer.cc
index dc951af..c05c32f 100644
--- a/cc/output/delegating_renderer.cc
+++ b/cc/output/delegating_renderer.cc
@@ -22,7 +22,7 @@
 
 scoped_ptr<DelegatingRenderer> DelegatingRenderer::Create(
     RendererClient* client,
-    const LayerTreeSettings* settings,
+    const RendererSettings* settings,
     OutputSurface* output_surface,
     ResourceProvider* resource_provider) {
   return make_scoped_ptr(new DelegatingRenderer(
@@ -30,7 +30,7 @@
 }
 
 DelegatingRenderer::DelegatingRenderer(RendererClient* client,
-                                       const LayerTreeSettings* settings,
+                                       const RendererSettings* settings,
                                        OutputSurface* output_surface,
                                        ResourceProvider* resource_provider)
     : Renderer(client, settings),
diff --git a/cc/output/delegating_renderer.h b/cc/output/delegating_renderer.h
index 89b47ad..b2bc01f 100644
--- a/cc/output/delegating_renderer.h
+++ b/cc/output/delegating_renderer.h
@@ -19,7 +19,7 @@
  public:
   static scoped_ptr<DelegatingRenderer> Create(
       RendererClient* client,
-      const LayerTreeSettings* settings,
+      const RendererSettings* settings,
       OutputSurface* output_surface,
       ResourceProvider* resource_provider);
   ~DelegatingRenderer() override;
@@ -39,7 +39,7 @@
 
  private:
   DelegatingRenderer(RendererClient* client,
-                     const LayerTreeSettings* settings,
+                     const RendererSettings* settings,
                      OutputSurface* output_surface,
                      ResourceProvider* resource_provider);
 
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc
index 50d82d0..93d7fb1 100644
--- a/cc/output/direct_renderer.cc
+++ b/cc/output/direct_renderer.cc
@@ -125,7 +125,7 @@
 }
 
 DirectRenderer::DirectRenderer(RendererClient* client,
-                               const LayerTreeSettings* settings,
+                               const RendererSettings* settings,
                                OutputSurface* output_surface,
                                ResourceProvider* resource_provider)
     : Renderer(client, settings),
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h
index 40fff83..e07cb93 100644
--- a/cc/output/direct_renderer.h
+++ b/cc/output/direct_renderer.h
@@ -59,7 +59,7 @@
 
  protected:
   DirectRenderer(RendererClient* client,
-                 const LayerTreeSettings* settings,
+                 const RendererSettings* settings,
                  OutputSurface* output_surface,
                  ResourceProvider* resource_provider);
 
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index cb6189e..49af1c3 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -289,7 +289,7 @@
 
 scoped_ptr<GLRenderer> GLRenderer::Create(
     RendererClient* client,
-    const LayerTreeSettings* settings,
+    const RendererSettings* settings,
     OutputSurface* output_surface,
     ResourceProvider* resource_provider,
     TextureMailboxDeleter* texture_mailbox_deleter,
@@ -303,7 +303,7 @@
 }
 
 GLRenderer::GLRenderer(RendererClient* client,
-                       const LayerTreeSettings* settings,
+                       const RendererSettings* settings,
                        OutputSurface* output_surface,
                        ResourceProvider* resource_provider,
                        TextureMailboxDeleter* texture_mailbox_deleter,
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index ecadebb..22e7706 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -49,7 +49,7 @@
 
   static scoped_ptr<GLRenderer> Create(
       RendererClient* client,
-      const LayerTreeSettings* settings,
+      const RendererSettings* settings,
       OutputSurface* output_surface,
       ResourceProvider* resource_provider,
       TextureMailboxDeleter* texture_mailbox_deleter,
@@ -74,7 +74,7 @@
 
  protected:
   GLRenderer(RendererClient* client,
-             const LayerTreeSettings* settings,
+             const RendererSettings* settings,
              OutputSurface* output_surface,
              ResourceProvider* resource_provider,
              TextureMailboxDeleter* texture_mailbox_deleter,
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 2af953e..2ac339d 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -172,7 +172,7 @@
 class FakeRendererGL : public GLRenderer {
  public:
   FakeRendererGL(RendererClient* client,
-                 const LayerTreeSettings* settings,
+                 const RendererSettings* settings,
                  OutputSurface* output_surface,
                  ResourceProvider* resource_provider)
       : GLRenderer(client,
@@ -215,7 +215,7 @@
 
   void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
 
-  LayerTreeSettings settings_;
+  RendererSettings settings_;
   FakeOutputSurfaceClient output_surface_client_;
   scoped_ptr<FakeOutputSurface> output_surface_;
   FakeRendererClient renderer_client_;
@@ -336,7 +336,7 @@
               renderer_->program_shadow_);
   }
 
-  LayerTreeSettings settings_;
+  RendererSettings settings_;
   FakeOutputSurfaceClient output_surface_client_;
   scoped_ptr<FakeOutputSurface> output_surface_;
   FakeRendererClient renderer_client_;
@@ -543,7 +543,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
                           &settings,
@@ -583,7 +583,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
                           &settings,
@@ -622,7 +622,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
                           &settings,
@@ -674,7 +674,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
                           &settings,
@@ -719,7 +719,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
                           &settings,
@@ -804,7 +804,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
                           &settings,
@@ -875,7 +875,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
                           &settings,
@@ -966,7 +966,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   settings.should_clear_root_render_pass = false;
 
   FakeRendererClient renderer_client;
@@ -1064,7 +1064,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
                           &settings,
@@ -1162,7 +1162,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   settings.partial_swap_enabled = true;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
@@ -1351,7 +1351,7 @@
                                false,
                                1));
 
-  LayerTreeSettings settings;
+  RendererSettings settings;
   FakeRendererClient renderer_client;
   FakeRendererGL renderer(&renderer_client,
                           &settings,
@@ -1814,7 +1814,7 @@
             ->TestContext3d());
   }
 
-  LayerTreeSettings settings_;
+  RendererSettings settings_;
   FakeOutputSurfaceClient output_surface_client_;
   StrictMock<MockOutputSurface> output_surface_;
   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index a3a297b..33c6f4a 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -524,7 +524,7 @@
 class OverlayInfoRendererGL : public GLRenderer {
  public:
   OverlayInfoRendererGL(RendererClient* client,
-                        const LayerTreeSettings* settings,
+                        const RendererSettings* settings,
                         OutputSurface* output_surface,
                         ResourceProvider* resource_provider)
       : GLRenderer(client,
@@ -601,7 +601,7 @@
 
   void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
 
-  LayerTreeSettings settings_;
+  RendererSettings settings_;
   FakeOutputSurfaceClient output_surface_client_;
   scoped_ptr<OverlayOutputSurface> output_surface_;
   FakeRendererClient renderer_client_;
diff --git a/cc/output/renderer.h b/cc/output/renderer.h
index 1953310..c92ce6f 100644
--- a/cc/output/renderer.h
+++ b/cc/output/renderer.h
@@ -80,13 +80,13 @@
   void SetVisible(bool visible);
 
  protected:
-  explicit Renderer(RendererClient* client, const LayerTreeSettings* settings)
+  Renderer(RendererClient* client, const RendererSettings* settings)
       : client_(client), settings_(settings), visible_(true) {}
 
   virtual void DidChangeVisibility() = 0;
 
   RendererClient* client_;
-  const LayerTreeSettings* settings_;
+  const RendererSettings* settings_;
   bool visible_;
 
  private:
diff --git a/cc/output/renderer_settings.cc b/cc/output/renderer_settings.cc
new file mode 100644
index 0000000..bacde5b
--- /dev/null
+++ b/cc/output/renderer_settings.cc
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/output/renderer_settings.h"
+
+#include <limits>
+
+#include "base/logging.h"
+
+namespace cc {
+
+RendererSettings::RendererSettings()
+    : allow_antialiasing(true),
+      force_antialiasing(false),
+      force_blending_with_shaders(false),
+      partial_swap_enabled(false),
+      should_clear_root_render_pass(true),
+      refresh_rate(60.0),
+      highp_threshold_min(0),
+      use_rgba_4444_textures(false),
+      texture_id_allocation_chunk_size(64) {
+}
+
+RendererSettings::~RendererSettings() {
+}
+
+}  // namespace cc
diff --git a/cc/output/renderer_settings.h b/cc/output/renderer_settings.h
new file mode 100644
index 0000000..748d230
--- /dev/null
+++ b/cc/output/renderer_settings.h
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_OUTPUT_RENDERER_SETTINGS_H_
+#define CC_OUTPUT_RENDERER_SETTINGS_H_
+
+#include "base/basictypes.h"
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+class CC_EXPORT RendererSettings {
+ public:
+  RendererSettings();
+  ~RendererSettings();
+
+  bool allow_antialiasing;
+  bool force_antialiasing;
+  bool force_blending_with_shaders;
+  bool partial_swap_enabled;
+  bool should_clear_root_render_pass;
+  double refresh_rate;
+  int highp_threshold_min;
+  bool use_rgba_4444_textures;
+  size_t texture_id_allocation_chunk_size;
+};
+
+}  // namespace cc
+
+#endif  // CC_OUTPUT_RENDERER_SETTINGS_H_
diff --git a/cc/output/renderer_unittest.cc b/cc/output/renderer_unittest.cc
index 6e43cc0..a8f09ff 100644
--- a/cc/output/renderer_unittest.cc
+++ b/cc/output/renderer_unittest.cc
@@ -50,14 +50,14 @@
 
 template <class T>
 scoped_ptr<Renderer> CreateRenderer(RendererClient* client,
-                                    const LayerTreeSettings* settings,
+                                    const RendererSettings* settings,
                                     OutputSurface* output_surface,
                                     ResourceProvider* resource_provider);
 
 template <>
 scoped_ptr<Renderer> CreateRenderer<DelegatingRenderer>(
     RendererClient* client,
-    const LayerTreeSettings* settings,
+    const RendererSettings* settings,
     OutputSurface* output_surface,
     ResourceProvider* resource_provider) {
   return DelegatingRenderer::Create(
@@ -67,7 +67,7 @@
 template <>
 scoped_ptr<Renderer> CreateRenderer<GLRenderer>(
     RendererClient* client,
-    const LayerTreeSettings* settings,
+    const RendererSettings* settings,
     OutputSurface* output_surface,
     ResourceProvider* resource_provider) {
   return GLRenderer::Create(
@@ -91,7 +91,7 @@
   }
 
   FakeRendererClient renderer_client_;
-  LayerTreeSettings tree_settings_;
+  RendererSettings tree_settings_;
   FakeOutputSurfaceClient output_surface_client_;
   scoped_refptr<MockContextProvider> context_provider_;
   scoped_ptr<OutputSurface> output_surface_;
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index 442cd8d..ddd3473 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -63,7 +63,7 @@
 
 scoped_ptr<SoftwareRenderer> SoftwareRenderer::Create(
     RendererClient* client,
-    const LayerTreeSettings* settings,
+    const RendererSettings* settings,
     OutputSurface* output_surface,
     ResourceProvider* resource_provider) {
   return make_scoped_ptr(new SoftwareRenderer(
@@ -71,7 +71,7 @@
 }
 
 SoftwareRenderer::SoftwareRenderer(RendererClient* client,
-                                   const LayerTreeSettings* settings,
+                                   const RendererSettings* settings,
                                    OutputSurface* output_surface,
                                    ResourceProvider* resource_provider)
     : DirectRenderer(client, settings, output_surface, resource_provider),
@@ -108,6 +108,7 @@
 void SoftwareRenderer::FinishDrawingFrame(DrawingFrame* frame) {
   TRACE_EVENT0("cc", "SoftwareRenderer::FinishDrawingFrame");
   current_framebuffer_lock_ = nullptr;
+  current_framebuffer_canvas_.clear();
   current_canvas_ = NULL;
   root_canvas_ = NULL;
 
@@ -151,6 +152,7 @@
 void SoftwareRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) {
   DCHECK(!output_surface_->HasExternalStencilTest());
   current_framebuffer_lock_ = nullptr;
+  current_framebuffer_canvas_.clear();
   current_canvas_ = root_canvas_;
 }
 
@@ -161,7 +163,9 @@
   current_framebuffer_lock_ = make_scoped_ptr(
       new ResourceProvider::ScopedWriteLockSoftware(
           resource_provider_, texture->id()));
-  current_canvas_ = current_framebuffer_lock_->sk_canvas();
+  current_framebuffer_canvas_ =
+      skia::AdoptRef(new SkCanvas(current_framebuffer_lock_->sk_bitmap()));
+  current_canvas_ = current_framebuffer_canvas_.get();
   InitializeViewport(frame,
                      target_rect,
                      gfx::Rect(target_rect.size()),
diff --git a/cc/output/software_renderer.h b/cc/output/software_renderer.h
index 2a672d5..99868c3 100644
--- a/cc/output/software_renderer.h
+++ b/cc/output/software_renderer.h
@@ -29,7 +29,7 @@
  public:
   static scoped_ptr<SoftwareRenderer> Create(
       RendererClient* client,
-      const LayerTreeSettings* settings,
+      const RendererSettings* settings,
       OutputSurface* output_surface,
       ResourceProvider* resource_provider);
 
@@ -63,7 +63,7 @@
       scoped_ptr<CopyOutputRequest> request) override;
 
   SoftwareRenderer(RendererClient* client,
-                   const LayerTreeSettings* settings,
+                   const RendererSettings* settings,
                    OutputSurface* output_surface,
                    ResourceProvider* resource_provider);
 
@@ -102,6 +102,7 @@
   SkPaint current_paint_;
   scoped_ptr<ResourceProvider::ScopedWriteLockSoftware>
       current_framebuffer_lock_;
+  skia::RefPtr<SkCanvas> current_framebuffer_canvas_;
   scoped_ptr<SoftwareFrameData> current_frame_data_;
 
   DISALLOW_COPY_AND_ASSIGN(SoftwareRenderer);
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc
index 60f75d9..ea584ee 100644
--- a/cc/output/software_renderer_unittest.cc
+++ b/cc/output/software_renderer_unittest.cc
@@ -86,7 +86,7 @@
   }
 
  protected:
-  LayerTreeSettings settings_;
+  RendererSettings settings_;
   FakeOutputSurfaceClient output_surface_client_;
   scoped_ptr<FakeOutputSurface> output_surface_;
   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
diff --git a/cc/resources/bitmap_raster_worker_pool.cc b/cc/resources/bitmap_raster_worker_pool.cc
index 3b3739a..a7adf4e 100644
--- a/cc/resources/bitmap_raster_worker_pool.cc
+++ b/cc/resources/bitmap_raster_worker_pool.cc
@@ -21,17 +21,20 @@
  public:
   RasterBufferImpl(ResourceProvider* resource_provider,
                    const Resource* resource)
-      : lock_(resource_provider, resource->id()) {}
+      : lock_(resource_provider, resource->id()), resource_(resource) {}
 
   // Overridden from RasterBuffer:
   void Playback(const RasterSource* raster_source,
                 const gfx::Rect& rect,
                 float scale) override {
-    raster_source->PlaybackToCanvas(lock_.sk_canvas(), rect, scale);
+    RasterWorkerPool::PlaybackToMemory(lock_.sk_bitmap().getPixels(),
+                                       resource_->format(), resource_->size(),
+                                       0, raster_source, rect, scale);
   }
 
  private:
   ResourceProvider::ScopedWriteLockSoftware lock_;
+  const Resource* resource_;
 
   DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
 };
diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc
index 35170a0..51896a5 100644
--- a/cc/resources/picture_layer_tiling_set.cc
+++ b/cc/resources/picture_layer_tiling_set.cc
@@ -6,6 +6,7 @@
 
 #include <limits>
 #include <set>
+#include <vector>
 
 namespace cc {
 
@@ -50,6 +51,68 @@
     tilings_[i]->RemoveTilesInRegion(region);
 }
 
+void PictureLayerTilingSet::CleanUpTilings(
+    float min_acceptable_high_res_scale,
+    float max_acceptable_high_res_scale,
+    const std::vector<PictureLayerTiling*>& needed_tilings,
+    bool should_have_low_res,
+    PictureLayerTilingSet* twin_set,
+    PictureLayerTilingSet* recycled_twin_set) {
+  float twin_low_res_scale = 0.f;
+  if (twin_set) {
+    PictureLayerTiling* tiling =
+        twin_set->FindTilingWithResolution(LOW_RESOLUTION);
+    if (tiling)
+      twin_low_res_scale = tiling->contents_scale();
+  }
+
+  std::vector<PictureLayerTiling*> to_remove;
+  for (auto* tiling : tilings_) {
+    // Keep all tilings within the min/max scales.
+    if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
+        tiling->contents_scale() <= max_acceptable_high_res_scale) {
+      continue;
+    }
+
+    // Keep low resolution tilings, if the tiling set should have them.
+    if (should_have_low_res &&
+        (tiling->resolution() == LOW_RESOLUTION ||
+         tiling->contents_scale() == twin_low_res_scale)) {
+      continue;
+    }
+
+    // Don't remove tilings that are required.
+    if (std::find(needed_tilings.begin(), needed_tilings.end(), tiling) !=
+        needed_tilings.end()) {
+      continue;
+    }
+
+    to_remove.push_back(tiling);
+  }
+
+  for (auto* tiling : to_remove) {
+    PictureLayerTiling* twin_tiling =
+        twin_set ? twin_set->FindTilingWithScale(tiling->contents_scale())
+                 : nullptr;
+    // Only remove tilings from the twin layer if they have
+    // NON_IDEAL_RESOLUTION.
+    if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
+      twin_set->Remove(twin_tiling);
+
+    PictureLayerTiling* recycled_twin_tiling =
+        recycled_twin_set
+            ? recycled_twin_set->FindTilingWithScale(tiling->contents_scale())
+            : nullptr;
+    // Remove the tiling from the recycle tree. Note that we ignore resolution,
+    // since we don't need to maintain high/low res on the recycle set.
+    if (recycled_twin_tiling)
+      recycled_twin_set->Remove(recycled_twin_tiling);
+
+    DCHECK_NE(HIGH_RESOLUTION, tiling->resolution());
+    Remove(tiling);
+  }
+}
+
 void PictureLayerTilingSet::MarkAllTilingsNonIdeal() {
   for (auto* tiling : tilings_)
     tiling->set_resolution(NON_IDEAL_RESOLUTION);
@@ -171,16 +234,6 @@
   tilings_.erase(iter);
 }
 
-void PictureLayerTilingSet::RemoveTilingWithScale(float scale) {
-  auto iter = std::find_if(tilings_.begin(), tilings_.end(),
-                           [scale](const PictureLayerTiling* tiling) {
-    return tiling->contents_scale() == scale;
-  });
-  if (iter == tilings_.end())
-    return;
-  tilings_.erase(iter);
-}
-
 void PictureLayerTilingSet::RemoveAllTiles() {
   for (size_t i = 0; i < tilings_.size(); ++i)
     tilings_[i]->Reset();
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h
index 661dd24..f0d0fd7 100644
--- a/cc/resources/picture_layer_tiling_set.h
+++ b/cc/resources/picture_layer_tiling_set.h
@@ -6,6 +6,7 @@
 #define CC_RESOURCES_PICTURE_LAYER_TILING_SET_H_
 
 #include <set>
+#include <vector>
 
 #include "cc/base/region.h"
 #include "cc/base/scoped_ptr_vector.h"
@@ -45,6 +46,12 @@
   const PictureLayerTilingClient* client() const { return client_; }
 
   void RemoveTilesInRegion(const Region& region);
+  void CleanUpTilings(float min_acceptable_high_res_scale,
+                      float max_acceptable_high_res_scale,
+                      const std::vector<PictureLayerTiling*>& needed_tilings,
+                      bool should_have_low_res,
+                      PictureLayerTilingSet* twin_set,
+                      PictureLayerTilingSet* recycled_twin_set);
 
   // Make this set of tilings match the same set of content scales from |other|.
   // Delete any tilings that don't meet |minimum_contents_scale|.  Recreate
@@ -85,10 +92,6 @@
   // Remove all tilings.
   void RemoveAllTilings();
 
-  // Remove one tiling.
-  void Remove(PictureLayerTiling* tiling);
-  void RemoveTilingWithScale(float scale);
-
   // Remove all tiles; keep all tilings.
   void RemoveAllTiles();
 
@@ -154,6 +157,9 @@
  private:
   explicit PictureLayerTilingSet(PictureLayerTilingClient* client);
 
+  // Remove one tiling.
+  void Remove(PictureLayerTiling* tiling);
+
   PictureLayerTilingClient* client_;
   ScopedPtrVector<PictureLayerTiling> tilings_;
 
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc
index 97cd127..d94ce7c 100644
--- a/cc/resources/picture_pile.cc
+++ b/cc/resources/picture_pile.cc
@@ -106,18 +106,17 @@
          static_cast<float>(total_record_area);
 }
 
-float ClusterTiles(const std::vector<gfx::Rect>& invalid_tiles,
-                   std::vector<gfx::Rect>* record_rects) {
+void ClusterTiles(const std::vector<gfx::Rect>& invalid_tiles,
+                  std::vector<gfx::Rect>* record_rects) {
   TRACE_EVENT1("cc", "ClusterTiles",
                "count",
                invalid_tiles.size());
-
   if (invalid_tiles.size() <= 1) {
     // Quickly handle the special case for common
     // single-invalidation update, and also the less common
     // case of no tiles passed in.
     *record_rects = invalid_tiles;
-    return 1;
+    return;
   }
 
   // Sort the invalid tiles by y coordinate.
@@ -126,15 +125,14 @@
             invalid_tiles_vertical.end(),
             rect_sort_y);
 
-  float vertical_density;
   std::vector<gfx::Rect> vertical_clustering;
-  vertical_density = PerformClustering(invalid_tiles_vertical,
-                                       &vertical_clustering);
+  float vertical_density =
+      PerformClustering(invalid_tiles_vertical, &vertical_clustering);
 
   // If vertical density is optimal, then we can return early.
   if (vertical_density == 1.f) {
     *record_rects = vertical_clustering;
-    return vertical_density;
+    return;
   }
 
   // Now try again with a horizontal sort, see which one is best
@@ -143,18 +141,16 @@
             invalid_tiles_horizontal.end(),
             rect_sort_x);
 
-  float horizontal_density;
   std::vector<gfx::Rect> horizontal_clustering;
-  horizontal_density = PerformClustering(invalid_tiles_horizontal,
-                                         &horizontal_clustering);
+  float horizontal_density =
+      PerformClustering(invalid_tiles_horizontal, &horizontal_clustering);
 
   if (vertical_density < horizontal_density) {
     *record_rects = horizontal_clustering;
-    return horizontal_density;
+    return;
   }
 
   *record_rects = vertical_clustering;
-  return vertical_density;
 }
 
 }  // namespace
@@ -190,6 +186,37 @@
   bool can_use_lcd_text_changed = can_use_lcd_text_ != can_use_lcd_text;
   can_use_lcd_text_ = can_use_lcd_text;
 
+  gfx::Rect interest_rect = visible_layer_rect;
+  interest_rect.Inset(-pixel_record_distance_, -pixel_record_distance_);
+  recorded_viewport_ = interest_rect;
+  recorded_viewport_.Intersect(gfx::Rect(layer_size));
+
+  bool updated =
+      ApplyInvalidationAndResize(interest_rect, invalidation, layer_size,
+                                 frame_number, can_use_lcd_text_changed);
+  std::vector<gfx::Rect> invalid_tiles;
+  GetInvalidTileRects(interest_rect, invalidation, visible_layer_rect,
+                      frame_number, &invalid_tiles);
+  std::vector<gfx::Rect> record_rects;
+  ClusterTiles(invalid_tiles, &record_rects);
+
+  if (record_rects.empty())
+    return updated;
+
+  CreatePictures(painter, recording_mode, record_rects);
+
+  DetermineIfSolidColor();
+
+  has_any_recordings_ = true;
+  DCHECK(CanRasterSlowTileCheck(recorded_viewport_));
+  return true;
+}
+
+bool PicturePile::ApplyInvalidationAndResize(const gfx::Rect& interest_rect,
+                                             Region* invalidation,
+                                             const gfx::Size& layer_size,
+                                             int frame_number,
+                                             bool can_use_lcd_text_changed) {
   bool updated = false;
 
   Region synthetic_invalidation;
@@ -207,22 +234,17 @@
     updated = true;
   }
 
-  gfx::Rect interest_rect = visible_layer_rect;
-  interest_rect.Inset(-pixel_record_distance_, -pixel_record_distance_);
-  recorded_viewport_ = interest_rect;
-  recorded_viewport_.Intersect(gfx::Rect(GetSize()));
-
   gfx::Rect interest_rect_over_tiles =
       tiling_.ExpandRectToTileBounds(interest_rect);
 
-  gfx::Size min_tiling_size(
-      std::min(GetSize().width(), old_tiling_size.width()),
-      std::min(GetSize().height(), old_tiling_size.height()));
-  gfx::Size max_tiling_size(
-      std::max(GetSize().width(), old_tiling_size.width()),
-      std::max(GetSize().height(), old_tiling_size.height()));
-
   if (old_tiling_size != layer_size) {
+    gfx::Size min_tiling_size(
+        std::min(GetSize().width(), old_tiling_size.width()),
+        std::min(GetSize().height(), old_tiling_size.height()));
+    gfx::Size max_tiling_size(
+        std::max(GetSize().width(), old_tiling_size.width()),
+        std::max(GetSize().height(), old_tiling_size.height()));
+
     has_any_recordings_ = false;
 
     // Drop recordings that are outside the new or old layer bounds or that
@@ -240,12 +262,10 @@
       min_toss_y =
           tiling_.FirstBorderTileYIndexFromSrcCoord(min_tiling_size.height());
     }
-    for (PictureMap::const_iterator it = picture_map_.begin();
-         it != picture_map_.end();
-         ++it) {
-      const PictureMapKey& key = it->first;
+    for (const auto& key_picture_pair : picture_map_) {
+      const PictureMapKey& key = key_picture_pair.first;
       if (key.first < min_toss_x && key.second < min_toss_y) {
-        has_any_recordings_ |= !!it->second.GetPicture();
+        has_any_recordings_ |= !!key_picture_pair.second.GetPicture();
         continue;
       }
       to_erase.push_back(key);
@@ -472,10 +492,16 @@
   }
 
   invalidation->Union(synthetic_invalidation);
+  return updated;
+}
 
+void PicturePile::GetInvalidTileRects(const gfx::Rect& interest_rect,
+                                      Region* invalidation,
+                                      const gfx::Rect& visible_layer_rect,
+                                      int frame_number,
+                                      std::vector<gfx::Rect>* invalid_tiles) {
   // Make a list of all invalid tiles; we will attempt to
   // cluster these into multiple invalidation regions.
-  std::vector<gfx::Rect> invalid_tiles;
   bool include_borders = true;
   for (TilingData::Iterator it(&tiling_, interest_rect, include_borders); it;
        ++it) {
@@ -488,7 +514,7 @@
 
     if (info.NeedsRecording(frame_number, distance_to_visible)) {
       gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
-      invalid_tiles.push_back(tile);
+      invalid_tiles->push_back(tile);
     } else if (!info.GetPicture()) {
       if (recorded_viewport_.Intersects(rect)) {
         // Recorded viewport is just an optimization for a fully recorded
@@ -504,18 +530,13 @@
       invalidation->Union(tiling_.TileBounds(it.index_x(), it.index_y()));
     }
   }
+}
 
-  std::vector<gfx::Rect> record_rects;
-  ClusterTiles(invalid_tiles, &record_rects);
-
-  if (record_rects.empty())
-    return updated;
-
-  for (std::vector<gfx::Rect>::iterator it = record_rects.begin();
-       it != record_rects.end();
-       it++) {
-    gfx::Rect record_rect = *it;
-    record_rect = PadRect(record_rect);
+void PicturePile::CreatePictures(ContentLayerClient* painter,
+                                 Picture::RecordingMode recording_mode,
+                                 const std::vector<gfx::Rect>& record_rects) {
+  for (const auto& record_rect : record_rects) {
+    gfx::Rect padded_record_rect = PadRect(record_rect);
 
     int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
     scoped_refptr<Picture> picture;
@@ -526,44 +547,34 @@
     // Picture::Create.
     bool gather_pixel_refs = RasterWorkerPool::GetNumRasterThreads() > 1;
 
-    {
-      for (int i = 0; i < repeat_count; i++) {
-        picture = Picture::Create(record_rect,
-                                  painter,
-                                  tile_grid_info_,
-                                  gather_pixel_refs,
-                                  recording_mode);
-        // Note the '&&' with previous is-suitable state.
-        // This means that once a picture-pile becomes unsuitable for gpu
-        // rasterization due to some content, it will continue to be unsuitable
-        // even if that content is replaced by gpu-friendly content.
-        // This is an optimization to avoid iterating though all pictures in
-        // the pile after each invalidation.
-        is_suitable_for_gpu_rasterization_ &=
-            picture->IsSuitableForGpuRasterization();
-      }
+    for (int i = 0; i < repeat_count; i++) {
+      picture = Picture::Create(padded_record_rect, painter, tile_grid_info_,
+                                gather_pixel_refs, recording_mode);
+      // Note the '&&' with previous is-suitable state.
+      // This means that once a picture-pile becomes unsuitable for gpu
+      // rasterization due to some content, it will continue to be unsuitable
+      // even if that content is replaced by gpu-friendly content.
+      // This is an optimization to avoid iterating though all pictures in
+      // the pile after each invalidation.
+      is_suitable_for_gpu_rasterization_ &=
+          picture->IsSuitableForGpuRasterization();
     }
 
     bool found_tile_for_recorded_picture = false;
 
     bool include_borders = true;
-    for (TilingData::Iterator it(&tiling_, record_rect, include_borders); it;
-         ++it) {
+    for (TilingData::Iterator it(&tiling_, padded_record_rect, include_borders);
+         it; ++it) {
       const PictureMapKey& key = it.index();
       gfx::Rect tile = PaddedRect(key);
-      if (record_rect.Contains(tile)) {
+      if (padded_record_rect.Contains(tile)) {
         PictureInfo& info = picture_map_[key];
         info.SetPicture(picture);
         found_tile_for_recorded_picture = true;
       }
     }
-    DetermineIfSolidColor();
     DCHECK(found_tile_for_recorded_picture);
   }
-
-  has_any_recordings_ = true;
-  DCHECK(CanRasterSlowTileCheck(recorded_viewport_));
-  return true;
 }
 
 scoped_refptr<RasterSource> PicturePile::CreateRasterSource() const {
diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h
index e1c1b46..fd1c454 100644
--- a/cc/resources/picture_pile.h
+++ b/cc/resources/picture_pile.h
@@ -7,6 +7,7 @@
 
 #include <bitset>
 #include <utility>
+#include <vector>
 
 #include "base/containers/hash_tables.h"
 #include "base/memory/ref_counted.h"
@@ -106,6 +107,19 @@
  private:
   friend class PicturePileImpl;
 
+  void CreatePictures(ContentLayerClient* painter,
+                      Picture::RecordingMode recording_mode,
+                      const std::vector<gfx::Rect>& record_rects);
+  void GetInvalidTileRects(const gfx::Rect& interest_rect,
+                           Region* invalidation,
+                           const gfx::Rect& visible_layer_rect,
+                           int frame_number,
+                           std::vector<gfx::Rect>* invalid_tiles);
+  bool ApplyInvalidationAndResize(const gfx::Rect& interest_rect,
+                                  Region* invalidation,
+                                  const gfx::Size& layer_size,
+                                  int frame_number,
+                                  bool can_use_lcd_text_changed);
   void DetermineIfSolidColor();
   void SetBufferPixels(int buffer_pixels);
 
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 06bb5f0..636e797 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -794,9 +794,9 @@
     image += source_offset.y() * image_row_bytes + source_offset.x() * 4;
 
     ScopedWriteLockSoftware lock(this, id);
-    SkCanvas* dest = lock.sk_canvas();
-    dest->writePixels(
-        source_info, image, image_row_bytes, dest_offset.x(), dest_offset.y());
+    SkCanvas dest(lock.sk_bitmap());
+    dest.writePixels(source_info, image, image_row_bytes, dest_offset.x(),
+                     dest_offset.y());
   }
 }
 
@@ -1038,7 +1038,6 @@
       resource_(resource_provider->LockForWrite(resource_id)) {
   ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
   DCHECK(valid());
-  sk_canvas_.reset(new SkCanvas(sk_bitmap_));
 }
 
 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
@@ -2077,7 +2076,7 @@
   DCHECK(dest_resource->origin == Resource::Internal);
   DCHECK_EQ(dest_resource->exported_count, 0);
   DCHECK_EQ(GLTexture, dest_resource->type);
-  LazyCreate(dest_resource);
+  LazyAllocate(dest_resource);
 
   DCHECK_EQ(source_resource->type, dest_resource->type);
   DCHECK_EQ(source_resource->format, dest_resource->format);
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index c2f349f..bfd3ebb 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -296,14 +296,13 @@
                             ResourceProvider::ResourceId resource_id);
     ~ScopedWriteLockSoftware();
 
-    SkCanvas* sk_canvas() { return sk_canvas_.get(); }
+    SkBitmap& sk_bitmap() { return sk_bitmap_; }
     bool valid() const { return !!sk_bitmap_.getPixels(); }
 
    private:
     ResourceProvider* resource_provider_;
     ResourceProvider::Resource* resource_;
     SkBitmap sk_bitmap_;
-    scoped_ptr<SkCanvas> sk_canvas_;
     base::ThreadChecker thread_checker_;
 
     DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockSoftware);
@@ -599,21 +598,24 @@
   DISALLOW_COPY_AND_ASSIGN(ResourceProvider);
 };
 
-
 // TODO(epenner): Move these format conversions to resource_format.h
 // once that builds on mac (npapi.h currently #includes OpenGL.h).
 inline unsigned BitsPerPixel(ResourceFormat format) {
-  DCHECK_LE(format, RESOURCE_FORMAT_MAX);
-  static const unsigned format_bits_per_pixel[RESOURCE_FORMAT_MAX + 1] = {
-    32,  // RGBA_8888
-    16,  // RGBA_4444
-    32,  // BGRA_8888
-    8,   // ALPHA_8
-    8,   // LUMINANCE_8
-    16,  // RGB_565,
-    4    // ETC1
-  };
-  return format_bits_per_pixel[format];
+  switch (format) {
+    case BGRA_8888:
+    case RGBA_8888:
+      return 32;
+    case RGBA_4444:
+    case RGB_565:
+      return 16;
+    case ALPHA_8:
+    case LUMINANCE_8:
+      return 8;
+    case ETC1:
+      return 4;
+  }
+  NOTREACHED();
+  return 0;
 }
 
 inline GLenum GLDataType(ResourceFormat format) {
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index d8bfe4c..34b604a 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -3416,6 +3416,10 @@
       .WillOnce(Return(kDestTextureId))
       .RetiresOnSaturation();
   EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
+      .Times(2)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA,
+                                   GL_UNSIGNED_BYTE, nullptr))
       .Times(1)
       .RetiresOnSaturation();
   EXPECT_CALL(*context, NextTextureId())
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
index 01a6042..7a775d9 100644
--- a/cc/resources/video_resource_updater.cc
+++ b/cc/resources/video_resource_updater.cc
@@ -249,7 +249,8 @@
     {
       ResourceProvider::ScopedWriteLockSoftware lock(
           resource_provider_, plane_resources[0].resource_id);
-      video_renderer_->Copy(video_frame, lock.sk_canvas());
+      SkCanvas canvas(lock.sk_bitmap());
+      video_renderer_->Copy(video_frame, &canvas);
     }
 
     RecycleResourceData recycle_data = {
diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc
index dd6cdbe..5252dcc 100644
--- a/cc/scheduler/begin_frame_source.cc
+++ b/cc/scheduler/begin_frame_source.cc
@@ -181,10 +181,9 @@
     return;
 
   base::TimeTicks now = Now();
-  BeginFrameArgs args =
-      BeginFrameArgs::Create(now,
-                             now + BeginFrameArgs::DefaultInterval(),
-                             BeginFrameArgs::DefaultInterval());
+  BeginFrameArgs args = BeginFrameArgs::Create(
+      now, now + BeginFrameArgs::DefaultInterval(),
+      BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
   CallOnBeginFrame(args);
 }
 
@@ -243,8 +242,8 @@
     base::TimeTicks frame_time,
     BeginFrameArgs::BeginFrameArgsType type) {
   base::TimeTicks deadline = time_source_->NextTickTime();
-  return BeginFrameArgs::CreateTyped(
-      frame_time, deadline, time_source_->Interval(), type);
+  return BeginFrameArgs::Create(frame_time, deadline, time_source_->Interval(),
+                                type);
 }
 
 // TimeSourceClient support
diff --git a/cc/scheduler/begin_frame_source_unittest.cc b/cc/scheduler/begin_frame_source_unittest.cc
index a4b3d6e..498d10b 100644
--- a/cc/scheduler/begin_frame_source_unittest.cc
+++ b/cc/scheduler/begin_frame_source_unittest.cc
@@ -38,13 +38,13 @@
 
 // Macros to send BeginFrameArgs on a FakeBeginFrameSink (and verify resulting
 // observer behaviour).
-#define SEND_BEGIN_FRAME(                                               \
-    args_equal_to, source, frame_time, deadline, interval)              \
+#define SEND_BEGIN_FRAME(args_equal_to, source, frame_time, deadline,   \
+                         interval)                                      \
   {                                                                     \
     BeginFrameArgs old_args = (source).TestLastUsedBeginFrameArgs();    \
     BeginFrameArgs new_args =                                           \
         CreateBeginFrameArgsForTesting(frame_time, deadline, interval); \
-    ASSERT_TRUE(!(old_args == new_args));                               \
+    ASSERT_FALSE(old_args == new_args);                                 \
     (source).TestOnBeginFrame(new_args);                                \
     EXPECT_EQ(args_equal_to, (source).TestLastUsedBeginFrameArgs());    \
   }
@@ -494,9 +494,8 @@
 TEST_F(SyntheticBeginFrameSourceTest,
        SetNeedsBeginFramesCallsOnBeginFrameWithMissedTick) {
   now_src_->SetNowMicroseconds(10010);
-  EXPECT_CALL((*obs_),
-              OnBeginFrame(CreateTypedBeginFrameArgsForTesting(
-                  10000, 20000, 10000, BeginFrameArgs::MISSED)));
+  EXPECT_CALL((*obs_), OnBeginFrame(CreateBeginFrameArgsForTesting(
+                           10000, 20000, 10000, BeginFrameArgs::MISSED)));
   source_->SetNeedsBeginFrames(true);  // Should cause the last tick to be sent
   // No tasks should need to be run for this to occur.
 }
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index b190988..3e6f6c6 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -393,6 +393,21 @@
 bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) {
   TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue());
 
+  // Deliver BeginFrames to children.
+  if (settings_.forward_begin_frames_to_children &&
+      state_machine_.children_need_begin_frames()) {
+    BeginFrameArgs adjusted_args_for_children(args);
+    // Adjust a deadline for child schedulers.
+    // TODO(simonhong): Once we have commitless update, we can get rid of
+    // BeginMainFrameToCommitDurationEstimate() +
+    // CommitToActivateDurationEstimate().
+    adjusted_args_for_children.deadline -=
+        (client_->BeginMainFrameToCommitDurationEstimate() +
+         client_->CommitToActivateDurationEstimate() +
+         client_->DrawDurationEstimate() + EstimatedParentDrawTime());
+    client_->SendBeginFramesToChildren(adjusted_args_for_children);
+  }
+
   // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has
   // sent us the last BeginFrame we have missed. As we might not be able to
   // actually make rendering for this call, handle it like a "retro frame".
@@ -428,6 +443,12 @@
   return true;
 }
 
+void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
+  DCHECK(settings_.forward_begin_frames_to_children);
+  state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames);
+  DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE);
+}
+
 // BeginRetroFrame is called for BeginFrames that we've deferred because
 // the scheduler was in the middle of processing a previous BeginFrame.
 void Scheduler::BeginRetroFrame() {
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index 2a924f1..ef52ccf 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -48,6 +48,7 @@
   virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() = 0;
   virtual base::TimeDelta CommitToActivateDurationEstimate() = 0;
   virtual void DidBeginImplFrameDeadline() = 0;
+  virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) = 0;
 
  protected:
   virtual ~SchedulerClient() {}
@@ -93,6 +94,9 @@
 
   ~Scheduler() override;
 
+  // BeginFrameObserverMixin
+  bool OnBeginFrameMixInDelegate(const BeginFrameArgs& args) override;
+
   // base::PowerObserver method.
   void OnPowerStateChange(bool on_battery_power) override;
 
@@ -164,8 +168,7 @@
     state_machine_.SetContinuousPainting(continuous_painting);
   }
 
-  // BeginFrameObserverMixin
-  bool OnBeginFrameMixInDelegate(const BeginFrameArgs& args) override;
+  void SetChildrenNeedBeginFrames(bool children_need_begin_frames);
 
  protected:
   Scheduler(SchedulerClient* client,
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index 82b13d7..5f56255 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -47,7 +47,8 @@
       skip_next_begin_main_frame_to_reduce_latency_(false),
       skip_begin_main_frame_to_reduce_latency_(false),
       continuous_painting_(false),
-      impl_latency_takes_priority_on_battery_(false) {
+      impl_latency_takes_priority_on_battery_(false),
+      children_need_begin_frames_(false) {
 }
 
 const char* SchedulerStateMachine::OutputSurfaceStateToString(
@@ -234,6 +235,7 @@
   state->SetBoolean("continuous_painting", continuous_painting_);
   state->SetBoolean("impl_latency_takes_priority_on_battery",
                     impl_latency_takes_priority_on_battery_);
+  state->SetBoolean("children_need_begin_frames", children_need_begin_frames_);
   state->EndDictionary();
 }
 
@@ -672,16 +674,28 @@
   skip_next_begin_main_frame_to_reduce_latency_ = true;
 }
 
+bool SchedulerStateMachine::BeginFrameNeededForChildren() const {
+  if (HasInitializedOutputSurface())
+    return children_need_begin_frames_;
+
+  return false;
+}
+
 bool SchedulerStateMachine::BeginFrameNeeded() const {
+  if (SupportsProactiveBeginFrame()) {
+    return (BeginFrameNeededToAnimateOrDraw() ||
+            BeginFrameNeededForChildren() ||
+            ProactiveBeginFrameWanted());
+  }
+
   // Proactive BeginFrames are bad for the synchronous compositor because we
   // have to draw when we get the BeginFrame and could end up drawing many
   // duplicate frames if our new frame isn't ready in time.
   // To poll for state with the synchronous compositor without having to draw,
   // we rely on ShouldPollForAnticipatedDrawTriggers instead.
-  if (!SupportsProactiveBeginFrame())
-    return BeginFrameNeededToAnimateOrDraw();
-
-  return BeginFrameNeededToAnimateOrDraw() || ProactiveBeginFrameWanted();
+  // Synchronous compositor doesn't have a browser.
+  DCHECK(!children_need_begin_frames_);
+  return BeginFrameNeededToAnimateOrDraw();
 }
 
 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
@@ -707,6 +721,12 @@
   return !settings_.using_synchronous_renderer_compositor;
 }
 
+void SchedulerStateMachine::SetChildrenNeedBeginFrames(
+    bool children_need_begin_frames) {
+  DCHECK(settings_.forward_begin_frames_to_children);
+  children_need_begin_frames_ = children_need_begin_frames;
+}
+
 // These are the cases where we definitely (or almost definitely) have a
 // new frame to animate and/or draw and can draw.
 bool SchedulerStateMachine::BeginFrameNeededToAnimateOrDraw() const {
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index 489ece6..c69c959 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -247,8 +247,14 @@
   // We should remove it afterwards.
   std::string GetStatesForDebugging() const;
 
+  void SetChildrenNeedBeginFrames(bool children_need_begin_frames);
+  bool children_need_begin_frames() const {
+    return children_need_begin_frames_;
+  }
+
  protected:
   bool BeginFrameNeededToAnimateOrDraw() const;
+  bool BeginFrameNeededForChildren() const;
   bool ProactiveBeginFrameWanted() const;
 
   // True if we need to force activations to make forward progress.
@@ -316,6 +322,7 @@
   bool skip_begin_main_frame_to_reduce_latency_;
   bool continuous_painting_;
   bool impl_latency_takes_priority_on_battery_;
+  bool children_need_begin_frames_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc
index 85160ed..af6d83a 100644
--- a/cc/scheduler/scheduler_state_machine_unittest.cc
+++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -1823,5 +1823,20 @@
       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
 }
 
+TEST(SchedulerStateMachineTest, TestForwardBeginFramesToChildren) {
+  SchedulerSettings settings;
+  settings.forward_begin_frames_to_children = true;
+  StateMachine state(settings);
+  state.SetCanStart();
+  state.UpdateState(state.NextAction());
+  state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+  state.SetVisible(true);
+  state.SetCanDraw(true);
+
+  EXPECT_FALSE(state.BeginFrameNeeded());
+  state.SetChildrenNeedBeginFrames(true);
+  EXPECT_TRUE(state.BeginFrameNeeded());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index 7d61df3..636beb0 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -88,6 +88,7 @@
 
   FakeSchedulerClient()
       : automatic_swap_ack_(true),
+        begin_frame_is_sent_to_children_(false),
         now_src_(TestNowSource::Create()),
         task_runner_(new OrderedSimpleTaskRunner(now_src_, true)),
         fake_external_begin_frame_source_(nullptr),
@@ -109,6 +110,7 @@
     swap_will_happen_if_draw_happens_ = true;
     num_draws_ = 0;
     log_anticipated_draw_time_change_ = false;
+    begin_frame_is_sent_to_children_ = false;
   }
 
   TestScheduler* CreateScheduler(const SchedulerSettings& settings) {
@@ -266,12 +268,20 @@
 
   void DidBeginImplFrameDeadline() override {}
 
+  void SendBeginFramesToChildren(const BeginFrameArgs& args) override {
+    begin_frame_is_sent_to_children_ = true;
+  }
+
   base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
     return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
                       base::Unretained(this),
                       state);
   }
 
+  bool begin_frame_is_sent_to_children() const {
+    return begin_frame_is_sent_to_children_;
+  }
+
  protected:
   bool ImplFrameDeadlinePendingCallback(bool state) {
     return scheduler_->BeginImplFrameDeadlinePending() == state;
@@ -282,6 +292,7 @@
   bool automatic_swap_ack_;
   int num_draws_;
   bool log_anticipated_draw_time_change_;
+  bool begin_frame_is_sent_to_children_;
   base::TimeTicks posted_begin_impl_frame_deadline_;
   std::vector<const char*> actions_;
   std::vector<scoped_refptr<base::debug::ConvertableToTraceFormat>> states_;
@@ -343,6 +354,36 @@
   EXPECT_NO_ACTION(client);
 }
 
+TEST(SchedulerTest, SendBeginFramesToChildren) {
+  FakeSchedulerClient client;
+  SchedulerSettings scheduler_settings;
+  scheduler_settings.use_external_begin_frame_source = true;
+  scheduler_settings.forward_begin_frames_to_children = true;
+  TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+  scheduler->SetCanStart();
+  scheduler->SetVisible(true);
+  scheduler->SetCanDraw(true);
+
+  EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+  InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+  client.Reset();
+  EXPECT_FALSE(client.begin_frame_is_sent_to_children());
+  scheduler->SetNeedsCommit();
+  EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
+  client.Reset();
+
+  scheduler->SetChildrenNeedBeginFrames(true);
+
+  client.AdvanceFrame();
+  EXPECT_TRUE(client.begin_frame_is_sent_to_children());
+  EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+  EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+  EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+  EXPECT_TRUE(client.needs_begin_frames());
+  client.Reset();
+}
+
 TEST(SchedulerTest, RequestCommit) {
   FakeSchedulerClient client;
   SchedulerSettings scheduler_settings;
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc
index 129a116..a8ae27a 100644
--- a/cc/surfaces/display.cc
+++ b/cc/surfaces/display.cc
@@ -11,6 +11,7 @@
 #include "cc/output/compositor_frame_ack.h"
 #include "cc/output/direct_renderer.h"
 #include "cc/output/gl_renderer.h"
+#include "cc/output/renderer_settings.h"
 #include "cc/output/software_renderer.h"
 #include "cc/resources/texture_mailbox_deleter.h"
 #include "cc/surfaces/display_client.h"
@@ -24,11 +25,13 @@
 Display::Display(DisplayClient* client,
                  SurfaceManager* manager,
                  SharedBitmapManager* bitmap_manager,
-                 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
+                 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+                 const RendererSettings& settings)
     : client_(client),
       manager_(manager),
       bitmap_manager_(bitmap_manager),
       gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
+      settings_(settings),
       device_scale_factor_(1.f),
       blocking_main_thread_task_runner_(
           BlockingTaskRunner::Create(base::MessageLoopProxy::current())),
@@ -59,28 +62,18 @@
   if (resource_provider_)
     return;
 
-  int highp_threshold_min = 0;
-  bool use_rgba_4444_texture_format = false;
-  size_t id_allocation_chunk_size = 1;
-  scoped_ptr<ResourceProvider> resource_provider =
-      ResourceProvider::Create(output_surface_.get(),
-                               bitmap_manager_,
-                               gpu_memory_buffer_manager_,
-                               blocking_main_thread_task_runner_.get(),
-                               highp_threshold_min,
-                               use_rgba_4444_texture_format,
-                               id_allocation_chunk_size);
+  scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
+      output_surface_.get(), bitmap_manager_, gpu_memory_buffer_manager_,
+      blocking_main_thread_task_runner_.get(), settings_.highp_threshold_min,
+      settings_.use_rgba_4444_textures,
+      settings_.texture_id_allocation_chunk_size);
   if (!resource_provider)
     return;
 
   if (output_surface_->context_provider()) {
-    scoped_ptr<GLRenderer> renderer =
-        GLRenderer::Create(this,
-                           &settings_,
-                           output_surface_.get(),
-                           resource_provider.get(),
-                           texture_mailbox_deleter_.get(),
-                           highp_threshold_min);
+    scoped_ptr<GLRenderer> renderer = GLRenderer::Create(
+        this, &settings_, output_surface_.get(), resource_provider.get(),
+        texture_mailbox_deleter_.get(), settings_.highp_threshold_min);
     if (!renderer)
       return;
     renderer_ = renderer.Pass();
diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h
index 5935534..a0bb62a 100644
--- a/cc/surfaces/display.h
+++ b/cc/surfaces/display.h
@@ -24,6 +24,7 @@
 class DirectRenderer;
 class DisplayClient;
 class OutputSurface;
+class RendererSettings;
 class ResourceProvider;
 class SharedBitmapManager;
 class Surface;
@@ -42,7 +43,8 @@
   Display(DisplayClient* client,
           SurfaceManager* manager,
           SharedBitmapManager* bitmap_manager,
-          gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
+          gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+          const RendererSettings& settings);
   ~Display() override;
 
   bool Initialize(scoped_ptr<OutputSurface> output_surface);
@@ -90,10 +92,10 @@
   SurfaceManager* manager_;
   SharedBitmapManager* bitmap_manager_;
   gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
+  RendererSettings settings_;
   SurfaceId current_surface_id_;
   gfx::Size current_surface_size_;
   float device_scale_factor_;
-  LayerTreeSettings settings_;
   scoped_ptr<OutputSurface> output_surface_;
   scoped_ptr<ResourceProvider> resource_provider_;
   scoped_ptr<SurfaceAggregator> aggregator_;
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index 588d624..f5689c5 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -163,6 +163,7 @@
 }
 
 void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
+                                          float opacity,
                                           RenderPass* dest_pass) {
   SurfaceId surface_id = surface_quad->surface_id;
   // If this surface's id is already in our referenced set then it creates
@@ -227,11 +228,8 @@
     copy_pass->transform_to_root_target.ConcatTransform(
         surface_quad->quadTransform());
 
-    CopyQuadsToPass(source.quad_list,
-                    source.shared_quad_state_list,
-                    gfx::Transform(),
-                    copy_pass.get(),
-                    surface_id);
+    CopyQuadsToPass(source.quad_list, source.shared_quad_state_list,
+                    gfx::Transform(), 1.f, copy_pass.get(), surface_id);
 
     dest_pass_list_->push_back(copy_pass.Pass());
   }
@@ -242,17 +240,16 @@
     const QuadList& quads = last_pass.quad_list;
 
     // TODO(jamesr): Make sure clipping is enforced.
-    CopyQuadsToPass(quads,
-                    last_pass.shared_quad_state_list,
+    CopyQuadsToPass(quads, last_pass.shared_quad_state_list,
                     surface_quad->quadTransform(),
-                    dest_pass,
-                    surface_id);
+                    surface_quad->opacity() * opacity, dest_pass, surface_id);
   } else {
     RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
 
     SharedQuadState* shared_quad_state =
         dest_pass->CreateAndAppendSharedQuadState();
     shared_quad_state->CopyFrom(surface_quad->shared_quad_state);
+    shared_quad_state->opacity *= opacity;
     RenderPassDrawQuad* quad =
         dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
     quad->SetNew(shared_quad_state,
@@ -300,6 +297,7 @@
     const QuadList& source_quad_list,
     const SharedQuadStateList& source_shared_quad_state_list,
     const gfx::Transform& content_to_target_transform,
+    float opacity,
     RenderPass* dest_pass,
     SurfaceId surface_id) {
   const SharedQuadState* last_copied_source_shared_quad_state = NULL;
@@ -315,11 +313,12 @@
 
     if (quad->material == DrawQuad::SURFACE_CONTENT) {
       const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
-      HandleSurfaceQuad(surface_quad, dest_pass);
+      HandleSurfaceQuad(surface_quad, opacity, dest_pass);
     } else {
       if (quad->shared_quad_state != last_copied_source_shared_quad_state) {
         CopySharedQuadState(
             quad->shared_quad_state, content_to_target_transform, dest_pass);
+        dest_pass->shared_quad_state_list.back()->opacity *= opacity;
         last_copied_source_shared_quad_state = quad->shared_quad_state;
       }
       if (quad->material == DrawQuad::RENDER_PASS) {
@@ -371,10 +370,8 @@
                       source.transform_to_root_target,
                       source.has_transparent_background);
 
-    CopyQuadsToPass(source.quad_list,
-                    source.shared_quad_state_list,
-                    gfx::Transform(),
-                    copy_pass.get(),
+    CopyQuadsToPass(source.quad_list, source.shared_quad_state_list,
+                    gfx::Transform(), 1.f, copy_pass.get(),
                     surface->surface_id());
 
     dest_pass_list_->push_back(copy_pass.Pass());
diff --git a/cc/surfaces/surface_aggregator.h b/cc/surfaces/surface_aggregator.h
index aeeb590..6965041 100644
--- a/cc/surfaces/surface_aggregator.h
+++ b/cc/surfaces/surface_aggregator.h
@@ -41,6 +41,7 @@
                            SurfaceId surface_id);
 
   void HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
+                         float opacity,
                          RenderPass* dest_pass);
   void CopySharedQuadState(const SharedQuadState* source_sqs,
                            const gfx::Transform& content_to_target_transform,
@@ -48,6 +49,7 @@
   void CopyQuadsToPass(const QuadList& source_quad_list,
                        const SharedQuadStateList& source_shared_quad_state_list,
                        const gfx::Transform& content_to_target_transform,
+                       float opacity,
                        RenderPass* dest_pass,
                        SurfaceId surface_id);
   void CopyPasses(const DelegatedFrameData* frame_data, Surface* surface);
diff --git a/cc/surfaces/surface_aggregator_test_helpers.cc b/cc/surfaces/surface_aggregator_test_helpers.cc
index 6b527c0..b21b37e 100644
--- a/cc/surfaces/surface_aggregator_test_helpers.cc
+++ b/cc/surfaces/surface_aggregator_test_helpers.cc
@@ -24,13 +24,13 @@
 
 void AddTestSurfaceQuad(TestRenderPass* pass,
                         const gfx::Size& surface_size,
+                        float opacity,
                         SurfaceId surface_id) {
   gfx::Transform content_to_target_transform;
   gfx::Size content_bounds = surface_size;
   gfx::Rect visible_content_rect = gfx::Rect(surface_size);
   gfx::Rect clip_rect = gfx::Rect(surface_size);
   bool is_clipped = false;
-  float opacity = 1.0;
   SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
 
   SharedQuadState* shared_quad_state = pass->CreateAndAppendSharedQuadState();
@@ -82,7 +82,7 @@
       AddQuad(pass, gfx::Rect(0, 0, 5, 5), desc.color);
       break;
     case DrawQuad::SURFACE_CONTENT:
-      AddTestSurfaceQuad(pass, gfx::Size(5, 5), desc.surface_id);
+      AddTestSurfaceQuad(pass, gfx::Size(5, 5), desc.opacity, desc.surface_id);
       break;
     case DrawQuad::RENDER_PASS:
       AddTestRenderPassQuad(pass, desc.render_pass_id);
diff --git a/cc/surfaces/surface_aggregator_test_helpers.h b/cc/surfaces/surface_aggregator_test_helpers.h
index 6f3a342..05c8344 100644
--- a/cc/surfaces/surface_aggregator_test_helpers.h
+++ b/cc/surfaces/surface_aggregator_test_helpers.h
@@ -30,9 +30,10 @@
     return quad;
   }
 
-  static Quad SurfaceQuad(SurfaceId surface_id) {
+  static Quad SurfaceQuad(SurfaceId surface_id, float opacity) {
     Quad quad;
     quad.material = DrawQuad::SURFACE_CONTENT;
+    quad.opacity = opacity;
     quad.surface_id = surface_id;
     return quad;
   }
@@ -47,6 +48,7 @@
   DrawQuad::Material material;
   // Set when material==DrawQuad::SURFACE_CONTENT.
   SurfaceId surface_id;
+  float opacity;
   // Set when material==DrawQuad::SOLID_COLOR.
   SkColor color;
   // Set when material==DrawQuad::RENDER_PASS.
@@ -55,6 +57,7 @@
  private:
   Quad()
       : material(DrawQuad::INVALID),
+        opacity(1.f),
         color(SK_ColorWHITE),
         render_pass_id(-1, -1) {}
 };
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc
index 5213327..2e47708 100644
--- a/cc/surfaces/surface_aggregator_unittest.cc
+++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -155,6 +155,88 @@
   AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
 }
 
+TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
+  SurfaceId embedded_surface_id = allocator_.GenerateId();
+  factory_.Create(embedded_surface_id, SurfaceSize());
+
+  test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
+  test::Pass embedded_passes[] = {
+      test::Pass(embedded_quads, arraysize(embedded_quads))};
+
+  SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
+
+  test::Quad quads[] = {test::Quad::SurfaceQuad(embedded_surface_id, .5f)};
+  test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
+
+  SubmitFrame(passes, arraysize(passes), root_surface_id_);
+
+  scoped_ptr<CompositorFrame> aggregated_frame =
+      aggregator_.Aggregate(root_surface_id_);
+
+  ASSERT_TRUE(aggregated_frame);
+  ASSERT_TRUE(aggregated_frame->delegated_frame_data);
+
+  DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
+
+  RenderPassList& render_pass_list(frame_data->render_pass_list);
+  ASSERT_EQ(1u, render_pass_list.size());
+  SharedQuadStateList& shared_quad_state_list(
+      render_pass_list[0]->shared_quad_state_list);
+  ASSERT_EQ(1u, shared_quad_state_list.size());
+  EXPECT_EQ(.5f, shared_quad_state_list.ElementAt(0)->opacity);
+
+  factory_.Destroy(embedded_surface_id);
+}
+
+TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCombinedWithNesting) {
+  SurfaceId surface_id1 = allocator_.GenerateId();
+  factory_.Create(surface_id1, SurfaceSize());
+  SurfaceId surface_id2 = allocator_.GenerateId();
+  factory_.Create(surface_id2, SurfaceSize());
+
+  // |surface_id1| is color quad.
+  {
+    test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
+    test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
+    SubmitFrame(passes, arraysize(passes), surface_id1);
+  }
+
+  // |surface_id2| has a color quad and a surface quad using |surface_id1| at .5
+  // opacity.
+  {
+    test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
+                          test::Quad::SurfaceQuad(surface_id1, .5f)};
+    test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
+    SubmitFrame(passes, arraysize(passes), surface_id2);
+  }
+
+  // Another frame with a surface referencing |surface_id2| @ .6 opacity.
+  {
+    test::Quad quads[] = {test::Quad::SurfaceQuad(surface_id2, .6f)};
+    test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
+    SubmitFrame(passes, arraysize(passes), root_surface_id_);
+  }
+
+  scoped_ptr<CompositorFrame> aggregated_frame =
+      aggregator_.Aggregate(root_surface_id_);
+
+  ASSERT_TRUE(aggregated_frame);
+  ASSERT_TRUE(aggregated_frame->delegated_frame_data);
+
+  DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
+
+  RenderPassList& render_pass_list(frame_data->render_pass_list);
+  ASSERT_EQ(1u, render_pass_list.size());
+  SharedQuadStateList& shared_quad_state_list(
+      render_pass_list[0]->shared_quad_state_list);
+  ASSERT_EQ(2u, shared_quad_state_list.size());
+  EXPECT_EQ(.6f, shared_quad_state_list.ElementAt(0)->opacity);
+  EXPECT_EQ(.3f, shared_quad_state_list.ElementAt(1)->opacity);
+
+  factory_.Destroy(surface_id1);
+  factory_.Destroy(surface_id2);
+}
+
 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
   test::Quad quads[][2] = {{test::Quad::SolidColorQuad(SK_ColorWHITE),
                             test::Quad::SolidColorQuad(SK_ColorLTGRAY)},
@@ -185,7 +267,7 @@
   SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
 
   test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
-                             test::Quad::SurfaceQuad(embedded_surface_id),
+                             test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
                              test::Quad::SolidColorQuad(SK_ColorBLACK)};
   test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
 
@@ -218,7 +300,7 @@
   factory_.RequestCopyOfSurface(embedded_surface_id, copy_request.Pass());
 
   test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
-                             test::Quad::SurfaceQuad(embedded_surface_id),
+                             test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
                              test::Quad::SolidColorQuad(SK_ColorBLACK)};
   test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
 
@@ -277,7 +359,7 @@
   CopyOutputRequest* copy_request2_ptr = copy_request2.get();
 
   test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
-                             test::Quad::SurfaceQuad(embedded_surface_id),
+                             test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
                              test::Quad::SolidColorQuad(SK_ColorBLACK)};
   test::Quad root_quads2[] = {test::Quad::SolidColorQuad(SK_ColorRED)};
   test::Pass root_passes[] = {
@@ -368,7 +450,7 @@
 
   test::Quad root_quads[][2] = {
       {test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
-      {test::Quad::SurfaceQuad(embedded_surface_id),
+      {test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
        test::Quad::RenderPassQuad(pass_ids[0])},
       {test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids[1])}};
   test::Pass root_passes[] = {
@@ -489,7 +571,7 @@
 // be dropped.
 TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
   test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
-                        test::Quad::SurfaceQuad(InvalidSurfaceId()),
+                        test::Quad::SurfaceQuad(InvalidSurfaceId(), 1.f),
                         test::Quad::SolidColorQuad(SK_ColorBLUE)};
   test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
 
@@ -510,7 +592,7 @@
   SurfaceId surface_with_no_frame_id = allocator_.GenerateId();
   factory_.Create(surface_with_no_frame_id, gfx::Size(5, 5));
   test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
-                        test::Quad::SurfaceQuad(surface_with_no_frame_id),
+                        test::Quad::SurfaceQuad(surface_with_no_frame_id, 1.f),
                         test::Quad::SolidColorQuad(SK_ColorBLUE)};
   test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
 
@@ -529,7 +611,7 @@
 // Tests a surface quad referencing itself, generating a trivial cycle.
 // The quad creating the cycle should be dropped from the final frame.
 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
-  test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_id_),
+  test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_id_, 1.f),
                         test::Quad::SolidColorQuad(SK_ColorYELLOW)};
   test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
 
@@ -549,7 +631,7 @@
   factory_.Create(child_surface_id, SurfaceSize());
 
   test::Quad parent_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
-                               test::Quad::SurfaceQuad(child_surface_id),
+                               test::Quad::SurfaceQuad(child_surface_id, 1.f),
                                test::Quad::SolidColorQuad(SK_ColorCYAN)};
   test::Pass parent_passes[] = {
       test::Pass(parent_quads, arraysize(parent_quads))};
@@ -557,7 +639,7 @@
   SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
 
   test::Quad child_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
-                              test::Quad::SurfaceQuad(root_surface_id_),
+                              test::Quad::SurfaceQuad(root_surface_id_, 1.f),
                               test::Quad::SolidColorQuad(SK_ColorMAGENTA)};
   test::Pass child_passes[] = {test::Pass(child_quads, arraysize(child_quads))};
 
@@ -599,7 +681,7 @@
   // Pass IDs from the parent surface may collide with ones from the child.
   RenderPassId parent_pass_id[] = {RenderPassId(2, 1), RenderPassId(1, 2)};
   test::Quad parent_quad[][1] = {
-      {test::Quad::SurfaceQuad(child_surface_id)},
+      {test::Quad::SurfaceQuad(child_surface_id, 1.f)},
       {test::Quad::RenderPassQuad(parent_pass_id[0])}};
   test::Pass parent_passes[] = {
       test::Pass(parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]),
@@ -858,7 +940,7 @@
   factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
 
   test::Quad root_quads[] = {test::Quad::SolidColorQuad(1),
-                             test::Quad::SurfaceQuad(child_surface_id)};
+                             test::Quad::SurfaceQuad(child_surface_id, 1.f)};
   test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
 
   RenderPassList root_pass_list;
@@ -981,7 +1063,7 @@
 
   factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
 
-  test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id)};
+  test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)};
   test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
 
   RenderPassList root_pass_list;
diff --git a/cc/test/begin_frame_args_test.cc b/cc/test/begin_frame_args_test.cc
index 1c4b236..f70d0c5 100644
--- a/cc/test/begin_frame_args_test.cc
+++ b/cc/test/begin_frame_args_test.cc
@@ -16,9 +16,8 @@
 
 BeginFrameArgs CreateBeginFrameArgsForTesting(base::TimeTicks frame_time) {
   return BeginFrameArgs::Create(
-      frame_time,
-      frame_time + (BeginFrameArgs::DefaultInterval() / 2),
-      BeginFrameArgs::DefaultInterval());
+      frame_time, frame_time + (BeginFrameArgs::DefaultInterval() / 2),
+      BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
 }
 
 BeginFrameArgs CreateBeginFrameArgsForTesting(int64 frame_time,
@@ -26,47 +25,47 @@
                                               int64 interval) {
   return BeginFrameArgs::Create(base::TimeTicks::FromInternalValue(frame_time),
                                 base::TimeTicks::FromInternalValue(deadline),
-                                base::TimeDelta::FromInternalValue(interval));
+                                base::TimeDelta::FromInternalValue(interval),
+                                BeginFrameArgs::NORMAL);
 }
 
-BeginFrameArgs CreateTypedBeginFrameArgsForTesting(
+BeginFrameArgs CreateBeginFrameArgsForTesting(
     int64 frame_time,
     int64 deadline,
     int64 interval,
     BeginFrameArgs::BeginFrameArgsType type) {
-  return BeginFrameArgs::CreateTyped(
-      base::TimeTicks::FromInternalValue(frame_time),
-      base::TimeTicks::FromInternalValue(deadline),
-      base::TimeDelta::FromInternalValue(interval),
-      type);
+  return BeginFrameArgs::Create(base::TimeTicks::FromInternalValue(frame_time),
+                                base::TimeTicks::FromInternalValue(deadline),
+                                base::TimeDelta::FromInternalValue(interval),
+                                type);
 }
 
 BeginFrameArgs CreateExpiredBeginFrameArgsForTesting() {
   base::TimeTicks now = gfx::FrameTime::Now();
-  return BeginFrameArgs::Create(now,
-                                now - BeginFrameArgs::DefaultInterval(),
-                                BeginFrameArgs::DefaultInterval());
+  return BeginFrameArgs::Create(now, now - BeginFrameArgs::DefaultInterval(),
+                                BeginFrameArgs::DefaultInterval(),
+                                BeginFrameArgs::NORMAL);
 }
 
 BeginFrameArgs CreateBeginFrameArgsForTesting(
     scoped_refptr<TestNowSource> now_src) {
   base::TimeTicks now = now_src->Now();
-  return BeginFrameArgs::Create(now,
-                                now + (BeginFrameArgs::DefaultInterval() / 2),
-                                BeginFrameArgs::DefaultInterval());
+  return BeginFrameArgs::Create(
+      now, now + (BeginFrameArgs::DefaultInterval() / 2),
+      BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
 }
 
 BeginFrameArgs CreateExpiredBeginFrameArgsForTesting(
     scoped_refptr<TestNowSource> now_src) {
   base::TimeTicks now = now_src->Now();
-  return BeginFrameArgs::Create(now,
-                                now - BeginFrameArgs::DefaultInterval(),
-                                BeginFrameArgs::DefaultInterval());
+  return BeginFrameArgs::Create(now, now - BeginFrameArgs::DefaultInterval(),
+                                BeginFrameArgs::DefaultInterval(),
+                                BeginFrameArgs::NORMAL);
 }
 
 bool operator==(const BeginFrameArgs& lhs, const BeginFrameArgs& rhs) {
-  return (lhs.frame_time == rhs.frame_time) && (lhs.deadline == rhs.deadline) &&
-         (lhs.interval == rhs.interval);
+  return (lhs.type == rhs.type) && (lhs.frame_time == rhs.frame_time) &&
+         (lhs.deadline == rhs.deadline) && (lhs.interval == rhs.interval);
 }
 
 ::std::ostream& operator<<(::std::ostream& os, const BeginFrameArgs& args) {
@@ -75,7 +74,8 @@
 }
 
 void PrintTo(const BeginFrameArgs& args, ::std::ostream* os) {
-  *os << "BeginFrameArgs(" << args.frame_time.ToInternalValue() << ", "
+  *os << "BeginFrameArgs(" << BeginFrameArgs::TypeToString(args.type) << ", "
+      << args.frame_time.ToInternalValue() << ", "
       << args.deadline.ToInternalValue() << ", "
       << args.interval.InMicroseconds() << "us)";
 }
diff --git a/cc/test/begin_frame_args_test.h b/cc/test/begin_frame_args_test.h
index 425a07b..ca4aa45 100644
--- a/cc/test/begin_frame_args_test.h
+++ b/cc/test/begin_frame_args_test.h
@@ -20,7 +20,7 @@
 BeginFrameArgs CreateBeginFrameArgsForTesting(int64 frame_time,
                                               int64 deadline,
                                               int64 interval);
-BeginFrameArgs CreateTypedBeginFrameArgsForTesting(
+BeginFrameArgs CreateBeginFrameArgsForTesting(
     int64 frame_time,
     int64 deadline,
     int64 interval,
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index 2bcacd8..5404cb0 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -45,6 +45,7 @@
   void SetDebugState(const LayerTreeDebugState& debug_state) override {}
   bool MainFrameWillHappenForTesting() override;
   void AsValueInto(base::debug::TracedValue* state) const override;
+  void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override {}
 
   virtual RendererCapabilities& GetRendererCapabilities();
   void SetMaxPartialTextureUpdates(size_t max);
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index 4542d2a..9bd75ac 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -26,13 +26,12 @@
     case GL_ZERO_COPY_2D_DRAW:
     case GL_ZERO_COPY_RECT_DRAW:
     case GL_ONE_COPY_2D_STAGING_2D_DRAW:
+    case GL_ONE_COPY_RECT_STAGING_2D_DRAW:
     case GL_ASYNC_UPLOAD_2D_DRAW:
       return true;
     case GL_ZERO_COPY_EXTERNAL_DRAW:
-    case GL_ONE_COPY_RECT_STAGING_2D_DRAW:
     case GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW:
       // These should all be enabled in practice.
-      // TODO(reveman): one copy with rect not supported in unit tests yet.
       // TODO(enne): look into getting texture external oes enabled.
       return false;
   }
@@ -76,7 +75,7 @@
     case GL_ONE_COPY_RECT_STAGING_2D_DRAW:
       test_type_ = PIXEL_TEST_GL;
       staging_texture_target_ = GL_TEXTURE_RECTANGLE_ARB;
-      draw_texture_target_ = GL_TEXTURE_RECTANGLE_ARB;
+      draw_texture_target_ = GL_TEXTURE_2D;
       resource_pool_option_ = ONE_COPY_RASTER_WORKER_POOL;
       return;
     case GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW:
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index a22c7af..80e9f11 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -380,6 +380,10 @@
     test_hooks_->DidInitializeOutputSurface();
   }
 
+  void SendBeginFramesToChildren(const BeginFrameArgs& args) override {
+    test_hooks_->SendBeginFramesToChildren(args);
+  }
+
   void DidFailToInitializeOutputSurface() override {
     test_hooks_->DidFailToInitializeOutputSurface();
   }
@@ -607,8 +611,8 @@
   scoped_ptr<ExternalBeginFrameSourceForTest> external_begin_frame_source;
   if (settings_.use_external_begin_frame_source &&
       settings_.throttle_frame_production) {
-    external_begin_frame_source.reset(
-        new ExternalBeginFrameSourceForTest(settings_.refresh_rate));
+    external_begin_frame_source.reset(new ExternalBeginFrameSourceForTest(
+        settings_.renderer_settings.refresh_rate));
     external_begin_frame_source_ = external_begin_frame_source.get();
   }
 
@@ -741,7 +745,7 @@
 
   // Spend less time waiting for BeginFrame because the output is
   // mocked out.
-  settings_.refresh_rate = 200.0;
+  settings_.renderer_settings.refresh_rate = 200.0;
   settings_.background_animation_rate = 200.0;
   settings_.impl_side_painting = impl_side_painting;
   InitializeSettings(&settings_);
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index b801d94..2914cfc 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -89,6 +89,7 @@
   virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl,
                                        bool visible) {}
   virtual void ScheduleComposite() {}
+  virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) {}
 
   // Hooks for SchedulerClient.
   virtual void ScheduledActionWillSendBeginMainFrame() {}
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index 28c0dc0..76966e9 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -144,12 +144,9 @@
   texture_mailbox_deleter_ = make_scoped_ptr(
       new TextureMailboxDeleter(base::MessageLoopProxy::current()));
 
-  renderer_ = GLRenderer::Create(this,
-                                 &settings_,
-                                 output_surface_.get(),
-                                 resource_provider_.get(),
-                                 texture_mailbox_deleter_.get(),
-                                 0);
+  renderer_ = GLRenderer::Create(
+      this, &settings_.renderer_settings, output_surface_.get(),
+      resource_provider_.get(), texture_mailbox_deleter_.get(), 0);
 }
 
 void PixelTest::ForceExpandedViewport(const gfx::Size& surface_expansion) {
@@ -188,8 +185,9 @@
                                0,
                                false,
                                1);
-  renderer_ = SoftwareRenderer::Create(
-      this, &settings_, output_surface_.get(), resource_provider_.get());
+  renderer_ =
+      SoftwareRenderer::Create(this, &settings_.renderer_settings,
+                               output_surface_.get(), resource_provider_.get());
 }
 
 }  // namespace cc
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h
index 46cdcba..3c5350c 100644
--- a/cc/test/pixel_test.h
+++ b/cc/test/pixel_test.h
@@ -101,7 +101,7 @@
 class GLRendererWithExpandedViewport : public GLRenderer {
  public:
   GLRendererWithExpandedViewport(RendererClient* client,
-                                 const LayerTreeSettings* settings,
+                                 const RendererSettings* settings,
                                  OutputSurface* output_surface,
                                  ResourceProvider* resource_provider,
                                  TextureMailboxDeleter* texture_mailbox_deleter,
@@ -117,7 +117,7 @@
 class SoftwareRendererWithExpandedViewport : public SoftwareRenderer {
  public:
   SoftwareRendererWithExpandedViewport(RendererClient* client,
-                                       const LayerTreeSettings* settings,
+                                       const RendererSettings* settings,
                                        OutputSurface* output_surface,
                                        ResourceProvider* resource_provider)
       : SoftwareRenderer(client, settings, output_surface, resource_provider) {}
@@ -126,7 +126,7 @@
 class GLRendererWithFlippedSurface : public GLRenderer {
  public:
   GLRendererWithFlippedSurface(RendererClient* client,
-                               const LayerTreeSettings* settings,
+                               const RendererSettings* settings,
                                OutputSurface* output_surface,
                                ResourceProvider* resource_provider,
                                TextureMailboxDeleter* texture_mailbox_deleter,
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc
index 847bc92..34b0493 100644
--- a/cc/test/test_in_process_context_provider.cc
+++ b/cc/test/test_in_process_context_provider.cc
@@ -129,7 +129,6 @@
   ContextProvider::Capabilities capabilities;
   capabilities.gpu.image = true;
   capabilities.gpu.texture_rectangle = true;
-  capabilities.gpu.sync_query = true;
 
   return capabilities;
 }
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 808bf21..c2fce2a 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -23,6 +23,7 @@
 #include "cc/debug/devtools_instrumentation.h"
 #include "cc/debug/rendering_stats_instrumentation.h"
 #include "cc/input/layer_selection_bound.h"
+#include "cc/input/page_scale_animation.h"
 #include "cc/input/top_controls_manager.h"
 #include "cc/layers/heads_up_display_layer.h"
 #include "cc/layers/heads_up_display_layer_impl.h"
@@ -197,7 +198,7 @@
   }
 
   // We must clear any pointers into the layer tree prior to destroying it.
-  RegisterViewportLayers(NULL, NULL, NULL);
+  RegisterViewportLayers(NULL, NULL, NULL, NULL);
 
   if (root_layer_.get()) {
     // The layer tree must be destroyed before the layer tree host. We've
@@ -347,11 +348,12 @@
   sync_tree->set_has_transparent_background(has_transparent_background_);
 
   if (page_scale_layer_.get() && inner_viewport_scroll_layer_.get()) {
-    sync_tree->SetViewportLayersFromIds(page_scale_layer_->id(),
-                                        inner_viewport_scroll_layer_->id(),
-                                        outer_viewport_scroll_layer_.get()
-                                            ? outer_viewport_scroll_layer_->id()
-                                            : Layer::INVALID_ID);
+    sync_tree->SetViewportLayersFromIds(
+        overscroll_elasticity_layer_.get() ? overscroll_elasticity_layer_->id()
+                                           : Layer::INVALID_ID,
+        page_scale_layer_->id(), inner_viewport_scroll_layer_->id(),
+        outer_viewport_scroll_layer_.get() ? outer_viewport_scroll_layer_->id()
+                                           : Layer::INVALID_ID);
   } else {
     sync_tree->ClearViewportLayers();
   }
@@ -381,12 +383,8 @@
   host_impl->SetDeviceScaleFactor(device_scale_factor_);
   host_impl->SetDebugState(debug_state_);
   if (pending_page_scale_animation_) {
-    sync_tree->SetPageScaleAnimation(
-        pending_page_scale_animation_->target_offset,
-        pending_page_scale_animation_->use_anchor,
-        pending_page_scale_animation_->scale,
-        pending_page_scale_animation_->duration);
-    pending_page_scale_animation_ = nullptr;
+    sync_tree->SetPendingPageScaleAnimation(
+        pending_page_scale_animation_.Pass());
   }
 
   if (!ui_resource_request_queue_.empty()) {
@@ -724,11 +722,12 @@
                                             bool use_anchor,
                                             float scale,
                                             base::TimeDelta duration) {
-  pending_page_scale_animation_.reset(new PendingPageScaleAnimation);
-  pending_page_scale_animation_->target_offset = target_offset;
-  pending_page_scale_animation_->use_anchor = use_anchor;
-  pending_page_scale_animation_->scale = scale;
-  pending_page_scale_animation_->duration = duration;
+  pending_page_scale_animation_.reset(
+      new PendingPageScaleAnimation(
+          target_offset,
+          use_anchor,
+          scale,
+          duration));
 
   SetNeedsCommit();
 }
@@ -1288,9 +1287,11 @@
 }
 
 void LayerTreeHost::RegisterViewportLayers(
+    scoped_refptr<Layer> overscroll_elasticity_layer,
     scoped_refptr<Layer> page_scale_layer,
     scoped_refptr<Layer> inner_viewport_scroll_layer,
     scoped_refptr<Layer> outer_viewport_scroll_layer) {
+  overscroll_elasticity_layer_ = overscroll_elasticity_layer;
   page_scale_layer_ = page_scale_layer;
   inner_viewport_scroll_layer_ = inner_viewport_scroll_layer;
   outer_viewport_scroll_layer_ = outer_viewport_scroll_layer;
@@ -1352,4 +1353,14 @@
   return SurfaceSequence(surface_id_namespace_, next_surface_sequence_++);
 }
 
+void LayerTreeHost::SetChildrenNeedBeginFrames(
+    bool children_need_begin_frames) const {
+  proxy_->SetChildrenNeedBeginFrames(children_need_begin_frames);
+}
+
+void LayerTreeHost::SendBeginFramesToChildren(
+    const BeginFrameArgs& args) const {
+  client_->SendBeginFramesToChildren(args);
+}
+
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 7820cc2..de91b76 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -63,6 +63,7 @@
 class SharedBitmapManager;
 class TopControlsManager;
 class UIResourceRequest;
+struct PendingPageScaleAnimation;
 struct RenderingStats;
 struct ScrollAndScaleSet;
 
@@ -179,11 +180,14 @@
   void SetRootLayer(scoped_refptr<Layer> root_layer);
   Layer* root_layer() { return root_layer_.get(); }
   const Layer* root_layer() const { return root_layer_.get(); }
+  const Layer* overscroll_elasticity_layer() const {
+    return overscroll_elasticity_layer_.get();
+  }
   const Layer* page_scale_layer() const { return page_scale_layer_.get(); }
-  void RegisterViewportLayers(
-      scoped_refptr<Layer> page_scale_layer,
-      scoped_refptr<Layer> inner_viewport_scroll_layer,
-      scoped_refptr<Layer> outer_viewport_scroll_layer);
+  void RegisterViewportLayers(scoped_refptr<Layer> overscroll_elasticity_layer,
+                              scoped_refptr<Layer> page_scale_layer,
+                              scoped_refptr<Layer> inner_viewport_scroll_layer,
+                              scoped_refptr<Layer> outer_viewport_scroll_layer);
   Layer* inner_viewport_scroll_layer() const {
     return inner_viewport_scroll_layer_.get();
   }
@@ -314,6 +318,9 @@
   void set_surface_id_namespace(uint32_t id_namespace);
   SurfaceSequence CreateSurfaceSequence();
 
+  void SetChildrenNeedBeginFrames(bool children_need_begin_frames) const;
+  void SendBeginFramesToChildren(const BeginFrameArgs& args) const;
+
  protected:
   LayerTreeHost(LayerTreeHostClient* client,
                 SharedBitmapManager* shared_bitmap_manager,
@@ -433,12 +440,6 @@
 
   scoped_ptr<AnimationRegistrar> animation_registrar_;
 
-  struct PendingPageScaleAnimation {
-    gfx::Vector2d target_offset;
-    bool use_anchor;
-    float scale;
-    base::TimeDelta duration;
-  };
   scoped_ptr<PendingPageScaleAnimation> pending_page_scale_animation_;
 
   bool in_paint_layer_contents_;
@@ -460,6 +461,7 @@
   int id_;
   bool next_commit_forces_redraw_;
 
+  scoped_refptr<Layer> overscroll_elasticity_layer_;
   scoped_refptr<Layer> page_scale_layer_;
   scoped_refptr<Layer> inner_viewport_scroll_layer_;
   scoped_refptr<Layer> outer_viewport_scroll_layer_;
diff --git a/cc/trees/layer_tree_host_client.h b/cc/trees/layer_tree_host_client.h
index dca389d..5b02964 100644
--- a/cc/trees/layer_tree_host_client.h
+++ b/cc/trees/layer_tree_host_client.h
@@ -45,6 +45,10 @@
   virtual void DidCommitAndDrawFrame() = 0;
   virtual void DidCompleteSwapBuffers() = 0;
 
+  // TODO(simonhong): Makes this to pure virtual function when client
+  // implementation is ready.
+  virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) {}
+
   // Requests that the client insert a rate limiting token in the shared main
   // thread context's command stream that will block if the context gets too far
   // ahead of the compositor's command stream. Only needed if the tree contains
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index bb1be98..e49dcfe 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -414,6 +414,48 @@
   client_->DidManageTiles();
 }
 
+void LayerTreeHostImpl::StartPageScaleAnimation(
+    const gfx::Vector2d& target_offset,
+    bool anchor_point,
+    float page_scale,
+    base::TimeDelta duration) {
+  if (!InnerViewportScrollLayer())
+    return;
+
+  gfx::ScrollOffset scroll_total = active_tree_->TotalScrollOffset();
+  gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize();
+  gfx::SizeF viewport_size =
+      active_tree_->InnerViewportContainerLayer()->bounds();
+
+  // Easing constants experimentally determined.
+  scoped_ptr<TimingFunction> timing_function =
+      CubicBezierTimingFunction::Create(.8, 0, .3, .9);
+
+  // TODO(miletus) : Pass in ScrollOffset.
+  page_scale_animation_ =
+      PageScaleAnimation::Create(ScrollOffsetToVector2dF(scroll_total),
+                                 active_tree_->total_page_scale_factor(),
+                                 viewport_size,
+                                 scaled_scrollable_size,
+                                 timing_function.Pass());
+
+  if (anchor_point) {
+    gfx::Vector2dF anchor(target_offset);
+    page_scale_animation_->ZoomWithAnchor(anchor,
+                                          page_scale,
+                                          duration.InSecondsF());
+  } else {
+    gfx::Vector2dF scaled_target_offset = target_offset;
+    page_scale_animation_->ZoomTo(scaled_target_offset,
+                                  page_scale,
+                                  duration.InSecondsF());
+  }
+
+  SetNeedsAnimate();
+  client_->SetNeedsCommitOnImplThread();
+  client_->RenewTreePriority();
+}
+
 bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt(
     const gfx::Point& viewport_point,
     InputHandler::ScrollInputType type) {
@@ -1514,7 +1556,8 @@
         IsActivelyScrolling() || needs_animate_layers();
 
     scoped_ptr<SoftwareRenderer> temp_software_renderer =
-        SoftwareRenderer::Create(this, &settings_, output_surface_.get(), NULL);
+        SoftwareRenderer::Create(this, &settings_.renderer_settings,
+                                 output_surface_.get(), NULL);
     temp_software_renderer->DrawFrame(&frame->render_passes,
                                       device_scale_factor_,
                                       DeviceViewport(),
@@ -1807,13 +1850,14 @@
         stats.draw_duration.GetLastTimeDelta());
   }
 
-  scoped_ptr<PageScaleAnimation> page_scale_animation =
-      active_tree_->TakePageScaleAnimation();
-  if (page_scale_animation) {
-    page_scale_animation_ = page_scale_animation.Pass();
-    SetNeedsAnimate();
-    client_->SetNeedsCommitOnImplThread();
-    client_->RenewTreePriority();
+  scoped_ptr<PendingPageScaleAnimation> pending_page_scale_animation =
+      active_tree_->TakePendingPageScaleAnimation();
+  if (pending_page_scale_animation) {
+    StartPageScaleAnimation(
+        pending_page_scale_animation->target_offset,
+        pending_page_scale_animation->use_anchor,
+        pending_page_scale_animation->scale,
+        pending_page_scale_animation->duration);
   }
 }
 
@@ -1896,18 +1940,18 @@
   DCHECK(resource_provider_);
 
   if (output_surface_->capabilities().delegated_rendering) {
-    renderer_ = DelegatingRenderer::Create(
-        this, &settings_, output_surface_.get(), resource_provider_.get());
+    renderer_ = DelegatingRenderer::Create(this, &settings_.renderer_settings,
+                                           output_surface_.get(),
+                                           resource_provider_.get());
   } else if (output_surface_->context_provider()) {
-    renderer_ = GLRenderer::Create(this,
-                                   &settings_,
-                                   output_surface_.get(),
-                                   resource_provider_.get(),
-                                   texture_mailbox_deleter_.get(),
-                                   settings_.highp_threshold_min);
+    renderer_ = GLRenderer::Create(
+        this, &settings_.renderer_settings, output_surface_.get(),
+        resource_provider_.get(), texture_mailbox_deleter_.get(),
+        settings_.renderer_settings.highp_threshold_min);
   } else if (output_surface_->software_device()) {
-    renderer_ = SoftwareRenderer::Create(
-        this, &settings_, output_surface_.get(), resource_provider_.get());
+    renderer_ = SoftwareRenderer::Create(this, &settings_.renderer_settings,
+                                         output_surface_.get(),
+                                         resource_provider_.get());
   }
   DCHECK(renderer_);
 
@@ -2026,12 +2070,11 @@
         resource_provider_->memory_efficient_texture_format());
 
     *raster_worker_pool = PixelBufferRasterWorkerPool::Create(
-        task_runner,
-        RasterWorkerPool::GetTaskGraphRunner(),
-        context_provider,
+        task_runner, RasterWorkerPool::GetTaskGraphRunner(), context_provider,
         resource_provider_.get(),
-        GetMaxTransferBufferUsageBytes(context_provider->ContextCapabilities(),
-                                       settings_.refresh_rate));
+        GetMaxTransferBufferUsageBytes(
+            context_provider->ContextCapabilities(),
+            settings_.renderer_settings.refresh_rate));
   }
 }
 
@@ -2058,9 +2101,7 @@
 }
 
 bool LayerTreeHostImpl::CanUseOneCopyRasterizer() const {
-  // Sync query support is required by one-copy rasterizer.
-  return GetRendererCapabilities().using_image &&
-         resource_provider_->use_sync_query();
+  return GetRendererCapabilities().using_image;
 }
 
 void LayerTreeHostImpl::EnforceZeroBudget(bool zero_budget) {
@@ -2086,14 +2127,12 @@
     return false;
 
   output_surface_ = output_surface.Pass();
-  resource_provider_ =
-      ResourceProvider::Create(output_surface_.get(),
-                               shared_bitmap_manager_,
-                               gpu_memory_buffer_manager_,
-                               proxy_->blocking_main_thread_task_runner(),
-                               settings_.highp_threshold_min,
-                               settings_.use_rgba_4444_textures,
-                               settings_.texture_id_allocation_chunk_size);
+  resource_provider_ = ResourceProvider::Create(
+      output_surface_.get(), shared_bitmap_manager_, gpu_memory_buffer_manager_,
+      proxy_->blocking_main_thread_task_runner(),
+      settings_.renderer_settings.highp_threshold_min,
+      settings_.renderer_settings.use_rgba_4444_textures,
+      settings_.renderer_settings.texture_id_allocation_chunk_size);
 
   if (output_surface_->capabilities().deferred_gl_initialization)
     EnforceZeroBudget(true);
@@ -2105,8 +2144,9 @@
 
   // Initialize vsync parameters to sane values.
   const base::TimeDelta display_refresh_interval =
-      base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond /
-                                        settings_.refresh_rate);
+      base::TimeDelta::FromMicroseconds(
+          base::Time::kMicrosecondsPerSecond /
+          settings_.renderer_settings.refresh_rate);
   CommitVSyncParameters(base::TimeTicks(), display_refresh_interval);
 
   // TODO(brianderson): Don't use a hard-coded parent draw time.
@@ -2633,40 +2673,49 @@
       }
     }
 
+    // Scrolls should bubble perfectly between the outer and inner viewports.
+    bool allow_unrestricted_bubbling_for_current_layer =
+        layer_impl == OuterViewportScrollLayer();
+    bool allow_bubbling_for_current_layer =
+        allow_unrestricted_bubbling_for_current_layer || should_bubble_scrolls_;
+
     // If the layer wasn't able to move, try the next one in the hierarchy.
     bool did_move_layer_x = std::abs(applied_delta.x()) > kEpsilon;
     bool did_move_layer_y = std::abs(applied_delta.y()) > kEpsilon;
     did_scroll_x |= did_move_layer_x;
     did_scroll_y |= did_move_layer_y;
     if (!did_move_layer_x && !did_move_layer_y) {
-      // Scrolls should always bubble between the outer and inner viewports
-      if (should_bubble_scrolls_ || !did_lock_scrolling_layer_ ||
-          layer_impl == OuterViewportScrollLayer())
+      if (allow_bubbling_for_current_layer || !did_lock_scrolling_layer_)
         continue;
       else
         break;
     }
 
     did_lock_scrolling_layer_ = true;
-    if (!should_bubble_scrolls_) {
+    if (!allow_bubbling_for_current_layer) {
       active_tree_->SetCurrentlyScrollingLayer(layer_impl);
       break;
     }
 
-    // If the applied delta is within 45 degrees of the input delta, bail out to
-    // make it easier to scroll just one layer in one direction without
-    // affecting any of its parents.
-    float angle_threshold = 45;
-    if (MathUtil::SmallestAngleBetweenVectors(
-            applied_delta, pending_delta) < angle_threshold) {
-      pending_delta = gfx::Vector2dF();
-      break;
-    }
+    if (allow_unrestricted_bubbling_for_current_layer) {
+      pending_delta -= applied_delta;
+    } else {
+      // If the applied delta is within 45 degrees of the input delta, bail out
+      // to make it easier to scroll just one layer in one direction without
+      // affecting any of its parents.
+      float angle_threshold = 45;
+      if (MathUtil::SmallestAngleBetweenVectors(applied_delta, pending_delta) <
+          angle_threshold) {
+        pending_delta = gfx::Vector2dF();
+        break;
+      }
 
-    // Allow further movement only on an axis perpendicular to the direction in
-    // which the layer moved.
-    gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
-    pending_delta = MathUtil::ProjectVector(pending_delta, perpendicular_axis);
+      // Allow further movement only on an axis perpendicular to the direction
+      // in which the layer moved.
+      gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
+      pending_delta =
+          MathUtil::ProjectVector(pending_delta, perpendicular_axis);
+    }
 
     if (gfx::ToRoundedVector2d(pending_delta).IsZero())
       break;
@@ -3202,9 +3251,9 @@
   // task), fall back to physical time.  This should still be monotonic.
   if (current_begin_frame_args_.IsValid())
     return current_begin_frame_args_;
-  return BeginFrameArgs::Create(gfx::FrameTime::Now(),
-                                base::TimeTicks(),
-                                BeginFrameArgs::DefaultInterval());
+  return BeginFrameArgs::Create(gfx::FrameTime::Now(), base::TimeTicks(),
+                                BeginFrameArgs::DefaultInterval(),
+                                BeginFrameArgs::NORMAL);
 }
 
 scoped_refptr<base::debug::ConvertableToTraceFormat>
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index ba4fabf..d1b29ca 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -146,6 +146,10 @@
   void PinchGestureUpdate(float magnify_delta,
                           const gfx::Point& anchor) override;
   void PinchGestureEnd() override;
+  void StartPageScaleAnimation(const gfx::Vector2d& target_offset,
+                               bool anchor_point,
+                               float page_scale,
+                               base::TimeDelta duration);
   void SetNeedsAnimate() override;
   bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point,
                                    InputHandler::ScrollInputType type) override;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 51377d2..7151689 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -96,7 +96,7 @@
     LayerTreeSettings settings;
     settings.minimum_occlusion_tracking_size = gfx::Size();
     settings.impl_side_painting = true;
-    settings.texture_id_allocation_chunk_size = 1;
+    settings.renderer_settings.texture_id_allocation_chunk_size = 1;
     settings.report_overscroll_only_for_scrollable_axes = true;
     settings.use_pinch_virtual_viewport = true;
     return settings;
@@ -256,7 +256,8 @@
 
     layer_tree_impl->SetRootLayer(root.Pass());
     layer_tree_impl->SetViewportLayersFromIds(
-        kPageScaleLayerId, kInnerViewportScrollLayerId, Layer::INVALID_ID);
+        Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
+        Layer::INVALID_ID);
 
     return scroll_layer;
   }
@@ -1159,11 +1160,12 @@
 
     did_request_redraw_ = false;
     did_request_animate_ = false;
-    host_impl_->active_tree()->SetPageScaleAnimation(
-        gfx::Vector2d(),
-        false,
-        2.f,
-        duration);
+    host_impl_->active_tree()->SetPendingPageScaleAnimation(
+        scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
+            gfx::Vector2d(),
+            false,
+            2.f,
+            duration)));
     host_impl_->ActivateSyncTree();
     EXPECT_FALSE(did_request_redraw_);
     EXPECT_TRUE(did_request_animate_);
@@ -1202,8 +1204,12 @@
 
     did_request_redraw_ = false;
     did_request_animate_ = false;
-    host_impl_->active_tree()->SetPageScaleAnimation(
-        gfx::Vector2d(25, 25), true, min_page_scale, duration);
+    host_impl_->active_tree()->SetPendingPageScaleAnimation(
+        scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
+            gfx::Vector2d(25, 25),
+            true,
+            min_page_scale,
+            duration)));
     host_impl_->ActivateSyncTree();
     EXPECT_FALSE(did_request_redraw_);
     EXPECT_TRUE(did_request_animate_);
@@ -1253,11 +1259,12 @@
                                                            max_page_scale);
     scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
 
-    host_impl_->active_tree()->SetPageScaleAnimation(
-        gfx::Vector2d(),
-        true,
-        1.f,
-        duration);
+    host_impl_->active_tree()->SetPendingPageScaleAnimation(
+        scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
+            gfx::Vector2d(),
+            true,
+            1.f,
+            duration)));
     host_impl_->ActivateSyncTree();
     host_impl_->Animate(start_time);
     host_impl_->Animate(halfway_through_animation);
@@ -1301,26 +1308,29 @@
   scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
 
   // Make sure TakePageScaleAnimation works properly.
-  host_impl_->sync_tree()->SetPageScaleAnimation(
-      gfx::Vector2d(),
-      false,
-      target_scale,
-      duration);
-  scoped_ptr<PageScaleAnimation> psa =
-      host_impl_->sync_tree()->TakePageScaleAnimation();
-  EXPECT_EQ(target_scale, psa->target_page_scale_factor());
-  EXPECT_EQ(duration, psa->duration());
-  EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePageScaleAnimation());
+
+  host_impl_->sync_tree()->SetPendingPageScaleAnimation(
+      scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
+          gfx::Vector2d(),
+          false,
+          target_scale,
+          duration)));
+  scoped_ptr<PendingPageScaleAnimation> psa =
+      host_impl_->sync_tree()->TakePendingPageScaleAnimation();
+  EXPECT_EQ(target_scale, psa->scale);
+  EXPECT_EQ(duration, psa->duration);
+  EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
 
   // Recreate the PSA. Nothing should happen here since the tree containing the
   // PSA hasn't been activated yet.
   did_request_redraw_ = false;
   did_request_animate_ = false;
-  host_impl_->sync_tree()->SetPageScaleAnimation(
-      gfx::Vector2d(),
-      false,
-      target_scale,
-      duration);
+  host_impl_->sync_tree()->SetPendingPageScaleAnimation(
+      scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
+          gfx::Vector2d(),
+          false,
+          target_scale,
+          duration)));
   host_impl_->Animate(halfway_through_animation);
   EXPECT_FALSE(did_request_animate_);
   EXPECT_FALSE(did_request_redraw_);
@@ -1328,7 +1338,8 @@
   // Activate the sync tree. This should cause the animation to become enabled.
   // It should also clear the pointer on the sync tree.
   host_impl_->ActivateSyncTree();
-  EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePageScaleAnimation().get());
+  EXPECT_EQ(nullptr,
+      host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
   EXPECT_FALSE(did_request_redraw_);
   EXPECT_TRUE(did_request_animate_);
 
@@ -1395,53 +1406,51 @@
   base::TimeTicks fake_current_physical_time_;
 };
 
-#define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST()                           \
-  gfx::Size viewport_size(10, 10);                                            \
-  gfx::Size content_size(100, 100);                                           \
-                                                                              \
-  LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =            \
-      new LayerTreeHostImplOverridePhysicalTime(settings,                     \
-                                                this,                         \
-                                                &proxy_,                      \
-                                                shared_bitmap_manager_.get(), \
-                                                &stats_instrumentation_);     \
-  host_impl_ = make_scoped_ptr(host_impl_override_time);                      \
-  host_impl_->InitializeRenderer(CreateOutputSurface());                      \
-  host_impl_->SetViewportSize(viewport_size);                                 \
-                                                                              \
-  scoped_ptr<LayerImpl> root =                                                \
-      LayerImpl::Create(host_impl_->active_tree(), 1);                        \
-  root->SetBounds(viewport_size);                                             \
-                                                                              \
-  scoped_ptr<LayerImpl> scroll =                                              \
-      LayerImpl::Create(host_impl_->active_tree(), 2);                        \
-  scroll->SetScrollClipLayer(root->id());                                     \
-  scroll->SetScrollOffset(gfx::ScrollOffset());                               \
-  root->SetBounds(viewport_size);                                             \
-  scroll->SetBounds(content_size);                                            \
-  scroll->SetContentBounds(content_size);                                     \
-  scroll->SetIsContainerForFixedPositionLayers(true);                         \
-                                                                              \
-  scoped_ptr<LayerImpl> contents =                                            \
-      LayerImpl::Create(host_impl_->active_tree(), 3);                        \
-  contents->SetDrawsContent(true);                                            \
-  contents->SetBounds(content_size);                                          \
-  contents->SetContentBounds(content_size);                                   \
-                                                                              \
-  scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =                        \
-      SolidColorScrollbarLayerImpl::Create(                                   \
-          host_impl_->active_tree(), 4, VERTICAL, 10, 0, false, true);        \
-  EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());                                 \
-                                                                              \
-  scroll->AddChild(contents.Pass());                                          \
-  root->AddChild(scroll.Pass());                                              \
-  scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);                           \
-  root->AddChild(scrollbar.Pass());                                           \
-                                                                              \
-  host_impl_->active_tree()->SetRootLayer(root.Pass());                       \
-  host_impl_->active_tree()->SetViewportLayersFromIds(                        \
-      1, 2, Layer::INVALID_ID);                                               \
-  host_impl_->active_tree()->DidBecomeActive();                               \
+#define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST()                            \
+  gfx::Size viewport_size(10, 10);                                             \
+  gfx::Size content_size(100, 100);                                            \
+                                                                               \
+  LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =             \
+      new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_,       \
+                                                shared_bitmap_manager_.get(),  \
+                                                &stats_instrumentation_);      \
+  host_impl_ = make_scoped_ptr(host_impl_override_time);                       \
+  host_impl_->InitializeRenderer(CreateOutputSurface());                       \
+  host_impl_->SetViewportSize(viewport_size);                                  \
+                                                                               \
+  scoped_ptr<LayerImpl> root =                                                 \
+      LayerImpl::Create(host_impl_->active_tree(), 1);                         \
+  root->SetBounds(viewport_size);                                              \
+                                                                               \
+  scoped_ptr<LayerImpl> scroll =                                               \
+      LayerImpl::Create(host_impl_->active_tree(), 2);                         \
+  scroll->SetScrollClipLayer(root->id());                                      \
+  scroll->SetScrollOffset(gfx::ScrollOffset());                                \
+  root->SetBounds(viewport_size);                                              \
+  scroll->SetBounds(content_size);                                             \
+  scroll->SetContentBounds(content_size);                                      \
+  scroll->SetIsContainerForFixedPositionLayers(true);                          \
+                                                                               \
+  scoped_ptr<LayerImpl> contents =                                             \
+      LayerImpl::Create(host_impl_->active_tree(), 3);                         \
+  contents->SetDrawsContent(true);                                             \
+  contents->SetBounds(content_size);                                           \
+  contents->SetContentBounds(content_size);                                    \
+                                                                               \
+  scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =                         \
+      SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4,       \
+                                           VERTICAL, 10, 0, false, true);      \
+  EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());                                  \
+                                                                               \
+  scroll->AddChild(contents.Pass());                                           \
+  root->AddChild(scroll.Pass());                                               \
+  scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);                            \
+  root->AddChild(scrollbar.Pass());                                            \
+                                                                               \
+  host_impl_->active_tree()->SetRootLayer(root.Pass());                        \
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, \
+                                                      Layer::INVALID_ID);      \
+  host_impl_->active_tree()->DidBecomeActive();                                \
   DrawFrame();
 
 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
@@ -1608,7 +1617,8 @@
   root->AddChild(scrollbar.Pass());
 
   host_impl_->active_tree()->SetRootLayer(root.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   DrawFrame();
 
@@ -2282,7 +2292,8 @@
     root_clip->AddChild(root.Pass());
     host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
     host_impl_->active_tree()->SetViewportLayersFromIds(
-        page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
+        Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
+        Layer::INVALID_ID);
     // Set a viewport size that is large enough to contain both the top controls
     // and some content.
     host_impl_->SetViewportSize(viewport_size_);
@@ -2306,7 +2317,8 @@
     root_clip->AddChild(root.Pass());
     host_impl_->sync_tree()->SetRootLayer(root_clip.Pass());
     host_impl_->sync_tree()->SetViewportLayersFromIds(
-        page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
+        Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
+        Layer::INVALID_ID);
     // Set a viewport size that is large enough to contain both the top controls
     // and some content.
     host_impl_->SetViewportSize(viewport_size_);
@@ -2361,8 +2373,7 @@
 
     host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
     host_impl_->active_tree()->SetViewportLayersFromIds(
-        page_scale_layer_id,
-        inner_viewport_scroll_layer_id,
+        Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
         outer_viewport_scroll_layer_id);
 
     host_impl_->SetViewportSize(inner_viewport_size);
@@ -2986,7 +2997,8 @@
   host_impl_->active_tree()->SetRootLayer(root.Pass());
   // The behaviour in this test assumes the page scale is applied at a layer
   // above the clip layer.
-  host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   host_impl_->SetViewportSize(viewport_size);
   DrawFrame();
@@ -3036,7 +3048,8 @@
   host_impl_->active_tree()->SetRootLayer(root.Pass());
   // The behaviour in this test assumes the page scale is applied at a layer
   // above the clip layer.
-  host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   host_impl_->SetViewportSize(viewport_size);
   host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
@@ -3151,7 +3164,8 @@
   LayerImpl* child = child_scrolling.get();
   root_scrolling_ptr->AddChild(child_scrolling.Pass());
   host_impl_->active_tree()->SetRootLayer(root.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   host_impl_->SetViewportSize(surface_size);
   DrawFrame();
@@ -3254,7 +3268,8 @@
   root->AddChild(root_scrolling.Pass());
   EXPECT_EQ(viewport_size, root->bounds());
   host_impl_->active_tree()->SetRootLayer(root.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   host_impl_->SetViewportSize(viewport_size);
 
@@ -3360,7 +3375,8 @@
 
   host_impl_->SetViewportSize(surface_size);
   host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   DrawFrame();
   {
@@ -3389,7 +3405,8 @@
   root_scroll->SetIsContainerForFixedPositionLayers(true);
   root_clip->AddChild(root_scroll.Pass());
   host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   host_impl_->SetViewportSize(surface_size);
 
@@ -3404,7 +3421,8 @@
   root_scroll2->SetIsContainerForFixedPositionLayers(true);
   root_clip2->AddChild(root_scroll2.Pass());
   host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
 
   // Scrolling should still work even though we did not draw yet.
@@ -3992,7 +4010,8 @@
 
   host_impl_->SetViewportSize(surface_size);
   host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   DrawFrame();
   {
@@ -4051,7 +4070,8 @@
   host_impl_->SetViewportSize(surface_size);
   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   DrawFrame();
   {
@@ -4085,7 +4105,8 @@
 
   host_impl_->SetViewportSize(surface_size);
   host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   DrawFrame();
   {
@@ -4795,7 +4816,7 @@
   // This test creates its own LayerTreeHostImpl, so
   // that we can force partial swap enabled.
   LayerTreeSettings settings;
-  settings.partial_swap_enabled = true;
+  settings.renderer_settings.partial_swap_enabled = true;
   scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
       new TestSharedBitmapManager());
   scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
@@ -5011,7 +5032,7 @@
 
   // Run test case
   LayerTreeSettings settings = DefaultSettings();
-  settings.partial_swap_enabled = false;
+  settings.renderer_settings.partial_swap_enabled = false;
   CreateHostImpl(settings,
                  FakeOutputSurface::Create3d(mock_context_owned.Pass()));
   SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
@@ -5047,7 +5068,7 @@
   MockContextHarness harness(mock_context);
 
   LayerTreeSettings settings = DefaultSettings();
-  settings.partial_swap_enabled = true;
+  settings.renderer_settings.partial_swap_enabled = true;
   CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
   SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
 
@@ -5091,7 +5112,7 @@
   provider->TestContext3d()->set_have_post_sub_buffer(true);
 
   LayerTreeSettings settings;
-  settings.partial_swap_enabled = partial_swap;
+  settings.renderer_settings.partial_swap_enabled = partial_swap;
   scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
       settings, client, proxy, stats_instrumentation, manager, NULL, 0);
   my_host_impl->InitializeRenderer(output_surface.Pass());
@@ -5264,7 +5285,7 @@
 
   // Run test case
   LayerTreeSettings settings = DefaultSettings();
-  settings.partial_swap_enabled = false;
+  settings.renderer_settings.partial_swap_enabled = false;
   CreateHostImpl(settings,
                  FakeOutputSurface::Create3d(mock_context_owned.Pass()));
   SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
@@ -6630,7 +6651,8 @@
 
   host_impl_->SetViewportSize(surface_size);
   host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
-  host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
+  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
+                                                      Layer::INVALID_ID);
   host_impl_->active_tree()->DidBecomeActive();
   DrawFrame();
   {
@@ -7472,8 +7494,9 @@
     inner_clip->AddChild(page_scale.Pass());
 
     layer_tree_impl->SetRootLayer(inner_clip.Pass());
-    layer_tree_impl->SetViewportLayersFromIds(kPageScaleLayerId,
-        kInnerViewportScrollLayerId, kOuterViewportScrollLayerId);
+    layer_tree_impl->SetViewportLayersFromIds(
+        Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
+        kOuterViewportScrollLayerId);
 
     host_impl_->active_tree()->DidBecomeActive();
   }
@@ -7527,6 +7550,49 @@
   }
 }
 
+TEST_F(LayerTreeHostImplVirtualViewportTest,
+       DiagonalScrollBubblesPerfectlyToInner) {
+  gfx::Size content_size = gfx::Size(100, 160);
+  gfx::Size outer_viewport = gfx::Size(50, 80);
+  gfx::Size inner_viewport = gfx::Size(25, 40);
+
+  SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
+
+  LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
+  LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
+  DrawFrame();
+  {
+    gfx::Vector2dF inner_expected;
+    gfx::Vector2dF outer_expected;
+    EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
+    EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
+
+    // Make sure the scroll goes to the outer viewport first.
+    EXPECT_EQ(InputHandler::ScrollStarted,
+              host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+    EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
+
+    // Scroll near the edge of the outer viewport.
+    gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
+    host_impl_->ScrollBy(gfx::Point(), scroll_delta);
+    outer_expected += scroll_delta;
+
+    EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
+    EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
+
+    // Now diagonal scroll across the outer viewport boundary in a single event.
+    // The entirety of the scroll should be consumed, as bubbling between inner
+    // and outer viewport layers is perfect.
+    host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
+    outer_expected += scroll_delta;
+    inner_expected += scroll_delta;
+    host_impl_->ScrollEnd();
+
+    EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
+    EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
+  }
+}
+
 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
  public:
   void SetUp() override {
diff --git a/cc/trees/layer_tree_host_pixeltest_blending.cc b/cc/trees/layer_tree_host_pixeltest_blending.cc
index 14029b5..aa236c8 100644
--- a/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -62,8 +62,9 @@
   }
 
   void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->force_antialiasing = force_antialiasing_;
-    settings->force_blending_with_shaders = force_blending_with_shaders_;
+    settings->renderer_settings.force_antialiasing = force_antialiasing_;
+    settings->renderer_settings.force_blending_with_shaders =
+        force_blending_with_shaders_;
   }
 
  protected:
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 4d0717d..c494914 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -51,6 +51,9 @@
   gfx::Size bounds_;
 };
 
+// TODO(enne): these time out on Windows.  http://crbug.com/435632
+#if !defined(OS_WIN)
+
 TEST_P(LayerTreeHostMasksPixelTest, MaskOfLayer) {
   scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
       gfx::Rect(200, 200), SK_ColorWHITE);
@@ -272,6 +275,8 @@
                            "mask_of_replica_of_clipped_layer.png")));
 }
 
+#endif  // !defined(OS_WIN)
+
 }  // namespace
 }  // namespace cc
 
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 72a5b45..f589c84 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1018,8 +1018,8 @@
     layer_tree_host()->root_layer()->AddChild(scroll_layer_);
     // This test requires the page_scale and inner viewport layers to be
     // identified.
-    layer_tree_host()->RegisterViewportLayers(
-        root_layer, scroll_layer_.get(), NULL);
+    layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
+                                              scroll_layer_.get(), NULL);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.5f, 2.f);
   }
 
@@ -1308,7 +1308,7 @@
 class LayerTreeHostTestDirectRendererAtomicCommit : public LayerTreeHostTest {
  public:
   void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->texture_id_allocation_chunk_size = 1;
+    settings->renderer_settings.texture_id_allocation_chunk_size = 1;
     // Make sure partial texture updates are turned off.
     settings->max_partial_texture_updates = 0;
     // Linear fade animator prevents scrollbars from drawing immediately.
@@ -1485,7 +1485,7 @@
     : public LayerTreeHostTest {
  public:
   void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->texture_id_allocation_chunk_size = 1;
+    settings->renderer_settings.texture_id_allocation_chunk_size = 1;
     // Allow one partial texture update.
     settings->max_partial_texture_updates = 1;
     // No partial updates when impl side painting is enabled.
@@ -2980,7 +2980,7 @@
   LayerTreeHostTestUIResource() : num_ui_resources_(0) {}
 
   void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->texture_id_allocation_chunk_size = 1;
+    settings->renderer_settings.texture_id_allocation_chunk_size = 1;
   }
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
@@ -5140,7 +5140,7 @@
             base::Unretained(this)));
     // Wait 50x longer than expected.
     double milliseconds_per_frame =
-        1000.0 / layer_tree_host()->settings().refresh_rate;
+        1000.0 / layer_tree_host()->settings().renderer_settings.refresh_rate;
     MainThreadTaskRunner()->PostDelayedTask(
         FROM_HERE,
         base::Bind(
@@ -5197,6 +5197,82 @@
 
 MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousPainting);
 
+class LayerTreeHostTestSendBeginFramesToChildren : public LayerTreeHostTest {
+ public:
+  LayerTreeHostTestSendBeginFramesToChildren()
+      : begin_frame_sent_to_children_(false) {
+  }
+
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->forward_begin_frames_to_children = true;
+  }
+
+  void BeginTest() override {
+    // Kick off the test with a commit.
+    PostSetNeedsCommitToMainThread();
+  }
+
+  void SendBeginFramesToChildren(const BeginFrameArgs& args) override {
+    begin_frame_sent_to_children_ = true;
+    EndTest();
+  }
+
+  void DidBeginMainFrame() override {
+    // Children requested BeginFrames.
+    layer_tree_host()->SetChildrenNeedBeginFrames(true);
+  }
+
+  void AfterTest() override {
+    // Ensure that BeginFrame message is sent to children during parent
+    // scheduler handles its BeginFrame.
+    EXPECT_TRUE(begin_frame_sent_to_children_);
+  }
+
+ private:
+  bool begin_frame_sent_to_children_;
+};
+
+SINGLE_THREAD_TEST_F(LayerTreeHostTestSendBeginFramesToChildren);
+
+class LayerTreeHostTestSendBeginFramesToChildrenWithExternalBFS
+    : public LayerTreeHostTest {
+ public:
+  LayerTreeHostTestSendBeginFramesToChildrenWithExternalBFS()
+      : begin_frame_sent_to_children_(false) {
+  }
+
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->use_external_begin_frame_source = true;
+    settings->forward_begin_frames_to_children = true;
+  }
+
+  void BeginTest() override {
+    // Kick off the test with a commit.
+    PostSetNeedsCommitToMainThread();
+  }
+
+  void SendBeginFramesToChildren(const BeginFrameArgs& args) override {
+    begin_frame_sent_to_children_ = true;
+    EndTest();
+  }
+
+  void DidBeginMainFrame() override {
+    // Children requested BeginFrames.
+    layer_tree_host()->SetChildrenNeedBeginFrames(true);
+  }
+
+  void AfterTest() override {
+    // Ensure that BeginFrame message is sent to children during parent
+    // scheduler handles its BeginFrame.
+    EXPECT_TRUE(begin_frame_sent_to_children_);
+  }
+
+ private:
+  bool begin_frame_sent_to_children_;
+};
+
+SINGLE_THREAD_TEST_F(LayerTreeHostTestSendBeginFramesToChildrenWithExternalBFS);
+
 class LayerTreeHostTestActivateOnInvisible : public LayerTreeHostTest {
  public:
   LayerTreeHostTestActivateOnInvisible()
@@ -5412,7 +5488,7 @@
     layer->disable_lcd_text();
     pinch->AddChild(layer);
 
-    layer_tree_host()->RegisterViewportLayers(root, pinch, pinch);
+    layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, pinch);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
     layer_tree_host()->SetRootLayer(root);
     LayerTreeHostTest::SetupTree();
@@ -5622,7 +5698,7 @@
     layer->disable_lcd_text();
     pinch->AddChild(layer);
 
-    layer_tree_host()->RegisterViewportLayers(root, pinch, pinch);
+    layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, pinch);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
     layer_tree_host()->SetRootLayer(root);
     LayerTreeHostTest::SetupTree();
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index dc34d3c..b646e6a 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -1247,7 +1247,7 @@
  public:
   UIResourceLostTest() : time_step_(0) {}
   void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->texture_id_allocation_chunk_size = 1;
+    settings->renderer_settings.texture_id_allocation_chunk_size = 1;
   }
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
   void AfterTest() override {}
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index 6526ff8..8015bda 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -45,7 +45,8 @@
     scroll_layer->SetIsContainerForFixedPositionLayers(true);
     scroll_layer->SetScrollClipLayerId(root_layer->id());
     scroll_layer->SetScrollOffset(initial_scroll_);
-    layer_tree_host()->RegisterViewportLayers(root_layer, scroll_layer, NULL);
+    layer_tree_host()->RegisterViewportLayers(NULL, root_layer, scroll_layer,
+                                              NULL);
     PostSetNeedsCommitToMainThread();
   }
 
@@ -122,7 +123,8 @@
     scroll_layer_->SetIsContainerForFixedPositionLayers(true);
     scroll_layer_->SetScrollClipLayerId(root_layer->id());
     scroll_layer_->SetScrollOffset(initial_scroll_);
-    layer_tree_host()->RegisterViewportLayers(root_layer, scroll_layer_, NULL);
+    layer_tree_host()->RegisterViewportLayers(NULL, root_layer, scroll_layer_,
+                                              NULL);
     PostSetNeedsCommitToMainThread();
   }
 
@@ -224,8 +226,8 @@
     root_scroll_layer->SetIsContainerForFixedPositionLayers(true);
     root_layer->AddChild(root_scroll_layer);
 
-    layer_tree_host()->RegisterViewportLayers(
-        root_layer, root_scroll_layer, NULL);
+    layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
+                                              root_scroll_layer, NULL);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
   }
 
@@ -407,8 +409,8 @@
     root_scroll_layer->SetIsContainerForFixedPositionLayers(true);
     root_layer->AddChild(root_scroll_layer);
 
-    layer_tree_host()->RegisterViewportLayers(
-        root_layer, root_scroll_layer, NULL);
+    layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
+                                              root_scroll_layer, NULL);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
   }
 
@@ -510,8 +512,8 @@
     expected_scroll_layer_->SetScrollOffset(initial_offset_);
 
     layer_tree_host()->SetRootLayer(root_layer);
-    layer_tree_host()->RegisterViewportLayers(
-        root_layer, root_scroll_layer_, NULL);
+    layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
+                                              root_scroll_layer_, NULL);
     LayerTreeHostScrollTest::SetupTree();
   }
 
@@ -779,8 +781,8 @@
     root_scroll_layer->SetIsContainerForFixedPositionLayers(true);
     root_layer->AddChild(root_scroll_layer);
 
-    layer_tree_host()->RegisterViewportLayers(
-        root_layer, root_scroll_layer, NULL);
+    layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
+                                              root_scroll_layer, NULL);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
   }
 
@@ -910,8 +912,8 @@
     root_scroll_layer->SetIsContainerForFixedPositionLayers(true);
     root_layer->AddChild(root_scroll_layer);
 
-    layer_tree_host()->RegisterViewportLayers(
-        root_layer, root_scroll_layer, NULL);
+    layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
+                                              root_scroll_layer, NULL);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
   }
 
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index c005a18..ad355fa 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -221,12 +221,14 @@
       target_tree->page_scale_delta() / target_tree->sent_page_scale_delta());
   target_tree->set_sent_page_scale_delta(1);
 
-  target_tree->page_scale_animation_ = page_scale_animation_.Pass();
+  target_tree->pending_page_scale_animation_ =
+      pending_page_scale_animation_.Pass();
 
   if (page_scale_layer_ && inner_viewport_scroll_layer_) {
     target_tree->SetViewportLayersFromIds(
-        page_scale_layer_->id(),
-        inner_viewport_scroll_layer_->id(),
+        overscroll_elasticity_layer_ ? overscroll_elasticity_layer_->id()
+                                     : Layer::INVALID_ID,
+        page_scale_layer_->id(), inner_viewport_scroll_layer_->id(),
         outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id()
                                      : Layer::INVALID_ID);
   } else {
@@ -425,9 +427,11 @@
 }
 
 void LayerTreeImpl::SetViewportLayersFromIds(
+    int overscroll_elasticity_layer_id,
     int page_scale_layer_id,
     int inner_viewport_scroll_layer_id,
     int outer_viewport_scroll_layer_id) {
+  overscroll_elasticity_layer_ = LayerById(overscroll_elasticity_layer_id);
   page_scale_layer_ = LayerById(page_scale_layer_id);
   DCHECK(page_scale_layer_);
 
@@ -1480,45 +1484,14 @@
   return proxy()->blocking_main_thread_task_runner();
 }
 
-void LayerTreeImpl::SetPageScaleAnimation(
-    const gfx::Vector2d& target_offset,
-    bool anchor_point,
-    float page_scale,
-    base::TimeDelta duration) {
-  if (!InnerViewportScrollLayer())
-    return;
-
-  gfx::ScrollOffset scroll_total = TotalScrollOffset();
-  gfx::SizeF scaled_scrollable_size = ScrollableSize();
-  gfx::SizeF viewport_size = InnerViewportContainerLayer()->bounds();
-
-  // Easing constants experimentally determined.
-  scoped_ptr<TimingFunction> timing_function =
-      CubicBezierTimingFunction::Create(.8, 0, .3, .9);
-
-  // TODO(miletus) : Pass in ScrollOffset.
-  page_scale_animation_ =
-      PageScaleAnimation::Create(ScrollOffsetToVector2dF(scroll_total),
-                                 total_page_scale_factor(),
-                                 viewport_size,
-                                 scaled_scrollable_size,
-                                 timing_function.Pass());
-
-  if (anchor_point) {
-    gfx::Vector2dF anchor(target_offset);
-    page_scale_animation_->ZoomWithAnchor(anchor,
-                                          page_scale,
-                                          duration.InSecondsF());
-  } else {
-    gfx::Vector2dF scaled_target_offset = target_offset;
-    page_scale_animation_->ZoomTo(scaled_target_offset,
-                                  page_scale,
-                                  duration.InSecondsF());
-  }
+void LayerTreeImpl::SetPendingPageScaleAnimation(
+    scoped_ptr<PendingPageScaleAnimation> pending_animation) {
+  pending_page_scale_animation_ = pending_animation.Pass();
 }
 
-scoped_ptr<PageScaleAnimation> LayerTreeImpl::TakePageScaleAnimation() {
-  return page_scale_animation_.Pass();
+scoped_ptr<PendingPageScaleAnimation>
+    LayerTreeImpl::TakePendingPageScaleAnimation() {
+  return pending_page_scale_animation_.Pass();
 }
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 57e6ca1..60a097d 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -44,6 +44,7 @@
 class ResourceProvider;
 class TileManager;
 class UIResourceRequest;
+struct PendingPageScaleAnimation;
 struct RendererCapabilities;
 struct SelectionHandle;
 
@@ -137,10 +138,14 @@
   void SetCurrentlyScrollingLayer(LayerImpl* layer);
   void ClearCurrentlyScrollingLayer();
 
-  void SetViewportLayersFromIds(int page_scale_layer_id,
+  void SetViewportLayersFromIds(int overscroll_elasticity_layer,
+                                int page_scale_layer_id,
                                 int inner_viewport_scroll_layer_id,
                                 int outer_viewport_scroll_layer_id);
   void ClearViewportLayers();
+  LayerImpl* overscroll_elasticity_layer() {
+    return overscroll_elasticity_layer_;
+  }
   LayerImpl* page_scale_layer() { return page_scale_layer_; }
   void ApplySentScrollAndScaleDeltasFromAbortedCommit();
   void ApplyScrollDeltasSinceBeginMainFrame();
@@ -310,12 +315,9 @@
     return top_controls_content_offset_ + top_controls_delta_;
   }
 
-  void SetPageScaleAnimation(
-      const gfx::Vector2d& target_offset,
-      bool anchor_point,
-      float page_scale,
-      base::TimeDelta duration);
-  scoped_ptr<PageScaleAnimation> TakePageScaleAnimation();
+  void SetPendingPageScaleAnimation(
+      scoped_ptr<PendingPageScaleAnimation> pending_animation);
+  scoped_ptr<PendingPageScaleAnimation> TakePendingPageScaleAnimation();
 
  protected:
   explicit LayerTreeImpl(LayerTreeHostImpl* layer_tree_host_impl);
@@ -334,6 +336,7 @@
   SkColor background_color_;
   bool has_transparent_background_;
 
+  LayerImpl* overscroll_elasticity_layer_;
   LayerImpl* page_scale_layer_;
   LayerImpl* inner_viewport_scroll_layer_;
   LayerImpl* outer_viewport_scroll_layer_;
@@ -387,7 +390,7 @@
   float top_controls_delta_;
   float sent_top_controls_delta_;
 
-  scoped_ptr<PageScaleAnimation> page_scale_animation_;
+  scoped_ptr<PendingPageScaleAnimation> pending_page_scale_animation_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LayerTreeImpl);
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index f8de8b0..52f8e0a 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -1798,7 +1798,8 @@
   host_impl().active_tree()->SetPageScaleFactorAndLimits(
       page_scale_factor, page_scale_factor, page_scale_factor);
   host_impl().active_tree()->SetRootLayer(root.Pass());
-  host_impl().active_tree()->SetViewportLayersFromIds(1, 1, Layer::INVALID_ID);
+  host_impl().active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 1,
+                                                      Layer::INVALID_ID);
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -2301,7 +2302,8 @@
   host_impl().active_tree()->SetPageScaleFactorAndLimits(
       page_scale_factor, page_scale_factor, page_scale_factor);
   host_impl().active_tree()->SetRootLayer(root.Pass());
-  host_impl().active_tree()->SetViewportLayersFromIds(1, 1, Layer::INVALID_ID);
+  host_impl().active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 1,
+                                                      Layer::INVALID_ID);
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index 14c1def..e792427 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -14,9 +14,6 @@
 
 LayerTreeSettings::LayerTreeSettings()
     : impl_side_painting(false),
-      allow_antialiasing(true),
-      force_antialiasing(false),
-      force_blending_with_shaders(false),
       throttle_frame_production(true),
       single_thread_proxy_scheduler(true),
       use_external_begin_frame_source(false),
@@ -26,11 +23,9 @@
       disable_hi_res_timer_tasks_on_battery(false),
       report_overscroll_only_for_scrollable_axes(false),
       per_tile_painting_enabled(false),
-      partial_swap_enabled(false),
       accelerated_animation_enabled(true),
       can_use_lcd_text(true),
       use_distance_field_text(false),
-      should_clear_root_render_pass(true),
       gpu_rasterization_enabled(false),
       gpu_rasterization_forced(false),
       create_low_res_tiling(false),
@@ -49,7 +44,6 @@
       top_controls_height(0.f),
       top_controls_show_threshold(0.5f),
       top_controls_hide_threshold(0.5f),
-      refresh_rate(60.0),
       background_animation_rate(1.0),
       max_partial_texture_updates(std::numeric_limits<size_t>::max()),
       default_tile_size(gfx::Size(256, 256)),
@@ -64,13 +58,10 @@
       skewport_extrapolation_limit_in_content_pixels(2000),
       max_unused_resource_memory_percentage(100),
       max_memory_for_prepaint_percentage(100),
-      highp_threshold_min(0),
       strict_layer_property_change_checking(false),
       use_one_copy(false),
       use_zero_copy(false),
       ignore_root_layer_flings(false),
-      use_rgba_4444_textures(false),
-      texture_id_allocation_chunk_size(64),
       scheduled_raster_task_limit(32),
       use_occlusion_for_tile_prioritization(false),
       record_full_layer(false) {
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 69ac995..ebbe7f7 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -8,6 +8,7 @@
 #include "base/basictypes.h"
 #include "cc/base/cc_export.h"
 #include "cc/debug/layer_tree_debug_state.h"
+#include "cc/output/renderer_settings.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/size.h"
 
@@ -18,10 +19,8 @@
   LayerTreeSettings();
   ~LayerTreeSettings();
 
+  RendererSettings renderer_settings;
   bool impl_side_painting;
-  bool allow_antialiasing;
-  bool force_antialiasing;
-  bool force_blending_with_shaders;
   bool throttle_frame_production;
   bool single_thread_proxy_scheduler;
   bool use_external_begin_frame_source;
@@ -31,11 +30,9 @@
   bool disable_hi_res_timer_tasks_on_battery;
   bool report_overscroll_only_for_scrollable_axes;
   bool per_tile_painting_enabled;
-  bool partial_swap_enabled;
   bool accelerated_animation_enabled;
   bool can_use_lcd_text;
   bool use_distance_field_text;
-  bool should_clear_root_render_pass;
   bool gpu_rasterization_enabled;
   bool gpu_rasterization_forced;
   bool create_low_res_tiling;
@@ -60,7 +57,6 @@
   float top_controls_height;
   float top_controls_show_threshold;
   float top_controls_hide_threshold;
-  double refresh_rate;
   double background_animation_rate;
   size_t max_partial_texture_updates;
   gfx::Size default_tile_size;
@@ -74,13 +70,10 @@
   int skewport_extrapolation_limit_in_content_pixels;
   size_t max_unused_resource_memory_percentage;
   size_t max_memory_for_prepaint_percentage;
-  int highp_threshold_min;
   bool strict_layer_property_change_checking;
   bool use_one_copy;
   bool use_zero_copy;
   bool ignore_root_layer_flings;
-  bool use_rgba_4444_textures;
-  size_t texture_id_allocation_chunk_size;
   size_t scheduled_raster_task_limit;
   bool use_occlusion_for_tile_prioritization;
   bool record_full_layer;
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index feeab43..c6f281b 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -104,6 +104,8 @@
 
   virtual void SetDebugState(const LayerTreeDebugState& debug_state) = 0;
 
+  virtual void SetChildrenNeedBeginFrames(bool children_need_begin_frames) = 0;
+
   // Testing hooks
   virtual bool MainFrameWillHappenForTesting() = 0;
 
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 4cb0a9e..5a40d7e 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -103,7 +103,7 @@
 }
 
 void SingleThreadProxy::SetVisible(bool visible) {
-  TRACE_EVENT0("cc", "SingleThreadProxy::SetVisible");
+  TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible);
   DebugScopedSetImplThread impl(this);
   layer_tree_host_impl_->SetVisible(visible);
   if (scheduler_on_impl_thread_)
@@ -492,10 +492,9 @@
   }
 
   {
-    BeginFrameArgs begin_frame_args(
-        BeginFrameArgs::Create(frame_begin_time,
-                               base::TimeTicks(),
-                               BeginFrameArgs::DefaultInterval()));
+    BeginFrameArgs begin_frame_args(BeginFrameArgs::Create(
+        frame_begin_time, base::TimeTicks(), BeginFrameArgs::DefaultInterval(),
+        BeginFrameArgs::SYNCHRONOUS));
     DoBeginMainFrame(begin_frame_args);
     DoCommit();
 
@@ -634,6 +633,12 @@
   return false;
 }
 
+void SingleThreadProxy::SetChildrenNeedBeginFrames(
+    bool children_need_begin_frames) {
+  scheduler_on_impl_thread_->SetChildrenNeedBeginFrames(
+      children_need_begin_frames);
+}
+
 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
   layer_tree_host_impl_->WillBeginImplFrame(args);
 }
@@ -792,4 +797,8 @@
   layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
 }
 
+void SingleThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
+  layer_tree_host_->SendBeginFramesToChildren(args);
+}
+
 }  // namespace cc
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index e4cf793..3eba6bb 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -59,6 +59,7 @@
   bool SupportsImplScrolling() const override;
   void AsValueInto(base::debug::TracedValue* state) const override;
   bool MainFrameWillHappenForTesting() override;
+  void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
 
   // SchedulerClient implementation
   void WillBeginImplFrame(const BeginFrameArgs& args) override;
@@ -75,6 +76,7 @@
   base::TimeDelta BeginMainFrameToCommitDurationEstimate() override;
   base::TimeDelta CommitToActivateDurationEstimate() override;
   void DidBeginImplFrameDeadline() override;
+  void SendBeginFramesToChildren(const BeginFrameArgs& args) override;
 
   // LayerTreeHostImplClient implementation
   void UpdateRendererCapabilitiesOnImplThread() override;
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index bd85f01..4793cc5 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -165,7 +165,7 @@
 }
 
 void ThreadProxy::SetVisible(bool visible) {
-  TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
+  TRACE_EVENT1("cc", "ThreadProxy::SetVisible", "visible", visible);
   DebugScopedSetMainThreadBlocked main_thread_blocked(this);
 
   CompletionEvent completion;
@@ -180,7 +180,7 @@
 
 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
                                          bool visible) {
-  TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
+  TRACE_EVENT1("cc", "ThreadProxy::SetVisibleOnImplThread", "visible", visible);
   impl().layer_tree_host_impl->SetVisible(visible);
   impl().scheduler->SetVisible(visible);
   completion->Signal();
@@ -1095,6 +1095,10 @@
   impl().layer_tree_host_impl->ResetCurrentBeginFrameArgsForNextFrame();
 }
 
+void ThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
+  NOTREACHED() << "Only used by SingleThreadProxy";
+}
+
 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
   DCHECK(IsImplThread());
   impl().scheduler->NotifyReadyToCommit();
@@ -1250,6 +1254,10 @@
   return main_frame_will_happen;
 }
 
+void ThreadProxy::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
+  NOTREACHED() << "Only used by SingleThreadProxy";
+}
+
 void ThreadProxy::MainFrameWillHappenOnImplThreadForTesting(
     CompletionEvent* completion,
     bool* main_frame_will_happen) {
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
index a1064ab..d6d53a8 100644
--- a/cc/trees/thread_proxy.h
+++ b/cc/trees/thread_proxy.h
@@ -175,6 +175,7 @@
   void SetDebugState(const LayerTreeDebugState& debug_state) override;
   void AsValueInto(base::debug::TracedValue* value) const override;
   bool MainFrameWillHappenForTesting() override;
+  void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
 
   // LayerTreeHostImplClient implementation
   void UpdateRendererCapabilitiesOnImplThread() override;
@@ -222,6 +223,7 @@
   base::TimeDelta BeginMainFrameToCommitDurationEstimate() override;
   base::TimeDelta CommitToActivateDurationEstimate() override;
   void DidBeginImplFrameDeadline() override;
+  void SendBeginFramesToChildren(const BeginFrameArgs& args) override;
 
   // ResourceUpdateControllerClient implementation
   void ReadyToFinalizeTextureUpdates() override;
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h
index a4017ec..6a31b8f 100644
--- a/gpu/GLES2/gl2extchromium.h
+++ b/gpu/GLES2/gl2extchromium.h
@@ -200,7 +200,7 @@
 
 #ifndef GL_GET_ERROR_QUERY_CHROMIUM
 // TODO(gman): Get official numbers for this constants.
-#define GL_GET_ERROR_QUERY_CHROMIUM 0x84F3
+#define GL_GET_ERROR_QUERY_CHROMIUM 0x6003
 #endif
 #endif  /* GL_CHROMIUM_get_error_query */
 
@@ -256,7 +256,7 @@
 
 #ifndef GL_COMMANDS_ISSUED_CHROMIUM
 // TODO(gman): Get official numbers for this constants.
-#define GL_COMMANDS_ISSUED_CHROMIUM 0x84F2
+#define GL_COMMANDS_ISSUED_CHROMIUM 0x6004
 #endif
 #endif  /* GL_CHROMIUM_command_buffer_query */
 
@@ -367,10 +367,10 @@
 #define GL_CHROMIUM_async_pixel_transfers 1
 
 #ifndef GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
-#define GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM 0x84F5
+#define GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM 0x6005
 #endif
 #ifndef GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
-#define GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM 0x84F6
+#define GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM 0x6006
 #endif
 #endif  /* GL_CHROMIUM_async_pixel_transfers */
 
@@ -455,7 +455,7 @@
 
 #ifndef GL_LATENCY_QUERY_CHROMIUM
 // TODO(gman): Get official numbers for these constants.
-#define GL_LATENCY_QUERY_CHROMIUM 0x84F4
+#define GL_LATENCY_QUERY_CHROMIUM 0x6007
 #endif
 #endif  /* GL_CHROMIUM_command_buffer_latency_query */
 
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 226cb73..7cccd43 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -8309,8 +8309,14 @@
         if m:
           name = m.group(1)
           value = m.group(2)
-          if len(value) <= 10 and not value in dict:
-            dict[value] = name
+          if len(value) <= 10:
+            if not value in dict:
+              dict[value] = name
+            # check our own _CHROMIUM macro conflicts with khronos GL headers.
+            elif dict[value] != name and (name.endswith('_CHROMIUM') or
+                dict[value].endswith('_CHROMIUM')):
+              self.Error("code collision: %s and %s have the same code %s" %
+                         (dict[value], name, value))
 
     file = CHeaderWriter(filename)
     file.Write("static const GLES2Util::EnumToString "
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index e7118e8..51c6370 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -210,8 +210,11 @@
   WaitForCmd();
   query_tracker_.reset();
 
-  if (support_client_side_arrays_)
+  // GLES2Implementation::Initialize() could fail before allocating
+  // reserved_ids_, so we need delete them carefully.
+  if (support_client_side_arrays_ && reserved_ids_[0]) {
     DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]);
+  }
 
   // Release any per-context data in share group.
   share_group_->FreeContext(this);
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 5c944a8..87aaeb1 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -93,7 +93,8 @@
       CommandBuffer* command_buffer,
       unsigned int size,
       unsigned int result_size,
-      unsigned int alignment)
+      unsigned int alignment,
+      bool initialize_fail)
       : command_buffer_(command_buffer),
         size_(size),
         result_size_(result_size),
@@ -102,7 +103,8 @@
         expected_buffer_index_(0),
         last_alloc_(NULL),
         expected_offset_(result_size),
-        actual_offset_(result_size) {
+        actual_offset_(result_size),
+        initialize_fail_(initialize_fail) {
     // We have to allocate the buffers here because
     // we need to know their address before GLES2Implementation::Initialize
     // is called.
@@ -220,6 +222,7 @@
   void* last_alloc_;
   uint32 expected_offset_;
   uint32 actual_offset_;
+  bool initialize_fail_;
 
   DISALLOW_COPY_AND_ASSIGN(MockTransferBuffer);
 };
@@ -234,7 +237,7 @@
   // Just check they match.
   return size_ == starting_buffer_size &&
          result_size_ == result_size &&
-         alignment_ == alignment;
+         alignment_ == alignment && !initialize_fail_;
 };
 
 int MockTransferBuffer::GetShmId() {
@@ -394,7 +397,8 @@
     bool Initialize(ShareGroup* share_group,
                     bool bind_generates_resource_client,
                     bool bind_generates_resource_service,
-                    bool lose_context_when_out_of_memory) {
+                    bool lose_context_when_out_of_memory,
+                    bool transfer_buffer_initialize_fail) {
       command_buffer_.reset(new StrictMock<MockClientCommandBuffer>());
       if (!command_buffer_->Initialize())
         return false;
@@ -403,7 +407,8 @@
           new MockTransferBuffer(command_buffer_.get(),
                                  kTransferBufferSize,
                                  GLES2Implementation::kStartingOffset,
-                                 GLES2Implementation::kAlignment));
+                                 GLES2Implementation::kAlignment,
+                                 transfer_buffer_initialize_fail));
 
       helper_.reset(new GLES2CmdHelper(command_buffer()));
       helper_->Initialize(kCommandBufferSizeBytes);
@@ -522,11 +527,13 @@
     ContextInitOptions()
         : bind_generates_resource_client(true),
           bind_generates_resource_service(true),
-          lose_context_when_out_of_memory(false) {}
+          lose_context_when_out_of_memory(false),
+          transfer_buffer_initialize_fail(false) {}
 
     bool bind_generates_resource_client;
     bool bind_generates_resource_service;
     bool lose_context_when_out_of_memory;
+    bool transfer_buffer_initialize_fail;
   };
 
   bool Initialize(const ContextInitOptions& init_options) {
@@ -538,7 +545,8 @@
               share_group_.get(),
               init_options.bind_generates_resource_client,
               init_options.bind_generates_resource_service,
-              init_options.lose_context_when_out_of_memory))
+              init_options.lose_context_when_out_of_memory,
+              init_options.transfer_buffer_initialize_fail))
         success = false;
     }
 
@@ -3302,6 +3310,12 @@
   EXPECT_FALSE(Initialize(init_options));
 }
 
+TEST_F(GLES2ImplementationManualInitTest, FailInitOnTransferBufferFail) {
+  ContextInitOptions init_options;
+  init_options.transfer_buffer_initialize_fail = true;
+  EXPECT_FALSE(Initialize(init_options));
+}
+
 #include "gpu/command_buffer/client/gles2_implementation_unittest_autogen.h"
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
index 1a0945a..3176cc8 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -449,6 +449,10 @@
      "GL_TIME_ELAPSED_EXT",
     },
     {
+     0x6003,
+     "GL_GET_ERROR_QUERY_CHROMIUM",
+    },
+    {
      0x0C10,
      "GL_SCISSOR_BOX",
     },
@@ -1089,6 +1093,10 @@
      "GL_RGBA32F_EXT",
     },
     {
+     0x6004,
+     "GL_COMMANDS_ISSUED_CHROMIUM",
+    },
+    {
      0x813D,
      "GL_TEXTURE_MAX_LEVEL_APPLE",
     },
@@ -1126,7 +1134,7 @@
     },
     {
      0x84F5,
-     "GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM",
+     "GL_TEXTURE_RECTANGLE_ARB",
     },
     {
      0x882A,
@@ -1142,7 +1150,7 @@
     },
     {
      0x84F6,
-     "GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM",
+     "GL_TEXTURE_BINDING_RECTANGLE_ARB",
     },
     {
      0x80AB,
@@ -1153,6 +1161,10 @@
      "GL_MAX_PATCH_VERTICES_EXT",
     },
     {
+     0x6005,
+     "GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM",
+    },
+    {
      0x9105,
      "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES",
     },
@@ -1193,6 +1205,10 @@
      "GL_ISOLINES_EXT",
     },
     {
+     0x6006,
+     "GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM",
+    },
+    {
      0x8A4A,
      "GL_SKIP_DECODE_EXT",
     },
@@ -1221,6 +1237,10 @@
      "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT",
     },
     {
+     0x6007,
+     "GL_LATENCY_QUERY_CHROMIUM",
+    },
+    {
      0x8916,
      "GL_GEOMETRY_LINKED_VERTICES_OUT_EXT",
     },
diff --git a/gpu/command_buffer/service/buffer_manager_unittest.cc b/gpu/command_buffer/service/buffer_manager_unittest.cc
index 5c24eb0..bef0089 100644
--- a/gpu/command_buffer/service/buffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/buffer_manager_unittest.cc
@@ -210,21 +210,21 @@
 TEST_F(BufferManagerTest, GetRange) {
   const GLuint kClientBufferId = 1;
   const GLuint kServiceBufferId = 11;
-  const uint8 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+  const GLsizeiptr kDataSize = 10;
   manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
   Buffer* buffer = manager_->GetBuffer(kClientBufferId);
   ASSERT_TRUE(buffer != NULL);
   manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER);
-  DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
+  DoBufferData(buffer, kDataSize, GL_STATIC_DRAW, NULL, GL_NO_ERROR);
   const char* buf =
-      static_cast<const char*>(buffer->GetRange(0, sizeof(data)));
+      static_cast<const char*>(buffer->GetRange(0, kDataSize));
   ASSERT_TRUE(buf != NULL);
   const char* buf1 =
-      static_cast<const char*>(buffer->GetRange(1, sizeof(data) - 1));
+      static_cast<const char*>(buffer->GetRange(1, kDataSize - 1));
   EXPECT_EQ(buf + 1, buf1);
-  EXPECT_TRUE(buffer->GetRange(sizeof(data), 1) == NULL);
-  EXPECT_TRUE(buffer->GetRange(0, sizeof(data) + 1) == NULL);
-  EXPECT_TRUE(buffer->GetRange(-1, sizeof(data)) == NULL);
+  EXPECT_TRUE(buffer->GetRange(kDataSize, 1) == NULL);
+  EXPECT_TRUE(buffer->GetRange(0, kDataSize + 1) == NULL);
+  EXPECT_TRUE(buffer->GetRange(-1, kDataSize) == NULL);
   EXPECT_TRUE(buffer->GetRange(-0, -1) == NULL);
   const int size = 0x20000;
   DoBufferData(buffer, size / 2, GL_STATIC_DRAW, NULL, GL_NO_ERROR);
@@ -350,7 +350,7 @@
 TEST_F(BufferManagerTest, UseDeletedBuffer) {
   const GLuint kClientBufferId = 1;
   const GLuint kServiceBufferId = 11;
-  const uint32 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+  const GLsizeiptr kDataSize = 10;
   manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
   scoped_refptr<Buffer> buffer = manager_->GetBuffer(kClientBufferId);
   ASSERT_TRUE(buffer.get() != NULL);
@@ -358,7 +358,7 @@
   // Remove buffer
   manager_->RemoveBuffer(kClientBufferId);
   // Use it after removing
-  DoBufferData(buffer.get(), sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
+  DoBufferData(buffer.get(), kDataSize, GL_STATIC_DRAW, NULL, GL_NO_ERROR);
   // Check that it gets deleted when the last reference is released.
   EXPECT_CALL(*gl_, DeleteBuffersARB(1, ::testing::Pointee(kServiceBufferId)))
       .Times(1)
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
index ffb9370..49bba9b 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
+++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
@@ -218,7 +218,6 @@
                       GLuint source_id,
                       GLuint dest_id,
                       GLint dest_level,
-                      GLenum dest_internal_format,
                       GLsizei width,
                       GLsizei height,
                       GLuint framebuffer) {
@@ -231,14 +230,8 @@
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glCopyTexImage2D(GL_TEXTURE_2D,
-                     dest_level,
-                     dest_internal_format,
-                     0 /* x */,
-                     0 /* y */,
-                     width,
-                     height,
-                     0 /* border */);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, dest_level, 0 /* xoffset */,
+                        0 /* yoffset */, 0 /* x */, 0 /* y */, width, height);
   }
 
   decoder->RestoreTextureState(source_id);
@@ -332,16 +325,15 @@
   bool source_format_contain_superset_of_dest_format =
       source_internal_format == dest_internal_format ||
       (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
-  // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
-  // so restrict this to GL_TEXTURE_2D.
-  if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change &&
+  bool source_target_allowed = source_target == GL_TEXTURE_2D ||
+                               source_target == GL_TEXTURE_RECTANGLE_ARB;
+  if (source_target_allowed && !flip_y && !premultiply_alpha_change &&
       source_format_contain_superset_of_dest_format) {
     DoCopyTexImage2D(decoder,
                      source_target,
                      source_id,
                      dest_id,
                      dest_level,
-                     dest_internal_format,
                      width,
                      height,
                      framebuffer_);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc
index a858cf7..fd28f75 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc
@@ -54,8 +54,7 @@
 using namespace cmds;
 
 TEST_P(GLES2DecoderWithShaderTest, GetVertexAttribPointervSucceeds) {
-  const float dummy = 0;
-  const GLuint kOffsetToTestFor = sizeof(dummy) * 4;
+  const GLuint kOffsetToTestFor = sizeof(float) * 4;
   const GLuint kIndexToTest = 1;
   GetVertexAttribPointerv::Result* result =
       static_cast<GetVertexAttribPointerv::Result*>(shared_memory_address_);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 36afe38..a27bb3d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -1532,8 +1532,7 @@
 void GLES2DecoderTestBase::SetupVertexBuffer() {
   DoEnableVertexAttribArray(1);
   DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId);
-  GLfloat f = 0;
-  DoBufferData(GL_ARRAY_BUFFER, kNumVertices * 2 * sizeof(f));
+  DoBufferData(GL_ARRAY_BUFFER, kNumVertices * 2 * sizeof(GLfloat));
 }
 
 void GLES2DecoderTestBase::SetupAllNeededVertexBuffers() {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
index 789b48a..78fa020 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
@@ -644,11 +644,10 @@
 
 TEST_P(GLES2DecoderTest, ReadPixelsInvalidArgs) {
   typedef ReadPixels::Result Result;
-  Result* result = GetSharedMemoryAs<Result*>();
   uint32 result_shm_id = kSharedMemoryId;
   uint32 result_shm_offset = kSharedMemoryOffset;
   uint32 pixels_shm_id = kSharedMemoryId;
-  uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
+  uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(Result);
   EXPECT_CALL(*gl_, ReadPixels(_, _, _, _, _, _, _)).Times(0);
   ReadPixels cmd;
   cmd.Init(0,
@@ -750,14 +749,13 @@
   InitDecoder(init);
 
   typedef ReadPixels::Result Result;
-  Result* result = GetSharedMemoryAs<Result*>();
 
   const GLsizei kWidth = 4;
   const GLsizei kHeight = 4;
   uint32 result_shm_id = kSharedMemoryId;
   uint32 result_shm_offset = kSharedMemoryOffset;
   uint32 pixels_shm_id = kSharedMemoryId;
-  uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
+  uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(Result);
 
   EXPECT_CALL(*gl_, GetError())
       // first error check must pass to get to the test
@@ -1637,11 +1635,10 @@
   GLsizei width = 2;
   GLsizei height = 4;
   typedef ReadPixels::Result Result;
-  Result* result = GetSharedMemoryAs<Result*>();
   uint32 result_shm_id = kSharedMemoryId;
   uint32 result_shm_offset = kSharedMemoryOffset;
   uint32 pixels_shm_id = kSharedMemoryId;
-  uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
+  uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(Result);
   EXPECT_CALL(*gl_, GetError())
       .WillOnce(Return(GL_NO_ERROR))
       .WillOnce(Return(GL_OUT_OF_MEMORY))
@@ -1765,11 +1762,10 @@
       .Times(1)
       .RetiresOnSaturation();
   typedef ReadPixels::Result Result;
-  Result* result = GetSharedMemoryAs<Result*>();
   uint32 result_shm_id = kSharedMemoryId;
   uint32 result_shm_offset = kSharedMemoryOffset;
   uint32 pixels_shm_id = kSharedMemoryId;
-  uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
+  uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(Result);
   ReadPixels cmd;
   cmd.Init(0,
            0,
diff --git a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
index 2c44e1a..a8cbb66 100644
--- a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
+++ b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
@@ -76,6 +76,43 @@
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 }
 
+TEST_F(GLCopyTextureCHROMIUMTest, ImmutableTexture) {
+  if (!GLTestHelper::HasExtension("GL_EXT_texture_storage")) {
+    LOG(INFO) << "GL_EXT_texture_storage not supported. Skipping test...";
+    return;
+  }
+
+  uint8 pixels[1 * 4] = {255u, 0u, 0u, 255u};
+
+  glBindTexture(GL_TEXTURE_2D, textures_[0]);
+  glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1);
+  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+                  pixels);
+
+  glBindTexture(GL_TEXTURE_2D, textures_[1]);
+  glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1);
+  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                         textures_[1], 0);
+  EXPECT_TRUE(glGetError() == GL_NO_ERROR);
+
+  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA,
+                        GL_UNSIGNED_BYTE);
+  EXPECT_TRUE(glGetError() == GL_NO_ERROR);
+
+  // Check the FB is still bound.
+  GLint value = 0;
+  glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value);
+  GLuint fb_id = value;
+  EXPECT_EQ(framebuffer_id_, fb_id);
+
+  // Check that FB is complete.
+  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+            glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+  GLTestHelper::CheckPixels(0, 0, 1, 1, 0, pixels);
+  EXPECT_TRUE(GL_NO_ERROR == glGetError());
+}
+
 TEST_F(GLCopyTextureCHROMIUMTest, InternalFormat) {
   GLint src_formats[] = {GL_ALPHA,     GL_RGB,             GL_RGBA,
                          GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_BGRA_EXT};
diff --git a/mojo/services/surfaces/surfaces_impl.cc b/mojo/services/surfaces/surfaces_impl.cc
index 6d98c9d..10414f9 100644
--- a/mojo/services/surfaces/surfaces_impl.cc
+++ b/mojo/services/surfaces/surfaces_impl.cc
@@ -80,7 +80,8 @@
     return;
   }
   if (!display_) {
-    display_.reset(new cc::Display(this, manager_, NULL, NULL));
+    cc::RendererSettings settings;
+    display_.reset(new cc::Display(this, manager_, nullptr, nullptr, settings));
     client_->SetDisplay(display_.get());
     display_->Initialize(make_scoped_ptr(new DirectOutputSurface(
         new ContextProviderMojo(command_buffer_handle_.Pass()))));
diff --git a/net/BUILD.gn b/net/BUILD.gn
index be0ac53..a9d20aa 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -406,8 +406,8 @@
       "websockets/websocket_frame_parser.h",
       "websockets/websocket_handshake_constants.cc",
       "websockets/websocket_handshake_constants.h",
-      "websockets/websocket_handshake_handler.cc",
-      "websockets/websocket_handshake_handler.h",
+      "websockets/websocket_handshake_challenge.cc",
+      "websockets/websocket_handshake_challenge.h",
       "websockets/websocket_handshake_request_info.cc",
       "websockets/websocket_handshake_request_info.h",
       "websockets/websocket_handshake_response_info.cc",
@@ -609,8 +609,12 @@
 source_set("test_support") {
   testonly = true
   sources = [
+    "base/captured_net_log_entry.cc",
+    "base/captured_net_log_entry.h",
     "base/capturing_net_log.cc",
     "base/capturing_net_log.h",
+    "base/capturing_net_log_observer.cc",
+    "base/capturing_net_log_observer.h",
     "base/load_timing_info_test_util.cc",
     "base/load_timing_info_test_util.h",
     "base/mock_file_stream.cc",
@@ -1238,8 +1242,7 @@
       "websockets/websocket_extension_parser_test.cc",
       "websockets/websocket_frame_parser_test.cc",
       "websockets/websocket_frame_test.cc",
-      "websockets/websocket_handshake_handler_spdy_test.cc",
-      "websockets/websocket_handshake_handler_test.cc",
+      "websockets/websocket_handshake_challenge_test.cc",
       "websockets/websocket_handshake_stream_create_helper_test.cc",
       "websockets/websocket_inflater_test.cc",
       "websockets/websocket_stream_test.cc",
diff --git a/net/android/java/src/org/chromium/net/DefaultAndroidKeyStore.java b/net/android/java/src/org/chromium/net/DefaultAndroidKeyStore.java
index 60f910c..2a6c2f2 100644
--- a/net/android/java/src/org/chromium/net/DefaultAndroidKeyStore.java
+++ b/net/android/java/src/org/chromium/net/DefaultAndroidKeyStore.java
@@ -123,8 +123,8 @@
             signature.update(message);
             return signature.sign();
         } catch (Exception e) {
-            Log.e(TAG, "Exception while signing message with " + javaKey.getAlgorithm() +
-                        " private key: " + e);
+            Log.e(TAG, "Exception while signing message with " + javaKey.getAlgorithm()
+                    + " private key: " + e);
             return null;
         }
     }
@@ -170,8 +170,8 @@
             // This may happen if the PrivateKey was not created by the "AndroidOpenSSL"
             // provider, which should be the default. That could happen if an OEM decided
             // to implement a different default provider. Also highly unlikely.
-            Log.e(TAG, "Private key is not an OpenSSLRSAPrivateKey instance, its class name is:" +
-                       javaKey.getClass().getCanonicalName());
+            Log.e(TAG, "Private key is not an OpenSSLRSAPrivateKey instance, its class name is:"
+                    + javaKey.getClass().getCanonicalName());
             return null;
         }
 
@@ -284,8 +284,8 @@
             }
             // Sanity-check the returned engine.
             if (!engineClass.isInstance(engine)) {
-                Log.e(TAG, "Engine is not an OpenSSLEngine instance, its class name is:" +
-                        engine.getClass().getCanonicalName());
+                Log.e(TAG, "Engine is not an OpenSSLEngine instance, its class name is:"
+                        + engine.getClass().getCanonicalName());
                 return null;
             }
             return engine;
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
index 1e72da9..9db46e2 100644
--- a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
+++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
@@ -161,8 +161,8 @@
 
     public int getCurrentConnectionType() {
         // Track exactly what type of connection we have.
-        if (!mConnectivityManagerDelegate.activeNetworkExists() ||
-                !mConnectivityManagerDelegate.isConnected()) {
+        if (!mConnectivityManagerDelegate.activeNetworkExists()
+                || !mConnectivityManagerDelegate.isConnected()) {
             return NetworkChangeNotifier.CONNECTION_NONE;
         }
 
diff --git a/net/android/java/src/org/chromium/net/X509Util.java b/net/android/java/src/org/chromium/net/X509Util.java
index 3f6c70d..08ead31 100644
--- a/net/android/java/src/org/chromium/net/X509Util.java
+++ b/net/android/java/src/org/chromium/net/X509Util.java
@@ -372,8 +372,8 @@
 
             // If the subject and public key match, this is a system root.
             X509Certificate anchorX509 = (X509Certificate) anchor;
-            if (root.getSubjectX500Principal().equals(anchorX509.getSubjectX500Principal()) &&
-                    root.getPublicKey().equals(anchorX509.getPublicKey())) {
+            if (root.getSubjectX500Principal().equals(anchorX509.getSubjectX500Principal())
+                    && root.getPublicKey().equals(anchorX509.getPublicKey())) {
                 sSystemTrustAnchorCache.add(key);
                 return true;
             }
@@ -405,10 +405,10 @@
         if (ekuOids == null) return true;
 
         for (String ekuOid : ekuOids) {
-            if (ekuOid.equals(OID_TLS_SERVER_AUTH) ||
-                    ekuOid.equals(OID_ANY_EKU) ||
-                    ekuOid.equals(OID_SERVER_GATED_NETSCAPE) ||
-                    ekuOid.equals(OID_SERVER_GATED_MICROSOFT)) {
+            if (ekuOid.equals(OID_TLS_SERVER_AUTH)
+                    || ekuOid.equals(OID_ANY_EKU)
+                    || ekuOid.equals(OID_SERVER_GATED_NETSCAPE)
+                    || ekuOid.equals(OID_SERVER_GATED_MICROSOFT)) {
                 return true;
             }
         }
@@ -421,8 +421,8 @@
                                                                    String host)
             throws KeyStoreException, NoSuchAlgorithmException {
         if (certChain == null || certChain.length == 0 || certChain[0] == null) {
-            throw new IllegalArgumentException("Expected non-null and non-empty certificate " +
-                    "chain passed as |certChain|. |certChain|=" + Arrays.deepToString(certChain));
+            throw new IllegalArgumentException("Expected non-null and non-empty certificate "
+                    + "chain passed as |certChain|. |certChain|=" + Arrays.deepToString(certChain));
         }
 
 
@@ -475,8 +475,8 @@
                 } catch (CertificateException eTestManager) {
                     // Neither of the trust managers confirms the validity of the certificate chain,
                     // log the error message returned by the system trust manager.
-                    Log.i(TAG, "Failed to validate the certificate chain, error: " +
-                              eDefaultManager.getMessage());
+                    Log.i(TAG, "Failed to validate the certificate chain, error: "
+                            + eDefaultManager.getMessage());
                     return new AndroidCertVerifyResult(
                             CertVerifyStatusAndroid.NO_TRUSTED_ROOT);
                 }
diff --git a/net/base/captured_net_log_entry.cc b/net/base/captured_net_log_entry.cc
new file mode 100644
index 0000000..9c57271
--- /dev/null
+++ b/net/base/captured_net_log_entry.cc
@@ -0,0 +1,77 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/captured_net_log_entry.h"
+
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/values.h"
+
+namespace net {
+
+CapturedNetLogEntry::CapturedNetLogEntry(
+    NetLog::EventType type,
+    const base::TimeTicks& time,
+    NetLog::Source source,
+    NetLog::EventPhase phase,
+    scoped_ptr<base::DictionaryValue> params)
+    : type(type),
+      time(time),
+      source(source),
+      phase(phase),
+      params(params.Pass()) {
+  // Only entries without a NetLog should have an invalid source.
+  CHECK(source.IsValid());
+}
+
+CapturedNetLogEntry::CapturedNetLogEntry(const CapturedNetLogEntry& entry) {
+  *this = entry;
+}
+
+CapturedNetLogEntry::~CapturedNetLogEntry() {}
+
+CapturedNetLogEntry& CapturedNetLogEntry::operator=(
+    const CapturedNetLogEntry& entry) {
+  type = entry.type;
+  time = entry.time;
+  source = entry.source;
+  phase = entry.phase;
+  params.reset(entry.params ? entry.params->DeepCopy() : NULL);
+  return *this;
+}
+
+bool CapturedNetLogEntry::GetStringValue(const std::string& name,
+                                         std::string* value) const {
+  if (!params)
+    return false;
+  return params->GetString(name, value);
+}
+
+bool CapturedNetLogEntry::GetIntegerValue(const std::string& name,
+                                          int* value) const {
+  if (!params)
+    return false;
+  return params->GetInteger(name, value);
+}
+
+bool CapturedNetLogEntry::GetListValue(const std::string& name,
+                                       base::ListValue** value) const {
+  if (!params)
+    return false;
+  return params->GetList(name, value);
+}
+
+bool CapturedNetLogEntry::GetNetErrorCode(int* value) const {
+  return GetIntegerValue("net_error", value);
+}
+
+std::string CapturedNetLogEntry::GetParamsJson() const {
+  if (!params)
+    return std::string();
+  std::string json;
+  base::JSONWriter::Write(params.get(), &json);
+  return json;
+}
+
+}  // namespace net
diff --git a/net/base/captured_net_log_entry.h b/net/base/captured_net_log_entry.h
new file mode 100644
index 0000000..97245e3
--- /dev/null
+++ b/net/base/captured_net_log_entry.h
@@ -0,0 +1,69 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_CAPTURED_NET_LOG_ENTRY_H_
+#define NET_BASE_CAPTURED_NET_LOG_ENTRY_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "net/base/net_log.h"
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+namespace net {
+
+// CapturedNetLogEntry is much like NetLog::Entry, except it has its own copy of
+// all log data, so a list of entries can be gathered over the course of a test,
+// and then inspected at the end.  It is intended for testing only, and is part
+// of the net_test_support project.
+struct CapturedNetLogEntry {
+  // Ordered set of logged entries.
+  typedef std::vector<CapturedNetLogEntry> List;
+
+  CapturedNetLogEntry(NetLog::EventType type,
+                      const base::TimeTicks& time,
+                      NetLog::Source source,
+                      NetLog::EventPhase phase,
+                      scoped_ptr<base::DictionaryValue> params);
+  // Copy constructor needed to store in a std::vector because of the
+  // scoped_ptr.
+  CapturedNetLogEntry(const CapturedNetLogEntry& entry);
+
+  ~CapturedNetLogEntry();
+
+  // Equality operator needed to store in a std::vector because of the
+  // scoped_ptr.
+  CapturedNetLogEntry& operator=(const CapturedNetLogEntry& entry);
+
+  // Attempt to retrieve an value of the specified type with the given name
+  // from |params|.  Returns true on success, false on failure.  Does not
+  // modify |value| on failure.
+  bool GetStringValue(const std::string& name, std::string* value) const;
+  bool GetIntegerValue(const std::string& name, int* value) const;
+  bool GetListValue(const std::string& name, base::ListValue** value) const;
+
+  // Same as GetIntegerValue, but returns the error code associated with a
+  // log entry.
+  bool GetNetErrorCode(int* value) const;
+
+  // Returns the parameters as a JSON string, or empty string if there are no
+  // parameters.
+  std::string GetParamsJson() const;
+
+  NetLog::EventType type;
+  base::TimeTicks time;
+  NetLog::Source source;
+  NetLog::EventPhase phase;
+  scoped_ptr<base::DictionaryValue> params;
+};
+
+}  // namespace net
+
+#endif  // NET_BASE_CAPTURED_NET_LOG_ENTRY_H_
diff --git a/net/base/capturing_net_log.cc b/net/base/capturing_net_log.cc
index 3837fe6..f2e2c04 100644
--- a/net/base/capturing_net_log.cc
+++ b/net/base/capturing_net_log.cc
@@ -4,130 +4,8 @@
 
 #include "net/base/capturing_net_log.h"
 
-#include "base/json/json_writer.h"
-#include "base/logging.h"
-#include "base/values.h"
-
 namespace net {
 
-CapturingNetLog::CapturedEntry::CapturedEntry(
-    EventType type,
-    const base::TimeTicks& time,
-    Source source,
-    EventPhase phase,
-    scoped_ptr<base::DictionaryValue> params)
-    : type(type),
-      time(time),
-      source(source),
-      phase(phase),
-      params(params.Pass()) {
-}
-
-CapturingNetLog::CapturedEntry::CapturedEntry(const CapturedEntry& entry) {
-  *this = entry;
-}
-
-CapturingNetLog::CapturedEntry::~CapturedEntry() {}
-
-CapturingNetLog::CapturedEntry&
-CapturingNetLog::CapturedEntry::operator=(const CapturedEntry& entry) {
-  type = entry.type;
-  time = entry.time;
-  source = entry.source;
-  phase = entry.phase;
-  params.reset(entry.params ? entry.params->DeepCopy() : NULL);
-  return *this;
-}
-
-bool CapturingNetLog::CapturedEntry::GetStringValue(
-    const std::string& name,
-    std::string* value) const {
-  if (!params)
-    return false;
-  return params->GetString(name, value);
-}
-
-bool CapturingNetLog::CapturedEntry::GetIntegerValue(
-    const std::string& name,
-    int* value) const {
-  if (!params)
-    return false;
-  return params->GetInteger(name, value);
-}
-
-bool CapturingNetLog::CapturedEntry::GetListValue(
-    const std::string& name,
-    base::ListValue** value) const {
-  if (!params)
-    return false;
-  return params->GetList(name, value);
-}
-
-bool CapturingNetLog::CapturedEntry::GetNetErrorCode(int* value) const {
-  return GetIntegerValue("net_error", value);
-}
-
-std::string CapturingNetLog::CapturedEntry::GetParamsJson() const {
-  if (!params)
-    return std::string();
-  std::string json;
-  base::JSONWriter::Write(params.get(), &json);
-  return json;
-}
-
-CapturingNetLog::Observer::Observer() {}
-
-CapturingNetLog::Observer::~Observer() {}
-
-void CapturingNetLog::Observer::GetEntries(
-    CapturedEntryList* entry_list) const {
-  base::AutoLock lock(lock_);
-  *entry_list = captured_entries_;
-}
-
-void CapturingNetLog::Observer::GetEntriesForSource(
-    NetLog::Source source,
-    CapturedEntryList* entry_list) const {
-  base::AutoLock lock(lock_);
-  entry_list->clear();
-  for (CapturedEntryList::const_iterator entry = captured_entries_.begin();
-       entry != captured_entries_.end(); ++entry) {
-    if (entry->source.id == source.id)
-      entry_list->push_back(*entry);
-  }
-}
-
-size_t CapturingNetLog::Observer::GetSize() const {
-  base::AutoLock lock(lock_);
-  return captured_entries_.size();
-}
-
-void CapturingNetLog::Observer::Clear() {
-  base::AutoLock lock(lock_);
-  captured_entries_.clear();
-}
-
-void CapturingNetLog::Observer::OnAddEntry(const net::NetLog::Entry& entry) {
-  // Only BoundNetLogs without a NetLog should have an invalid source.
-  CHECK(entry.source().IsValid());
-
-  // Using Dictionaries instead of Values makes checking values a little
-  // simpler.
-  base::DictionaryValue* param_dict = NULL;
-  base::Value* param_value = entry.ParametersToValue();
-  if (param_value && !param_value->GetAsDictionary(&param_dict))
-    delete param_value;
-
-  // Only need to acquire the lock when accessing class variables.
-  base::AutoLock lock(lock_);
-  captured_entries_.push_back(
-      CapturedEntry(entry.type(),
-                    base::TimeTicks::Now(),
-                    entry.source(),
-                    entry.phase(),
-                    scoped_ptr<base::DictionaryValue>(param_dict)));
-}
-
 CapturingNetLog::CapturingNetLog() {
   AddThreadSafeObserver(&capturing_net_log_observer_, LOG_ALL_BUT_BYTES);
 }
diff --git a/net/base/capturing_net_log.h b/net/base/capturing_net_log.h
index 5977533..452c9a0 100644
--- a/net/base/capturing_net_log.h
+++ b/net/base/capturing_net_log.h
@@ -8,68 +8,22 @@
 #include <string>
 #include <vector>
 
-#include "base/atomicops.h"
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
+#include "net/base/captured_net_log_entry.h"
+#include "net/base/capturing_net_log_observer.h"
 #include "net/base/net_log.h"
 
-namespace base {
-class DictionaryValue;
-class ListValue;
-}
-
 namespace net {
 
-// CapturingNetLog is a NetLog which instantiates Observer that saves messages
-// to a bounded buffer.  It is intended for testing only, and is part of the
-// net_test_support project. This is provided for convinience and compatilbility
-// with the old unittests.
+// CapturingNetLog is convenience class which combines a NetLog and a
+// CapturingNetLogObserver.  It is intended for testing only, and is part of the
+// net_test_support project.
 class CapturingNetLog : public NetLog {
  public:
-  struct CapturedEntry {
-    CapturedEntry(EventType type,
-                  const base::TimeTicks& time,
-                  Source source,
-                  EventPhase phase,
-                  scoped_ptr<base::DictionaryValue> params);
-    // Copy constructor needed to store in a std::vector because of the
-    // scoped_ptr.
-    CapturedEntry(const CapturedEntry& entry);
-
-    ~CapturedEntry();
-
-    // Equality operator needed to store in a std::vector because of the
-    // scoped_ptr.
-    CapturedEntry& operator=(const CapturedEntry& entry);
-
-    // Attempt to retrieve an value of the specified type with the given name
-    // from |params|.  Returns true on success, false on failure.  Does not
-    // modify |value| on failure.
-    bool GetStringValue(const std::string& name, std::string* value) const;
-    bool GetIntegerValue(const std::string& name, int* value) const;
-    bool GetListValue(const std::string& name, base::ListValue** value) const;
-
-    // Same as GetIntegerValue, but returns the error code associated with a
-    // log entry.
-    bool GetNetErrorCode(int* value) const;
-
-    // Returns the parameters as a JSON string, or empty string if there are no
-    // parameters.
-    std::string GetParamsJson() const;
-
-    EventType type;
-    base::TimeTicks time;
-    Source source;
-    EventPhase phase;
-    scoped_ptr<base::DictionaryValue> params;
-  };
-
-  // Ordered set of entries that were logged.
-  typedef std::vector<CapturedEntry> CapturedEntryList;
+  // TODO(mmenke):  Get rid of these.
+  typedef CapturedNetLogEntry CapturedEntry;
+  typedef CapturedNetLogEntry::List CapturedEntryList;
 
   CapturingNetLog();
   ~CapturingNetLog() override;
@@ -83,39 +37,7 @@
   void Clear();
 
  private:
-  // Observer is an implementation of NetLog::ThreadSafeObserver
-  // that saves messages to a bounded buffer. It is intended for testing only,
-  // and is part of the net_test_support project.
-  class Observer : public NetLog::ThreadSafeObserver {
-   public:
-    Observer();
-    ~Observer() override;
-
-    // Returns the list of all entries in the log.
-    void GetEntries(CapturedEntryList* entry_list) const;
-
-    // Fills |entry_list| with all entries in the log from the specified Source.
-    void GetEntriesForSource(Source source,
-                             CapturedEntryList* entry_list) const;
-
-    // Returns number of entries in the log.
-    size_t GetSize() const;
-
-    void Clear();
-
-   private:
-    // ThreadSafeObserver implementation:
-    void OnAddEntry(const Entry& entry) override;
-
-    // Needs to be "mutable" so can use it in GetEntries().
-    mutable base::Lock lock_;
-
-    CapturedEntryList captured_entries_;
-
-    DISALLOW_COPY_AND_ASSIGN(Observer);
-  };
-
-  Observer capturing_net_log_observer_;
+  CapturingNetLogObserver capturing_net_log_observer_;
 
   DISALLOW_COPY_AND_ASSIGN(CapturingNetLog);
 };
@@ -123,7 +45,7 @@
 // Helper class that exposes a similar API as BoundNetLog, but uses a
 // CapturingNetLog rather than the more generic NetLog.
 //
-// CapturingBoundNetLog can easily be converted to a BoundNetLog using the
+// A CapturingBoundNetLog can easily be converted to a BoundNetLog using the
 // bound() method.
 class CapturingBoundNetLog {
  public:
diff --git a/net/base/capturing_net_log_observer.cc b/net/base/capturing_net_log_observer.cc
new file mode 100644
index 0000000..da99852
--- /dev/null
+++ b/net/base/capturing_net_log_observer.cc
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/capturing_net_log_observer.h"
+
+#include "base/values.h"
+
+namespace net {
+
+CapturingNetLogObserver::CapturingNetLogObserver() {}
+
+CapturingNetLogObserver::~CapturingNetLogObserver() {}
+
+void CapturingNetLogObserver::GetEntries(
+    CapturedNetLogEntry::List* entry_list) const {
+  base::AutoLock lock(lock_);
+  *entry_list = captured_entries_;
+}
+
+void CapturingNetLogObserver::GetEntriesForSource(
+    NetLog::Source source,
+    CapturedNetLogEntry::List* entry_list) const {
+  base::AutoLock lock(lock_);
+  entry_list->clear();
+  for (CapturedNetLogEntry::List::const_iterator entry =
+           captured_entries_.begin();
+       entry != captured_entries_.end(); ++entry) {
+    if (entry->source.id == source.id)
+      entry_list->push_back(*entry);
+  }
+}
+
+size_t CapturingNetLogObserver::GetSize() const {
+  base::AutoLock lock(lock_);
+  return captured_entries_.size();
+}
+
+void CapturingNetLogObserver::Clear() {
+  base::AutoLock lock(lock_);
+  captured_entries_.clear();
+}
+
+void CapturingNetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) {
+  // Using Dictionaries instead of Values makes checking values a little
+  // simpler.
+  base::DictionaryValue* param_dict = nullptr;
+  base::Value* param_value = entry.ParametersToValue();
+  if (param_value && !param_value->GetAsDictionary(&param_dict))
+    delete param_value;
+
+  // Only need to acquire the lock when accessing class variables.
+  base::AutoLock lock(lock_);
+  captured_entries_.push_back(
+      CapturedNetLogEntry(entry.type(),
+                          base::TimeTicks::Now(),
+                          entry.source(),
+                          entry.phase(),
+                          scoped_ptr<base::DictionaryValue>(param_dict)));
+}
+
+}  // namespace net
diff --git a/net/base/capturing_net_log_observer.h b/net/base/capturing_net_log_observer.h
new file mode 100644
index 0000000..267352a
--- /dev/null
+++ b/net/base/capturing_net_log_observer.h
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_CAPTURING_NET_LOG_OBSERVER_H_
+#define NET_BASE_CAPTURING_NET_LOG_OBSERVER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/synchronization/lock.h"
+#include "net/base/captured_net_log_entry.h"
+#include "net/base/net_log.h"
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+namespace net {
+
+// CapturingNetLogObserver is an implementation of NetLog::ThreadSafeObserver
+// that saves messages to a bounded buffer. It is intended for testing only,
+// and is part of the net_test_support project.
+class CapturingNetLogObserver : public NetLog::ThreadSafeObserver {
+ public:
+  CapturingNetLogObserver();
+  ~CapturingNetLogObserver() override;
+
+  // Returns the list of all entries in the log.
+  void GetEntries(CapturedNetLogEntry::List* entry_list) const;
+
+  // Fills |entry_list| with all entries in the log from the specified Source.
+  void GetEntriesForSource(NetLog::Source source,
+                           CapturedNetLogEntry::List* entry_list) const;
+
+  // Returns number of entries in the log.
+  size_t GetSize() const;
+
+  void Clear();
+
+ private:
+  // ThreadSafeObserver implementation:
+  void OnAddEntry(const NetLog::Entry& entry) override;
+
+  // Needs to be "mutable" so can use it in GetEntries().
+  mutable base::Lock lock_;
+
+  CapturedNetLogEntry::List captured_entries_;
+
+  DISALLOW_COPY_AND_ASSIGN(CapturingNetLogObserver);
+};
+
+}  // namespace net
+
+#endif  // NET_BASE_CAPTURING_NET_LOG_OBSERVER_H_
diff --git a/net/base/file_stream_context_win.cc b/net/base/file_stream_context_win.cc
index 3b942d3..369dfc1 100644
--- a/net/base/file_stream_context_win.cc
+++ b/net/base/file_stream_context_win.cc
@@ -68,14 +68,13 @@
   if (!ReadFile(file_.GetPlatformFile(), buf->data(), buf_len,
                 &bytes_read, &io_context_.overlapped)) {
     IOResult error = IOResult::FromOSError(GetLastError());
-    if (error.os_error == ERROR_IO_PENDING) {
-      IOCompletionIsPending(callback, buf);
-    } else if (error.os_error == ERROR_HANDLE_EOF) {
+    if (error.os_error == ERROR_HANDLE_EOF)
       return 0;  // Report EOF by returning 0 bytes read.
-    } else {
+    if (error.os_error == ERROR_IO_PENDING)
+      IOCompletionIsPending(callback, buf);
+    else
       LOG(WARNING) << "ReadFile failed: " << error.os_error;
-    }
-    return error.result;
+    return static_cast<int>(error.result);
   }
 
   IOCompletionIsPending(callback, buf);
@@ -89,12 +88,11 @@
   if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len,
                  &bytes_written, &io_context_.overlapped)) {
     IOResult error = IOResult::FromOSError(GetLastError());
-    if (error.os_error == ERROR_IO_PENDING) {
+    if (error.os_error == ERROR_IO_PENDING)
       IOCompletionIsPending(callback, buf);
-    } else {
+    else
       LOG(WARNING) << "WriteFile failed: " << error.os_error;
-    }
-    return error.result;
+    return static_cast<int>(error.result);
   }
 
   IOCompletionIsPending(callback, buf);
@@ -149,7 +147,7 @@
     result = 0;
   } else if (error) {
     IOResult error_result = IOResult::FromOSError(error);
-    result = error_result.result;
+    result = static_cast<int>(error_result.result);
   } else {
     result = bytes_read;
     IncrementOffset(&io_context_.overlapped, bytes_read);
diff --git a/net/base/host_mapping_rules.cc b/net/base/host_mapping_rules.cc
index f91f3fd..01b98b7 100644
--- a/net/base/host_mapping_rules.cc
+++ b/net/base/host_mapping_rules.cc
@@ -58,7 +58,7 @@
 
     host_port->set_host(rule.replacement_hostname);
     if (rule.replacement_port != -1)
-      host_port->set_port(rule.replacement_port);
+      host_port->set_port(static_cast<uint16>(rule.replacement_port));
     return true;
   }
 
diff --git a/net/base/host_port_pair.cc b/net/base/host_port_pair.cc
index 18cf9f5..1570bbb 100644
--- a/net/base/host_port_pair.cc
+++ b/net/base/host_port_pair.cc
@@ -21,7 +21,8 @@
 
 // static
 HostPortPair HostPortPair::FromURL(const GURL& url) {
-  return HostPortPair(url.HostNoBrackets(), url.EffectiveIntPort());
+  return HostPortPair(url.HostNoBrackets(),
+                      static_cast<uint16>(url.EffectiveIntPort()));
 }
 
 // static
@@ -41,7 +42,7 @@
     return HostPortPair();
   HostPortPair host_port_pair;
   host_port_pair.set_host(key_port[0]);
-  host_port_pair.set_port(port);
+  host_port_pair.set_port(static_cast<uint16>(port));
   return host_port_pair;
 }
 
diff --git a/net/base/ip_endpoint.cc b/net/base/ip_endpoint.cc
index a0d378e..65c5d50 100644
--- a/net/base/ip_endpoint.cc
+++ b/net/base/ip_endpoint.cc
@@ -25,7 +25,7 @@
 
 IPEndPoint::~IPEndPoint() {}
 
-IPEndPoint::IPEndPoint(const IPAddressNumber& address, int port)
+IPEndPoint::IPEndPoint(const IPAddressNumber& address, uint16 port)
     : address_(address),
       port_(port) {}
 
diff --git a/net/base/ip_endpoint.h b/net/base/ip_endpoint.h
index 5e5d9c1..c2639b1 100644
--- a/net/base/ip_endpoint.h
+++ b/net/base/ip_endpoint.h
@@ -24,11 +24,11 @@
  public:
   IPEndPoint();
   ~IPEndPoint();
-  IPEndPoint(const IPAddressNumber& address, int port);
+  IPEndPoint(const IPAddressNumber& address, uint16 port);
   IPEndPoint(const IPEndPoint& endpoint);
 
   const IPAddressNumber& address() const { return address_; }
-  int port() const { return port_; }
+  uint16 port() const { return port_; }
 
   // Returns AddressFamily of the address.
   AddressFamily GetFamily() const;
@@ -66,7 +66,7 @@
 
  private:
   IPAddressNumber address_;
-  int port_;
+  uint16 port_;
 };
 
 }  // namespace net
diff --git a/net/base/ip_endpoint_unittest.cc b/net/base/ip_endpoint_unittest.cc
index 5d70911..17b325c 100644
--- a/net/base/ip_endpoint_unittest.cc
+++ b/net/base/ip_endpoint_unittest.cc
@@ -29,7 +29,7 @@
   { "::1", "[::1]", true },
   { "2001:db8:0::42", "[2001:db8::42]", true },
 };
-int test_count = arraysize(tests);
+uint16 test_count = static_cast<uint16>(arraysize(tests));
 
 class IPEndPointTest : public PlatformTest {
  public:
@@ -46,7 +46,7 @@
   IPEndPoint endpoint;
   EXPECT_EQ(0, endpoint.port());
 
-  for (int index = 0; index < test_count; ++index) {
+  for (uint16 index = 0; index < test_count; ++index) {
     IPEndPoint endpoint(tests[index].ip_address, 80);
     EXPECT_EQ(80, endpoint.port());
     EXPECT_EQ(tests[index].ip_address, endpoint.address());
@@ -54,7 +54,7 @@
 }
 
 TEST_F(IPEndPointTest, Assignment) {
-  for (int index = 0; index < test_count; ++index) {
+  for (uint16 index = 0; index < test_count; ++index) {
     IPEndPoint src(tests[index].ip_address, index);
     IPEndPoint dest = src;
 
@@ -64,7 +64,7 @@
 }
 
 TEST_F(IPEndPointTest, Copy) {
-  for (int index = 0; index < test_count; ++index) {
+  for (uint16 index = 0; index < test_count; ++index) {
     IPEndPoint src(tests[index].ip_address, index);
     IPEndPoint dest(src);
 
@@ -74,7 +74,7 @@
 }
 
 TEST_F(IPEndPointTest, ToFromSockAddr) {
-  for (int index = 0; index < test_count; ++index) {
+  for (uint16 index = 0; index < test_count; ++index) {
     IPEndPoint ip_endpoint(tests[index].ip_address, index);
 
     // Convert to a sockaddr.
@@ -97,7 +97,7 @@
 }
 
 TEST_F(IPEndPointTest, ToSockAddrBufTooSmall) {
-  for (int index = 0; index < test_count; ++index) {
+  for (uint16 index = 0; index < test_count; ++index) {
     IPEndPoint ip_endpoint(tests[index].ip_address, index);
 
     SockaddrStorage storage;
@@ -116,7 +116,7 @@
 }
 
 TEST_F(IPEndPointTest, Equality) {
-  for (int index = 0; index < test_count; ++index) {
+  for (uint16 index = 0; index < test_count; ++index) {
     IPEndPoint src(tests[index].ip_address, index);
     IPEndPoint dest(src);
     EXPECT_TRUE(src == dest);
@@ -159,8 +159,8 @@
   IPEndPoint endpoint;
   EXPECT_EQ(0, endpoint.port());
 
-  for (int index = 0; index < test_count; ++index) {
-    int port = 100 + index;
+  for (uint16 index = 0; index < test_count; ++index) {
+    uint16 port = 100 + index;
     IPEndPoint endpoint(tests[index].ip_address, port);
     const std::string result = endpoint.ToString();
     EXPECT_EQ(tests[index].host_normalized + ":" + base::IntToString(port),
diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h
index 494b762..d6e6187 100644
--- a/net/base/net_log_event_type_list.h
+++ b/net/base/net_log_event_type_list.h
@@ -1325,6 +1325,10 @@
 EVENT_TYPE(SPDY_STREAM)
 
 // A stream is attached to a pushed stream.
+//   {
+//     "stream_id":  <The stream id>,
+//     "url":        <The url of the pushed resource>,
+//   }
 EVENT_TYPE(SPDY_STREAM_ADOPTED_PUSH_STREAM)
 
 // A stream is unstalled by flow control.
diff --git a/net/base/net_log_util.cc b/net/base/net_log_util.cc
index a15e899..3b437aa 100644
--- a/net/base/net_log_util.cc
+++ b/net/base/net_log_util.cc
@@ -4,12 +4,17 @@
 
 #include "net/base/net_log_util.h"
 
+#include <algorithm>
 #include <string>
+#include <vector>
 
+#include "base/bind.h"
+#include "base/logging.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "net/base/address_family.h"
 #include "net/base/load_states.h"
@@ -28,6 +33,7 @@
 #include "net/proxy/proxy_service.h"
 #include "net/quic/quic_protocol.h"
 #include "net/quic/quic_utils.h"
+#include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 
 namespace net {
@@ -101,6 +107,25 @@
   return http_cache->GetCurrentBackend();
 }
 
+// Returns true if |request1| was created before |request2|.
+bool RequestCreatedBefore(const net::URLRequest* request1,
+                          const net::URLRequest* request2) {
+  if (request1->creation_time() < request2->creation_time())
+    return true;
+  if (request1->creation_time() > request2->creation_time())
+    return false;
+  // If requests were created at the same time, sort by ID.  Mostly matters for
+  // testing purposes.
+  return request1->identifier() < request2->identifier();
+}
+
+// Returns a Value representing the state of a pre-existing URLRequest when
+// net-internals was opened.
+base::Value* GetRequestStateAsValue(const net::URLRequest* request,
+                                    net::NetLog::LogLevel log_level) {
+  return request->GetStateAsValue();
+}
+
 }  // namespace
 
 scoped_ptr<base::DictionaryValue> GetNetConstants() {
@@ -298,6 +323,9 @@
 
 NET_EXPORT scoped_ptr<base::DictionaryValue> GetNetInfo(
     URLRequestContext* context, int info_sources) {
+  // May only be called on the context's thread.
+  DCHECK(context->CalledOnValidThread());
+
   scoped_ptr<base::DictionaryValue> net_info_dict(new base::DictionaryValue());
 
   // TODO(mmenke):  The code for most of these sources should probably be moved
@@ -489,4 +517,41 @@
   return net_info_dict.Pass();
 }
 
+NET_EXPORT void CreateNetLogEntriesForActiveObjects(
+    const std::set<URLRequestContext*>& contexts,
+    NetLog::ThreadSafeObserver* observer) {
+  // Not safe to call this when the observer is watching a NetLog.
+  DCHECK(!observer->net_log());
+
+  // Put together the list of all requests.
+  std::vector<const URLRequest*> requests;
+  for (const auto& context : contexts) {
+    // May only be called on the context's thread.
+    DCHECK(context->CalledOnValidThread());
+    // Contexts should all be using the same NetLog.
+    DCHECK_EQ((*contexts.begin())->net_log(), context->net_log());
+    for (const auto& request : *context->url_requests()) {
+      requests.push_back(request);
+    }
+  }
+
+  // Sort by creation time.
+  std::sort(requests.begin(), requests.end(), RequestCreatedBefore);
+
+  // Create fake events.
+  ScopedVector<NetLog::Entry> entries;
+  for (const auto& request : requests) {
+    net::NetLog::ParametersCallback callback =
+        base::Bind(&GetRequestStateAsValue, base::Unretained(request));
+
+    net::NetLog::EntryData entry_data(net::NetLog::TYPE_REQUEST_ALIVE,
+                                      request->net_log().source(),
+                                      net::NetLog::PHASE_BEGIN,
+                                      request->creation_time(),
+                                      &callback);
+    NetLog::Entry entry(&entry_data, request->net_log().GetLogLevel());
+    observer->OnAddEntry(entry);
+  }
+}
+
 }  // namespace net
diff --git a/net/base/net_log_util.h b/net/base/net_log_util.h
index d9627da..d6d6857 100644
--- a/net/base/net_log_util.h
+++ b/net/base/net_log_util.h
@@ -5,8 +5,11 @@
 #ifndef NET_BASE_NET_LOG_UTIL_H_
 #define NET_BASE_NET_LOG_UTIL_H_
 
+#include <set>
+
 #include "base/memory/scoped_ptr.h"
 #include "net/base/net_export.h"
+#include "net/base/net_log.h"
 
 namespace base {
 class DictionaryValue;
@@ -28,16 +31,38 @@
 
 // Utility methods for creating NetLog dumps.
 
-// Create a dictionary containing legend for net/ constants.
+// Create a dictionary containing a legend for net/ constants.
 NET_EXPORT scoped_ptr<base::DictionaryValue> GetNetConstants();
 
 // Retrieves a dictionary containing information about the current state of
 // |context|.  |info_sources| is a set of NetInfoSources OR'd together,
 // indicating just what information is being requested.  Each NetInfoSource adds
 // one top-level entry to the returned dictionary.
+//
+// May only be called on |context|'s thread.
 NET_EXPORT scoped_ptr<base::DictionaryValue> GetNetInfo(
     URLRequestContext* context, int info_sources);
 
+// Takes in a set of contexts and a NetLog::Observer, and passes in
+// NetLog::Entries to the observer for certain NetLog::Sources with pending
+// events.  This allows requests that were ongoing when logging was started to
+// have an initial event that has some information.  This is particularly useful
+// for hung requests.  Note that these calls are not protected by the NetLog's
+// lock, so this should generally be invoked before the observer starts watching
+// the NetLog.
+//
+// All members of |contexts| must be using the same NetLog, and live on the
+// current thread.
+//
+// Currently only creates events for URLRequests.
+//
+// The reason for not returning a list of NetLog::Entries is that entries don't
+// own most of their data, so it's simplest just to pass them in to the observer
+// directly while their data is on the stack.
+NET_EXPORT void CreateNetLogEntriesForActiveObjects(
+    const std::set<URLRequestContext*>& contexts,
+    NetLog::ThreadSafeObserver* observer);
+
 }  // namespace net
 
 #endif  // NET_BASE_NET_LOG_UTIL_H_
diff --git a/net/base/net_log_util_unittest.cc b/net/base/net_log_util_unittest.cc
index e5cc3a3..e052980 100644
--- a/net/base/net_log_util_unittest.cc
+++ b/net/base/net_log_util_unittest.cc
@@ -4,12 +4,17 @@
 
 #include "net/base/net_log_util.h"
 
+#include <set>
+
+#include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/values.h"
+#include "net/base/capturing_net_log_observer.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
 #include "net/http/http_cache.h"
 #include "net/http/http_transaction.h"
+#include "net/test/spawned_test_server/spawned_test_server.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -49,6 +54,65 @@
   EXPECT_EQ(net_info_without_cache->size(), net_info_with_cache->size());
 }
 
+// Make sure CreateNetLogEntriesForActiveObjects works for requests from a
+// single URLRequestContext.
+TEST(NetLogUtil, CreateNetLogEntriesForActiveObjectsOneContext) {
+  // Using same context for each iteration makes sure deleted requests don't
+  // appear in the list, or result in crashes.
+  TestURLRequestContext context(true);
+  NetLog net_log;
+  context.set_net_log(&net_log);
+  context.Init();
+  TestDelegate delegate;
+  for (size_t num_requests = 0; num_requests < 5; ++num_requests) {
+    ScopedVector<URLRequest> requests;
+    for (size_t i = 0; i < num_requests; ++i) {
+      requests.push_back(context.CreateRequest(
+          GURL("about:life"), DEFAULT_PRIORITY, &delegate, nullptr).release());
+    }
+    std::set<URLRequestContext*> contexts;
+    contexts.insert(&context);
+    CapturingNetLogObserver capturing_observer;
+    CreateNetLogEntriesForActiveObjects(contexts, &capturing_observer);
+    CapturedNetLogEntry::List entry_list;
+    capturing_observer.GetEntries(&entry_list);
+    ASSERT_EQ(num_requests, entry_list.size());
+
+    for (size_t i = 0; i < num_requests; ++i) {
+      EXPECT_EQ(entry_list[i].source.id, requests[i]->net_log().source().id);
+    }
+  }
+}
+
+// Make sure CreateNetLogEntriesForActiveObjects works with multiple
+// URLRequestContexts.
+TEST(NetLogUtil, CreateNetLogEntriesForActiveObjectsMultipleContexts) {
+  TestDelegate delegate;
+  for (size_t num_requests = 0; num_requests < 5; ++num_requests) {
+    ScopedVector<TestURLRequestContext> contexts;
+    ScopedVector<URLRequest> requests;
+    NetLog net_log;
+    std::set<URLRequestContext*> context_set;
+    for (size_t i = 0; i < num_requests; ++i) {
+      contexts.push_back(new TestURLRequestContext(true));
+      contexts[i]->set_net_log(&net_log);
+      contexts[i]->Init();
+      context_set.insert(contexts[i]);
+      requests.push_back(contexts[i]->CreateRequest(
+          GURL("about:hats"), DEFAULT_PRIORITY, &delegate, nullptr).release());
+    }
+    CapturingNetLogObserver capturing_observer;
+    CreateNetLogEntriesForActiveObjects(context_set, &capturing_observer);
+    CapturedNetLogEntry::List entry_list;
+    capturing_observer.GetEntries(&entry_list);
+    ASSERT_EQ(num_requests, entry_list.size());
+
+    for (size_t i = 0; i < num_requests; ++i) {
+      EXPECT_EQ(entry_list[i].source.id, requests[i]->net_log().source().id);
+    }
+  }
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/net/base/net_util.cc b/net/base/net_util.cc
index 9dcf9df..3b49dff 100644
--- a/net/base/net_util.cc
+++ b/net/base/net_util.cc
@@ -306,7 +306,7 @@
       return false;
     }
   }
-  return true;
+  return IsPortValid(port);
 }
 
 bool IsPortAllowedByFtp(int port) {
@@ -573,7 +573,7 @@
     *address = reinterpret_cast<const uint8*>(&addr->btAddr);
     *address_len = kBluetoothAddressSize;
     if (port)
-      *port = addr->port;
+      *port = static_cast<uint16>(addr->port);
     return true;
   }
 #endif
@@ -1015,8 +1015,7 @@
 }
 
 NetworkInterface::NetworkInterface()
-    : type(NetworkChangeNotifier::CONNECTION_UNKNOWN),
-      network_prefix(0) {
+    : type(NetworkChangeNotifier::CONNECTION_UNKNOWN), prefix_length(0) {
 }
 
 NetworkInterface::NetworkInterface(const std::string& name,
@@ -1024,14 +1023,14 @@
                                    uint32 interface_index,
                                    NetworkChangeNotifier::ConnectionType type,
                                    const IPAddressNumber& address,
-                                   uint32 network_prefix,
+                                   uint32 prefix_length,
                                    int ip_address_attributes)
     : name(name),
       friendly_name(friendly_name),
       interface_index(interface_index),
       type(type),
       address(address),
-      network_prefix(network_prefix),
+      prefix_length(prefix_length),
       ip_address_attributes(ip_address_attributes) {
 }
 
diff --git a/net/base/net_util.h b/net/base/net_util.h
index 44b913a..9e9dbad 100644
--- a/net/base/net_util.h
+++ b/net/base/net_util.h
@@ -468,7 +468,7 @@
                    uint32 interface_index,
                    NetworkChangeNotifier::ConnectionType type,
                    const IPAddressNumber& address,
-                   uint32 network_prefix,
+                   uint32 prefix_length,
                    int ip_address_attributes);
   ~NetworkInterface();
 
@@ -477,7 +477,7 @@
   uint32 interface_index;  // Always 0 on Android.
   NetworkChangeNotifier::ConnectionType type;
   IPAddressNumber address;
-  uint32 network_prefix;
+  uint32 prefix_length;
   int ip_address_attributes;  // Combination of |IPAddressAttributes|.
 };
 
@@ -487,9 +487,6 @@
 enum HostAddressSelectionPolicy {
   INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES           = 0x0,
   EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES           = 0x1,
-  // Include temp address only when interface has both permanent and
-  // temp addresses.
-  INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE      = 0x2,
 };
 
 // Returns list of network interfaces except loopback interface. If an
diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc
index a25903a..cb9ec1f 100644
--- a/net/base/net_util_unittest.cc
+++ b/net/base/net_util_unittest.cc
@@ -36,21 +36,22 @@
 #include <iphlpapi.h>
 #include <objbase.h>
 #include "base/win/windows_version.h"
-#include "net/base/net_util_win.h"
 #endif  // OS_WIN
 
 #if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_WIN)
 #include "net/base/address_tracker_linux.h"
 #endif  // !OS_MACOSX && !OS_NACL && !OS_WIN
 
-#if !defined(OS_WIN)
+#if defined(OS_WIN)
+#include "net/base/net_util_win.h"
+#else  // OS_WIN
 #include "net/base/net_util_posix.h"
 #if defined(OS_MACOSX)
 #include "net/base/net_util_mac.h"
 #else  // OS_MACOSX
 #include "net/base/net_util_linux.h"
-#endif
-#endif  // !OS_WIN
+#endif  // OS_MACOSX
+#endif  // OS_WIN
 
 using base::ASCIIToUTF16;
 using base::WideToUTF16;
@@ -830,8 +831,8 @@
       }
     }
     EXPECT_FALSE(all_zeroes);
-    EXPECT_GT(it->network_prefix, 1u);
-    EXPECT_LE(it->network_prefix, it->address.size() * 8);
+    EXPECT_GT(it->prefix_length, 1u);
+    EXPECT_LE(it->prefix_length, it->address.size() * 8);
 
 #if defined(OS_WIN)
     // On Windows |name| is NET_LUID.
@@ -877,16 +878,32 @@
 }
 
 static const char ifname_em1[] = "em1";
+#if defined(OS_WIN)
+static const char ifname_vm[] = "VMnet";
+#else
 static const char ifname_vm[] = "vmnet";
+#endif  // OS_WIN
 
 static const unsigned char kIPv6LocalAddr[] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+
+// The following 3 addresses need to be changed together. IPv6Addr is the IPv6
+// address. IPv6Netmask is the mask address with as many leading bits set to 1
+// as the prefix length. IPv6AddrPrefix needs to match IPv6Addr with the same
+// number of bits as the prefix length.
 static const unsigned char kIPv6Addr[] =
   {0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
    0xfe, 0xe5, 0x00, 0xc3};
+#if defined(OS_WIN)
+static const unsigned char kIPv6AddrPrefix[] =
+  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#endif  // OS_WIN
+#if defined(OS_MACOSX)
 static const unsigned char kIPv6Netmask[] =
   {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00};
+#endif  // OS_MACOSX
 
 #if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_NACL)
 
@@ -908,8 +925,6 @@
   IPAddressNumber ipv6_local_address(
       kIPv6LocalAddr, kIPv6LocalAddr + arraysize(kIPv6LocalAddr));
   IPAddressNumber ipv6_address(kIPv6Addr, kIPv6Addr + arraysize(kIPv6Addr));
-  IPAddressNumber ipv6_netmask(kIPv6Netmask,
-                               kIPv6Netmask + arraysize(kIPv6Netmask));
 
   NetworkInterfaceList results;
   ::base::hash_set<int> online_links;
@@ -960,7 +975,7 @@
                                         GetInterfaceNameVM));
   EXPECT_EQ(results.size(), 1ul);
   EXPECT_EQ(results[0].name, ifname_vm);
-  EXPECT_EQ(results[0].network_prefix, 1ul);
+  EXPECT_EQ(results[0].prefix_length, 1ul);
   EXPECT_EQ(results[0].address, ipv6_address);
   results.clear();
 
@@ -1002,7 +1017,7 @@
                                         GetInterfaceName));
   EXPECT_EQ(results.size(), 1ul);
   EXPECT_EQ(results[0].name, ifname_em1);
-  EXPECT_EQ(results[0].network_prefix, 1ul);
+  EXPECT_EQ(results[0].prefix_length, 1ul);
   EXPECT_EQ(results[0].address, ipv6_address);
   EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_TEMPORARY);
   results.clear();
@@ -1020,7 +1035,7 @@
                                         GetInterfaceName));
   EXPECT_EQ(results.size(), 1ul);
   EXPECT_EQ(results[0].name, ifname_em1);
-  EXPECT_EQ(results[0].network_prefix, 1ul);
+  EXPECT_EQ(results[0].prefix_length, 1ul);
   EXPECT_EQ(results[0].address, ipv6_address);
   EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_DEPRECATED);
   results.clear();
@@ -1064,7 +1079,7 @@
       &ip_attributes_getter));
   EXPECT_EQ(results.size(), 1ul);
   EXPECT_EQ(results[0].name, ifname_vm);
-  EXPECT_EQ(results[0].network_prefix, 1ul);
+  EXPECT_EQ(results[0].prefix_length, 1ul);
   EXPECT_EQ(results[0].address, ipv6_address);
   results.clear();
 
@@ -1098,7 +1113,7 @@
       &ip_attributes_getter));
   EXPECT_EQ(results.size(), 1ul);
   EXPECT_EQ(results[0].name, ifname_em1);
-  EXPECT_EQ(results[0].network_prefix, 1ul);
+  EXPECT_EQ(results[0].prefix_length, 1ul);
   EXPECT_EQ(results[0].address, ipv6_address);
   EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_TEMPORARY);
   results.clear();
@@ -1113,12 +1128,181 @@
       &ip_attributes_getter));
   EXPECT_EQ(results.size(), 1ul);
   EXPECT_EQ(results[0].name, ifname_em1);
-  EXPECT_EQ(results[0].network_prefix, 1ul);
+  EXPECT_EQ(results[0].prefix_length, 1ul);
   EXPECT_EQ(results[0].address, ipv6_address);
   EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_DEPRECATED);
   results.clear();
 #endif  // !OS_IOS
 }
+#elif defined(OS_WIN)  // !OS_MACOSX && !OS_WIN && !OS_NACL
+
+// Helper function to create a valid IP_ADAPTER_ADDRESSES with reasonable
+// default value. The output is the |adapter_address|. All the rests are input
+// to fill the |adapter_address|. |sock_addrs| are temporary storage used by
+// |adapter_address| once the function is returned.
+bool FillAdapterAddress(IP_ADAPTER_ADDRESSES* adapter_address,
+                        const char* ifname,
+                        const IPAddressNumber& ip_address,
+                        const IPAddressNumber& ip_netmask,
+                        sockaddr_storage sock_addrs[2]) {
+  adapter_address->AdapterName = const_cast<char*>(ifname);
+  adapter_address->FriendlyName = const_cast<PWCHAR>(L"interface");
+  adapter_address->IfType = IF_TYPE_ETHERNET_CSMACD;
+  adapter_address->OperStatus = IfOperStatusUp;
+  adapter_address->FirstUnicastAddress->DadState = IpDadStatePreferred;
+  adapter_address->FirstUnicastAddress->PrefixOrigin = IpPrefixOriginOther;
+  adapter_address->FirstUnicastAddress->SuffixOrigin = IpSuffixOriginOther;
+  adapter_address->FirstUnicastAddress->PreferredLifetime = 100;
+  adapter_address->FirstUnicastAddress->ValidLifetime = 1000;
+
+  socklen_t sock_len = sizeof(sockaddr_storage);
+
+  // Convert to sockaddr for next check.
+  if (!IPEndPoint(ip_address, 0)
+           .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[0]),
+                       &sock_len)) {
+    return false;
+  }
+  adapter_address->FirstUnicastAddress->Address.lpSockaddr =
+      reinterpret_cast<sockaddr*>(&sock_addrs[0]);
+  adapter_address->FirstUnicastAddress->Address.iSockaddrLength = sock_len;
+  adapter_address->FirstUnicastAddress->OnLinkPrefixLength = 1;
+
+  sock_len = sizeof(sockaddr_storage);
+  if (!IPEndPoint(ip_netmask, 0)
+           .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[1]),
+                       &sock_len)) {
+    return false;
+  }
+  adapter_address->FirstPrefix->Address.lpSockaddr =
+      reinterpret_cast<sockaddr*>(&sock_addrs[1]);
+  adapter_address->FirstPrefix->Address.iSockaddrLength = sock_len;
+  adapter_address->FirstPrefix->PrefixLength = 1;
+
+  DCHECK_EQ(sock_addrs[0].ss_family, sock_addrs[1].ss_family);
+  if (sock_addrs[0].ss_family == AF_INET6) {
+    adapter_address->Ipv6IfIndex = 0;
+  } else {
+    DCHECK_EQ(sock_addrs[0].ss_family, AF_INET);
+    adapter_address->IfIndex = 0;
+  }
+
+  return true;
+}
+
+TEST(NetUtilTest, GetNetworkListTrimming) {
+  IPAddressNumber ipv6_local_address(
+      kIPv6LocalAddr, kIPv6LocalAddr + arraysize(kIPv6LocalAddr));
+  IPAddressNumber ipv6_address(kIPv6Addr, kIPv6Addr + arraysize(kIPv6Addr));
+  IPAddressNumber ipv6_prefix(kIPv6AddrPrefix,
+                              kIPv6AddrPrefix + arraysize(kIPv6AddrPrefix));
+
+  NetworkInterfaceList results;
+  sockaddr_storage addresses[2];
+  IP_ADAPTER_ADDRESSES adapter_address = {0};
+  IP_ADAPTER_UNICAST_ADDRESS address = {0};
+  IP_ADAPTER_PREFIX adapter_prefix = {0};
+  adapter_address.FirstUnicastAddress = &address;
+  adapter_address.FirstPrefix = &adapter_prefix;
+
+  // Address of offline links should be ignored.
+  ASSERT_TRUE(FillAdapterAddress(
+      &adapter_address /* adapter_address */, ifname_em1 /* ifname */,
+      ipv6_address /* ip_address */, ipv6_prefix /* ip_netmask */,
+      addresses /* sock_addrs */));
+  adapter_address.OperStatus = IfOperStatusDown;
+
+  EXPECT_TRUE(net::internal::GetNetworkListImpl(
+      &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address));
+
+  EXPECT_EQ(results.size(), 0ul);
+
+  // Address on loopback interface should be trimmed out.
+  ASSERT_TRUE(FillAdapterAddress(
+      &adapter_address /* adapter_address */, ifname_em1 /* ifname */,
+      ipv6_local_address /* ip_address */, ipv6_prefix /* ip_netmask */,
+      addresses /* sock_addrs */));
+  adapter_address.IfType = IF_TYPE_SOFTWARE_LOOPBACK;
+
+  EXPECT_TRUE(net::internal::GetNetworkListImpl(
+      &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address));
+  EXPECT_EQ(results.size(), 0ul);
+
+  // vmware address should return by default.
+  ASSERT_TRUE(FillAdapterAddress(
+      &adapter_address /* adapter_address */, ifname_vm /* ifname */,
+      ipv6_address /* ip_address */, ipv6_prefix /* ip_netmask */,
+      addresses /* sock_addrs */));
+  EXPECT_TRUE(net::internal::GetNetworkListImpl(
+      &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address));
+  EXPECT_EQ(results.size(), 1ul);
+  EXPECT_EQ(results[0].name, ifname_vm);
+  EXPECT_EQ(results[0].prefix_length, 1ul);
+  EXPECT_EQ(results[0].address, ipv6_address);
+  EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_NONE);
+  results.clear();
+
+  // vmware address should be trimmed out if policy specified so.
+  ASSERT_TRUE(FillAdapterAddress(
+      &adapter_address /* adapter_address */, ifname_vm /* ifname */,
+      ipv6_address /* ip_address */, ipv6_prefix /* ip_netmask */,
+      addresses /* sock_addrs */));
+  EXPECT_TRUE(net::internal::GetNetworkListImpl(
+      &results, EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address));
+  EXPECT_EQ(results.size(), 0ul);
+  results.clear();
+
+  // Addresses with incompleted DAD should be ignored.
+  ASSERT_TRUE(FillAdapterAddress(
+      &adapter_address /* adapter_address */, ifname_em1 /* ifname */,
+      ipv6_address /* ip_address */, ipv6_prefix /* ip_netmask */,
+      addresses /* sock_addrs */));
+  adapter_address.FirstUnicastAddress->DadState = IpDadStateTentative;
+
+  EXPECT_TRUE(net::internal::GetNetworkListImpl(
+      &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address));
+  EXPECT_EQ(results.size(), 0ul);
+  results.clear();
+
+  // Addresses with allowed attribute IpSuffixOriginRandom should be returned
+  // and attributes should be translated correctly to
+  // IP_ADDRESS_ATTRIBUTE_TEMPORARY.
+  ASSERT_TRUE(FillAdapterAddress(
+      &adapter_address /* adapter_address */, ifname_em1 /* ifname */,
+      ipv6_address /* ip_address */, ipv6_prefix /* ip_netmask */,
+      addresses /* sock_addrs */));
+  adapter_address.FirstUnicastAddress->PrefixOrigin =
+      IpPrefixOriginRouterAdvertisement;
+  adapter_address.FirstUnicastAddress->SuffixOrigin = IpSuffixOriginRandom;
+
+  EXPECT_TRUE(net::internal::GetNetworkListImpl(
+      &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address));
+  EXPECT_EQ(results.size(), 1ul);
+  EXPECT_EQ(results[0].name, ifname_em1);
+  EXPECT_EQ(results[0].prefix_length, 1ul);
+  EXPECT_EQ(results[0].address, ipv6_address);
+  EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_TEMPORARY);
+  results.clear();
+
+  // Addresses with preferred lifetime 0 should be returned and
+  // attributes should be translated correctly to
+  // IP_ADDRESS_ATTRIBUTE_DEPRECATED.
+  ASSERT_TRUE(FillAdapterAddress(
+      &adapter_address /* adapter_address */, ifname_em1 /* ifname */,
+      ipv6_address /* ip_address */, ipv6_prefix /* ip_netmask */,
+      addresses /* sock_addrs */));
+  adapter_address.FirstUnicastAddress->PreferredLifetime = 0;
+  adapter_address.FriendlyName = const_cast<PWCHAR>(L"FriendlyInterfaceName");
+  EXPECT_TRUE(net::internal::GetNetworkListImpl(
+      &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address));
+  EXPECT_EQ(results.size(), 1ul);
+  EXPECT_EQ(results[0].friendly_name, "FriendlyInterfaceName");
+  EXPECT_EQ(results[0].name, ifname_em1);
+  EXPECT_EQ(results[0].prefix_length, 1ul);
+  EXPECT_EQ(results[0].address, ipv6_address);
+  EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_DEPRECATED);
+  results.clear();
+}
 
 #endif  // !OS_MACOSX && !OS_WIN && !OS_NACL
 
diff --git a/net/base/net_util_win.cc b/net/base/net_util_win.cc
index 7d146b9..ec40233 100644
--- a/net/base/net_util_win.cc
+++ b/net/base/net_util_win.cc
@@ -85,35 +85,11 @@
       free_memory_func && close_handle_func;
 }
 
-}  // namespace internal
-
-bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
-  // GetAdaptersAddresses() may require IO operations.
-  base::ThreadRestrictions::AssertIOAllowed();
-  bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
-  ULONG len = 0;
-  ULONG flags = is_xp ? GAA_FLAG_INCLUDE_PREFIX : 0;
-  // First get number of networks.
-  ULONG result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len);
-  if (result != ERROR_BUFFER_OVERFLOW) {
-    // There are 0 networks.
-    return true;
-  }
-  scoped_ptr<char[]> buf(new char[len]);
-  IP_ADAPTER_ADDRESSES *adapters =
-      reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get());
-  result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &len);
-  if (result != NO_ERROR) {
-    LOG(ERROR) << "GetAdaptersAddresses failed: " << result;
-    return false;
-  }
-
-  // These two variables are used below when this method is asked to pick a
-  // IPv6 address which has the shortest lifetime.
-  ULONG ipv6_valid_lifetime = 0;
-  scoped_ptr<NetworkInterface> ipv6_address;
-
-  for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL;
+bool GetNetworkListImpl(NetworkInterfaceList* networks,
+                        int policy,
+                        bool is_xp,
+                        const IP_ADAPTER_ADDRESSES* adapters) {
+  for (const IP_ADAPTER_ADDRESSES* adapter = adapters; adapter != NULL;
        adapter = adapter->Next) {
     // Ignore the loopback device.
     if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
@@ -128,7 +104,7 @@
     // VMware Virtual Ethernet Adapter for VMnet1
     // but don't ignore any GUEST side adapters with a description like:
     // VMware Accelerated AMD PCNet Adapter #2
-    if (policy == EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES &&
+    if ((policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES) &&
         strstr(adapter->AdapterName, "VMnet") != NULL) {
       continue;
     }
@@ -141,7 +117,7 @@
         if (endpoint.FromSockAddr(address->Address.lpSockaddr,
                                   address->Address.iSockaddrLength)) {
           // XP has no OnLinkPrefixLength field.
-          size_t net_prefix = is_xp ? 0 : address->OnLinkPrefixLength;
+          size_t prefix_length = is_xp ? 0 : address->OnLinkPrefixLength;
           if (is_xp) {
             // Prior to Windows Vista the FirstPrefix pointed to the list with
             // single prefix for each IP address assigned to the adapter.
@@ -157,52 +133,72 @@
                   IPNumberMatchesPrefix(endpoint.address(),
                                         network_endpoint.address(),
                                         prefix->PrefixLength)) {
-                net_prefix = std::max<size_t>(net_prefix, prefix->PrefixLength);
+                prefix_length =
+                    std::max<size_t>(prefix_length, prefix->PrefixLength);
               }
             }
           }
+
+          // If the duplicate address detection (DAD) state is not changed to
+          // Preferred, skip this address.
+          if (address->DadState != IpDadStatePreferred) {
+            continue;
+          }
+
           uint32 index =
               (family == AF_INET) ? adapter->IfIndex : adapter->Ipv6IfIndex;
-          // Pick one IPv6 address with least valid lifetime.
-          // The reason we are checking |ValidLifeftime| as there is no other
-          // way identifying the interface type. Usually (and most likely) temp
-          // IPv6 will have a shorter ValidLifetime value then the permanent
-          // interface.
-          if (family == AF_INET6 &&
-              (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE)) {
-            if (ipv6_valid_lifetime == 0 ||
-                ipv6_valid_lifetime > address->ValidLifetime) {
-              ipv6_valid_lifetime = address->ValidLifetime;
-              ipv6_address.reset(new NetworkInterface(
-                  adapter->AdapterName,
-                  base::SysWideToNativeMB(adapter->FriendlyName),
-                  index,
-                  GetNetworkInterfaceType(adapter->IfType),
-                  endpoint.address(),
-                  net_prefix,
-                  IP_ADDRESS_ATTRIBUTE_NONE));
-              continue;
+
+          // From http://technet.microsoft.com/en-us/ff568768(v=vs.60).aspx, the
+          // way to identify a temporary IPv6 Address is to check if
+          // PrefixOrigin is equal to IpPrefixOriginRouterAdvertisement and
+          // SuffixOrigin equal to IpSuffixOriginRandom.
+          int ip_address_attributes = IP_ADDRESS_ATTRIBUTE_NONE;
+          if (family == AF_INET6) {
+            if (address->PrefixOrigin == IpPrefixOriginRouterAdvertisement &&
+                address->SuffixOrigin == IpSuffixOriginRandom) {
+              ip_address_attributes |= IP_ADDRESS_ATTRIBUTE_TEMPORARY;
+            }
+            if (address->PreferredLifetime == 0) {
+              ip_address_attributes |= IP_ADDRESS_ATTRIBUTE_DEPRECATED;
             }
           }
-          networks->push_back(
-              NetworkInterface(adapter->AdapterName,
-                               base::SysWideToNativeMB(adapter->FriendlyName),
-                               index,
-                               GetNetworkInterfaceType(adapter->IfType),
-                               endpoint.address(),
-                               net_prefix,
-                               IP_ADDRESS_ATTRIBUTE_NONE));
+          networks->push_back(NetworkInterface(
+              adapter->AdapterName,
+              base::SysWideToNativeMB(adapter->FriendlyName), index,
+              GetNetworkInterfaceType(adapter->IfType), endpoint.address(),
+              prefix_length, ip_address_attributes));
         }
       }
     }
   }
-
-  if (ipv6_address.get()) {
-    networks->push_back(*(ipv6_address.get()));
-  }
   return true;
 }
 
+}  // namespace internal
+
+bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
+  bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
+  ULONG len = 0;
+  ULONG flags = is_xp ? GAA_FLAG_INCLUDE_PREFIX : 0;
+  // GetAdaptersAddresses() may require IO operations.
+  base::ThreadRestrictions::AssertIOAllowed();
+  ULONG result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len);
+  if (result != ERROR_BUFFER_OVERFLOW) {
+    // There are 0 networks.
+    return true;
+  }
+  scoped_ptr<char[]> buf(new char[len]);
+  IP_ADAPTER_ADDRESSES* adapters =
+      reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buf.get());
+  result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &len);
+  if (result != NO_ERROR) {
+    LOG(ERROR) << "GetAdaptersAddresses failed: " << result;
+    return false;
+  }
+
+  return internal::GetNetworkListImpl(networks, policy, is_xp, adapters);
+}
+
 WifiPHYLayerProtocol GetWifiPHYLayerProtocol() {
   const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance();
   if (!wlanapi.initialized)
diff --git a/net/base/net_util_win.h b/net/base/net_util_win.h
index afa888b..b0c2dd6 100644
--- a/net/base/net_util_win.h
+++ b/net/base/net_util_win.h
@@ -8,10 +8,12 @@
 // This file is only used to expose some of the internals
 // of net_util_win.cc to tests.
 
+#include <iphlpapi.h>
 #include <wlanapi.h>
 
 #include "base/win/scoped_handle.h"
 #include "net/base/net_export.h"
+#include "net/base/net_util.h"
 
 namespace net {
 namespace internal {
@@ -78,6 +80,12 @@
   }
 };
 
+NET_EXPORT bool GetNetworkListImpl(
+    NetworkInterfaceList* networks,
+    int policy,
+    bool is_xp,
+    const IP_ADAPTER_ADDRESSES* ip_adapter_addresses);
+
 }  // namespace internal
 
 }  // namespace net
diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc
index 5b69cfb..d4aa19e 100644
--- a/net/base/network_delegate.cc
+++ b/net/base/network_delegate.cc
@@ -339,12 +339,6 @@
   return false;
 }
 
-int NetworkDelegate::OnBeforeSocketStreamConnect(
-    SocketStream* socket,
-    const CompletionCallback& callback) {
-  return OK;
-}
-
 bool NetworkDelegate::OnCancelURLRequestWithPolicyViolatingReferrerHeader(
     const URLRequest& request,
     const GURL& target_url,
diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h
index 03dee0b..a169fc6 100644
--- a/net/base/network_delegate.h
+++ b/net/base/network_delegate.h
@@ -38,7 +38,6 @@
 class ProxyInfo;
 class ProxyServer;
 class ProxyService;
-class SocketStream;
 class URLRequest;
 
 class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
@@ -268,11 +267,6 @@
       const GURL& url,
       const GURL& first_party_for_cookies) const;
 
-  // Called before a SocketStream tries to connect.
-  // See OnBeforeURLRequest for return value description. Returns OK by default.
-  virtual int OnBeforeSocketStreamConnect(
-      SocketStream* socket, const CompletionCallback& callback);
-
   // Called when the |referrer_url| for requesting |target_url| during handling
   // of the |request| is does not comply with the referrer policy (e.g. a
   // secure referrer for an insecure initial target).
diff --git a/net/base/sdch_manager.cc b/net/base/sdch_manager.cc
index af5e6ee..1aa9627 100644
--- a/net/base/sdch_manager.cc
+++ b/net/base/sdch_manager.cc
@@ -9,6 +9,7 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/time/default_clock.h"
 #include "base/values.h"
 #include "crypto/sha2.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
@@ -38,9 +39,6 @@
 
 namespace net {
 
-//------------------------------------------------------------------------------
-// static
-
 // Adjust SDCH limits downwards for mobile.
 #if defined(OS_ANDROID) || defined(OS_IOS)
 // static
@@ -58,7 +56,6 @@
 // static
 bool SdchManager::g_secure_scheme_supported_ = true;
 
-//------------------------------------------------------------------------------
 SdchManager::Dictionary::Dictionary(const std::string& dictionary_text,
                                     size_t offset,
                                     const std::string& client_hash,
@@ -73,45 +70,22 @@
       domain_(domain),
       path_(path),
       expiration_(expiration),
-      ports_(ports) {
+      ports_(ports),
+      clock_(new base::DefaultClock) {
 }
 
-SdchManager::Dictionary::~Dictionary() {
-}
+SdchManager::Dictionary::Dictionary(const SdchManager::Dictionary& rhs)
+    : text_(rhs.text_),
+      client_hash_(rhs.client_hash_),
+      url_(rhs.url_),
+      domain_(rhs.domain_),
+      path_(rhs.path_),
+      expiration_(rhs.expiration_),
+      ports_(rhs.ports_),
+      clock_(new base::DefaultClock) {}
 
-SdchProblemCode SdchManager::Dictionary::CanAdvertise(
-    const GURL& target_url) const {
-  /* The specific rules of when a dictionary should be advertised in an
-     Avail-Dictionary header are modeled after the rules for cookie scoping. The
-     terms "domain-match" and "pathmatch" are defined in RFC 2965 [6]. A
-     dictionary may be advertised in the Avail-Dictionaries header exactly when
-     all of the following are true:
-      1. The server's effective host name domain-matches the Domain attribute of
-         the dictionary.
-      2. If the dictionary has a Port attribute, the request port is one of the
-         ports listed in the Port attribute.
-      3. The request URI path-matches the path header of the dictionary.
-      4. The request is not an HTTPS request.
-     We can override (ignore) item (4) only when we have explicitly enabled
-     HTTPS support AND the dictionary acquisition scheme matches the target
-     url scheme.
-    */
-  if (!DomainMatch(target_url, domain_))
-    return SDCH_DICTIONARY_FOUND_HAS_WRONG_DOMAIN;
-  if (!ports_.empty() && 0 == ports_.count(target_url.EffectiveIntPort()))
-    return SDCH_DICTIONARY_FOUND_HAS_WRONG_PORT_LIST;
-  if (path_.size() && !PathMatch(target_url.path(), path_))
-    return SDCH_DICTIONARY_FOUND_HAS_WRONG_PATH;
-  if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure())
-    return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME;
-  if (target_url.SchemeIsSecure() != url_.SchemeIsSecure())
-    return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME;
-  if (base::Time::Now() > expiration_)
-    return SDCH_DICTIONARY_FOUND_EXPIRED;
-  return SDCH_OK;
-}
+SdchManager::Dictionary::~Dictionary() {}
 
-//------------------------------------------------------------------------------
 // Security functions restricting loads and use of dictionaries.
 
 // static
@@ -168,7 +142,7 @@
 }
 
 SdchProblemCode SdchManager::Dictionary::CanUse(
-    const GURL& referring_url) const {
+    const GURL& target_url) const {
   /*
     1. The request URL's host name domain-matches the Domain attribute of the
       dictionary.
@@ -180,24 +154,24 @@
     HTTPS support AND the dictionary acquisition scheme matches the target
      url scheme.
   */
-  if (!DomainMatch(referring_url, domain_))
+  if (!DomainMatch(target_url, domain_))
     return SDCH_DICTIONARY_FOUND_HAS_WRONG_DOMAIN;
 
-  if (!ports_.empty() && 0 == ports_.count(referring_url.EffectiveIntPort()))
+  if (!ports_.empty() && 0 == ports_.count(target_url.EffectiveIntPort()))
     return SDCH_DICTIONARY_FOUND_HAS_WRONG_PORT_LIST;
 
-  if (path_.size() && !PathMatch(referring_url.path(), path_))
+  if (path_.size() && !PathMatch(target_url.path(), path_))
     return SDCH_DICTIONARY_FOUND_HAS_WRONG_PATH;
 
-  if (!SdchManager::secure_scheme_supported() && referring_url.SchemeIsSecure())
+  if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure())
     return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME;
 
-  if (referring_url.SchemeIsSecure() != url_.SchemeIsSecure())
+  if (target_url.SchemeIsSecure() != url_.SchemeIsSecure())
     return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME;
 
   // TODO(jar): Remove overly restrictive failsafe test (added per security
   // review) when we have a need to be more general.
-  if (!referring_url.SchemeIsHTTPOrHTTPS())
+  if (!target_url.SchemeIsHTTPOrHTTPS())
     return SDCH_ATTEMPT_TO_DECODE_NON_HTTP_DATA;
 
   return SDCH_OK;
@@ -228,7 +202,54 @@
   return gurl.DomainIs(restriction.data(), restriction.size());
 }
 
-//------------------------------------------------------------------------------
+bool SdchManager::Dictionary::Expired() const {
+  return clock_->Now() > expiration_;
+}
+
+void SdchManager::Dictionary::SetClockForTesting(
+    scoped_ptr<base::Clock> clock) {
+  clock_ = clock.Pass();
+}
+
+SdchManager::DictionarySet::DictionarySet() {}
+
+SdchManager::DictionarySet::~DictionarySet() {}
+
+std::string SdchManager::DictionarySet::GetDictionaryClientHashList() const {
+  std::string result;
+  bool first = true;
+  for (const auto& entry: dictionaries_) {
+    if (!first)
+      result.append(",");
+
+    result.append(entry.second->data.client_hash());
+    first = false;
+  }
+  return result;
+}
+
+const SdchManager::Dictionary* SdchManager::DictionarySet::GetDictionary(
+    const std::string& hash) const {
+  auto it = dictionaries_.find(hash);
+  if (it == dictionaries_.end())
+    return NULL;
+
+  return &it->second->data;
+}
+
+bool SdchManager::DictionarySet::Empty() const {
+  return dictionaries_.empty();
+}
+
+void SdchManager::DictionarySet::AddDictionary(
+    const std::string& server_hash,
+    const scoped_refptr<base::RefCountedData<SdchManager::Dictionary>>&
+    dictionary) {
+  DCHECK(dictionaries_.end() == dictionaries_.find(server_hash));
+
+  dictionaries_[server_hash] = dictionary;
+}
+
 SdchManager::SdchManager() {
   DCHECK(thread_checker_.CalledOnValidThread());
 }
@@ -236,7 +257,7 @@
 SdchManager::~SdchManager() {
   DCHECK(thread_checker_.CalledOnValidThread());
   while (!dictionaries_.empty()) {
-    DictionaryMap::iterator it = dictionaries_.begin();
+    auto it = dictionaries_.begin();
     dictionaries_.erase(it->first);
   }
 }
@@ -246,7 +267,7 @@
   allow_latency_experiment_.clear();
 
   // Note that this may result in not having dictionaries we've advertised
-  // for incoming responses.  The window is relatively small (as ClearData()
+  // for incoming responses. The window is relatively small (as ClearData()
   // is not expected to be called frequently), so we rely on meta-refresh
   // to handle this case.
   dictionaries_.clear();
@@ -386,7 +407,7 @@
        3 The parent domain of the referrer URL host name is not a top level
            domain
    */
-  // Item (1) above implies item (2).  Spec should be updated.
+  // Item (1) above implies item (2). Spec should be updated.
   // I take "host name match" to be "is identical to"
   if (referring_url.host() != dictionary_url.host() ||
       referring_url.scheme() != dictionary_url.scheme())
@@ -403,51 +424,49 @@
   return SDCH_OK;
 }
 
-SdchProblemCode SdchManager::GetVcdiffDictionary(
-    const std::string& server_hash,
-    const GURL& referring_url,
-    scoped_refptr<Dictionary>* dictionary) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  *dictionary = NULL;
-  DictionaryMap::iterator it = dictionaries_.find(server_hash);
-  if (it == dictionaries_.end())
-    return SDCH_DICTIONARY_HASH_NOT_FOUND;
+scoped_ptr<SdchManager::DictionarySet>
+SdchManager::GetDictionarySet(const GURL& target_url) {
+  if (IsInSupportedDomain(target_url) != SDCH_OK)
+    return NULL;
 
-  scoped_refptr<Dictionary> matching_dictionary = it->second;
-
-  SdchProblemCode rv = IsInSupportedDomain(referring_url);
-  if (rv != SDCH_OK)
-    return rv;
-
-  rv = matching_dictionary->CanUse(referring_url);
-  if (rv == SDCH_OK)
-    *dictionary = matching_dictionary;
-  return rv;
-}
-
-// TODO(jar): If we have evictions from the dictionaries_, then we need to
-// change this interface to return a list of reference counted Dictionary
-// instances that can be used if/when a server specifies one.
-void SdchManager::GetAvailDictionaryList(const GURL& target_url,
-                                         std::string* list) {
-  DCHECK(thread_checker_.CalledOnValidThread());
   int count = 0;
-  for (DictionaryMap::iterator it = dictionaries_.begin();
-       it != dictionaries_.end(); ++it) {
-    SdchProblemCode rv = IsInSupportedDomain(target_url);
-    if (rv != SDCH_OK)
+  scoped_ptr<SdchManager::DictionarySet> result(new DictionarySet);
+  for (const auto& entry: dictionaries_) {
+    if (entry.second->data.CanUse(target_url) != SDCH_OK)
       continue;
-
-    if (it->second->CanAdvertise(target_url) != SDCH_OK)
+    if (entry.second->data.Expired())
       continue;
     ++count;
-    if (!list->empty())
-      list->append(",");
-    list->append(it->second->client_hash());
+    result->AddDictionary(entry.first, entry.second);
   }
-  // Watch to see if we have corrupt or numerous dictionaries.
-  if (count > 0)
-    UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count);
+
+  if (count == 0)
+    return NULL;
+
+  UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count);
+
+  return result.Pass();
+}
+
+scoped_ptr<SdchManager::DictionarySet>
+SdchManager::GetDictionarySetByHash(
+    const GURL& target_url,
+    const std::string& server_hash,
+    SdchProblemCode* problem_code) {
+  scoped_ptr<SdchManager::DictionarySet> result;
+
+  *problem_code = SDCH_DICTIONARY_HASH_NOT_FOUND;
+  const auto& it = dictionaries_.find(server_hash);
+  if (it == dictionaries_.end())
+    return result;
+
+  *problem_code = it->second->data.CanUse(target_url);
+  if (*problem_code != SDCH_OK)
+    return result;
+
+  result.reset(new DictionarySet);
+  result->AddDictionary(it->first, it->second);
+  return result;
 }
 
 // static
@@ -465,7 +484,6 @@
   DCHECK_EQ(client_hash->length(), 8u);
 }
 
-//------------------------------------------------------------------------------
 // Methods for supporting latency experiments.
 
 bool SdchManager::AllowLatencyExperiment(const GURL& url) const {
@@ -575,8 +593,8 @@
     return rv;
 
   // TODO(jar): Remove these hacks to preclude a DOS attack involving piles of
-  // useless dictionaries.  We should probably have a cache eviction plan,
-  // instead of just blocking additions.  For now, with the spec in flux, it
+  // useless dictionaries. We should probably have a cache eviction plan,
+  // instead of just blocking additions. For now, with the spec in flux, it
   // is probably not worth doing eviction handling.
   if (kMaxDictionarySize < dictionary_text.size())
     return SDCH_DICTIONARY_IS_TOO_LARGE;
@@ -587,15 +605,22 @@
   UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size());
   DVLOG(1) << "Loaded dictionary with client hash " << client_hash
            << " and server hash " << server_hash;
-  Dictionary* dictionary =
-      new Dictionary(dictionary_text, header_end + 2, client_hash,
-                     dictionary_url_normalized, domain,
-                     path, expiration, ports);
-  dictionaries_[server_hash] = dictionary;
+  Dictionary dictionary(dictionary_text, header_end + 2, client_hash,
+                        dictionary_url_normalized, domain, path, expiration,
+                        ports);
+  dictionaries_[server_hash] =
+      new base::RefCountedData<Dictionary>(dictionary);
+
   return SDCH_OK;
 }
 
 // static
+scoped_ptr<SdchManager::DictionarySet>
+SdchManager::CreateEmptyDictionarySetForTesting() {
+  return scoped_ptr<DictionarySet>(new DictionarySet).Pass();
+}
+
+// static
 void SdchManager::UrlSafeBase64Encode(const std::string& input,
                                       std::string* output) {
   // Since this is only done during a dictionary load, and hashes are only 8
@@ -612,20 +637,20 @@
   value->SetBoolean("secure_scheme_support", secure_scheme_supported());
 
   base::ListValue* entry_list = new base::ListValue();
-  for (DictionaryMap::const_iterator it = dictionaries_.begin();
-       it != dictionaries_.end(); ++it) {
+  for (const auto& entry: dictionaries_) {
     base::DictionaryValue* entry_dict = new base::DictionaryValue();
-    entry_dict->SetString("url", it->second->url().spec());
-    entry_dict->SetString("client_hash", it->second->client_hash());
-    entry_dict->SetString("domain", it->second->domain());
-    entry_dict->SetString("path", it->second->path());
+    entry_dict->SetString("url", entry.second->data.url().spec());
+    entry_dict->SetString("client_hash", entry.second->data.client_hash());
+    entry_dict->SetString("domain", entry.second->data.domain());
+    entry_dict->SetString("path", entry.second->data.path());
     base::ListValue* port_list = new base::ListValue();
-    for (std::set<int>::const_iterator port_it = it->second->ports().begin();
-         port_it != it->second->ports().end(); ++port_it) {
+    for (std::set<int>::const_iterator port_it =
+             entry.second->data.ports().begin();
+         port_it != entry.second->data.ports().end(); ++port_it) {
       port_list->AppendInteger(*port_it);
     }
     entry_dict->Set("ports", port_list);
-    entry_dict->SetString("server_hash", it->first);
+    entry_dict->SetString("server_hash", entry.first);
     entry_list->Append(entry_dict);
   }
   value->Set("dictionaries", entry_list);
diff --git a/net/base/sdch_manager.h b/net/base/sdch_manager.h
index 016978a..0948b4c 100644
--- a/net/base/sdch_manager.h
+++ b/net/base/sdch_manager.h
@@ -2,12 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// This file contains the SdchManager class and two nested classes
+// (Dictionary, DictionarySet). SdchManager::Dictionary contains all
+// of the information about an SDCH dictionary. The manager is
+// responsible for storing those dictionaries, and provides access to
+// them through DictionarySet objects. A DictionarySet is an object
+// whose lifetime is under the control of the consumer. It is a
+// reference to a set of dictionaries, and guarantees that none of
+// those dictionaries will be destroyed while the DictionarySet
+// reference is alive.
+
 #ifndef NET_BASE_SDCH_MANAGER_H_
 #define NET_BASE_SDCH_MANAGER_H_
 
 #include <map>
 #include <set>
 #include <string>
+#include <vector>
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
@@ -20,6 +31,7 @@
 #include "url/gurl.h"
 
 namespace base {
+class Clock;
 class Value;
 }
 
@@ -38,25 +50,22 @@
 // These dictionaries are acquired over the net, and include a header
 // (containing metadata) as well as a VCDIFF dictionary (for use by a VCDIFF
 // module) to decompress data.
+//
+// A dictionary held by the manager may nonetheless outlive the manager if
+// a DictionarySet object refers to it; see below.
 class NET_EXPORT SdchManager {
  public:
+  class Dictionary;
+  typedef std::map<std::string, scoped_refptr<base::RefCountedData<Dictionary>>>
+      DictionaryMap;
+
   // Use the following static limits to block DOS attacks until we implement
   // a cached dictionary evicition strategy.
   static const size_t kMaxDictionarySize;
   static const size_t kMaxDictionaryCount;
 
-  // There is one instance of |Dictionary| for each memory-cached SDCH
-  // dictionary.
-  class NET_EXPORT_PRIVATE Dictionary : public base::RefCounted<Dictionary> {
+  class NET_EXPORT_PRIVATE Dictionary {
    public:
-    // Sdch filters can get our text to use in decoding compressed data.
-    const std::string& text() const { return text_; }
-
-   private:
-    friend class base::RefCounted<Dictionary>;
-    friend class SdchManager;  // Only manager can construct an instance.
-    FRIEND_TEST_ALL_PREFIXES(SdchManagerTest, PathMatch);
-
     // Construct a vc-diff usable dictionary from the dictionary_text starting
     // at the given offset. The supplied client_hash should be used to
     // advertise the dictionary's availability relative to the suppplied URL.
@@ -68,7 +77,11 @@
                const std::string& path,
                const base::Time& expiration,
                const std::set<int>& ports);
-    virtual ~Dictionary();
+
+    ~Dictionary();
+
+    // Sdch filters can get our text to use in decoding compressed data.
+    const std::string& text() const { return text_; }
 
     const GURL& url() const { return url_; }
     const std::string& client_hash() const { return client_hash_; }
@@ -77,10 +90,6 @@
     const base::Time& expiration() const { return expiration_; }
     const std::set<int>& ports() const { return ports_; }
 
-    // Security method to check if we can advertise this dictionary for use
-    // if the |target_url| returns SDCH compressed data.
-    SdchProblemCode CanAdvertise(const GURL& target_url) const;
-
     // Security methods to check if we can establish a new dictionary with the
     // given data, that arrived in response to get of dictionary_url.
     static SdchProblemCode CanSet(const std::string& domain,
@@ -99,6 +108,19 @@
     // Compare domains to see if the "match" for dictionary use.
     static bool DomainMatch(const GURL& url, const std::string& restriction);
 
+    // Is this dictionary expired?
+    bool Expired() const;
+
+    void SetClockForTesting(scoped_ptr<base::Clock> clock);
+
+   private:
+    friend class base::RefCountedData<Dictionary>;
+
+    // Private copy-constructor to support RefCountedData<>, which requires
+    // that an object stored in it be either DefaultConstructible or
+    // CopyConstructible
+    Dictionary(const Dictionary& rhs);
+
     // The actual text of the dictionary.
     std::string text_;
 
@@ -118,7 +140,40 @@
     const base::Time expiration_;  // Implied by max-age.
     const std::set<int> ports_;
 
-    DISALLOW_COPY_AND_ASSIGN(Dictionary);
+    scoped_ptr<base::Clock> clock_;
+
+    void operator=(const Dictionary&) = delete;
+  };
+
+  // A handle for one or more dictionaries which will keep the dictionaries
+  // alive and accessible for the handle's lifetime.
+  class NET_EXPORT_PRIVATE DictionarySet {
+   public:
+    ~DictionarySet();
+
+    // Return a comma separated list of client hashes.
+    std::string GetDictionaryClientHashList() const;
+
+    // Lookup a given dictionary based on server hash. Returned pointer
+    // is guaranteed to be valid for the lifetime of the DictionarySet.
+    // Returns NULL if hash is not a valid server hash for a dictionary
+    // named by DictionarySet.
+    const SdchManager::Dictionary* GetDictionary(const std::string& hash) const;
+
+    bool Empty() const;
+
+   private:
+    // A DictionarySet may only be constructed by the SdchManager.
+    friend class SdchManager;
+
+    DictionarySet();
+    void AddDictionary(const std::string& server_hash,
+                       const scoped_refptr<base::RefCountedData<
+                           SdchManager::Dictionary>>& dictionary);
+
+    DictionaryMap dictionaries_;
+
+    DISALLOW_COPY_AND_ASSIGN(DictionarySet);
   };
 
   SdchManager();
@@ -178,23 +233,22 @@
   SdchProblemCode OnGetDictionary(const GURL& request_url,
                                   const GURL& dictionary_url);
 
-  // Find the vcdiff dictionary (the body of the sdch dictionary that appears
-  // after the meta-data headers like Domain:...) with the given |server_hash|
-  // to use to decompreses data that arrived as SDCH encoded content. Check to
-  // be sure the returned |dictionary| can be used for decoding content supplied
-  // in response to a request for |referring_url|.
-  // Return null in |dictionary| if there is no matching legal dictionary.
-  // Returns SDCH_OK if dictionary is not found, SDCH(-over-https) is disabled,
-  // or if matching legal dictionary exists. Otherwise returns the
-  // corresponding problem code.
-  SdchProblemCode GetVcdiffDictionary(const std::string& server_hash,
-                                      const GURL& referring_url,
-                                      scoped_refptr<Dictionary>* dictionary);
+  // Get a handle to the available dictionaries that might be used
+  // for encoding responses for the given URL. The return set will not
+  // include expired dictionaries. If no dictionaries
+  // are appropriate to use with the target_url, NULL is returned.
+  scoped_ptr<DictionarySet> GetDictionarySet(const GURL& target_url);
 
-  // Get list of available (pre-cached) dictionaries that we have already loaded
-  // into memory. The list is a comma separated list of (client) hashes per
-  // the SDCH spec.
-  void GetAvailDictionaryList(const GURL& target_url, std::string* list);
+  // Get a handle to a specific dictionary, by its server hash, confirming
+  // that that specific dictionary is appropriate to use with |target_url|.
+  // Expired dictionaries will be returned. If no dictionary with that
+  // hash exists that is usable with |target_url|, NULL is returned.
+  // If there is a usability problem, |*error_code| is set to the
+  // appropriate problem code.
+  scoped_ptr<DictionarySet> GetDictionarySetByHash(
+      const GURL& target_url,
+      const std::string& server_hash,
+      SdchProblemCode* problem_code);
 
   // Construct the pair of hashes for client and server to identify an SDCH
   // dictionary. This is only made public to facilitate unit testing, but is
@@ -225,6 +279,8 @@
   void AddObserver(SdchObserver* observer);
   void RemoveObserver(SdchObserver* observer);
 
+  static scoped_ptr<DictionarySet> CreateEmptyDictionarySetForTesting();
+
  private:
   struct BlacklistInfo {
     BlacklistInfo() : count(0), exponential_count(0), reason(SDCH_OK) {}
@@ -233,18 +289,16 @@
     int exponential_count;   // Current exponential backoff ratchet.
     SdchProblemCode reason;  // Why domain was blacklisted.
   };
+
   typedef std::map<std::string, BlacklistInfo> DomainBlacklistInfo;
   typedef std::set<std::string> ExperimentSet;
 
   // Determines whether a "Get-Dictionary" header is legal (dictionary
   // url has appropriate relationship to referrer url) in the SDCH
-  // protocol.  Return SDCH_OK if fetch is legal.
+  // protocol. Return SDCH_OK if fetch is legal.
   SdchProblemCode CanFetchDictionary(const GURL& referring_url,
                                      const GURL& dictionary_url) const;
 
-  // A map of dictionaries info indexed by the hash that the server provides.
-  typedef std::map<std::string, scoped_refptr<Dictionary> > DictionaryMap;
-
   // Support SDCH compression, by advertising in headers.
   static bool g_sdch_enabled_;
 
diff --git a/net/base/sdch_manager_unittest.cc b/net/base/sdch_manager_unittest.cc
index c20be58..2b78394 100644
--- a/net/base/sdch_manager_unittest.cc
+++ b/net/base/sdch_manager_unittest.cc
@@ -8,6 +8,8 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/simple_test_clock.h"
 #include "net/base/net_log.h"
 #include "net/base/sdch_manager.h"
 #include "net/base/sdch_observer.h"
@@ -199,12 +201,9 @@
   EXPECT_TRUE(AddSdchDictionary(dictionary_text,
                                 GURL("http://" + dictionary_domain)));
 
-  std::string dictionary_list;
   // HTTP target URL can advertise dictionary.
-  sdch_manager()->GetAvailDictionaryList(
-      GURL("http://" + dictionary_domain + "/test"),
-      &dictionary_list);
-  EXPECT_FALSE(dictionary_list.empty());
+  EXPECT_TRUE(sdch_manager()->GetDictionarySet(
+      GURL("http://" + dictionary_domain + "/test")));
 }
 
 TEST_F(SdchManagerTest, CanNotAdvertiseDictionaryOverHTTPS) {
@@ -214,12 +213,9 @@
   EXPECT_TRUE(AddSdchDictionary(dictionary_text,
                                 GURL("http://" + dictionary_domain)));
 
-  std::string dictionary_list;
   // HTTPS target URL should NOT advertise dictionary.
-  sdch_manager()->GetAvailDictionaryList(
-      GURL("https://" + dictionary_domain + "/test"),
-      &dictionary_list);
-  EXPECT_TRUE(dictionary_list.empty());
+  EXPECT_FALSE(sdch_manager()->GetDictionarySet(
+      GURL("https://" + dictionary_domain + "/test")));
 }
 
 TEST_F(SdchManagerTest, CanUseHTTPSDictionaryOverHTTPSIfEnabled) {
@@ -234,20 +230,21 @@
                                 GURL("https://" + dictionary_domain)));
 
   GURL target_url("https://" + dictionary_domain + "/test");
-  std::string dictionary_list;
   // HTTPS target URL should advertise dictionary if secure scheme support is
   // enabled.
-  sdch_manager()->GetAvailDictionaryList(target_url, &dictionary_list);
-  EXPECT_FALSE(dictionary_list.empty());
+  EXPECT_TRUE(sdch_manager()->GetDictionarySet(target_url));
 
   // Dictionary should be available.
-  scoped_refptr<SdchManager::Dictionary> dictionary;
   std::string client_hash;
   std::string server_hash;
   sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash);
-  EXPECT_EQ(SDCH_OK, sdch_manager()->GetVcdiffDictionary(
-                         server_hash, target_url, &dictionary));
-  EXPECT_TRUE(dictionary.get() != NULL);
+  SdchProblemCode problem_code;
+  scoped_ptr<SdchManager::DictionarySet> dict_set(
+      sdch_manager()->GetDictionarySetByHash(
+          target_url, server_hash, &problem_code));
+  EXPECT_EQ(SDCH_OK, problem_code);
+  EXPECT_TRUE(dict_set.get());
+  EXPECT_TRUE(dict_set->GetDictionary(server_hash));
 }
 
 TEST_F(SdchManagerTest, CanNotUseHTTPDictionaryOverHTTPS) {
@@ -258,21 +255,20 @@
                                 GURL("http://" + dictionary_domain)));
 
   GURL target_url("https://" + dictionary_domain + "/test");
-  std::string dictionary_list;
   // HTTPS target URL should not advertise dictionary acquired over HTTP even if
   // secure scheme support is enabled.
   SdchManager::EnableSecureSchemeSupport(true);
-  sdch_manager()->GetAvailDictionaryList(target_url, &dictionary_list);
-  EXPECT_TRUE(dictionary_list.empty());
+  EXPECT_FALSE(sdch_manager()->GetDictionarySet(target_url));
 
-  scoped_refptr<SdchManager::Dictionary> dictionary;
   std::string client_hash;
   std::string server_hash;
   sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash);
-  EXPECT_EQ(SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME,
-            sdch_manager()->GetVcdiffDictionary(server_hash, target_url,
-                                                &dictionary));
-  EXPECT_TRUE(dictionary.get() == NULL);
+  SdchProblemCode problem_code;
+  scoped_ptr<SdchManager::DictionarySet> dict_set(
+      sdch_manager()->GetDictionarySetByHash(
+          target_url, server_hash, &problem_code));
+  EXPECT_FALSE(dict_set.get());
+  EXPECT_EQ(SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME, problem_code);
 }
 
 TEST_F(SdchManagerTest, CanNotUseHTTPSDictionaryOverHTTP) {
@@ -284,20 +280,19 @@
                                 GURL("https://" + dictionary_domain)));
 
   GURL target_url("http://" + dictionary_domain + "/test");
-  std::string dictionary_list;
   // HTTP target URL should not advertise dictionary acquired over HTTPS even if
   // secure scheme support is enabled.
-  sdch_manager()->GetAvailDictionaryList(target_url, &dictionary_list);
-  EXPECT_TRUE(dictionary_list.empty());
+  EXPECT_FALSE(sdch_manager()->GetDictionarySet(target_url));
 
-  scoped_refptr<SdchManager::Dictionary> dictionary;
   std::string client_hash;
   std::string server_hash;
   sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash);
-  EXPECT_EQ(SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME,
-            sdch_manager()->GetVcdiffDictionary(server_hash, target_url,
-                                                &dictionary));
-  EXPECT_TRUE(dictionary.get() == NULL);
+  SdchProblemCode problem_code;
+  scoped_ptr<SdchManager::DictionarySet> dict_set(
+      sdch_manager()->GetDictionarySetByHash(
+          target_url, server_hash, &problem_code));
+  EXPECT_FALSE(dict_set.get());
+  EXPECT_EQ(SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME, problem_code);
 }
 
 TEST_F(SdchManagerTest, FailToSetDomainMismatchDictionary) {
@@ -438,7 +433,7 @@
   EXPECT_TRUE(PathMatch("/search/", "/search/"));
 
   // Prefix only works if last character of restriction is a slash, or first
-  // character in path after a match is a slash.  Validate each case separately.
+  // character in path after a match is a slash. Validate each case separately.
 
   // Rely on the slash in the path (not at the end of the restriction).
   EXPECT_TRUE(PathMatch("/search/something", "/search"));
@@ -519,34 +514,36 @@
   // can't get them from the other.
   EXPECT_TRUE(AddSdchDictionary(dictionary_text_1,
                                 GURL("http://" + dictionary_domain_1)));
-  scoped_refptr<SdchManager::Dictionary> dictionary;
-  EXPECT_EQ(SDCH_OK, sdch_manager()->GetVcdiffDictionary(
-                         server_hash_1,
-                         GURL("http://" + dictionary_domain_1 + "/random_url"),
-                         &dictionary));
-  EXPECT_TRUE(dictionary.get());
+  scoped_ptr<SdchManager::DictionarySet> dict_set;
+
+  SdchProblemCode problem_code;
+  dict_set = sdch_manager()->GetDictionarySetByHash(
+      GURL("http://" + dictionary_domain_1 + "/random_url"),
+      server_hash_1, &problem_code);
+  EXPECT_TRUE(dict_set);
+  EXPECT_TRUE(dict_set->GetDictionary(server_hash_1));
+  EXPECT_EQ(SDCH_OK, problem_code);
 
   second_manager.AddSdchDictionary(
       dictionary_text_2, GURL("http://" + dictionary_domain_2));
-  second_manager.GetVcdiffDictionary(
-      server_hash_2,
+  dict_set = second_manager.GetDictionarySetByHash(
       GURL("http://" + dictionary_domain_2 + "/random_url"),
-      &dictionary);
-  EXPECT_TRUE(dictionary.get());
+      server_hash_2, &problem_code);
+  EXPECT_TRUE(dict_set);
+  EXPECT_TRUE(dict_set->GetDictionary(server_hash_2));
+  EXPECT_EQ(SDCH_OK, problem_code);
 
-  EXPECT_EQ(
-      SDCH_DICTIONARY_HASH_NOT_FOUND,
-      sdch_manager()->GetVcdiffDictionary(
-          server_hash_2, GURL("http://" + dictionary_domain_2 + "/random_url"),
-          &dictionary));
-  EXPECT_FALSE(dictionary.get());
+  dict_set = sdch_manager()->GetDictionarySetByHash(
+      GURL("http://" + dictionary_domain_2 + "/random_url"),
+      server_hash_2, &problem_code);
+  EXPECT_FALSE(dict_set);
+  EXPECT_EQ(SDCH_DICTIONARY_HASH_NOT_FOUND, problem_code);
 
-  EXPECT_EQ(
-      SDCH_DICTIONARY_HASH_NOT_FOUND,
-      second_manager.GetVcdiffDictionary(
-          server_hash_1, GURL("http://" + dictionary_domain_1 + "/random_url"),
-          &dictionary));
-  EXPECT_FALSE(dictionary.get());
+  dict_set = second_manager.GetDictionarySetByHash(
+      GURL("http://" + dictionary_domain_1 + "/random_url"),
+      server_hash_1, &problem_code);
+  EXPECT_FALSE(dict_set);
+  EXPECT_EQ(SDCH_DICTIONARY_HASH_NOT_FOUND, problem_code);
 }
 
 TEST_F(SdchManagerTest, HttpsCorrectlySupported) {
@@ -578,12 +575,16 @@
 
   EXPECT_TRUE(AddSdchDictionary(dictionary_text,
                                 GURL("http://" + dictionary_domain)));
-  scoped_refptr<SdchManager::Dictionary> dictionary;
-  EXPECT_EQ(SDCH_OK, sdch_manager()->GetVcdiffDictionary(
-                         server_hash,
-                         GURL("http://" + dictionary_domain + "/random_url"),
-                         &dictionary));
-  EXPECT_TRUE(dictionary.get());
+
+  scoped_ptr<SdchManager::DictionarySet> dict_set;
+
+  SdchProblemCode problem_code;
+  dict_set = sdch_manager()->GetDictionarySetByHash(
+      GURL("http://" + dictionary_domain + "/random_url"),
+      server_hash, &problem_code);
+  EXPECT_TRUE(dict_set);
+  EXPECT_TRUE(dict_set->GetDictionary(server_hash));
+  EXPECT_EQ(SDCH_OK, problem_code);
 
   sdch_manager()->BlacklistDomain(GURL(blacklist_url), SDCH_OK);
   EXPECT_EQ(SDCH_DOMAIN_BLACKLIST_INCLUDES_TARGET,
@@ -591,13 +592,11 @@
 
   sdch_manager()->ClearData();
 
-  dictionary = NULL;
-  EXPECT_EQ(
-      SDCH_DICTIONARY_HASH_NOT_FOUND,
-      sdch_manager()->GetVcdiffDictionary(
-          server_hash, GURL("http://" + dictionary_domain + "/random_url"),
-          &dictionary));
-  EXPECT_FALSE(dictionary.get());
+  dict_set = sdch_manager()->GetDictionarySetByHash(
+      GURL("http://" + dictionary_domain + "/random_url"),
+      server_hash, &problem_code);
+  EXPECT_FALSE(dict_set);
+  EXPECT_EQ(SDCH_DICTIONARY_HASH_NOT_FOUND, problem_code);
   EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(blacklist_url));
 }
 
@@ -620,4 +619,39 @@
   EXPECT_EQ(test_dictionary_gurl, observer.last_dictionary_url());
 }
 
+TEST_F(SdchManagerTest, ExpirationCheckedProperly) {
+  // Create an SDCH dictionary with an expiration time in the past.
+  std::string dictionary_domain("x.y.z.google.com");
+  std::string dictionary_text(base::StringPrintf(
+      "Domain: %s\nMax-age: 0\n\n", dictionary_domain.c_str()));
+  dictionary_text.append(
+      kTestVcdiffDictionary, sizeof(kTestVcdiffDictionary) - 1);
+  std::string client_hash;
+  std::string server_hash;
+  SdchManager::GenerateHash(dictionary_text, &client_hash, &server_hash);
+  GURL target_gurl("http://" + dictionary_domain);
+  AddSdchDictionary(dictionary_text, target_gurl);
+
+  // It should be visible if looked up by hash whether expired or not.
+  scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock);
+  clock->SetNow(base::Time::Now());
+  clock->Advance(base::TimeDelta::FromMinutes(5));
+  SdchProblemCode problem_code;
+  scoped_ptr<SdchManager::DictionarySet> hash_set(
+      sdch_manager()->GetDictionarySetByHash(
+          target_gurl, server_hash, &problem_code).Pass());
+  ASSERT_TRUE(hash_set);
+  ASSERT_EQ(SDCH_OK, problem_code);
+  const_cast<SdchManager::Dictionary*>(
+      hash_set->GetDictionary(server_hash))->SetClockForTesting(
+      clock.Pass());
+
+  // Make sure it's not visible for advertisement, but is visible
+  // if looked up by hash.
+  EXPECT_FALSE(sdch_manager()->GetDictionarySet(target_gurl));
+  EXPECT_TRUE(sdch_manager()->GetDictionarySetByHash(
+      target_gurl, server_hash, &problem_code));
+  EXPECT_EQ(SDCH_OK, problem_code);
+}
+
 }  // namespace net
diff --git a/net/base/sdch_problem_code_list.h b/net/base/sdch_problem_code_list.h
index a0d5196..0eef912 100644
--- a/net/base/sdch_problem_code_list.h
+++ b/net/base/sdch_problem_code_list.h
@@ -65,6 +65,10 @@
 SDCH_PROBLEM_CODE(MULTIENCODING_FOR_NON_SDCH_REQUEST, 50)
 SDCH_PROBLEM_CODE(SDCH_CONTENT_ENCODE_FOR_NON_SDCH_REQUEST, 51)
 
+// A dictionary that wasn't advertised is being used for decoding.
+SDCH_PROBLEM_CODE(UNADVERTISED_DICTIONARY_USED, 52)
+SDCH_PROBLEM_CODE(UNADVERTISED_DICTIONARY_USED_CACHED, 53)
+
 // Dictionary manager issues.
 SDCH_PROBLEM_CODE(DOMAIN_BLACKLIST_INCLUDES_TARGET, 61)
 
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index c3f118d..cd9c9b8 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -1319,16 +1319,12 @@
   if (!HasCookieableScheme(url))
     return std::string();
 
-  TimeTicks start_time(TimeTicks::Now());
-
   std::vector<CanonicalCookie*> cookies;
   FindCookiesForHostAndDomain(url, options, true, &cookies);
   std::sort(cookies.begin(), cookies.end(), CookieSorter);
 
   std::string cookie_line = BuildCookieLine(cookies);
 
-  histogram_time_get_->AddTime(TimeTicks::Now() - start_time);
-
   VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;
 
   return cookie_line;
@@ -2245,9 +2241,6 @@
       base::Histogram::kUmaTargetedHistogramFlag);
 
   // From UMA_HISTOGRAM_{CUSTOM_,}TIMES
-  histogram_time_get_ = base::Histogram::FactoryTimeGet("Cookie.TimeGet",
-      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
-      50, base::Histogram::kUmaTargetedHistogramFlag);
   histogram_time_blocked_on_load_ = base::Histogram::FactoryTimeGet(
       "Cookie.TimeBlockedOnLoad",
       base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index 18d1b8a..0f00490 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -635,7 +635,6 @@
   base::HistogramBase* histogram_domain_per_etldp1_count_;
   base::HistogramBase* histogram_number_duplicate_db_cookies_;
   base::HistogramBase* histogram_cookie_deletion_cause_;
-  base::HistogramBase* histogram_time_get_;
   base::HistogramBase* histogram_time_mac_;
   base::HistogramBase* histogram_time_blocked_on_load_;
 
diff --git a/net/disk_cache/blockfile/in_flight_backend_io.cc b/net/disk_cache/blockfile/in_flight_backend_io.cc
index 2cb3ff0..5b3b904 100644
--- a/net/disk_cache/blockfile/in_flight_backend_io.cc
+++ b/net/disk_cache/blockfile/in_flight_backend_io.cc
@@ -341,35 +341,57 @@
 }
 
 void InFlightBackendIO::Init(const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  // TODO(vadimt): Remove wrapping the callback with
+  // ScopedTracker::TrackCallback() once crbug.com/422516 is fixed.
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_,
+      tracked_objects::ScopedTracker::TrackCallback(
+          FROM_HERE_WITH_EXPLICIT_FUNCTION("422516 InFlightBackendIO::Init"),
+          callback)));
   operation->Init();
   PostOperation(operation.get());
 }
 
 void InFlightBackendIO::OpenEntry(const std::string& key, Entry** entry,
                                   const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::OpenEntry"),
+                          callback)));
   operation->OpenEntry(key, entry);
   PostOperation(operation.get());
 }
 
 void InFlightBackendIO::CreateEntry(const std::string& key, Entry** entry,
                                     const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::CreateEntry"),
+                          callback)));
   operation->CreateEntry(key, entry);
   PostOperation(operation.get());
 }
 
 void InFlightBackendIO::DoomEntry(const std::string& key,
                                   const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::DoomEntry"),
+                          callback)));
   operation->DoomEntry(key);
   PostOperation(operation.get());
 }
 
 void InFlightBackendIO::DoomAllEntries(
     const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::DoomAllEntries"),
+                          callback)));
   operation->DoomAllEntries();
   PostOperation(operation.get());
 }
@@ -377,14 +399,22 @@
 void InFlightBackendIO::DoomEntriesBetween(const base::Time initial_time,
                         const base::Time end_time,
                         const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::DoomEntriesBetween"),
+                          callback)));
   operation->DoomEntriesBetween(initial_time, end_time);
   PostOperation(operation.get());
 }
 
 void InFlightBackendIO::DoomEntriesSince(
     const base::Time initial_time, const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::DoomEntriesSince"),
+                          callback)));
   operation->DoomEntriesSince(initial_time);
   PostOperation(operation.get());
 }
@@ -392,7 +422,11 @@
 void InFlightBackendIO::OpenNextEntry(Rankings::Iterator* iterator,
                                       Entry** next_entry,
                                       const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::OpenNextEntry"),
+                          callback)));
   operation->OpenNextEntry(iterator, next_entry);
   PostOperation(operation.get());
 }
@@ -427,14 +461,22 @@
 }
 
 void InFlightBackendIO::FlushQueue(const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::FlushQueue"),
+                          callback)));
   operation->FlushQueue();
   PostOperation(operation.get());
 }
 
 void InFlightBackendIO::RunTask(
     const base::Closure& task, const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_,
+      tracked_objects::ScopedTracker::TrackCallback(
+          FROM_HERE_WITH_EXPLICIT_FUNCTION("422516 InFlightBackendIO::RunTask"),
+          callback)));
   operation->RunTask(task);
   PostOperation(operation.get());
 }
@@ -442,7 +484,11 @@
 void InFlightBackendIO::ReadData(EntryImpl* entry, int index, int offset,
                                  net::IOBuffer* buf, int buf_len,
                                  const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::ReadData"),
+                          callback)));
   operation->ReadData(entry, index, offset, buf, buf_len);
   PostOperation(operation.get());
 }
@@ -451,7 +497,11 @@
                                   net::IOBuffer* buf, int buf_len,
                                   bool truncate,
                                   const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::WriteData"),
+                          callback)));
   operation->WriteData(entry, index, offset, buf, buf_len, truncate);
   PostOperation(operation.get());
 }
@@ -459,7 +509,11 @@
 void InFlightBackendIO::ReadSparseData(
     EntryImpl* entry, int64 offset, net::IOBuffer* buf, int buf_len,
     const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::ReadSparseData"),
+                          callback)));
   operation->ReadSparseData(entry, offset, buf, buf_len);
   PostOperation(operation.get());
 }
@@ -467,7 +521,11 @@
 void InFlightBackendIO::WriteSparseData(
     EntryImpl* entry, int64 offset, net::IOBuffer* buf, int buf_len,
     const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::WriteSparseData"),
+                          callback)));
   operation->WriteSparseData(entry, offset, buf, buf_len);
   PostOperation(operation.get());
 }
@@ -475,7 +533,11 @@
 void InFlightBackendIO::GetAvailableRange(
     EntryImpl* entry, int64 offset, int len, int64* start,
     const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::GetAvailableRange"),
+                          callback)));
   operation->GetAvailableRange(entry, offset, len, start);
   PostOperation(operation.get());
 }
@@ -489,7 +551,11 @@
 
 void InFlightBackendIO::ReadyForSparseIO(
     EntryImpl* entry, const net::CompletionCallback& callback) {
-  scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
+  scoped_refptr<BackendIO> operation(new BackendIO(
+      this, backend_, tracked_objects::ScopedTracker::TrackCallback(
+                          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                              "422516 InFlightBackendIO::CancelSparseIO"),
+                          callback)));
   operation->ReadyForSparseIO(entry);
   PostOperation(operation.get());
 }
diff --git a/net/disk_cache/simple/simple_util_win.cc b/net/disk_cache/simple/simple_util_win.cc
index d0d191d..f2adcd0 100644
--- a/net/disk_cache/simple/simple_util_win.cc
+++ b/net/disk_cache/simple/simple_util_win.cc
@@ -24,7 +24,7 @@
   // Why a random name? Because if the name was derived from our original name,
   // then churn on a particular cache entry could cause flakey behaviour.
 
-  // TODO(gaivnp): Ensure these "todelete_" files are cleaned up on periodic
+  // TODO(gavinp): Ensure these "todelete_" files are cleaned up on periodic
   // directory sweeps.
   const base::FilePath rename_target =
       path.DirName().AppendASCII(base::StringPrintf("todelete_%016" PRIx64,
diff --git a/net/dns/dns_config_service_win_unittest.cc b/net/dns/dns_config_service_win_unittest.cc
index 7ac01d1..54a6411 100644
--- a/net/dns/dns_config_service_win_unittest.cc
+++ b/net/dns/dns_config_service_win_unittest.cc
@@ -55,7 +55,7 @@
   IF_OPER_STATUS oper_status;
   const WCHAR* dns_suffix;
   std::string dns_server_addresses[4];  // Empty string indicates end.
-  int ports[4];
+  uint16 ports[4];
 };
 
 scoped_ptr<IP_ADAPTER_ADDRESSES, base::FreeDeleter> CreateAdapterAddresses(
@@ -102,7 +102,7 @@
       }
       IPAddressNumber ip;
       CHECK(ParseIPLiteralToNumber(info.dns_server_addresses[j], &ip));
-      IPEndPoint ipe(ip, info.ports[j]);
+      IPEndPoint ipe = IPEndPoint(ip, info.ports[j]);
       address->Address.lpSockaddr =
           reinterpret_cast<LPSOCKADDR>(storage + num_addresses);
       socklen_t length = sizeof(struct sockaddr_storage);
@@ -120,7 +120,7 @@
     AdapterInfo input_adapters[4];        // |if_type| == 0 indicates end.
     std::string expected_nameservers[4];  // Empty string indicates end.
     std::string expected_suffix;
-    int expected_ports[4];
+    uint16 expected_ports[4];
   } cases[] = {
     {  // Ignore loopback and inactive adapters.
       {
@@ -181,7 +181,7 @@
     for (size_t j = 0; !t.expected_nameservers[j].empty(); ++j) {
       IPAddressNumber ip;
       ASSERT_TRUE(ParseIPLiteralToNumber(t.expected_nameservers[j], &ip));
-      int port = t.expected_ports[j];
+      uint16 port = t.expected_ports[j];
       if (!port)
         port = dns_protocol::kDefaultPort;
       expected_nameservers.push_back(IPEndPoint(ip, port));
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h
index 2823c4b..0203dc9 100644
--- a/net/dns/host_resolver.h
+++ b/net/dns/host_resolver.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "net/base/address_family.h"
 #include "net/base/completion_callback.h"
@@ -67,7 +68,7 @@
       host_port_pair_ = host_port_pair;
     }
 
-    int port() const { return host_port_pair_.port(); }
+    uint16 port() const { return host_port_pair_.port(); }
     const std::string& hostname() const { return host_port_pair_.host(); }
 
     AddressFamily address_family() const { return address_family_; }
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index fe63820..9426da5 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -300,14 +300,13 @@
 #elif defined(OS_WIN)
     // Map the error code to a human-readable string.
     LPWSTR error_string = NULL;
-    int size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                             FORMAT_MESSAGE_FROM_SYSTEM,
-                             0,  // Use the internal message table.
-                             os_error,
-                             0,  // Use default language.
-                             (LPWSTR)&error_string,
-                             0,  // Buffer size.
-                             0);  // Arguments (unused).
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                  0,  // Use the internal message table.
+                  os_error,
+                  0,  // Use default language.
+                  (LPWSTR)&error_string,
+                  0,  // Buffer size.
+                  0);  // Arguments (unused).
     dict->SetString("os_error_string", base::WideToUTF8(error_string));
     LocalFree(error_string);
 #endif
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc
index 7b6a391..7a46a1c 100644
--- a/net/dns/host_resolver_impl_unittest.cc
+++ b/net/dns/host_resolver_impl_unittest.cc
@@ -181,7 +181,7 @@
 };
 
 bool AddressListContains(const AddressList& list, const std::string& address,
-                         int port) {
+                         uint16 port) {
   IPAddressNumber ip;
   bool rv = ParseIPLiteralToNumber(address, &ip);
   DCHECK(rv);
@@ -249,7 +249,7 @@
   bool completed() const { return result_ != ERR_IO_PENDING; }
   bool pending() const { return handle_ != NULL; }
 
-  bool HasAddress(const std::string& address, int port) const {
+  bool HasAddress(const std::string& address, uint16 port) const {
     return AddressListContains(list_, address, port);
   }
 
@@ -258,7 +258,7 @@
     return list_.size();
   }
 
-  bool HasOneAddress(const std::string& address, int port) const {
+  bool HasOneAddress(const std::string& address, uint16 port) const {
     return HasAddress(address, port) && (NumberOfAddresses() == 1u);
   }
 
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc
index 48e004e..6d8cba3 100644
--- a/net/dns/mock_host_resolver.cc
+++ b/net/dns/mock_host_resolver.cc
@@ -48,7 +48,7 @@
       LOG(WARNING) << "Not a supported IP literal: " << addresses[index];
       return ERR_UNEXPECTED;
     }
-    addrlist->push_back(IPEndPoint(ip_number, -1));
+    addrlist->push_back(IPEndPoint(ip_number, 0));
   }
   return OK;
 }
diff --git a/net/filter/filter.cc b/net/filter/filter.cc
index 53d6583..b3f98cb 100644
--- a/net/filter/filter.cc
+++ b/net/filter/filter.cc
@@ -3,20 +3,20 @@
 // found in the LICENSE file.
 
 // The basic usage of the Filter interface is described in the comment at
-// the beginning of filter.h.  If Filter::Factory is passed a vector of
+// the beginning of filter.h. If Filter::Factory is passed a vector of
 // size greater than 1, that interface is implemented by a series of filters
-// connected in a chain.  In such a case the first filter
+// connected in a chain. In such a case the first filter
 // in the chain proxies calls to ReadData() so that its return values
 // apply to the entire chain.
 //
 // In a filter chain, the data flows from first filter (held by the
-// caller) down the chain.  When ReadData() is called on any filter
+// caller) down the chain. When ReadData() is called on any filter
 // except for the last filter, it proxies the call down the chain,
 // filling in the input buffers of subsequent filters if needed (==
 // that filter's last_status() value is FILTER_NEED_MORE_DATA) and
-// available (== the current filter has data it can output).  The last
+// available (== the current filter has data it can output). The last
 // Filter will then output data if possible, and return
-// FILTER_NEED_MORE_DATA if not.  Because the indirection pushes
+// FILTER_NEED_MORE_DATA if not. Because the indirection pushes
 // data along the filter chain at each level if it's available and the
 // next filter needs it, a return value of FILTER_NEED_MORE_DATA from the
 // final filter will apply to the entire chain.
@@ -43,8 +43,8 @@
 const char kGZip[]         = "gzip";
 const char kXGZip[]        = "x-gzip";
 const char kSdch[]         = "sdch";
-// compress and x-compress are currently not supported.  If we decide to support
-// them, we'll need the same mime type compatibility hack we have for gzip.  For
+// compress and x-compress are currently not supported. If we decide to support
+// them, we'll need the same mime type compatibility hack we have for gzip. For
 // more information, see Firefox's nsHttpChannel::ProcessNormal.
 
 // Mime types:
@@ -153,9 +153,9 @@
     // In the case where this filter has data internally, and is indicating such
     // with a last_status_ of FILTER_OK, but at the same time the next filter in
     // the chain indicated it FILTER_NEED_MORE_DATA, we have to be cautious
-    // about confusing the caller.  The API confusion can appear if we return
+    // about confusing the caller. The API confusion can appear if we return
     // FILTER_OK (suggesting we have more data in aggregate), but yet we don't
-    // populate our output buffer.  When that is the case, we need to
+    // populate our output buffer. When that is the case, we need to
     // alternately call our filter element, and the next_filter element until we
     // get out of this state (by pumping data into the next filter until it
     // outputs data, or it runs out of data and reports that it NEED_MORE_DATA.)
@@ -217,8 +217,8 @@
         LowerCaseEqualsASCII(mime_type, kApplicationGzip) ||
         LowerCaseEqualsASCII(mime_type, kApplicationXGunzip))
       // The server has told us that it sent us gziped content with a gzip
-      // content encoding.  Sadly, Apache mistakenly sets these headers for all
-      // .gz files.  We match Firefox's nsHttpChannel::ProcessNormal and ignore
+      // content encoding. Sadly, Apache mistakenly sets these headers for all
+      // .gz files. We match Firefox's nsHttpChannel::ProcessNormal and ignore
       // the Content-Encoding here.
       encoding_types->clear();
 
@@ -256,7 +256,7 @@
   }
 
   // If the request was for SDCH content, then we might need additional fixups.
-  if (!filter_context.SdchResponseExpected()) {
+  if (!filter_context.SdchDictionariesAdvertised()) {
     // It was not an SDCH request, so we'll just record stats.
     if (1 < encoding_types->size()) {
       // Multiple filters were intended to only be used for SDCH (thus far!)
@@ -271,7 +271,7 @@
   }
 
   // The request was tagged as an SDCH request, which means the server supplied
-  // a dictionary, and we advertised it in the request.  Some proxies will do
+  // a dictionary, and we advertised it in the request. Some proxies will do
   // very strange things to the request, or the response, so we have to handle
   // them gracefully.
 
@@ -280,7 +280,7 @@
       (FILTER_TYPE_SDCH == encoding_types->front())) {
     // Some proxies (found currently in Argentina) strip the Content-Encoding
     // text from "sdch,gzip" to a mere "sdch" without modifying the compressed
-    // payload.   To handle this gracefully, we simulate the "probably" deleted
+    // payload.  To handle this gracefully, we simulate the "probably" deleted
     // ",gzip" by appending a tentative gzip decode, which will default to a
     // no-op pass through filter if it doesn't get gzip headers where expected.
     if (1 == encoding_types->size()) {
@@ -290,20 +290,20 @@
     return;
   }
 
-  // There are now several cases to handle for an SDCH request.  Foremost, if
+  // There are now several cases to handle for an SDCH request. Foremost, if
   // the outbound request was stripped so as not to advertise support for
   // encodings, we might get back content with no encoding, or (for example)
-  // just gzip.  We have to be sure that any changes we make allow for such
-  // minimal coding to work.  That issue is why we use TENTATIVE filters if we
+  // just gzip. We have to be sure that any changes we make allow for such
+  // minimal coding to work. That issue is why we use TENTATIVE filters if we
   // add any, as those filters sniff the content, and act as pass-through
   // filters if headers are not found.
 
   // If the outbound GET is not modified, then the server will generally try to
-  // send us SDCH encoded content.  As that content returns, there are several
+  // send us SDCH encoded content. As that content returns, there are several
   // corruptions of the header "content-encoding" that proxies may perform (and
-  // have been detected in the wild).  We already dealt with the a honest
+  // have been detected in the wild). We already dealt with the a honest
   // content encoding of "sdch,gzip" being corrupted into "sdch" with on change
-  // of the actual content.  Another common corruption is to either disscard
+  // of the actual content. Another common corruption is to either disscard
   // the accurate content encoding, or to replace it with gzip only (again, with
   // no change in actual content). The last observed corruption it to actually
   // change the content, such as by re-gzipping it, and that may happen along
@@ -328,7 +328,7 @@
   } else {
     // Remarkable case!?!  We advertised an SDCH dictionary, content-encoding
     // was not marked for SDCH processing: Why did the server suggest an SDCH
-    // dictionary in the first place??.  Also, the content isn't
+    // dictionary in the first place??. Also, the content isn't
     // tagged as HTML, despite the fact that SDCH encoding is mostly likely for
     // HTML: Did some anti-virus system strip this tag (sometimes they strip
     // accept-encoding headers on the request)??  Does the content encoding not
@@ -344,9 +344,9 @@
   }
 
   // Leave the existing encoding type to be processed first, and add our
-  // tentative decodings to be done afterwards.  Vodaphone UK reportedyl will
+  // tentative decodings to be done afterwards. Vodaphone UK reportedyl will
   // perform a second layer of gzip encoding atop the server's sdch,gzip
-  // encoding, and then claim that the content encoding is a mere gzip.  As a
+  // encoding, and then claim that the content encoding is a mere gzip. As a
   // result we'll need (in that case) to do the gunzip, plus our tentative
   // gunzip and tentative SDCH decoding.
   // This approach nicely handles the empty() list as well, and should work with
diff --git a/net/filter/filter.h b/net/filter/filter.h
index cec8398..428dc8c 100644
--- a/net/filter/filter.h
+++ b/net/filter/filter.h
@@ -20,22 +20,22 @@
 // through its accessor and fills in stream_buffer_ with pre-filter data, next
 // calls FlushStreamBuffer to notify Filter, then calls ReadFilteredData
 // repeatedly to get all the filtered data. After all data have been filtered
-// and read out, the caller may fill in stream_buffer_ again.  This
+// and read out, the caller may fill in stream_buffer_ again. This
 // WriteBuffer-Flush-Read cycle is repeated until reaching the end of data
 // stream.
 //
 // A return of FILTER_OK from ReadData() means that more data is
 // available to a future ReadData() call and data may not be written
-// into stream_buffer().  A return of FILTER_NEED_MORE_DATA from ReadData()
+// into stream_buffer(). A return of FILTER_NEED_MORE_DATA from ReadData()
 // indicates that no data will be forthcoming from the filter until
 // it receives more input data, and that the buffer at
 // stream_buffer() may be written to.
 //
 // The filter being complete (no more data to provide) may be indicated
 // by either returning FILTER_DONE or by returning FILTER_OK and indicating
-// zero bytes output; consumers understand both those signals.  Consumers
+// zero bytes output; consumers understand both those signals. Consumers
 // are responsible for not calling ReadData() on a filter after one of these
-// signals have been returned.  Note that some filters may never signal that
+// signals have been returned. Note that some filters may never signal that
 // they are done (e.g. a pass-through filter will always
 // say FILTER_NEED_MORE_DATA), so the consumer will also need to
 // recognize the state of |no_more_input_data_available &&
@@ -55,6 +55,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
+#include "net/base/sdch_manager.h"
 
 class GURL;
 
@@ -66,11 +67,19 @@
 
 //------------------------------------------------------------------------------
 // Define an interface class that allows access to contextual information
-// supplied by the owner of this filter.  In the case where there are a chain of
+// supplied by the owner of this filter. In the case where there are a chain of
 // filters, there is only one owner of all the chained filters, and that context
-// is passed to the constructor of all those filters.  To be clear, the context
+// is passed to the constructor of all those filters. To be clear, the context
 // does NOT reflect the position in a chain, or the fact that there are prior
 // or later filters in a chain.
+//
+// TODO(rdsmith): FilterContext is a grab-bag of methods which may or may
+// not be relevant for any particular filter, and it's getting worse over
+// time. In addition, it only supports two filters, SDCH and gzip.
+// It would make more sense to implement FilterContext as a
+// base::SupportsUserData structure to which filter-specific information
+// could be added by whatever the ultimate consumer of the filter chain is,
+// and a particular filter (if included) could access that information.
 class NET_EXPORT_PRIVATE FilterContext {
  public:
   // Enum to control what histograms are emitted near end-of-life of this
@@ -107,14 +116,14 @@
   virtual bool IsDownload() const = 0;
 
   // Was this data flagged as a response to a request with an SDCH dictionary?
-  virtual bool SdchResponseExpected() const = 0;
+  virtual SdchManager::DictionarySet* SdchDictionariesAdvertised() const = 0;
 
   // How many bytes were read from the net or cache so far (and potentially
   // pushed into a filter for processing)?
   virtual int64 GetByteReadCount() const = 0;
 
   // What response code was received with the associated network transaction?
-  // For example: 200 is ok.   4xx are error codes. etc.
+  // For example: 200 is ok.  4xx are error codes. etc.
   virtual int GetResponseCode() const = 0;
 
   // The URLRequestContext associated with the request.
@@ -137,7 +146,7 @@
     FILTER_OK,
     // Read filtered data successfully, and the data in the buffer has been
     // consumed by the filter, but more data is needed in order to continue
-    // filtering.  At this point, the caller is free to reuse the filter
+    // filtering. At this point, the caller is free to reuse the filter
     // buffer to provide more data.
     FILTER_NEED_MORE_DATA,
     // Read filtered data successfully, and filter reaches the end of the data
@@ -169,7 +178,7 @@
   //
   // Note: filter_types is an array of filter types (content encoding types as
   // provided in an HTTP header), which will be chained together serially to do
-  // successive filtering of data.  The types in the vector are ordered based on
+  // successive filtering of data. The types in the vector are ordered based on
   // encoding order, and the filters are chained to operate in the reverse
   // (decoding) order. For example, types[0] = FILTER_TYPE_SDCH,
   // types[1] = FILTER_TYPE_GZIP will cause data to first be gunzip filtered,
@@ -182,7 +191,7 @@
   // initialized.
   static Filter* GZipFactory();
 
-  // External call to obtain data from this filter chain.  If ther is no
+  // External call to obtain data from this filter chain. If ther is no
   // next_filter_, then it obtains data from this specific filter.
   FilterStatus ReadData(char* dest_buffer, int* dest_len);
 
@@ -216,10 +225,10 @@
   static FilterType ConvertEncodingToType(const std::string& filter_type);
 
   // Given a array of encoding_types, try to do some error recovery adjustment
-  // to the list.  This includes handling known bugs in the Apache server (where
+  // to the list. This includes handling known bugs in the Apache server (where
   // redundant gzip encoding is specified), as well as issues regarding SDCH
   // encoding, where various proxies and anti-virus products modify or strip the
-  // encodings.  These fixups require context, which includes whether this
+  // encodings. These fixups require context, which includes whether this
   // response was made to an SDCH request (i.e., an available dictionary was
   // advertised in the GET), as well as the mime type of the content.
   static void FixupEncodingTypes(const FilterContext& filter_context,
@@ -270,8 +279,8 @@
   void InitBuffer(int size);
 
   // A factory helper for creating filters for within a chain of potentially
-  // multiple encodings.  If a chain of filters is created, then this may be
-  // called multiple times during the filter creation process.  In most simple
+  // multiple encodings. If a chain of filters is created, then this may be
+  // called multiple times during the filter creation process. In most simple
   // cases, this is only called once. Returns NULL and cleans up (deleting
   // filter_list) if a new filter can't be constructed.
   static Filter* PrependNewFilter(FilterType type_id,
diff --git a/net/filter/filter_unittest.cc b/net/filter/filter_unittest.cc
index 5b2446c..fcedeaf 100644
--- a/net/filter/filter_unittest.cc
+++ b/net/filter/filter_unittest.cc
@@ -24,9 +24,6 @@
 
 }  // namespace
 
-class FilterTest : public testing::Test {
-};
-
 TEST(FilterTest, ContentTypeId) {
   // Check for basic translation of Content-Encoding, including case variations.
   EXPECT_EQ(Filter::FILTER_TYPE_DEFLATE,
@@ -54,7 +51,7 @@
 // Check various fixups that modify content encoding lists.
 TEST(FilterTest, ApacheGzip) {
   MockFilterContext filter_context;
-  filter_context.SetSdchResponse(false);
+  filter_context.SetSdchResponse(NULL);
 
   // Check that redundant gzip mime type removes only solo gzip encoding.
   const std::string kGzipMime1("application/x-gzip");
@@ -100,7 +97,7 @@
 
 TEST(FilterTest, GzipContentDispositionFilename) {
   MockFilterContext filter_context;
-  filter_context.SetSdchResponse(false);
+  filter_context.SetSdchResponse(NULL);
 
   const std::string kGzipMime("application/x-tar");
   const std::string kContentDisposition("attachment; filename=\"foo.tgz\"");
@@ -119,7 +116,9 @@
   // Handle content encodings including SDCH.
   const std::string kTextHtmlMime("text/html");
   MockFilterContext filter_context;
-  filter_context.SetSdchResponse(true);
+  // Empty handle indicates to filter that SDCH is active.
+  filter_context.SetSdchResponse(
+      SdchManager::CreateEmptyDictionarySetForTesting().Pass());
 
   std::vector<Filter::FilterType> encoding_types;
 
@@ -156,7 +155,8 @@
   // Handle interesting case where entire SDCH encoding assertion "got lost."
   const std::string kTextHtmlMime("text/html");
   MockFilterContext filter_context;
-  filter_context.SetSdchResponse(true);
+  filter_context.SetSdchResponse(
+      SdchManager::CreateEmptyDictionarySetForTesting().Pass());
 
   std::vector<Filter::FilterType> encoding_types;
 
@@ -169,7 +169,7 @@
   EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
 
   // Loss of encoding, but it was an SDCH response with a prefix that says it
-  // was an html type.  Note that it *should* be the case that a precise match
+  // was an html type. Note that it *should* be the case that a precise match
   // with "text/html" we be collected by GetMimeType() and passed in, but we
   // coded the fixup defensively (scanning for a prefix of "text/html", so this
   // is an example which could survive such confusion in the caller).
diff --git a/net/filter/mock_filter_context.cc b/net/filter/mock_filter_context.cc
index 35ab9ee..67012de 100644
--- a/net/filter/mock_filter_context.cc
+++ b/net/filter/mock_filter_context.cc
@@ -11,7 +11,6 @@
 MockFilterContext::MockFilterContext()
     : is_cached_content_(false),
       is_download_(false),
-      is_sdch_response_(false),
       ok_to_call_get_url_(true),
       response_code_(-1),
       context_(new URLRequestContext()) {
@@ -54,8 +53,9 @@
 
 bool MockFilterContext::IsDownload() const { return is_download_; }
 
-bool MockFilterContext::SdchResponseExpected() const {
-  return is_sdch_response_;
+SdchManager::DictionarySet*
+MockFilterContext::SdchDictionariesAdvertised() const {
+  return dictionaries_handle_.get();
 }
 
 int64 MockFilterContext::GetByteReadCount() const { return 0; }
diff --git a/net/filter/mock_filter_context.h b/net/filter/mock_filter_context.h
index 41c9e9e..776a237 100644
--- a/net/filter/mock_filter_context.h
+++ b/net/filter/mock_filter_context.h
@@ -9,6 +9,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "net/base/net_log.h"
+#include "net/base/sdch_manager.h"
 #include "net/filter/filter.h"
 #include "url/gurl.h"
 
@@ -30,15 +31,15 @@
   void SetCached(bool is_cached) { is_cached_content_ = is_cached; }
   void SetDownload(bool is_download) { is_download_ = is_download; }
   void SetResponseCode(int response_code) { response_code_ = response_code; }
-  void SetSdchResponse(bool is_sdch_response) {
-    is_sdch_response_ = is_sdch_response;
+  void SetSdchResponse(scoped_ptr<SdchManager::DictionarySet> handle) {
+    dictionaries_handle_ = handle.Pass();
   }
   URLRequestContext* GetModifiableURLRequestContext() const {
     return context_.get();
   }
 
   // After a URLRequest's destructor is called, some interfaces may become
-  // unstable.  This method is used to signal that state, so we can tag use
+  // unstable. This method is used to signal that state, so we can tag use
   // of those interfaces as coding errors.
   void NukeUnstableInterfaces();
 
@@ -61,8 +62,8 @@
   // Is this a download?
   bool IsDownload() const override;
 
-  // Was this data flagged as a response to a request with an SDCH dictionary?
-  bool SdchResponseExpected() const override;
+  // Handle to dictionaries advertised.
+  SdchManager::DictionarySet* SdchDictionariesAdvertised() const override;
 
   // How many bytes were fed to filter(s) so far?
   int64 GetByteReadCount() const override;
@@ -84,7 +85,7 @@
   base::Time request_time_;
   bool is_cached_content_;
   bool is_download_;
-  bool is_sdch_response_;
+  scoped_ptr<SdchManager::DictionarySet> dictionaries_handle_;
   bool ok_to_call_get_url_;
   int response_code_;
   scoped_ptr<URLRequestContext> context_;
diff --git a/net/filter/sdch_filter.cc b/net/filter/sdch_filter.cc
index d1eb7f4..30392cd 100644
--- a/net/filter/sdch_filter.cc
+++ b/net/filter/sdch_filter.cc
@@ -14,6 +14,7 @@
 #include "base/values.h"
 #include "net/base/sdch_manager.h"
 #include "net/base/sdch_net_log_params.h"
+#include "net/base/sdch_problem_codes.h"
 #include "net/url_request/url_request_context.h"
 
 #include "sdch/open-vcdiff/src/google/vcdecoder.h"
@@ -251,12 +252,12 @@
       // advertisement (so that we are sure we're not hurting anything).
       //
       // Watch out for an error page inserted by the proxy as part of a 40x
-      // error response.  When we see such content molestation, we certainly
+      // error response. When we see such content molestation, we certainly
       // need to fall into the meta-refresh case.
       ResponseCorruptionDetectionCause cause = RESPONSE_NONE;
       if (filter_context_.GetResponseCode() == 404) {
         // We could be more generous, but for now, only a "NOT FOUND" code will
-        // cause a pass through.  All other bad codes will fall into a
+        // cause a pass through. All other bad codes will fall into a
         // meta-refresh.
         LogSdchProblem(SDCH_PASS_THROUGH_404_CODE);
         cause = RESPONSE_404;
@@ -276,13 +277,13 @@
         // error. We were just overly cautious when we added a TENTATIVE_SDCH.
         // We added the sdch coding tag, and it should not have been added.
         // This can happen in server experiments, where the server decides
-        // not to use sdch, even though there is a dictionary.  To be
+        // not to use sdch, even though there is a dictionary. To be
         // conservative, we locally added the tentative sdch (fearing that a
         // proxy stripped it!) and we must now recant (pass through).
         //
         // However.... just to be sure we don't get burned by proxies that
         // re-compress with gzip or other system, we can sniff to see if this
-        // is compressed data etc.  For now, we do nothing, which gets us into
+        // is compressed data etc. For now, we do nothing, which gets us into
         // the meta-refresh result.
         // TODO(jar): Improve robustness by sniffing for valid text that we can
         // actual use re: decoding_status_ = PASS_THROUGH;
@@ -292,8 +293,8 @@
         // The common cause is a restart of the browser, where we try to render
         // cached content that was saved when we had a dictionary.
         cause = RESPONSE_NO_DICTIONARY;
-      } else if (filter_context_.SdchResponseExpected()) {
-        // This is a very corrupt SDCH request response.  We can't decode it.
+      } else if (filter_context_.SdchDictionariesAdvertised()) {
+        // This is a very corrupt SDCH request response. We can't decode it.
         // We'll use a meta-refresh, and get content without asking for SDCH.
         // This will also progressively disable SDCH for this domain.
         cause = RESPONSE_CORRUPT_SDCH;
@@ -377,7 +378,7 @@
 
   if (decoding_status_ != DECODING_IN_PROGRESS) {
     if (META_REFRESH_RECOVERY == decoding_status_) {
-      // Absorb all input data.  We've already output page reload HTML.
+      // Absorb all input data. We've already output page reload HTML.
       next_stream_data_ = NULL;
       stream_data_len_ = 0;
       return FILTER_NEED_MORE_DATA;
@@ -441,25 +442,52 @@
   else
     next_stream_data_ = NULL;
 
-  DCHECK(!dictionary_.get());
+  DCHECK(!dictionary_);
   dictionary_hash_is_plausible_ = true;  // Assume plausible, but check.
 
   SdchProblemCode rv = SDCH_OK;
   if ('\0' == dictionary_hash_[kServerIdLength - 1]) {
-    SdchManager* manager(url_request_context_->sdch_manager());
-    rv = manager->GetVcdiffDictionary(
-        std::string(dictionary_hash_, 0, kServerIdLength - 1), url_,
-        &dictionary_);
-    if (rv == SDCH_DICTIONARY_HASH_NOT_FOUND) {
-      DCHECK(dictionary_hash_.size() == kServerIdLength);
-      // Since dictionary was not found, check to see if hash was even
-      // plausible.
-      for (size_t i = 0; i < kServerIdLength - 1; ++i) {
-        char base64_char = dictionary_hash_[i];
-        if (!isalnum(base64_char) && '-' != base64_char && '_' != base64_char) {
-          rv = SDCH_DICTIONARY_HASH_MALFORMED;
-          dictionary_hash_is_plausible_ = false;
-          break;
+    std::string server_hash(dictionary_hash_, 0, kServerIdLength - 1);
+    SdchManager::DictionarySet* handle =
+        filter_context_.SdchDictionariesAdvertised();
+    if (handle)
+      dictionary_ = handle->GetDictionary(server_hash);
+    if (!dictionary_) {
+      // This is a hack. Naively, the dictionaries available for
+      // decoding should be only the ones advertised. However, there are
+      // cases, specifically resources encoded with old dictionaries living
+      // in the cache, that mean the full set of dictionaries should be made
+      // available for decoding. It's not known how often this happens;
+      // if it happens rarely enough, this code can be removed.
+      //
+      // TODO(rdsmith): Long-term, a better solution is necessary, since
+      // an entry in the cache being encoded with the dictionary doesn't
+      // guarantee that the dictionary is present. That solution probably
+      // involves storing unencoded resources in the cache, but might
+      // involve evicting encoded resources on dictionary removal.
+      // See http://crbug.com/383405.
+      unexpected_dictionary_handle_ =
+          url_request_context_->sdch_manager()->GetDictionarySetByHash(
+              url_, server_hash, &rv);
+      if (unexpected_dictionary_handle_) {
+        dictionary_ = unexpected_dictionary_handle_->GetDictionary(server_hash);
+        // Override SDCH_OK rv; this is still worth logging.
+        rv = (filter_context_.IsCachedContent() ?
+              SDCH_UNADVERTISED_DICTIONARY_USED_CACHED :
+              SDCH_UNADVERTISED_DICTIONARY_USED);
+      } else {
+        // Since dictionary was not found, check to see if hash was
+        // even plausible.
+        DCHECK(dictionary_hash_.size() == kServerIdLength);
+        rv = SDCH_DICTIONARY_HASH_NOT_FOUND;
+        for (size_t i = 0; i < kServerIdLength - 1; ++i) {
+          char base64_char = dictionary_hash_[i];
+          if (!isalnum(base64_char) &&
+              '-' != base64_char && '_' != base64_char) {
+            dictionary_hash_is_plausible_ = false;
+            rv = SDCH_DICTIONARY_HASH_MALFORMED;
+            break;
+          }
         }
       }
     }
@@ -467,12 +495,15 @@
     dictionary_hash_is_plausible_ = false;
     rv = SDCH_DICTIONARY_HASH_MALFORMED;
   }
-  if (rv != SDCH_OK) {
+
+  if (rv != SDCH_OK)
     LogSdchProblem(rv);
+
+  if (!dictionary_) {
     decoding_status_ = DECODING_ERROR;
     return FILTER_ERROR;
   }
-  DCHECK(dictionary_.get());
+
   vcdiff_streaming_decoder_.reset(new open_vcdiff::VCDiffStreamingDecoder);
   vcdiff_streaming_decoder_->SetAllowVcdTarget(false);
   vcdiff_streaming_decoder_->StartDecoding(dictionary_->text().data(),
diff --git a/net/filter/sdch_filter.h b/net/filter/sdch_filter.h
index bc7788c..9541742 100644
--- a/net/filter/sdch_filter.h
+++ b/net/filter/sdch_filter.h
@@ -43,7 +43,7 @@
   FilterStatus ReadFilteredData(char* dest_buffer, int* dest_len) override;
 
  private:
-  // Internal status.  Once we enter an error state, we stop processing data.
+  // Internal status. Once we enter an error state, we stop processing data.
   enum DecodingStatus {
     DECODING_UNINITIALIZED,
     WAITING_FOR_DICTIONARY_SELECTION,
@@ -87,19 +87,19 @@
   // After assembling an entire dictionary hash (the first 9 bytes of the
   // sdch payload, we check to see if it is plausible, meaning it has a null
   // termination, and has 8 characters that are possible in a net-safe base64
-  // encoding.  If the hash is not plausible, then the payload is probably not
+  // encoding. If the hash is not plausible, then the payload is probably not
   // an SDCH encoded bundle, and various error recovery strategies can be
   // attempted.
   bool dictionary_hash_is_plausible_;
 
-  // We hold an in-memory copy of the dictionary during the entire decoding, as
-  // it is used directly by the VC-DIFF decoding system.
-  // That char* data is part of the dictionary_ we hold a reference to.
-  scoped_refptr<SdchManager::Dictionary> dictionary_;
+  // Validity of this pointer is guaranteed by either the FilterContext holding
+  // a containing SdchManager::DictionarySet, or this object holding a
+  // container in |unexpected_dictionary_handle_| below.
+  const SdchManager::Dictionary *dictionary_;
 
   // We keep a copy of the URLRequestContext for use in the destructor, (at
   // which point GetURLRequestContext() will likely return null because of
-  // the disassociation of the URLRequest from the URLRequestJob).  This is
+  // the disassociation of the URLRequest from the URLRequestJob). This is
   // safe because the URLRequestJob (and any filters) are guaranteed to be
   // deleted before the URLRequestContext is destroyed.
   const URLRequestContext* const url_request_context_;
@@ -129,6 +129,11 @@
   // by checking within this mime type (we may do a meta-refresh via html).
   std::string mime_type_;
 
+  // If the response was encoded with a dictionary different than those
+  // advertised (e.g. a cached response using an old dictionary), this
+  // variable preserves that dictionary from deletion during decoding.
+  scoped_ptr<SdchManager::DictionarySet> unexpected_dictionary_handle_;
+
   DISALLOW_COPY_AND_ASSIGN(SdchFilter);
 };
 
diff --git a/net/filter/sdch_filter_unittest.cc b/net/filter/sdch_filter_unittest.cc
index 79b5673..be9790d 100644
--- a/net/filter/sdch_filter_unittest.cc
+++ b/net/filter/sdch_filter_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/test/simple_test_clock.h"
 #include "net/base/io_buffer.h"
 #include "net/filter/mock_filter_context.h"
 #include "net/filter/sdch_filter.h"
@@ -25,12 +26,12 @@
 // Note an SDCH dictionary has extra meta-data before the VCDIFF dictionary.
 static const char kTestVcdiffDictionary[] = "DictionaryFor"
     "SdchCompression1SdchCompression2SdchCompression3SdchCompression\n";
-// Pre-compression test data.  Note that we pad with a lot of highly gzip
-// compressible content to help to exercise the chaining pipeline.  That is why
+// Pre-compression test data. Note that we pad with a lot of highly gzip
+// compressible content to help to exercise the chaining pipeline. That is why
 // there are a PILE of zeros at the start and end.
 // This will ensure that gzip compressed data can be fed to the chain in one
 // gulp, but (with careful selection of intermediate buffers) that it takes
-// several sdch buffers worth of data to satisfy the sdch filter.  See detailed
+// several sdch buffers worth of data to satisfy the sdch filter. See detailed
 // CHECK() calls in FilterChaining test for specifics.
 static const char kTestData[] = "0000000000000000000000000000000000000000000000"
     "0000000000000000000000000000TestData "
@@ -63,8 +64,8 @@
     url_request_context->set_sdch_manager(sdch_manager_.get());
   }
 
-  // Attempt to add a dictionary to the manager; returns whether or not
-  // the attempt succeeded.
+  // Attempt to add a dictionary to the manager and probe for success or
+  // failure.
   bool AddSdchDictionary(const std::string& dictionary_text,
                          const GURL& gurl) {
     return sdch_manager_->AddSdchDictionary(dictionary_text, gurl) == SDCH_OK;
@@ -72,6 +73,13 @@
 
   MockFilterContext* filter_context() { return filter_context_.get(); }
 
+  // Sets both the GURL and the SDCH response for a filter context.
+  void SetupFilterContextWithGURL(GURL url) {
+    filter_context_->SetURL(url);
+    filter_context_->SetSdchResponse(
+        sdch_manager_->GetDictionarySet(url).Pass());
+  }
+
   std::string NewSdchCompressedData(const std::string dictionary) {
     std::string client_hash;
     std::string server_hash;
@@ -108,11 +116,11 @@
 //------------------------------------------------------------------------------
 // Provide a generic helper function for trying to filter data.
 // This function repeatedly calls the filter to process data, until the entire
-// source is consumed.  The return value from the filter is appended to output.
+// source is consumed. The return value from the filter is appended to output.
 // This allows us to vary input and output block sizes in order to test for edge
 // effects (boundary effects?) during the filtering process.
 // This function provides data to the filter in blocks of no-more-than the
-// specified input_block_length.  It allows the filter to fill no more than
+// specified input_block_length. It allows the filter to fill no more than
 // output_buffer_length in any one call to proccess (a.k.a., Read) data, and
 // concatenates all these little output blocks into the singular output string.
 static bool FilterTestData(const std::string& source,
@@ -159,6 +167,19 @@
   return dictionary;
 }
 
+static std::string NewSdchExpiredDictionary(const std::string& domain) {
+  std::string dictionary;
+  if (!domain.empty()) {
+    dictionary.append("Domain: ");
+    dictionary.append(domain);
+    dictionary.append("\n");
+  }
+  dictionary.append("Max-Age: 0\n");
+  dictionary.append("\n");
+  dictionary.append(kTestVcdiffDictionary, sizeof(kTestVcdiffDictionary) - 1);
+  return dictionary;
+}
+
 //------------------------------------------------------------------------------
 
 TEST_F(SdchFilterTest, EmptyInputOk) {
@@ -197,10 +218,10 @@
   EXPECT_EQ(0, output_bytes_or_buffer_size);
   EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status);
 
-  // Partially tear down context.  Anything that goes through request()
+  // Partially tear down context. Anything that goes through request()
   // without checking it for null in the URLRequestJob::HttpFilterContext
-  // implementation is suspect.  Everything that does check it for null should
-  // return null.  This is to test for incorrectly relying on filter_context()
+  // implementation is suspect. Everything that does check it for null should
+  // return null. This is to test for incorrectly relying on filter_context()
   // from the SdchFilter destructor.
   filter_context()->NukeUnstableInterfaces();
 }
@@ -451,7 +472,7 @@
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
-  filter_context()->SetURL(url);
+  SetupFilterContextWithGURL(url);
 
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
@@ -488,7 +509,8 @@
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
-  filter_context()->SetURL(GURL("https://" + kSampleDomain));
+  GURL filter_context_gurl("https://" + kSampleDomain);
+  SetupFilterContextWithGURL(GURL("https://" + kSampleDomain));
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   const size_t feed_block_size(100);
@@ -501,7 +523,7 @@
 
 // Current failsafe TODO/hack refuses to decode any content that doesn't use
 // http as the scheme (see use of DICTIONARY_SELECTED_FOR_NON_HTTP).
-// The following tests this blockage.  Note that blacklisting results, so we
+// The following tests this blockage. Note that blacklisting results, so we
 // we need separate tests for each of these.
 TEST_F(SdchFilterTest, NoDecodeFtp) {
   // Construct a valid SDCH dictionary from a VCDIFF dictionary.
@@ -518,7 +540,7 @@
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
-  filter_context()->SetURL(GURL("ftp://" + kSampleDomain));
+  SetupFilterContextWithGURL(GURL("ftp://" + kSampleDomain));
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   const size_t feed_block_size(100);
@@ -544,7 +566,7 @@
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
-  filter_context()->SetURL(GURL("file://" + kSampleDomain));
+  SetupFilterContextWithGURL(GURL("file://" + kSampleDomain));
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   const size_t feed_block_size(100);
@@ -570,7 +592,7 @@
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
-  filter_context()->SetURL(GURL("about://" + kSampleDomain));
+  SetupFilterContextWithGURL(GURL("about://" + kSampleDomain));
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   const size_t feed_block_size(100);
@@ -596,7 +618,7 @@
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
-  filter_context()->SetURL(GURL("javascript://" + kSampleDomain));
+  SetupFilterContextWithGURL(GURL("javascript://" + kSampleDomain));
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   const size_t feed_block_size(100);
@@ -622,7 +644,7 @@
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
-  filter_context()->SetURL(GURL("http://" + kSampleDomain));
+  SetupFilterContextWithGURL(GURL("http://" + kSampleDomain));
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   const size_t feed_block_size(100);
@@ -651,7 +673,7 @@
   // Decode with content arriving from the "wrong" domain.
   // This tests SdchManager::CanSet().
   GURL wrong_domain_url("http://www.wrongdomain.com");
-  filter_context()->SetURL(wrong_domain_url);
+  SetupFilterContextWithGURL(wrong_domain_url);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types,  *filter_context()));
 
   size_t feed_block_size = 100;
@@ -696,7 +718,7 @@
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
   // Test decode the path data, arriving from a valid path.
-  filter_context()->SetURL(GURL(url_string + path));
+  SetupFilterContextWithGURL(GURL(url_string + path));
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   size_t feed_block_size = 100;
@@ -708,7 +730,7 @@
   EXPECT_EQ(output, expanded_);
 
   // Test decode the path data, arriving from a invalid path.
-  filter_context()->SetURL(GURL(url_string));
+  SetupFilterContextWithGURL(GURL(url_string));
   filter.reset(Filter::Factory(filter_types, *filter_context()));
 
   feed_block_size = 100;
@@ -753,7 +775,7 @@
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
   // Test decode the port data, arriving from a valid port.
-  filter_context()->SetURL(GURL(url_string + ":" + port));
+  SetupFilterContextWithGURL(GURL(url_string + ":" + port));
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   size_t feed_block_size = 100;
@@ -764,7 +786,7 @@
   EXPECT_EQ(output, expanded_);
 
   // Test decode the port data, arriving from a valid (default) port.
-  filter_context()->SetURL(GURL(url_string));  // Default port.
+  SetupFilterContextWithGURL(GURL(url_string));  // Default port.
   filter.reset(Filter::Factory(filter_types, *filter_context()));
 
   feed_block_size = 100;
@@ -775,7 +797,7 @@
   EXPECT_EQ(output, expanded_);
 
   // Test decode the port data, arriving from a invalid port.
-  filter_context()->SetURL(GURL(url_string + ":" + port + "1"));
+  SetupFilterContextWithGURL(GURL(url_string + ":" + port + "1"));
   filter.reset(Filter::Factory(filter_types, *filter_context()));
 
   feed_block_size = 100;
@@ -856,8 +878,8 @@
 };
 
 // Test that filters can be cascaded (chained) so that the output of one filter
-// is processed by the next one.  This is most critical for SDCH, which is
-// routinely followed by gzip (during encoding).  The filter we'll test for will
+// is processed by the next one. This is most critical for SDCH, which is
+// routinely followed by gzip (during encoding). The filter we'll test for will
 // do the gzip decoding first, and then decode the SDCH content.
 TEST_F(SdchFilterTest, FilterChaining) {
   // Construct a valid SDCH dictionary from a VCDIFF dictionary.
@@ -884,7 +906,7 @@
   CHECK_GT(kLargeInputBufferSize, gzip_compressed_sdch.size());
   CHECK_GT(kLargeInputBufferSize, sdch_compressed.size());
   CHECK_GT(kLargeInputBufferSize, expanded_.size());
-  filter_context()->SetURL(url);
+  SetupFilterContextWithGURL(url);
   scoped_ptr<Filter> filter(
       SdchFilterChainingTest::Factory(filter_types, *filter_context(),
                                       kLargeInputBufferSize));
@@ -962,16 +984,15 @@
   filter_types.push_back(Filter::FILTER_TYPE_SDCH);
 
   filter_context()->SetMimeType("anything/mime");
-  filter_context()->SetSdchResponse(true);
+  SetupFilterContextWithGURL(url);
+
   Filter::FixupEncodingTypes(*filter_context(), &filter_types);
   ASSERT_EQ(filter_types.size(), 2u);
   EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH);
   EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH);
 
   // First try with a large buffer (larger than test input, or compressed data).
-  filter_context()->SetURL(url);
-  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
-
+    scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   // Verify that chained filter is waiting for data.
   char tiny_output_buffer[10];
@@ -1020,7 +1041,7 @@
   filter_types.push_back(Filter::FILTER_TYPE_GZIP);
 
   filter_context()->SetMimeType("anything/mime");
-  filter_context()->SetSdchResponse(true);
+  SetupFilterContextWithGURL(url);
   Filter::FixupEncodingTypes(*filter_context(), &filter_types);
   ASSERT_EQ(filter_types.size(), 3u);
   EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE);
@@ -1028,10 +1049,8 @@
   EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP);
 
   // First try with a large buffer (larger than test input, or compressed data).
-  filter_context()->SetURL(url);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
-
   // Verify that chained filter is waiting for data.
   char tiny_output_buffer[10];
   int tiny_output_size = sizeof(tiny_output_buffer);
@@ -1077,17 +1096,15 @@
   std::vector<Filter::FilterType> filter_types;
 
   filter_context()->SetMimeType("anything/mime");
-  filter_context()->SetSdchResponse(true);
+  SetupFilterContextWithGURL(url);
   Filter::FixupEncodingTypes(*filter_context(), &filter_types);
   ASSERT_EQ(filter_types.size(), 2u);
   EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE);
   EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH);
 
   // First try with a large buffer (larger than test input, or compressed data).
-  filter_context()->SetURL(url);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
-
   // Verify that chained filter is waiting for data.
   char tiny_output_buffer[10];
   int tiny_output_size = sizeof(tiny_output_buffer);
@@ -1138,7 +1155,7 @@
   filter_types.push_back(Filter::FILTER_TYPE_GZIP);
 
   filter_context()->SetMimeType("anything/mime");
-  filter_context()->SetSdchResponse(true);
+  SetupFilterContextWithGURL(url);
   Filter::FixupEncodingTypes(*filter_context(), &filter_types);
   ASSERT_EQ(filter_types.size(), 3u);
   EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE);
@@ -1146,7 +1163,6 @@
   EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP);
 
   // First try with a large buffer (larger than test input, or compressed data).
-  filter_context()->SetURL(url);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
 
   // Verify that chained filter is waiting for data.
@@ -1173,4 +1189,58 @@
   EXPECT_EQ(output, expanded_);
 }
 
+// Test to make sure we decode properly with an unexpected dictionary.
+TEST_F(SdchFilterTest, UnexpectedDictionary) {
+  // Setup a dictionary, add it to the filter context, and create a filter
+  // based on that dictionary.
+  const std::string kSampleDomain = "sdchtest.com";
+  std::string dictionary(NewSdchDictionary(kSampleDomain));
+  std::string url_string = "http://" + kSampleDomain;
+  GURL url(url_string);
+  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
+
+  SetupFilterContextWithGURL(url);
+
+  std::vector<Filter::FilterType> filter_types;
+  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
+  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
+
+  // Setup another dictionary, expired. Don't add it to the filter context.
+  // Delete stored dictionaries first to handle platforms which only
+  // have room for a single dictionary.
+  sdch_manager_->ClearData();
+  std::string expired_dictionary(NewSdchExpiredDictionary(kSampleDomain));
+
+  // Don't use the Helper function since its insertion check is indeterminate
+  // for a Max-Age: 0 dictionary.
+  sdch_manager_->AddSdchDictionary(expired_dictionary, url);
+
+  std::string client_hash;
+  std::string server_hash;
+  SdchManager::GenerateHash(expired_dictionary, &client_hash, &server_hash);
+
+  // Make sure Max-Age: 0 shows up as expired.
+  scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock);
+  clock->SetNow(base::Time::Now());
+  clock->Advance(base::TimeDelta::FromMinutes(5));
+  SdchProblemCode problem_code;
+  scoped_ptr<SdchManager::DictionarySet> hash_set(
+      sdch_manager_->GetDictionarySetByHash(
+          url, server_hash, &problem_code).Pass());
+  ASSERT_TRUE(hash_set);
+  ASSERT_EQ(SDCH_OK, problem_code);
+
+  const_cast<SdchManager::Dictionary*>(
+      hash_set->GetDictionary(server_hash))->SetClockForTesting(
+      clock.Pass());
+
+  // Encode output with the second dictionary.
+  std::string sdch_compressed(NewSdchCompressedData(expired_dictionary));
+
+  // See if the filter decodes it.
+  std::string output;
+  EXPECT_TRUE(FilterTestData(sdch_compressed, 100, 100, filter.get(), &output));
+  EXPECT_EQ(expanded_, output);
+}
+
 }  // namespace net
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index 4cbde27..74bd6bf 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -965,14 +965,16 @@
   switch (GetErrorClass(response.status_code)) {
     case ERROR_CLASS_INITIATED:
       return Stop(ERR_INVALID_RESPONSE);
-    case ERROR_CLASS_OK:
-      if (!ExtractPortFromEPSVResponse( response, &data_connection_port_))
+    case ERROR_CLASS_OK: {
+      int port;
+      if (!ExtractPortFromEPSVResponse(response, &port))
         return Stop(ERR_INVALID_RESPONSE);
-      if (data_connection_port_ < 1024 ||
-          !IsPortAllowedByFtp(data_connection_port_))
+      if (port < 1024 || !IsPortAllowedByFtp(port))
         return Stop(ERR_UNSAFE_PORT);
+      data_connection_port_ = static_cast<uint16>(port);
       next_state_ = STATE_DATA_CONNECT;
       break;
+    }
     case ERROR_CLASS_INFO_NEEDED:
       return Stop(ERR_INVALID_RESPONSE);
     case ERROR_CLASS_TRANSIENT_ERROR:
@@ -999,14 +1001,16 @@
   switch (GetErrorClass(response.status_code)) {
     case ERROR_CLASS_INITIATED:
       return Stop(ERR_INVALID_RESPONSE);
-    case ERROR_CLASS_OK:
-      if (!ExtractPortFromPASVResponse(response, &data_connection_port_))
+    case ERROR_CLASS_OK: {
+      int port;
+      if (!ExtractPortFromPASVResponse(response, &port))
         return Stop(ERR_INVALID_RESPONSE);
-      if (data_connection_port_ < 1024 ||
-          !IsPortAllowedByFtp(data_connection_port_))
+      if (port < 1024 || !IsPortAllowedByFtp(port))
         return Stop(ERR_UNSAFE_PORT);
+      data_connection_port_ = static_cast<uint16>(port);
       next_state_ = STATE_DATA_CONNECT;
       break;
+    }
     case ERROR_CLASS_INFO_NEEDED:
       return Stop(ERR_INVALID_RESPONSE);
     case ERROR_CLASS_TRANSIENT_ERROR:
diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h
index c8ed550..e350e16 100644
--- a/net/ftp/ftp_network_transaction.h
+++ b/net/ftp/ftp_network_transaction.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <utility>
 
+#include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
@@ -245,7 +246,7 @@
   // with any trailing slash removed.
   std::string current_remote_directory_;
 
-  int data_connection_port_;
+  uint16 data_connection_port_;
 
   ClientSocketFactory* socket_factory_;
 
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 20ffdd1..8cddaf5 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -1027,11 +1027,8 @@
     return OK;
   }
 
-  HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(),
-                                       request_->url.EffectiveIntPort());
-  ProcessAlternateProtocol(session_,
-                           *response_.headers.get(),
-                           endpoint);
+  ProcessAlternateProtocol(session_, *response_.headers.get(),
+                           HostPortPair::FromURL(request_->url));
 
   int rv = HandleAuthChallenge();
   if (rv != OK)
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index d08d162..878406e 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -268,12 +268,15 @@
     base::MessageLoop::current()->RunUntilIdle();
   }
 
+  const char* GetAlternateProtocolFromParam() {
+    return
+        AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
+  }
+
   // This is the expected return from a current server advertising SPDY.
   std::string GetAlternateProtocolHttpHeader() {
-    return
-        std::string("Alternate-Protocol: 443:") +
-        AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
-        "\r\n\r\n";
+    return std::string("Alternate-Protocol: 443:") +
+        GetAlternateProtocolFromParam() + "\r\n\r\n";
   }
 
   // Either |write_failure| specifies a write failure or |read_failure|
@@ -407,8 +410,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     HttpNetworkTransactionTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 namespace {
 
@@ -10107,10 +10109,12 @@
   };
   MockRead data_reads_1[] = {
     MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
-    MockRead("HTTP/1.1 200 OK\r\n"
-             "Alternate-Protocol: 443:npn-spdy/2\r\n"
-             "Proxy-Connection: close\r\n"
-             "\r\n"),
+    MockRead("HTTP/1.1 200 OK\r\n"),
+    MockRead("Alternate-Protocol: 443:"),
+    MockRead(GetAlternateProtocolFromParam()),
+    MockRead("\r\n"),
+    MockRead("Proxy-Connection: close\r\n"),
+    MockRead("\r\n"),
   };
   StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
                                   data_writes_1, arraysize(data_writes_1));
@@ -11402,8 +11406,7 @@
   // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
   SpdyHeaderBlock req2_block;
   req2_block[spdy_util_.GetMethodKey()] = "GET";
-  req2_block[spdy_util_.GetPathKey()] =
-      spdy_util_.is_spdy2() ? http_url.c_str() : "/";
+  req2_block[spdy_util_.GetPathKey()] = "/";
   req2_block[spdy_util_.GetHostKey()] = "www.google.com:443";
   req2_block[spdy_util_.GetSchemeKey()] = "http";
   spdy_util_.MaybeAddVersionHeader(&req2_block);
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 694d394..bdaf57f 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -42,7 +42,7 @@
 struct HttpProxyClientSocketPoolTestParams {
   HttpProxyClientSocketPoolTestParams()
       : proxy_type(HTTP),
-        protocol(kProtoSPDY3) {}
+        protocol(kProtoSPDY31) {}
 
   HttpProxyClientSocketPoolTestParams(
       HttpProxyType proxy_type,
@@ -342,12 +342,6 @@
     HttpProxyClientSocketPoolTests,
     HttpProxyClientSocketPoolTest,
     ::testing::Values(
-        HttpProxyClientSocketPoolTestParams(HTTP, kProtoDeprecatedSPDY2),
-        HttpProxyClientSocketPoolTestParams(HTTPS, kProtoDeprecatedSPDY2),
-        HttpProxyClientSocketPoolTestParams(SPDY, kProtoDeprecatedSPDY2),
-        HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY3),
-        HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY3),
-        HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY3),
         HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY31),
         HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY31),
         HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY31),
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc
index 65ecd11..1bf541b 100644
--- a/net/http/http_server_properties_impl.cc
+++ b/net/http/http_server_properties_impl.cc
@@ -67,7 +67,7 @@
   }
 
   // Attempt to find canonical servers.
-  int canonical_ports[] = { 80, 443 };
+  uint16 canonical_ports[] = { 80, 443 };
   for (size_t i = 0; i < canonical_suffixes_.size(); ++i) {
     std::string canonical_suffix = canonical_suffixes_[i];
     for (size_t j = 0; j < arraysize(canonical_ports); ++j) {
@@ -301,8 +301,14 @@
     const HostPortPair& server) {
   AlternateProtocolMap::iterator it = alternate_protocol_map_.Get(server);
   if (it == alternate_protocol_map_.end()) {
-    LOG(DFATAL) << "Trying to mark unknown alternate protocol broken.";
-    return;
+    if (!HasAlternateProtocol(server)) {
+      LOG(DFATAL) << "Trying to mark unknown alternate protocol broken.";
+      return;
+    }
+    // This server's alternate protocol information is coming from a canonical
+    // server. Add an entry in the map for this server explicitly so that
+    // it can be marked as broken.
+    it = alternate_protocol_map_.Put(server, GetAlternateProtocol(server));
   }
   it->second.is_broken = true;
   int count = ++broken_alternate_protocol_map_[server];
diff --git a/net/http/http_server_properties_impl_unittest.cc b/net/http/http_server_properties_impl_unittest.cc
index 1c016b7..3d1bacb 100644
--- a/net/http/http_server_properties_impl_unittest.cc
+++ b/net/http/http_server_properties_impl_unittest.cc
@@ -475,6 +475,23 @@
   EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
 }
 
+TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken2) {
+  HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
+  HostPortPair canonical_port_pair("bar.c.youtube.com", 80);
+
+  AlternateProtocolInfo canonical_protocol(1234, QUIC, 1);
+
+  impl_.SetAlternateProtocol(canonical_port_pair,
+                             canonical_protocol.port,
+                             canonical_protocol.protocol,
+                             canonical_protocol.probability);
+
+  impl_.SetBrokenAlternateProtocol(test_host_port_pair);
+  AlternateProtocolInfo alternate =
+      impl_.GetAlternateProtocol(test_host_port_pair);
+  EXPECT_TRUE(alternate.is_broken);
+}
+
 TEST_F(AlternateProtocolServerPropertiesTest, ClearWithCanonical) {
   HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
   HostPortPair canonical_port_pair("bar.c.youtube.com", 80);
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index 41b70b1..5773129 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -449,9 +449,8 @@
         continue;
       }
 
-      net::AlternateProtocolInfo port_alternate_protocol(port,
-                                                         protocol,
-                                                         probability);
+      net::AlternateProtocolInfo port_alternate_protocol(
+          static_cast<uint16>(port), protocol, probability);
       alternate_protocol_map->Put(server, port_alternate_protocol);
       ++count;
     } while (false);
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index 29d9b26..f84b80c 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -60,7 +60,7 @@
     }
 
     if (!base::StringToInt(port_protocol_vector[0], &port) ||
-        port <= 0 || port >= 1 << 16) {
+        port == 0 || !IsPortValid(port)) {
       DVLOG(1) << kAlternateProtocolHeader
                << " header has unrecognizable port: "
                << port_protocol_vector[0];
@@ -94,8 +94,8 @@
       return;
   }
 
-  http_server_properties->SetAlternateProtocol(host_port, port, protocol,
-                                               probability);
+  http_server_properties->SetAlternateProtocol(
+      host_port, static_cast<uint16>(port), protocol, probability);
 }
 
 GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index 8304694..8b12dba 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -184,8 +184,7 @@
   if (original_url.SchemeIs("ftp"))
     return kNoAlternateProtocol;
 
-  HostPortPair origin = HostPortPair(original_url.HostNoBrackets(),
-                                     original_url.EffectiveIntPort());
+  HostPortPair origin = HostPortPair::FromURL(original_url);
 
   HttpServerProperties& http_server_properties =
       *session_->http_server_properties();
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index a11dd2e..8369443 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -132,13 +132,10 @@
 
 int HttpStreamFactoryImpl::Job::Preconnect(int num_streams) {
   DCHECK_GT(num_streams, 0);
-  HostPortPair origin_server =
-      HostPortPair(request_info_.url.HostNoBrackets(),
-                   request_info_.url.EffectiveIntPort());
   base::WeakPtr<HttpServerProperties> http_server_properties =
       session_->http_server_properties();
-  if (http_server_properties &&
-      http_server_properties->SupportsSpdy(origin_server)) {
+  if (http_server_properties && http_server_properties->SupportsSpdy(
+      HostPortPair::FromURL(request_info_.url))) {
     num_streams_ = 1;
   } else {
     num_streams_ = num_streams;
@@ -617,8 +614,7 @@
 }
 
 int HttpStreamFactoryImpl::Job::DoStart() {
-  int port = request_info_.url.EffectiveIntPort();
-  origin_ = HostPortPair(request_info_.url.HostNoBrackets(), port);
+  origin_ = HostPortPair::FromURL(request_info_.url);
   origin_url_ = stream_factory_->ApplyHostMappingRules(
       request_info_.url, &origin_);
 
@@ -628,14 +624,14 @@
                                  priority_));
 
   // Don't connect to restricted ports.
-  bool is_port_allowed = IsPortAllowedByDefault(port);
+  bool is_port_allowed = IsPortAllowedByDefault(origin_.port());
   if (request_info_.url.SchemeIs("ftp")) {
     // Never share connection with other jobs for FTP requests.
     DCHECK(!waiting_job_);
 
-    is_port_allowed = IsPortAllowedByFtp(port);
+    is_port_allowed = IsPortAllowedByFtp(origin_.port());
   }
-  if (!is_port_allowed && !IsPortAllowedByOverride(port)) {
+  if (!is_port_allowed && !IsPortAllowedByOverride(origin_.port())) {
     if (waiting_job_) {
       waiting_job_->Resume(this);
       waiting_job_ = NULL;
diff --git a/net/http/http_stream_factory_impl_request_unittest.cc b/net/http/http_stream_factory_impl_request_unittest.cc
index 587358d..32900f9 100644
--- a/net/http/http_stream_factory_impl_request_unittest.cc
+++ b/net/http/http_stream_factory_impl_request_unittest.cc
@@ -19,8 +19,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     HttpStreamFactoryImplRequestTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 namespace {
 
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index 68e9114..4ac5467 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -424,8 +424,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     HttpStreamFactoryTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 TEST_P(HttpStreamFactoryTest, PreconnectDirect) {
   for (size_t i = 0; i < arraysize(kTests); ++i) {
diff --git a/net/net.gyp b/net/net.gyp
index 3c9a520..da91a92 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -876,8 +876,12 @@
         '../testing/gmock.gyp:gmock',
       ],
       'sources': [
+        'base/captured_net_log_entry.cc',
+        'base/captured_net_log_entry.h',
         'base/capturing_net_log.cc',
         'base/capturing_net_log.h',
+        'base/capturing_net_log_observer.cc',
+        'base/capturing_net_log_observer.h',
         'base/load_timing_info_test_util.cc',
         'base/load_timing_info_test_util.h',
         'base/mock_file_stream.cc',
diff --git a/net/net.gypi b/net/net.gypi
index 337f016..cc9ff35 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -1236,8 +1236,8 @@
       'websockets/websocket_frame_parser.h',
       'websockets/websocket_handshake_constants.cc',
       'websockets/websocket_handshake_constants.h',
-      'websockets/websocket_handshake_handler.cc',
-      'websockets/websocket_handshake_handler.h',
+      'websockets/websocket_handshake_challenge.cc',
+      'websockets/websocket_handshake_challenge.h',
       'websockets/websocket_handshake_request_info.cc',
       'websockets/websocket_handshake_request_info.h',
       'websockets/websocket_handshake_response_info.cc',
@@ -1709,7 +1709,7 @@
       'websockets/websocket_extension_parser_test.cc',
       'websockets/websocket_frame_parser_test.cc',
       'websockets/websocket_frame_test.cc',
-      'websockets/websocket_handshake_handler_test.cc',
+      'websockets/websocket_handshake_challenge_test.cc',
       'websockets/websocket_handshake_stream_create_helper_test.cc',
       'websockets/websocket_inflater_test.cc',
       'websockets/websocket_stream_test.cc',
diff --git a/net/proxy/network_delegate_error_observer_unittest.cc b/net/proxy/network_delegate_error_observer_unittest.cc
index 5d2c501..da87f8d 100644
--- a/net/proxy/network_delegate_error_observer_unittest.cc
+++ b/net/proxy/network_delegate_error_observer_unittest.cc
@@ -77,10 +77,6 @@
   bool OnCanThrottleRequest(const URLRequest& request) const override {
     return false;
   }
-  int OnBeforeSocketStreamConnect(SocketStream* stream,
-                                  const CompletionCallback& callback) override {
-    return OK;
-  }
 
   bool got_pac_error_;
 };
diff --git a/net/proxy/proxy_config_service_android.cc b/net/proxy/proxy_config_service_android.cc
index f1a0b6c..50407fe 100644
--- a/net/proxy/proxy_config_service_android.cc
+++ b/net/proxy/proxy_config_service_android.cc
@@ -197,7 +197,8 @@
       : jni_delegate_(this),
         network_task_runner_(network_task_runner),
         jni_task_runner_(jni_task_runner),
-        get_property_callback_(get_property_callback) {
+        get_property_callback_(get_property_callback),
+        exclude_pac_url_(false) {
   }
 
   void SetupJNI() {
@@ -271,13 +272,22 @@
                               const std::vector<std::string>& exclusion_list) {
     DCHECK(OnJNIThread());
     ProxyConfig proxy_config;
-    CreateStaticProxyConfig(host, port, pac_url, exclusion_list, &proxy_config);
+    if (exclude_pac_url_) {
+      CreateStaticProxyConfig(host, port, "", exclusion_list, &proxy_config);
+    } else {
+      CreateStaticProxyConfig(host, port, pac_url, exclusion_list,
+          &proxy_config);
+    }
     network_task_runner_->PostTask(
         FROM_HERE,
         base::Bind(
             &Delegate::SetNewConfigOnNetworkThread, this, proxy_config));
   }
 
+  void set_exclude_pac_url(bool enabled) {
+    exclude_pac_url_ = enabled;
+  }
+
  private:
   friend class base::RefCountedThreadSafe<Delegate>;
 
@@ -344,6 +354,7 @@
   scoped_refptr<base::SequencedTaskRunner> jni_task_runner_;
   GetPropertyCallback get_property_callback_;
   ProxyConfig proxy_config_;
+  bool exclude_pac_url_;
 
   DISALLOW_COPY_AND_ASSIGN(Delegate);
 };
@@ -366,6 +377,10 @@
   return RegisterNativesImpl(env);
 }
 
+void ProxyConfigServiceAndroid::set_exclude_pac_url(bool enabled) {
+  delegate_->set_exclude_pac_url(enabled);
+}
+
 void ProxyConfigServiceAndroid::AddObserver(Observer* observer) {
   delegate_->AddObserver(observer);
 }
diff --git a/net/proxy/proxy_config_service_android.h b/net/proxy/proxy_config_service_android.h
index d642d37..cb15bc5 100644
--- a/net/proxy/proxy_config_service_android.h
+++ b/net/proxy/proxy_config_service_android.h
@@ -64,6 +64,11 @@
   // Register JNI bindings.
   static bool Register(JNIEnv* env);
 
+  // Android provides a local HTTP proxy that does PAC resolution. When this
+  // setting is enabled, the proxy config service ignores the PAC URL and uses
+  // the local proxy for all proxy resolution.
+  void set_exclude_pac_url(bool enabled);
+
   // ProxyConfigService:
   // Called only on the network thread.
   virtual void AddObserver(Observer* observer) override;
diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc
index 24fbe9e..963153d 100644
--- a/net/proxy/proxy_resolver_v8.cc
+++ b/net/proxy/proxy_resolver_v8.cc
@@ -196,7 +196,7 @@
     return false;
 
   v8::HandleScope scope(isolate);
-  v8::Local<v8::String> str_object = object->ToString();
+  v8::Local<v8::String> str_object = object->ToString(isolate);
   if (str_object.IsEmpty())
     return false;
   *utf16_result = V8StringToUTF16(str_object);
@@ -211,7 +211,8 @@
   if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString())
     return false;
 
-  const base::string16 hostname_utf16 = V8StringToUTF16(args[0]->ToString());
+  const base::string16 hostname_utf16 =
+      V8StringToUTF16(v8::Local<v8::String>::Cast(args[0]));
 
   // If the hostname is already in ASCII, simply return it as is.
   if (base::IsStringASCII(hostname_utf16)) {
@@ -393,7 +394,7 @@
       return ERR_PAC_SCRIPT_FAILED;
     }
 
-    base::string16 ret_str = V8StringToUTF16(ret->ToString());
+    base::string16 ret_str = V8StringToUTF16(v8::Local<v8::String>::Cast(ret));
 
     if (!base::IsStringASCII(ret_str)) {
       // TODO(eroman): Rather than failing when a wide string is returned, we
@@ -656,7 +657,8 @@
       return;
     }
 
-    std::string ip_address_list = V8StringToUTF8(args[0]->ToString());
+    std::string ip_address_list =
+        V8StringToUTF8(v8::Local<v8::String>::Cast(args[0]));
     if (!base::IsStringASCII(ip_address_list)) {
       args.GetReturnValue().SetNull();
       return;
@@ -681,12 +683,14 @@
       return;
     }
 
-    std::string ip_address = V8StringToUTF8(args[0]->ToString());
+    std::string ip_address =
+        V8StringToUTF8(v8::Local<v8::String>::Cast(args[0]));
     if (!base::IsStringASCII(ip_address)) {
       args.GetReturnValue().Set(false);
       return;
     }
-    std::string ip_prefix = V8StringToUTF8(args[1]->ToString());
+    std::string ip_prefix =
+        V8StringToUTF8(v8::Local<v8::String>::Cast(args[1]));
     if (!base::IsStringASCII(ip_prefix)) {
       args.GetReturnValue().Set(false);
       return;
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc
index 2073d00..4c5bd4c 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -179,11 +179,6 @@
     return false;
   }
 
-  int OnBeforeSocketStreamConnect(SocketStream* stream,
-                                  const CompletionCallback& callback) override {
-    return OK;
-  }
-
   DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
 };
 
diff --git a/net/proxy/proxy_server.cc b/net/proxy/proxy_server.cc
index 0b9ba67..78d5c3e 100644
--- a/net/proxy/proxy_server.cc
+++ b/net/proxy/proxy_server.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/basictypes.h"
 #include "base/strings/string_util.h"
 #include "net/base/net_util.h"
 #include "net/http/http_util.h"
@@ -238,7 +239,7 @@
     if (port == -1)
       port = GetDefaultPortForScheme(scheme);
 
-    host_port_pair = HostPortPair(host, port);
+    host_port_pair = HostPortPair(host, static_cast<uint16>(port));
   }
 
   return ProxyServer(scheme, host_port_pair);
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc
index 8073c5b..7e9f81a 100644
--- a/net/quic/congestion_control/pacing_sender.cc
+++ b/net/quic/congestion_control/pacing_sender.cc
@@ -27,6 +27,11 @@
   sender_->SetFromConfig(config, is_server, using_pacing);
 }
 
+void PacingSender::ResumeConnectionState(
+    const CachedNetworkParameters& cached_network_params) {
+  sender_->ResumeConnectionState(cached_network_params);
+}
+
 void PacingSender::SetNumEmulatedConnections(int num_connections) {
   sender_->SetNumEmulatedConnections(num_connections);
 }
diff --git a/net/quic/congestion_control/pacing_sender.h b/net/quic/congestion_control/pacing_sender.h
index 4eb3dab..d7d3b2d 100644
--- a/net/quic/congestion_control/pacing_sender.h
+++ b/net/quic/congestion_control/pacing_sender.h
@@ -16,6 +16,7 @@
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/crypto/cached_network_parameters.h"
 #include "net/quic/quic_bandwidth.h"
 #include "net/quic/quic_config.h"
 #include "net/quic/quic_protocol.h"
@@ -38,6 +39,8 @@
   void SetFromConfig(const QuicConfig& config,
                      bool is_server,
                      bool using_pacing) override;
+  void ResumeConnectionState(
+      const CachedNetworkParameters& cached_network_params) override;
   void SetNumEmulatedConnections(int num_connections) override;
   void OnCongestionEvent(bool rtt_updated,
                          QuicByteCount bytes_in_flight,
@@ -63,6 +66,7 @@
   bool InRecovery() const override;
   QuicByteCount GetSlowStartThreshold() const override;
   CongestionControlType GetCongestionControlType() const override;
+  // End implementation of SendAlgorithmInterface.
 
  private:
   scoped_ptr<SendAlgorithmInterface> sender_;  // Underlying sender.
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h
index 7195f81..322ff1d 100644
--- a/net/quic/congestion_control/send_algorithm_interface.h
+++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -12,6 +12,7 @@
 
 #include "base/basictypes.h"
 #include "net/base/net_export.h"
+#include "net/quic/crypto/cached_network_parameters.h"
 #include "net/quic/quic_bandwidth.h"
 #include "net/quic/quic_clock.h"
 #include "net/quic/quic_config.h"
@@ -113,6 +114,10 @@
   virtual QuicByteCount GetSlowStartThreshold() const = 0;
 
   virtual CongestionControlType GetCongestionControlType() const = 0;
+
+  // Called by the Session when we get a bandwidth estimate from the client.
+  virtual void ResumeConnectionState(
+      const CachedNetworkParameters& cached_network_params) = 0;
 };
 
 }  // namespace net
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index 2d0efd7..5fa1559 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -27,13 +27,12 @@
 const uint32 kDefaultNumConnections = 2;  // N-connection emulation.
 }  // namespace
 
-TcpCubicSender::TcpCubicSender(
-    const QuicClock* clock,
-    const RttStats* rtt_stats,
-    bool reno,
-    QuicPacketCount initial_tcp_congestion_window,
-    QuicPacketCount max_tcp_congestion_window,
-    QuicConnectionStats* stats)
+TcpCubicSender::TcpCubicSender(const QuicClock* clock,
+                               const RttStats* rtt_stats,
+                               bool reno,
+                               QuicPacketCount initial_tcp_congestion_window,
+                               QuicPacketCount max_tcp_congestion_window,
+                               QuicConnectionStats* stats)
     : hybrid_slow_start_(clock),
       cubic_(clock, stats),
       rtt_stats_(rtt_stats),
@@ -49,8 +48,8 @@
       slowstart_threshold_(max_tcp_congestion_window),
       previous_slowstart_threshold_(0),
       last_cutback_exited_slowstart_(false),
-      max_tcp_congestion_window_(max_tcp_congestion_window) {
-}
+      max_tcp_congestion_window_(max_tcp_congestion_window),
+      clock_(clock) {}
 
 TcpCubicSender::~TcpCubicSender() {
   UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_);
@@ -73,6 +72,26 @@
   }
 }
 
+void TcpCubicSender::ResumeConnectionState(
+    const CachedNetworkParameters& cached_network_params) {
+  // If the previous bandwidth estimate is less than an hour old, store in
+  // preparation for doing bandwidth resumption.
+  int64 seconds_since_estimate =
+      clock_->WallNow().ToUNIXSeconds() - cached_network_params.timestamp();
+  if (seconds_since_estimate > kNumSecondsPerHour) {
+    return;
+  }
+
+  QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(
+      cached_network_params.bandwidth_estimate_bytes_per_second());
+  QuicTime::Delta rtt_ms =
+      QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms());
+  congestion_window_ = bandwidth.ToBytesPerPeriod(rtt_ms) / kMaxPacketSize;
+
+  // TODO(rjshade): Set appropriate CWND when previous connection was in slow
+  // start at time of estimate.
+}
+
 void TcpCubicSender::SetNumEmulatedConnections(int num_connections) {
   num_connections_ = max(1, num_connections);
   cubic_.SetNumConnections(num_connections_);
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h
index a7507a2..eeb9331 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -15,6 +15,7 @@
 #include "net/quic/congestion_control/hybrid_slow_start.h"
 #include "net/quic/congestion_control/prr_sender.h"
 #include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/crypto/cached_network_parameters.h"
 #include "net/quic/quic_bandwidth.h"
 #include "net/quic/quic_connection_stats.h"
 #include "net/quic/quic_protocol.h"
@@ -43,6 +44,8 @@
   void SetFromConfig(const QuicConfig& config,
                      bool is_server,
                      bool using_pacing) override;
+  void ResumeConnectionState(
+      const CachedNetworkParameters& cached_network_params) override;
   void SetNumEmulatedConnections(int num_connections) override;
   void OnCongestionEvent(bool rtt_updated,
                          QuicByteCount bytes_in_flight,
@@ -130,6 +133,8 @@
   // Maximum number of outstanding packets for tcp.
   QuicPacketCount max_tcp_congestion_window_;
 
+  const QuicClock* clock_;
+
   DISALLOW_COPY_AND_ASSIGN(TcpCubicSender);
 };
 
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc
index 427dd8c..e4737eb 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -701,5 +701,32 @@
   EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
 }
 
+TEST_F(TcpCubicSenderTest, BandwidthResumption) {
+  // Test that when provided with CachedNetworkParameters and opted in to the
+  // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
+  // appropriately.
+
+  // Set some common values.
+  CachedNetworkParameters cached_network_params;
+  const QuicPacketCount kNumberOfPackets = 123;
+  const int kBandwidthEstimateBytesPerSecond =
+      kNumberOfPackets * kMaxPacketSize;
+  cached_network_params.set_bandwidth_estimate_bytes_per_second(
+      kBandwidthEstimateBytesPerSecond);
+  cached_network_params.set_min_rtt_ms(1000);
+
+  // Ensure that an old estimate is not used for bandwidth resumption.
+  cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() -
+                                      (kNumSecondsPerHour + 1));
+  sender_->ResumeConnectionState(cached_network_params);
+  EXPECT_EQ(10u, sender_->congestion_window());
+
+  // If the estimate is new enough, make sure it is used.
+  cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() -
+                                      (kNumSecondsPerHour - 1));
+  sender_->ResumeConnectionState(cached_network_params);
+  EXPECT_EQ(kNumberOfPackets, sender_->congestion_window());
+}
+
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/congestion_control/tcp_loss_algorithm.cc b/net/quic/congestion_control/tcp_loss_algorithm.cc
index 6cf56d8..9366105 100644
--- a/net/quic/congestion_control/tcp_loss_algorithm.cc
+++ b/net/quic/congestion_control/tcp_loss_algorithm.cc
@@ -40,7 +40,7 @@
       continue;
     }
 
-    LOG_IF(DFATAL, it->nack_count == 0)
+    LOG_IF(DFATAL, it->nack_count == 0 && it->sent_time.IsInitialized())
         << "All packets less than largest observed should have been nacked."
         << "sequence_number:" << sequence_number
         << " largest_observed:" << largest_observed;
diff --git a/net/quic/congestion_control/tcp_loss_algorithm_test.cc b/net/quic/congestion_control/tcp_loss_algorithm_test.cc
index 5819fb1..fe6a6ea 100644
--- a/net/quic/congestion_control/tcp_loss_algorithm_test.cc
+++ b/net/quic/congestion_control/tcp_loss_algorithm_test.cc
@@ -12,8 +12,14 @@
 #include "net/quic/test_tools/mock_clock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using std::vector;
+
 namespace net {
 namespace test {
+namespace {
+
+// Default packet length.
+const uint32 kDefaultLength = 1000;
 
 class TcpLossAlgorithmTest : public ::testing::Test {
  protected:
@@ -24,9 +30,16 @@
                          clock_.Now());
   }
 
+  ~TcpLossAlgorithmTest() override {
+    STLDeleteElements(&packets_);
+  }
+
   void SendDataPacket(QuicPacketSequenceNumber sequence_number) {
+    packets_.push_back(QuicPacket::NewDataPacket(
+        nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
+        PACKET_1BYTE_SEQUENCE_NUMBER));
     SerializedPacket packet(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
-                            nullptr, 0, new RetransmittableFrames());
+                            packets_.back(), 0, new RetransmittableFrames());
     unacked_packets_.AddSentPacket(packet, 0, NOT_RETRANSMISSION, clock_.Now(),
                                    1000, true);
   }
@@ -43,6 +56,7 @@
     }
   }
 
+  vector<QuicPacket*> packets_;
   QuicUnackedPacketMap unacked_packets_;
   TCPLossAlgorithm loss_algorithm_;
   RttStats rtt_stats_;
@@ -179,5 +193,6 @@
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
+}  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/congestion_control/time_loss_algorithm.cc b/net/quic/congestion_control/time_loss_algorithm.cc
index 9dd9ae9..b5f90b7 100644
--- a/net/quic/congestion_control/time_loss_algorithm.cc
+++ b/net/quic/congestion_control/time_loss_algorithm.cc
@@ -46,8 +46,10 @@
     if (!it->in_flight) {
       continue;
     }
-    LOG_IF(DFATAL, it->nack_count == 0)
-        << "All packets less than largest observed should have been nacked.";
+    LOG_IF(DFATAL, it->nack_count == 0 && it->sent_time.IsInitialized())
+        << "All packets less than largest observed should have been nacked."
+        << "sequence_number:" << sequence_number
+        << " largest_observed:" << largest_observed;
 
     // Packets are sent in order, so break when we haven't waited long enough
     // to lose any more packets and leave the loss_time_ set for the timeout.
diff --git a/net/quic/congestion_control/time_loss_algorithm_test.cc b/net/quic/congestion_control/time_loss_algorithm_test.cc
index b964d28..1e9b7e5 100644
--- a/net/quic/congestion_control/time_loss_algorithm_test.cc
+++ b/net/quic/congestion_control/time_loss_algorithm_test.cc
@@ -12,8 +12,14 @@
 #include "net/quic/test_tools/mock_clock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using std::vector;
+
 namespace net {
 namespace test {
+namespace {
+
+// Default packet length.
+const uint32 kDefaultLength = 1000;
 
 class TimeLossAlgorithmTest : public ::testing::Test {
  protected:
@@ -24,9 +30,16 @@
                          clock_.Now());
   }
 
+  ~TimeLossAlgorithmTest() override {
+    STLDeleteElements(&packets_);
+  }
+
   void SendDataPacket(QuicPacketSequenceNumber sequence_number) {
+    packets_.push_back(QuicPacket::NewDataPacket(
+        nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
+        PACKET_1BYTE_SEQUENCE_NUMBER));
     SerializedPacket packet(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
-                            nullptr, 0, new RetransmittableFrames());
+                            packets_.back(), 0, new RetransmittableFrames());
     unacked_packets_.AddSentPacket(packet, 0, NOT_RETRANSMISSION, clock_.Now(),
                                    1000, true);
   }
@@ -43,6 +56,7 @@
     }
   }
 
+  vector<QuicPacket*> packets_;
   QuicUnackedPacketMap unacked_packets_;
   TimeLossAlgorithm loss_algorithm_;
   RttStats rtt_stats_;
@@ -134,5 +148,6 @@
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
+}  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/crypto/common_cert_set.cc b/net/quic/crypto/common_cert_set.cc
index 09379f3..b2ea3a7 100644
--- a/net/quic/crypto/common_cert_set.cc
+++ b/net/quic/crypto/common_cert_set.cc
@@ -153,7 +153,7 @@
 
  private:
   CommonCertSetsQUIC() {}
-  virtual ~CommonCertSetsQUIC() {}
+  ~CommonCertSetsQUIC() override {}
 
   friend struct DefaultSingletonTraits<CommonCertSetsQUIC>;
   DISALLOW_COPY_AND_ASSIGN(CommonCertSetsQUIC);
diff --git a/net/quic/crypto/crypto_handshake_message.cc b/net/quic/crypto/crypto_handshake_message.cc
index 9125968..23e8ea2 100644
--- a/net/quic/crypto/crypto_handshake_message.cc
+++ b/net/quic/crypto/crypto_handshake_message.cc
@@ -302,8 +302,9 @@
                             static_cast<int>(it->second.size()));
         done = true;
         break;
+      case kSNI:
       case kUAID:
-        ret += it->second;
+        ret += "\"" + it->second + "\"";
         done = true;
         break;
     }
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h
index d010776..57a5508 100644
--- a/net/quic/crypto/crypto_protocol.h
+++ b/net/quic/crypto/crypto_protocol.h
@@ -71,6 +71,9 @@
 // FEC options
 const QuicTag kFHDR = TAG('F', 'H', 'D', 'R');   // FEC protect headers
 
+// Enable bandwidth resumption experiment.
+const QuicTag kBWRE = TAG('B', 'W', 'R', 'E');  // Bandwidth resumption.
+
 // Proof types (i.e. certificate types)
 // NOTE: although it would be silly to do so, specifying both kX509 and kX59R
 // is allowed and is equivalent to specifying only kX509.
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 274099c..97d6c3b 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -13,6 +13,7 @@
 #include "base/values.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
+#include "net/base/network_activity_monitor.h"
 #include "net/http/transport_security_state.h"
 #include "net/quic/crypto/proof_verifier_chromium.h"
 #include "net/quic/crypto/quic_server_info.h"
@@ -633,6 +634,18 @@
             "Net.QuicSession.TimedOutWithOpenStreams.ConsecutiveTLPCount",
             connection()->sent_packet_manager().consecutive_tlp_count());
       }
+      if (connection()->sent_packet_manager().HasUnackedPackets()) {
+        UMA_HISTOGRAM_TIMES(
+            "Net.QuicSession.LocallyTimedOutWithOpenStreams."
+                "TimeSinceLastReceived.UnackedPackets",
+            NetworkActivityMonitor::GetInstance()->GetTimeSinceLastReceived());
+      } else {
+        UMA_HISTOGRAM_TIMES(
+            "Net.QuicSession.LocallyTimedOutWithOpenStreams."
+                "TimeSinceLastReceived.NoUnackedPackets",
+            NetworkActivityMonitor::GetInstance()->GetTimeSinceLastReceived());
+      }
+
     } else {
       UMA_HISTOGRAM_COUNTS(
           "Net.QuicSession.ConnectionClose.NumOpenStreams.HandshakeTimedOut",
diff --git a/net/quic/quic_client_session_test.cc b/net/quic/quic_client_session_test.cc
index 66583b8..88beca7 100644
--- a/net/quic/quic_client_session_test.cc
+++ b/net/quic/quic_client_session_test.cc
@@ -52,6 +52,8 @@
                                             /*is_secure=*/false,
                                             PRIVACY_MODE_DISABLED),
         &crypto_config_, nullptr);
+    // Advance the time, because timers do not like uninitialized times.
+    connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
   }
 
   void TearDown() override { session_.CloseSessionOnError(ERR_ABORTED); }
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index fd9ec5f..62cbc64 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -282,6 +282,11 @@
   max_undecryptable_packets_ = config.max_undecryptable_packets();
 }
 
+void QuicConnection::ResumeConnectionState(
+    const CachedNetworkParameters& cached_network_params) {
+  sent_packet_manager_.ResumeConnectionState(cached_network_params);
+}
+
 void QuicConnection::SetNumOpenStreams(size_t num_streams) {
   sent_packet_manager_.SetNumOpenStreams(num_streams);
 }
@@ -911,10 +916,6 @@
     } else {
       // Send an ack much more quickly for crypto handshake packets.
       QuicTime::Delta delayed_ack_time = sent_packet_manager_.DelayedAckTime();
-      if (last_stream_frames_.size() == 1 &&
-          last_stream_frames_[0].stream_id == kCryptoStreamId) {
-        delayed_ack_time = QuicTime::Delta::Zero();
-      }
       ack_alarm_->Set(clock_->ApproximateNow().Add(delayed_ack_time));
       DVLOG(1) << "Ack timer set; next packet or timer will trigger ACK.";
     }
@@ -1449,6 +1450,13 @@
            << QuicUtils::StringToHexASCIIDump(
                packet->serialized_packet.packet->AsStringPiece());
 
+  QuicTime packet_send_time = QuicTime::Zero();
+  if (FLAGS_quic_record_send_time_before_write) {
+    // Measure the RTT from before the write begins to avoid underestimating the
+    // min_rtt_, especially in cases where the thread blocks or gets swapped out
+    // during the WritePacket below.
+    packet_send_time = clock_->Now();
+  }
   WriteResult result = writer_->WritePacket(encrypted->data(),
                                             encrypted->length(),
                                             self_address().address(),
@@ -1467,7 +1475,16 @@
       return false;
     }
   }
-  QuicTime now = clock_->Now();
+  if (!FLAGS_quic_record_send_time_before_write) {
+    packet_send_time = clock_->Now();
+  }
+  if (!packet_send_time.IsInitialized()) {
+    // TODO(jokulik): This is only needed because of the two code paths for
+    // initializing packet_send_time.  Once "quic_record_send_time_before_write"
+    // is deprecated, this check can be removed.
+    LOG(DFATAL) << "The packet send time should never be zero. "
+                << "This is a programming bug, please report it.";
+  }
   if (result.status != WRITE_STATUS_ERROR && debug_visitor_.get() != nullptr) {
     // Pass the write result to the visitor.
     debug_visitor_->OnPacketSent(packet->serialized_packet,
@@ -1475,14 +1492,17 @@
                                  packet->encryption_level,
                                  packet->transmission_type,
                                  *encrypted,
-                                 now);
+                                 packet_send_time);
   }
   if (packet->transmission_type == NOT_RETRANSMISSION) {
-    time_of_last_sent_new_packet_ = now;
+    time_of_last_sent_new_packet_ = packet_send_time;
   }
   SetPingAlarm();
-  DVLOG(1) << ENDPOINT << "time of last sent packet: "
-           << now.ToDebuggingValue();
+  DVLOG(1) << ENDPOINT << "time "
+           << (FLAGS_quic_record_send_time_before_write ?
+               "we began writing " : "we finished writing ")
+           << "last sent packet: "
+           << packet_send_time.ToDebuggingValue();
 
   // TODO(ianswett): Change the sequence number length and other packet creator
   // options by a more explicit API than setting a struct value directly,
@@ -1494,7 +1514,7 @@
   bool reset_retransmission_alarm = sent_packet_manager_.OnPacketSent(
       &packet->serialized_packet,
       packet->original_sequence_number,
-      now,
+      packet_send_time,
       encrypted->length(),
       packet->transmission_type,
       IsRetransmittable(*packet));
@@ -1585,6 +1605,12 @@
 
 void QuicConnection::OnHandshakeComplete() {
   sent_packet_manager_.SetHandshakeConfirmed();
+  // The client should immediately ack the SHLO to confirm the handshake is
+  // complete with the server.
+  if (!is_server_ && !ack_queued_) {
+    ack_alarm_->Cancel();
+    ack_alarm_->Set(clock_->ApproximateNow());
+  }
 }
 
 void QuicConnection::SendOrQueuePacket(QueuedPacket packet) {
@@ -1598,8 +1624,6 @@
   sent_entropy_manager_.RecordPacketEntropyHash(
       packet.serialized_packet.sequence_number,
       packet.serialized_packet.entropy_hash);
-  LOG_IF(DFATAL, !queued_packets_.empty() && !writer_->IsWriteBlocked())
-      << "Packets should only be left queued if we're write blocked.";
   if (!WritePacket(&packet)) {
     queued_packets_.push_back(packet);
   }
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 96f5cbc..abab048 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -24,6 +24,7 @@
 #include <string>
 #include <vector>
 
+#include "base/basictypes.h"
 #include "base/logging.h"
 #include "net/base/iovec.h"
 #include "net/base/ip_endpoint.h"
@@ -258,6 +259,11 @@
   // Sets connection parameters from the supplied |config|.
   void SetFromConfig(const QuicConfig& config);
 
+  // Called by the Session when the client has provided CachedNetworkParameters.
+  // Virtual for tests.
+  virtual void ResumeConnectionState(
+      const CachedNetworkParameters& cached_network_params);
+
   // Sets the number of active streams on the connection for congestion control.
   void SetNumOpenStreams(size_t num_streams);
 
@@ -689,7 +695,7 @@
   IPEndPoint self_address_;
   IPEndPoint peer_address_;
   // Used to store latest peer port to possibly migrate to later.
-  int migrating_peer_port_;
+  uint16 migrating_peer_port_;
 
   // True if the last packet has gotten far enough in the framer to be
   // decrypted.
@@ -783,8 +789,8 @@
   // This is used for timeouts, and does not indicate the packet was processed.
   QuicTime time_of_last_received_packet_;
 
-  // The last time a new (non-retransmitted) packet was sent for this
-  // connection.
+  // The last time this connection began sending a new (non-retransmitted)
+  // packet.
   QuicTime time_of_last_sent_new_packet_;
 
   // Sequence number of the last sent packet.  Packets are guaranteed to be sent
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 4e58dfd..ede61c8 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -67,7 +67,7 @@
   }
 
   bool GenerateCongestionFeedback(
-      QuicCongestionFeedbackFrame* congestion_feedback) {
+      QuicCongestionFeedbackFrame* congestion_feedback) override {
     if (feedback_ == nullptr) {
       return false;
     }
@@ -95,6 +95,7 @@
 
   // QuicEncrypter interface.
   bool SetKey(StringPiece key) override { return true; }
+
   bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
 
   bool Encrypt(StringPiece nonce,
@@ -149,6 +150,7 @@
 
   // QuicDecrypter interface
   bool SetKey(StringPiece key) override { return true; }
+
   bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
 
   bool Decrypt(StringPiece nonce,
@@ -258,7 +260,7 @@
 
 class TestPacketWriter : public QuicPacketWriter {
  public:
-  explicit TestPacketWriter(QuicVersion version)
+  TestPacketWriter(QuicVersion version, MockClock *clock)
       : version_(version),
         framer_(SupportedVersions(version_)),
         last_packet_size_(0),
@@ -268,7 +270,9 @@
         final_bytes_of_last_packet_(0),
         final_bytes_of_previous_packet_(0),
         use_tagging_decrypter_(false),
-        packets_write_attempts_(0) {
+        packets_write_attempts_(0),
+        clock_(clock),
+        write_pause_time_delta_(QuicTime::Delta::Zero()) {
   }
 
   // QuicPacketWriter interface
@@ -297,6 +301,10 @@
       return WriteResult(WRITE_STATUS_BLOCKED, -1);
     }
     last_packet_size_ = packet.length();
+
+    if (!write_pause_time_delta_.IsZero()) {
+      clock_->AdvanceTime(write_pause_time_delta_);
+    }
     return WriteResult(WRITE_STATUS_OK, last_packet_size_);
   }
 
@@ -310,6 +318,11 @@
 
   void BlockOnNextWrite() { block_on_next_write_ = true; }
 
+  // Sets the amount of time that the writer should before the actual write.
+  void SetWritePauseTimeDelta(QuicTime::Delta delta) {
+    write_pause_time_delta_ = delta;
+  }
+
   const QuicPacketHeader& header() { return framer_.header(); }
 
   size_t frame_count() const { return framer_.num_frames(); }
@@ -390,6 +403,10 @@
   uint32 final_bytes_of_previous_packet_;
   bool use_tagging_decrypter_;
   uint32 packets_write_attempts_;
+  MockClock *clock_;
+  // If non-zero, the clock will pause during WritePacket for this amount of
+  // time.
+  QuicTime::Delta write_pause_time_delta_;
 
   DISALLOW_COPY_AND_ASSIGN(TestPacketWriter);
 };
@@ -597,7 +614,7 @@
   MockPacketWriterFactory(QuicPacketWriter* writer) {
     ON_CALL(*this, Create(_)).WillByDefault(Return(writer));
   }
-  virtual ~MockPacketWriterFactory() {}
+  ~MockPacketWriterFactory() override {}
 
   MOCK_CONST_METHOD1(Create, QuicPacketWriter*(QuicConnection* connection));
 };
@@ -611,7 +628,7 @@
         send_algorithm_(new StrictMock<MockSendAlgorithm>),
         loss_algorithm_(new MockLossAlgorithm()),
         helper_(new TestConnectionHelper(&clock_, &random_generator_)),
-        writer_(new TestPacketWriter(version())),
+        writer_(new TestPacketWriter(version(), &clock_)),
         factory_(writer_.get()),
         connection_(connection_id_, IPEndPoint(), helper_.get(),
                     factory_, false, version()),
@@ -974,6 +991,10 @@
     EXPECT_CALL(visitor_, OnWriteBlocked()).Times(AtLeast(1));
   }
 
+  void SetWritePauseTimeDelta(QuicTime::Delta delta) {
+    writer_->SetWritePauseTimeDelta(delta);
+  }
+
   void CongestionBlockWrites() {
     EXPECT_CALL(*send_algorithm_,
                 TimeUntilSend(_, _, _)).WillRepeatedly(
@@ -1548,6 +1569,74 @@
   EXPECT_EQ(7u, least_unacked());
 }
 
+// If FLAGS_quic_record_send_time_before_write is disabled, QuicConnection
+// should record the packet sen-tdime after the packet is sent.
+TEST_P(QuicConnectionTest, RecordSentTimeAfterPacketSent) {
+  ValueRestore<bool> old_flag(&FLAGS_quic_record_send_time_before_write, false);
+  // We're using a MockClock for the tests, so we have complete control over the
+  // time.
+  // Our recorded timestamp for the last packet sent time will be passed in to
+  // the send_algorithm.  Make sure that it is set to the correct value.
+  QuicTime actual_recorded_send_time = QuicTime::Zero();
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+      .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true)));
+
+  // First send without any pause and check the result.
+  QuicTime expected_recorded_send_time = clock_.Now();
+  connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr);
+  EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time)
+      << "Expected time = " << expected_recorded_send_time.ToDebuggingValue()
+      << ".  Actual time = " << actual_recorded_send_time.ToDebuggingValue();
+
+  // Now pause during the write, and check the results.
+  actual_recorded_send_time = QuicTime::Zero();
+  const QuicTime::Delta kWritePauseTimeDelta =
+      QuicTime::Delta::FromMilliseconds(5000);
+  SetWritePauseTimeDelta(kWritePauseTimeDelta);
+  expected_recorded_send_time = clock_.Now().Add(kWritePauseTimeDelta);
+
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+      .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true)));
+  connection_.SendStreamDataWithString(2, "baz", 0, !kFin, nullptr);
+  EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time)
+      << "Expected time = " << expected_recorded_send_time.ToDebuggingValue()
+      << ".  Actual time = " << actual_recorded_send_time.ToDebuggingValue();
+}
+
+// If FLAGS_quic_record_send_time_before_write is enabled, QuicConnection should
+// record the the packet sent-time prior to sending the packet.
+TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) {
+  ValueRestore<bool> old_flag(&FLAGS_quic_record_send_time_before_write, true);
+  // We're using a MockClock for the tests, so we have complete control over the
+  // time.
+  // Our recorded timestamp for the last packet sent time will be passed in to
+  // the send_algorithm.  Make sure that it is set to the correct value.
+  QuicTime actual_recorded_send_time = QuicTime::Zero();
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+      .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true)));
+
+  // First send without any pause and check the result.
+  QuicTime expected_recorded_send_time = clock_.Now();
+  connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr);
+  EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time)
+      << "Expected time = " << expected_recorded_send_time.ToDebuggingValue()
+      << ".  Actual time = " << actual_recorded_send_time.ToDebuggingValue();
+
+  // Now pause during the write, and check the results.
+  actual_recorded_send_time = QuicTime::Zero();
+  const QuicTime::Delta kWritePauseTimeDelta =
+      QuicTime::Delta::FromMilliseconds(5000);
+  SetWritePauseTimeDelta(kWritePauseTimeDelta);
+  expected_recorded_send_time = clock_.Now();
+
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+      .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true)));
+  connection_.SendStreamDataWithString(2, "baz", 0, !kFin, nullptr);
+  EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time)
+      << "Expected time = " << expected_recorded_send_time.ToDebuggingValue()
+      << ".  Actual time = " << actual_recorded_send_time.ToDebuggingValue();
+}
+
 TEST_P(QuicConnectionTest, FECSending) {
   // All packets carry version info till version is negotiated.
   QuicPacketCreator* creator =
@@ -1565,7 +1654,8 @@
   creator->set_max_packet_length(length);
 
   // Send 4 protected data packets, which should also trigger 1 FEC packet.
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(5);
+  EXPECT_CALL(*send_algorithm_,
+              OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(5);
   // The first stream frame will have 2 fewer overhead bytes than the other 3.
   const string payload(payload_length * 4 + 2, 'a');
   connection_.SendStreamDataWithStringWithFec(1, payload, 0, !kFin, nullptr);
@@ -1601,7 +1691,8 @@
       &connection_)->IsFecEnabled());
 
   // 1 Data and 1 FEC packet.
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+  EXPECT_CALL(*send_algorithm_,
+              OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(2);
   connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr);
 
   const QuicTime::Delta retransmission_time =
@@ -1620,8 +1711,9 @@
   EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator(
       &connection_)->IsFecEnabled());
 
-  // 1 Data and 1 FEC packet.
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
+  // 3 Data and 3 FEC packets.
+  EXPECT_CALL(*send_algorithm_,
+              OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(6);
   connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr);
   // Send some more data afterwards to ensure early retransmit doesn't trigger.
   connection_.SendStreamDataWithStringWithFec(3, "foo", 3, !kFin, nullptr);
@@ -1648,8 +1740,9 @@
   EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator(
       &connection_)->IsFecEnabled());
 
-  // 1 Data and 1 FEC packet.
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
+  // 3 Data and 3 FEC packet.
+  EXPECT_CALL(*send_algorithm_,
+              OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(6);
   connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr);
   // Send some more data afterwards to ensure early retransmit doesn't trigger.
   connection_.SendStreamDataWithStringWithFec(3, "foo", 3, !kFin, nullptr);
@@ -3070,22 +3163,25 @@
   EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
 }
 
-TEST_P(QuicConnectionTest, SendEarlyDelayedAckForCrypto) {
-  QuicTime ack_time = clock_.ApproximateNow();
+TEST_P(QuicConnectionTest, SendDelayedAckOnHandshakeConfirmed) {
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
-  // Process a packet from the crypto stream, which is frame1_'s default.
   ProcessPacket(1);
-  // Check if delayed ack timer is running for the expected interval.
+  // Check that ack is sent and that delayed ack alarm is set.
+  EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+  QuicTime ack_time = clock_.ApproximateNow().Add(DefaultDelayedAckTime());
+  EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
+
+  // Completing the handshake as the server does nothing.
+  QuicConnectionPeer::SetIsServer(&connection_, true);
+  connection_.OnHandshakeComplete();
   EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
   EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
-  // Simulate delayed ack alarm firing.
-  connection_.GetAckAlarm()->Fire();
-  // Check that ack is sent and that delayed ack alarm is reset.
-  EXPECT_EQ(2u, writer_->frame_count());
-  EXPECT_FALSE(writer_->stop_waiting_frames().empty());
-  EXPECT_FALSE(writer_->ack_frames().empty());
-  EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+
+  // Complete the handshake as the client decreases the delayed ack time to 0ms.
+  QuicConnectionPeer::SetIsServer(&connection_, false);
+  connection_.OnHandshakeComplete();
+  EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+  EXPECT_EQ(clock_.ApproximateNow(), connection_.GetAckAlarm()->deadline());
 }
 
 TEST_P(QuicConnectionTest, SendDelayedAckOnSecondPacket) {
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index 1df2313..8e14d77 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -34,6 +34,8 @@
         stream_(new QuicCryptoClientStream(server_id_, session_.get(), nullptr,
                                            &crypto_config_)) {
     session_->SetCryptoStream(stream_.get());
+    // Advance the time, because timers do not like uninitialized times.
+    connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
   }
 
   void CompleteCryptoHandshake() {
@@ -128,8 +130,8 @@
 
   // Advance time 5 years to ensure that we pass the expiry time of the cached
   // server config.
-  reinterpret_cast<MockClock*>(const_cast<QuicClock*>(connection_->clock()))
-      ->AdvanceTime(QuicTime::Delta::FromSeconds(60 * 60 * 24 * 365 * 5));
+  connection_->AdvanceTime(
+      QuicTime::Delta::FromSeconds(60 * 60 * 24 * 365 * 5));
 
   // Check that a client hello was sent and that CryptoConnect doesn't fail
   // with an error.
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc
index 1d62376..c4b5893 100644
--- a/net/quic/quic_crypto_server_stream.cc
+++ b/net/quic/quic_crypto_server_stream.cc
@@ -245,8 +245,8 @@
 void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) {
 }
 
-CachedNetworkParameters*
-QuicCryptoServerStream::get_previous_cached_network_params() {
+const CachedNetworkParameters*
+QuicCryptoServerStream::previous_cached_network_params() const {
   return previous_cached_network_params_.get();
 }
 
diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h
index 09d9bd8..f88affe 100644
--- a/net/quic/quic_crypto_server_stream.h
+++ b/net/quic/quic_crypto_server_stream.h
@@ -82,6 +82,8 @@
   void set_previous_cached_network_params(
       CachedNetworkParameters cached_network_params);
 
+  const CachedNetworkParameters* previous_cached_network_params() const;
+
  protected:
   virtual QuicErrorCode ProcessClientHello(
       const CryptoHandshakeMessage& message,
@@ -93,8 +95,6 @@
   // before going through the parameter negotiation step.
   virtual void OverrideQuicConfigDefaults(QuicConfig* config);
 
-  CachedNetworkParameters* get_previous_cached_network_params();
-
  private:
   friend class test::CryptoTestUtils;
 
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc
index 47d58ce..e737933 100644
--- a/net/quic/quic_flags.cc
+++ b/net/quic/quic_flags.cc
@@ -54,3 +54,14 @@
 // If true, QUIC connections will delay moving to forward security until the
 // client starts sending foward secure encrypted packets.
 bool FLAGS_enable_quic_delay_forward_security = true;
+
+// Do not flip this flag.  jokulik plans more testing and additional monitoring
+// before the flag can go the auto-flip process.
+//
+// If true, record the timestamp for the last sent new packet before the call to
+// WritePacket, rather than after in QUIC.
+bool FLAGS_quic_record_send_time_before_write = false;
+
+// If true, enables the QUIC bandwidth resumption experiment (triggered by
+// Chrome/Finch).
+bool FLAGS_quic_enable_bandwidth_resumption_experiment = true;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h
index a75f79b..2ffe618 100644
--- a/net/quic/quic_flags.h
+++ b/net/quic/quic_flags.h
@@ -20,5 +20,8 @@
 NET_EXPORT_PRIVATE extern bool FLAGS_allow_truncated_connection_ids_for_quic;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_too_many_outstanding_packets;
 NET_EXPORT_PRIVATE extern bool FLAGS_enable_quic_delay_forward_security;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_record_send_time_before_write;
+NET_EXPORT_PRIVATE
+extern bool FLAGS_quic_enable_bandwidth_resumption_experiment;
 
 #endif  // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index 4e03e3a..578acea 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -87,8 +87,7 @@
     server_framer_.set_visitor(&framer_visitor_);
   }
 
-  virtual ~QuicPacketCreatorTest() override {
-  }
+  ~QuicPacketCreatorTest() override {}
 
   void ProcessPacket(QuicPacket* packet) {
     scoped_ptr<QuicEncryptedPacket> encrypted(
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc
index 3f2472c..ac99144 100644
--- a/net/quic/quic_packet_generator_test.cc
+++ b/net/quic/quic_packet_generator_test.cc
@@ -33,7 +33,7 @@
 class MockDelegate : public QuicPacketGenerator::DelegateInterface {
  public:
   MockDelegate() {}
-  virtual ~MockDelegate() override {}
+  ~MockDelegate() override {}
 
   MOCK_METHOD3(ShouldGeneratePacket,
                bool(TransmissionType transmission_type,
@@ -116,7 +116,7 @@
         packet6_(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0, nullptr),
         packet7_(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0, nullptr) {}
 
-  virtual ~QuicPacketGeneratorTest() override {
+  ~QuicPacketGeneratorTest() override {
     delete packet_.packet;
     delete packet_.retransmittable_frames;
     delete packet2_.packet;
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index 5aa831e..b631b07 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -704,7 +704,8 @@
       transmission_type(NOT_RETRANSMISSION),
       all_transmissions(nullptr),
       in_flight(false),
-      is_unackable(false) {}
+      is_unackable(false),
+      is_fec_packet(false) {}
 
 TransmissionInfo::TransmissionInfo(
     RetransmittableFrames* retransmittable_frames,
@@ -719,6 +720,7 @@
       transmission_type(transmission_type),
       all_transmissions(nullptr),
       in_flight(false),
-      is_unackable(false) {}
+      is_unackable(false),
+      is_fec_packet(false) {}
 
 }  // namespace net
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index 00064ff..4cd53a9 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -1099,6 +1099,8 @@
   bool in_flight;
   // True if the packet can never be acked, so it can be removed.
   bool is_unackable;
+  // True if the packet is an FEC packet.
+  bool is_fec_packet;
 };
 
 }  // namespace net
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
index 7978fed..142871e 100644
--- a/net/quic/quic_sent_packet_manager.cc
+++ b/net/quic/quic_sent_packet_manager.cc
@@ -163,6 +163,11 @@
   }
 }
 
+void QuicSentPacketManager::ResumeConnectionState(
+    const CachedNetworkParameters& cached_network_params) {
+  send_algorithm_->ResumeConnectionState(cached_network_params);
+}
+
 void QuicSentPacketManager::SetNumOpenStreams(size_t num_streams) {
   if (n_connection_simulation_) {
     // Ensure the number of connections is between 1 and 5.
@@ -323,6 +328,9 @@
         (retransmission_type == ALL_UNACKED_RETRANSMISSION ||
          frames->encryption_level() == ENCRYPTION_INITIAL)) {
       MarkForRetransmission(sequence_number, retransmission_type);
+    } else if (it->is_fec_packet) {
+      // Remove FEC packets from the packet map, since we can't retransmit them.
+      unacked_packets_.RemoveFromInFlight(sequence_number);
     }
   }
 }
@@ -549,12 +557,18 @@
   }
 
   // Only track packets as in flight that the send algorithm wants us to track.
+  // Since FEC packets should also be counted towards the congestion window,
+  // consider them as retransmittable for the purposes of congestion control.
+  HasRetransmittableData has_congestion_controlled_data =
+      serialized_packet->packet->is_fec_packet() ?
+      HAS_RETRANSMITTABLE_DATA : has_retransmittable_data;
   const bool in_flight =
       send_algorithm_->OnPacketSent(sent_time,
                                     unacked_packets_.bytes_in_flight(),
                                     sequence_number,
                                     bytes,
-                                    has_retransmittable_data);
+                                    has_congestion_controlled_data);
+
   unacked_packets_.AddSentPacket(*serialized_packet,
                                  original_sequence_number,
                                  transmission_type,
diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h
index 2a3ea64..2a94e09 100644
--- a/net/quic/quic_sent_packet_manager.h
+++ b/net/quic/quic_sent_packet_manager.h
@@ -16,6 +16,7 @@
 #include "net/quic/congestion_control/loss_detection_interface.h"
 #include "net/quic/congestion_control/rtt_stats.h"
 #include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/crypto/cached_network_parameters.h"
 #include "net/quic/quic_ack_notifier_manager.h"
 #include "net/quic/quic_protocol.h"
 #include "net/quic/quic_sustained_bandwidth_recorder.h"
@@ -99,6 +100,10 @@
 
   virtual void SetFromConfig(const QuicConfig& config);
 
+  // Pass the CachedNetworkParameters to the send algorithm.
+  void ResumeConnectionState(
+      const CachedNetworkParameters& cached_network_params);
+
   void SetNumOpenStreams(size_t num_streams);
 
   void SetHandshakeConfirmed() { handshake_confirmed_ = true; }
@@ -111,6 +116,13 @@
   bool IsUnacked(QuicPacketSequenceNumber sequence_number) const;
 
   // Requests retransmission of all unacked packets of |retransmission_type|.
+  // The behavior of this method depends on the value of |retransmission_type|:
+  // ALL_UNACKED_RETRANSMISSION - All unacked packets will be retransmitted.
+  // This can happen, for example, after a version negotiation packet has been
+  // received and all packets needs to be retransmitted with the new version.
+  // ALL_INITIAL_RETRANSMISSION - Only initially encrypted packets will be
+  // retransmitted. This can happen, for example, when a CHLO has been rejected
+  // and the previously encrypted data needs to be encrypted with a new key.
   void RetransmitUnackedPackets(TransmissionType retransmission_type);
 
   // Retransmits the oldest pending packet there is still a tail loss probe
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc
index d710120..c1e6f20 100644
--- a/net/quic/quic_sent_packet_manager_test.cc
+++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -64,9 +64,7 @@
     EXPECT_CALL(*send_algorithm_, InRecovery()).Times(AnyNumber());
   }
 
-  virtual ~QuicSentPacketManagerTest() override {
-    STLDeleteElements(&packets_);
-  }
+  ~QuicSentPacketManagerTest() override { STLDeleteElements(&packets_); }
 
   QuicByteCount BytesInFlight() {
     return QuicSentPacketManagerPeer::GetBytesInFlight(&manager_);
@@ -216,7 +214,7 @@
   void SendFecPacket(QuicPacketSequenceNumber sequence_number) {
     EXPECT_CALL(*send_algorithm_,
                 OnPacketSent(_, BytesInFlight(), sequence_number,
-                             kDefaultLength, NO_RETRANSMITTABLE_DATA))
+                             kDefaultLength, HAS_RETRANSMITTABLE_DATA))
                     .Times(1).WillOnce(Return(true));
     SerializedPacket packet(CreateFecPacket(sequence_number));
     manager_.OnPacketSent(&packet, 0, clock_.Now(),
diff --git a/net/quic/quic_server_session.cc b/net/quic/quic_server_session.cc
index 1d48182..e0defd6 100644
--- a/net/quic/quic_server_session.cc
+++ b/net/quic/quic_server_session.cc
@@ -37,14 +37,29 @@
 
 void QuicServerSession::OnConfigNegotiated() {
   QuicSession::OnConfigNegotiated();
-  if (!FLAGS_enable_quic_fec ||
-      !config()->HasReceivedConnectionOptions() ||
-      !ContainsQuicTag(config()->ReceivedConnectionOptions(), kFHDR)) {
+
+  if (!config()->HasReceivedConnectionOptions()) {
     return;
   }
-  // kFHDR config maps to FEC protection always for headers stream.
-  // TODO(jri): Add crypto stream in addition to headers for kHDR.
-  headers_stream_->set_fec_policy(FEC_PROTECT_ALWAYS);
+
+  // If the client has provided a bandwidth estimate from the same serving
+  // region, then pass it to the sent packet manager in preparation for possible
+  // bandwidth resumption.
+  const CachedNetworkParameters* cached_network_params =
+      crypto_stream_->previous_cached_network_params();
+  if (FLAGS_quic_enable_bandwidth_resumption_experiment &&
+      cached_network_params != nullptr &&
+      ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWRE) &&
+      cached_network_params->serving_region() == serving_region_) {
+    connection()->ResumeConnectionState(*cached_network_params);
+  }
+
+  if (FLAGS_enable_quic_fec &&
+      ContainsQuicTag(config()->ReceivedConnectionOptions(), kFHDR)) {
+    // kFHDR config maps to FEC protection always for headers stream.
+    // TODO(jri): Add crypto stream in addition to headers for kHDR.
+    headers_stream_->set_fec_policy(FEC_PROTECT_ALWAYS);
+  }
 }
 
 void QuicServerSession::OnConnectionClosed(QuicErrorCode error,
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 2318ab4..e4b163f 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -48,8 +48,8 @@
     session_->PostProcessAfterData();
   }
 
-  void OnWindowUpdateFrames(const vector<QuicWindowUpdateFrame>& frames)
-      override {
+  void OnWindowUpdateFrames(
+      const vector<QuicWindowUpdateFrame>& frames) override {
     session_->OnWindowUpdateFrames(frames);
     session_->PostProcessAfterData();
   }
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc
index d14d875..d953678 100644
--- a/net/quic/quic_session_test.cc
+++ b/net/quic/quic_session_test.cc
@@ -54,8 +54,7 @@
       : QuicCryptoStream(session) {
   }
 
-  virtual void OnHandshakeMessage(
-      const CryptoHandshakeMessage& message) override {
+  void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
     encryption_established_ = true;
     handshake_confirmed_ = true;
     CryptoHandshakeMessage msg;
@@ -94,7 +93,7 @@
 
   using ReliableQuicStream::CloseWriteSide;
 
-  virtual uint32 ProcessData(const char* data, uint32 data_len) override {
+  uint32 ProcessData(const char* data, uint32 data_len) override {
     return data_len;
   }
 
@@ -131,17 +130,15 @@
     InitializeSession();
   }
 
-  virtual TestCryptoStream* GetCryptoStream() override {
-    return &crypto_stream_;
-  }
+  TestCryptoStream* GetCryptoStream() override { return &crypto_stream_; }
 
-  virtual TestStream* CreateOutgoingDataStream() override {
+  TestStream* CreateOutgoingDataStream() override {
     TestStream* stream = new TestStream(GetNextStreamId(), this);
     ActivateStream(stream);
     return stream;
   }
 
-  virtual TestStream* CreateIncomingDataStream(QuicStreamId id) override {
+  TestStream* CreateIncomingDataStream(QuicStreamId id) override {
     return new TestStream(id, this);
   }
 
@@ -153,7 +150,7 @@
     return QuicSession::GetIncomingDataStream(stream_id);
   }
 
-  virtual QuicConsumedData WritevData(
+  QuicConsumedData WritevData(
       QuicStreamId id,
       const IOVector& data,
       QuicStreamOffset offset,
@@ -223,6 +220,7 @@
         "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
         "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
         "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
+    connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
   }
 
   void CheckClosedStreams() {
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc
index 8c90c9f..43a105b 100644
--- a/net/quic/quic_stream_sequencer_test.cc
+++ b/net/quic/quic_stream_sequencer_test.cc
@@ -44,7 +44,7 @@
                                                 const string& details));
   MOCK_METHOD1(Reset, void(QuicRstStreamErrorCode error));
   MOCK_METHOD0(OnCanWrite, void());
-  virtual QuicPriority EffectivePriority() const override {
+  QuicPriority EffectivePriority() const override {
     return QuicUtils::HighestPriority();
   }
   virtual bool IsFlowControlEnabled() const {
diff --git a/net/quic/quic_time.h b/net/quic/quic_time.h
index 53e5ebe..62bf582 100644
--- a/net/quic/quic_time.h
+++ b/net/quic/quic_time.h
@@ -17,6 +17,8 @@
 
 namespace net {
 
+static const int kNumSecondsPerMinute = 60;
+static const int kNumSecondsPerHour = kNumSecondsPerMinute * 60;
 static const uint64 kNumMicrosPerSecond = base::Time::kMicrosecondsPerSecond;
 static const uint64 kNumMicrosPerMilli =
     base::Time::kMicrosecondsPerMillisecond;
diff --git a/net/quic/quic_unacked_packet_map.cc b/net/quic/quic_unacked_packet_map.cc
index 04eb1b8..bbff3c9 100644
--- a/net/quic/quic_unacked_packet_map.cc
+++ b/net/quic/quic_unacked_packet_map.cc
@@ -53,6 +53,9 @@
                         packet.sequence_number_length,
                         transmission_type,
                         sent_time);
+  DCHECK(packet.packet != nullptr);
+  info.is_fec_packet = packet.packet->is_fec_packet();
+
   if (old_sequence_number == 0) {
     if (packet.retransmittable_frames != nullptr &&
         packet.retransmittable_frames->HasCryptoHandshake() == IS_HANDSHAKE) {
diff --git a/net/quic/quic_unacked_packet_map_test.cc b/net/quic/quic_unacked_packet_map_test.cc
index d31ce44..7840495 100644
--- a/net/quic/quic_unacked_packet_map_test.cc
+++ b/net/quic/quic_unacked_packet_map_test.cc
@@ -8,6 +8,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using std::min;
+using std::vector;
 
 namespace net {
 namespace test {
@@ -23,16 +24,26 @@
       : now_(QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(1000))) {
   }
 
+  ~QuicUnackedPacketMapTest() override {
+    STLDeleteElements(&packets_);
+  }
+
   SerializedPacket CreateRetransmittablePacket(
       QuicPacketSequenceNumber sequence_number) {
+    packets_.push_back(QuicPacket::NewDataPacket(
+        nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
+        PACKET_1BYTE_SEQUENCE_NUMBER));
     return SerializedPacket(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
-                            nullptr, 0, new RetransmittableFrames());
+                            packets_.back(), 0, new RetransmittableFrames());
   }
 
   SerializedPacket CreateNonRetransmittablePacket(
       QuicPacketSequenceNumber sequence_number) {
+    packets_.push_back(QuicPacket::NewDataPacket(
+        nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
+        PACKET_1BYTE_SEQUENCE_NUMBER));
     return SerializedPacket(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
-                            nullptr, 0, nullptr);
+                            packets_.back(), 0, nullptr);
   }
 
   void VerifyInFlightPackets(QuicPacketSequenceNumber* packets,
@@ -94,7 +105,7 @@
           << " packets[" << i << "]:" << packets[i];
     }
   }
-
+  vector<QuicPacket*> packets_;
   QuicUnackedPacketMap unacked_packets_;
   QuicTime now_;
 };
@@ -185,8 +196,8 @@
 
   unacked_packets_.RemoveFromInFlight(2);
   QuicPacketSequenceNumber unacked2[] = { 1 };
-  VerifyUnackedPackets(unacked, arraysize(unacked2));
-  VerifyInFlightPackets(unacked, arraysize(unacked2));
+  VerifyUnackedPackets(unacked2, arraysize(unacked2));
+  VerifyInFlightPackets(unacked2, arraysize(unacked2));
   VerifyRetransmittablePackets(nullptr, 0);
 
   unacked_packets_.RemoveFromInFlight(1);
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index 814be7b..b24316f 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -214,6 +214,8 @@
     QuicCryptoServerStream* server,
     const FakeClientOptions& options) {
   PacketSavingConnection* client_conn = new PacketSavingConnection(false);
+  // Advance the time, because timers do not like uninitialized times.
+  client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
   TestClientSession client_session(client_conn, DefaultQuicConfig());
   QuicCryptoClientConfig crypto_config;
 
diff --git a/net/quic/test_tools/mock_quic_dispatcher.h b/net/quic/test_tools/mock_quic_dispatcher.h
index f923790..4945724 100644
--- a/net/quic/test_tools/mock_quic_dispatcher.h
+++ b/net/quic/test_tools/mock_quic_dispatcher.h
@@ -22,7 +22,7 @@
                      PacketWriterFactory* packet_writer_factory,
                      QuicConnectionHelperInterface* helper);
 
-  virtual ~MockQuicDispatcher();
+  ~MockQuicDispatcher() override;
 
   MOCK_METHOD3(ProcessPacket, void(const IPEndPoint& server_address,
                                    const IPEndPoint& client_address,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index fa987de..9df03eb 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "base/basictypes.h"
 #include "base/strings/string_piece.h"
 #include "net/quic/congestion_control/loss_detection_interface.h"
 #include "net/quic/congestion_control/send_algorithm_interface.h"
@@ -31,7 +32,7 @@
 namespace test {
 
 static const QuicConnectionId kTestConnectionId = 42;
-static const int kTestPort = 123;
+static const uint16 kTestPort = 123;
 static const uint32 kInitialStreamFlowControlWindowForTest =
     32 * 1024;  // 32 KB
 static const uint32 kInitialSessionFlowControlWindowForTest =
@@ -150,7 +151,7 @@
 class MockFramerVisitor : public QuicFramerVisitorInterface {
  public:
   MockFramerVisitor();
-  virtual ~MockFramerVisitor();
+  ~MockFramerVisitor() override;
 
   MOCK_METHOD1(OnError, void(QuicFramer* framer));
   // The constructor sets this up to return false by default.
@@ -225,7 +226,7 @@
 class MockConnectionVisitor : public QuicConnectionVisitorInterface {
  public:
   MockConnectionVisitor();
-  virtual ~MockConnectionVisitor();
+  ~MockConnectionVisitor() override;
 
   MOCK_METHOD1(OnStreamFrames, void(const std::vector<QuicStreamFrame>& frame));
   MOCK_METHOD1(OnWindowUpdateFrames,
@@ -293,7 +294,7 @@
   // Uses a Mock helper, ConnectionId of 42, and 127.0.0.1:123.
   MockConnection(bool is_server, const QuicVersionVector& supported_versions);
 
-  virtual ~MockConnection();
+  ~MockConnection() override;
 
   // If the constructor that uses a MockHelper has been used then this method
   // will advance the time of the MockClock.
@@ -324,7 +325,7 @@
     QuicConnection::ProcessUdpPacket(self_address, peer_address, packet);
   }
 
-  virtual bool OnProtocolVersionMismatch(QuicVersion version) override {
+  bool OnProtocolVersionMismatch(QuicVersion version) override {
     return false;
   }
 
@@ -355,7 +356,7 @@
 class MockSession : public QuicSession {
  public:
   explicit MockSession(QuicConnection* connection);
-  virtual ~MockSession();
+  ~MockSession() override;
   MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
   MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
   MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*());
@@ -388,14 +389,14 @@
 class TestSession : public QuicSession {
  public:
   TestSession(QuicConnection* connection, const QuicConfig& config);
-  virtual ~TestSession();
+  ~TestSession() override;
 
   MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
   MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
 
   void SetCryptoStream(QuicCryptoStream* stream);
 
-  virtual QuicCryptoStream* GetCryptoStream() override;
+  QuicCryptoStream* GetCryptoStream() override;
 
  private:
   QuicCryptoStream* crypto_stream_;
@@ -406,7 +407,7 @@
 class TestClientSession : public QuicClientSessionBase {
  public:
   TestClientSession(QuicConnection* connection, const QuicConfig& config);
-  virtual ~TestClientSession();
+  ~TestClientSession() override;
 
   // QuicClientSessionBase
   MOCK_METHOD1(OnProofValid,
@@ -420,7 +421,7 @@
 
   void SetCryptoStream(QuicCryptoStream* stream);
 
-  virtual QuicCryptoStream* GetCryptoStream() override;
+  QuicCryptoStream* GetCryptoStream() override;
 
  private:
   QuicCryptoStream* crypto_stream_;
@@ -431,7 +432,7 @@
 class MockPacketWriter : public QuicPacketWriter {
  public:
   MockPacketWriter();
-  virtual ~MockPacketWriter();
+  ~MockPacketWriter() override;
 
   MOCK_METHOD4(WritePacket,
                WriteResult(const char* buffer,
@@ -449,7 +450,7 @@
 class MockSendAlgorithm : public SendAlgorithmInterface {
  public:
   MockSendAlgorithm();
-  virtual ~MockSendAlgorithm();
+  ~MockSendAlgorithm() override;
 
   MOCK_METHOD3(SetFromConfig, void(const QuicConfig& config,
                                    bool is_server,
@@ -482,6 +483,7 @@
   MOCK_CONST_METHOD0(InRecovery, bool());
   MOCK_CONST_METHOD0(GetSlowStartThreshold, QuicByteCount());
   MOCK_CONST_METHOD0(GetCongestionControlType, CongestionControlType());
+  MOCK_METHOD1(ResumeConnectionState, void(const CachedNetworkParameters&));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockSendAlgorithm);
@@ -490,7 +492,7 @@
 class MockLossAlgorithm : public LossDetectionInterface {
  public:
   MockLossAlgorithm();
-  virtual ~MockLossAlgorithm();
+  ~MockLossAlgorithm() override;
 
   MOCK_CONST_METHOD0(GetLossDetectionType, LossDetectionType());
   MOCK_METHOD4(DetectLostPackets,
@@ -520,7 +522,7 @@
 class MockEntropyCalculator : public TestEntropyCalculator {
  public:
   MockEntropyCalculator();
-  virtual ~MockEntropyCalculator();
+  ~MockEntropyCalculator() override;
 
   MOCK_CONST_METHOD1(
       EntropyHash,
@@ -542,7 +544,7 @@
 
  protected:
   // Object is ref counted.
-  virtual ~MockAckNotifierDelegate();
+  ~MockAckNotifierDelegate() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockAckNotifierDelegate);
@@ -552,7 +554,7 @@
       public QuicSentPacketManager::NetworkChangeVisitor {
  public:
   MockNetworkChangeVisitor();
-  virtual ~MockNetworkChangeVisitor();
+  ~MockNetworkChangeVisitor() override;
 
   MOCK_METHOD0(OnCongestionWindowChange, void());
 
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index b996127..bc7d111 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -91,9 +91,7 @@
   bool using_ssl = request_url.SchemeIs("https") ||
       request_url.SchemeIs("wss") || force_spdy_over_ssl;
 
-  HostPortPair origin_host_port =
-      HostPortPair(request_url.HostNoBrackets(),
-                   request_url.EffectiveIntPort());
+  HostPortPair origin_host_port = HostPortPair::FromURL(request_url);
 
   if (!using_ssl && session->params().testing_fixed_http_port != 0) {
     origin_host_port.set_port(session->params().testing_fixed_http_port);
diff --git a/net/socket/server_socket.cc b/net/socket/server_socket.cc
index da89b46..7cf6c64 100644
--- a/net/socket/server_socket.cc
+++ b/net/socket/server_socket.cc
@@ -17,7 +17,7 @@
 }
 
 int ServerSocket::ListenWithAddressAndPort(const std::string& address_string,
-                                           int port,
+                                           uint16 port,
                                            int backlog) {
   IPAddressNumber address_number;
   if (!ParseIPLiteralToNumber(address_string, &address_number)) {
diff --git a/net/socket/server_socket.h b/net/socket/server_socket.h
index 4b9ca8e..828b399 100644
--- a/net/socket/server_socket.h
+++ b/net/socket/server_socket.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "net/base/completion_callback.h"
 #include "net/base/net_export.h"
@@ -30,7 +31,7 @@
   // Subclasses may override this function if |address_string| is in a different
   // format, for example, unix domain socket path.
   virtual int ListenWithAddressAndPort(const std::string& address_string,
-                                       int port,
+                                       uint16 port,
                                        int backlog);
 
   // Gets current address the socket is bound to.
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 5ae4eee..308de2e 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -682,7 +682,7 @@
       new MockUDPClientSocket(data_provider, net_log));
   data_provider->set_socket(socket.get());
   if (bind_type == DatagramSocket::RANDOM_BIND)
-    socket->set_source_port(rand_int_cb.Run(1025, 65535));
+    socket->set_source_port(static_cast<uint16>(rand_int_cb.Run(1025, 65535)));
   return socket.Pass();
 }
 
@@ -1917,7 +1917,7 @@
   data_provider->set_delegate(socket->AsWeakPtr());
   udp_client_sockets().push_back(socket.get());
   if (bind_type == DatagramSocket::RANDOM_BIND)
-    socket->set_source_port(rand_int_cb.Run(1025, 65535));
+    socket->set_source_port(static_cast<uint16>(rand_int_cb.Run(1025, 65535)));
   return socket.Pass();
 }
 
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 7bccdae..7b45c0c 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -881,13 +881,13 @@
   void OnReadComplete(const MockRead& data) override;
   void OnConnectComplete(const MockConnect& data) override;
 
-  void set_source_port(int port) { source_port_ = port; }
+  void set_source_port(uint16 port) { source_port_ = port; }
 
  private:
   bool connected_;
   IPEndPoint peer_address_;
   DeterministicSocketHelper helper_;
-  int source_port_;  // Ephemeral source port.
+  uint16 source_port_;  // Ephemeral source port.
 
   DISALLOW_COPY_AND_ASSIGN(DeterministicMockUDPClientSocket);
 };
@@ -1051,7 +1051,7 @@
   void OnReadComplete(const MockRead& data) override;
   void OnConnectComplete(const MockConnect& data) override;
 
-  void set_source_port(int port) { source_port_ = port;}
+  void set_source_port(uint16 port) { source_port_ = port;}
 
  private:
   int CompleteRead();
@@ -1064,7 +1064,7 @@
   int read_offset_;
   MockRead read_data_;
   bool need_read_data_;
-  int source_port_;  // Ephemeral source port.
+  uint16 source_port_;  // Ephemeral source port.
 
   // Address of the "remote" peer we're connected to.
   IPEndPoint peer_addr_;
diff --git a/net/socket/socks5_client_socket_unittest.cc b/net/socket/socks5_client_socket_unittest.cc
index c474a0b..5bcc146 100644
--- a/net/socket/socks5_client_socket_unittest.cc
+++ b/net/socket/socks5_client_socket_unittest.cc
@@ -258,7 +258,7 @@
     const char partial1[] = { 0x05, 0x01 };
     const char partial2[] = { 0x00 };
     MockWrite data_writes[] = {
-        MockWrite(ASYNC, arraysize(partial1)),
+        MockWrite(ASYNC, partial1, arraysize(partial1)),
         MockWrite(ASYNC, partial2, arraysize(partial2)),
         MockWrite(ASYNC, kOkRequest, arraysize(kOkRequest)) };
     MockRead data_reads[] = {
diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc
index fbb84f8..01bffe6 100644
--- a/net/socket/socks_client_socket_unittest.cc
+++ b/net/socket/socks_client_socket_unittest.cc
@@ -287,12 +287,12 @@
   const char kSOCKSPartialRequest2[] = { 0x00, 0x50, 127, 0, 0, 1, 0 };
 
   MockWrite data_writes[] = {
-      MockWrite(ASYNC, arraysize(kSOCKSPartialRequest1)),
+      MockWrite(ASYNC, kSOCKSPartialRequest1, arraysize(kSOCKSPartialRequest1)),
       // simulate some empty writes
       MockWrite(ASYNC, 0),
       MockWrite(ASYNC, 0),
-      MockWrite(ASYNC, kSOCKSPartialRequest2,
-                arraysize(kSOCKSPartialRequest2)) };
+      MockWrite(ASYNC, kSOCKSPartialRequest2, arraysize(kSOCKSPartialRequest2)),
+  };
   MockRead data_reads[] = {
       MockRead(ASYNC, kSOCKSOkReply, arraysize(kSOCKSOkReply)) };
   CapturingNetLog log;
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index 57aa619..05eb1cb 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -17,6 +17,7 @@
 #include "base/environment.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/histogram.h"
+#include "base/profiler/scoped_tracker.h"
 #include "base/strings/string_piece.h"
 #include "base/synchronization/lock.h"
 #include "crypto/ec_private_key.h"
@@ -899,10 +900,20 @@
 }
 
 int SSLClientSocketOpenSSL::DoHandshake() {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile1(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketOpenSSL::DoHandshake1"));
+
   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
   int net_error = OK;
   int rv = SSL_do_handshake(ssl_);
 
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile2(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketOpenSSL::DoHandshake2"));
+
   if (client_auth_cert_needed_) {
     net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
     // If the handshake already succeeded (because the server requests but
@@ -1608,6 +1619,11 @@
 }
 
 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketOpenSSL::ClientCertRequestCallback"));
+
   DVLOG(3) << "OpenSSL ClientCertRequestCallback called";
   DCHECK(ssl == ssl_);
 
@@ -1705,6 +1721,11 @@
 }
 
 int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketOpenSSL::CertVerifyCallback"));
+
   if (!completed_connect_) {
     // If the first handshake hasn't completed then we accept any certificates
     // because we verify after the handshake.
@@ -1739,6 +1760,11 @@
                                                     unsigned char* outlen,
                                                     const unsigned char* in,
                                                     unsigned int inlen) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424386 SSLClientSocketOpenSSL::SelectNextProtoCallback"));
+
   if (ssl_config_.next_protos.empty()) {
     *out = reinterpret_cast<uint8*>(
         const_cast<char*>(kDefaultSupportedNPNProtocol));
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index 8ac29ef..23bb111 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -239,8 +239,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     SSLClientSocketPoolTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 // Tests that the final socket will connect even if all sockets
 // prior to it fail.
diff --git a/net/socket/tcp_listen_socket.cc b/net/socket/tcp_listen_socket.cc
index 585c412..11b2390 100644
--- a/net/socket/tcp_listen_socket.cc
+++ b/net/socket/tcp_listen_socket.cc
@@ -31,7 +31,9 @@
 
 // static
 scoped_ptr<TCPListenSocket> TCPListenSocket::CreateAndListen(
-    const string& ip, int port, StreamListenSocket::Delegate* del) {
+    const string& ip,
+    uint16 port,
+    StreamListenSocket::Delegate* del) {
   SocketDescriptor s = CreateAndBind(ip, port);
   if (s == kInvalidSocket)
     return scoped_ptr<TCPListenSocket>();
@@ -47,7 +49,7 @@
 
 TCPListenSocket::~TCPListenSocket() {}
 
-SocketDescriptor TCPListenSocket::CreateAndBind(const string& ip, int port) {
+SocketDescriptor TCPListenSocket::CreateAndBind(const string& ip, uint16 port) {
   SocketDescriptor s = CreatePlatformSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (s != kInvalidSocket) {
 #if defined(OS_POSIX)
@@ -74,7 +76,7 @@
 }
 
 SocketDescriptor TCPListenSocket::CreateAndBindAnyPort(const string& ip,
-                                                       int* port) {
+                                                       uint16* port) {
   SocketDescriptor s = CreateAndBind(ip, 0);
   if (s == kInvalidSocket)
     return kInvalidSocket;
@@ -110,16 +112,4 @@
   socket_delegate_->DidAccept(this, sock.Pass());
 }
 
-TCPListenSocketFactory::TCPListenSocketFactory(const string& ip, int port)
-    : ip_(ip),
-      port_(port) {
-}
-
-TCPListenSocketFactory::~TCPListenSocketFactory() {}
-
-scoped_ptr<StreamListenSocket> TCPListenSocketFactory::CreateAndListen(
-    StreamListenSocket::Delegate* delegate) const {
-  return TCPListenSocket::CreateAndListen(ip_, port_, delegate);
-}
-
 }  // namespace net
diff --git a/net/socket/tcp_listen_socket.h b/net/socket/tcp_listen_socket.h
index 1702e50..01a08a1 100644
--- a/net/socket/tcp_listen_socket.h
+++ b/net/socket/tcp_listen_socket.h
@@ -21,14 +21,16 @@
   // Listen on port for the specified IP address.  Use 127.0.0.1 to only
   // accept local connections.
   static scoped_ptr<TCPListenSocket> CreateAndListen(
-      const std::string& ip, int port, StreamListenSocket::Delegate* del);
+      const std::string& ip,
+      uint16 port,
+      StreamListenSocket::Delegate* del);
 
   // Get raw TCP socket descriptor bound to ip:port.
-  static SocketDescriptor CreateAndBind(const std::string& ip, int port);
+  static SocketDescriptor CreateAndBind(const std::string& ip, uint16 port);
 
   // Get raw TCP socket descriptor bound to ip and return port it is bound to.
   static SocketDescriptor CreateAndBindAnyPort(const std::string& ip,
-                                               int* port);
+                                               uint16* port);
 
  protected:
   TCPListenSocket(SocketDescriptor s, StreamListenSocket::Delegate* del);
@@ -40,23 +42,6 @@
   DISALLOW_COPY_AND_ASSIGN(TCPListenSocket);
 };
 
-// Factory that can be used to instantiate TCPListenSocket.
-class NET_EXPORT TCPListenSocketFactory : public StreamListenSocketFactory {
- public:
-  TCPListenSocketFactory(const std::string& ip, int port);
-  ~TCPListenSocketFactory() override;
-
-  // StreamListenSocketFactory overrides.
-  scoped_ptr<StreamListenSocket> CreateAndListen(
-      StreamListenSocket::Delegate* delegate) const override;
-
- private:
-  const std::string ip_;
-  const int port_;
-
-  DISALLOW_COPY_AND_ASSIGN(TCPListenSocketFactory);
-};
-
 }  // namespace net
 
 #endif  // NET_SOCKET_TCP_LISTEN_SOCKET_H_
diff --git a/net/socket/tcp_server_socket_unittest.cc b/net/socket/tcp_server_socket_unittest.cc
index 01bae9f..2f6491b 100644
--- a/net/socket/tcp_server_socket_unittest.cc
+++ b/net/socket/tcp_server_socket_unittest.cc
@@ -50,7 +50,7 @@
     *success = true;
   }
 
-  void ParseAddress(std::string ip_str, int port, IPEndPoint* address) {
+  void ParseAddress(std::string ip_str, uint16 port, IPEndPoint* address) {
     IPAddressNumber ip_number;
     bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
     if (!rv)
diff --git a/net/socket/tcp_socket_unittest.cc b/net/socket/tcp_socket_unittest.cc
index 1981388..4bfc138 100644
--- a/net/socket/tcp_socket_unittest.cc
+++ b/net/socket/tcp_socket_unittest.cc
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "net/base/address_list.h"
@@ -56,7 +57,9 @@
     *success = true;
   }
 
-  void ParseAddress(const std::string& ip_str, int port, IPEndPoint* address) {
+  void ParseAddress(const std::string& ip_str,
+                    uint16 port,
+                    IPEndPoint* address) {
     IPAddressNumber ip_number;
     bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
     if (!rv)
diff --git a/net/socket/transport_client_socket_unittest.cc b/net/socket/transport_client_socket_unittest.cc
index d01cbad..e4e060a 100644
--- a/net/socket/transport_client_socket_unittest.cc
+++ b/net/socket/transport_client_socket_unittest.cc
@@ -89,7 +89,7 @@
   }
 
  protected:
-  int listen_port_;
+  uint16 listen_port_;
   CapturingNetLog net_log_;
   ClientSocketFactory* const socket_factory_;
   scoped_ptr<StreamSocket> sock_;
@@ -105,10 +105,10 @@
 
   // Find a free port to listen on
   scoped_ptr<TCPListenSocket> sock;
-  int port;
+  uint16 port;
   // Range of ports to listen on.  Shouldn't need to try many.
-  const int kMinPort = 10100;
-  const int kMaxPort = 10200;
+  const uint16 kMinPort = 10100;
+  const uint16 kMaxPort = 10200;
 #if defined(OS_WIN)
   EnsureWinsockInit();
 #endif
diff --git a/net/socket/unix_domain_server_socket_posix.cc b/net/socket/unix_domain_server_socket_posix.cc
index 4d63283..6866d36 100644
--- a/net/socket/unix_domain_server_socket_posix.cc
+++ b/net/socket/unix_domain_server_socket_posix.cc
@@ -67,7 +67,7 @@
 
 int UnixDomainServerSocket::ListenWithAddressAndPort(
     const std::string& unix_domain_path,
-    int port_unused,
+    uint16 port_unused,
     int backlog) {
   DCHECK(!listen_socket_);
 
diff --git a/net/socket/unix_domain_server_socket_posix.h b/net/socket/unix_domain_server_socket_posix.h
index 0a26eb3..1097548 100644
--- a/net/socket/unix_domain_server_socket_posix.h
+++ b/net/socket/unix_domain_server_socket_posix.h
@@ -53,7 +53,7 @@
   // ServerSocket implementation.
   int Listen(const IPEndPoint& address, int backlog) override;
   int ListenWithAddressAndPort(const std::string& unix_domain_path,
-                               int port_unused,
+                               uint16 port_unused,
                                int backlog) override;
   int GetLocalAddress(IPEndPoint* address) const override;
   int Accept(scoped_ptr<StreamSocket>* socket,
diff --git a/net/spdy/buffered_spdy_framer_unittest.cc b/net/spdy/buffered_spdy_framer_unittest.cc
index 11f8d08..5304f08 100644
--- a/net/spdy/buffered_spdy_framer_unittest.cc
+++ b/net/spdy/buffered_spdy_framer_unittest.cc
@@ -208,8 +208,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     BufferedSpdyFramerTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 TEST_P(BufferedSpdyFramerTest, OnSetting) {
   SpdyFramer framer(spdy_version());
diff --git a/net/spdy/hpack_huffman_aggregator.cc b/net/spdy/hpack_huffman_aggregator.cc
index 41a3f48..8080a9b 100644
--- a/net/spdy/hpack_huffman_aggregator.cc
+++ b/net/spdy/hpack_huffman_aggregator.cc
@@ -49,10 +49,8 @@
   if (IsCrossOrigin(request)) {
     return;
   }
-  HostPortPair endpoint = HostPortPair(request.url.HostNoBrackets(),
-                                       request.url.EffectiveIntPort());
-  HpackEncoder* encoder = ObtainEncoder(
-      SpdySessionKey(endpoint, proxy, request.privacy_mode));
+  HpackEncoder* encoder = ObtainEncoder(SpdySessionKey(
+      HostPortPair::FromURL(request.url), proxy, request.privacy_mode));
 
   // Convert and encode the request and response header sets.
   {
@@ -108,8 +106,6 @@
 bool HpackHuffmanAggregator::IsCrossOrigin(const HttpRequestInfo& request) {
   // Require that the request is top-level, or that it shares
   // an origin with its referer.
-  HostPortPair endpoint = HostPortPair(request.url.HostNoBrackets(),
-                                       request.url.EffectiveIntPort());
   if ((request.load_flags & LOAD_MAIN_FRAME) == 0) {
     std::string referer_str;
     if (!request.extra_headers.GetHeader(HttpRequestHeaders::kReferer,
@@ -118,9 +114,8 @@
       return true;
     }
     GURL referer(referer_str);
-    HostPortPair referer_endpoint = HostPortPair(referer.HostNoBrackets(),
-                                                 referer.EffectiveIntPort());
-    if (!endpoint.Equals(referer_endpoint)) {
+    if (!HostPortPair::FromURL(request.url).Equals(
+        HostPortPair::FromURL(referer))) {
       // Cross-origin request.
       return true;
     }
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index c08b597..f1b1de3 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -1991,7 +1991,8 @@
       DCHECK(successful_read);
       if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
                                                 status_raw)) {
-        status = static_cast<SpdyRstStreamStatus>(status_raw);
+        status =
+            SpdyConstants::ParseRstStreamStatus(protocol_version(), status_raw);
       } else {
         if (protocol_version() > SPDY3) {
           // Treat unrecognized status codes as INTERNAL_ERROR as
@@ -2484,7 +2485,8 @@
     builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
   }
 
-  builder.WriteUInt32(rst_stream.status());
+  builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
+      protocol_version(), rst_stream.status()));
 
   // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
   if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc
index 2b7bc4b..2fac61c 100644
--- a/net/spdy/spdy_framer_test.cc
+++ b/net/spdy/spdy_framer_test.cc
@@ -2474,7 +2474,7 @@
       0x00, 0x00, 0x04, 0x03,
       0x00, 0x7f, 0xff, 0xff,
       0xff, 0x00, 0x00, 0x00,
-      0x06,
+      0x02,
     };
     SpdyRstStreamIR rst_stream(0x7FFFFFFF,
                                RST_STREAM_INTERNAL_ERROR,
diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc
index 574b76a..f22b75f 100644
--- a/net/spdy/spdy_http_stream_unittest.cc
+++ b/net/spdy/spdy_http_stream_unittest.cc
@@ -130,8 +130,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     SpdyHttpStreamTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 // SpdyHttpStream::GetUploadProgress() should still work even before the
 // stream is initialized.
@@ -700,9 +699,6 @@
 // Test the receipt of a WINDOW_UPDATE frame while waiting for a chunk to be
 // made available is handled correctly.
 TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) {
-  if (GetParam() < kProtoSPDY3)
-    return;
-
   scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
   scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, true));
   MockWrite writes[] = {
diff --git a/net/spdy/spdy_http_utils.cc b/net/spdy/spdy_http_utils.cc
index b67e699..fc77f5d 100644
--- a/net/spdy/spdy_http_utils.cc
+++ b/net/spdy/spdy_http_utils.cc
@@ -170,42 +170,21 @@
     SpdyMajorVersion protocol_version) {
   DCHECK_GE(priority, MINIMUM_PRIORITY);
   DCHECK_LE(priority, MAXIMUM_PRIORITY);
-  if (protocol_version == SPDY2) {
-    // SPDY 2 only has 2 bits of priority, but we have 5 RequestPriorities.
-    // Map IDLE => 3, LOWEST => 2, LOW => 2, MEDIUM => 1, HIGHEST => 0.
-    if (priority > LOWEST) {
-      return static_cast<SpdyPriority>(HIGHEST - priority);
-    } else {
-      return static_cast<SpdyPriority>(HIGHEST - priority - 1);
-    }
-  } else {
-    return static_cast<SpdyPriority>(HIGHEST - priority);
-  }
+  return static_cast<SpdyPriority>(MAXIMUM_PRIORITY - priority);
 }
 
 NET_EXPORT_PRIVATE RequestPriority ConvertSpdyPriorityToRequestPriority(
     SpdyPriority priority,
     SpdyMajorVersion protocol_version) {
-  // Handle invalid values gracefully, and pick LOW to map 2 back
-  // to for SPDY/2.
-  SpdyPriority idle_cutoff = (protocol_version == SPDY2) ? 3 : 5;
-  return (priority >= idle_cutoff) ?
-      IDLE : static_cast<RequestPriority>(HIGHEST - priority);
+  // Handle invalid values gracefully.
+  // Note that SpdyPriority is not an enum, hence the magic constants.
+  return (priority >= 5) ?
+      IDLE : static_cast<RequestPriority>(4 - priority);
 }
 
 GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers,
                            SpdyMajorVersion protocol_version,
                            bool pushed) {
-  // SPDY 2 server push urls are specified in a single "url" header.
-  if (pushed && protocol_version == SPDY2) {
-      std::string url;
-      SpdyHeaderBlock::const_iterator it;
-      it = headers.find("url");
-      if (it != headers.end())
-        url = it->second;
-      return GURL(url);
-  }
-
   const char* scheme_header = protocol_version >= SPDY3 ? ":scheme" : "scheme";
   const char* host_header = protocol_version >= SPDY4 ? ":authority" :
       (protocol_version >= SPDY3 ? ":host" : "host");
diff --git a/net/spdy/spdy_http_utils_unittest.cc b/net/spdy/spdy_http_utils_unittest.cc
index d811164..b66534b 100644
--- a/net/spdy/spdy_http_utils_unittest.cc
+++ b/net/spdy/spdy_http_utils_unittest.cc
@@ -11,14 +11,6 @@
 
 namespace {
 
-TEST(SpdyHttpUtilsTest, ConvertRequestPriorityToSpdy2Priority) {
-  EXPECT_EQ(0, ConvertRequestPriorityToSpdyPriority(HIGHEST, SPDY2));
-  EXPECT_EQ(1, ConvertRequestPriorityToSpdyPriority(MEDIUM, SPDY2));
-  EXPECT_EQ(2, ConvertRequestPriorityToSpdyPriority(LOW, SPDY2));
-  EXPECT_EQ(2, ConvertRequestPriorityToSpdyPriority(LOWEST, SPDY2));
-  EXPECT_EQ(3, ConvertRequestPriorityToSpdyPriority(IDLE, SPDY2));
-}
-
 TEST(SpdyHttpUtilsTest, ConvertRequestPriorityToSpdy3Priority) {
   EXPECT_EQ(0, ConvertRequestPriorityToSpdyPriority(HIGHEST, SPDY3));
   EXPECT_EQ(1, ConvertRequestPriorityToSpdyPriority(MEDIUM, SPDY3));
@@ -27,18 +19,6 @@
   EXPECT_EQ(4, ConvertRequestPriorityToSpdyPriority(IDLE, SPDY3));
 }
 
-TEST(SpdyHttpUtilsTest, ConvertSpdy2PriorityToRequestPriority) {
-  EXPECT_EQ(HIGHEST, ConvertSpdyPriorityToRequestPriority(0, SPDY2));
-  EXPECT_EQ(MEDIUM, ConvertSpdyPriorityToRequestPriority(1, SPDY2));
-  EXPECT_EQ(LOW, ConvertSpdyPriorityToRequestPriority(2, SPDY2));
-  EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(3, SPDY2));
-  // These are invalid values, but we should still handle them
-  // gracefully.
-  for (int i = 4; i < kuint8max; ++i) {
-    EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(i, SPDY2));
-  }
-}
-
 TEST(SpdyHttpUtilsTest, ConvertSpdy3PriorityToRequestPriority) {
   EXPECT_EQ(HIGHEST, ConvertSpdyPriorityToRequestPriority(0, SPDY3));
   EXPECT_EQ(MEDIUM, ConvertSpdyPriorityToRequestPriority(1, SPDY3));
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index edb39e9..3836fd3 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -58,7 +58,7 @@
 
 struct SpdyNetworkTransactionTestParams {
   SpdyNetworkTransactionTestParams()
-      : protocol(kProtoSPDY3),
+      : protocol(kProtoSPDY31),
         ssl_type(SPDYNPN) {}
 
   SpdyNetworkTransactionTestParams(
@@ -717,12 +717,6 @@
     Spdy,
     SpdyNetworkTransactionTest,
     ::testing::Values(
-        SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNOSSL),
-        SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYSSL),
-        SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNPN),
-        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL),
-        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL),
-        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
         SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
         SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
         SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
@@ -5843,9 +5837,6 @@
 // limitations as described above and it's not deterministic, tests may
 // fail under specific circumstances.
 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
-  if (GetParam().protocol < kProtoSPDY3)
-    return;
-
   static int kFrameCount = 2;
   scoped_ptr<std::string> content(
       new std::string(kMaxSpdyFrameChunkSize, 'a'));
@@ -5934,9 +5925,6 @@
 // Test that received data frames and sent WINDOW_UPDATE frames change
 // the recv_window_size_ correctly.
 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
-  if (GetParam().protocol < kProtoSPDY3)
-    return;
-
   // Amount of body required to trigger a sent window update.
   const size_t kTargetSize = kSpdyStreamInitialWindowSize / 2 + 1;
 
@@ -6016,9 +6004,6 @@
 
 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
-  if (GetParam().protocol < kProtoSPDY3)
-    return;
-
   // Number of full frames we hope to write (but will not, used to
   // set content-length header correctly)
   static int kFrameCount = 3;
@@ -6098,9 +6083,6 @@
 // After that, next read is artifically enforced, which causes a
 // WINDOW_UPDATE to be read and I/O process resumes.
 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
-  if (GetParam().protocol < kProtoSPDY3)
-    return;
-
   // Number of frames we need to send to zero out the window size: data
   // frames plus SYN_STREAM plus the last data frame; also we need another
   // data frame that we will send once the WINDOW_UPDATE is received,
@@ -6212,9 +6194,6 @@
 // Test we correctly handle the case where the SETTINGS frame results in
 // unstalling the send window.
 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
-  if (GetParam().protocol < kProtoSPDY3)
-    return;
-
   // Number of frames we need to send to zero out the window size: data
   // frames plus SYN_STREAM plus the last data frame; also we need another
   // data frame that we will send once the SETTING is received, therefore +3.
@@ -6333,9 +6312,6 @@
 // Test we correctly handle the case where the SETTINGS frame results in a
 // negative send window size.
 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
-  if (GetParam().protocol < kProtoSPDY3)
-    return;
-
   // Number of frames we need to send to zero out the window size: data
   // frames plus SYN_STREAM plus the last data frame; also we need another
   // data frame that we will send once the SETTING is received, therefore +3.
@@ -6390,10 +6366,7 @@
       spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
 
   reads.push_back(CreateMockRead(*settings_frame_small, i++));
-
-  if (GetParam().protocol >= kProtoSPDY3)
-    reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
-
+  reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
   reads.push_back(CreateMockRead(*window_update_init_size, i++));
 
   scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
@@ -6557,10 +6530,7 @@
 INSTANTIATE_TEST_CASE_P(
     Spdy,
     SpdyNetworkTransactionNoTLSUsageCheckTest,
-    ::testing::Values(SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2,
-                                                       SPDYNPN),
-                      SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
-                      SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN)));
+    ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN)));
 
 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
   scoped_ptr<SSLSocketDataProvider> ssl_provider(
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc
index ba5d867..a707ef4 100644
--- a/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -142,8 +142,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     SpdyProxyClientSocketTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
     : spdy_util_(GetParam()),
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 08d838a..1c9abce 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -271,6 +271,14 @@
   return dict;
 }
 
+base::Value* NetLogSpdyAdoptedPushStreamCallback(
+    SpdyStreamId stream_id, const GURL* url, NetLog::LogLevel log_level) {
+  base::DictionaryValue* dict = new base::DictionaryValue();
+  dict->SetInteger("stream_id", stream_id);
+  dict->SetString("url", url->spec());
+  return dict;
+}
+
 // Helper function to return the total size of an array of objects
 // with .size() member functions.
 template <typename T, size_t N> size_t GetTotalSize(const T (&arr)[N]) {
@@ -1963,7 +1971,9 @@
     return base::WeakPtr<SpdyStream>();
   }
 
-  net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM);
+  net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM,
+                    base::Bind(&NetLogSpdyAdoptedPushStreamCallback,
+                               active_it->second.stream->stream_id(), &url));
   used_push_streams.Increment();
   return active_it->second.stream->GetWeakPtr();
 }
diff --git a/net/spdy/spdy_session_pool_unittest.cc b/net/spdy/spdy_session_pool_unittest.cc
index fc38cc2..9d5e48c 100644
--- a/net/spdy/spdy_session_pool_unittest.cc
+++ b/net/spdy/spdy_session_pool_unittest.cc
@@ -51,8 +51,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     SpdySessionPoolTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 // A delegate that opens a new session when it is closed.
 class SessionOpeningDelegate : public SpdyStream::Delegate {
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 02e0c74..6ec3383 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -181,8 +181,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     SpdySessionTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 // Try to create a SPDY session that will fail during
 // initialization. Nothing should blow up.
@@ -1798,10 +1797,6 @@
   data.RunFor(1);
   // Regression test of compression performance under the request fixture.
   switch (spdy_util_.spdy_version()) {
-    case SPDY2:
-      histogram_tester.ExpectBucketCount(
-          "Net.SpdySynStreamCompressionPercentage", 0, 1);
-      break;
     case SPDY3:
       histogram_tester.ExpectBucketCount(
           "Net.SpdySynStreamCompressionPercentage", 30, 1);
@@ -3084,22 +3079,12 @@
 
   EXPECT_EQ(spdy_util_.spdy_version(),
             session->buffered_spdy_framer_->protocol_version());
-  if (GetParam() == kProtoDeprecatedSPDY2) {
-    EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
-    EXPECT_EQ(0, session->session_send_window_size_);
-    EXPECT_EQ(0, session->session_recv_window_size_);
-  } else if (GetParam() == kProtoSPDY3) {
-    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
-    EXPECT_EQ(0, session->session_send_window_size_);
-    EXPECT_EQ(0, session->session_recv_window_size_);
-  } else {
-    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
-              session->flow_control_state());
-    EXPECT_EQ(kSpdySessionInitialWindowSize,
-              session->session_send_window_size_);
-    EXPECT_EQ(kSpdySessionInitialWindowSize,
-              session->session_recv_window_size_);
-  }
+  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
+            session->flow_control_state());
+  EXPECT_EQ(kSpdySessionInitialWindowSize,
+            session->session_send_window_size_);
+  EXPECT_EQ(kSpdySessionInitialWindowSize,
+            session->session_recv_window_size_);
   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
 }
 
@@ -3455,9 +3440,6 @@
 // The tests below are only for SPDY/3 and above.
 
 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
-  if (GetParam() < kProtoSPDY3)
-    return;
-
   // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
   // gets sent.
   SettingsMap new_settings;
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc
index 96153bf..e8915bb 100644
--- a/net/spdy/spdy_stream_unittest.cc
+++ b/net/spdy/spdy_stream_unittest.cc
@@ -110,8 +110,7 @@
 INSTANTIATE_TEST_CASE_P(
     NextProto,
     SpdyStreamTest,
-    testing::Values(kProtoDeprecatedSPDY2,
-                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
+    testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
 
 TEST_P(SpdyStreamTest, SendDataAfterOpen) {
   GURL url(kStreamUrl);
@@ -717,9 +716,6 @@
 // to overflow an int32. The SpdyStream should handle that case
 // gracefully.
 TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
-  if (spdy_util_.protocol() < kProtoSPDY3)
-    return;
-
   session_ =
       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
 
@@ -877,17 +873,11 @@
 }
 
 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) {
-  if (spdy_util_.protocol() < kProtoSPDY3)
-    return;
-
   RunResumeAfterUnstallRequestResponseTest(
       base::Bind(&IncreaseStreamSendWindowSize));
 }
 
 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
-  if (spdy_util_.protocol() < kProtoSPDY3)
-    return;
-
   RunResumeAfterUnstallRequestResponseTest(
       base::Bind(&AdjustStreamSendWindowSize));
 }
@@ -972,17 +962,11 @@
 }
 
 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) {
-  if (spdy_util_.protocol() < kProtoSPDY3)
-    return;
-
   RunResumeAfterUnstallBidirectionalTest(
       base::Bind(&IncreaseStreamSendWindowSize));
 }
 
 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
-  if (spdy_util_.protocol() < kProtoSPDY3)
-    return;
-
   RunResumeAfterUnstallBidirectionalTest(
       base::Bind(&AdjustStreamSendWindowSize));
 }
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 801d67d..9543e64 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -54,8 +54,6 @@
 NextProtoVector SpdyNextProtos() {
   NextProtoVector next_protos;
   next_protos.push_back(kProtoHTTP11);
-  next_protos.push_back(kProtoDeprecatedSPDY2);
-  next_protos.push_back(kProtoSPDY3);
   next_protos.push_back(kProtoSPDY31);
   next_protos.push_back(kProtoSPDY4_14);
   next_protos.push_back(kProtoSPDY4_15);
@@ -720,15 +718,11 @@
 
 void SpdyTestUtil::AddUrlToHeaderBlock(base::StringPiece url,
                                        SpdyHeaderBlock* headers) const {
-  if (is_spdy2()) {
-    (*headers)["url"] = url.as_string();
-  } else {
-    std::string scheme, host, path;
-    ParseUrl(url, &scheme, &host, &path);
-    (*headers)[GetSchemeKey()] = scheme;
-    (*headers)[GetHostKey()] = host;
-    (*headers)[GetPathKey()] = path;
-  }
+  std::string scheme, host, path;
+  ParseUrl(url, &scheme, &host, &path);
+  (*headers)[GetSchemeKey()] = scheme;
+  (*headers)[GetHostKey()] = host;
+  (*headers)[GetPathKey()] = path;
 }
 
 scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructGetHeaderBlock(
@@ -739,8 +733,6 @@
 scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructGetHeaderBlockForProxy(
     base::StringPiece url) const {
   scoped_ptr<SpdyHeaderBlock> headers(ConstructGetHeaderBlock(url));
-  if (is_spdy2())
-    (*headers)[GetPathKey()] = url.data();
   return headers.Pass();
 }
 
@@ -963,8 +955,7 @@
                                           bool direct) const {
   SpdyHeaderBlock block;
   block[GetMethodKey()] = "GET";
-  block[GetPathKey()] =
-      (is_spdy2() && !direct) ? "http://www.google.com/" : "/";
+  block[GetPathKey()] = "/";
   block[GetHostKey()] = "www.google.com";
   block[GetSchemeKey()] = "http";
   MaybeAddVersionHeader(&block);
@@ -1259,16 +1250,14 @@
 }
 
 const char* SpdyTestUtil::GetMethodKey() const {
-  return is_spdy2() ? "method" : ":method";
+  return ":method";
 }
 
 const char* SpdyTestUtil::GetStatusKey() const {
-  return is_spdy2() ? "status" : ":status";
+  return ":status";
 }
 
 const char* SpdyTestUtil::GetHostKey() const {
-  if (protocol_ < kProtoSPDY3)
-    return "host";
   if (protocol_ < kProtoSPDY4MinimumVersion)
     return ":host";
   else
@@ -1276,15 +1265,15 @@
 }
 
 const char* SpdyTestUtil::GetSchemeKey() const {
-  return is_spdy2() ? "scheme" : ":scheme";
+  return ":scheme";
 }
 
 const char* SpdyTestUtil::GetVersionKey() const {
-  return is_spdy2() ? "version" : ":version";
+  return ":version";
 }
 
 const char* SpdyTestUtil::GetPathKey() const {
-  return is_spdy2() ? "url" : ":path";
+  return ":path";
 }
 
 scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructHeaderBlock(
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h
index b08657c..0ee59d4 100644
--- a/net/spdy/spdy_test_util_common.h
+++ b/net/spdy/spdy_test_util_common.h
@@ -551,7 +551,6 @@
 
   NextProto protocol() const { return protocol_; }
   SpdyMajorVersion spdy_version() const { return spdy_version_; }
-  bool is_spdy2() const { return protocol_ < kProtoSPDY3; }
   bool include_version_header() const {
     return protocol_ < kProtoSPDY4MinimumVersion;
   }
diff --git a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
index 66a9bd9..6121a2a 100644
--- a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
+++ b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
@@ -86,8 +86,8 @@
             mIsRedirect = isRedirect;
             mIsNotFound = isNotFound;
             mResponseData = responseData;
-            mResponseHeaders = responseHeaders == null ?
-                    new ArrayList<Pair<String, String>>() : responseHeaders;
+            mResponseHeaders = responseHeaders == null
+                    ? new ArrayList<Pair<String, String>>() : responseHeaders;
             mResponseAction = responseAction;
         }
     }
@@ -534,30 +534,30 @@
          * single self-generated key. The subject name is "Test Server".
          */
         private static final String SERVER_KEYS_BKS =
-                "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41" +
-                "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
-                "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
-                "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw" +
-                "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
-                "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl" +
-                "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy" +
-                "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV" +
-                "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG" +
-                "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU" +
-                "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV" +
-                "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx" +
-                "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR" +
-                "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN" +
-                "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs" +
-                "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck" +
-                "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM" +
-                "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI" +
-                "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f" +
-                "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx" +
-                "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt" +
-                "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw" +
-                "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl" +
-                "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
+                "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41"
+                + "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET"
+                + "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV"
+                + "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw"
+                + "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U"
+                + "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl"
+                + "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy"
+                + "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV"
+                + "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG"
+                + "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU"
+                + "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV"
+                + "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx"
+                + "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR"
+                + "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN"
+                + "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs"
+                + "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck"
+                + "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM"
+                + "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI"
+                + "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f"
+                + "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx"
+                + "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt"
+                + "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw"
+                + "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl"
+                + "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
 
         private static final String PASSWORD = "android";
 
diff --git a/net/test/embedded_test_server/embedded_test_server.cc b/net/test/embedded_test_server/embedded_test_server.cc
index 7ac764f..97b5d84 100644
--- a/net/test/embedded_test_server/embedded_test_server.cc
+++ b/net/test/embedded_test_server/embedded_test_server.cc
@@ -115,7 +115,7 @@
 }
 
 EmbeddedTestServer::EmbeddedTestServer()
-    : port_(-1),
+    : port_(0),
       weak_factory_(this) {
   DCHECK(thread_checker_.CalledOnValidThread());
 }
diff --git a/net/test/embedded_test_server/embedded_test_server.h b/net/test/embedded_test_server/embedded_test_server.h
index 24ff8d7..586e1f4 100644
--- a/net/test/embedded_test_server/embedded_test_server.h
+++ b/net/test/embedded_test_server/embedded_test_server.h
@@ -136,7 +136,7 @@
               const std::string& relative_url) const;
 
   // Returns the port number used by the server.
-  int port() const { return port_; }
+  uint16 port() const { return port_; }
 
   // Registers request handler which serves files from |directory|.
   // For instance, a request to "/foo.html" is served by "foo.html" under
@@ -188,7 +188,7 @@
   scoped_ptr<base::Thread> io_thread_;
 
   scoped_ptr<HttpListenSocket> listen_socket_;
-  int port_;
+  uint16 port_;
   GURL base_url_;
 
   // Owns the HttpConnection objects.
diff --git a/net/test/embedded_test_server/embedded_test_server_unittest.cc b/net/test/embedded_test_server/embedded_test_server_unittest.cc
index 28d909e..efa4b0c 100644
--- a/net/test/embedded_test_server/embedded_test_server_unittest.cc
+++ b/net/test/embedded_test_server/embedded_test_server_unittest.cc
@@ -112,12 +112,12 @@
 };
 
 TEST_F(EmbeddedTestServerTest, GetBaseURL) {
-  EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%d/", server_->port()),
+  EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%u/", server_->port()),
                                server_->base_url().spec());
 }
 
 TEST_F(EmbeddedTestServerTest, GetURL) {
-  EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%d/path?query=foo",
+  EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%u/path?query=foo",
                                server_->port()),
             server_->GetURL("/path?query=foo").spec());
 }
diff --git a/net/tools/dump_cache/cache_dumper.cc b/net/tools/dump_cache/cache_dumper.cc
index 0ce46a9..99e3dcd 100644
--- a/net/tools/dump_cache/cache_dumper.cc
+++ b/net/tools/dump_cache/cache_dumper.cc
@@ -45,7 +45,6 @@
 #ifdef WIN32_LARGE_FILENAME_SUPPORT
   // Due to large paths on windows, it can't simply do a
   // CreateDirectory("a/b/c").  Instead, create each subdirectory manually.
-  bool rv = false;
   std::wstring::size_type pos(0);
   std::wstring backslash(L"\\");
 
diff --git a/net/tools/flip_server/spdy_interface_test.cc b/net/tools/flip_server/spdy_interface_test.cc
index 09909e2..d845438 100644
--- a/net/tools/flip_server/spdy_interface_test.cc
+++ b/net/tools/flip_server/spdy_interface_test.cc
@@ -206,8 +206,8 @@
 
 INSTANTIATE_TEST_CASE_P(SpdySMProxyTest,
                         SpdySMProxyTest,
-                        Values(SPDY2, SPDY3, SPDY4));
-INSTANTIATE_TEST_CASE_P(SpdySMServerTest, SpdySMServerTest, Values(SPDY2));
+                        Values(SPDY3, SPDY4));
+INSTANTIATE_TEST_CASE_P(SpdySMServerTest, SpdySMServerTest, Values(SPDY4));
 
 TEST_P(SpdySMProxyTest, InitSMConnection) {
   {
@@ -218,113 +218,7 @@
       NULL, NULL, epoll_server_.get(), -1, "", "", "", false);
 }
 
-TEST_P(SpdySMProxyTest, OnSynStream_SPDY2) {
-  if (GetParam() != SPDY2) {
-    // This test case is for SPDY2.
-    return;
-  }
-  BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
-  scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
-  uint32 stream_id = 92;
-  uint32 associated_id = 43;
-  std::string expected = "GET /path HTTP/1.0\r\n"
-      "Host: 127.0.0.1\r\n"
-      "hoge: fuga\r\n\r\n";
-  SpdyHeaderBlock block;
-  block["method"] = "GET";
-  block["url"] = "/path";
-  block["scheme"] = "http";
-  block["version"] = "HTTP/1.0";
-  block["hoge"] = "fuga";
-  StringSaver saver;
-  {
-    InSequence s;
-    EXPECT_CALL(*interface_, FindOrMakeNewSMConnectionInterface(_, _))
-        .WillOnce(Return(mock_interface.get()));
-    EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
-    EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _))
-        .WillOnce(DoAll(SaveArg<0>(&saver.data),
-                        SaveArg<1>(&saver.size),
-                        InvokeWithoutArgs(&saver, &StringSaver::Save),
-                        Return(0)));
-  }
-  visitor->OnSynStream(stream_id, associated_id, 0, false, false, block);
-  ASSERT_EQ(expected, saver.string);
-}
-
-TEST_P(SpdySMProxyTest, OnSynStream) {
-  if (GetParam() == SPDY2) {
-    // This test case is not for SPDY2.
-    return;
-  }
-  BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
-  scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
-  uint32 stream_id = 92;
-  uint32 associated_id = 43;
-  std::string expected = "GET /path HTTP/1.1\r\n"
-      "Host: 127.0.0.1\r\n"
-      "foo: bar\r\n\r\n";
-  SpdyHeaderBlock block;
-  block[":method"] = "GET";
-  block[":host"] = "www.example.com";
-  block[":path"] = "/path";
-  block[":scheme"] = "http";
-  block["foo"] = "bar";
-  StringSaver saver;
-  {
-    InSequence s;
-    EXPECT_CALL(*interface_,
-                FindOrMakeNewSMConnectionInterface(_, _))
-        .WillOnce(Return(mock_interface.get()));
-    EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
-    EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _))
-        .WillOnce(DoAll(SaveArg<0>(&saver.data),
-                        SaveArg<1>(&saver.size),
-                        InvokeWithoutArgs(&saver, &StringSaver::Save),
-                        Return(0)));
-  }
-  visitor->OnSynStream(stream_id, associated_id, 0, false, false, block);
-  ASSERT_EQ(expected, saver.string);
-}
-
-TEST_P(SpdySMProxyTest, OnStreamFrameData_SPDY2) {
-  if (GetParam() != SPDY2) {
-    // This test case is for SPDY2.
-    return;
-  }
-  BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
-  scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
-  uint32 stream_id = 92;
-  uint32 associated_id = 43;
-  SpdyHeaderBlock block;
-  testing::MockFunction<void(int)> checkpoint;  // NOLINT
-
-  scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12, false));
-  block["method"] = "GET";
-  block["url"] = "http://www.example.com/path";
-  block["scheme"] = "http";
-  block["version"] = "HTTP/1.0";
-  {
-    InSequence s;
-    EXPECT_CALL(*interface_, FindOrMakeNewSMConnectionInterface(_, _))
-        .WillOnce(Return(mock_interface.get()));
-    EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
-    EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)).Times(1);
-    EXPECT_CALL(checkpoint, Call(0));
-    EXPECT_CALL(*mock_interface,
-                ProcessWriteInput(frame->data(), frame->size())).Times(1);
-  }
-
-  visitor->OnSynStream(stream_id, associated_id, 0, false, false, block);
-  checkpoint.Call(0);
-  visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true);
-}
-
 TEST_P(SpdySMProxyTest, OnStreamFrameData) {
-  if (GetParam() == SPDY2) {
-    // This test case is not for SPDY2.
-    return;
-  }
   BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
   scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
   uint32 stream_id = 92;
@@ -407,14 +301,14 @@
 
 TEST_P(SpdySMProxyTest, CreateFramer) {
   interface_->ResetForNewConnection();
-  interface_->CreateFramer(SPDY2);
-  ASSERT_TRUE(interface_->spdy_framer() != NULL);
-  ASSERT_EQ(interface_->spdy_version(), SPDY2);
-
-  interface_->ResetForNewConnection();
   interface_->CreateFramer(SPDY3);
   ASSERT_TRUE(interface_->spdy_framer() != NULL);
   ASSERT_EQ(interface_->spdy_version(), SPDY3);
+
+  interface_->ResetForNewConnection();
+  interface_->CreateFramer(SPDY4);
+  ASSERT_TRUE(interface_->spdy_framer() != NULL);
+  ASSERT_EQ(interface_->spdy_version(), SPDY4);
 }
 
 TEST_P(SpdySMProxyTest, PostAcceptHook) {
@@ -455,61 +349,7 @@
   ASSERT_TRUE(HasStream(stream_id));
 }
 
-TEST_P(SpdySMProxyTest, SendErrorNotFound_SPDY2) {
-  if (GetParam() != SPDY2) {
-    // This test is for SPDY2.
-    return;
-  }
-  uint32 stream_id = 82;
-  SpdyHeaderBlock actual_header_block;
-  const char* actual_data;
-  size_t actual_size;
-  testing::MockFunction<void(int)> checkpoint;  // NOLINT
-
-  interface_->SendErrorNotFound(stream_id);
-
-  ASSERT_EQ(2u, connection_->output_list()->size());
-
-  {
-    InSequence s;
-    if (GetParam() < SPDY4) {
-      EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
-          .WillOnce(SaveArg<2>(&actual_header_block));
-    } else {
-      EXPECT_CALL(*spdy_framer_visitor_,
-                  OnHeaders(stream_id, false, 0, false, _))
-          .WillOnce(SaveArg<4>(&actual_header_block));
-    }
-    EXPECT_CALL(checkpoint, Call(0));
-    EXPECT_CALL(*spdy_framer_visitor_,
-                OnDataFrameHeader(stream_id, _, true));
-    EXPECT_CALL(*spdy_framer_visitor_,
-                OnStreamFrameData(stream_id, _, _, false)).Times(1)
-        .WillOnce(DoAll(SaveArg<1>(&actual_data),
-                        SaveArg<2>(&actual_size)));
-    EXPECT_CALL(*spdy_framer_visitor_,
-                OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
-  }
-
-  std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
-  DataFrame* df = *i++;
-  spdy_framer_->ProcessInput(df->data, df->size);
-  checkpoint.Call(0);
-  df = *i++;
-  spdy_framer_->ProcessInput(df->data, df->size);
-
-  ASSERT_EQ(2, spdy_framer_->frames_received());
-  ASSERT_EQ(2u, actual_header_block.size());
-  ASSERT_EQ("404 Not Found", actual_header_block["status"]);
-  ASSERT_EQ("HTTP/1.1", actual_header_block["version"]);
-  ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
-}
-
 TEST_P(SpdySMProxyTest, SendErrorNotFound) {
-  if (GetParam() == SPDY2) {
-    // This test is not for SPDY2.
-    return;
-  }
   uint32 stream_id = 82;
   SpdyHeaderBlock actual_header_block;
   const char* actual_data;
@@ -556,44 +396,7 @@
   ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
 }
 
-TEST_P(SpdySMProxyTest, SendSynStream_SPDY2) {
-  if (GetParam() != SPDY2) {
-    // This test is for SPDY2.
-    return;
-  }
-  uint32 stream_id = 82;
-  BalsaHeaders headers;
-  SpdyHeaderBlock actual_header_block;
-  headers.AppendHeader("key1", "value1");
-  headers.SetRequestFirstlineFromStringPieces("GET", "/path", "HTTP/1.0");
-
-  interface_->SendSynStream(stream_id, headers);
-
-  ASSERT_EQ(1u, connection_->output_list()->size());
-  std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
-  DataFrame* df = *i++;
-
-  {
-    InSequence s;
-    EXPECT_CALL(*spdy_framer_visitor_,
-                OnSynStream(stream_id, 0, _, false, false, _))
-        .WillOnce(SaveArg<5>(&actual_header_block));
-  }
-
-  spdy_framer_->ProcessInput(df->data, df->size);
-  ASSERT_EQ(1, spdy_framer_->frames_received());
-  ASSERT_EQ(4u, actual_header_block.size());
-  ASSERT_EQ("GET", actual_header_block["method"]);
-  ASSERT_EQ("HTTP/1.0", actual_header_block["version"]);
-  ASSERT_EQ("/path", actual_header_block["url"]);
-  ASSERT_EQ("value1", actual_header_block["key1"]);
-}
-
 TEST_P(SpdySMProxyTest, SendSynStream) {
-  if (GetParam() == SPDY2) {
-    // This test is not for SPDY2.
-    return;
-  }
   uint32 stream_id = 82;
   BalsaHeaders headers;
   SpdyHeaderBlock actual_header_block;
@@ -624,48 +427,7 @@
   ASSERT_EQ("value1", actual_header_block["key1"]);
 }
 
-TEST_P(SpdySMProxyTest, SendSynReply_SPDY2) {
-  if (GetParam() != SPDY2) {
-    // This test is for SPDY2.
-    return;
-  }
-  uint32 stream_id = 82;
-  BalsaHeaders headers;
-  SpdyHeaderBlock actual_header_block;
-  headers.AppendHeader("key1", "value1");
-  headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
-
-  interface_->SendSynReply(stream_id, headers);
-
-  ASSERT_EQ(1u, connection_->output_list()->size());
-  std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
-  DataFrame* df = *i++;
-
-  {
-    InSequence s;
-    if (GetParam() < SPDY4) {
-      EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
-          .WillOnce(SaveArg<2>(&actual_header_block));
-    } else {
-      EXPECT_CALL(*spdy_framer_visitor_,
-                  OnHeaders(stream_id, false, 0, false, _))
-          .WillOnce(SaveArg<4>(&actual_header_block));
-    }
-  }
-
-  spdy_framer_->ProcessInput(df->data, df->size);
-  ASSERT_EQ(1, spdy_framer_->frames_received());
-  ASSERT_EQ(3u, actual_header_block.size());
-  ASSERT_EQ("200 OK", actual_header_block["status"]);
-  ASSERT_EQ("HTTP/1.1", actual_header_block["version"]);
-  ASSERT_EQ("value1", actual_header_block["key1"]);
-}
-
 TEST_P(SpdySMProxyTest, SendSynReply) {
-  if (GetParam() == SPDY2) {
-    // This test is not for SPDY2.
-    return;
-  }
   uint32 stream_id = 82;
   BalsaHeaders headers;
   SpdyHeaderBlock actual_header_block;
@@ -763,58 +525,6 @@
   ASSERT_EQ("c", StringPiece(actual_data, actual_size));
 }
 
-TEST_P(SpdySMProxyTest, SendEOF_SPDY2) {
-  // This test is for SPDY2.
-  if (GetParam() != SPDY2) {
-    return;
-  }
-
-  uint32 stream_id = 82;
-  // SPDY2 data frame
-  char empty_data_frame[] = {'\0', '\0', '\0', '\x52', '\x1', '\0', '\0', '\0'};
-  MemCacheIter mci;
-  mci.stream_id = stream_id;
-
-  {
-    BalsaHeaders headers;
-    std::string filename = "foobar";
-    memory_cache_->InsertFile(&headers, filename, "");
-    mci.file_data = memory_cache_->GetFileData(filename);
-  }
-
-  interface_->AddToOutputOrder(mci);
-  ASSERT_TRUE(HasStream(stream_id));
-  interface_->SendEOF(stream_id);
-  ASSERT_FALSE(HasStream(stream_id));
-
-  ASSERT_EQ(1u, connection_->output_list()->size());
-  std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
-  DataFrame* df = *i++;
-  ASSERT_EQ(StringPiece(empty_data_frame, sizeof(empty_data_frame)),
-            StringPiece(df->data, df->size));
-}
-
-TEST_P(SpdySMProxyTest, SendEmptyDataFrame_SPDY2) {
-  // This test is for SPDY2.
-  if (GetParam() != SPDY2) {
-    return;
-  }
-
-  uint32 stream_id = 133;
-  SpdyDataFlags flags = DATA_FLAG_NONE;
-  // SPDY2 data frame
-  char expected[] = {'\0', '\0', '\0', '\x85', '\0', '\0', '\0', '\0'};
-
-  interface_->SendDataFrame(stream_id, "hello", 0, flags, true);
-
-  ASSERT_EQ(1u, connection_->output_list()->size());
-  std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
-  DataFrame* df = *i++;
-
-  ASSERT_EQ(StringPiece(expected, sizeof(expected)),
-            StringPiece(df->data, df->size));
-}
-
 TEST_P(SpdySMServerTest, OnSynStream) {
   BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
   uint32 stream_id = 82;
diff --git a/net/tools/gdig/gdig.cc b/net/tools/gdig/gdig.cc
index 179ab78..0f8c1fe 100644
--- a/net/tools/gdig/gdig.cc
+++ b/net/tools/gdig/gdig.cc
@@ -6,6 +6,7 @@
 #include <string>
 
 #include "base/at_exit.h"
+#include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/cancelable_callback.h"
 #include "base/command_line.h"
@@ -53,7 +54,7 @@
   if (!net::ParseIPLiteralToNumber(ip, &ip_number))
     return false;
 
-  *ip_end_point = net::IPEndPoint(ip_number, port);
+  *ip_end_point = net::IPEndPoint(ip_number, static_cast<uint16>(port));
   return true;
 }
 
@@ -90,7 +91,7 @@
        ++i) {
     const DnsHostsKey& key = i->first;
     std::string host_name = key.first;
-    output.append(IPEndPoint(i->second, -1).ToStringWithoutPort());
+    output.append(IPEndPoint(i->second, 0).ToStringWithoutPort());
     output.append(" ").append(host_name).append("\n");
   }
   return output;
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 33f30fc..dcc9345 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -221,7 +221,7 @@
                "HTTP/1.1", "200", "OK", kBarResponseBody);
   }
 
-  virtual ~EndToEndTest() {
+  ~EndToEndTest() override {
     // TODO(rtenneti): port RecycleUnusedPort if needed.
     // RecycleUnusedPort(server_address_.port());
     QuicInMemoryCachePeer::ResetForTests();
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc
index 5b5c415..496211f 100644
--- a/net/tools/quic/quic_client_session_test.cc
+++ b/net/tools/quic/quic_client_session_test.cc
@@ -46,6 +46,8 @@
     session_->InitializeSession(
         QuicServerId(kServerHostname, kPort, false, PRIVACY_MODE_DISABLED),
         &crypto_config_);
+    // Advance the time, because timers do not like uninitialized times.
+    connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
   }
 
   void CompleteCryptoHandshake() {
diff --git a/net/tools/quic/quic_server_session.cc b/net/tools/quic/quic_server_session.cc
index 45c1379..9db2365 100644
--- a/net/tools/quic/quic_server_session.cc
+++ b/net/tools/quic/quic_server_session.cc
@@ -38,14 +38,29 @@
 
 void QuicServerSession::OnConfigNegotiated() {
   QuicSession::OnConfigNegotiated();
-  if (!FLAGS_enable_quic_fec ||
-      !config()->HasReceivedConnectionOptions() ||
-      !net::ContainsQuicTag(config()->ReceivedConnectionOptions(), kFHDR)) {
+
+  if (!config()->HasReceivedConnectionOptions()) {
     return;
   }
-  // kFHDR config maps to FEC protection always for headers stream.
-  // TODO(jri): Add crypto stream in addition to headers for kHDR.
-  headers_stream_->set_fec_policy(FEC_PROTECT_ALWAYS);
+
+  // If the client has provided a bandwidth estimate from the same serving
+  // region, then pass it to the sent packet manager in preparation for possible
+  // bandwidth resumption.
+  const CachedNetworkParameters* cached_network_params =
+      crypto_stream_->previous_cached_network_params();
+  if (FLAGS_quic_enable_bandwidth_resumption_experiment &&
+      cached_network_params != nullptr &&
+      ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWRE) &&
+      cached_network_params->serving_region() == serving_region_) {
+    connection()->ResumeConnectionState(*cached_network_params);
+  }
+
+  if (FLAGS_enable_quic_fec &&
+      ContainsQuicTag(config()->ReceivedConnectionOptions(), kFHDR)) {
+    // kFHDR config maps to FEC protection always for headers stream.
+    // TODO(jri): Add crypto stream in addition to headers for kHDR.
+    headers_stream_->set_fec_policy(FEC_PROTECT_ALWAYS);
+  }
 }
 
 void QuicServerSession::OnConnectionClosed(QuicErrorCode error,
diff --git a/net/tools/quic/quic_server_session_test.cc b/net/tools/quic/quic_server_session_test.cc
index 6a17f53..b0ed5d1 100644
--- a/net/tools/quic/quic_server_session_test.cc
+++ b/net/tools/quic/quic_server_session_test.cc
@@ -292,7 +292,7 @@
   explicit MockQuicCryptoServerStream(
       const QuicCryptoServerConfig& crypto_config, QuicSession* session)
       : QuicCryptoServerStream(crypto_config, session) {}
-  virtual ~MockQuicCryptoServerStream() {}
+  ~MockQuicCryptoServerStream() override {}
 
   MOCK_METHOD1(SendServerConfigUpdate,
                void(const CachedNetworkParameters* cached_network_parameters));
@@ -383,6 +383,46 @@
   session_->OnCongestionWindowChange(now);
 }
 
+TEST_P(QuicServerSessionTest, BandwidthResumptionExperiment) {
+  ValueRestore<bool> old_flag(
+      &FLAGS_quic_enable_bandwidth_resumption_experiment, true);
+
+  // Test that if a client provides a CachedNetworkParameters with the same
+  // serving region as the current server, that this data is passed down to the
+  // send algorithm.
+
+  // Client has sent kBWRE connection option to trigger bandwidth resumption.
+  QuicTagVector copt;
+  copt.push_back(kBWRE);
+  QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
+
+  const string kTestServingRegion = "a serving region";
+  session_->set_serving_region(kTestServingRegion);
+
+  QuicCryptoServerStream* crypto_stream =
+      static_cast<QuicCryptoServerStream*>(
+          QuicSessionPeer::GetCryptoStream(session_.get()));
+
+  // No effect if no CachedNetworkParameters provided.
+  EXPECT_CALL(*connection_, ResumeConnectionState(_)).Times(0);
+  session_->OnConfigNegotiated();
+
+  // No effect if CachedNetworkParameters provided, but different serving
+  // regions.
+  CachedNetworkParameters cached_network_params;
+  cached_network_params.set_bandwidth_estimate_bytes_per_second(1);
+  cached_network_params.set_serving_region("different serving region");
+  crypto_stream->set_previous_cached_network_params(cached_network_params);
+  EXPECT_CALL(*connection_, ResumeConnectionState(_)).Times(0);
+  session_->OnConfigNegotiated();
+
+  // Same serving region results in CachedNetworkParameters being stored.
+  cached_network_params.set_serving_region(kTestServingRegion);
+  crypto_stream->set_previous_cached_network_params(cached_network_params);
+  EXPECT_CALL(*connection_, ResumeConnectionState(_)).Times(1);
+  session_->OnConfigNegotiated();
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace tools
diff --git a/net/tools/quic/quic_spdy_server_stream_test.cc b/net/tools/quic/quic_spdy_server_stream_test.cc
index 4f5484a..8a3600c 100644
--- a/net/tools/quic/quic_spdy_server_stream_test.cc
+++ b/net/tools/quic/quic_spdy_server_stream_test.cc
@@ -97,7 +97,7 @@
     QuicInMemoryCachePeer::ResetForTests();
   }
 
-  virtual void SetUp() override {
+  void SetUp() override {
     QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
 
     BalsaHeaders request_headers, response_headers;
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc
index 05c3954..4e5d7c3 100644
--- a/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -95,9 +95,9 @@
         client_address_(net::test::TestPeerIPAddress(), kTestPort),
         writer_is_blocked_(false) {}
 
-  virtual ~QuicTimeWaitListManagerTest() override {}
+  ~QuicTimeWaitListManagerTest() override {}
 
-  virtual void SetUp() override {
+  void SetUp() override {
     EXPECT_CALL(writer_, IsWriteBlocked())
         .WillRepeatedly(ReturnPointee(&writer_is_blocked_));
     EXPECT_CALL(writer_, IsWriteBlockedDataBuffered())
diff --git a/net/tools/quic/test_tools/mock_quic_dispatcher.h b/net/tools/quic/test_tools/mock_quic_dispatcher.h
index df32ce4..81f1004 100644
--- a/net/tools/quic/test_tools/mock_quic_dispatcher.h
+++ b/net/tools/quic/test_tools/mock_quic_dispatcher.h
@@ -24,7 +24,7 @@
                      PacketWriterFactory* packet_writer_factory,
                      EpollServer* eps);
 
-  virtual ~MockQuicDispatcher();
+  ~MockQuicDispatcher() override;
 
   MOCK_METHOD3(ProcessPacket, void(const IPEndPoint& server_address,
                                    const IPEndPoint& client_address,
diff --git a/net/tools/quic/test_tools/quic_test_utils.h b/net/tools/quic/test_tools/quic_test_utils.h
index 9db9fb5..e1220cb 100644
--- a/net/tools/quic/test_tools/quic_test_utils.h
+++ b/net/tools/quic/test_tools/quic_test_utils.h
@@ -10,6 +10,7 @@
 #include <string>
 
 #include "base/strings/string_piece.h"
+#include "net/quic/crypto/cached_network_parameters.h"
 #include "net/quic/quic_connection.h"
 #include "net/quic/quic_packet_writer.h"
 #include "net/quic/quic_session.h"
@@ -94,6 +95,8 @@
   MOCK_METHOD0(OnCanWrite, void());
   MOCK_CONST_METHOD0(HasPendingWrites, bool());
 
+  MOCK_METHOD1(ResumeConnectionState, void(const CachedNetworkParameters&));
+
   void ReallyProcessUdpPacket(const IPEndPoint& self_address,
                               const IPEndPoint& peer_address,
                               const QuicEncryptedPacket& packet) {
diff --git a/net/udp/udp_socket_unittest.cc b/net/udp/udp_socket_unittest.cc
index 83689c7..8282596 100644
--- a/net/udp/udp_socket_unittest.cc
+++ b/net/udp/udp_socket_unittest.cc
@@ -119,7 +119,7 @@
 };
 
 // Creates and address from an ip/port and returns it in |address|.
-void CreateUDPAddress(std::string ip_str, int port, IPEndPoint* address) {
+void CreateUDPAddress(std::string ip_str, uint16 port, IPEndPoint* address) {
   IPAddressNumber ip_number;
   bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
   if (!rv)
@@ -128,7 +128,7 @@
 }
 
 TEST_F(UDPSocketTest, Connect) {
-  const int kPort = 9999;
+  const uint16 kPort = 9999;
   std::string simple_message("hello world!");
 
   // Setup the server to listen.
@@ -216,7 +216,7 @@
 #else
 TEST_F(UDPSocketTest, Broadcast) {
 #endif
-  const int kPort = 9999;
+  const uint16 kPort = 9999;
   std::string first_message("first message"), second_message("second message");
 
   IPEndPoint broadcast_address;
@@ -369,8 +369,8 @@
 // not bind the client's reads to only be from that endpoint, and that we need
 // to always use recvfrom() to disambiguate.
 TEST_F(UDPSocketTest, VerifyConnectBindsAddr) {
-  const int kPort1 = 9999;
-  const int kPort2 = 10000;
+  const uint16 kPort1 = 9999;
+  const uint16 kPort2 = 10000;
   std::string simple_message("hello world!");
   std::string foreign_message("BAD MESSAGE TO GET!!");
 
@@ -538,7 +538,7 @@
 #endif  // defined(OS_ANDROID)
 
 TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) {
-  const int kPort = 9999;
+  const uint16 kPort = 9999;
   const char* const kGroup = "237.132.100.17";
 
   IPEndPoint bind_address;
@@ -562,7 +562,7 @@
 }
 
 TEST_F(UDPSocketTest, MulticastOptions) {
-  const int kPort = 9999;
+  const uint16 kPort = 9999;
   IPEndPoint bind_address;
   CreateUDPAddress("0.0.0.0", kPort, &bind_address);
 
diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc
index 11c731f..7be97e8 100644
--- a/net/udp/udp_socket_win.cc
+++ b/net/udp/udp_socket_win.cc
@@ -6,6 +6,7 @@
 
 #include <mstcpip.h>
 
+#include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
@@ -808,8 +809,8 @@
   DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
 
   for (int i = 0; i < kBindRetries; ++i) {
-    int rv = DoBind(IPEndPoint(address,
-                               rand_int_cb_.Run(kPortStart, kPortEnd)));
+    int rv = DoBind(IPEndPoint(
+        address, static_cast<uint16>(rand_int_cb_.Run(kPortStart, kPortEnd))));
     if (rv == OK || rv != ERR_ADDRESS_IN_USE)
       return rv;
   }
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index a2ce07e..c61a14b 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -650,12 +650,8 @@
 
   response_info_.was_cached = false;
 
-  // If the referrer is secure, but the requested URL is not, the referrer
-  // policy should be something non-default. If you hit this, please file a
-  // bug.
-  if (referrer_policy_ ==
-          CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE &&
-      GURL(referrer_).SchemeIsSecure() && !url().SchemeIsSecure()) {
+  if (GURL(referrer_) != URLRequestJob::ComputeReferrerForRedirect(
+                             referrer_policy_, referrer_, url())) {
     if (!network_delegate_ ||
         !network_delegate_->CancelURLRequestWithPolicyViolatingReferrerHeader(
             *this, url(), GURL(referrer_))) {
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 6117419..af972bd 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -94,14 +94,22 @@
   // referrer header might be cleared, if the protocol changes from HTTPS to
   // HTTP. This is the default behavior of URLRequest, corresponding to
   // CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE. Alternatively, the
-  // referrer policy can be set to never change the referrer header. This
-  // behavior corresponds to NEVER_CLEAR_REFERRER. Embedders will want to use
-  // NEVER_CLEAR_REFERRER when implementing the meta-referrer support
-  // (http://wiki.whatwg.org/wiki/Meta_referrer) and sending requests with a
-  // non-default referrer policy. Only the default referrer policy requires
-  // the referrer to be cleared on transitions from HTTPS to HTTP.
+  // referrer policy can be set to strip the referrer down to an origin upon
+  // cross-origin navigation (ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN), or
+  // never change the referrer header (NEVER_CLEAR_REFERRER). Embedders will
+  // want to use these options when implementing referrer policy support
+  // (https://w3c.github.io/webappsec/specs/referrer-policy/).
+  //
+  // REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN is a slight variant
+  // on CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE: If the request
+  // downgrades from HTTPS to HTTP, the referrer will be cleared. If the request
+  // transitions cross-origin (but does not downgrade), the referrer's
+  // granularity will be reduced (currently stripped down to an origin rather
+  // than a full URL). Same-origin requests will send the full referrer.
   enum ReferrerPolicy {
     CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+    REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+    ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
     NEVER_CLEAR_REFERRER,
   };
 
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 41420d5..838aa7b 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -122,11 +122,6 @@
     return true;
   }
 
-  int OnBeforeSocketStreamConnect(SocketStream* stream,
-                                  const CompletionCallback& callback) override {
-    return OK;
-  }
-
   DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
 };
 
diff --git a/net/url_request/url_request_data_job.cc b/net/url_request/url_request_data_job.cc
index 879b8ba..e074646 100644
--- a/net/url_request/url_request_data_job.cc
+++ b/net/url_request/url_request_data_job.cc
@@ -6,7 +6,6 @@
 
 #include "net/url_request/url_request_data_job.h"
 
-#include "base/profiler/scoped_tracker.h"
 #include "net/base/data_url.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_response_headers.h"
@@ -53,10 +52,6 @@
                                std::string* charset,
                                std::string* data,
                                const CompletionCallback& callback) const {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/422489 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("422489 URLRequestDataJob::GetData"));
-
   // Check if data URL is valid. If not, don't bother to try to extract data.
   // Otherwise, parse the data from the data URL.
   const GURL& url = request_->url();
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 33a5088..acf1d07 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -66,17 +66,13 @@
   base::Time GetRequestTime() const override;
   bool IsCachedContent() const override;
   bool IsDownload() const override;
-  bool SdchResponseExpected() const override;
+  SdchManager::DictionarySet* SdchDictionariesAdvertised() const override;
   int64 GetByteReadCount() const override;
   int GetResponseCode() const override;
   const URLRequestContext* GetURLRequestContext() const override;
   void RecordPacketStats(StatisticSelector statistic) const override;
   const BoundNetLog& GetNetLog() const override;
 
-  // Method to allow us to reset filter context for a response that should have
-  // been SDCH encoded when there is an update due to an explicit HTTP header.
-  void ResetSdchResponseToFalse();
-
  private:
   URLRequestHttpJob* job_;
 
@@ -126,13 +122,9 @@
   return (job_->request_info_.load_flags & LOAD_IS_DOWNLOAD) != 0;
 }
 
-void URLRequestHttpJob::HttpFilterContext::ResetSdchResponseToFalse() {
-  DCHECK(job_->sdch_dictionary_advertised_);
-  job_->sdch_dictionary_advertised_ = false;
-}
-
-bool URLRequestHttpJob::HttpFilterContext::SdchResponseExpected() const {
-  return job_->sdch_dictionary_advertised_;
+SdchManager::DictionarySet*
+URLRequestHttpJob::HttpFilterContext::SdchDictionariesAdvertised() const {
+  return job_->dictionaries_advertised_.get();
 }
 
 int64 URLRequestHttpJob::HttpFilterContext::GetByteReadCount() const {
@@ -200,7 +192,6 @@
                      base::Unretained(this))),
       read_in_progress_(false),
       throttling_entry_(NULL),
-      sdch_dictionary_advertised_(false),
       sdch_test_activated_(false),
       sdch_test_control_(false),
       is_cached_content_(false),
@@ -273,7 +264,7 @@
   // plugin could set a referrer although sending the referrer is inhibited.
   request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer);
 
-  // Our consumer should have made sure that this is a safe referrer.  See for
+  // Our consumer should have made sure that this is a safe referrer. See for
   // instance WebCore::FrameLoader::HideReferrer.
   if (referrer.is_valid()) {
     request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
@@ -330,6 +321,7 @@
   ProcessStrictTransportSecurityHeader();
   ProcessPublicKeyPinsHeader();
 
+  // Handle the server notification of a new SDCH dictionary.
   SdchManager* sdch_manager(request()->context()->sdch_manager());
   if (sdch_manager) {
     SdchProblemCode rv = sdch_manager->IsInSupportedDomain(request()->url());
@@ -371,6 +363,24 @@
     }
   }
 
+  // Handle the server signalling no SDCH encoding.
+  if (dictionaries_advertised_) {
+    // We are wary of proxies that discard or damage SDCH encoding. If a server
+    // explicitly states that this is not SDCH content, then we can correct our
+    // assumption that this is an SDCH response, and avoid the need to recover
+    // as though the content is corrupted (when we discover it is not SDCH
+    // encoded).
+    std::string sdch_response_status;
+    void* iter = NULL;
+    while (GetResponseHeaders()->EnumerateHeader(&iter, "X-Sdch-Encode",
+                                                 &sdch_response_status)) {
+      if (sdch_response_status == "0") {
+        dictionaries_advertised_.reset();
+        break;
+      }
+    }
+  }
+
   // The HTTP transaction may be restarted several times for the purposes
   // of sending authorization information. Each time it restarts, we get
   // notified of the headers completion so that we can update the cookie store.
@@ -532,34 +542,34 @@
         }
       }
     }
-    std::string avail_dictionaries;
     if (advertise_sdch) {
-      sdch_manager->GetAvailDictionaryList(request_->url(),
-                                           &avail_dictionaries);
+      dictionaries_advertised_ =
+          sdch_manager->GetDictionarySet(request_->url());
+    }
 
-      // The AllowLatencyExperiment() is only true if we've successfully done a
-      // full SDCH compression recently in this browser session for this host.
-      // Note that for this path, there might be no applicable dictionaries,
-      // and hence we can't participate in the experiment.
-      if (!avail_dictionaries.empty() &&
-          sdch_manager->AllowLatencyExperiment(request_->url())) {
-        // We are participating in the test (or control), and hence we'll
-        // eventually record statistics via either SDCH_EXPERIMENT_DECODE or
-        // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data.
-        packet_timing_enabled_ = true;
-        if (base::RandDouble() < .01) {
-          sdch_test_control_ = true;  // 1% probability.
-          advertise_sdch = false;
-        } else {
-          sdch_test_activated_ = true;
-        }
+    // The AllowLatencyExperiment() is only true if we've successfully done a
+    // full SDCH compression recently in this browser session for this host.
+    // Note that for this path, there might be no applicable dictionaries,
+    // and hence we can't participate in the experiment.
+    if (dictionaries_advertised_ &&
+        sdch_manager->AllowLatencyExperiment(request_->url())) {
+      // We are participating in the test (or control), and hence we'll
+      // eventually record statistics via either SDCH_EXPERIMENT_DECODE or
+      // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data.
+      packet_timing_enabled_ = true;
+      if (base::RandDouble() < .01) {
+        sdch_test_control_ = true;  // 1% probability.
+        dictionaries_advertised_.reset();
+        advertise_sdch = false;
+      } else {
+        sdch_test_activated_ = true;
       }
     }
 
     // Supply Accept-Encoding headers first so that it is more likely that they
-    // will be in the first transmitted packet.  This can sometimes make it
+    // will be in the first transmitted packet. This can sometimes make it
     // easier to filter and analyze the streams to assure that a proxy has not
-    // damaged these headers.  Some proxies deliberately corrupt Accept-Encoding
+    // damaged these headers. Some proxies deliberately corrupt Accept-Encoding
     // headers.
     if (!advertise_sdch) {
       // Tell the server what compression formats we support (other than SDCH).
@@ -569,15 +579,14 @@
       // Include SDCH in acceptable list.
       request_info_.extra_headers.SetHeader(
           HttpRequestHeaders::kAcceptEncoding, "gzip, deflate, sdch");
-      if (!avail_dictionaries.empty()) {
+      if (dictionaries_advertised_) {
         request_info_.extra_headers.SetHeader(
             kAvailDictionaryHeader,
-            avail_dictionaries);
-        sdch_dictionary_advertised_ = true;
+            dictionaries_advertised_->GetDictionaryClientHashList());
         // Since we're tagging this transaction as advertising a dictionary,
         // we'll definitely employ an SDCH filter (or tentative sdch filter)
-        // when we get a response.  When done, we'll record histograms via
-        // SDCH_DECODE or SDCH_PASSTHROUGH.  Hence we need to record packet
+        // when we get a response. When done, we'll record histograms via
+        // SDCH_DECODE or SDCH_PASSTHROUGH. Hence we need to record packet
         // arrival times.
         packet_timing_enabled_ = true;
       }
@@ -1029,7 +1038,7 @@
 void URLRequestHttpJob::GetLoadTimingInfo(
     LoadTimingInfo* load_timing_info) const {
   // If haven't made it far enough to receive any headers, don't return
-  // anything.  This makes for more consistent behavior in the case of errors.
+  // anything. This makes for more consistent behavior in the case of errors.
   if (!transaction_ || receive_headers_end_.is_null())
     return;
   if (transaction_->GetLoadTimingInfo(load_timing_info))
@@ -1072,23 +1081,6 @@
     encoding_types.push_back(Filter::ConvertEncodingToType(encoding_type));
   }
 
-  if (filter_context_->SdchResponseExpected()) {
-    // We are wary of proxies that discard or damage SDCH encoding.  If a server
-    // explicitly states that this is not SDCH content, then we can correct our
-    // assumption that this is an SDCH response, and avoid the need to recover
-    // as though the content is corrupted (when we discover it is not SDCH
-    // encoded).
-    std::string sdch_response_status;
-    iter = NULL;
-    while (headers->EnumerateHeader(&iter, "X-Sdch-Encode",
-                                    &sdch_response_status)) {
-      if (sdch_response_status == "0") {
-        filter_context_->ResetSdchResponseToFalse();
-        break;
-      }
-    }
-  }
-
   // Even if encoding types are empty, there is a chance that we need to add
   // some decoding, as some proxies strip encoding completely. In such cases,
   // we may need to add (for example) SDCH filtering (when the context suggests
@@ -1132,7 +1124,7 @@
   if (code == -1)
     return false;
 
-  // Check if we need either Proxy or WWW Authentication.  This could happen
+  // Check if we need either Proxy or WWW Authentication. This could happen
   // because we either provided no auth info, or provided incorrect info.
   switch (code) {
     case 407:
@@ -1266,7 +1258,7 @@
 
 bool URLRequestHttpJob::ShouldFixMismatchedContentLength(int rv) const {
   // Some servers send the body compressed, but specify the content length as
-  // the uncompressed size.  Although this violates the HTTP spec we want to
+  // the uncompressed size. Although this violates the HTTP spec we want to
   // support it (as IE and FireFox do), but *only* for an exact match.
   // See http://crbug.com/79694.
   if (rv == net::ERR_CONTENT_LENGTH_MISMATCH ||
@@ -1461,7 +1453,7 @@
       !prefilter_bytes_read())       // Zero-byte responses aren't useful.
     return;
 
-  // Miniature requests aren't really compressible.  Don't count them.
+  // Miniature requests aren't really compressible. Don't count them.
   const int kMinSize = 16;
   if (prefilter_bytes_read() < kMinSize)
     return;
@@ -1478,14 +1470,14 @@
 
   // We want to record how often downloaded resources are compressed.
   // But, we recognize that different protocols may have different
-  // properties.  So, for each request, we'll put it into one of 3
+  // properties. So, for each request, we'll put it into one of 3
   // groups:
   //      a) SSL resources
   //         Proxies cannot tamper with compression headers with SSL.
   //      b) Non-SSL, loaded-via-proxy resources
   //         In this case, we know a proxy might have interfered.
   //      c) Non-SSL, loaded-without-proxy resources
-  //         In this case, we know there was no explicit proxy.  However,
+  //         In this case, we know there was no explicit proxy. However,
   //         it is possible that a transparent proxy was still interfering.
   //
   // For each group, we record the same 3 histograms.
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index f4bea7e..3a23e8a 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -15,6 +15,7 @@
 #include "net/base/auth.h"
 #include "net/base/completion_callback.h"
 #include "net/base/net_export.h"
+#include "net/base/sdch_manager.h"
 #include "net/cookies/cookie_store.h"
 #include "net/filter/filter.h"
 #include "net/http/http_request_info.h"
@@ -32,7 +33,7 @@
 class UploadDataStream;
 class URLRequestContext;
 
-// A URLRequestJob subclass that is built on top of HttpTransaction.  It
+// A URLRequestJob subclass that is built on top of HttpTransaction. It
 // provides an implementation for both HTTP and HTTPS.
 class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob {
  public:
@@ -194,17 +195,15 @@
   scoped_ptr<HttpTransaction> transaction_;
 
   // This is used to supervise traffic and enforce exponential
-  // back-off.  May be NULL.
+  // back-off. May be NULL.
   scoped_refptr<URLRequestThrottlerEntryInterface> throttling_entry_;
 
-  // Indicated if an SDCH dictionary was advertised, and hence an SDCH
-  // compressed response is expected.  We use this to help detect (accidental?)
-  // proxy corruption of a response, which sometimes marks SDCH content as
-  // having no content encoding <oops>.
-  bool sdch_dictionary_advertised_;
+  // A handle to the SDCH dictionaries that were advertised in this request.
+  // May be null.
+  scoped_ptr<SdchManager::DictionarySet> dictionaries_advertised_;
 
   // For SDCH latency experiments, when we are able to do SDCH, we may enable
-  // either an SDCH latency test xor a pass through test.  The following bools
+  // either an SDCH latency test xor a pass through test. The following bools
   // indicate what we decided on for this instance.
   bool sdch_test_activated_;  // Advertising a dictionary for sdch.
   bool sdch_test_control_;    // Not even accepting-content sdch.
@@ -219,7 +218,7 @@
   //
   // TODO(jar): improve the quality of the gathered info by gathering most times
   // at a lower point in the network stack, assuring we have actual packet
-  // boundaries, rather than approximations.  Also note that input byte count
+  // boundaries, rather than approximations. Also note that input byte count
   // as gathered here is post-SSL, and post-cache-fetch, and does not reflect
   // true packet arrival times in such cases.
 
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 5d32c6f..3cd8cf4 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -20,7 +20,6 @@
 #include "net/base/network_delegate.h"
 #include "net/filter/filter.h"
 #include "net/http/http_response_headers.h"
-#include "net/url_request/url_request.h"
 
 namespace {
 
@@ -255,6 +254,42 @@
 void URLRequestJob::NotifyURLRequestDestroyed() {
 }
 
+// static
+GURL URLRequestJob::ComputeReferrerForRedirect(
+    URLRequest::ReferrerPolicy policy,
+    const std::string& referrer,
+    const GURL& redirect_destination) {
+  GURL original_referrer(referrer);
+  bool secure_referrer_but_insecure_destination =
+      original_referrer.SchemeIsSecure() &&
+      !redirect_destination.SchemeIsSecure();
+  bool same_origin =
+      original_referrer.GetOrigin() == redirect_destination.GetOrigin();
+  switch (policy) {
+    case URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE:
+      return secure_referrer_but_insecure_destination ? GURL()
+                                                      : original_referrer;
+
+    case URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN:
+      if (same_origin) {
+        return original_referrer;
+      } else if (secure_referrer_but_insecure_destination) {
+        return GURL();
+      } else {
+        return original_referrer.GetOrigin();
+      }
+
+    case URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN:
+      return same_origin ? original_referrer : original_referrer.GetOrigin();
+
+    case URLRequest::NEVER_CLEAR_REFERRER:
+      return original_referrer;
+  }
+
+  NOTREACHED();
+  return GURL();
+}
+
 URLRequestJob::~URLRequestJob() {
   base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
   if (power_monitor)
@@ -863,15 +898,11 @@
         request_->first_party_for_cookies();
   }
 
-  // Suppress the referrer if we're redirecting out of https.
-  if (request_->referrer_policy() ==
-          URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE &&
-      GURL(request_->referrer()).SchemeIsSecure() &&
-      !redirect_info.new_url.SchemeIsSecure()) {
-    redirect_info.new_referrer.clear();
-  } else {
-    redirect_info.new_referrer = request_->referrer();
-  }
+  // Alter the referrer if redirecting cross-origin (especially HTTP->HTTPS).
+  redirect_info.new_referrer =
+      ComputeReferrerForRedirect(request_->referrer_policy(),
+                                 request_->referrer(),
+                                 redirect_info.new_url).spec();
 
   return redirect_info;
 }
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index e824689..ceb71f5 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -20,6 +20,7 @@
 #include "net/base/upload_progress.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/url_request/redirect_info.h"
+#include "net/url_request/url_request.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -36,7 +37,6 @@
 class NetworkDelegate;
 class SSLCertRequestInfo;
 class SSLInfo;
-class URLRequest;
 class UploadDataStream;
 class URLRequestStatus;
 class X509Certificate;
@@ -227,6 +227,12 @@
   // canceled by an explicit NetworkDelegate::NotifyURLRequestDestroyed() call.
   virtual void NotifyURLRequestDestroyed();
 
+  // Given |policy|, |referrer|, and |redirect_destination|, returns the
+  // referrer URL mandated by |request|'s referrer policy.
+  static GURL ComputeReferrerForRedirect(URLRequest::ReferrerPolicy policy,
+                                         const std::string& referrer,
+                                         const GURL& redirect_destination);
+
  protected:
   friend class base::RefCounted<URLRequestJob>;
   ~URLRequestJob() override;
diff --git a/net/url_request/url_request_job_manager.h b/net/url_request/url_request_job_manager.h
index ca67e56..6329eab 100644
--- a/net/url_request/url_request_job_manager.h
+++ b/net/url_request/url_request_job_manager.h
@@ -10,6 +10,7 @@
 
 #include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
+#include "net/base/net_export.h"
 #include "net/url_request/url_request.h"
 
 template <typename T> struct DefaultSingletonTraits;
@@ -24,7 +25,7 @@
 //   URLRequest is designed to have all consumers on a single thread, and
 //   so no attempt is made to support Interceptor instances being
 //   registered/unregistered or in any way poked on multiple threads.
-class URLRequestJobManager {
+class NET_EXPORT URLRequestJobManager {
  public:
   // Returns the singleton instance.
   static URLRequestJobManager* GetInstance();
diff --git a/net/url_request/url_request_simple_job.cc b/net/url_request/url_request_simple_job.cc
index 55a0f88..060a90e 100644
--- a/net/url_request/url_request_simple_job.cc
+++ b/net/url_request/url_request_simple_job.cc
@@ -47,6 +47,11 @@
 
 bool URLRequestSimpleJob::ReadRawData(IOBuffer* buf, int buf_size,
                                       int* bytes_read) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/422489 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "422489 URLRequestSimpleJob::ReadRawData"));
+
   DCHECK(bytes_read);
   int remaining = byte_range_.last_byte_position() - data_offset_ + 1;
   if (buf_size > remaining)
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index 8f70ee7..6be7da3 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -604,12 +604,6 @@
   return can_throttle_requests_;
 }
 
-int TestNetworkDelegate::OnBeforeSocketStreamConnect(
-    SocketStream* socket,
-    const CompletionCallback& callback) {
-  return OK;
-}
-
 bool TestNetworkDelegate::OnCancelURLRequestWithPolicyViolatingReferrerHeader(
     const URLRequest& request,
     const GURL& target_url,
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h
index 1289db7..1c385b2 100644
--- a/net/url_request/url_request_test_util.h
+++ b/net/url_request/url_request_test_util.h
@@ -325,8 +325,6 @@
   bool OnCanAccessFile(const URLRequest& request,
                        const base::FilePath& path) const override;
   bool OnCanThrottleRequest(const URLRequest& request) const override;
-  int OnBeforeSocketStreamConnect(SocketStream* stream,
-                                  const CompletionCallback& callback) override;
   bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(
       const URLRequest& request,
       const GURL& target_url,
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 1d777dc..9892a69 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -3913,32 +3913,6 @@
   }
 }
 
-TEST_F(URLRequestTestHTTP, HTTPSToHTTPRedirectNoRefererTest) {
-  ASSERT_TRUE(test_server_.Start());
-
-  SpawnedTestServer https_test_server(
-      SpawnedTestServer::TYPE_HTTPS, SpawnedTestServer::kLocalhost,
-      base::FilePath(FILE_PATH_LITERAL("net/data/ssl")));
-  ASSERT_TRUE(https_test_server.Start());
-
-  // An https server is sent a request with an https referer,
-  // and responds with a redirect to an http url. The http
-  // server should not be sent the referer.
-  GURL http_destination = test_server_.GetURL(std::string());
-  TestDelegate d;
-  scoped_ptr<URLRequest> req(default_context_.CreateRequest(
-      https_test_server.GetURL("server-redirect?" + http_destination.spec()),
-      DEFAULT_PRIORITY, &d, NULL));
-  req->SetReferrer("https://www.referrer.com/");
-  req->Start();
-  base::RunLoop().Run();
-
-  EXPECT_EQ(1, d.response_started_count());
-  EXPECT_EQ(1, d.received_redirect_count());
-  EXPECT_EQ(http_destination, req->url());
-  EXPECT_EQ(std::string(), req->referrer());
-}
-
 TEST_F(URLRequestTestHTTP, RedirectLoadTiming) {
   ASSERT_TRUE(test_server_.Start());
 
@@ -6727,6 +6701,219 @@
   EXPECT_EQ(2, default_network_delegate()->headers_received_count());
 }
 
+class URLRequestTestReferrerPolicy : public URLRequestTest {
+ public:
+  URLRequestTestReferrerPolicy() {}
+
+  void InstantiateSameOriginServers(SpawnedTestServer::Type origin_type) {
+    origin_server_.reset(new SpawnedTestServer(
+        origin_type, SpawnedTestServer::kLocalhost,
+        origin_type == SpawnedTestServer::TYPE_HTTPS
+            ? base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))
+            : base::FilePath(
+                  FILE_PATH_LITERAL("net/data/url_request_unittest"))));
+    ASSERT_TRUE(origin_server_->Start());
+  }
+
+  void InstantiateCrossOriginServers(SpawnedTestServer::Type origin_type,
+                                     SpawnedTestServer::Type destination_type) {
+    origin_server_.reset(new SpawnedTestServer(
+        origin_type, SpawnedTestServer::kLocalhost,
+        origin_type == SpawnedTestServer::TYPE_HTTPS
+            ? base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))
+            : base::FilePath(
+                  FILE_PATH_LITERAL("net/data/url_request_unittest"))));
+    ASSERT_TRUE(origin_server_->Start());
+
+    destination_server_.reset(new SpawnedTestServer(
+        destination_type, SpawnedTestServer::kLocalhost,
+        destination_type == SpawnedTestServer::TYPE_HTTPS
+            ? base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))
+            : base::FilePath(
+                  FILE_PATH_LITERAL("net/data/url_request_unittest"))));
+    ASSERT_TRUE(destination_server_->Start());
+  }
+
+  void VerifyReferrerAfterRedirect(URLRequest::ReferrerPolicy policy,
+                                   const GURL& referrer,
+                                   const GURL& expected) {
+    // Create and execute the request: we'll only have a |destination_server_|
+    // if the origins are meant to be distinct. Otherwise, we'll use the
+    // |origin_server_| for both endpoints.
+    GURL destination_url =
+        destination_server_ ? destination_server_->GetURL("echoheader?Referer")
+                            : origin_server_->GetURL("echoheader?Referer");
+    GURL origin_url =
+        origin_server_->GetURL("server-redirect?" + destination_url.spec());
+
+    TestDelegate d;
+    scoped_ptr<URLRequest> req(
+        default_context_.CreateRequest(origin_url, DEFAULT_PRIORITY, &d, NULL));
+    req->set_referrer_policy(policy);
+    req->SetReferrer(referrer.spec());
+    req->Start();
+    base::RunLoop().Run();
+
+    EXPECT_EQ(1, d.response_started_count());
+    EXPECT_EQ(1, d.received_redirect_count());
+    EXPECT_EQ(destination_url, req->url());
+    EXPECT_TRUE(req->status().is_success());
+    EXPECT_EQ(200, req->response_headers()->response_code());
+
+    EXPECT_EQ(expected.spec(), req->referrer());
+    if (expected.is_empty())
+      EXPECT_EQ("None", d.data_received());
+    else
+      EXPECT_EQ(expected.spec(), d.data_received());
+  }
+
+  SpawnedTestServer* origin_server() const { return origin_server_.get(); }
+
+ private:
+  scoped_ptr<SpawnedTestServer> origin_server_;
+  scoped_ptr<SpawnedTestServer> destination_server_;
+};
+
+TEST_F(URLRequestTestReferrerPolicy, HTTPToSameOriginHTTP) {
+  InstantiateSameOriginServers(SpawnedTestServer::TYPE_HTTP);
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL("path/to/file.html"));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL("path/to/file.html"));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL("path/to/file.html"));
+
+  VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER,
+                              origin_server()->GetURL("path/to/file.html"),
+                              origin_server()->GetURL("path/to/file.html"));
+}
+
+TEST_F(URLRequestTestReferrerPolicy, HTTPToCrossOriginHTTP) {
+  InstantiateCrossOriginServers(SpawnedTestServer::TYPE_HTTP,
+                                SpawnedTestServer::TYPE_HTTP);
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL("path/to/file.html"));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL(std::string()));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL(std::string()));
+
+  VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER,
+                              origin_server()->GetURL("path/to/file.html"),
+                              origin_server()->GetURL("path/to/file.html"));
+}
+
+TEST_F(URLRequestTestReferrerPolicy, HTTPSToSameOriginHTTPS) {
+  InstantiateSameOriginServers(SpawnedTestServer::TYPE_HTTPS);
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL("path/to/file.html"));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL("path/to/file.html"));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL("path/to/file.html"));
+
+  VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER,
+                              origin_server()->GetURL("path/to/file.html"),
+                              origin_server()->GetURL("path/to/file.html"));
+}
+
+TEST_F(URLRequestTestReferrerPolicy, HTTPSToCrossOriginHTTPS) {
+  InstantiateCrossOriginServers(SpawnedTestServer::TYPE_HTTPS,
+                                SpawnedTestServer::TYPE_HTTPS);
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL("path/to/file.html"));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL(std::string()));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL(std::string()));
+
+  VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER,
+                              origin_server()->GetURL("path/to/file.html"),
+                              origin_server()->GetURL("path/to/file.html"));
+}
+
+TEST_F(URLRequestTestReferrerPolicy, HTTPToHTTPS) {
+  InstantiateCrossOriginServers(SpawnedTestServer::TYPE_HTTP,
+                                SpawnedTestServer::TYPE_HTTPS);
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL("path/to/file.html"));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL(std::string()));
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL(std::string()));
+
+  VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER,
+                              origin_server()->GetURL("path/to/file.html"),
+                              origin_server()->GetURL("path/to/file.html"));
+}
+
+TEST_F(URLRequestTestReferrerPolicy, HTTPSToHTTP) {
+  InstantiateCrossOriginServers(SpawnedTestServer::TYPE_HTTPS,
+                                SpawnedTestServer::TYPE_HTTP);
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      origin_server()->GetURL("path/to/file.html"), GURL());
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"), GURL());
+
+  VerifyReferrerAfterRedirect(
+      URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
+      origin_server()->GetURL("path/to/file.html"),
+      origin_server()->GetURL(std::string()));
+
+  VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER,
+                              origin_server()->GetURL("path/to/file.html"),
+                              origin_server()->GetURL("path/to/file.html"));
+}
+
 class HTTPSRequestTest : public testing::Test {
  public:
   HTTPSRequestTest() : default_context_(true) {
@@ -7981,7 +8168,13 @@
   EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
 }
 
-TEST_F(HTTPSOCSPTest, RevokedStapled) {
+// Disabled on NSS ports. See https://crbug.com/431716.
+#if defined(USE_NSS)
+#define MAYBE_RevokedStapled DISABLED_RevokedStapled
+#else
+#define MAYBE_RevokedStapled RevokedStapled
+#endif
+TEST_F(HTTPSOCSPTest, MAYBE_RevokedStapled) {
   if (!SystemSupportsOCSPStapling()) {
     LOG(WARNING)
         << "Skipping test because system doesn't support OCSP stapling";
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc
index 769b802..08ee6ae 100644
--- a/net/websockets/websocket_basic_handshake_stream.cc
+++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -39,8 +39,8 @@
 #include "net/websockets/websocket_deflate_stream.h"
 #include "net/websockets/websocket_deflater.h"
 #include "net/websockets/websocket_extension_parser.h"
+#include "net/websockets/websocket_handshake_challenge.h"
 #include "net/websockets/websocket_handshake_constants.h"
-#include "net/websockets/websocket_handshake_handler.h"
 #include "net/websockets/websocket_handshake_request_info.h"
 #include "net/websockets/websocket_handshake_response_info.h"
 #include "net/websockets/websocket_stream.h"
@@ -435,8 +435,8 @@
                             requested_sub_protocols_,
                             &enriched_headers);
 
-  ComputeSecWebSocketAccept(handshake_challenge,
-                            &handshake_challenge_response_);
+  handshake_challenge_response_ =
+      ComputeSecWebSocketAccept(handshake_challenge);
 
   DCHECK(connect_delegate_);
   scoped_ptr<WebSocketHandshakeRequestInfo> request(
diff --git a/net/websockets/websocket_handshake_challenge.cc b/net/websockets/websocket_handshake_challenge.cc
new file mode 100644
index 0000000..3a1c3e8
--- /dev/null
+++ b/net/websockets/websocket_handshake_challenge.cc
@@ -0,0 +1,20 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/websockets/websocket_handshake_challenge.h"
+
+#include "base/base64.h"
+#include "base/sha1.h"
+#include "net/websockets/websocket_handshake_constants.h"
+
+namespace net {
+
+std::string ComputeSecWebSocketAccept(const std::string& key) {
+  std::string accept;
+  std::string hash = base::SHA1HashString(key + websockets::kWebSocketGuid);
+  base::Base64Encode(hash, &accept);
+  return accept;
+}
+
+}  // namespace net
diff --git a/net/websockets/websocket_handshake_challenge.h b/net/websockets/websocket_handshake_challenge.h
new file mode 100644
index 0000000..e21f2b0
--- /dev/null
+++ b/net/websockets/websocket_handshake_challenge.h
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_CHALLENGE_H_
+#define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_CHALLENGE_H_
+
+#include <string>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// Given a WebSocket handshake challenge, compute the value that the server
+// should return in the Sec-WebSocket-Accept header.
+NET_EXPORT_PRIVATE std::string ComputeSecWebSocketAccept(
+    const std::string& key);
+
+}  // namespace net
+
+#endif  // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_CHALLENGE_H_
diff --git a/net/websockets/websocket_handshake_challenge_test.cc b/net/websockets/websocket_handshake_challenge_test.cc
new file mode 100644
index 0000000..d7e45ca
--- /dev/null
+++ b/net/websockets/websocket_handshake_challenge_test.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/websockets/websocket_handshake_challenge.h"
+
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+// Test the example challenge from the RFC6455.
+TEST(WebSocketHandshakeChallengeTest, RFC6455) {
+  const std::string key = "dGhlIHNhbXBsZSBub25jZQ==";
+  std::string accept = ComputeSecWebSocketAccept(key);
+  EXPECT_EQ("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", accept);
+}
+
+}  // namespace
+
+}  // namespace net
diff --git a/net/websockets/websocket_handshake_handler.cc b/net/websockets/websocket_handshake_handler.cc
deleted file mode 100644
index 6bcc230..0000000
--- a/net/websockets/websocket_handshake_handler.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/websockets/websocket_handshake_handler.h"
-
-#include "base/base64.h"
-#include "base/logging.h"
-#include "base/sha1.h"
-#include "net/websockets/websocket_handshake_constants.h"
-
-namespace net {
-
-void ComputeSecWebSocketAccept(const std::string& key,
-                               std::string* accept) {
-  DCHECK(accept);
-
-  std::string hash =
-      base::SHA1HashString(key + websockets::kWebSocketGuid);
-  base::Base64Encode(hash, accept);
-}
-
-}  // namespace net
diff --git a/net/websockets/websocket_handshake_handler.h b/net/websockets/websocket_handshake_handler.h
deleted file mode 100644
index c65e6d9..0000000
--- a/net/websockets/websocket_handshake_handler.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_
-#define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_
-
-#include <string>
-
-namespace net {
-
-// Given a WebSocket handshake challenge, compute the correct response.
-// TODO(ricea): There should probably be a test for this.
-void ComputeSecWebSocketAccept(const std::string& key,
-                               std::string* accept);
-
-}  // namespace net
-
-#endif  // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_
diff --git a/net/websockets/websocket_handshake_handler_test.cc b/net/websockets/websocket_handshake_handler_test.cc
deleted file mode 100644
index 8eff571..0000000
--- a/net/websockets/websocket_handshake_handler_test.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/websockets/websocket_handshake_handler.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-namespace {
-
-// TODO(ricea): Put a test for ComputeSecWebSocketAccept() here.
-
-}  // namespace
-
-}  // namespace net
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index 23baf4e..0f8f86a 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -68,6 +68,7 @@
 test("sandbox_linux_unittests") {
   sources = [
     "services/scoped_process_unittest.cc",
+    "services/syscall_wrappers_unittest.cc",
     "services/thread_helpers_unittests.cc",
     "services/yama_unittests.cc",
     "syscall_broker/broker_process_unittest.cc",
@@ -75,6 +76,7 @@
     "tests/scoped_temporary_file.cc",
     "tests/scoped_temporary_file.h",
     "tests/scoped_temporary_file_unittest.cc",
+    "tests/test_utils_unittest.cc",
     "tests/unit_tests_unittest.cc",
   ]
 
@@ -150,15 +152,12 @@
     "bpf_dsl/policy_compiler.cc",
     "bpf_dsl/policy_compiler.h",
     "bpf_dsl/trap_registry.h",
-    "seccomp-bpf/basicblock.cc",
-    "seccomp-bpf/basicblock.h",
     "seccomp-bpf/codegen.cc",
     "seccomp-bpf/codegen.h",
     "seccomp-bpf/die.cc",
     "seccomp-bpf/die.h",
     "seccomp-bpf/errorcode.cc",
     "seccomp-bpf/errorcode.h",
-    "seccomp-bpf/instruction.h",
     "seccomp-bpf/linux_seccomp.h",
     "seccomp-bpf/sandbox_bpf.cc",
     "seccomp-bpf/sandbox_bpf.h",
@@ -225,6 +224,8 @@
     "services/init_process_reaper.h",
     "services/scoped_process.cc",
     "services/scoped_process.h",
+    "services/syscall_wrappers.cc",
+    "services/syscall_wrappers.h",
     "services/thread_helpers.cc",
     "services/thread_helpers.h",
     "services/yama.h",
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc b/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc
index b3d9126..66669e7 100644
--- a/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc
+++ b/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc
@@ -41,6 +41,7 @@
 #include "sandbox/linux/seccomp-bpf/syscall.h"
 #include "sandbox/linux/seccomp-bpf/trap.h"
 #include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/syscall_broker/broker_process.h"
 #include "sandbox/linux/tests/scoped_temporary_file.h"
 #include "sandbox/linux/tests/unit_tests.h"
@@ -203,7 +204,7 @@
 BPF_TEST_C(SandboxBPF, ApplyBasicWhitelistPolicy, WhitelistGetpidPolicy) {
   // getpid() should be allowed
   errno = 0;
-  BPF_ASSERT(syscall(__NR_getpid) > 0);
+  BPF_ASSERT(sys_getpid() > 0);
   BPF_ASSERT(errno == 0);
 
   // getpgid() should be denied
@@ -246,7 +247,7 @@
          int /* (*BPF_AUX) */) {
   // getpid() should work properly
   errno = 0;
-  BPF_ASSERT(syscall(__NR_getpid) > 0);
+  BPF_ASSERT(sys_getpid() > 0);
   BPF_ASSERT(errno == 0);
 
   // Our Auxiliary Data, should be reset by the signal handler
@@ -512,7 +513,7 @@
 
   // Verify that within the callback function all filtering is temporarily
   // disabled.
-  BPF_ASSERT(syscall(__NR_getpid) > 1);
+  BPF_ASSERT(sys_getpid() > 1);
 
   // Verify that we can now call the underlying system call without causing
   // infinite recursion.
@@ -549,7 +550,7 @@
 };
 
 BPF_TEST(SandboxBPF, GreyListedPolicy, GreyListedPolicy, int /* (*BPF_AUX) */) {
-  BPF_ASSERT(syscall(__NR_getpid) == -1);
+  BPF_ASSERT(sys_getpid() == -1);
   BPF_ASSERT(errno == EPERM);
   BPF_ASSERT(*BPF_AUX == 0);
   BPF_ASSERT(syscall(__NR_geteuid) == syscall(__NR_getuid));
@@ -2098,7 +2099,7 @@
     BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED));
 
     // getpid is allowed.
-    BPF_ASSERT_EQ(my_pid, syscall(__NR_getpid));
+    BPF_ASSERT_EQ(my_pid, sys_getpid());
 
     // write to stdout is skipped and returns a fake value.
     BPF_ASSERT_EQ(kExpectedReturnValue,
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index aa6341d..08a5c43 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -130,15 +130,12 @@
         'bpf_dsl/policy_compiler.cc',
         'bpf_dsl/policy_compiler.h',
         'bpf_dsl/trap_registry.h',
-        'seccomp-bpf/basicblock.cc',
-        'seccomp-bpf/basicblock.h',
         'seccomp-bpf/codegen.cc',
         'seccomp-bpf/codegen.h',
         'seccomp-bpf/die.cc',
         'seccomp-bpf/die.h',
         'seccomp-bpf/errorcode.cc',
         'seccomp-bpf/errorcode.h',
-        'seccomp-bpf/instruction.h',
         'seccomp-bpf/linux_seccomp.h',
         'seccomp-bpf/sandbox_bpf.cc',
         'seccomp-bpf/sandbox_bpf.h',
@@ -153,6 +150,7 @@
       ],
       'dependencies': [
         '../base/base.gyp:base',
+        'sandbox_services',
         'sandbox_services_headers',
       ],
       'defines': [
@@ -182,6 +180,7 @@
       ],
       'dependencies': [
         '../base/base.gyp:base',
+        'sandbox_services',
         'seccomp_bpf',
       ],
       'defines': [
@@ -224,6 +223,8 @@
         'services/init_process_reaper.h',
         'services/scoped_process.cc',
         'services/scoped_process.h',
+        'services/syscall_wrappers.cc',
+        'services/syscall_wrappers.h',
         'services/thread_helpers.cc',
         'services/thread_helpers.h',
         'services/yama.cc',
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi
index f246ebb..cefe962 100644
--- a/sandbox/linux/sandbox_linux_test_sources.gypi
+++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -8,6 +8,7 @@
   'dependencies': [
     'sandbox',
     'sandbox_linux_test_utils',
+    'sandbox_services',
     '../base/base.gyp:base',
     '../base/base.gyp:test_support_base',
     '../testing/gtest.gyp:gtest',
@@ -17,6 +18,7 @@
   ],
   'sources': [
     'services/scoped_process_unittest.cc',
+    'services/syscall_wrappers_unittest.cc',
     'services/thread_helpers_unittests.cc',
     'services/yama_unittests.cc',
     'syscall_broker/broker_process_unittest.cc',
@@ -24,6 +26,7 @@
     'tests/scoped_temporary_file.cc',
     'tests/scoped_temporary_file.h',
     'tests/scoped_temporary_file_unittest.cc',
+    'tests/test_utils_unittest.cc',
     'tests/unit_tests_unittest.cc',
   ],
   'conditions': [
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index 8f11bbb..69d32bc 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -19,6 +19,7 @@
 #include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
 #include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 
 // Changing this implementation will have an effect on *all* policies.
 // Currently this means: Renderer/Worker, GPU, Flash and NaCl.
@@ -237,12 +238,13 @@
 BaselinePolicy::BaselinePolicy() : BaselinePolicy(EPERM) {}
 
 BaselinePolicy::BaselinePolicy(int fs_denied_errno)
-    : fs_denied_errno_(fs_denied_errno), policy_pid_(syscall(__NR_getpid)) {}
+    : fs_denied_errno_(fs_denied_errno), policy_pid_(sys_getpid()) {
+}
 
 BaselinePolicy::~BaselinePolicy() {
   // Make sure that this policy is created, used and destroyed by a single
   // process.
-  DCHECK_EQ(syscall(__NR_getpid), policy_pid_);
+  DCHECK_EQ(sys_getpid(), policy_pid_);
 }
 
 ResultExpr BaselinePolicy::EvaluateSyscall(int sysno) const {
@@ -250,7 +252,7 @@
   DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
   // Make sure that this policy is used in the creating process.
   if (1 == sysno) {
-    DCHECK_EQ(syscall(__NR_getpid), policy_pid_);
+    DCHECK_EQ(sys_getpid(), policy_pid_);
   }
   return EvaluateSyscallImpl(fs_denied_errno_, policy_pid_, sysno);
 }
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
index a71975b..4955dfb 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -32,34 +32,15 @@
 #include "sandbox/linux/seccomp-bpf/syscall.h"
 #include "sandbox/linux/services/android_futex.h"
 #include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/services/thread_helpers.h"
+#include "sandbox/linux/tests/test_utils.h"
 #include "sandbox/linux/tests/unit_tests.h"
 
 namespace sandbox {
 
 namespace {
 
-// |pid| is the return value of a fork()-like call. This
-// makes sure that if fork() succeeded the child exits
-// and the parent waits for it.
-void HandlePostForkReturn(pid_t pid) {
-  const int kChildExitCode = 1;
-  if (pid > 0) {
-    int status = 0;
-    PCHECK(pid == HANDLE_EINTR(waitpid(pid, &status, 0)));
-    CHECK(WIFEXITED(status));
-    CHECK_EQ(kChildExitCode, WEXITSTATUS(status));
-  } else if (pid == 0) {
-    _exit(kChildExitCode);
-  }
-}
-
-// Check that HandlePostForkReturn works.
-TEST(BaselinePolicy, HandlePostForkReturn) {
-  pid_t pid = fork();
-  HandlePostForkReturn(pid);
-}
-
 // This also tests that read(), write() and fstat() are allowed.
 void TestPipeOrSocketPair(base::ScopedFD read_end, base::ScopedFD write_end) {
   BPF_ASSERT_LE(0, read_end.get());
@@ -106,36 +87,39 @@
   errno = 0;
   pid_t pid = fork();
   const int fork_errno = errno;
-  HandlePostForkReturn(pid);
+  TestUtils::HandlePostForkReturn(pid);
 
   BPF_ASSERT_EQ(-1, pid);
   BPF_ASSERT_EQ(EPERM, fork_errno);
 }
 
 pid_t ForkX86Glibc() {
-  return syscall(__NR_clone, CLONE_PARENT_SETTID | SIGCHLD);
+  static pid_t ptid;
+  return sys_clone(CLONE_PARENT_SETTID | SIGCHLD, nullptr, &ptid, nullptr,
+                   nullptr);
 }
 
 BPF_TEST_C(BaselinePolicy, ForkX86Eperm, BaselinePolicy) {
   errno = 0;
   pid_t pid = ForkX86Glibc();
   const int fork_errno = errno;
-  HandlePostForkReturn(pid);
+  TestUtils::HandlePostForkReturn(pid);
 
   BPF_ASSERT_EQ(-1, pid);
   BPF_ASSERT_EQ(EPERM, fork_errno);
 }
 
 pid_t ForkARMGlibc() {
-  return syscall(__NR_clone,
-                 CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD);
+  static pid_t ctid;
+  return sys_clone(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, nullptr,
+                   nullptr, &ctid, nullptr);
 }
 
 BPF_TEST_C(BaselinePolicy, ForkArmEperm, BaselinePolicy) {
   errno = 0;
   pid_t pid = ForkARMGlibc();
   const int fork_errno = errno;
-  HandlePostForkReturn(pid);
+  TestUtils::HandlePostForkReturn(pid);
 
   BPF_ASSERT_EQ(-1, pid);
   BPF_ASSERT_EQ(EPERM, fork_errno);
@@ -150,8 +134,8 @@
                  DisallowedCloneFlagCrashes,
                  DEATH_SEGV_MESSAGE(GetCloneErrorMessageContentForTests()),
                  BaselinePolicy) {
-  pid_t pid = syscall(__NR_clone, CLONE_THREAD | SIGCHLD);
-  HandlePostForkReturn(pid);
+  pid_t pid = sys_clone(CLONE_THREAD | SIGCHLD);
+  TestUtils::HandlePostForkReturn(pid);
 }
 
 BPF_DEATH_TEST_C(BaselinePolicy,
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
index 162b371..42be00b 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -17,6 +17,7 @@
 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
 #include "sandbox/linux/seccomp-bpf/syscall.h"
 #include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 
 #if defined(__mips__)
 // __NR_Linux, is defined in <asm/unistd.h>.
@@ -223,7 +224,7 @@
     case __NR_sched_setattr:
     case __NR_sched_setparam:
     case __NR_sched_setscheduler:
-      const pid_t tid = syscall(__NR_gettid);
+      const pid_t tid = sys_gettid();
       // The first argument is the pid.  If is our thread id, then replace it
       // with 0, which is equivalent and allowed by the policy.
       if (args.args[0] == static_cast<uint64_t>(tid)) {
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 82cdc8d..2d3e7de 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -286,5 +286,9 @@
   }
 }
 
+ResultExpr RestrictPrlimit64(pid_t target_pid) {
+  const Arg<pid_t> pid(0);
+  return If(pid == 0 || pid == target_pid, Allow()).Else(CrashSIGSYS());
+}
 
 }  // namespace sandbox.
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
index ec30511..8bde616 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
@@ -87,6 +87,10 @@
 SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictSchedTarget(pid_t target_pid,
                                                        int sysno);
 
+// Restricts the |pid| argument of prlimit64 to 0 (meaning the calling process)
+// or target_pid.
+SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPrlimit64(pid_t target_pid);
+
 }  // namespace sandbox.
 
 #endif  // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
index 83e8489..264ee4d 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
@@ -6,7 +6,9 @@
 
 #include <errno.h>
 #include <sched.h>
+#include <sys/resource.h>
 #include <sys/syscall.h>
+#include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -23,6 +25,7 @@
 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
 #include "sandbox/linux/seccomp-bpf/syscall.h"
 #include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/tests/unit_tests.h"
 
 #if !defined(OS_ANDROID)
@@ -163,7 +166,7 @@
 
 void SchedGetParamThread(base::WaitableEvent* thread_run) {
   const pid_t pid = getpid();
-  const pid_t tid = syscall(__NR_gettid);
+  const pid_t tid = sys_gettid();
   BPF_ASSERT_NE(pid, tid);
 
   struct sched_param current_pid_param;
@@ -208,6 +211,35 @@
   sched_getparam(kInitPID, &param);
 }
 
+class RestrictPrlimit64Policy : public bpf_dsl::Policy {
+ public:
+  RestrictPrlimit64Policy() {}
+  ~RestrictPrlimit64Policy() override {}
+
+  ResultExpr EvaluateSyscall(int sysno) const override {
+    switch (sysno) {
+      case __NR_prlimit64:
+        return RestrictPrlimit64(getpid());
+      default:
+        return Allow();
+    }
+  }
+};
+
+BPF_TEST_C(ParameterRestrictions, prlimit64_allowed, RestrictPrlimit64Policy) {
+  BPF_ASSERT_EQ(0, syscall(__NR_prlimit64, 0, RLIMIT_AS, NULL, NULL));
+  BPF_ASSERT_EQ(0, syscall(__NR_prlimit64, getpid(), RLIMIT_AS, NULL, NULL));
+}
+
+BPF_DEATH_TEST_C(ParameterRestrictions,
+                 prlimit64_crash_not_self,
+                 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+                 RestrictPrlimit64Policy) {
+  const pid_t kInitPID = 1;
+  BPF_ASSERT_NE(kInitPID, getpid());
+  syscall(__NR_prlimit64, kInitPID, RLIMIT_AS, NULL, NULL);
+}
+
 }  // namespace
 
 }  // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/basicblock.cc b/sandbox/linux/seccomp-bpf/basicblock.cc
deleted file mode 100644
index eb857f0..0000000
--- a/sandbox/linux/seccomp-bpf/basicblock.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/linux/seccomp-bpf/basicblock.h"
-
-namespace sandbox {
-
-BasicBlock::BasicBlock() {}
-
-BasicBlock::~BasicBlock() {}
-
-}  // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/basicblock.h b/sandbox/linux/seccomp-bpf/basicblock.h
deleted file mode 100644
index d15a372..0000000
--- a/sandbox/linux/seccomp-bpf/basicblock.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_LINUX_SECCOMP_BPF_BASICBLOCK_H__
-#define SANDBOX_LINUX_SECCOMP_BPF_BASICBLOCK_H__
-
-#include <vector>
-
-#include "sandbox/linux/seccomp-bpf/instruction.h"
-
-namespace sandbox {
-
-struct BasicBlock {
-  BasicBlock();
-  ~BasicBlock();
-
-  // Our implementation of the code generator uses a "Less" operator to
-  // identify common sequences of basic blocks. This would normally be
-  // really easy to do, but STL requires us to wrap the comparator into
-  // a class. We begrudgingly add some code here that provides this wrapping.
-  template <class T>
-  class Less {
-   public:
-    Less(const T& data,
-         int (*cmp)(const BasicBlock*, const BasicBlock*, const T& data))
-        : data_(data), cmp_(cmp) {}
-
-    bool operator()(const BasicBlock* a, const BasicBlock* b) const {
-      return cmp_(a, b, data_) < 0;
-    }
-
-   private:
-    const T& data_;
-    int (*cmp_)(const BasicBlock*, const BasicBlock*, const T&);
-  };
-
-  // Basic blocks are essentially nothing more than a set of instructions.
-  std::vector<Instruction*> instructions;
-
-  // In order to compute relative branch offsets we need to keep track of
-  // how far our block is away from the very last basic block. The "offset_"
-  // is measured in number of BPF instructions.
-  int offset;
-};
-
-}  // namespace sandbox
-
-#endif  // SANDBOX_LINUX_SECCOMP_BPF_BASICBLOCK_H__
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc b/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
index 9d2bb79..192e68d 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
@@ -17,6 +17,7 @@
 #include "sandbox/linux/bpf_dsl/policy.h"
 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
 #include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/tests/unit_tests.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -82,13 +83,11 @@
 
 class EnosysPtracePolicy : public bpf_dsl::Policy {
  public:
-  EnosysPtracePolicy() {
-    my_pid_ = syscall(__NR_getpid);
-  }
+  EnosysPtracePolicy() { my_pid_ = sys_getpid(); }
   virtual ~EnosysPtracePolicy() {
     // Policies should be able to bind with the process on which they are
     // created. They should never be created in a parent process.
-    BPF_ASSERT_EQ(my_pid_, syscall(__NR_getpid));
+    BPF_ASSERT_EQ(my_pid_, sys_getpid());
   }
 
   virtual ResultExpr EvaluateSyscall(int system_call_number) const override {
@@ -96,7 +95,7 @@
     if (system_call_number == __NR_ptrace) {
       // The EvaluateSyscall function should run in the process that created
       // the current object.
-      BPF_ASSERT_EQ(my_pid_, syscall(__NR_getpid));
+      BPF_ASSERT_EQ(my_pid_, sys_getpid());
       return Error(ENOSYS);
     } else {
       return Allow();
diff --git a/sandbox/linux/seccomp-bpf/codegen.cc b/sandbox/linux/seccomp-bpf/codegen.cc
index 18d26da..3ed06cb 100644
--- a/sandbox/linux/seccomp-bpf/codegen.cc
+++ b/sandbox/linux/seccomp-bpf/codegen.cc
@@ -6,590 +6,148 @@
 
 #include <linux/filter.h>
 
-#include <set>
+#include <limits>
+#include <utility>
 
 #include "base/logging.h"
-#include "sandbox/linux/seccomp-bpf/basicblock.h"
-#include "sandbox/linux/seccomp-bpf/die.h"
-#include "sandbox/linux/seccomp-bpf/instruction.h"
+
+// This CodeGen implementation strives for simplicity while still
+// generating acceptable BPF programs under typical usage patterns
+// (e.g., by PolicyCompiler).
+//
+// The key to its simplicity is that BPF programs only support forward
+// jumps/branches, which allows constraining the DAG construction API
+// to make instruction nodes immutable. Immutable nodes admits a
+// simple greedy approach of emitting new instructions as needed and
+// then reusing existing ones that have already been emitted. This
+// cleanly avoids any need to compute basic blocks or apply
+// topological sorting because the API effectively sorts instructions
+// for us (e.g., before MakeInstruction() can be called to emit a
+// branch instruction, it must have already been called for each
+// branch path).
+//
+// This greedy algorithm is not without (theoretical) weakness though:
+//
+//   1. In the general case, we don't eliminate dead code.  If needed,
+//      we could trace back through the program in Compile() and elide
+//      any unneeded instructions, but in practice we only emit live
+//      instructions anyway.
+//
+//   2. By not dividing instructions into basic blocks and sorting, we
+//      lose an opportunity to move non-branch/non-return instructions
+//      adjacent to their successor instructions, which means we might
+//      need to emit additional jumps. But in practice, they'll
+//      already be nearby as long as callers don't go out of their way
+//      to interleave MakeInstruction() calls for unrelated code
+//      sequences.
 
 namespace sandbox {
 
-// Unfortunately this needs to be defined out-of-line because inline
-// initializing a static member to "nullptr" requires "constexpr",
-// which is currently banned by the Chromium style guide.
-const CodeGen::Node CodeGen::kNullNode = nullptr;
+// kBranchRange is the maximum value that can be stored in
+// sock_filter's 8-bit jt and jf fields.
+const size_t kBranchRange = std::numeric_limits<uint8_t>::max();
 
-CodeGen::CodeGen() : compiled_(false) {}
+const CodeGen::Node CodeGen::kNullNode;
+
+CodeGen::CodeGen() : program_(), memos_() {
+}
 
 CodeGen::~CodeGen() {
-  for (Instructions::iterator iter = instructions_.begin();
-       iter != instructions_.end();
-       ++iter) {
-    delete *iter;
-  }
-  for (BasicBlocks::iterator iter = basic_blocks_.begin();
-       iter != basic_blocks_.end();
-       ++iter) {
-    delete *iter;
-  }
+}
+
+void CodeGen::Compile(CodeGen::Node head, Program* out) {
+  DCHECK(out);
+  out->assign(program_.rbegin() + Offset(head), program_.rend());
 }
 
 CodeGen::Node CodeGen::MakeInstruction(uint16_t code,
                                        uint32_t k,
                                        Node jt,
                                        Node jf) {
-  Node insn;
+  // To avoid generating redundant code sequences, we memoize the
+  // results from AppendInstruction().
+  auto res = memos_.insert(std::make_pair(MemoKey(code, k, jt, jf), kNullNode));
+  CodeGen::Node* node = &res.first->second;
+  if (res.second) {  // Newly inserted memo entry.
+    *node = AppendInstruction(code, k, jt, jf);
+  }
+  return *node;
+}
+
+CodeGen::Node CodeGen::AppendInstruction(uint16_t code,
+                                         uint32_t k,
+                                         Node jt,
+                                         Node jf) {
   if (BPF_CLASS(code) == BPF_JMP) {
-    CHECK_NE(kNullNode, jt);
-    if (BPF_OP(code) == BPF_JA) {
-      CHECK_EQ(kNullNode, jf);
-    } else {
-      CHECK_NE(kNullNode, jf);
-    }
-    insn = new Instruction(code, k, jt, jf);
+    CHECK_NE(BPF_JA, BPF_OP(code)) << "CodeGen inserts JAs as needed";
+
+    // We need to check |jt| twice because it might get pushed
+    // out-of-range by appending a jump for |jf|.
+    jt = WithinRange(jt, kBranchRange);
+    jf = WithinRange(jf, kBranchRange);
+    jt = WithinRange(jt, kBranchRange);
+    return Append(code, k, Offset(jt), Offset(jf));
+  }
+
+  CHECK_EQ(kNullNode, jf) << "Non-branch instructions shouldn't provide jf";
+  if (BPF_CLASS(code) == BPF_RET) {
+    CHECK_EQ(kNullNode, jt) << "Return instructions shouldn't provide jt";
   } else {
-    if (BPF_CLASS(code) == BPF_RET) {
-      CHECK_EQ(kNullNode, jt);
-    } else {
-      CHECK_NE(kNullNode, jt);
-    }
-    CHECK_EQ(kNullNode, jf);
-    insn = new Instruction(code, k, jt);
+    // For non-branch/non-return instructions, execution always
+    // proceeds to the next instruction; so we need to arrange for
+    // that to be |jt|.
+    jt = WithinRange(jt, 0);
   }
-  instructions_.push_back(insn);
-  return insn;
+  return Append(code, k, 0, 0);
 }
 
-void CodeGen::FindBranchTargets(const Instruction& instructions,
-                                BranchTargets* branch_targets) {
-  // Follow all possible paths through the "instructions" graph and compute
-  // a list of branch targets. This will later be needed to compute the
-  // boundaries of basic blocks.
-  // We maintain a set of all instructions that we have previously seen. This
-  // set ultimately converges on all instructions in the program.
-  std::set<const Instruction*> seen_instructions;
-  Instructions stack;
-  for (const Instruction* insn = &instructions; insn;) {
-    seen_instructions.insert(insn);
-    if (BPF_CLASS(insn->code) == BPF_JMP) {
-      // Found a jump. Increase count of incoming edges for each of the jump
-      // targets.
-      ++(*branch_targets)[insn->jt_ptr];
-      if (BPF_OP(insn->code) != BPF_JA) {
-        ++(*branch_targets)[insn->jf_ptr];
-        stack.push_back(const_cast<Instruction*>(insn));
-      }
-      // Start a recursive decent for depth-first traversal.
-      if (seen_instructions.find(insn->jt_ptr) == seen_instructions.end()) {
-        // We haven't seen the "true" branch yet. Traverse it now. We have
-        // already remembered the "false" branch on the stack and will
-        // traverse it later.
-        insn = insn->jt_ptr;
-        continue;
-      } else {
-        // Now try traversing the "false" branch.
-        insn = NULL;
-      }
-    } else {
-      // This is a non-jump instruction, just continue to the next instruction
-      // (if any). It's OK if "insn" becomes NULL when reaching a return
-      // instruction.
-      if (!insn->next != (BPF_CLASS(insn->code) == BPF_RET)) {
-        SANDBOX_DIE(
-            "Internal compiler error; return instruction must be at "
-            "the end of the BPF program");
-      }
-      if (seen_instructions.find(insn->next) == seen_instructions.end()) {
-        insn = insn->next;
-      } else {
-        // We have seen this instruction before. That could happen if it is
-        // a branch target. No need to continue processing.
-        insn = NULL;
-      }
-    }
-    while (!insn && !stack.empty()) {
-      // We are done processing all the way to a leaf node, backtrack up the
-      // stack to any branches that we haven't processed yet. By definition,
-      // this has to be a "false" branch, as we always process the "true"
-      // branches right away.
-      insn = stack.back();
-      stack.pop_back();
-      if (seen_instructions.find(insn->jf_ptr) == seen_instructions.end()) {
-        // We haven't seen the "false" branch yet. So, that's where we'll
-        // go now.
-        insn = insn->jf_ptr;
-      } else {
-        // We have seen both the "true" and the "false" branch, continue
-        // up the stack.
-        if (seen_instructions.find(insn->jt_ptr) == seen_instructions.end()) {
-          SANDBOX_DIE(
-              "Internal compiler error; cannot find all "
-              "branch targets");
-        }
-        insn = NULL;
-      }
-    }
+CodeGen::Node CodeGen::WithinRange(Node target, size_t range) {
+  if (Offset(target) > range) {
+    // TODO(mdempsky): If |range > 0|, we might be able to reuse an
+    // existing instruction within that range.
+
+    // TODO(mdempsky): If |target| is a branch or return, it might be
+    // possible to duplicate that instruction rather than jump to it.
+
+    // Fall back to emitting a jump instruction.
+    target = Append(BPF_JMP | BPF_JA, Offset(target), 0, 0);
   }
-  return;
+
+  CHECK_LE(Offset(target), range) << "ICE: Failed to bring target within range";
+  return target;
 }
 
-BasicBlock* CodeGen::MakeBasicBlock(Instruction* head, Instruction* tail) {
-  // Iterate over all the instructions between "head" and "tail" and
-  // insert them into a new basic block.
-  BasicBlock* bb = new BasicBlock;
-  for (;; head = head->next) {
-    bb->instructions.push_back(head);
-    if (head == tail) {
-      break;
-    }
-    if (BPF_CLASS(head->code) == BPF_JMP) {
-      SANDBOX_DIE("Found a jump inside of a basic block");
-    }
+CodeGen::Node CodeGen::Append(uint16_t code, uint32_t k, size_t jt, size_t jf) {
+  if (BPF_CLASS(code) == BPF_JMP && BPF_OP(code) != BPF_JA) {
+    CHECK_LE(jt, kBranchRange);
+    CHECK_LE(jf, kBranchRange);
+  } else {
+    CHECK_EQ(0U, jt);
+    CHECK_EQ(0U, jf);
   }
-  basic_blocks_.push_back(bb);
-  return bb;
+
+  CHECK_LT(program_.size(), static_cast<size_t>(BPF_MAXINSNS));
+  program_.push_back(sock_filter{code, jt, jf, k});
+  return program_.size() - 1;
 }
 
-void CodeGen::AddBasicBlock(Instruction* head,
-                            Instruction* tail,
-                            const BranchTargets& branch_targets,
-                            TargetsToBlocks* basic_blocks,
-                            BasicBlock** firstBlock) {
-  // Add a new basic block to "basic_blocks". Also set "firstBlock", if it
-  // has not been set before.
-  BranchTargets::const_iterator iter = branch_targets.find(head);
-  if ((iter == branch_targets.end()) != !*firstBlock ||
-      !*firstBlock != basic_blocks->empty()) {
-    SANDBOX_DIE(
-        "Only the very first basic block should have no "
-        "incoming jumps");
-  }
-  BasicBlock* bb = MakeBasicBlock(head, tail);
-  if (!*firstBlock) {
-    *firstBlock = bb;
-  }
-  (*basic_blocks)[head] = bb;
-  return;
+size_t CodeGen::Offset(Node target) const {
+  CHECK_LT(target, program_.size()) << "Bogus offset target node";
+  return (program_.size() - 1) - target;
 }
 
-BasicBlock* CodeGen::CutGraphIntoBasicBlocks(
-    Instruction* instructions,
-    const BranchTargets& branch_targets,
-    TargetsToBlocks* basic_blocks) {
-  // Textbook implementation of a basic block generator. All basic blocks
-  // start with a branch target and end with either a return statement or
-  // a jump (or are followed by an instruction that forms the beginning of a
-  // new block). Both conditional and "always" jumps are supported.
-  BasicBlock* first_block = NULL;
-  std::set<const Instruction*> seen_instructions;
-  Instructions stack;
-  Instruction* tail = NULL;
-  Instruction* head = instructions;
-  for (Instruction* insn = head; insn;) {
-    if (seen_instructions.find(insn) != seen_instructions.end()) {
-      // We somehow went in a circle. This should never be possible. Not even
-      // cyclic graphs are supposed to confuse us this much.
-      SANDBOX_DIE("Internal compiler error; cannot compute basic blocks");
-    }
-    seen_instructions.insert(insn);
-    if (tail && branch_targets.find(insn) != branch_targets.end()) {
-      // We reached a branch target. Start a new basic block (this means,
-      // flushing the previous basic block first).
-      AddBasicBlock(head, tail, branch_targets, basic_blocks, &first_block);
-      head = insn;
-    }
-    if (BPF_CLASS(insn->code) == BPF_JMP) {
-      // We reached a jump instruction, this completes our current basic
-      // block. Flush it and continue by traversing both the true and the
-      // false branch of the jump. We need to maintain a stack to do so.
-      AddBasicBlock(head, insn, branch_targets, basic_blocks, &first_block);
-      if (BPF_OP(insn->code) != BPF_JA) {
-        stack.push_back(insn->jf_ptr);
-      }
-      insn = insn->jt_ptr;
-
-      // If we are jumping to an instruction that we have previously
-      // processed, we are done with this branch. Continue by backtracking
-      // up the stack.
-      while (seen_instructions.find(insn) != seen_instructions.end()) {
-      backtracking:
-        if (stack.empty()) {
-          // We successfully traversed all reachable instructions.
-          return first_block;
-        } else {
-          // Going up the stack.
-          insn = stack.back();
-          stack.pop_back();
-        }
-      }
-      // Starting a new basic block.
-      tail = NULL;
-      head = insn;
-    } else {
-      // We found a non-jumping instruction, append it to current basic
-      // block.
-      tail = insn;
-      insn = insn->next;
-      if (!insn) {
-        // We reached a return statement, flush the current basic block and
-        // backtrack up the stack.
-        AddBasicBlock(head, tail, branch_targets, basic_blocks, &first_block);
-        goto backtracking;
-      }
-    }
-  }
-  return first_block;
-}
-
-// We define a comparator that inspects the sequence of instructions in our
-// basic block and any blocks referenced by this block. This function can be
-// used in a "less" comparator for the purpose of storing pointers to basic
-// blocks in STL containers; this gives an easy option to use STL to find
-// shared tail  sequences of basic blocks.
-static int PointerCompare(const BasicBlock* block1,
-                          const BasicBlock* block2,
-                          const TargetsToBlocks& blocks) {
-  // Return <0, 0, or >0 depending on the ordering of "block1" and "block2".
-  // If we are looking at the exact same block, this is trivial and we don't
-  // need to do a full comparison.
-  if (block1 == block2) {
-    return 0;
-  }
-
-  // We compare the sequence of instructions in both basic blocks.
-  const Instructions& insns1 = block1->instructions;
-  const Instructions& insns2 = block2->instructions;
-  // Basic blocks should never be empty.
-  CHECK(!insns1.empty());
-  CHECK(!insns2.empty());
-
-  Instructions::const_iterator iter1 = insns1.begin();
-  Instructions::const_iterator iter2 = insns2.begin();
-  for (;; ++iter1, ++iter2) {
-    // If we have reached the end of the sequence of instructions in one or
-    // both basic blocks, we know the relative ordering between the two blocks
-    // and can return.
-    if (iter1 == insns1.end() || iter2 == insns2.end()) {
-      if (iter1 != insns1.end()) {
-        return 1;
-      }
-      if (iter2 != insns2.end()) {
-        return -1;
-      }
-
-      // If the two blocks are the same length (and have elementwise-equal code
-      // and k fields) and their last instructions are neither a JMP nor a RET
-      // (which is the only way we can reach this point), then we must compare
-      // their successors.
-      Instruction* const insns1_last = insns1.back();
-      Instruction* const insns2_last = insns2.back();
-      CHECK(BPF_CLASS(insns1_last->code) != BPF_JMP &&
-            BPF_CLASS(insns1_last->code) != BPF_RET);
-
-      // Non jumping instructions will always have a valid next instruction.
-      CHECK(insns1_last->next);
-      CHECK(insns2_last->next);
-      return PointerCompare(blocks.find(insns1_last->next)->second,
-                            blocks.find(insns2_last->next)->second,
-                            blocks);
-    }
-
-    // Compare the individual fields for both instructions.
-    const Instruction& insn1 = **iter1;
-    const Instruction& insn2 = **iter2;
-    if (insn1.code != insn2.code) {
-      return insn1.code - insn2.code;
-    }
-    if (insn1.k != insn2.k) {
-      return insn1.k - insn2.k;
-    }
-
-    // Sanity check: If we're looking at a JMP or RET instruction, by definition
-    // it should be the last instruction of the basic block.
-    if (BPF_CLASS(insn1.code) == BPF_JMP || BPF_CLASS(insn1.code) == BPF_RET) {
-      CHECK_EQ(insns1.back(), &insn1);
-      CHECK_EQ(insns2.back(), &insn2);
-    }
-
-    // RET instructions terminate execution, and only JMP instructions use the
-    // jt_ptr and jf_ptr fields.  Anything else can continue to the next
-    // instruction in the basic block.
-    if (BPF_CLASS(insn1.code) == BPF_RET) {
-      return 0;
-    } else if (BPF_CLASS(insn1.code) != BPF_JMP) {
-      continue;
-    }
-
-    // Recursively compare the "true" and "false" branches.
-    // A well-formed BPF program can't have any cycles, so we know
-    // that our recursive algorithm will ultimately terminate.
-    // In the unlikely event that the programmer made a mistake and
-    // went out of the way to give us a cyclic program, we will crash
-    // with a stack overflow. We are OK with that.
-    if (BPF_OP(insn1.code) != BPF_JA) {
-      int c = PointerCompare(blocks.find(insn1.jf_ptr)->second,
-                             blocks.find(insn2.jf_ptr)->second,
-                             blocks);
-      if (c != 0) {
-        return c;
-      }
-    }
-    return PointerCompare(blocks.find(insn1.jt_ptr)->second,
-                          blocks.find(insn2.jt_ptr)->second,
-                          blocks);
-  }
-}
-
-void CodeGen::MergeTails(TargetsToBlocks* blocks) {
-  // We enter all of our basic blocks into a set using the BasicBlock::Less()
-  // comparator. This naturally results in blocks with identical tails of
-  // instructions to map to the same entry in the set. Whenever we discover
-  // that a particular chain of instructions is already in the set, we merge
-  // the basic blocks and update the pointer in the "blocks" map.
-  // Returns the number of unique basic blocks.
-  // N.B. We don't merge instructions on a granularity that is finer than
-  //      a basic block. In practice, this is sufficiently rare that we don't
-  //      incur a big cost.
-  //      Similarly, we currently don't merge anything other than tails. In
-  //      the future, we might decide to revisit this decision and attempt to
-  //      merge arbitrary sub-sequences of instructions.
-  BasicBlock::Less<TargetsToBlocks> less(*blocks, PointerCompare);
-  typedef std::set<BasicBlock*, BasicBlock::Less<TargetsToBlocks> > Set;
-  Set seen_basic_blocks(less);
-  for (TargetsToBlocks::iterator iter = blocks->begin(); iter != blocks->end();
-       ++iter) {
-    BasicBlock* bb = iter->second;
-    Set::const_iterator entry = seen_basic_blocks.find(bb);
-    if (entry == seen_basic_blocks.end()) {
-      // This is the first time we see this particular sequence of
-      // instructions. Enter the basic block into the set of known
-      // basic blocks.
-      seen_basic_blocks.insert(bb);
-    } else {
-      // We have previously seen another basic block that defines the same
-      // sequence of instructions. Merge the two blocks and update the
-      // pointer in the "blocks" map.
-      iter->second = *entry;
-    }
-  }
-}
-
-void CodeGen::ComputeIncomingBranches(BasicBlock* block,
-                                      const TargetsToBlocks& targets_to_blocks,
-                                      IncomingBranches* incoming_branches) {
-  // We increment the number of incoming branches each time we encounter a
-  // basic block. But we only traverse recursively the very first time we
-  // encounter a new block. This is necessary to make topological sorting
-  // work correctly.
-  if (++(*incoming_branches)[block] == 1) {
-    Instruction* last_insn = block->instructions.back();
-    if (BPF_CLASS(last_insn->code) == BPF_JMP) {
-      ComputeIncomingBranches(targets_to_blocks.find(last_insn->jt_ptr)->second,
-                              targets_to_blocks,
-                              incoming_branches);
-      if (BPF_OP(last_insn->code) != BPF_JA) {
-        ComputeIncomingBranches(
-            targets_to_blocks.find(last_insn->jf_ptr)->second,
-            targets_to_blocks,
-            incoming_branches);
-      }
-    } else if (BPF_CLASS(last_insn->code) != BPF_RET) {
-      ComputeIncomingBranches(targets_to_blocks.find(last_insn->next)->second,
-                              targets_to_blocks,
-                              incoming_branches);
-    }
-  }
-}
-
-void CodeGen::TopoSortBasicBlocks(BasicBlock* first_block,
-                                  const TargetsToBlocks& blocks,
-                                  BasicBlocks* basic_blocks) {
-  // Textbook implementation of a toposort. We keep looking for basic blocks
-  // that don't have any incoming branches (initially, this is just the
-  // "first_block") and add them to the topologically sorted list of
-  // "basic_blocks". As we do so, we remove outgoing branches. This potentially
-  // ends up making our descendants eligible for the sorted list. The
-  // sorting algorithm terminates when there are no more basic blocks that have
-  // no incoming branches. If we didn't move all blocks from the set of
-  // "unordered_blocks" to the sorted list of "basic_blocks", there must have
-  // been a cyclic dependency. This should never happen in a BPF program, as
-  // well-formed BPF programs only ever have forward branches.
-  IncomingBranches unordered_blocks;
-  ComputeIncomingBranches(first_block, blocks, &unordered_blocks);
-
-  std::set<BasicBlock*> heads;
-  for (;;) {
-    // Move block from "unordered_blocks" to "basic_blocks".
-    basic_blocks->push_back(first_block);
-
-    // Inspect last instruction in the basic block. This is typically either a
-    // jump or a return statement. But it could also be a "normal" instruction
-    // that is followed by a jump target.
-    Instruction* last_insn = first_block->instructions.back();
-    if (BPF_CLASS(last_insn->code) == BPF_JMP) {
-      // Remove outgoing branches. This might end up moving our descendants
-      // into set of "head" nodes that no longer have any incoming branches.
-      TargetsToBlocks::const_iterator iter;
-      if (BPF_OP(last_insn->code) != BPF_JA) {
-        iter = blocks.find(last_insn->jf_ptr);
-        if (!--unordered_blocks[iter->second]) {
-          heads.insert(iter->second);
-        }
-      }
-      iter = blocks.find(last_insn->jt_ptr);
-      if (!--unordered_blocks[iter->second]) {
-        first_block = iter->second;
-        continue;
-      }
-    } else if (BPF_CLASS(last_insn->code) != BPF_RET) {
-      // We encountered an instruction that doesn't change code flow. Try to
-      // pick the next "first_block" from "last_insn->next", if possible.
-      TargetsToBlocks::const_iterator iter;
-      iter = blocks.find(last_insn->next);
-      if (!--unordered_blocks[iter->second]) {
-        first_block = iter->second;
-        continue;
-      } else {
-        // Our basic block is supposed to be followed by "last_insn->next",
-        // but dependencies prevent this from happening. Insert a BPF_JA
-        // instruction to correct the code flow.
-        Instruction* ja = MakeInstruction(BPF_JMP + BPF_JA, 0, last_insn->next);
-        first_block->instructions.push_back(ja);
-        last_insn->next = ja;
-      }
-    }
-    if (heads.empty()) {
-      if (unordered_blocks.size() != basic_blocks->size()) {
-        SANDBOX_DIE("Internal compiler error; cyclic graph detected");
-      }
-      return;
-    }
-    // Proceed by picking an arbitrary node from the set of basic blocks that
-    // do not have any incoming branches.
-    first_block = *heads.begin();
-    heads.erase(heads.begin());
-  }
-}
-
-void CodeGen::ComputeRelativeJumps(BasicBlocks* basic_blocks,
-                                   const TargetsToBlocks& targets_to_blocks) {
-  // While we previously used pointers in jt_ptr and jf_ptr to link jump
-  // instructions to their targets, we now convert these jumps to relative
-  // jumps that are suitable for loading the BPF program into the kernel.
-  int offset = 0;
-
-  // Since we just completed a toposort, all jump targets are guaranteed to
-  // go forward. This means, iterating over the basic blocks in reverse makes
-  // it trivial to compute the correct offsets.
-  BasicBlock* bb = NULL;
-  BasicBlock* last_bb = NULL;
-  for (BasicBlocks::reverse_iterator iter = basic_blocks->rbegin();
-       iter != basic_blocks->rend();
-       ++iter) {
-    last_bb = bb;
-    bb = *iter;
-    Instruction* insn = bb->instructions.back();
-    if (BPF_CLASS(insn->code) == BPF_JMP) {
-      // Basic block ended in a jump instruction. We can now compute the
-      // appropriate offsets.
-      if (BPF_OP(insn->code) == BPF_JA) {
-        // "Always" jumps use the 32bit "k" field for the offset, instead
-        // of the 8bit "jt" and "jf" fields.
-        int jmp = offset - targets_to_blocks.find(insn->jt_ptr)->second->offset;
-        insn->k = jmp;
-        insn->jt = insn->jf = 0;
-      } else {
-        // The offset computations for conditional jumps are just the same
-        // as for "always" jumps.
-        int jt = offset - targets_to_blocks.find(insn->jt_ptr)->second->offset;
-        int jf = offset - targets_to_blocks.find(insn->jf_ptr)->second->offset;
-
-        // There is an added complication, because conditional relative jumps
-        // can only jump at most 255 instructions forward. If we have to jump
-        // further, insert an extra "always" jump.
-        Instructions::size_type jmp = bb->instructions.size();
-        if (jt > 255 || (jt == 255 && jf > 255)) {
-          Instruction* ja = MakeInstruction(BPF_JMP + BPF_JA, 0, insn->jt_ptr);
-          bb->instructions.push_back(ja);
-          ja->k = jt;
-          ja->jt = ja->jf = 0;
-
-          // The newly inserted "always" jump, of course, requires us to adjust
-          // the jump targets in the original conditional jump.
-          jt = 0;
-          ++jf;
-        }
-        if (jf > 255) {
-          Instruction* ja = MakeInstruction(BPF_JMP + BPF_JA, 0, insn->jf_ptr);
-          bb->instructions.insert(bb->instructions.begin() + jmp, ja);
-          ja->k = jf;
-          ja->jt = ja->jf = 0;
-
-          // Again, we have to adjust the jump targets in the original
-          // conditional jump.
-          ++jt;
-          jf = 0;
-        }
-
-        // Now we can finally set the relative jump targets in the conditional
-        // jump instruction. Afterwards, we must no longer access the jt_ptr
-        // and jf_ptr fields.
-        insn->jt = jt;
-        insn->jf = jf;
-      }
-    } else if (BPF_CLASS(insn->code) != BPF_RET &&
-               targets_to_blocks.find(insn->next)->second != last_bb) {
-      SANDBOX_DIE("Internal compiler error; invalid basic block encountered");
-    }
-
-    // Proceed to next basic block.
-    offset += bb->instructions.size();
-    bb->offset = offset;
-  }
-  return;
-}
-
-void CodeGen::ConcatenateBasicBlocks(const BasicBlocks& basic_blocks,
-                                     Program* program) {
-  // Our basic blocks have been sorted and relative jump offsets have been
-  // computed. The last remaining step is for all the instructions in our
-  // basic blocks to be concatenated into a BPF program.
-  program->clear();
-  for (BasicBlocks::const_iterator bb_iter = basic_blocks.begin();
-       bb_iter != basic_blocks.end();
-       ++bb_iter) {
-    const BasicBlock& bb = **bb_iter;
-    for (Instructions::const_iterator insn_iter = bb.instructions.begin();
-         insn_iter != bb.instructions.end();
-         ++insn_iter) {
-      const Instruction& insn = **insn_iter;
-      program->push_back(
-          (struct sock_filter) {insn.code, insn.jt, insn.jf, insn.k});
-    }
-  }
-  return;
-}
-
-void CodeGen::Compile(Instruction* instructions, Program* program) {
-  if (compiled_) {
-    SANDBOX_DIE(
-        "Cannot call Compile() multiple times. Create a new code "
-        "generator instead");
-  }
-  compiled_ = true;
-
-  BranchTargets branch_targets;
-  FindBranchTargets(*instructions, &branch_targets);
-  TargetsToBlocks all_blocks;
-  BasicBlock* first_block =
-      CutGraphIntoBasicBlocks(instructions, branch_targets, &all_blocks);
-  MergeTails(&all_blocks);
-  BasicBlocks basic_blocks;
-  TopoSortBasicBlocks(first_block, all_blocks, &basic_blocks);
-  ComputeRelativeJumps(&basic_blocks, all_blocks);
-  ConcatenateBasicBlocks(basic_blocks, program);
-  return;
+// TODO(mdempsky): Move into a general base::Tuple helper library.
+bool CodeGen::MemoKeyLess::operator()(const MemoKey& lhs,
+                                      const MemoKey& rhs) const {
+  if (lhs.a != rhs.a)
+    return lhs.a < rhs.a;
+  if (lhs.b != rhs.b)
+    return lhs.b < rhs.b;
+  if (lhs.c != rhs.c)
+    return lhs.c < rhs.c;
+  if (lhs.d != rhs.d)
+    return lhs.d < rhs.d;
+  return false;
 }
 
 }  // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/codegen.h b/sandbox/linux/seccomp-bpf/codegen.h
index fd229f7..bca4046 100644
--- a/sandbox/linux/seccomp-bpf/codegen.h
+++ b/sandbox/linux/seccomp-bpf/codegen.h
@@ -5,28 +5,23 @@
 #ifndef SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
 #define SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
 
+#include <stddef.h>
 #include <stdint.h>
 
 #include <map>
 #include <vector>
 
+#include "base/macros.h"
+#include "base/tuple.h"
 #include "sandbox/sandbox_export.h"
 
 struct sock_filter;
 
 namespace sandbox {
-struct BasicBlock;
-struct Instruction;
-
-typedef std::vector<Instruction*> Instructions;
-typedef std::vector<BasicBlock*> BasicBlocks;
-typedef std::map<const Instruction*, int> BranchTargets;
-typedef std::map<const Instruction*, BasicBlock*> TargetsToBlocks;
-typedef std::map<const BasicBlock*, int> IncomingBranches;
 
 // The code generator implements a basic assembler that can convert a
 // graph of BPF instructions into a well-formed array of BPF
-// instructions.  Most notably, it ensures that jumps are always
+// instructions. Most notably, it ensures that jumps are always
 // forward and don't exceed the limit of 255 instructions imposed by
 // the instruction set.
 //
@@ -62,19 +57,18 @@
   typedef std::vector<struct sock_filter> Program;
 
   // Node represents a node within the instruction DAG being compiled.
-  // Nodes are owned by the CodeGen object and need not be explicitly
-  // deleted.
-  using Node = Instruction*;
+  using Node = Program::size_type;
 
   // kNullNode represents the "null" node; i.e., the reserved node
   // value guaranteed to not equal any actual nodes.
-  static const Node kNullNode;
+  static const Node kNullNode = -1;
 
   CodeGen();
   ~CodeGen();
 
   // MakeInstruction creates a node representing the specified
-  // instruction. For details on the possible parameters refer to
+  // instruction, or returns and existing equivalent node if one
+  // exists. For details on the possible parameters refer to
   // https://www.kernel.org/doc/Documentation/networking/filter.txt.
   // TODO(mdempsky): Reconsider using default arguments here.
   Node MakeInstruction(uint16_t code,
@@ -82,72 +76,39 @@
                        Node jt = kNullNode,
                        Node jf = kNullNode);
 
-  // Compile linearizes the instruction DAG into a BPF program that
-  // can be executed by a BPF virtual machine. Please note that this
-  // function modifies the graph in place and must therefore only be
-  // called once per graph.
+  // Compile linearizes the instruction DAG rooted at |head| into a
+  // program that can be executed by a BPF virtual machine.
   void Compile(Node head, Program* program);
 
  private:
-  friend class CodeGenUnittestHelper;
+  using MemoKey = Tuple4<uint16_t, uint32_t, Node, Node>;
+  struct MemoKeyLess {
+    bool operator()(const MemoKey& lhs, const MemoKey& rhs) const;
+  };
 
-  // Find all the instructions that are the target of BPF_JMPs.
-  void FindBranchTargets(const Instruction& instructions,
-                         BranchTargets* branch_targets);
+  // AppendInstruction adds a new instruction, ensuring that |jt| and
+  // |jf| are within range as necessary for |code|.
+  Node AppendInstruction(uint16_t code, uint32_t k, Node jt, Node jf);
 
-  // Combine instructions between "head" and "tail" into a new basic block.
-  // Basic blocks are defined as sequences of instructions whose only branch
-  // target is the very first instruction; furthermore, any BPF_JMP or BPF_RET
-  // instruction must be at the very end of the basic block.
-  BasicBlock* MakeBasicBlock(Instruction* head, Instruction* tail);
+  // WithinRange returns a node equivalent to |next| that is at most
+  // |range| instructions away from the (logical) beginning of the
+  // program.
+  Node WithinRange(Node next, size_t range);
 
-  // Creates a basic block and adds it to "basic_blocks"; sets "first_block"
-  // if it is still NULL.
-  void AddBasicBlock(Instruction* head,
-                     Instruction* tail,
-                     const BranchTargets& branch_targets,
-                     TargetsToBlocks* basic_blocks,
-                     BasicBlock** first_block);
+  // Append appends a new instruction to the physical end (i.e.,
+  // logical beginning) of |program_|.
+  Node Append(uint16_t code, uint32_t k, size_t jt, size_t jf);
 
-  // Cuts the DAG of instructions into basic blocks.
-  BasicBlock* CutGraphIntoBasicBlocks(Instruction* instructions,
-                                      const BranchTargets& branch_targets,
-                                      TargetsToBlocks* blocks);
+  // Offset returns how many instructions exist in |program_| after |target|.
+  size_t Offset(Node target) const;
 
-  // Find common tail sequences of basic blocks and coalesce them.
-  void MergeTails(TargetsToBlocks* blocks);
+  // NOTE: program_ is the compiled program in *reverse*, so that
+  // indices remain stable as we add instructions.
+  Program program_;
 
-  // For each basic block, compute the number of incoming branches.
-  void ComputeIncomingBranches(BasicBlock* block,
-                               const TargetsToBlocks& targets_to_blocks,
-                               IncomingBranches* incoming_branches);
+  std::map<MemoKey, Node, MemoKeyLess> memos_;
 
-  // Topologically sort the basic blocks so that all jumps are forward jumps.
-  // This is a requirement for any well-formed BPF program.
-  void TopoSortBasicBlocks(BasicBlock* first_block,
-                           const TargetsToBlocks& blocks,
-                           BasicBlocks* basic_blocks);
-
-  // Convert jt_ptr_ and jf_ptr_ fields in BPF_JMP instructions to valid
-  // jt_ and jf_ jump offsets. This can result in BPF_JA instructions being
-  // inserted, if we need to jump over more than 256 instructions.
-  void ComputeRelativeJumps(BasicBlocks* basic_blocks,
-                            const TargetsToBlocks& targets_to_blocks);
-
-  // Concatenate instructions from all basic blocks into a BPF program that
-  // can be passed to the kernel.
-  void ConcatenateBasicBlocks(const BasicBlocks&, Program* program);
-
-  // We stick all instructions and basic blocks into pools that get destroyed
-  // when the CodeGen object is destroyed. This way, we neither need to worry
-  // about explicitly managing ownership, nor do we need to worry about using
-  // smart pointers in the presence of circular references.
-  Instructions instructions_;
-  BasicBlocks basic_blocks_;
-
-  // Compile() must only ever be called once as it makes destructive changes
-  // to the DAG.
-  bool compiled_;
+  DISALLOW_COPY_AND_ASSIGN(CodeGen);
 };
 
 }  // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/codegen_unittest.cc b/sandbox/linux/seccomp-bpf/codegen_unittest.cc
index 3f1a04b..a001668 100644
--- a/sandbox/linux/seccomp-bpf/codegen_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/codegen_unittest.cc
@@ -116,13 +116,7 @@
     CodeGen::Node res = gen_.MakeInstruction(code, k, jt, jf);
     EXPECT_NE(CodeGen::kNullNode, res);
 
-    Hash digest;
-    if (code == BPF_JMP + BPF_JA) {
-      // TODO(mdempsky): Disallow use of JA.
-      digest = Lookup(jt);
-    } else {
-      digest = Hash(code, k, Lookup(jt), Lookup(jf));
-    }
+    Hash digest(code, k, Lookup(jt), Lookup(jf));
     auto it = node_hashes_.insert(std::make_pair(res, digest));
     EXPECT_EQ(digest, it.first->second);
 
@@ -224,12 +218,12 @@
   //    RET 42                           (insn3+)
   CodeGen::Node insn0 = MakeInstruction(BPF_RET + BPF_K, 42);
   CodeGen::Node insn1 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42, insn0);
-  CodeGen::Node insn2 = MakeInstruction(BPF_JMP + BPF_JA, 0, insn1);
+  CodeGen::Node insn2 = insn1;  // Implicit JUMP
 
-  // We explicitly duplicate instructions so that MergeTails() can coalesce
-  // them later.
+  // We explicitly duplicate instructions to test that they're merged.
   CodeGen::Node insn3 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42,
                                         MakeInstruction(BPF_RET + BPF_K, 42));
+  EXPECT_EQ(insn2, insn3);
 
   CodeGen::Node insn4 =
       MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 42, insn2, insn3);
@@ -328,5 +322,50 @@
   RunTest(i0);
 }
 
+TEST_F(ProgramTest, InstructionFolding) {
+  // Check that simple instructions are folded as expected.
+  CodeGen::Node a = MakeInstruction(BPF_RET + BPF_K, 0);
+  EXPECT_EQ(a, MakeInstruction(BPF_RET + BPF_K, 0));
+  CodeGen::Node b = MakeInstruction(BPF_RET + BPF_K, 1);
+  EXPECT_EQ(a, MakeInstruction(BPF_RET + BPF_K, 0));
+  EXPECT_EQ(b, MakeInstruction(BPF_RET + BPF_K, 1));
+  EXPECT_EQ(b, MakeInstruction(BPF_RET + BPF_K, 1));
+
+  // Check that complex sequences are folded too.
+  CodeGen::Node c =
+      MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0,
+                      MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, 0x100, a, b));
+  EXPECT_EQ(c, MakeInstruction(
+                   BPF_LD + BPF_W + BPF_ABS, 0,
+                   MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, 0x100, a, b)));
+
+  RunTest(c);
+}
+
+TEST_F(ProgramTest, FarBranches) {
+  // BPF instructions use 8-bit fields for branch offsets, which means
+  // branch targets must be within 255 instructions of the branch
+  // instruction. CodeGen abstracts away this detail by inserting jump
+  // instructions as needed, which we test here by generating programs
+  // that should trigger any interesting boundary conditions.
+
+  // Populate with 260 initial instruction nodes.
+  std::vector<CodeGen::Node> nodes;
+  nodes.push_back(MakeInstruction(BPF_RET + BPF_K, 0));
+  for (size_t i = 1; i < 260; ++i) {
+    nodes.push_back(
+        MakeInstruction(BPF_ALU + BPF_ADD + BPF_K, i, nodes.back()));
+  }
+
+  // Exhaustively test branch offsets near BPF's limits.
+  for (size_t jt = 250; jt < 260; ++jt) {
+    for (size_t jf = 250; jf < 260; ++jf) {
+      nodes.push_back(MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 0,
+                                      nodes.rbegin()[jt], nodes.rbegin()[jf]));
+      RunTest(nodes.back());
+    }
+  }
+}
+
 }  // namespace
 }  // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/instruction.h b/sandbox/linux/seccomp-bpf/instruction.h
deleted file mode 100644
index 70b7791..0000000
--- a/sandbox/linux/seccomp-bpf/instruction.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_LINUX_SECCOMP_BPF_INSTRUCTION_H__
-#define SANDBOX_LINUX_SECCOMP_BPF_INSTRUCTION_H__
-
-#include <stdint.h>
-
-#include <cstddef>
-
-namespace sandbox {
-
-// The fields in this structure have the same meaning as the corresponding
-// fields in "struct sock_filter". See <linux/filter.h> for a lot more
-// detail.
-// code     -- Opcode of the instruction. This is typically a bitwise
-//             combination BPF_XXX values.
-// k        -- Operand; BPF instructions take zero or one operands. Operands
-//             are 32bit-wide constants, if present. They can be immediate
-//             values (if BPF_K is present in "code_"), addresses (if BPF_ABS
-//             is present in "code_"), or relative jump offsets (if BPF_JMP
-//             and BPF_JA are present in "code_").
-// jt, jf   -- all conditional jumps have a 8bit-wide jump offset that allows
-//             jumps of up to 256 instructions forward. Conditional jumps are
-//             identified by BPF_JMP in "code_", but the lack of BPF_JA.
-//             Conditional jumps have a "t"rue and "f"alse branch.
-struct Instruction {
-  // Constructor for an non-jumping instruction or for an unconditional
-  // "always" jump.
-  Instruction(uint16_t c, uint32_t parm, Instruction* n)
-      : code(c), jt(0), jf(0), jt_ptr(NULL), jf_ptr(NULL), next(n), k(parm) {}
-
-  // Constructor for a conditional jump instruction.
-  Instruction(uint16_t c, uint32_t parm, Instruction* jt, Instruction* jf)
-      : code(c), jt(0), jf(0), jt_ptr(jt), jf_ptr(jf), next(NULL), k(parm) {}
-
-  uint16_t code;
-
-  // When code generation is complete, we will have computed relative
-  // branch targets that are in the range 0..255.
-  uint8_t jt, jf;
-
-  // While assembling the BPF program, we use pointers for branch targets.
-  // Once we have computed basic blocks, these pointers will be entered as
-  // keys in a TargetsToBlocks map and should no longer be dereferenced
-  // directly.
-  Instruction* jt_ptr, *jf_ptr;
-
-  // While assembling the BPF program, non-jumping instructions are linked
-  // by the "next_" pointer. This field is no longer needed when we have
-  // computed basic blocks.
-  Instruction* next;
-
-  uint32_t k;
-};
-
-}  // namespace sandbox
-
-#endif  // SANDBOX_LINUX_SECCOMP_BPF_INSTRUCTION_H__
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index d5a5d4d..43c9af6 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -41,6 +41,7 @@
 #include "sandbox/linux/seccomp-bpf/trap.h"
 #include "sandbox/linux/seccomp-bpf/verifier.h"
 #include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 
 using sandbox::bpf_dsl::Allow;
 using sandbox::bpf_dsl::Error;
@@ -92,8 +93,8 @@
 };
 
 void ProbeProcess(void) {
-  if (syscall(__NR_getpid) < 0 && errno == EPERM) {
-    syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode));
+  if (sys_getpid() < 0 && errno == EPERM) {
+    sys_exit_group(kExpectedExitCode);
   }
 }
 
@@ -117,7 +118,7 @@
   // vsyscall=emulate and some versions of the seccomp BPF patch
   // we may get SIGKILL-ed. Detect this!
   if (time(&current_time) != static_cast<time_t>(-1)) {
-    syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode));
+    sys_exit_group(kExpectedExitCode);
   }
 }
 
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index 96702b1..a745220 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -24,6 +24,7 @@
 #include "base/template_util.h"
 #include "base/third_party/valgrind/valgrind.h"
 #include "base/threading/thread.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 
 namespace {
 
@@ -286,7 +287,7 @@
   }
 
   // This is roughly a fork().
-  const pid_t pid = syscall(__NR_clone, CLONE_NEWUSER | SIGCHLD, 0, 0, 0);
+  const pid_t pid = sys_clone(CLONE_NEWUSER | SIGCHLD, 0, 0, 0, 0);
 
   if (pid == -1) {
     CheckCloneNewUserErrno(errno);
diff --git a/sandbox/linux/services/scoped_process.cc b/sandbox/linux/services/scoped_process.cc
index fd42a2a..bdeaee9 100644
--- a/sandbox/linux/services/scoped_process.cc
+++ b/sandbox/linux/services/scoped_process.cc
@@ -17,6 +17,7 @@
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 #include "build/build_config.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/services/thread_helpers.h"
 
 namespace sandbox {
@@ -112,7 +113,7 @@
 // This method allows to assert it is not happening.
 bool ScopedProcess::IsOriginalProcess() {
   // Make a direct syscall to bypass glibc caching of PIDs.
-  int pid = syscall(__NR_getpid);
+  pid_t pid = sys_getpid();
   return pid == process_id_;
 }
 
diff --git a/sandbox/linux/services/syscall_wrappers.cc b/sandbox/linux/services/syscall_wrappers.cc
new file mode 100644
index 0000000..3938694
--- /dev/null
+++ b/sandbox/linux/services/syscall_wrappers.cc
@@ -0,0 +1,59 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/linux/services/syscall_wrappers.h"
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+
+namespace sandbox {
+
+pid_t sys_getpid(void) {
+  return syscall(__NR_getpid);
+}
+
+pid_t sys_gettid(void) {
+  return syscall(__NR_gettid);
+}
+
+long sys_clone(unsigned long flags) {
+  return sys_clone(flags, nullptr, nullptr, nullptr, nullptr);
+}
+
+long sys_clone(unsigned long flags,
+               void* child_stack,
+               pid_t* ptid,
+               pid_t* ctid,
+               decltype(nullptr) tls) {
+  const bool clone_tls_used = flags & CLONE_SETTLS;
+  const bool invalid_ctid =
+      (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && !ctid;
+  const bool invalid_ptid = (flags & CLONE_PARENT_SETTID) && !ptid;
+  const bool invalid_stack = (flags & CLONE_VM) && !child_stack;
+
+  if (clone_tls_used || invalid_ctid || invalid_ptid || invalid_stack) {
+    RAW_LOG(FATAL, "Invalid usage of sys_clone");
+  }
+
+// See kernel/fork.c in Linux. There is different ordering of sys_clone
+// parameters depending on CONFIG_CLONE_BACKWARDS* configuration options.
+#if defined(ARCH_CPU_X86_64)
+  return syscall(__NR_clone, flags, child_stack, ptid, ctid, tls);
+#elif defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARM_FAMILY) || \
+    defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_MIPS64_FAMILY)
+  // CONFIG_CLONE_BACKWARDS defined.
+  return syscall(__NR_clone, flags, child_stack, ptid, tls, ctid);
+#endif
+}
+
+void sys_exit_group(int status) {
+  syscall(__NR_exit_group, status);
+}
+
+}  // namespace sandbox
diff --git a/sandbox/linux/services/syscall_wrappers.h b/sandbox/linux/services/syscall_wrappers.h
new file mode 100644
index 0000000..03d5cdf
--- /dev/null
+++ b/sandbox/linux/services/syscall_wrappers.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
+#define SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
+
+#include <sys/types.h>
+
+#include "sandbox/sandbox_export.h"
+
+namespace sandbox {
+
+// Provide direct system call wrappers for a few common system calls.
+// These are guaranteed to perform a system call and do not rely on things such
+// as caching the current pid (c.f. getpid()).
+
+SANDBOX_EXPORT pid_t sys_getpid(void);
+
+SANDBOX_EXPORT pid_t sys_gettid(void);
+
+SANDBOX_EXPORT long sys_clone(unsigned long flags);
+
+// |regs| is not supported and must be passed as nullptr.
+SANDBOX_EXPORT long sys_clone(unsigned long flags,
+                              void* child_stack,
+                              pid_t* ptid,
+                              pid_t* ctid,
+                              decltype(nullptr) regs);
+
+SANDBOX_EXPORT void sys_exit_group(int status);
+
+}  // namespace sandbox
+
+#endif  // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
diff --git a/sandbox/linux/services/syscall_wrappers_unittest.cc b/sandbox/linux/services/syscall_wrappers_unittest.cc
new file mode 100644
index 0000000..861dd5f
--- /dev/null
+++ b/sandbox/linux/services/syscall_wrappers_unittest.cc
@@ -0,0 +1,63 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/linux/services/syscall_wrappers.h"
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "build/build_config.h"
+#include "sandbox/linux/tests/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+
+namespace {
+
+TEST(SyscallWrappers, BasicSyscalls) {
+  EXPECT_EQ(getpid(), sys_getpid());
+}
+
+TEST(SyscallWrappers, CloneBasic) {
+  pid_t child = sys_clone(SIGCHLD);
+  TestUtils::HandlePostForkReturn(child);
+  EXPECT_LT(0, child);
+}
+
+TEST(SyscallWrappers, CloneParentSettid) {
+  pid_t ptid = 0;
+  pid_t child = sys_clone(CLONE_PARENT_SETTID | SIGCHLD, nullptr, &ptid,
+                          nullptr, nullptr);
+  TestUtils::HandlePostForkReturn(child);
+  EXPECT_LT(0, child);
+  EXPECT_EQ(child, ptid);
+}
+
+TEST(SyscallWrappers, CloneChildSettid) {
+  pid_t ctid = 0;
+  pid_t pid =
+      sys_clone(CLONE_CHILD_SETTID | SIGCHLD, nullptr, nullptr, &ctid, nullptr);
+
+  const int kSuccessExit = 0;
+  if (0 == pid) {
+    // In child.
+    if (sys_getpid() == ctid)
+      _exit(kSuccessExit);
+    _exit(1);
+  }
+
+  ASSERT_NE(-1, pid);
+  int status = 0;
+  ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
+  ASSERT_TRUE(WIFEXITED(status));
+  EXPECT_EQ(kSuccessExit, WEXITSTATUS(status));
+}
+
+}  // namespace
+
+}  // namespace sandbox
diff --git a/sandbox/linux/services/unix_domain_socket_unittest.cc b/sandbox/linux/services/unix_domain_socket_unittest.cc
index 17208a8..4d57c0d 100644
--- a/sandbox/linux/services/unix_domain_socket_unittest.cc
+++ b/sandbox/linux/services/unix_domain_socket_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/posix/unix_domain_socket_linux.h"
 #include "base/process/process_handle.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/tests/unit_tests.h"
 
 // Additional tests for base's UnixDomainSocket to make sure it behaves
@@ -144,14 +145,14 @@
 
   CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
 
-  const pid_t pid = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 0, 0, 0);
+  const pid_t pid = sys_clone(CLONE_NEWPID | SIGCHLD, 0, 0, 0, 0);
   CHECK_NE(-1, pid);
   if (pid == 0) {
     // Child process.
     recv_sock.reset();
 
     // Check that we think we're pid 1 in our new namespace.
-    CHECK_EQ(1, syscall(__NR_getpid));
+    CHECK_EQ(1, sys_getpid());
 
     SendHello(send_sock.get());
     _exit(0);
@@ -178,13 +179,13 @@
 
   CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
 
-  const pid_t pid = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 0, 0, 0);
+  const pid_t pid = sys_clone(CLONE_NEWPID | SIGCHLD, 0, 0, 0, 0);
   CHECK_NE(-1, pid);
   if (pid == 0) {
     // Child process.
     recv_sock.reset();
 
-    const pid_t pid2 = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 0, 0, 0);
+    const pid_t pid2 = sys_clone(CLONE_NEWPID | SIGCHLD, 0, 0, 0, 0);
     CHECK_NE(-1, pid2);
 
     if (pid2 != 0) {
@@ -195,7 +196,7 @@
     }
 
     // Check that we think we're pid 1.
-    CHECK_EQ(1, syscall(__NR_getpid));
+    CHECK_EQ(1, sys_getpid());
 
     SendHello(send_sock.get());
     _exit(0);
@@ -244,7 +245,7 @@
 
   CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
 
-  const pid_t pid = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 0, 0, 0);
+  const pid_t pid = sys_clone(CLONE_NEWPID | SIGCHLD, 0, 0, 0, 0);
   CHECK_NE(-1, pid);
   if (pid == 0) {
     // Child process.
diff --git a/sandbox/linux/tests/test_utils.cc b/sandbox/linux/tests/test_utils.cc
index 398654b..6000b8a 100644
--- a/sandbox/linux/tests/test_utils.cc
+++ b/sandbox/linux/tests/test_utils.cc
@@ -28,4 +28,16 @@
   }
 }
 
+void TestUtils::HandlePostForkReturn(pid_t pid) {
+  const int kChildExitCode = 1;
+  if (pid > 0) {
+    int status = 0;
+    PCHECK(pid == HANDLE_EINTR(waitpid(pid, &status, 0)));
+    CHECK(WIFEXITED(status));
+    CHECK_EQ(kChildExitCode, WEXITSTATUS(status));
+  } else if (pid == 0) {
+    _exit(kChildExitCode);
+  }
+}
+
 }  // namespace sandbox
diff --git a/sandbox/linux/tests/test_utils.h b/sandbox/linux/tests/test_utils.h
index 3269847..1d9eb79 100644
--- a/sandbox/linux/tests/test_utils.h
+++ b/sandbox/linux/tests/test_utils.h
@@ -5,6 +5,8 @@
 #ifndef SANDBOX_LINUX_TESTS_TEST_UTILS_H_
 #define SANDBOX_LINUX_TESTS_TEST_UTILS_H_
 
+#include <sys/types.h>
+
 #include "base/basictypes.h"
 
 namespace sandbox {
@@ -13,6 +15,10 @@
 class TestUtils {
  public:
   static bool CurrentProcessHasChildren();
+  // |pid| is the return value of a fork()-like call. This
+  // makes sure that if fork() succeeded the child exits
+  // and the parent waits for it.
+  static void HandlePostForkReturn(pid_t pid);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(TestUtils);
diff --git a/sandbox/linux/tests/test_utils_unittest.cc b/sandbox/linux/tests/test_utils_unittest.cc
new file mode 100644
index 0000000..0f86e61
--- /dev/null
+++ b/sandbox/linux/tests/test_utils_unittest.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/linux/tests/test_utils.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+
+namespace {
+
+// Check that HandlePostForkReturn works.
+TEST(TestUtils, HandlePostForkReturn) {
+  pid_t pid = fork();
+  TestUtils::HandlePostForkReturn(pid);
+}
+
+}  // namespace
+
+}  // namespace sandbox
diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi
index 46259e5..7d369d8 100644
--- a/skia/skia_library.gypi
+++ b/skia/skia_library.gypi
@@ -360,6 +360,13 @@
         ['include', 'SkStream_mac\\.cpp$',],
         ['include', 'SkCreateCGImageRef\\.cpp$',],
       ],
+      'xcode_settings' : {
+        'WARNING_CFLAGS': [
+          # SkFontHost_mac.cpp uses API deprecated in iOS 7.
+          # crbug.com/408571
+          '-Wno-deprecated-declarations',
+        ],
+      },
     }],
   ],
 
diff --git a/testing/android/junit/javatests/src/org/chromium/testing/local/GtestLoggerTest.java b/testing/android/junit/javatests/src/org/chromium/testing/local/GtestLoggerTest.java
index 2a442fc..2bb3040 100644
--- a/testing/android/junit/javatests/src/org/chromium/testing/local/GtestLoggerTest.java
+++ b/testing/android/junit/javatests/src/org/chromium/testing/local/GtestLoggerTest.java
@@ -43,8 +43,8 @@
                 Description.createTestDescription(GtestLoggerTest.class, "testTestFinishedPassed"),
                 true, 123);
         Assert.assertEquals(
-                "[       OK ] org.chromium.testing.local.GtestLoggerTest.testTestFinishedPassed" +
-                        " (123 ms)\n",
+                "[       OK ] org.chromium.testing.local.GtestLoggerTest.testTestFinishedPassed"
+                        + " (123 ms)\n",
                 actual.toString());
     }
 
@@ -56,8 +56,8 @@
                 Description.createTestDescription(GtestLoggerTest.class, "testTestFinishedPassed"),
                 false, 123);
         Assert.assertEquals(
-                "[   FAILED ] org.chromium.testing.local.GtestLoggerTest.testTestFinishedPassed" +
-                        " (123 ms)\n",
+                "[   FAILED ] org.chromium.testing.local.GtestLoggerTest.testTestFinishedPassed"
+                        + " (123 ms)\n",
                 actual.toString());
     }
 
@@ -79,8 +79,8 @@
         loggerUnderTest.testCaseFinished(
                 Description.createSuiteDescription(GtestLoggerTest.class), 456, 123);
         Assert.assertEquals(
-                "[----------] Run 456 test cases from org.chromium.testing.local.GtestLoggerTest" +
-                        " (123 ms)\n\n",
+                "[----------] Run 456 test cases from org.chromium.testing.local.GtestLoggerTest"
+                        + " (123 ms)\n\n",
                 actual.toString());
     }
 
@@ -90,8 +90,8 @@
         GtestLogger loggerUnderTest = new GtestLogger(new PrintStream(actual));
         loggerUnderTest.testRunStarted(1234);
         Assert.assertEquals(
-                "[==========] Running 1234 tests.\n" +
-                "[----------] Global test environment set-up.\n\n",
+                "[==========] Running 1234 tests.\n"
+                        + "[----------] Global test environment set-up.\n\n",
                 actual.toString());
     }
 
@@ -101,9 +101,9 @@
         GtestLogger loggerUnderTest = new GtestLogger(new PrintStream(actual));
         loggerUnderTest.testRunFinished(1234, new HashSet<Description>(), 4321);
         Assert.assertEquals(
-                "[----------] Global test environment tear-down.\n" +
-                "[==========] 1234 tests ran. (4321 ms total)\n" +
-                "[  PASSED  ] 1234 tests.\n",
+                "[----------] Global test environment tear-down.\n"
+                        + "[==========] 1234 tests ran. (4321 ms total)\n"
+                        + "[  PASSED  ] 1234 tests.\n",
                 actual.toString());
     }
 
@@ -120,13 +120,13 @@
 
         loggerUnderTest.testRunFinished(1232, failures, 4312);
         Assert.assertEquals(
-                "[----------] Global test environment tear-down.\n" +
-                "[==========] 1234 tests ran. (4312 ms total)\n" +
-                "[  PASSED  ] 1232 tests.\n" +
-                "[  FAILED  ] 2 tests.\n" +
-                "[  FAILED  ] GtestLoggerTest.testTestRunFinishedNoFailures\n" +
-                "[  FAILED  ] GtestLoggerTest.testTestRunFinishedWithFailures\n" +
-                "\n",
+                "[----------] Global test environment tear-down.\n"
+                        + "[==========] 1234 tests ran. (4312 ms total)\n"
+                        + "[  PASSED  ] 1232 tests.\n"
+                        + "[  FAILED  ] 2 tests.\n"
+                        + "[  FAILED  ] GtestLoggerTest.testTestRunFinishedNoFailures\n"
+                        + "[  FAILED  ] GtestLoggerTest.testTestRunFinishedWithFailures\n"
+                        + "\n",
                 actual.toString());
     }
 
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index a2a9b23..70393de 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -61,6 +61,7 @@
         "args": ["--test-launcher-print-test-stdio=always"]
       },
       "ui_base_unittests",
+      "ui_chromeos_unittests",
       "views_unittests",
       "wm_unittests",
       "aura_unittests",
@@ -133,6 +134,7 @@
       "sql_unittests",
       "sync_unit_tests",
       "ui_base_unittests",
+      "ui_chromeos_unittests",
       "unit_tests",
       "url_unittests",
       "views_unittests",
@@ -180,6 +182,7 @@
         "args": ["--test-launcher-print-test-stdio=always"]
       },
       "ui_base_unittests",
+      "ui_chromeos_unittests",
       "views_unittests",
       "wm_unittests",
       "aura_unittests",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index bee8677..3c54f1b 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -353,6 +353,12 @@
       { "test": "content_browsertests", "args": ["--site-per-process", "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DontSwapProcessWithOnlyTargetBlank:*.DisownOpener:*.NavigateWithLeftoverFrames:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort:*.AllowTargetedNavigationsInOpenerAfterSwap"] }
     ]
   },
+  "Browser Side Navigation Linux": {
+    "gtest_tests": [
+      { "test": "content_unittests", "args": ["--enable-browser-side-navigation"] },
+      { "test": "content_browsertests", "args": ["--enable-browser-side-navigation"] }
+    ]
+  },
   "Linux ChromeOS MSan Tests": {
     "gtest_tests": [
       "accessibility_unittests",
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 8f72e65..9987ad7 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -304,6 +304,7 @@
         }
       },
       "ui_base_unittests",
+      "ui_chromeos_unittests",
       "url_unittests",
       "views_unittests"
     ]
diff --git a/testing/buildbot/chromium_trybot.json b/testing/buildbot/chromium_trybot.json
index 6e3cff5..4b6de77 100644
--- a/testing/buildbot/chromium_trybot.json
+++ b/testing/buildbot/chromium_trybot.json
@@ -165,6 +165,15 @@
         "shards": 2
       }
     },
+    {
+      "test": "ui_chromeos_unittests",
+      "platforms": ["linux"],
+      "chromium_configs": [
+        "chromium_chromeos",
+        "chromium_chromeos_clang",
+        "chromium_chromeos_ozone"
+      ]
+    },
     "url_unittests",
     {
       "test": "wm_unittests",
diff --git a/third_party/android_testrunner/README.chromium b/third_party/android_testrunner/README.chromium
index 7d382a1..6ca8498 100644
--- a/third_party/android_testrunner/README.chromium
+++ b/third_party/android_testrunner/README.chromium
@@ -18,6 +18,8 @@
    bugs in run_command.py.
 4. Fixed a bug where wait_time wasn't properly respected in
     _WaitForShellCommandContents.
+5. Added option to specify the ADB binary that should be used instead of always
+  using the ADB in the environment path.
 
 Here is the detail steps
 1. Checkout Android source code
diff --git a/third_party/android_testrunner/adb_interface.py b/third_party/android_testrunner/adb_interface.py
index 93e1963..306f186 100644
--- a/third_party/android_testrunner/adb_interface.py
+++ b/third_party/android_testrunner/adb_interface.py
@@ -34,11 +34,19 @@
 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 __init__(self, adb_path='adb'):
+    """Constructor.
+
+    Args:
+      adb_path: Absolute path to the adb binary that should be used. Defaults
+                to the adb in the environment path.
+    """
+    self._adb_path = adb_path
+    # argument to pass to adb, to direct command to specific device
+    self._target_arg = ""
+
   def SetEmulatorTarget(self):
     """Direct all future commands to the only running emulator."""
     self._target_arg = "-e"
@@ -66,7 +74,7 @@
     Raises:
       WaitForResponseTimedOutError if device does not respond to command within time
     """
-    adb_cmd = "adb %s %s" % (self._target_arg, command_string)
+    adb_cmd = "%s %s %s" % (self._adb_path, 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)
diff --git a/third_party/checkstyle/README.chromium b/third_party/checkstyle/README.chromium
index 53a267c..0ceef78 100644
--- a/third_party/checkstyle/README.chromium
+++ b/third_party/checkstyle/README.chromium
@@ -2,7 +2,7 @@
       adheres to a coding standard.
 Short Name: checkstyle
 URL: http://checkstyle.sourceforge.net/
-Version: 5.9
+Version: 6.1
 License: LGPL 2.1
 License File: LICENSE
 Security Critical: no
@@ -11,16 +11,5 @@
 Checkstyle is used to validate Java code style on Chromium PRESUBMIT step.
 
 Local Modifications:
-- Removed contrib/ and site/ directories that contained examples of how to write
-  new checkstyle modules.
-- Removed xml files used for Eclipse setup when building new checkstyle modules.
-  - checkstyle_checks.xml
-  - import-control.xml
-  - supressions.xml
-- Removed jars already included in checkstyle-5.9-all.jar
-  - antlr-2.7.7.jar
-  - checkstyle-5.9.jar
-  - commons-beanutils-core-1.8.3.jar
-  - commons-cli-1.2.jar
-  - commons-logging-1.1.1.jar
-  - guava-jdk5-14.0.1.jar
+- Downloaded checkstyle-6.1-all.jar without source code development
+  documentation.
diff --git a/third_party/checkstyle/checkstyle-5.9-all.jar b/third_party/checkstyle/checkstyle-5.9-all.jar
deleted file mode 100644
index a820e2e..0000000
--- a/third_party/checkstyle/checkstyle-5.9-all.jar
+++ /dev/null
Binary files differ
diff --git a/third_party/checkstyle/checkstyle-6.1-all.jar b/third_party/checkstyle/checkstyle-6.1-all.jar
new file mode 100644
index 0000000..70c272b
--- /dev/null
+++ b/third_party/checkstyle/checkstyle-6.1-all.jar
Binary files differ
diff --git a/third_party/checkstyle/sun_checks.xml b/third_party/checkstyle/sun_checks.xml
deleted file mode 100644
index 709f3ec..0000000
--- a/third_party/checkstyle/sun_checks.xml
+++ /dev/null
@@ -1,177 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE module PUBLIC
-          "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
-          "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
-
-<!--
-
-  Checkstyle configuration that checks the sun coding conventions from:
-
-    - the Java Language Specification at
-      http://java.sun.com/docs/books/jls/second_edition/html/index.html
-
-    - the Sun Code Conventions at http://java.sun.com/docs/codeconv/
-
-    - the Javadoc guidelines at
-      http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
-
-    - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
-
-    - some best practices
-
-  Checkstyle is very configurable. Be sure to read the documentation at
-  http://checkstyle.sf.net (or in your downloaded distribution).
-
-  Most Checks are configurable, be sure to consult the documentation.
-
-  To completely disable a check, just comment it out or delete it from the file.
-
-  Finally, it is worth reading the documentation.
-
--->
-
-<module name="Checker">
-    <!--
-        If you set the basedir property below, then all reported file
-        names will be relative to the specified directory. See
-        http://checkstyle.sourceforge.net/5.x/config.html#Checker
-
-        <property name="basedir" value="${basedir}"/>
-    -->
-
-    <!-- Checks that a package-info.java file exists for each package.     -->
-    <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
-    <module name="JavadocPackage"/>
-
-    <!-- Checks whether files end with a new line.                        -->
-    <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
-    <module name="NewlineAtEndOfFile"/>
-
-    <!-- Checks that property files contain the same keys.         -->
-    <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
-    <module name="Translation"/>
-    
-    <!-- Checks for Size Violations.                    -->
-    <!-- See http://checkstyle.sf.net/config_sizes.html -->
-    <module name="FileLength"/>
-    
-    <!-- Checks for whitespace                               -->
-    <!-- See http://checkstyle.sf.net/config_whitespace.html -->
-    <module name="FileTabCharacter"/>
-
-    <!-- Miscellaneous other checks.                   -->
-    <!-- See http://checkstyle.sf.net/config_misc.html -->
-    <module name="RegexpSingleline">
-       <property name="format" value="\s+$"/>
-       <property name="minimum" value="0"/>
-       <property name="maximum" value="0"/>
-       <property name="message" value="Line has trailing spaces."/>
-    </module>
-
-    <!-- Checks for Headers                                -->
-    <!-- See http://checkstyle.sf.net/config_header.html   -->
-    <!-- <module name="Header"> -->
-    <!--   <property name="headerFile" value="${checkstyle.header.file}"/> -->
-    <!--   <property name="fileExtensions" value="java"/> -->
-    <!-- </module> -->
-
-    <module name="TreeWalker">
-
-        <!-- Checks for Javadoc comments.                     -->
-        <!-- See http://checkstyle.sf.net/config_javadoc.html -->
-        <module name="JavadocMethod"/>
-        <module name="JavadocType"/>
-        <module name="JavadocVariable"/>
-        <module name="JavadocStyle"/>
-
-
-        <!-- Checks for Naming Conventions.                  -->
-        <!-- See http://checkstyle.sf.net/config_naming.html -->
-        <module name="ConstantName"/>
-        <module name="LocalFinalVariableName"/>
-        <module name="LocalVariableName"/>
-        <module name="MemberName"/>
-        <module name="MethodName"/>
-        <module name="PackageName"/>
-        <module name="ParameterName"/>
-        <module name="StaticVariableName"/>
-        <module name="TypeName"/>
-
-
-        <!-- Checks for imports                              -->
-        <!-- See http://checkstyle.sf.net/config_import.html -->
-        <module name="AvoidStarImport"/>
-        <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
-        <module name="RedundantImport"/>
-        <module name="UnusedImports"/>
-
-
-        <!-- Checks for Size Violations.                    -->
-        <!-- See http://checkstyle.sf.net/config_sizes.html -->
-        <module name="LineLength"/>
-        <module name="MethodLength"/>
-        <module name="ParameterNumber"/>
-
-
-        <!-- Checks for whitespace                               -->
-        <!-- See http://checkstyle.sf.net/config_whitespace.html -->
-        <module name="EmptyForIteratorPad"/>
-        <module name="GenericWhitespace"/>
-        <module name="MethodParamPad"/>
-        <module name="NoWhitespaceAfter"/>
-        <module name="NoWhitespaceBefore"/>
-        <module name="OperatorWrap"/>
-        <module name="ParenPad"/>
-        <module name="TypecastParenPad"/>
-        <module name="WhitespaceAfter"/>
-        <module name="WhitespaceAround"/>
-
-
-        <!-- Modifier Checks                                    -->
-        <!-- See http://checkstyle.sf.net/config_modifiers.html -->
-        <module name="ModifierOrder"/>
-        <module name="RedundantModifier"/>
-
-
-        <!-- Checks for blocks. You know, those {}'s         -->
-        <!-- See http://checkstyle.sf.net/config_blocks.html -->
-        <module name="AvoidNestedBlocks"/>
-        <module name="EmptyBlock"/>
-        <module name="LeftCurly"/>
-        <module name="NeedBraces"/>
-        <module name="RightCurly"/>
-
-
-        <!-- Checks for common coding problems               -->
-        <!-- See http://checkstyle.sf.net/config_coding.html -->
-        <module name="AvoidInlineConditionals"/>
-        <module name="EmptyStatement"/>
-        <module name="EqualsHashCode"/>
-        <module name="HiddenField"/>
-        <module name="IllegalInstantiation"/>
-        <module name="InnerAssignment"/>
-        <module name="MagicNumber"/>
-        <module name="MissingSwitchDefault"/>
-        <module name="RedundantThrows"/>
-        <module name="SimplifyBooleanExpression"/>
-        <module name="SimplifyBooleanReturn"/>
-
-        <!-- Checks for class design                         -->
-        <!-- See http://checkstyle.sf.net/config_design.html -->
-        <module name="DesignForExtension"/>
-        <module name="FinalClass"/>
-        <module name="HideUtilityClassConstructor"/>
-        <module name="InterfaceIsType"/>
-        <module name="VisibilityModifier"/>
-
-
-        <!-- Miscellaneous other checks.                   -->
-        <!-- See http://checkstyle.sf.net/config_misc.html -->
-        <module name="ArrayTypeStyle"/>
-        <module name="FinalParameters"/>
-        <module name="TodoComment"/>
-        <module name="UpperEll"/>
-
-    </module>
-
-</module>
diff --git a/third_party/cython/rules.gni b/third_party/cython/rules.gni
index 252e948..efd9ca3 100644
--- a/third_party/cython/rules.gni
+++ b/third_party/cython/rules.gni
@@ -76,6 +76,9 @@
       sources += invoker.additional_sources
     }
     configs += [ ":$config_name" ]
+    if (defined(invoker.configs)) {
+      configs += invoker.configs
+    }
   }
 
   copy(target_name) {
diff --git a/third_party/harfbuzz-ng/harfbuzz.gyp b/third_party/harfbuzz-ng/harfbuzz.gyp
index 3e6fed4..96e4b7c 100644
--- a/third_party/harfbuzz-ng/harfbuzz.gyp
+++ b/third_party/harfbuzz-ng/harfbuzz.gyp
@@ -30,6 +30,12 @@
       }, {
         'use_system_harfbuzz': 0,
       }],
+      ['OS=="linux" and target_arch=="arm" and chromeos==0', {
+        # Override use_system_harfbuzz for ARM cross compiling so system
+        # harfbuzz is not used because the corresponding package is not
+        # available.
+        'use_system_harfbuzz': 0,
+      }],
     ],
   },
   'conditions': [
diff --git a/third_party/zlib/google/zip.h b/third_party/zlib/google/zip.h
index 0232401..216b09e 100644
--- a/third_party/zlib/google/zip.h
+++ b/third_party/zlib/google/zip.h
@@ -30,9 +30,10 @@
 
 #if defined(OS_POSIX)
 // Zips files listed in |src_relative_paths| to destination specified by file
-// descriptor |dest_fd|. The paths listed in |src_relative_paths| are relative
-// to the |src_dir| and will be used as the file names in the created zip file.
-// All source paths must be under |src_dir| in the file system hierarchy.
+// descriptor |dest_fd|, without taking ownership of |dest_fd|. The paths listed
+// in |src_relative_paths| are relative to the |src_dir| and will be used as the
+// file names in the created zip file. All source paths must be under |src_dir|
+// in the file system hierarchy.
 bool ZipFiles(const base::FilePath& src_dir,
               const std::vector<base::FilePath>& src_relative_paths,
               int dest_fd);
diff --git a/third_party/zlib/google/zip_internal.cc b/third_party/zlib/google/zip_internal.cc
index d62e0bb..1f026c9 100644
--- a/third_party/zlib/google/zip_internal.cc
+++ b/third_party/zlib/google/zip_internal.cc
@@ -79,6 +79,8 @@
 
 #if defined(OS_POSIX)
 // Callback function for zlib that opens a file stream from a file descriptor.
+// Since we do not own the file descriptor, dup it so that we can fdopen/fclose
+// a file stream.
 void* FdOpenFileFunc(void* opaque, const char* filename, int mode) {
   FILE* file = NULL;
   const char* mode_fopen = NULL;
@@ -90,18 +92,18 @@
   else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
     mode_fopen = "wb";
 
-  if ((filename != NULL) && (mode_fopen != NULL))
-    file = fdopen(*static_cast<int*>(opaque), mode_fopen);
+  if ((filename != NULL) && (mode_fopen != NULL)) {
+    int fd = dup(*static_cast<int*>(opaque));
+    if (fd != -1)
+      file = fdopen(fd, mode_fopen);
+  }
 
   return file;
 }
 
-// We don't actually close the file stream since that would close
-// the underlying file descriptor, and we don't own it. However we do need to
-// flush buffers and free |opaque| since we malloc'ed it in FillFdOpenFileFunc.
-int CloseFileFunc(void* opaque, void* stream) {
-  fflush(static_cast<FILE*>(stream));
-  free(opaque);
+int FdCloseFileFunc(void* opaque, void* stream) {
+  fclose(static_cast<FILE*>(stream));
+  free(opaque); // malloc'ed in FillFdOpenFileFunc()
   return 0;
 }
 
@@ -110,7 +112,7 @@
 void FillFdOpenFileFunc(zlib_filefunc_def* pzlib_filefunc_def, int fd) {
   fill_fopen_filefunc(pzlib_filefunc_def);
   pzlib_filefunc_def->zopen_file = FdOpenFileFunc;
-  pzlib_filefunc_def->zclose_file = CloseFileFunc;
+  pzlib_filefunc_def->zclose_file = FdCloseFileFunc;
   int* ptr_fd = static_cast<int*>(malloc(sizeof(fd)));
   *ptr_fd = fd;
   pzlib_filefunc_def->opaque = ptr_fd;
@@ -119,6 +121,7 @@
 
 #if defined(OS_WIN)
 // Callback function for zlib that opens a file stream from a Windows handle.
+// Does not take ownership of the handle.
 void* HandleOpenFileFunc(void* opaque, const char* filename, int mode) {
   WIN32FILE_IOWIN file_ret;
   file_ret.hf = static_cast<HANDLE>(opaque);
@@ -131,6 +134,11 @@
     *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret;
   return ret;
 }
+
+int HandleCloseFileFunc(void* opaque, void* stream) {
+  free(stream); // malloc'ed in HandleOpenFileFunc()
+  return 0;
+}
 #endif
 
 // A struct that contains data required for zlib functions to extract files from
@@ -282,6 +290,7 @@
   zlib_filefunc_def zip_funcs;
   fill_win32_filefunc(&zip_funcs);
   zip_funcs.zopen_file = HandleOpenFileFunc;
+  zip_funcs.zclose_file = HandleCloseFileFunc;
   zip_funcs.opaque = zip_handle;
   return unzOpen2("fd", &zip_funcs);
 }
diff --git a/third_party/zlib/google/zip_reader.h b/third_party/zlib/google/zip_reader.h
index cda9cf7..9280f23 100644
--- a/third_party/zlib/google/zip_reader.h
+++ b/third_party/zlib/google/zip_reader.h
@@ -102,8 +102,8 @@
   // success.
   bool Open(const base::FilePath& zip_file_path);
 
-  // Opens the zip file referred to by the platform file |zip_fd|.
-  // Returns true on success.
+  // Opens the zip file referred to by the platform file |zip_fd|, without
+  // taking ownership of |zip_fd|. Returns true on success.
   bool OpenFromPlatformFile(base::PlatformFile zip_fd);
 
   // Opens the zip data stored in |data|. This class uses a weak reference to
diff --git a/third_party/zlib/google/zip_reader_unittest.cc b/third_party/zlib/google/zip_reader_unittest.cc
index 09fc241..d4bb579 100644
--- a/third_party/zlib/google/zip_reader_unittest.cc
+++ b/third_party/zlib/google/zip_reader_unittest.cc
@@ -573,4 +573,13 @@
   reader.Close();
 }
 
+// This test exposes http://crbug.com/430959, at least on OS X
+TEST_F(ZipReaderTest, DISABLED_LeakDetectionTest) {
+  for (int i = 0; i < 100000; ++i) {
+    FileWrapper zip_fd_wrapper(test_zip_file_, FileWrapper::READ_ONLY);
+    ZipReader reader;
+    ASSERT_TRUE(reader.OpenFromPlatformFile(zip_fd_wrapper.platform_file()));
+  }
+}
+
 }  // namespace zip
diff --git a/tools/android/checkstyle/checkstyle.py b/tools/android/checkstyle/checkstyle.py
index c8ad04f..0c260bb 100644
--- a/tools/android/checkstyle/checkstyle.py
+++ b/tools/android/checkstyle/checkstyle.py
@@ -13,7 +13,7 @@
     os.path.join(os.path.dirname(__file__),
                  os.pardir, os.pardir, os.pardir))
 CHECKSTYLE_ROOT = os.path.join(CHROMIUM_SRC, 'third_party', 'checkstyle',
-                               'checkstyle-5.9-all.jar')
+                               'checkstyle-6.1-all.jar')
 
 
 def RunCheckstyle(input_api, output_api, style_file):
diff --git a/tools/android/checkstyle/chromium-style-5.0.xml b/tools/android/checkstyle/chromium-style-5.0.xml
index 46b19e9..c43f779 100644
--- a/tools/android/checkstyle/chromium-style-5.0.xml
+++ b/tools/android/checkstyle/chromium-style-5.0.xml
@@ -91,7 +91,7 @@
     </module>
     <module name="LineLength">
       <property name="severity" value="error"/>
-      <property name="ignorePattern" value="^import.*$" />
+      <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
       <property name="max" value="100"/>
     </module>
     <module name="LeftCurly">
@@ -138,6 +138,17 @@
       <property name="allowLineBreaks" value="true"/>
       <property name="tokens" value="SEMI, DOT, POST_DEC, POST_INC"/>
     </module>
+    <module name="GenericWhitespace">
+      <property name="severity" value="error"/>
+      <message key="ws.followed"
+       value="GenericWhitespace ''{0}'' is followed by whitespace."/>
+       <message key="ws.preceded"
+       value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
+       <message key="ws.illegalFollow"
+       value="GenericWhitespace ''{0}'' should followed by whitespace."/>
+       <message key="ws.notPreceded"
+       value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
+    </module>
     <module name="EmptyStatement">
       <property name="severity" value="error"/>
     </module>
@@ -166,22 +177,22 @@
     </module>
     <!-- TODO(aurimas): make OperatorWrap into an error once all the warnings are fixed. -->
     <module name="OperatorWrap">
-      <property name="severity" value="warning"/>
+      <property name="severity" value="error"/>
       <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="severity" value="error"/>
      <property name="option" value="eol"/>
      <property name="tokens" value="ASSIGN"/>
     </module>
     <module name="SeparatorWrap">
-      <property name="severity" value="warning"/>
+      <property name="severity" value="error"/>
       <property name="tokens" value="DOT"/>
       <property name="option" value="nl"/>
     </module>
     <module name="SeparatorWrap">
-      <property name="severity" value="warning"/>
+      <property name="severity" value="error"/>
       <property name="tokens" value="COMMA"/>
       <property name="option" value="EOL"/>
     </module>
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index c8bc543..7e36653 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -206,7 +206,7 @@
   // Enum type with _LAST members where _LAST doesn't mean last enum value.
   ignored_record_names_.insert("ServerFieldType");
 
-  // Used heavily in ui_unittests and once in views_unittests. Fixing this
+  // Used heavily in ui_base_unittests and once in views_unittests. Fixing this
   // isn't worth the overhead of an additional library.
   ignored_record_names_.insert("TestAnimationDelegate");
 
diff --git a/tools/clang/plugins/FindBadConstructsConsumer.cpp b/tools/clang/plugins/FindBadConstructsConsumer.cpp
index 0a230e0..f08ca71 100644
--- a/tools/clang/plugins/FindBadConstructsConsumer.cpp
+++ b/tools/clang/plugins/FindBadConstructsConsumer.cpp
@@ -724,28 +724,37 @@
       the_end(record->field_end());
   SourceLocation weak_ptr_factory_location;  // Invalid initially.
   for (; iter != the_end; ++iter) {
-    // If we enter the loop but have already seen a matching WeakPtrFactory,
-    // it means there is at least one member after the factory.
-    if (weak_ptr_factory_location.isValid()) {
-      diagnostic().Report(weak_ptr_factory_location,
-                          diag_weak_ptr_factory_order_);
-    }
     const TemplateSpecializationType* template_spec_type =
         iter->getType().getTypePtr()->getAs<TemplateSpecializationType>();
+    bool param_is_weak_ptr_factory_to_self = false;
     if (template_spec_type) {
       const TemplateDecl* template_decl =
           template_spec_type->getTemplateName().getAsTemplateDecl();
-      if (template_decl && template_spec_type->getNumArgs() >= 1) {
+      if (template_decl && template_spec_type->getNumArgs() == 1) {
         if (template_decl->getNameAsString().compare("WeakPtrFactory") == 0 &&
             GetNamespace(template_decl) == "base") {
+          // Only consider WeakPtrFactory members which are specialized for the
+          // owning class.
           const TemplateArgument& arg = template_spec_type->getArg(0);
           if (arg.getAsType().getTypePtr()->getAsCXXRecordDecl() ==
               record->getTypeForDecl()->getAsCXXRecordDecl()) {
-            weak_ptr_factory_location = iter->getLocation();
+            if (!weak_ptr_factory_location.isValid()) {
+              // Save the first matching WeakPtrFactory member for the
+              // diagnostic.
+              weak_ptr_factory_location = iter->getLocation();
+            }
+            param_is_weak_ptr_factory_to_self = true;
           }
         }
       }
     }
+    // If we've already seen a WeakPtrFactory<OwningType> and this param is not
+    // one of those, it means there is at least one member after a factory.
+    if (weak_ptr_factory_location.isValid() &&
+        !param_is_weak_ptr_factory_to_self) {
+      diagnostic().Report(weak_ptr_factory_location,
+                          diag_weak_ptr_factory_order_);
+    }
   }
 }
 
diff --git a/tools/clang/plugins/tests/weak_ptr_factory.cpp b/tools/clang/plugins/tests/weak_ptr_factory.cpp
index 79c23b4..50de97c 100644
--- a/tools/clang/plugins/tests/weak_ptr_factory.cpp
+++ b/tools/clang/plugins/tests/weak_ptr_factory.cpp
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "weak_ptr_factory.h"
+
 namespace should_succeed {
 
 class OnlyMember {
@@ -27,6 +28,13 @@
   base::WeakPtrFactory<FirstFactoryRefersToOtherType> factory_;
 };
 
+class TwoFactories {
+  bool bool_member_;
+  int int_member_;
+  base::WeakPtrFactory<TwoFactories> factory1_;
+  base::WeakPtrFactory<TwoFactories> factory2_;
+};
+
 }  // namespace should_succeed
 
 namespace should_fail {
@@ -42,6 +50,13 @@
   int int_member_;
 };
 
+class TwoFactoriesOneBad {
+  bool bool_member_;
+  base::WeakPtrFactory<TwoFactoriesOneBad> factory1_;
+  int int_member_;
+  base::WeakPtrFactory<TwoFactoriesOneBad> factory2_;
+};
+
 }  // namespace should_fail
 
 int main() {
diff --git a/tools/clang/plugins/tests/weak_ptr_factory.txt b/tools/clang/plugins/tests/weak_ptr_factory.txt
index f9c2c0a..820b7db 100644
--- a/tools/clang/plugins/tests/weak_ptr_factory.txt
+++ b/tools/clang/plugins/tests/weak_ptr_factory.txt
@@ -1,7 +1,10 @@
-weak_ptr_factory.cpp:35:38: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
+weak_ptr_factory.cpp:43:38: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
   base::WeakPtrFactory<FactoryFirst> factory_;
                                      ^
-weak_ptr_factory.cpp:41:39: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
+weak_ptr_factory.cpp:49:39: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
   base::WeakPtrFactory<FactoryMiddle> factory_;
                                       ^
-2 warnings generated.
+weak_ptr_factory.cpp:55:44: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
+  base::WeakPtrFactory<TwoFactoriesOneBad> factory1_;
+                                           ^
+3 warnings generated.
diff --git a/tools/clang/rewrite_scoped_refptr/CMakeLists.txt b/tools/clang/rewrite_scoped_refptr/CMakeLists.txt
index 9b0184d..aa47400 100644
--- a/tools/clang/rewrite_scoped_refptr/CMakeLists.txt
+++ b/tools/clang/rewrite_scoped_refptr/CMakeLists.txt
@@ -2,6 +2,7 @@
   BitReader
   MCParser
   Option
+  X86AsmParser
   )
 
 add_llvm_executable(rewrite_scoped_refptr
diff --git a/tools/clang/rewrite_scoped_refptr/RewriteScopedRefptr.cpp b/tools/clang/rewrite_scoped_refptr/RewriteScopedRefptr.cpp
index fe9d860..e11d5f9 100644
--- a/tools/clang/rewrite_scoped_refptr/RewriteScopedRefptr.cpp
+++ b/tools/clang/rewrite_scoped_refptr/RewriteScopedRefptr.cpp
@@ -22,6 +22,7 @@
 #include "clang/Tooling/Refactoring.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/support/TargetSelect.h"
 
 using namespace clang::ast_matchers;
 using clang::tooling::CommonOptionsParser;
@@ -255,6 +256,10 @@
 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
 
 int main(int argc, const char* argv[]) {
+  // TODO(dcheng): Clang tooling should do this itself.
+  // http://llvm.org/bugs/show_bug.cgi?id=21627
+  llvm::InitializeNativeTarget();
+  llvm::InitializeNativeTargetAsmParser();
   llvm::cl::OptionCategory category("Remove scoped_refptr conversions");
   CommonOptionsParser options(argc, argv, category);
   clang::tooling::ClangTool tool(options.getCompilations(),
diff --git a/tools/clang/scripts/generate_win_compdb.py b/tools/clang/scripts/generate_win_compdb.py
new file mode 100755
index 0000000..32f5f75
--- /dev/null
+++ b/tools/clang/scripts/generate_win_compdb.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Clang tools on Windows are still a bit busted. The tooling can't handle
+backslashes in paths, doesn't understand how to read .rsp files, etc. In
+addition, ninja generates compile commands prefixed with the ninja msvc helper,
+which also confuses clang. This script generates a compile DB that should mostly
+work until clang tooling can be improved upstream.
+"""
+
+import os
+import re
+import json
+import shlex
+import subprocess
+import sys
+
+
+_NINJA_MSVC_WRAPPER = re.compile('ninja -t msvc -e .+? -- ')
+_RSP_RE = re.compile(r' (@(.+?\.rsp)) ')
+
+
+def _ProcessEntry(e):
+  # Strip off the ninja -t msvc wrapper.
+  e['command'] = _NINJA_MSVC_WRAPPER.sub('', e['command'])
+
+  # Prepend --driver-mode=cl to the command's arguments.
+  # Escape backslashes so shlex doesn't try to interpret them.
+  escaped_command = e['command'].replace('\\', '\\\\')
+  split_command = shlex.split(escaped_command)
+  e['command'] = ' '.join(
+      split_command[:1] + ['--driver-mode=cl'] + split_command[1:])
+
+  # Expand the contents of the response file, if any.
+  # http://llvm.org/bugs/show_bug.cgi?id=21634
+  try:
+    match = _RSP_RE.search(e['command'])
+    rsp_path = os.path.join(e['directory'], match.group(2))
+    rsp_contents = file(rsp_path).read()
+    e['command'] = ''.join([
+        e['command'][:match.start(1)],
+        rsp_contents,
+        e['command'][match.end(1):]])
+  except IOError:
+    pass
+
+  # TODO(dcheng): This should be implemented in Clang tooling.
+  # http://llvm.org/bugs/show_bug.cgi?id=19687
+  # Finally, use slashes instead of backslashes to avoid bad escaping by the
+  # tooling. This should really only matter for command, but we do it for all
+  # keys for consistency.
+  e['directory'] = e['directory'].replace('\\', '/')
+  e['command'] = e['command'].replace('\\', '/')
+  e['file'] = e['file'].replace('\\', '/')
+
+  return e
+
+
+def main(argv):
+  # First, generate the compile database.
+  print 'Generating compile DB with ninja...'
+  compile_db_as_json = subprocess.check_output(shlex.split(
+      'ninja -C out/Debug -t compdb cc cxx objc objcxx'))
+
+  compile_db = json.loads(compile_db_as_json)
+  print 'Read in %d entries from the compile db' % len(compile_db)
+  compile_db = [_ProcessEntry(e) for e in compile_db]
+  original_length = len(compile_db)
+
+  # Filter out NaCl stuff. The clang tooling chokes on them.
+  compile_db = [e for e in compile_db if '_nacl.cc.pdb' not in e['command']
+      and '_nacl_win64.cc.pdb' not in e['command']]
+  print 'Filtered out %d entries...' % (original_length - len(compile_db))
+  f = file('out/Debug/compile_commands.json', 'w')
+  f.write(json.dumps(compile_db, indent=2))
+  print 'Done!'
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv[1:]))
diff --git a/tools/clang/scripts/run_tool.py b/tools/clang/scripts/run_tool.py
index 61417e4..3725ca3 100755
--- a/tools/clang/scripts/run_tool.py
+++ b/tools/clang/scripts/run_tool.py
@@ -9,6 +9,9 @@
 If you want to run the tool across all Chromium code:
 run_tool.py <tool> <path/to/compiledb>
 
+If you want to include all files mentioned in the compilation database:
+run_tool.py <tool> <path/to/compiledb> --all
+
 If you only want to run the tool across just chrome/browser and content/browser:
 run_tool.py <tool> <path/to/compiledb> chrome/browser content/browser
 
@@ -37,6 +40,7 @@
 
 import collections
 import functools
+import json
 import multiprocessing
 import os.path
 import pipes
@@ -67,6 +71,20 @@
   return [os.path.realpath(p) for p in output.splitlines()]
 
 
+def _GetFilesFromCompileDB(build_directory):
+  """ Gets the list of files mentioned in the compilation database.
+
+  Args:
+    build_directory: Directory that contains the compile database.
+  """
+  compiledb_path = os.path.join(build_directory, 'compile_commands.json')
+  with open(compiledb_path, 'rb') as compiledb_file:
+    json_commands = json.load(compiledb_file)
+
+  return [os.path.join(entry['directory'], entry['file'])
+          for entry in json_commands]
+
+
 def _ExtractEditsFromStdout(build_directory, stdout):
   """Extracts generated list of edits from the tool's stdout.
 
@@ -295,7 +313,10 @@
   if not os.path.isfile(clang_format_diff_path) or sys.platform == 'win32':
     clang_format_diff_path = None
 
-  filenames = frozenset(_GetFilesFromGit(argv[2:]))
+  if len(argv) == 3 and argv[2] == '--all':
+    filenames = frozenset(_GetFilesFromCompileDB(argv[1]))
+  else:
+    filenames = frozenset(_GetFilesFromGit(argv[2:]))
   # Filter out files that aren't C/C++/Obj-C/Obj-C++.
   extensions = frozenset(('.c', '.cc', '.m', '.mm'))
   dispatcher = _CompilerDispatcher(argv[0], argv[1],
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
index e576cac..ad534ad 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -704,7 +704,8 @@
       --platform=android-14 \
       --install-dir="${LLVM_BUILD_DIR}/android-toolchain" \
       --system=linux-x86_64 \
-      --stl=stlport
+      --stl=stlport \
+      --toolchain=arm-linux-androideabi-4.9
 
   # Android NDK r9d copies a broken unwind.h into the toolchain, see
   # http://crbug.com/357890
diff --git a/tools/clang/translation_unit/CMakeLists.txt b/tools/clang/translation_unit/CMakeLists.txt
new file mode 100644
index 0000000..9b4fd8b
--- /dev/null
+++ b/tools/clang/translation_unit/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(LLVM_LINK_COMPONENTS
+  BitReader
+  MCParser
+  Option
+  )
+
+add_llvm_executable(translation_unit
+  TranslationUnitGenerator.cpp
+  )
+
+target_link_libraries(translation_unit
+  clangAST
+  clangASTMatchers
+  clangAnalysis
+  clangBasic
+  clangDriver
+  clangEdit
+  clangFrontend
+  clangLex
+  clangParse
+  clangSema
+  clangSerialization
+  clangTooling
+  )
+
+cr_install(TARGETS translation_unit RUNTIME DESTINATION bin)
diff --git a/tools/clang/translation_unit/TranslationUnitGenerator.cpp b/tools/clang/translation_unit/TranslationUnitGenerator.cpp
new file mode 100644
index 0000000..df9eaeb
--- /dev/null
+++ b/tools/clang/translation_unit/TranslationUnitGenerator.cpp
@@ -0,0 +1,218 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This implements a Clang tool to generate compilation information that is
+// sufficient to recompile the code with clang. For each compilation unit, all
+// source files which are necessary for compiling it are determined. For each
+// compilation unit, a file is created containing a list of all file paths of
+// included files.
+
+#include <assert.h>
+#include <unistd.h>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <stack>
+#include <string>
+#include <vector>
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+
+using clang::tooling::CommonOptionsParser;
+using std::set;
+using std::stack;
+using std::string;
+using std::vector;
+
+namespace {
+// Set of preprocessor callbacks used to record files included.
+class IncludeFinderPPCallbacks : public clang::PPCallbacks {
+ public:
+  IncludeFinderPPCallbacks(clang::SourceManager* source_manager,
+                           string* main_source_file,
+                           set<string>* source_file_paths)
+      : source_manager_(source_manager),
+        main_source_file_(main_source_file),
+        source_file_paths_(source_file_paths) {}
+  void FileChanged(clang::SourceLocation /*loc*/,
+                   clang::PPCallbacks::FileChangeReason reason,
+                   clang::SrcMgr::CharacteristicKind /*file_type*/,
+                   clang::FileID /*prev_fid*/) override;
+  void AddFile(const string& path);
+  void InclusionDirective(clang::SourceLocation hash_loc,
+                          const clang::Token& include_tok,
+                          llvm::StringRef file_name,
+                          bool is_angled,
+                          clang::CharSourceRange range,
+                          const clang::FileEntry* file,
+                          llvm::StringRef search_path,
+                          llvm::StringRef relative_path,
+                          const clang::Module* imported) override;
+  void EndOfMainFile() override;
+
+ private:
+  clang::SourceManager* const source_manager_;
+  string* const main_source_file_;
+  set<string>* const source_file_paths_;
+  // The path of the file that was last referenced by an inclusion directive,
+  // normalized for includes that are relative to a different source file.
+  string last_inclusion_directive_;
+  // The stack of currently parsed files. top() gives the current file.
+  stack<string> current_files_;
+};
+
+void IncludeFinderPPCallbacks::FileChanged(
+    clang::SourceLocation /*loc*/,
+    clang::PPCallbacks::FileChangeReason reason,
+    clang::SrcMgr::CharacteristicKind /*file_type*/,
+    clang::FileID /*prev_fid*/) {
+  if (reason == clang::PPCallbacks::EnterFile) {
+    if (!last_inclusion_directive_.empty()) {
+      current_files_.push(last_inclusion_directive_);
+    } else {
+      current_files_.push(
+          source_manager_->getFileEntryForID(source_manager_->getMainFileID())
+              ->getName());
+    }
+  } else if (reason == ExitFile) {
+    current_files_.pop();
+  }
+  // Other reasons are not interesting for us.
+}
+
+void IncludeFinderPPCallbacks::AddFile(const string& path) {
+  source_file_paths_->insert(path);
+}
+
+void IncludeFinderPPCallbacks::InclusionDirective(
+    clang::SourceLocation hash_loc,
+    const clang::Token& include_tok,
+    llvm::StringRef file_name,
+    bool is_angled,
+    clang::CharSourceRange range,
+    const clang::FileEntry* file,
+    llvm::StringRef search_path,
+    llvm::StringRef relative_path,
+    const clang::Module* imported) {
+  if (!file)
+    return;
+
+  assert(!current_files_.top().empty());
+  const clang::DirectoryEntry* const search_path_entry =
+      source_manager_->getFileManager().getDirectory(search_path);
+  const clang::DirectoryEntry* const current_file_parent_entry =
+      source_manager_->getFileManager()
+          .getFile(current_files_.top().c_str())
+          ->getDir();
+
+  // If the include file was found relatively to the current file's parent
+  // directory or a search path, we need to normalize it. This is necessary
+  // because llvm internalizes the path by which an inode was first accessed,
+  // and always returns that path afterwards. If we do not normalize this
+  // we will get an error when we replay the compilation, as the virtual
+  // file system is not aware of inodes.
+  if (search_path_entry == current_file_parent_entry) {
+    string parent =
+        llvm::sys::path::parent_path(current_files_.top().c_str()).str();
+
+    // If the file is a top level file ("file.cc"), we normalize to a path
+    // relative to "./".
+    if (parent.empty() || parent == "/")
+      parent = ".";
+
+    // Otherwise we take the literal path as we stored it for the current
+    // file, and append the relative path.
+    last_inclusion_directive_ = parent + "/" + relative_path.str();
+  } else if (!search_path.empty()) {
+    last_inclusion_directive_ = string(search_path) + "/" + relative_path.str();
+  } else {
+    last_inclusion_directive_ = file_name.str();
+  }
+  AddFile(last_inclusion_directive_);
+}
+
+void IncludeFinderPPCallbacks::EndOfMainFile() {
+  const clang::FileEntry* main_file =
+      source_manager_->getFileEntryForID(source_manager_->getMainFileID());
+  assert(*main_source_file_ == main_file->getName());
+  AddFile(main_file->getName());
+}
+
+class CompilationIndexerAction : public clang::PreprocessorFrontendAction {
+ public:
+  CompilationIndexerAction() {}
+  void ExecuteAction() override;
+
+  // Runs the preprocessor over the translation unit.
+  // This triggers the PPCallbacks we register to intercept all required
+  // files for the compilation.
+  void Preprocess();
+  void EndSourceFileAction() override;
+
+ private:
+  // Set up the state extracted during the compilation, and run Clang over the
+  // input.
+  string main_source_file_;
+  // Maps file names to their contents as read by Clang's source manager.
+  set<string> source_file_paths_;
+};
+
+void CompilationIndexerAction::ExecuteAction() {
+  vector<clang::FrontendInputFile> inputs =
+      getCompilerInstance().getFrontendOpts().Inputs;
+  assert(inputs.size() == 1);
+  main_source_file_ = inputs[0].getFile();
+
+  Preprocess();
+}
+
+void CompilationIndexerAction::Preprocess() {
+  clang::Preprocessor& preprocessor = getCompilerInstance().getPreprocessor();
+  preprocessor.addPPCallbacks(llvm::make_unique<IncludeFinderPPCallbacks>(
+      &getCompilerInstance().getSourceManager(),
+      &main_source_file_,
+      &source_file_paths_));
+  preprocessor.IgnorePragmas();
+  preprocessor.SetSuppressIncludeNotFoundError(true);
+  preprocessor.EnterMainSourceFile();
+  clang::Token token;
+  do {
+    preprocessor.Lex(token);
+  } while (token.isNot(clang::tok::eof));
+}
+
+void CompilationIndexerAction::EndSourceFileAction() {
+  std::ofstream out(main_source_file_ + ".filepaths");
+  for (string path : source_file_paths_) {
+    out << path << std::endl;
+  }
+}
+}  // namespace
+
+static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
+
+int main(int argc, const char* argv[]) {
+  llvm::cl::OptionCategory category("TranslationUnitGenerator Tool");
+  CommonOptionsParser options(argc, argv, category);
+  std::unique_ptr<clang::tooling::FrontendActionFactory> frontend_factory =
+      clang::tooling::newFrontendActionFactory<CompilationIndexerAction>();
+  clang::tooling::ClangTool tool(options.getCompilations(),
+                                 options.getSourcePathList());
+  // This clang tool does not actually produce edits, but run_tool.py expects
+  // this. So we just print an empty edit block.
+  llvm::outs() << "==== BEGIN EDITS ====\n";
+  llvm::outs() << "==== END EDITS ====\n";
+  return tool.run(frontend_factory.get());
+}
diff --git a/tools/clang/translation_unit/test_files/binomial.h b/tools/clang/translation_unit/test_files/binomial.h
new file mode 100644
index 0000000..c67b273
--- /dev/null
+++ b/tools/clang/translation_unit/test_files/binomial.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_BINOMIAL_H_
+#define TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_BINOMIAL_H_
+
+int binomial(int n, int k) {
+  return k > 0 ? binomial(n - 1, k - 1) * n / k : 1;
+}
+
+#endif  // TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_BINOMIAL_H_
diff --git a/tools/clang/translation_unit/test_files/test.cc b/tools/clang/translation_unit/test_files/test.cc
new file mode 100644
index 0000000..e735f55
--- /dev/null
+++ b/tools/clang/translation_unit/test_files/test.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test.h"
+
+#include "binomial.h"
+
+// Notice that "binomial.h" is included both here and in the "test.h" file.
+// The tool should however print the path to this header file only once.
+
+int main() {
+  // Just some nonesense calculations.
+  int result = calculateNumberOfWaysToDistributeNItemsAmongKPersons(10, 5);
+  return result + binomial(42, 1);
+}
diff --git a/tools/clang/translation_unit/test_files/test.cc.filepaths.expected b/tools/clang/translation_unit/test_files/test.cc.filepaths.expected
new file mode 100644
index 0000000..3dc4421
--- /dev/null
+++ b/tools/clang/translation_unit/test_files/test.cc.filepaths.expected
@@ -0,0 +1,3 @@
+./binomial.h
+./test.cc
+./test.h
diff --git a/tools/clang/translation_unit/test_files/test.h b/tools/clang/translation_unit/test_files/test.h
new file mode 100644
index 0000000..8cc20ce
--- /dev/null
+++ b/tools/clang/translation_unit/test_files/test.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_TEST_H_
+#define TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_TEST_H_
+
+#include "binomial.h"
+
+// Number of ways to distribute n items of the same thing to k persons; each
+// person should get at least one item.
+int calculateNumberOfWaysToDistributeNItemsAmongKPersons(int n, int k) {
+  return binomial(n - 1, k - 1);
+}
+
+#endif  // TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_TEST_H_
diff --git a/tools/clang/translation_unit/test_translation_unit.py b/tools/clang/translation_unit/test_translation_unit.py
new file mode 100755
index 0000000..eb5cce8
--- /dev/null
+++ b/tools/clang/translation_unit/test_translation_unit.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Test for TranslationUnitGenerator tool."""
+
+import difflib
+import glob
+import json
+import ntpath
+import os
+import os.path
+import subprocess
+import sys
+
+
+def _GenerateCompileCommands(files):
+  """Returns a JSON string containing a compilation database for the input."""
+  return json.dumps([{'directory': '.',
+                      'command': 'clang++ -fsyntax-only -std=c++11 -c %s' % f,
+                      'file': f} for f in files], indent=2)
+
+
+def _NumberOfTestsToString(tests):
+  """Returns an English sentence describing the number of tests."""
+  return "%d test%s" % (tests, 's' if tests != 1 else '')
+
+
+# Before running this test script, please build the translation_unit clang tool
+# first. This is explained here:
+# https://code.google.com/p/chromium/wiki/ClangToolRefactoring
+def main():
+  tools_clang_directory = os.path.dirname(os.path.dirname(
+      os.path.realpath(__file__)))
+  tools_clang_scripts_directory = os.path.join(tools_clang_directory, 'scripts')
+  test_directory_for_tool = os.path.join(
+      tools_clang_directory, 'translation_unit', 'test_files')
+  compile_database = os.path.join(test_directory_for_tool,
+                                  'compile_commands.json')
+  source_files = glob.glob(os.path.join(test_directory_for_tool, '*.cc'))
+
+  # Generate a temporary compilation database to run the tool over.
+  with open(compile_database, 'w') as f:
+    f.write(_GenerateCompileCommands(source_files))
+
+  args = ['python',
+          os.path.join(tools_clang_scripts_directory, 'run_tool.py'),
+          'translation_unit',
+          test_directory_for_tool]
+  args.extend(source_files)
+  run_tool = subprocess.Popen(args, stdout=subprocess.PIPE)
+  stdout, _ = run_tool.communicate()
+  if run_tool.returncode != 0:
+    print 'run_tool failed:\n%s' % stdout
+    sys.exit(1)
+
+  passed = 0
+  failed = 0
+  for actual in source_files:
+    actual += '.filepaths'
+    expected = actual + '.expected'
+    print '[ RUN      ] %s' % os.path.relpath(actual)
+    expected_output = actual_output = None
+    with open(expected, 'r') as f:
+      expected_output = f.readlines()
+    with open(actual, 'r') as f:
+      actual_output = f.readlines()
+    has_same_filepaths = True
+    for expected_line, actual_line in zip(expected_output, actual_output):
+      if ntpath.basename(expected_line) != ntpath.basename(actual_line):
+        sys.stdout.write(ntpath.basename(expected_line))
+        sys.stdout.write(ntpath.basename(actual_line))
+        has_same_filepaths = False
+        break
+    if not has_same_filepaths:
+      failed += 1
+      for line in difflib.unified_diff(expected_output, actual_output,
+                                       fromfile=os.path.relpath(expected),
+                                       tofile=os.path.relpath(actual)):
+        sys.stdout.write(line)
+      print '[  FAILED  ] %s' % os.path.relpath(actual)
+      # Don't clean up the file on failure, so the results can be referenced
+      # more easily.
+      continue
+    print '[       OK ] %s' % os.path.relpath(actual)
+    passed += 1
+    os.remove(actual)
+
+  if failed == 0:
+    os.remove(compile_database)
+
+  print '[==========] %s ran.' % _NumberOfTestsToString(len(source_files))
+  if passed > 0:
+    print '[  PASSED  ] %s.' % _NumberOfTestsToString(passed)
+  if failed > 0:
+    print '[  FAILED  ] %s.' % _NumberOfTestsToString(failed)
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py
index 8f5432f..677cb63 100755
--- a/tools/valgrind/chrome_tests.py
+++ b/tools/valgrind/chrome_tests.py
@@ -470,6 +470,9 @@
   def TestUIBaseUnit(self):
     return self.SimpleTest("chrome", "ui_base_unittests")
 
+  def TestUIChromeOS(self):
+    return self.SimpleTest("chrome", "ui_chromeos_unittests")
+
   def TestURL(self):
     return self.SimpleTest("chrome", "url_unittests")
 
@@ -712,6 +715,7 @@
     "sync_integration_tests": TestSyncIntegration,
     "sync_integration": TestSyncIntegration,
     "ui_base_unit": TestUIBaseUnit,       "ui_base_unittests": TestUIBaseUnit,
+    "ui_chromeos": TestUIChromeOS, "ui_chromeos_unittests": TestUIChromeOS,
     "unit": TestUnit,            "unit_tests": TestUnit,
     "url": TestURL,              "url_unittests": TestURL,
     "views": TestViews,          "views_unittests": TestViews,
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
index aa85c27..74a4ac5 100644
--- a/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
+++ b/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
@@ -27,3 +27,6 @@
 
 # Crashes under Valgrind, see http://crbug.com/355436
 OutOfMemoryHandledTest.Unchecked*
+
+# Fail under Valgrind, see http://crbug.com/431702
+ProcMapsTest.ReadProcMaps
diff --git a/tools/valgrind/gtest_exclude/components_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/components_unittests.gtest-drmemory_win32.txt
new file mode 100644
index 0000000..a8edd28
--- /dev/null
+++ b/tools/valgrind/gtest_exclude/components_unittests.gtest-drmemory_win32.txt
@@ -0,0 +1,3 @@
+# http://crbug.com/435320
+MetricsServiceTest.InitialStabilityLogAfterCrash
+MetricsServiceTest.InitialStabilityLogAtProviderRequest
diff --git a/tools/valgrind/gtest_exclude/content_unittests.gtest.txt b/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
index 3376b22..03eb062 100644
--- a/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
+++ b/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
@@ -10,3 +10,6 @@
 
 # http://crbug.com/430391
 WebDataConsumerHandleImplTest.*
+
+# http://crbug.com/435441
+PluginLoaderPosixTest.*
diff --git a/ui/base/x/x11_foreign_window_manager.h b/ui/base/x/x11_foreign_window_manager.h
index 2bf1937..354cfba 100644
--- a/ui/base/x/x11_foreign_window_manager.h
+++ b/ui/base/x/x11_foreign_window_manager.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/compiler_specific.h"
 #include "ui/base/ui_base_export.h"
 #include "ui/gfx/x/x11_types.h"
 
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 6bcb02a..e0b125a 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -114,7 +114,7 @@
   CommandLine* command_line = CommandLine::ForCurrentProcess();
 
   cc::LayerTreeSettings settings;
-  settings.refresh_rate =
+  settings.renderer_settings.refresh_rate =
       context_factory_->DoesCreateTestContexts()
       ? kTestRefreshRate
       : kDefaultRefreshRate;
@@ -122,7 +122,7 @@
   settings.throttle_frame_production =
       !command_line->HasSwitch(switches::kDisableGpuVsync);
 #if !defined(OS_MACOSX)
-  settings.partial_swap_enabled =
+  settings.renderer_settings.partial_swap_enabled =
       !command_line->HasSwitch(cc::switches::kUIDisablePartialSwap);
 #endif
 #if defined(OS_CHROMEOS)
@@ -253,10 +253,9 @@
   if (!IsLocked()) {
     // TODO(nduca): Temporary while compositor calls
     // compositeImmediately() directly.
-    cc::BeginFrameArgs args =
-        cc::BeginFrameArgs::Create(gfx::FrameTime::Now(),
-                                   base::TimeTicks(),
-                                   cc::BeginFrameArgs::DefaultInterval());
+    cc::BeginFrameArgs args = cc::BeginFrameArgs::Create(
+        gfx::FrameTime::Now(), base::TimeTicks(),
+        cc::BeginFrameArgs::DefaultInterval(), cc::BeginFrameArgs::SYNCHRONOUS);
     BeginMainFrame(args);
     host_->Composite(args.frame_time);
   }
diff --git a/ui/compositor/layer_tree_owner.h b/ui/compositor/layer_tree_owner.h
index 8b75355..0b2c478 100644
--- a/ui/compositor/layer_tree_owner.h
+++ b/ui/compositor/layer_tree_owner.h
@@ -6,6 +6,7 @@
 #define UI_COMPOSITOR_LAYER_TREE_OWNER_H_
 
 #include "base/basictypes.h"
+#include "base/compiler_specific.h"
 #include "ui/compositor/compositor_export.h"
 
 namespace ui {
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index da668ec..6fff4cb 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -39,18 +39,32 @@
   'names': ['glAttachShader'],
   'arguments': 'GLuint program, GLuint shader', },
 { 'return_type': 'void',
-  'names': ['glBeginQuery'],
+  'versions': [{ 'name': 'glBeginQuery',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
   'arguments': 'GLenum target, GLuint id', },
 { 'return_type': 'void',
   'names': ['glBeginQueryARB', 'glBeginQueryEXT'],
   'arguments': 'GLenum target, GLuint id', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glBeginTransformFeedback',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum primitiveMode', },
+{ 'return_type': 'void',
   'names': ['glBindAttribLocation'],
   'arguments': 'GLuint program, GLuint index, const char* name', },
 { 'return_type': 'void',
   'names': ['glBindBuffer'],
   'arguments': 'GLenum target, GLuint buffer', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glBindBufferBase',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum target, GLuint index, GLuint buffer', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glBindBufferRange',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum target, GLuint index, GLuint buffer, GLintptr offset, '
+               'GLsizeiptr size', },
+{ 'return_type': 'void',
   'names': ['glBindFragDataLocation'],
   'arguments': 'GLuint program, GLuint colorNumber, const char* name', },
 { 'return_type': 'void',
@@ -64,9 +78,17 @@
   'names': ['glBindRenderbufferEXT', 'glBindRenderbuffer'],
   'arguments': 'GLenum target, GLuint renderbuffer', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glBindSampler',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLuint unit, GLuint sampler', },
+{ 'return_type': 'void',
   'names': ['glBindTexture'],
   'arguments': 'GLenum target, GLuint texture', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glBindTransformFeedback',
+                 'gl_versions': ['gl4', 'es3'] }],
+  'arguments': 'GLenum target, GLuint id', },
+{ 'return_type': 'void',
   'known_as': 'glBindVertexArrayOES',
   'versions': [{ 'name': 'glBindVertexArray',
                  'gl_versions': ['gl3', 'gl4', 'es3'] },
@@ -133,6 +155,23 @@
   'names': ['glClear'],
   'arguments': 'GLbitfield mask', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glClearBufferfi',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum buffer, GLint drawbuffer, const GLfloat depth, '
+               'GLint stencil', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glClearBufferfv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum buffer, GLint drawbuffer, const GLfloat* value', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glClearBufferiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum buffer, GLint drawbuffer, const GLint* value', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glClearBufferuiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum buffer, GLint drawbuffer, const GLuint* value', },
+{ 'return_type': 'void',
   'names': ['glClearColor'],
   'arguments': 'GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha', },
 { 'return_type': 'void',
@@ -160,11 +199,32 @@
       'GLenum target, GLint level, GLenum internalformat, GLsizei width, '
       'GLsizei height, GLint border, GLsizei imageSize, const void* data', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glCompressedTexImage3D',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments':
+      'GLenum target, GLint level, GLenum internalformat, GLsizei width, '
+      'GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, '
+      'const void* data', },
+{ 'return_type': 'void',
   'names': ['glCompressedTexSubImage2D'],
   'arguments':
-     'GLenum target, GLint level, GLint xoffset, GLint yoffset, '
-     'GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, '
-     'const void* data', },
+      'GLenum target, GLint level, GLint xoffset, GLint yoffset, '
+      'GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, '
+      'const void* data', },
+# TODO(zmo): wait for MOCK_METHOD11.
+# { 'return_type': 'void',
+#   'versions': [{ 'name': 'glCompressedTexSubImage3D',
+#                  'gl_versions': ['gl3', 'gl4', 'es3'] }],
+#   'arguments':
+#       'GLenum target, GLint level, GLint xoffset, GLint yoffset, '
+#       'GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, '
+#       'GLenum format, GLsizei imageSize, const void* data', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glCopyBufferSubData',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.1 or higher.
+  'arguments':
+      'GLenum readTarget, GLenum writeTarget, GLintptr readOffset, '
+      'GLintptr writeOffset, GLsizeiptr size', },
 { 'return_type': 'void',
   'names': ['glCopyTexImage2D'],
   'arguments':
@@ -175,6 +235,12 @@
   'arguments':
       'GLenum target, GLint level, GLint xoffset, '
       'GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glCopyTexSubImage3D',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments':
+      'GLenum target, GLint level, GLint xoffset, GLint yoffset, '
+      'GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height', },
 { 'return_type': 'GLuint',
   'names': ['glCreateProgram'],
   'arguments': 'void', },
@@ -202,7 +268,8 @@
   'names': ['glDeleteProgram'],
   'arguments': 'GLuint program', },
 { 'return_type': 'void',
-  'names': ['glDeleteQueries'],
+  'versions': [{ 'name': 'glDeleteQueries',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
   'arguments': 'GLsizei n, const GLuint* ids', },
 { 'return_type': 'void',
   'names': ['glDeleteQueriesARB', 'glDeleteQueriesEXT'],
@@ -211,6 +278,10 @@
   'names': ['glDeleteRenderbuffersEXT', 'glDeleteRenderbuffers'],
   'arguments': 'GLsizei n, const GLuint* renderbuffers', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glDeleteSamplers',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLsizei n, const GLuint* samplers', },
+{ 'return_type': 'void',
   'names': ['glDeleteShader'],
   'arguments': 'GLuint shader', },
 { 'return_type': 'void',
@@ -220,6 +291,10 @@
   'names': ['glDeleteTextures'],
   'arguments': 'GLsizei n, const GLuint* textures', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glDeleteTransformFeedbacks',
+                 'gl_versions': ['gl4', 'es3'] }],
+  'arguments': 'GLsizei n, const GLuint* ids', },
+{ 'return_type': 'void',
   'known_as': 'glDeleteVertexArraysOES',
   'versions': [{ 'name': 'glDeleteVertexArrays',
                  'gl_versions': ['gl3', 'gl4', 'es3'] },
@@ -285,6 +360,11 @@
       'GLenum mode, GLsizei count, GLenum type, const void* indices, '
       'GLsizei primcount', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glDrawRangeElements',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum mode, GLuint start, GLuint end, GLsizei count, '
+               'GLenum type, const void* indices', },
+{ 'return_type': 'void',
   'names': ['glEGLImageTargetRenderbufferStorageOES'],
   'arguments': 'GLenum target, GLeglImageOES image', },
 { 'return_type': 'void',
@@ -297,11 +377,16 @@
   'names': ['glEnableVertexAttribArray'],
   'arguments': 'GLuint index', },
 { 'return_type': 'void',
-  'names': ['glEndQuery'],
+  'versions': [{ 'name': 'glEndQuery',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
   'arguments': 'GLenum target', },
 { 'return_type': 'void',
   'names': ['glEndQueryARB', 'glEndQueryEXT'],
   'arguments': 'GLenum target', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glEndTransformFeedback',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'void', },
 { 'return_type': 'GLsync',
   'names': ['glFenceSync'],
   'arguments': 'GLenum condition, GLbitfield flags', },
@@ -343,6 +428,11 @@
       'GLenum target, GLenum attachment, GLenum textarget, GLuint texture, '
       'GLint level, GLsizei samples', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glFramebufferTextureLayer',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum target, GLenum attachment, GLuint texture, GLint level, '
+               'GLint layer', },
+{ 'return_type': 'void',
   'names': ['glFrontFace'],
   'arguments': 'GLenum mode', },
 { 'return_type': 'void',
@@ -363,7 +453,8 @@
   'names': ['glGenFramebuffersEXT', 'glGenFramebuffers'],
   'arguments': 'GLsizei n, GLuint* framebuffers', },
 { 'return_type': 'void',
-  'names': ['glGenQueries'],
+  'versions': [{ 'name': 'glGenQueries',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
   'arguments': 'GLsizei n, GLuint* ids', },
 { 'return_type': 'void',
   'names': ['glGenQueriesARB', 'glGenQueriesEXT'],
@@ -372,9 +463,17 @@
   'names': ['glGenRenderbuffersEXT', 'glGenRenderbuffers'],
   'arguments': 'GLsizei n, GLuint* renderbuffers', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glGenSamplers',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLsizei n, GLuint* samplers', },
+{ 'return_type': 'void',
   'names': ['glGenTextures'],
   'arguments': 'GLsizei n, GLuint* textures', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glGenTransformFeedbacks',
+                 'gl_versions': ['gl4', 'es3'] }],
+  'arguments': 'GLsizei n, GLuint* ids', },
+{ 'return_type': 'void',
   'known_as': 'glGenVertexArraysOES',
   'versions': [{ 'name': 'glGenVertexArrays',
                  'gl_versions': ['gl3', 'gl4', 'es3'] },
@@ -395,6 +494,21 @@
       'GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, '
       'GLint* size, GLenum* type, char* name', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glGetActiveUniformBlockiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.1 or higher.
+  'arguments': 'GLuint program, GLuint uniformBlockIndex, GLenum pname, '
+               'GLint* params', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glGetActiveUniformBlockName',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.1 or higher.
+  'arguments': 'GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, '
+               'GLsizei* length, char* uniformBlockName', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glGetActiveUniformsiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.1 or higher.
+  'arguments': 'GLuint program, GLsizei uniformCount, '
+               'const GLuint* uniformIndices, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
   'names': ['glGetAttachedShaders'],
   'arguments':
       'GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders', },
@@ -419,6 +533,10 @@
 { 'return_type': 'void',
   'names': ['glGetFloatv'],
   'arguments': 'GLenum pname, GLfloat* params', },
+{ 'return_type': 'GLint',
+  'versions': [{ 'name': 'glGetFragDataLocation',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint program, const char* name', },
 { 'return_type': 'void',
   'names': ['glGetFramebufferAttachmentParameterivEXT',
             'glGetFramebufferAttachmentParameteriv'],
@@ -431,12 +549,25 @@
             'glGetGraphicsResetStatus'],
   'arguments': 'void', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glGetInteger64i_v',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLenum target, GLuint index, GLint64* data', },
+{ 'return_type': 'void',
   'names': ['glGetInteger64v'],
   'arguments': 'GLenum pname, GLint64* params', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glGetIntegeri_v',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLenum target, GLuint index, GLint* data', },
+{ 'return_type': 'void',
   'names': ['glGetIntegerv'],
   'arguments': 'GLenum pname, GLint* params', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glGetInternalformativ',
+                 'gl_versions': ['gl4', 'es3'] }],  # GL 4.2 or higher.
+  'arguments': 'GLenum target, GLenum internalformat, GLenum pname, '
+               'GLsizei bufSize, GLint* params', },
+{ 'return_type': 'void',
   'known_as': 'glGetProgramBinary',
   'versions': [{ 'name': 'glGetProgramBinaryOES' },
                { 'name': 'glGetProgramBinary',
@@ -452,7 +583,8 @@
   'names': ['glGetProgramiv'],
   'arguments': 'GLuint program, GLenum pname, GLint* params', },
 { 'return_type': 'void',
-  'names': ['glGetQueryiv'],
+  'versions': [{ 'name': 'glGetQueryiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
   'arguments': 'GLenum target, GLenum pname, GLint* params', },
 { 'return_type': 'void',
   'names': ['glGetQueryivARB', 'glGetQueryivEXT'],
@@ -461,14 +593,18 @@
   'names': ['glGetQueryObjecti64v'],
   'arguments': 'GLuint id, GLenum pname, GLint64* params', },
 { 'return_type': 'void',
-  'names': ['glGetQueryObjectiv', 'glGetQueryObjectivARB',
-            'glGetQueryObjectivEXT'],
+  'versions': [{ 'name': 'glGetQueryObjectiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint id, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+  'names': ['glGetQueryObjectivARB', 'glGetQueryObjectivEXT'],
   'arguments': 'GLuint id, GLenum pname, GLint* params', },
 { 'return_type': 'void',
   'names': ['glGetQueryObjectui64v', 'glGetQueryObjectui64vEXT'],
   'arguments': 'GLuint id, GLenum pname, GLuint64* params', },
 { 'return_type': 'void',
-  'names': ['glGetQueryObjectuiv'],
+  'versions': [{ 'name': 'glGetQueryObjectuiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
   'arguments': 'GLuint id, GLenum pname, GLuint* params', },
 { 'return_type': 'void',
   'names': ['glGetQueryObjectuivARB', 'glGetQueryObjectuivEXT'],
@@ -477,6 +613,14 @@
   'names': ['glGetRenderbufferParameterivEXT', 'glGetRenderbufferParameteriv'],
   'arguments': 'GLenum target, GLenum pname, GLint* params', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glGetSamplerParameterfv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLuint sampler, GLenum pname, GLfloat* params', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glGetSamplerParameteriv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLuint sampler, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
   'names': ['glGetShaderInfoLog'],
   'arguments':
       'GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog', },
@@ -512,13 +656,27 @@
   'names': ['glGetTexParameteriv'],
   'arguments': 'GLenum target, GLenum pname, GLint* params', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glGetTransformFeedbackVarying',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint program, GLuint index, GLsizei bufSize, '
+               'GLsizei* length, GLenum* type, char* name', },
+{ 'return_type': 'void',
   'names': ['glGetTranslatedShaderSourceANGLE'],
   'arguments':
       'GLuint shader, GLsizei bufsize, GLsizei* length, char* source', },
+{ 'return_type': 'GLuint',
+  'versions': [{ 'name': 'glGetUniformBlockIndex',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.1 or higher.
+  'arguments': 'GLuint program, const char* uniformBlockName', },
 { 'return_type': 'void',
   'names': ['glGetUniformfv'],
   'arguments': 'GLuint program, GLint location, GLfloat* params', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glGetUniformIndices',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.1 or higher.
+  'arguments': 'GLuint program, GLsizei uniformCount, '
+               'const char* const* uniformNames, GLuint* uniformIndices', },
+{ 'return_type': 'void',
   'names': ['glGetUniformiv'],
   'arguments': 'GLuint program, GLint location, GLint* params', },
 { 'return_type': 'GLint',
@@ -539,6 +697,12 @@
 { 'return_type': 'void',
   'names': ['glInsertEventMarkerEXT'],
   'arguments': 'GLsizei length, const char* marker', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glInvalidateSubFramebuffer',
+                 'gl_versions': ['gl4', 'es3'] }],  # GL 4.3 or higher.
+  'arguments':
+      'GLenum target, GLsizei numAttachments, const GLenum* attachments, '
+      'GLint x, GLint y, GLint width, GLint height', },
 { 'return_type': 'GLboolean',
   'names': ['glIsBuffer'],
   'arguments': 'GLuint buffer', },
@@ -560,12 +724,20 @@
   'names': ['glIsProgram'],
   'arguments': 'GLuint program', },
 { 'return_type': 'GLboolean',
+  'versions': [{ 'name': 'glIsQuery',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint query', },
+{ 'return_type': 'GLboolean',
   'names': ['glIsQueryARB', 'glIsQueryEXT'],
   'arguments': 'GLuint query', },
 { 'return_type': 'GLboolean',
   'names': ['glIsRenderbufferEXT', 'glIsRenderbuffer'],
   'arguments': 'GLuint renderbuffer', },
 { 'return_type': 'GLboolean',
+  'versions': [{ 'name': 'glIsSampler',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLuint sampler', },
+{ 'return_type': 'GLboolean',
   'names': ['glIsShader'],
   'arguments': 'GLuint shader', },
 { 'return_type': 'GLboolean',
@@ -575,9 +747,13 @@
   'names': ['glIsTexture'],
   'arguments': 'GLuint texture', },
 { 'return_type': 'GLboolean',
+  'versions': [{ 'name': 'glIsTransformFeedback',
+                 'gl_versions': ['gl4', 'es3'] }],
+  'arguments': 'GLuint id', },
+{ 'return_type': 'GLboolean',
   'known_as': 'glIsVertexArrayOES',
   'versions': [{ 'name': 'glIsVertexArray',
-                 'gl_versions': ['gl3', 'gl4'] },
+                 'gl_versions': ['gl3', 'gl4', 'es3'] },
                { 'name': 'glIsVertexArray',
                  'extensions': ['GL_ARB_vertex_array_object'] },
                { 'name': 'glIsVertexArrayOES' },
@@ -623,6 +799,10 @@
                  'extensions': ['GL_NV_path_rendering'] }],
   'arguments': 'GLenum matrixMode' },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glPauseTransformFeedback',
+                 'gl_versions': ['gl4', 'es3'] }],
+  'arguments': 'void', },
+{ 'return_type': 'void',
   'names': ['glPixelStorei'],
   'arguments': 'GLenum pname, GLint param', },
 { 'return_type': 'void',
@@ -704,9 +884,29 @@
   'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
                'GLsizei width, GLsizei height', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glResumeTransformFeedback',
+                 'gl_versions': ['gl4', 'es3'] }],
+  'arguments': 'void', },
+{ 'return_type': 'void',
   'names': ['glSampleCoverage'],
   'arguments': 'GLclampf value, GLboolean invert', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glSamplerParameterf',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLuint sampler, GLenum pname, GLfloat param', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glSamplerParameterfv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLuint sampler, GLenum pname, const GLfloat* params', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glSamplerParameteri',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLuint sampler, GLenum pname, GLint param', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glSamplerParameteriv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.2 or higher.
+  'arguments': 'GLuint sampler, GLenum pname, const GLint* params', },
+{ 'return_type': 'void',
   'names': ['glScissor'],
   'arguments': 'GLint x, GLint y, GLsizei width, GLsizei height', },
 { 'return_type': 'void',
@@ -774,6 +974,13 @@
       'GLsizei height, GLint border, GLenum format, GLenum type, '
       'const void* pixels', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glTexImage3D',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments':
+      'GLenum target, GLint level, GLint internalformat, GLsizei width, '
+      'GLsizei height, GLsizei depth, GLint border, GLenum format, '
+      'GLenum type, const void* pixels', },
+{ 'return_type': 'void',
   'names': ['glTexParameterf'],
   'arguments': 'GLenum target, GLenum pname, GLfloat param', },
 { 'return_type': 'void',
@@ -796,11 +1003,29 @@
   'arguments': 'GLenum target, GLsizei levels, GLenum internalformat, '
                'GLsizei width, GLsizei height', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glTexStorage3D',
+                 'gl_versions': ['gl4', 'es3'] }],  # GL 4.2 or higher.
+  'arguments': 'GLenum target, GLsizei levels, GLenum internalformat, '
+               'GLsizei width, GLsizei height, GLsizei depth', },
+{ 'return_type': 'void',
   'names': ['glTexSubImage2D'],
   'arguments':
      'GLenum target, GLint level, GLint xoffset, GLint yoffset, '
      'GLsizei width, GLsizei height, GLenum format, GLenum type, '
      'const void* pixels', },
+# TODO(zmo): wait for MOCK_METHOD11.
+# { 'return_type': 'void',
+#   'versions': [{ 'name': 'glTexSubImage3D',
+#                  'gl_versions': ['gl3', 'gl4', 'es3'] }],
+#   'arguments':
+#       'GLenum target, GLint level, GLint xoffset, GLint yoffset, '
+#       'GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, '
+#       'GLenum format, GLenum type, const void* pixels', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glTransformFeedbackVaryings',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint program, GLsizei count, const char* const* varyings, '
+               'GLenum bufferMode', },
 { 'return_type': 'void',
   'names': ['glUniform1f'],
   'arguments': 'GLint location, GLfloat x', },
@@ -814,6 +1039,14 @@
   'names': ['glUniform1iv'],
   'arguments': 'GLint location, GLsizei count, const GLint* v', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glUniform1ui',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLuint v0', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glUniform1uiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, const GLuint* v', },
+{ 'return_type': 'void',
   'names': ['glUniform2f'],
   'arguments': 'GLint location, GLfloat x, GLfloat y', },
 { 'return_type': 'void',
@@ -826,6 +1059,14 @@
   'names': ['glUniform2iv'],
   'arguments': 'GLint location, GLsizei count, const GLint* v', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glUniform2ui',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLuint v0, GLuint v1', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glUniform2uiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, const GLuint* v', },
+{ 'return_type': 'void',
   'names': ['glUniform3f'],
   'arguments': 'GLint location, GLfloat x, GLfloat y, GLfloat z', },
 { 'return_type': 'void',
@@ -838,6 +1079,14 @@
   'names': ['glUniform3iv'],
   'arguments': 'GLint location, GLsizei count, const GLint* v', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glUniform3ui',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLuint v0, GLuint v1, GLuint v2', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glUniform3uiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, const GLuint* v', },
+{ 'return_type': 'void',
   'names': ['glUniform4f'],
   'arguments': 'GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w', },
 { 'return_type': 'void',
@@ -850,17 +1099,60 @@
   'names': ['glUniform4iv'],
   'arguments': 'GLint location, GLsizei count, const GLint* v', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glUniform4ui',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glUniform4uiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, const GLuint* v', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glUniformBlockBinding',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],  # GL 3.1 or higher.
+  'arguments': 'GLuint program, GLuint uniformBlockIndex, '
+               'GLuint uniformBlockBinding', },
+{ 'return_type': 'void',
   'names': ['glUniformMatrix2fv'],
   'arguments': 'GLint location, GLsizei count, '
                'GLboolean transpose, const GLfloat* value', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glUniformMatrix2x3fv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glUniformMatrix2x4fv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value', },
+{ 'return_type': 'void',
   'names': ['glUniformMatrix3fv'],
   'arguments': 'GLint location, GLsizei count, '
                'GLboolean transpose, const GLfloat* value', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glUniformMatrix3x2fv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glUniformMatrix3x4fv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value', },
+{ 'return_type': 'void',
   'names': ['glUniformMatrix4fv'],
   'arguments': 'GLint location, GLsizei count, '
                'GLboolean transpose, const GLfloat* value', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glUniformMatrix4x2fv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glUniformMatrix4x3fv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value', },
 { 'return_type': 'GLboolean',
   'known_as': 'glUnmapBuffer',
   'names': ['glUnmapBufferOES', 'glUnmapBuffer'],
@@ -902,6 +1194,27 @@
   'arguments':
       'GLuint index, GLuint divisor', },
 { 'return_type': 'void',
+  'versions': [{ 'name': 'glVertexAttribI4i',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint indx, GLint x, GLint y, GLint z, GLint w', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glVertexAttribI4iv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint indx, const GLint* values', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glVertexAttribI4ui',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint indx, GLuint x, GLuint y, GLuint z, GLuint w', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glVertexAttribI4uiv',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint indx, const GLuint* values', },
+{ 'return_type': 'void',
+  'versions': [{ 'name': 'glVertexAttribIPointer',
+                 'gl_versions': ['gl3', 'gl4', 'es3'] }],
+  'arguments': 'GLuint indx, GLint size, GLenum type, GLsizei stride, '
+               'const void* ptr', },
+{ 'return_type': 'void',
   'names': ['glVertexAttribPointer'],
   'arguments': 'GLuint indx, GLint size, GLenum type, GLboolean normalized, '
                'GLsizei stride, const void* ptr', },
diff --git a/ui/gl/gl_bindings.h b/ui/gl/gl_bindings.h
index aea47fc..595a31f 100644
--- a/ui/gl/gl_bindings.h
+++ b/ui/gl/gl_bindings.h
@@ -116,17 +116,17 @@
 #define GL_QUERY_RESULT_AVAILABLE_EXT                    0x8867
 
 // GL_CHROMIUM_command_buffer_query
-#define GL_COMMANDS_ISSUED_CHROMIUM                      0x84F2
+#define GL_COMMANDS_ISSUED_CHROMIUM                      0x6004
 
 /* GL_CHROMIUM_get_error_query */
-#define GL_GET_ERROR_QUERY_CHROMIUM                      0x84F3
+#define GL_GET_ERROR_QUERY_CHROMIUM                      0x6003
 
 /* GL_CHROMIUM_command_buffer_latency_query */
-#define GL_LATENCY_QUERY_CHROMIUM                        0x84F4
+#define GL_LATENCY_QUERY_CHROMIUM                        0x6007
 
 /* GL_CHROMIUM_async_pixel_transfers */
-#define GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM         0x84F5
-#define GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM           0x84F6
+#define GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM         0x6005
+#define GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM           0x6006
 
 // GL_CHROMIUM_sync_query
 #define GL_COMMANDS_COMPLETED_CHROMIUM                   0x84F7
diff --git a/ui/gl/gl_image_memory.cc b/ui/gl/gl_image_memory.cc
index a752940..0a67e00 100644
--- a/ui/gl/gl_image_memory.cc
+++ b/ui/gl/gl_image_memory.cc
@@ -179,15 +179,11 @@
     return false;
 
   DCHECK(memory_);
-  glTexImage2D(target,
-               0,  // mip level
-               TextureFormat(format_),
-               size_.width(),
-               size_.height(),
-               0,  // border
-               DataFormat(format_),
-               DataType(format_),
-               memory_);
+  glTexSubImage2D(target, 0,  // level
+                  0,          // x
+                  0,          // y
+                  size_.width(), size_.height(), DataFormat(format_),
+                  DataType(format_), memory_);
 
   return true;
 }
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc
index 4459d48..00e224d 100644
--- a/ui/gl/gl_surface.cc
+++ b/ui/gl/gl_surface.cc
@@ -166,6 +166,10 @@
   return true;
 }
 
+void GLSurface::DestroyAndTerminateDisplay() {
+  Destroy();
+}
+
 bool GLSurface::Resize(const gfx::Size& size) {
   NOTIMPLEMENTED();
   return false;
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h
index d458063..1351638 100644
--- a/ui/gl/gl_surface.h
+++ b/ui/gl/gl_surface.h
@@ -38,6 +38,10 @@
   // Destroys the surface.
   virtual void Destroy() = 0;
 
+  // Destroys the surface and terminates its underlying display. This must be
+  // the last surface which uses the display.
+  virtual void DestroyAndTerminateDisplay();
+
   virtual bool Resize(const gfx::Size& size);
 
   // Recreate the surface without changing the size.
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 19119a9..3a453b6 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -61,7 +61,16 @@
 
 EGLConfig g_config;
 EGLDisplay g_display;
-EGLNativeDisplayType g_native_display;
+EGLNativeDisplayType g_native_display_type;
+
+// In the Cast environment, we need to destroy the EGLNativeDisplayType and
+// EGLDisplay returned by the GPU platform when we switch to an external app
+// which will temporarily own all screen and GPU resources.
+// Even though Chromium is still in the background.
+// As such, it must be reinitialized each time we come back to the foreground.
+bool g_initialized = false;
+int g_num_surfaces = 0;
+bool g_terminate_pending = false;
 
 const char* g_egl_extensions = NULL;
 bool g_egl_create_context_robustness_supported = false;
@@ -105,21 +114,34 @@
   DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider);
 };
 
+void DeinitializeEgl() {
+  if (g_initialized) {
+    g_initialized = false;
+    eglTerminate(g_display);
+  }
+}
+
 }  // namespace
 
-GLSurfaceEGL::GLSurfaceEGL() {}
+GLSurfaceEGL::GLSurfaceEGL() {
+  ++g_num_surfaces;
+  if (!g_initialized) {
+    bool result = GLSurfaceEGL::InitializeOneOff();
+    DCHECK(result);
+    DCHECK(g_initialized);
+  }
+}
 
 bool GLSurfaceEGL::InitializeOneOff() {
-  static bool initialized = false;
-  if (initialized)
+  if (g_initialized)
     return true;
 
-  g_native_display = GetPlatformDefaultEGLNativeDisplay();
+  g_native_display_type = GetPlatformDefaultEGLNativeDisplay();
 
 #if defined(OS_WIN)
-  g_display = GetPlatformDisplay(g_native_display);
+  g_display = GetPlatformDisplay(g_native_display_type);
 #else
-  g_display = eglGetDisplay(g_native_display);
+  g_display = eglGetDisplay(g_native_display_type);
 #endif
 
   if (!g_display) {
@@ -187,6 +209,12 @@
   g_egl_window_fixed_size_supported =
       HasEGLExtension("EGL_ANGLE_window_fixed_size");
 
+  // We always succeed beyond this point so set g_initialized here to avoid
+  // infinite recursion through CreateGLContext and GetDisplay
+  // if g_egl_surfaceless_context_supported.
+  g_initialized = true;
+  g_terminate_pending = false;
+
   // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary
   // workaround, since code written for Android WebView takes different paths
   // based on whether GL surface objects have underlying EGL surface handles,
@@ -216,24 +244,35 @@
   }
 #endif
 
-  initialized = true;
-
   return true;
 }
 
 EGLDisplay GLSurfaceEGL::GetDisplay() {
+  DCHECK(g_initialized);
   return g_display;
 }
 
+// static
 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() {
+  if (!g_initialized) {
+    bool result = GLSurfaceEGL::InitializeOneOff();
+    DCHECK(result);
+  }
   return g_display;
 }
 
+// static
 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() {
-  return g_native_display;
+  if (!g_initialized) {
+    bool result = GLSurfaceEGL::InitializeOneOff();
+    DCHECK(result);
+  }
+  return g_native_display_type;
 }
 
 const char* GLSurfaceEGL::GetEGLExtensions() {
+  // No need for InitializeOneOff. Assume that extensions will not change
+  // after the first initialization.
   return g_egl_extensions;
 }
 
@@ -249,7 +288,20 @@
   return g_egl_surfaceless_context_supported;
 }
 
-GLSurfaceEGL::~GLSurfaceEGL() {}
+void GLSurfaceEGL::DestroyAndTerminateDisplay() {
+  DCHECK(g_initialized);
+  DCHECK_EQ(g_num_surfaces, 1);
+  Destroy();
+  g_terminate_pending = true;
+}
+
+GLSurfaceEGL::~GLSurfaceEGL() {
+  DCHECK_GT(g_num_surfaces, 0) << "Bad surface count";
+  if (--g_num_surfaces == 0 && g_terminate_pending) {
+    DeinitializeEgl();
+    g_terminate_pending = false;
+  }
+}
 
 #if defined(OS_WIN)
 static const EGLint kDisplayAttribsWarp[] {
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h
index 952ccad..720c7dd 100644
--- a/ui/gl/gl_surface_egl.h
+++ b/ui/gl/gl_surface_egl.h
@@ -29,6 +29,7 @@
   GLSurfaceEGL();
 
   // Implement GLSurface.
+  void DestroyAndTerminateDisplay() override;
   EGLDisplay GetDisplay() override;
 
   static bool InitializeOneOff();