diff --git a/.gitignore b/.gitignore
index b1e7c27..974e4c8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
 *.orig
 *.props
 *.pyc
+*.pyproj
 *.rules
 *.sdf
 *.sln
@@ -50,6 +51,7 @@
 # Settings directories for eclipse
 /.externalToolBuilders/
 /.settings/
+/.vs/
 /_out
 /android_emulator_sdk
 /ash/ash_unittests_run.xml
diff --git a/AUTHORS b/AUTHORS
index 28d2719..83ba47a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -295,6 +295,7 @@
 Joshua Roesslein <jroesslein@gmail.com>
 Josué Ratelle <jorat1346@gmail.com>
 Juhui Lee <juhui24.lee@samsung.com>
+Julien Brianceau <jbriance@cisco.com>
 Julien Racle <jracle@logitech.com>
 Jun Jiang <jun.a.jiang@intel.com>
 Junchao Han <junchao.han@intel.com>
diff --git a/DEPS b/DEPS
index 75bddad..fead1ce 100644
--- a/DEPS
+++ b/DEPS
@@ -39,11 +39,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'a7627dc5cc2bf5d9a95d883d20c40d477ecadadf',
+  'skia_revision': 'd75ccc6a0a2eb166234d919ffd3f62ed39dd3a6e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'e6b4ab5c3268efc45d13e06b7758670934f93fc5',
+  'v8_revision': '23533853f416feadfc1b39db7501837d4bf5f7fa',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -71,7 +71,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nss
   # and whatever else without interference from each other.
-  'nss_revision': 'aab0d08a298b29407397fbb1c4219f99e99431ed', # from svn revision 295435
+  'nss_revision': 'a676aa04ff18b30983cac03dede5861b3db62c9d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -226,7 +226,7 @@
     Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + 'f572e8e42e22cfcf5ab0aea26574f408943edfa4', # from svn 248
 
   'src/third_party/libyuv':
-    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'c2bff1a1af3933c866673c8184e635495d648739', # from version 1531
+    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '98eb102bead73b6fd16a11c0fa7bdc85be69246f', # from version 1533
 
   'src/third_party/smhasher/src':
     Var('chromium_git') + '/external/smhasher.git' + '@' + 'e87738e57558e0ec472b2fc3a643b838e5b6e88f',
diff --git a/android_webview/android_webview_shell.gyp b/android_webview/android_webview_shell.gyp
index 89b7785..c9bf96ef 100644
--- a/android_webview/android_webview_shell.gyp
+++ b/android_webview/android_webview_shell.gyp
@@ -63,7 +63,7 @@
         'java_in_dir': '../android_webview/tools/WebViewShellTest',
         'is_test_apk': 1,
         'test_type': 'instrumentation',
-        'isolate_file': 'android_webview_shell_test_apk.isolate',
+        'isolate_file': 'system_webview_shell_test_apk.isolate',
         'android_manifest_path': '../android_webview/tools/WebViewShellTest/AndroidManifest.xml',
       },
       'includes': [
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
index fdc1f68..79cc1d06 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
@@ -16,6 +16,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content_public.browser.GestureStateListener;
 import org.chromium.net.test.util.TestWebServer;
@@ -32,6 +33,8 @@
  * Integration tests for synchronous scrolling.
  */
 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
+// Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+@ParameterizedTest.Set
 public class AndroidScrollIntegrationTest extends AwTestBase {
     private TestWebServer mWebServer;
 
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
index 2c3bc37..aab4b6e 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
@@ -16,6 +16,7 @@
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.android_webview.test.util.GraphicsTestUtils;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.ui.gfx.DeviceDisplayInfo;
 
@@ -303,6 +304,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testViewIsNotBlankInWrapContentsMode() throws Throwable {
         final TestAwContentsClient contentsClient = new TestAwContentsClient();
         final AwTestContainerView testContainerView =
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
index 302ccba..77e6322 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
@@ -12,6 +12,7 @@
 import org.chromium.android_webview.test.util.JavascriptEventObserver;
 import org.chromium.android_webview.test.util.VideoSurfaceViewUtils;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
@@ -30,6 +31,8 @@
  * we pick a div containing a video and custom html controls since this is a
  * very common use case.
  */
+// Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+@ParameterizedTest.Set
 public class AwContentsClientFullScreenTest extends AwTestBase {
     private static final String VIDEO_TEST_URL =
             "file:///android_asset/full_screen_video_test.html";
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientGetVideoLoadingProgressViewTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientGetVideoLoadingProgressViewTest.java
index 6275682..68e10d63 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientGetVideoLoadingProgressViewTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientGetVideoLoadingProgressViewTest.java
@@ -9,6 +9,7 @@
 
 import org.chromium.android_webview.AwContents;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
 
@@ -25,6 +26,8 @@
  * used to trigger switch occupies almost the whole WebView so the simulated click event
  * can't miss it.
  */
+// Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+@ParameterizedTest.Set
 public class AwContentsClientGetVideoLoadingProgressViewTest extends AwTestBase
         implements View.OnAttachStateChangeListener {
     private static final String VIDEO_TEST_URL =
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java
index 338216a1..c8a779d3 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java
@@ -9,12 +9,15 @@
 import org.chromium.android_webview.AwContents;
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 
 /**
  * Tests for the WebViewClient.onScaleChanged.
  */
+// Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+@ParameterizedTest.Set
 public class AwContentsClientOnScaleChangedTest extends AwTestBase {
     private TestAwContentsClient mContentsClient;
     private AwContents mAwContents;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java
index 7a3c609..6611529 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java
@@ -14,6 +14,7 @@
 import org.chromium.android_webview.test.util.JSUtils;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.TestFileUtil;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
 import org.chromium.net.test.util.TestWebServer;
@@ -223,6 +224,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testCalledWithCorrectHasUserGestureParam() throws Throwable {
         final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
         final String pageWithLinkUrl = addPageToTestServer(mWebServer, "/page_with_link.html",
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java
index 9e1e6ed..4329707f 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java
@@ -14,6 +14,7 @@
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper;
@@ -726,6 +727,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Navigation"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testCalledOn302Redirect() throws Throwable {
         final String redirectTargetUrl = createRedirectTargetPage();
         final String redirectUrl = mWebServer.setRedirect("/302.html", redirectTargetUrl);
@@ -734,6 +737,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Navigation"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testCalledOnMetaRefreshRedirect() throws Throwable {
         final String redirectTargetUrl = createRedirectTargetPage();
         final String redirectUrl = addPageToTestServer("/meta_refresh.html",
@@ -744,6 +749,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Navigation"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testCalledOnJavaScriptLocationImmediateAssignRedirect()
             throws Throwable {
         final String redirectTargetUrl = createRedirectTargetPage();
@@ -754,6 +761,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Navigation"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testCalledOnJavaScriptLocationImmediateReplaceRedirect()
             throws Throwable {
         final String redirectTargetUrl = createRedirectTargetPage();
@@ -764,6 +773,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Navigation"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testCalledOnJavaScriptLocationDelayedAssignRedirect()
             throws Throwable {
         final String redirectTargetUrl = createRedirectTargetPage();
@@ -774,6 +785,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Navigation"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testCalledOnJavaScriptLocationDelayedReplaceRedirect()
             throws Throwable {
         final String redirectTargetUrl = createRedirectTargetPage();
@@ -890,6 +903,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testNullContentsClientOpenLink() throws Throwable {
         try {
             // The test will fire real intents through the test activity.
@@ -940,6 +955,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testNullContentsClientClickableContent() throws Throwable {
         try {
             // The test will fire real intents through the test activity.
@@ -1023,12 +1040,16 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testClickableContent() throws Throwable {
         doTestClickableContent(true);
     }
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testClickableContentInIframe() throws Throwable {
         doTestClickableContent(false);
     }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java
index 0b17619..17a5e8b 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java
@@ -14,6 +14,7 @@
 import org.chromium.android_webview.test.util.GraphicsTestUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -21,6 +22,8 @@
 /**
  * AwContents rendering / pixel tests.
  */
+// Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+@ParameterizedTest.Set
 public class AwContentsRenderTest extends AwTestBase {
 
     private TestAwContentsClient mContentsClient;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
index 1f2bcfe..6d536bb 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -30,6 +30,7 @@
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.BindingManager;
 import org.chromium.content.browser.ChildProcessConnection;
 import org.chromium.content.browser.ChildProcessLauncher;
@@ -79,6 +80,8 @@
 
     @LargeTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testCreateLoadDestroyManyTimes() throws Throwable {
         for (int i = 0; i < 10; ++i) {
             AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
@@ -588,11 +591,15 @@
         public void releaseAllModerateBindings() {}
     }
 
+    /**
+     * Verifies that a child process is actually gets created with WEBVIEW_SANDBOXED_RENDERER flag.
+     */
     @Feature({"AndroidWebView"})
     @SmallTest
     @CommandLineFlags.Add({
             AwSwitches.WEBVIEW_SANDBOXED_RENDERER,
             ContentSwitches.IPC_SYNC_COMPOSITING})
+    @ParameterizedTest.Set
     public void testSandboxedRendererWorks() throws Throwable {
         MockBindingManager bindingManager = new MockBindingManager();
         ChildProcessLauncher.setBindingManagerForTesting(bindingManager);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java
index 9565638a..6334e3e 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java
@@ -11,6 +11,7 @@
 import org.chromium.android_webview.AwSettings;
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.ui.gfx.DeviceDisplayInfo;
 
@@ -242,6 +243,8 @@
 
     @MediumTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testInitialScaleClobberQuirk() throws Throwable {
         final TestAwContentsClient contentClient = new TestAwContentsClient();
         final AwTestContainerView testContainerView =
@@ -276,6 +279,8 @@
 
     @MediumTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testNoUserScalableQuirk() throws Throwable {
         final TestAwContentsClient contentClient = new TestAwContentsClient();
         final AwTestContainerView testContainerView =
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
index 431c2a2..bf3969d 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
@@ -32,6 +32,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.TestFileUtil;
 import org.chromium.base.test.util.UrlUtils;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content.browser.test.util.HistoryUtils;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
@@ -2192,6 +2193,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Preferences"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testLayoutAlgorithmWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
@@ -2210,6 +2213,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Preferences"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testTextZoomAutosizingWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
@@ -2578,6 +2583,8 @@
 
     @MediumTest
     @Feature({"AndroidWebView", "Preferences"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testUseWideViewportControlsDoubleTabToZoom() throws Throwable {
         final TestAwContentsClient contentClient = new TestAwContentsClient();
         final AwTestContainerView testContainerView =
@@ -2650,6 +2657,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Preferences"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testLoadWithOverviewModeWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
@@ -2661,6 +2670,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Preferences"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testLoadWithOverviewModeViewportTagWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
@@ -2672,6 +2683,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Preferences"})
+    // Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+    @ParameterizedTest.Set
     public void testSetInitialScale() throws Throwable {
         final TestAwContentsClient contentClient = new TestAwContentsClient();
         final AwTestContainerView testContainerView =
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
index 9dd82b1..22b041d 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
@@ -17,12 +17,16 @@
 import org.chromium.android_webview.AwContents;
 import org.chromium.android_webview.AwContentsClient;
 import org.chromium.android_webview.AwSettings;
+import org.chromium.android_webview.AwSwitches;
 import org.chromium.android_webview.test.util.GraphicsTestUtils;
 import org.chromium.android_webview.test.util.JSUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.BaseActivityInstrumentationTestCase;
+import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.InMemorySharedPreferences;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
+import org.chromium.base.test.util.parameter.Parameter;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
@@ -40,8 +44,26 @@
 /**
  * A base class for android_webview tests. WebView only runs on KitKat and later,
  * so make sure no one attempts to run the tests on earlier OS releases.
+ *
+ * By default, all tests run both in single-process mode, and with sandboxed renderer.
+ * If a test doesn't yet work with sandboxed renderer, an entire class, or an individual test
+ * method can be marked for single-process testing only by adding the following annotation:
+ *
+ * @ParameterizedTest.Set
  */
 @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT)
+@ParameterizedTest.Set(tests = {
+            @ParameterizedTest(parameters = {
+                        @Parameter(
+                                tag = CommandLineFlags.Parameter.PARAMETER_TAG)}),
+            @ParameterizedTest(parameters = {
+                        @Parameter(
+                                tag = CommandLineFlags.Parameter.PARAMETER_TAG,
+                                arguments = {
+                                    @Parameter.Argument(
+                                        name = CommandLineFlags.Parameter.ADD_ARG,
+                                        stringArray = {AwSwitches.WEBVIEW_SANDBOXED_RENDERER})
+            })})})
 public class AwTestBase
         extends BaseActivityInstrumentationTestCase<AwTestRunnerActivity> {
     public static final long WAIT_TIMEOUT_MS = scaleTimeout(15000);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java
index 9056c7f..ebd0b0e 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java
@@ -14,6 +14,7 @@
 import org.chromium.android_webview.AwSettings;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 
 import java.util.Locale;
 import java.util.concurrent.Callable;
@@ -21,6 +22,8 @@
 /**
  * A test suite for zooming-related methods and settings.
  */
+// Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+@ParameterizedTest.Set
 public class AwZoomTest extends AwTestBase {
     private TestAwContentsClient mContentsClient;
     private AwContents mAwContents;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java
index 2b681db..bf63aa7 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java
@@ -10,6 +10,7 @@
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.android_webview.test.util.JSUtils;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
 import org.chromium.net.test.util.TestWebServer;
 
@@ -148,6 +149,8 @@
 
     @MediumTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by multiple RVHs crbug.com/533516.
+    @ParameterizedTest.Set
     public void testNotCalledForValidSubresources() throws Throwable {
         TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
                 mContentsClient.getOnPageFinishedHelper();
@@ -371,6 +374,8 @@
 
     @MediumTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by multiple RVHs crbug.com/533516.
+    @ParameterizedTest.Set
     public void testNotCalledOnDomModificationAfterLoadData()
             throws Throwable {
         TestWebServer webServer = TestWebServer.start();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java
index dbda31ad..1a38acb 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java
@@ -14,6 +14,7 @@
 import org.chromium.android_webview.test.util.AwTestTouchUtils;
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
 import org.chromium.net.test.util.TestWebServer;
 
@@ -113,6 +114,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testUserGesture() throws Throwable {
         useDefaultTestAwContentsClient();
         final String pageHtml = CommonResources.makeHtmlPageWithSimpleLinkTo(BAD_HTML_URL);
@@ -172,6 +175,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testUserGestureForIframeSubresource() throws Throwable {
         useDefaultTestAwContentsClient();
         startWebServer();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedHttpErrorTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedHttpErrorTest.java
index c01c4f73..47b3a08a 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedHttpErrorTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedHttpErrorTest.java
@@ -13,6 +13,7 @@
 import org.chromium.android_webview.test.util.AwTestTouchUtils;
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.net.test.util.TestWebServer;
 
 import java.util.ArrayList;
@@ -117,6 +118,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testForUserGesture() throws Throwable {
         useDefaultTestAwContentsClient();
         List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ExternalVideoSurfaceContainerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ExternalVideoSurfaceContainerTest.java
index cadac0e..71109c9 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/ExternalVideoSurfaceContainerTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/ExternalVideoSurfaceContainerTest.java
@@ -9,6 +9,7 @@
 
 import org.chromium.android_webview.test.util.VideoTestUtil;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.components.external_video_surface.ExternalVideoSurfaceContainer;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.test.util.CallbackHelper;
@@ -16,6 +17,8 @@
 /**
  * A test suite for ExternalVideoSurfaceContainerTest.
  */
+// Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+@ParameterizedTest.Set
 public class ExternalVideoSurfaceContainerTest extends AwTestBase {
 
     // Callback helper to track the position/size of the external surface.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java
index 4237f48f..85c24a2 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java
@@ -12,6 +12,7 @@
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.test.util.HistoryUtils;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
 import org.chromium.content_public.browser.WebContents;
@@ -185,6 +186,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by multiple RVHs crbug.com/533516.
+    @ParameterizedTest.Set
     public void testHistoryUrl() throws Throwable {
 
         final String pageHtml = "<html><body>Hello, world!</body></html>";
@@ -203,6 +206,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by multiple RVHs crbug.com/533516.
+    @ParameterizedTest.Set
     public void testOnPageFinishedUrlIsBaseUrl() throws Throwable {
         final String pageHtml = "<html><body>Hello, world!</body></html>";
         final String baseUrl = "http://example.com/";
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/MultipleVideosTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/MultipleVideosTest.java
index 18cd891..c5f8d7f 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/MultipleVideosTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/MultipleVideosTest.java
@@ -8,6 +8,7 @@
 
 import org.chromium.android_webview.test.util.VideoSurfaceViewUtils;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.test.util.DOMUtils;
 import org.chromium.content_public.browser.WebContents;
@@ -17,6 +18,8 @@
 /**
  * Tests pages with multiple videos.
  */
+// Run in single-process mode only. Blocked by inline video support crbug.com/545618.
+@ParameterizedTest.Set
 public class MultipleVideosTest extends AwTestBase {
     private static final String MULTIPLE_VIDEOS_TEST_URL =
             "file:///android_asset/multiple_videos_test.html";
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
index 80ebe074..c2106c72 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
@@ -9,6 +9,7 @@
 import org.chromium.android_webview.AwContents;
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
@@ -90,6 +91,8 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
+    // Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+    @ParameterizedTest.Set
     public void testPopupWindowTextHandle() throws Throwable {
         final String popupPath = "/popup.html";
         final String parentPageHtml = CommonResources.makeHtmlPageFrom("", "<script>"
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java
index 8af193f..bd18553 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java
@@ -21,6 +21,7 @@
 import org.chromium.android_webview.test.util.JavascriptEventObserver;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
@@ -39,6 +40,8 @@
 /**
  * Visual state related tests.
  */
+// Run in single-process mode only. Blocked by rendering support crbug.com/526842.
+@ParameterizedTest.Set
 public class VisualStateTest extends AwTestBase {
     private static final String WAIT_FOR_JS_TEST_URL =
             "file:///android_asset/visual_state_waits_for_js_test.html";
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java
index db20532..6bb3b5a 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java
@@ -16,6 +16,7 @@
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.parameter.ParameterizedTest;
 import org.chromium.net.test.util.TestWebServer;
 
 import java.util.concurrent.Callable;
@@ -23,6 +24,8 @@
 /**
  * Test for getHitTestResult, requestFocusNodeHref, and requestImageRef methods
  */
+// Run in single-process mode only. Blocked by software draws support crbug.com/545611.
+@ParameterizedTest.Set
 public class WebKitHitTestTest extends AwTestBase {
     private TestAwContentsClient mContentsClient;
     private AwTestContainerView mTestView;
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc
index 1b50da26..24bd3e3 100644
--- a/base/memory/discardable_shared_memory.cc
+++ b/base/memory/discardable_shared_memory.cc
@@ -21,6 +21,10 @@
 #include "third_party/ashmem/ashmem.h"
 #endif
 
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
 namespace base {
 namespace {
 
@@ -214,6 +218,7 @@
   DCHECK_EQ(locked_pages_.size(), locked_page_count_);
 #endif
 
+// Pin pages if supported.
 #if defined(OS_ANDROID)
   SharedMemoryHandle handle = shared_memory_.handle();
   if (SharedMemory::IsHandleValid(handle)) {
@@ -222,6 +227,14 @@
       return PURGED;
     }
   }
+#elif defined(OS_WIN)
+  if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+    if (!VirtualAlloc(reinterpret_cast<char*>(shared_memory_.memory()) +
+                          AlignToPageSize(sizeof(SharedState)) + offset,
+                      length, MEM_RESET_UNDO, PAGE_READWRITE)) {
+      return PURGED;
+    }
+  }
 #endif
 
   return SUCCESS;
@@ -240,6 +253,7 @@
 
   DCHECK(shared_memory_.memory());
 
+// Unpin pages if supported.
 #if defined(OS_ANDROID)
   SharedMemoryHandle handle = shared_memory_.handle();
   if (SharedMemory::IsHandleValid(handle)) {
@@ -248,6 +262,18 @@
       DPLOG(ERROR) << "ashmem_unpin_region() failed";
     }
   }
+#elif defined(OS_WIN)
+  if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+    // Note: MEM_RESET is not technically gated on Win8.  However, this Unlock
+    // function needs to match the Lock behaviour (MEM_RESET_UNDO) to properly
+    // implement memory pinning.  It needs to bias towards preserving the
+    // contents of memory between an Unlock and next Lock.
+    if (!VirtualAlloc(reinterpret_cast<char*>(shared_memory_.memory()) +
+                          AlignToPageSize(sizeof(SharedState)) + offset,
+                      length, MEM_RESET, PAGE_READWRITE)) {
+      DPLOG(ERROR) << "VirtualAlloc() MEM_RESET failed in Unlock()";
+    }
+  }
 #endif
 
   size_t start = offset / base::GetPageSize();
@@ -323,6 +349,12 @@
     return false;
   }
 
+// The next section will release as much resource as can be done
+// from the purging process, until the client process notices the
+// purge and releases its own references.
+// Note: this memory will not be accessed again.  The segment will be
+// freed asynchronously at a later time, so just do the best
+// immediately.
 #if defined(OS_POSIX) && !defined(OS_NACL)
 // Linux and Android provide MADV_REMOVE which is preferred as it has a
 // behavior that can be verified in tests. Other POSIX flavors (MacOSX, BSDs),
@@ -340,6 +372,14 @@
               AlignToPageSize(mapped_size_), MADV_PURGE_ARGUMENT)) {
     DPLOG(ERROR) << "madvise() failed";
   }
+#elif defined(OS_WIN)
+  // MEM_DECOMMIT the purged pages to release the physical storage,
+  // either in memory or in the paging file on disk.  Pages remain RESERVED.
+  if (!VirtualFree(reinterpret_cast<char*>(shared_memory_.memory()) +
+                       AlignToPageSize(sizeof(SharedState)),
+                   AlignToPageSize(mapped_size_), MEM_DECOMMIT)) {
+    DPLOG(ERROR) << "VirtualFree() MEM_DECOMMIT failed in Purge()";
+  }
 #endif
 
   last_known_usage_ = Time();
diff --git a/base/memory/shared_memory_mac.cc b/base/memory/shared_memory_mac.cc
index 179fa3b..03c9a6c 100644
--- a/base/memory/shared_memory_mac.cc
+++ b/base/memory/shared_memory_mac.cc
@@ -4,6 +4,7 @@
 
 #include "base/memory/shared_memory.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <mach/mach_vm.h>
 #include <sys/mman.h>
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc
index c67de032..e1e5bf2 100644
--- a/base/memory/shared_memory_posix.cc
+++ b/base/memory/shared_memory_posix.cc
@@ -4,6 +4,7 @@
 
 #include "base/memory/shared_memory.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
diff --git a/base/process/kill_mac.cc b/base/process/kill_mac.cc
index a4e0a14c..0110c908 100644
--- a/base/process/kill_mac.cc
+++ b/base/process/kill_mac.cc
@@ -4,6 +4,7 @@
 
 #include "base/process/kill.h"
 
+#include <errno.h>
 #include <signal.h>
 #include <sys/event.h>
 #include <sys/types.h>
diff --git a/base/process/kill_posix.cc b/base/process/kill_posix.cc
index f0d2d44..fd83ae1 100644
--- a/base/process/kill_posix.cc
+++ b/base/process/kill_posix.cc
@@ -4,6 +4,7 @@
 
 #include "base/process/kill.h"
 
+#include <errno.h>
 #include <signal.h>
 #include <sys/types.h>
 #include <sys/wait.h>
diff --git a/base/process/memory_stubs.cc b/base/process/memory_stubs.cc
index b06c7d5f..a99e94d 100644
--- a/base/process/memory_stubs.cc
+++ b/base/process/memory_stubs.cc
@@ -4,6 +4,8 @@
 
 #include "base/process/memory.h"
 
+#include <stdlib.h>
+
 namespace base {
 
 void EnableTerminationOnOutOfMemory() {
@@ -16,4 +18,22 @@
   return false;
 }
 
+// UncheckedMalloc and Calloc exist so that platforms making use of
+// EnableTerminationOnOutOfMemory have a way to allocate memory without
+// crashing. This _stubs.cc file is for platforms that do not support
+// EnableTerminationOnOutOfMemory (note the empty implementation above). As
+// such, these two Unchecked.alloc functions need only trivially pass-through to
+// their respective stdlib function since those functions will return null on a
+// failure to allocate.
+
+bool UncheckedMalloc(size_t size, void** result) {
+  *result = malloc(size);
+  return *result != nullptr;
+}
+
+bool UncheckedCalloc(size_t num_items, size_t size, void** result) {
+  *result = calloc(num_items, size);
+  return *result != nullptr;
+}
+
 }  // namespace base
diff --git a/base/process/process_iterator_freebsd.cc b/base/process/process_iterator_freebsd.cc
index 22087fd..1d603934 100644
--- a/base/process/process_iterator_freebsd.cc
+++ b/base/process/process_iterator_freebsd.cc
@@ -4,6 +4,7 @@
 
 #include "base/process/process_iterator.h"
 
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/sysctl.h>
 #include <unistd.h>
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index 72e49fae..2320ce7 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -4,6 +4,7 @@
 
 #include "base/process/process.h"
 
+#include <errno.h>
 #include <sys/resource.h>
 #include <sys/wait.h>
 
diff --git a/base/strings/safe_sprintf.cc b/base/strings/safe_sprintf.cc
index b1fcf45..6aa1cbe 100644
--- a/base/strings/safe_sprintf.cc
+++ b/base/strings/safe_sprintf.cc
@@ -4,6 +4,9 @@
 
 #include "base/strings/safe_sprintf.h"
 
+#include <errno.h>
+#include <string.h>
+
 #include <limits>
 
 #if !defined(NDEBUG)
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java b/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
index 64ad9f2..7ac4bee 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
@@ -14,6 +14,7 @@
 import junit.framework.TestResult;
 
 import org.chromium.base.Log;
+import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.parameter.BaseParameter;
 import org.chromium.base.test.util.parameter.Parameter;
 import org.chromium.base.test.util.parameter.Parameterizable;
@@ -156,6 +157,19 @@
         List<ParameterError> failures = new ArrayList<>();
         Map<String, BaseParameter> availableParameters = testCase.getAvailableParameters();
 
+        // Remove all @ParameterizedTests that contain CommandLineFlags.Parameter -- those
+        // are handled in test_runner.py as it is needed to re-launch the whole test activity
+        // to apply command-line args correctly. Note that this way we will also ignore any
+        // other parameters that may present in these @ParameterizedTests.
+        for (Iterator<ParameterizedTest> iter = parameterizedTests.iterator(); iter.hasNext();) {
+            ParameterizedTest paramTest = iter.next();
+            for (Parameter p: paramTest.parameters()) {
+                if (CommandLineFlags.Parameter.PARAMETER_TAG.equals(p.tag())) {
+                    iter.remove();
+                }
+            }
+        }
+
         if (parameterizedTests.isEmpty()) {
             super.run(test);
         } else {
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
index 408074c..6c778b71 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
@@ -11,6 +11,7 @@
 import org.chromium.base.BaseChromiumApplication;
 import org.chromium.base.CommandLine;
 import org.chromium.base.test.BaseTestResult.PreTestHook;
+import org.chromium.base.test.util.parameter.BaseParameter;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Inherited;
@@ -113,4 +114,38 @@
 
         };
     }
+
+    /**
+     * Instructs the test runner to execute the test with modified command-line flags.
+     * Flags to add are specified using 'stringArray' of argument named 'add',
+     * and flags to remove -- in the argument named 'remove'. A parameter without arguments
+     * instructs to run the test with default command-line flags.
+     *
+     * Example:
+     * @ParameterizedTest.Set(tests = {
+     *             @ParameterizedTest(parameters = {
+     *                         @Parameter(
+     *                                 tag = CommandLineFlags.Parameter.PARAMETER_TAG)}),
+     *             @ParameterizedTest(parameters = {
+     *                         @Parameter(
+     *                                 tag = CommandLineFlags.Parameter.PARAMETER_TAG,
+     *                                 arguments = {
+     *                                     @Parameter.Argument(
+     *                                         name = CommandLineFlags.Parameter.ADD_ARG,
+     *                                         stringArray = {'arg1', 'arg2'})
+     *             })})})
+     *
+     * Note that because the entire instrumentation test process needs to be restarted to apply
+     * modified command-line arguments, this annotation is handled by test_runner.py, not by
+     * BaseTestResult class.
+     */
+    public static class Parameter extends BaseParameter {
+        public static final String PARAMETER_TAG = "cmdlinearg-parameter";
+        public static final String ADD_ARG = "add";
+        public static final String REMOVE_ARG = "remove";
+
+        public Parameter(org.chromium.base.test.util.parameter.Parameter.Reader parameterReader) {
+            super(PARAMETER_TAG, parameterReader);
+        }
+    }
 }
diff --git a/blimp/common/BUILD.gn b/blimp/common/BUILD.gn
index 4c3e275..07bc2fa 100644
--- a/blimp/common/BUILD.gn
+++ b/blimp/common/BUILD.gn
@@ -11,16 +11,12 @@
     "compositor/blimp_layer_tree_settings.h",
     "compositor/blimp_task_graph_runner.cc",
     "compositor/blimp_task_graph_runner.h",
-  ]
 
-  if (is_android) {
-    sources += [
-      # TODO(dtrainor): Remove this once the LayerTreeHost settings for Blimp
-      # are finalized or are pushed from the server component.  See
-      # crbug.com/527655.
-      "../../content/public/common/content_switches.cc",
-    ]
-  }
+    # TODO(dtrainor): Remove this once the LayerTreeHost settings for Blimp
+    # are finalized or are pushed from the server component.  See
+    # crbug.com/527655.
+    "../../content/public/common/content_switches.cc",
+  ]
 
   defines = [ "BLIMP_COMMON_IMPLEMENTATION=1" ]
 
diff --git a/build/android/gyp/java_google_api_keys.py b/build/android/gyp/java_google_api_keys.py
index 2f7b6e46..95257d36 100755
--- a/build/android/gyp/java_google_api_keys.py
+++ b/build/android/gyp/java_google_api_keys.py
@@ -102,6 +102,8 @@
   values = {}
   values['GOOGLE_API_KEY'] = google_api_keys.GetAPIKey()
   values['GOOGLE_API_KEY_REMOTING'] = google_api_keys.GetAPIKeyRemoting()
+  values['GOOGLE_API_KEY_PHYSICAL_WEB_TEST'] = (google_api_keys.
+      GetAPIKeyPhysicalWebTest())
   values['GOOGLE_CLIENT_ID_MAIN'] = google_api_keys.GetClientID('MAIN')
   values['GOOGLE_CLIENT_SECRET_MAIN'] = google_api_keys.GetClientSecret('MAIN')
   values['GOOGLE_CLIENT_ID_CLOUD_PRINT'] = google_api_keys.GetClientID(
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py
index 624e157d..2bde2b5f 100755
--- a/build/android/provision_devices.py
+++ b/build/android/provision_devices.py
@@ -57,15 +57,17 @@
   blacklist = (device_blacklist.Blacklist(args.blacklist_file)
                if args.blacklist_file
                else None)
-
-  devices = device_utils.DeviceUtils.HealthyDevices(blacklist)
+  devices = [d for d in device_utils.DeviceUtils.HealthyDevices(blacklist)
+             if not args.emulators or d.adb.is_emulator]
   if args.device:
     devices = [d for d in devices if d == args.device]
-    if not devices:
-      raise device_errors.DeviceUnreachableError(args.device)
-
+  if not devices:
+    raise device_errors.DeviceUnreachableError(args.device)
   parallel_devices = device_utils.DeviceUtils.parallel(devices)
-  parallel_devices.pMap(ProvisionDevice, blacklist, args)
+  if args.emulators:
+    parallel_devices.pMap(SetProperties, args)
+  else:
+    parallel_devices.pMap(ProvisionDevice, blacklist, args)
   if args.auto_reconnect:
     _LaunchHostHeartbeat()
   blacklisted_devices = blacklist.Read() if blacklist else []
@@ -479,6 +481,8 @@
                       help='Json file to output the device blacklist.')
   parser.add_argument('--chrome-specific-wipe', action='store_true',
                       help='only wipe chrome specific data during provisioning')
+  parser.add_argument('--emulators', action='store_true',
+                      help='provision only emulators and ignore usb devices')
   args = parser.parse_args()
   constants.SetBuildType(args.target)
 
diff --git a/build/android/pylib/flag_changer.py b/build/android/pylib/flag_changer.py
index 28580c75..5b9021f 100644
--- a/build/android/pylib/flag_changer.py
+++ b/build/android/pylib/flag_changer.py
@@ -56,9 +56,7 @@
     Args:
       flags: A sequence of flags to add on, eg. ['--single-process'].
     """
-    new_flags = self._state_stack[-1].copy()
-    new_flags.update(flags)
-    self.ReplaceFlags(new_flags)
+    self.PushFlags(add=flags)
 
   def RemoveFlags(self, flags):
     """Removes flags from the command line, if they exist.
@@ -74,8 +72,25 @@
              to remove a switch with a value, you must use the exact string
              used to add it in the first place.
     """
+    self.PushFlags(remove=flags)
+
+  def PushFlags(self, add=None, remove=None):
+    """Appends and removes flags to/from the command line if they aren't already
+       there. Saves the current flags state on the stack, so a call to Restore
+       will change the state back to the one preceeding the call to PushFlags.
+
+    Args:
+      add: A list of flags to add on, eg. ['--single-process'].
+      remove: A list of flags to remove, eg. ['--single-process'].  Note that we
+              expect a complete match when removing flags; if you want to remove
+              a switch with a value, you must use the exact string used to add
+              it in the first place.
+    """
     new_flags = self._state_stack[-1].copy()
-    new_flags.difference_update(flags)
+    if add:
+      new_flags.update(add)
+    if remove:
+      new_flags.difference_update(remove)
     self.ReplaceFlags(new_flags)
 
   def Restore(self):
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 7c35ff29..f3c3d3c 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import collections
+import copy
 import logging
 import os
 import pickle
@@ -25,6 +27,7 @@
 _ACTIVITY_RESULT_CANCELED = 0
 _ACTIVITY_RESULT_OK = -1
 
+_COMMAND_LINE_PARAMETER = 'cmdlinearg-parameter'
 _DEFAULT_ANNOTATIONS = [
     'Smoke', 'SmallTest', 'MediumTest', 'LargeTest',
     'EnormousTest', 'IntegrationTest']
@@ -41,6 +44,8 @@
     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetPackage')
 _EXTRA_DRIVER_TARGET_CLASS = (
     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetClass')
+_PARAMETERIZED_TEST_ANNOTATION = 'ParameterizedTest'
+_PARAMETERIZED_TEST_SET_ANNOTATION = 'ParameterizedTest$Set'
 _NATIVE_CRASH_RE = re.compile('native crash', re.IGNORECASE)
 _PICKLE_FORMAT_VERSION = 10
 
@@ -134,6 +139,56 @@
   return results
 
 
+def ParseCommandLineFlagParameters(annotations):
+  """Determines whether the test is parameterized to be run with different
+     command-line flags.
+
+  Args:
+    annotations: The annotations of the test.
+
+  Returns:
+    If the test is parameterized, returns a list of named tuples
+    with lists of flags, e.g.:
+
+      [(add=['--flag-to-add']), (remove=['--flag-to-remove']), ()]
+
+    That means, the test must be run three times, the first time with
+    "--flag-to-add" added to command-line, the second time with
+    "--flag-to-remove" to be removed from command-line, and the third time
+    with default command-line args. If the same flag is listed both for adding
+    and for removing, it is left unchanged.
+
+    If the test is not parametrized, returns None.
+
+  """
+  ParamsTuple = collections.namedtuple('ParamsTuple', ['add', 'remove'])
+  parameterized_tests = []
+  if _PARAMETERIZED_TEST_ANNOTATION in annotations:
+    parameterized_tests = [annotations[_PARAMETERIZED_TEST_ANNOTATION]]
+  elif _PARAMETERIZED_TEST_SET_ANNOTATION in annotations:
+    if annotations[_PARAMETERIZED_TEST_SET_ANNOTATION]:
+      parameterized_tests = annotations[
+        _PARAMETERIZED_TEST_SET_ANNOTATION].get('tests', [])
+  else:
+    return None
+
+  result = []
+  for pt in parameterized_tests:
+    if not pt:
+      continue
+    for p in pt['parameters']:
+      if p['tag'] == _COMMAND_LINE_PARAMETER:
+        to_add = []
+        to_remove = []
+        for a in p.get('arguments', []):
+          if a['name'] == 'add':
+            to_add = ['--%s' % f for f in a['stringArray']]
+          elif a['name'] == 'remove':
+            to_remove = ['--%s' % f for f in a['stringArray']]
+        result.append(ParamsTuple(to_add, to_remove))
+  return result if result else None
+
+
 class InstrumentationTestInstance(test_instance.TestInstance):
 
   def __init__(self, args, isolate_delegate, error_func):
@@ -392,7 +447,8 @@
       logging.info('Getting tests from JAR via proguard. (%s)', str(e))
       tests = self._GetTestsFromProguard(self.test_jar)
       self._SaveTestsToPickle(pickle_path, self.test_jar, tests)
-    return self._InflateTests(self._FilterTests(tests))
+    return self._ParametrizeTestsWithFlags(
+        self._InflateTests(self._FilterTests(tests)))
 
   class ProguardPickleException(Exception):
     pass
@@ -517,6 +573,18 @@
         })
     return inflated_tests
 
+  def _ParametrizeTestsWithFlags(self, tests):
+    new_tests = []
+    for t in tests:
+      parameters = ParseCommandLineFlagParameters(t['annotations'])
+      if parameters:
+        t['flags'] = parameters[0]
+        for p in parameters[1:]:
+          parameterized_t = copy.copy(t)
+          parameterized_t['flags'] = p
+          new_tests.append(parameterized_t)
+    return tests + new_tests
+
   @staticmethod
   def GetHttpServerEnvironmentVars():
     return {
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py
index e526bff29..3645c85 100644
--- a/build/android/pylib/instrumentation/test_runner.py
+++ b/build/android/pylib/instrumentation/test_runner.py
@@ -4,6 +4,7 @@
 
 """Class for running instrumentation tests on a single device."""
 
+import collections
 import logging
 import os
 import re
@@ -123,7 +124,7 @@
       self.flags.Restore()
     super(TestRunner, self).TearDown()
 
-  def TestSetup(self, test):
+  def TestSetup(self, test, flag_modifiers):
     """Sets up the test harness for running a particular test.
 
     Args:
@@ -133,8 +134,8 @@
     self._SetupIndividualTestTimeoutScale(test)
     self.tool.SetupEnvironment()
 
-    if self.flags and self._IsFreTest(test):
-      self.flags.RemoveFlags(['--disable-fre'])
+    if self.flags:
+      self.flags.PushFlags(add=flag_modifiers.add, remove=flag_modifiers.remove)
 
     # Make sure the forwarder is still running.
     self._RestartHttpServerForwarderIfNecessary()
@@ -171,6 +172,23 @@
     """
     return _PERF_TEST_ANNOTATION in self.test_pkg.GetTestAnnotations(test)
 
+  def _GetTestCmdlineParameters(self, test):
+    """Determines whether the test is parameterized to be run with different
+       command-line flags.
+
+    Args:
+      test: The name of the test to be checked.
+
+    Returns:
+      The list of parameters.
+    """
+    annotations = self.test_pkg.GetTestAnnotations(test)
+    params = instrumentation_test_instance.ParseCommandLineFlagParameters(
+      annotations)
+    if not params:
+      params = [collections.namedtuple('Dummy', ['add', 'remove'])([], [])]
+    return params
+
   def SetupPerfMonitoringIfNeeded(self, test):
     """Sets up performance monitoring if the specified test requires it.
 
@@ -184,7 +202,7 @@
     self._logcat_monitor = self.device.GetLogcatMonitor()
     self._logcat_monitor.Start()
 
-  def TestTeardown(self, test, result):
+  def TestTeardown(self, test, results):
     """Cleans up the test harness after running a particular test.
 
     Depending on the options of this TestRunner this might handle performance
@@ -192,17 +210,17 @@
 
     Args:
       test: The name of the test that was just run.
-      result: result for this test.
+      results: results for this test.
     """
 
     self.tool.CleanUpEnvironment()
 
-    if self.flags and self._IsFreTest(test):
+    if self.flags:
       self.flags.Restore()
 
-    if not result:
+    if not results:
       return
-    if result.DidRunPass():
+    if results.DidRunPass():
       self.TearDownPerfMonitoring(test)
 
       if self.coverage_dir:
@@ -345,40 +363,57 @@
                self._GetIndividualTestTimeoutScale(test) *
                self.tool.GetTimeoutScale())
 
-    start_ms = 0
-    duration_ms = 0
-    try:
-      self.TestSetup(test)
-
+    cmdline_parameters = self._GetTestCmdlineParameters(test)
+    for flag_modifiers in cmdline_parameters:
+      start_ms = 0
+      duration_ms = 0
       try:
-        self.device.GoHome()
-      except device_errors.CommandTimeoutError:
-        logging.exception('Failed to focus the launcher.')
+        if self._IsFreTest(test):
+          flag_modifiers.remove.append('--disable-fre')
+        self.TestSetup(test, flag_modifiers)
 
-      time_ms = lambda: int(time.time() * 1000)
-      start_ms = time_ms()
-      raw_output = self._RunTest(test, timeout)
-      duration_ms = time_ms() - start_ms
+        try:
+          self.device.GoHome()
+        except device_errors.CommandTimeoutError:
+          logging.exception('Failed to focus the launcher.')
 
-      # Parse the test output
-      result_code, result_bundle, statuses = (
-          instrumentation_test_instance.ParseAmInstrumentRawOutput(raw_output))
-      result = self._GenerateTestResult(
-          test, result_code, result_bundle, statuses, start_ms, duration_ms)
-      if local_device_instrumentation_test_run.DidPackageCrashOnDevice(
-          self.test_pkg.GetPackageName(), self.device):
-        result.SetType(base_test_result.ResultType.CRASH)
-      results.AddResult(result)
-    except device_errors.CommandTimeoutError as e:
-      results.AddResult(test_result.InstrumentationTestResult(
+        time_ms = lambda: int(time.time() * 1000)
+        start_ms = time_ms()
+        raw_output = self._RunTest(test, timeout)
+        duration_ms = time_ms() - start_ms
+
+        # Parse the test output
+        result_code, result_bundle, statuses = (
+            instrumentation_test_instance.ParseAmInstrumentRawOutput(
+              raw_output))
+        result = self._GenerateTestResult(
+            test, result_code, result_bundle, statuses, start_ms, duration_ms)
+        if local_device_instrumentation_test_run.DidPackageCrashOnDevice(
+            self.test_pkg.GetPackageName(), self.device):
+          result.SetType(base_test_result.ResultType.CRASH)
+      except device_errors.CommandTimeoutError as e:
+        result = test_result.InstrumentationTestResult(
           test, base_test_result.ResultType.TIMEOUT, start_ms, duration_ms,
-          log=str(e) or 'No information'))
-      if self.package_info:
-        self.device.ForceStop(self.package_info.package)
-        self.device.ForceStop(self.package_info.test_package)
-    except device_errors.DeviceUnreachableError as e:
-      results.AddResult(test_result.InstrumentationTestResult(
-          test, base_test_result.ResultType.CRASH, start_ms, duration_ms,
-          log=str(e) or 'No information'))
-    self.TestTeardown(test, results)
+          log=str(e) or 'No information')
+        if self.package_info:
+          self.device.ForceStop(self.package_info.package)
+          self.device.ForceStop(self.package_info.test_package)
+      except device_errors.DeviceUnreachableError as e:
+        result = test_result.InstrumentationTestResult(
+            test, base_test_result.ResultType.CRASH, start_ms, duration_ms,
+            log=str(e) or 'No information')
+      if len(cmdline_parameters) > 1:
+        # Specify commandline flag modifications used in the test run
+        result_name = result.GetName()
+        if flag_modifiers.add:
+          result_name = '%s with {%s}' % (
+            result_name, ' '.join(flag_modifiers.add))
+        if flag_modifiers.remove:
+          result_name = '%s without {%s}' % (
+            result_name, ' '.join(flag_modifiers.remove))
+        result.SetName(result_name)
+      results.AddResult(result)
+
+      self.TestTeardown(test, results)
+
     return (results, None if results.DidRunPass() else test)
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index afae9ab..a36c6587 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -85,8 +85,7 @@
         elif not self._test_instance.package_info.cmdline_file:
           logging.error("Couldn't set flags: no cmdline_file")
         else:
-          self._flag_changers[str(dev)] = flag_changer.FlagChanger(
-              dev, self._test_instance.package_info.cmdline_file)
+          self._CreateFlagChangerIfNeeded(dev)
           logging.debug('Attempting to set flags: %r',
                         self._test_instance.flags)
           self._flag_changers[str(dev)].AddFlags(self._test_instance.flags)
@@ -102,6 +101,11 @@
 
     self._env.parallel_devices.pMap(individual_device_tear_down)
 
+  def _CreateFlagChangerIfNeeded(self, device):
+    if not str(device) in self._flag_changers:
+      self._flag_changers[str(device)] = flag_changer.FlagChanger(
+        device, self._test_instance.package_info.cmdline_file)
+
   #override
   def _CreateShards(self, tests):
     return tests
@@ -114,10 +118,20 @@
   def _GetTestName(self, test):
     return '%s#%s' % (test['class'], test['method'])
 
+  def _GetTestNameForDisplay(self, test):
+    display_name = self._GetTestName(test)
+    flags = test['flags']
+    if flags.add:
+      display_name = '%s with {%s}' % (display_name, ' '.join(flags.add))
+    if flags.remove:
+      display_name = '%s without {%s}' % (display_name, ' '.join(flags.remove))
+    return display_name
+
   #override
   def _RunTest(self, device, test):
     extras = self._test_instance.GetHttpServerEnvironmentVars()
 
+    flags = None
     if isinstance(test, list):
       if not self._test_instance.driver_apk:
         raise Exception('driver_apk does not exist. '
@@ -131,6 +145,7 @@
       test_names, timeouts = zip(*(name_and_timeout(t) for t in test))
 
       test_name = ','.join(test_names)
+      test_display_name = test_name
       target = '%s/%s' % (
           self._test_instance.driver_package,
           self._test_instance.driver_name)
@@ -140,22 +155,36 @@
       timeout = sum(timeouts)
     else:
       test_name = self._GetTestName(test)
+      test_display_name = test_name
       target = '%s/%s' % (
           self._test_instance.test_package, self._test_instance.test_runner)
       extras['class'] = test_name
-      timeout = self._GetTimeoutFromAnnotations(test['annotations'], test_name)
+      if 'flags' in test:
+        flags = test['flags']
+        test_display_name = self._GetTestNameForDisplay(test)
+      timeout = self._GetTimeoutFromAnnotations(
+        test['annotations'], test_display_name)
 
-    logging.info('preparing to run %s: %s', test_name, test)
+    logging.info('preparing to run %s: %s', test_display_name, test)
 
-    time_ms = lambda: int(time.time() * 1e3)
-    start_ms = time_ms()
-    output = device.StartInstrumentation(
-        target, raw=True, extras=extras, timeout=timeout, retries=0)
-    duration_ms = time_ms() - start_ms
+    if flags:
+      self._CreateFlagChangerIfNeeded(device)
+      self._flag_changers[str(device)].PushFlags(
+        add=flags.add, remove=flags.remove)
+
+    try:
+      time_ms = lambda: int(time.time() * 1e3)
+      start_ms = time_ms()
+      output = device.StartInstrumentation(
+          target, raw=True, extras=extras, timeout=timeout, retries=0)
+      duration_ms = time_ms() - start_ms
+    finally:
+      if flags:
+        self._flag_changers[str(device)].Restore()
 
     # TODO(jbudorick): Make instrumentation tests output a JSON so this
     # doesn't have to parse the output.
-    logging.debug('output from %s:', test_name)
+    logging.debug('output from %s:', test_display_name)
     for l in output:
       logging.debug('  %s', l)
 
@@ -163,6 +192,10 @@
         self._test_instance.ParseAmInstrumentRawOutput(output))
     results = self._test_instance.GenerateTestResults(
         result_code, result_bundle, statuses, start_ms, duration_ms)
+    if flags:
+      for r in results:
+        if r.GetName() == test_name:
+          r.SetName(test_display_name)
     if DidPackageCrashOnDevice(self._test_instance.test_package, device):
       for r in results:
         if r.GetType() == base_test_result.ResultType.UNKNOWN:
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 2ff2593..9d3cc43f 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -138,6 +138,8 @@
     "layers/layer_lists.h",
     "layers/layer_position_constraint.cc",
     "layers/layer_position_constraint.h",
+    "layers/layer_proto_converter.cc",
+    "layers/layer_proto_converter.h",
     "layers/layer_utils.cc",
     "layers/layer_utils.h",
     "layers/nine_patch_layer.cc",
@@ -753,6 +755,7 @@
     "layers/layer_impl_unittest.cc",
     "layers/layer_iterator_unittest.cc",
     "layers/layer_position_constraint_unittest.cc",
+    "layers/layer_proto_converter_unittest.cc",
     "layers/layer_unittest.cc",
     "layers/layer_utils_unittest.cc",
     "layers/nine_patch_layer_impl_unittest.cc",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 2a4043729..c453330 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -200,6 +200,8 @@
         'layers/layer_lists.h',
         'layers/layer_position_constraint.cc',
         'layers/layer_position_constraint.h',
+        'layers/layer_proto_converter.cc',
+        'layers/layer_proto_converter.h',
         'layers/layer_utils.cc',
         'layers/layer_utils.h',
         'layers/nine_patch_layer.cc',
@@ -584,6 +586,7 @@
       'type': '<(component)',
       'sources': [
         'proto/display_item.proto',
+        'proto/layer.proto',
         'proto/point.proto',
         'proto/pointf.proto',
         'proto/rect.proto',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 65107ac..222b202576 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -45,6 +45,7 @@
       'layers/layer_impl_unittest.cc',
       'layers/layer_iterator_unittest.cc',
       'layers/layer_position_constraint_unittest.cc',
+      'layers/layer_proto_converter_unittest.cc',
       'layers/layer_unittest.cc',
       'layers/layer_utils_unittest.cc',
       'layers/nine_patch_layer_impl_unittest.cc',
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index d1a95bc9..5ebe0d8c 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -21,9 +21,11 @@
 #include "cc/debug/frame_viewer_instrumentation.h"
 #include "cc/layers/layer_client.h"
 #include "cc/layers/layer_impl.h"
+#include "cc/layers/layer_proto_converter.h"
 #include "cc/layers/scrollbar_layer_interface.h"
 #include "cc/output/copy_output_request.h"
 #include "cc/output/copy_output_result.h"
+#include "cc/proto/layer.pb.h"
 #include "cc/trees/draw_property_utils.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
@@ -1349,6 +1351,73 @@
   num_dependents_need_push_properties_ = 0;
 }
 
+void Layer::SetTypeForProtoSerialization(proto::LayerNode* proto) const {
+  proto->set_type(proto::LayerType::Base);
+}
+
+void Layer::ToLayerNodeProto(proto::LayerNode* proto) const {
+  proto->set_id(layer_id_);
+  SetTypeForProtoSerialization(proto);
+
+  if (parent_)
+    proto->set_parent_id(parent_->id());
+
+  DCHECK_EQ(0, proto->children_size());
+  for (const auto& child : children_) {
+    child->ToLayerNodeProto(proto->add_children());
+  }
+
+  if (mask_layer_)
+    mask_layer_->ToLayerNodeProto(proto->mutable_mask_layer());
+  if (replica_layer_)
+    replica_layer_->ToLayerNodeProto(proto->mutable_replica_layer());
+}
+
+void Layer::FromLayerNodeProto(const proto::LayerNode& proto,
+                               const LayerIdMap& layer_map) {
+  DCHECK(proto.has_id());
+  layer_id_ = proto.id();
+
+  // Recursively remove all children. In the case of when the updated
+  // hierarchy has no children, or the children has changed, the old list
+  // of children must be removed. The whole hierarchy is always sent, so
+  // if there were no change in the children, they will be correctly added back
+  // below.
+  RemoveAllChildren();
+  for (int i = 0; i < proto.children_size(); ++i) {
+    const proto::LayerNode& child_proto = proto.children(i);
+    DCHECK(child_proto.has_type());
+    scoped_refptr<Layer> child =
+        LayerProtoConverter::FindOrAllocateAndConstruct(child_proto, layer_map);
+    child->FromLayerNodeProto(child_proto, layer_map);
+    AddChild(child);
+  }
+
+  if (mask_layer_)
+    mask_layer_->RemoveFromParent();
+  if (proto.has_mask_layer()) {
+    mask_layer_ = LayerProtoConverter::FindOrAllocateAndConstruct(
+        proto.mask_layer(), layer_map);
+    mask_layer_->FromLayerNodeProto(proto.mask_layer(), layer_map);
+    mask_layer_->SetParent(this);
+    // SetIsMask() is only ever called with true, so no need to reset flag.
+    mask_layer_->SetIsMask(true);
+  } else {
+    mask_layer_ = nullptr;
+  }
+
+  if (replica_layer_)
+    replica_layer_->RemoveFromParent();
+  if (proto.has_replica_layer()) {
+    replica_layer_ = LayerProtoConverter::FindOrAllocateAndConstruct(
+        proto.replica_layer(), layer_map);
+    replica_layer_->FromLayerNodeProto(proto.replica_layer(), layer_map);
+    replica_layer_->SetParent(this);
+  } else {
+    replica_layer_ = nullptr;
+  }
+}
+
 scoped_ptr<LayerImpl> Layer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
   return LayerImpl::Create(tree_impl, layer_id_,
                            new LayerImpl::SyncedScrollOffset);
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 2fec3636..5c298f5 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -67,6 +67,10 @@
 class SimpleEnclosedRegion;
 struct AnimationEvent;
 
+namespace proto {
+class LayerNode;
+}  // namespace proto
+
 // Base class for composited layers. Special layer types are derived from
 // this class.
 class CC_EXPORT Layer : public base::RefCounted<Layer>,
@@ -74,6 +78,7 @@
                         public LayerAnimationValueProvider {
  public:
   typedef LayerList LayerListType;
+  typedef base::hash_map<int, scoped_refptr<Layer>> LayerIdMap;
 
   enum LayerIdLabels {
     INVALID_ID = -1,
@@ -358,6 +363,30 @@
 
   virtual void PushPropertiesTo(LayerImpl* layer);
 
+  // Sets the type proto::LayerType that should be used for serialization
+  // of the current layer by calling LayerNode::set_type(proto::LayerType).
+  // TODO(nyquist): Start using a forward declared enum class when
+  // https://github.com/google/protobuf/issues/67 has been fixed and rolled in.
+  // This function would preferably instead return a proto::LayerType, but
+  // since that is an enum (the protobuf library does not generate enum
+  // classes), it can't be forward declared. We don't want to include
+  // //cc/proto/layer.pb.h in this header file, as it requires that all
+  // dependent targets would have to be given the config for how to include it.
+  virtual void SetTypeForProtoSerialization(proto::LayerNode* proto) const;
+
+  // Recursively iterate over this layer and all children and write the
+  // hierarchical structure to the given LayerNode proto. In addition to the
+  // structure itself, the Layer id and type is also written to facilitate
+  // construction of the correct layer on the client.
+  void ToLayerNodeProto(proto::LayerNode* proto) const;
+
+  // Recursively iterate over the given LayerNode proto and read the structure
+  // into this node and its children. The |layer_map| should be used to look
+  // for previously existing Layers, since they should be re-used between each
+  // hierarchy update.
+  void FromLayerNodeProto(const proto::LayerNode& proto,
+                          const LayerIdMap& layer_map);
+
   LayerTreeHost* layer_tree_host() { return layer_tree_host_; }
   const LayerTreeHost* layer_tree_host() const { return layer_tree_host_; }
 
diff --git a/cc/layers/layer_proto_converter.cc b/cc/layers/layer_proto_converter.cc
new file mode 100644
index 0000000..2dcc3d9
--- /dev/null
+++ b/cc/layers/layer_proto_converter.cc
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/layers/layer_proto_converter.h"
+
+#include "base/stl_util.h"
+#include "cc/layers/layer.h"
+#include "cc/proto/layer.pb.h"
+#include "cc/trees/layer_tree_host_common.h"
+#include "cc/trees/layer_tree_settings.h"
+
+namespace cc {
+
+LayerProtoConverter::LayerProtoConverter() {}
+
+LayerProtoConverter::~LayerProtoConverter() {}
+
+// static
+void LayerProtoConverter::SerializeLayerHierarchy(
+    const scoped_refptr<Layer> root_layer,
+    proto::LayerNode* root_node) {
+  root_layer->ToLayerNodeProto(root_node);
+}
+
+// static
+scoped_refptr<Layer> LayerProtoConverter::DeserializeLayerHierarchy(
+    scoped_refptr<Layer> existing_root,
+    const proto::LayerNode& root_node) {
+  LayerIdMap layer_id_map;
+  RecursivelyFindAllLayers(existing_root, &layer_id_map);
+
+  scoped_refptr<Layer> new_root = existing_root;
+  if (!existing_root ||
+      (root_node.has_id() && root_node.id() != existing_root->id())) {
+    // The root node has changed or there was no root node,
+    // so find or create the new root.
+    new_root = FindOrAllocateAndConstruct(root_node, layer_id_map);
+  }
+  new_root->FromLayerNodeProto(root_node, layer_id_map);
+  return new_root;
+}
+
+// static
+void LayerProtoConverter::RecursivelyFindAllLayers(
+    const scoped_refptr<Layer>& layer,
+    LayerIdMap* layer_id_map) {
+  LayerTreeHostCommon::CallFunctionForSubtree(
+      layer.get(),
+      [layer_id_map](Layer* layer) { (*layer_id_map)[layer->id()] = layer; });
+}
+
+// static
+scoped_refptr<Layer> LayerProtoConverter::FindOrAllocateAndConstruct(
+    const proto::LayerNode& proto,
+    const Layer::LayerIdMap& layer_id_map) {
+  DCHECK(proto.has_id());
+  Layer::LayerIdMap::const_iterator iter = layer_id_map.find(proto.id());
+  if (iter != layer_id_map.end())
+    return iter->second;
+  DCHECK(proto.has_type());
+  switch (proto.type()) {
+    case proto::Base:
+      return Layer::Create(LayerSettings()).get();
+  }
+  // TODO(nyquist): Add the rest of the necessary LayerTypes. This function
+  // should not return null.
+  NOTREACHED();
+  return nullptr;
+}
+
+}  // namespace cc
diff --git a/cc/layers/layer_proto_converter.h b/cc/layers/layer_proto_converter.h
new file mode 100644
index 0000000..29424a0
--- /dev/null
+++ b/cc/layers/layer_proto_converter.h
@@ -0,0 +1,54 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_LAYERS_LAYER_PROTO_CONVERTER_H_
+#define CC_LAYERS_LAYER_PROTO_CONVERTER_H_
+
+#include "base/macros.h"
+#include "cc/base/cc_export.h"
+#include "cc/layers/layer.h"
+
+namespace cc {
+
+namespace proto {
+class LayerNode;
+}
+
+// A class to faciliate (de)serialization of a Layer tree to protocol buffers.
+class CC_EXPORT LayerProtoConverter {
+ public:
+  // Starting at |root_layer|, serializes the layer hierarchy into the
+  // proto::LayerNode.
+  static void SerializeLayerHierarchy(const scoped_refptr<Layer> root_layer,
+                                      proto::LayerNode* root_node);
+
+  // Recursively iterate over the given LayerNode proto and read the structure
+  // into a local Layer structure, re-using existing Layers. returns the new
+  // root Layer after updating the hierarchy (may be the same as
+  // |existing_root|).
+  static scoped_refptr<Layer> DeserializeLayerHierarchy(
+      scoped_refptr<Layer> existing_root,
+      const proto::LayerNode& root_node);
+
+  // Returns the Layer with proto.id() as the Layer id, if it exists in
+  // |layer_id_map|. Otherwise, a new Layer is constructed of the type given
+  // from proto.type().
+  static scoped_refptr<Layer> FindOrAllocateAndConstruct(
+      const proto::LayerNode& proto,
+      const Layer::LayerIdMap& layer_id_map);
+
+ private:
+  LayerProtoConverter();
+  ~LayerProtoConverter();
+
+  using LayerIdMap = base::hash_map<int, scoped_refptr<Layer>>;
+  // Start at |layer| and recursively add |layer| and all its children and
+  // special layers to |layer_id_map|.
+  static void RecursivelyFindAllLayers(const scoped_refptr<Layer>& layer,
+                                       LayerIdMap* layer_id_map);
+};
+
+}  // namespace cc
+
+#endif  // CC_LAYERS_LAYER_PROTO_CONVERTER_H_
diff --git a/cc/layers/layer_proto_converter_unittest.cc b/cc/layers/layer_proto_converter_unittest.cc
new file mode 100644
index 0000000..040be97
--- /dev/null
+++ b/cc/layers/layer_proto_converter_unittest.cc
@@ -0,0 +1,110 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/layers/layer_proto_converter.h"
+
+#include "cc/layers/layer.h"
+#include "cc/proto/layer.pb.h"
+#include "cc/trees/layer_tree_settings.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+
+TEST(LayerProtoConverterTest, TestKeepingRoot) {
+  /* Test deserialization of a tree that looks like:
+         root
+        /   \
+       a     b
+              \
+               c
+     The old root node will be reused during deserialization.
+  */
+  scoped_refptr<Layer> old_root = Layer::Create(LayerSettings());
+  proto::LayerNode root_node;
+  root_node.set_id(old_root->id());
+  root_node.set_type(proto::LayerType::Base);
+
+  proto::LayerNode* child_a_node = root_node.add_children();
+  child_a_node->set_id(442);
+  child_a_node->set_type(proto::LayerType::Base);
+  child_a_node->set_parent_id(old_root->id());  // root_node
+
+  proto::LayerNode* child_b_node = root_node.add_children();
+  child_b_node->set_id(443);
+  child_b_node->set_type(proto::LayerType::Base);
+  child_b_node->set_parent_id(old_root->id());  // root_node
+
+  proto::LayerNode* child_c_node = child_b_node->add_children();
+  child_c_node->set_id(444);
+  child_c_node->set_type(proto::LayerType::Base);
+  child_c_node->set_parent_id(child_b_node->id());
+
+  scoped_refptr<Layer> new_root =
+      LayerProtoConverter::DeserializeLayerHierarchy(old_root, root_node);
+
+  // The new root should not be the same as the old root.
+  EXPECT_EQ(old_root->id(), new_root->id());
+  ASSERT_EQ(2u, new_root->children().size());
+  scoped_refptr<Layer> child_a = new_root->children()[0];
+  scoped_refptr<Layer> child_b = new_root->children()[1];
+
+  EXPECT_EQ(child_a_node->id(), child_a->id());
+  EXPECT_EQ(child_b_node->id(), child_b->id());
+
+  EXPECT_EQ(0u, child_a->children().size());
+  ASSERT_EQ(1u, child_b->children().size());
+
+  scoped_refptr<Layer> child_c = child_b->children()[0];
+  EXPECT_EQ(child_c_node->id(), child_c->id());
+}
+
+TEST(LayerProtoConverterTest, TestSwappingRoot) {
+  /* Test deserialization of a tree that looks like:
+         root
+        /   \
+       a     b
+              \
+               c
+     The old root node will be swapped out during deserialization.
+  */
+  proto::LayerNode root_node;
+  root_node.set_id(441);
+  root_node.set_type(proto::LayerType::Base);
+
+  proto::LayerNode* child_a_node = root_node.add_children();
+  child_a_node->set_id(442);
+  child_a_node->set_type(proto::LayerType::Base);
+  child_a_node->set_parent_id(root_node.id());
+
+  proto::LayerNode* child_b_node = root_node.add_children();
+  child_b_node->set_id(443);
+  child_b_node->set_type(proto::LayerType::Base);
+  child_b_node->set_parent_id(root_node.id());
+
+  proto::LayerNode* child_c_node = child_b_node->add_children();
+  child_c_node->set_id(444);
+  child_c_node->set_type(proto::LayerType::Base);
+  child_c_node->set_parent_id(child_b_node->id());
+
+  scoped_refptr<Layer> old_root = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> new_root =
+      LayerProtoConverter::DeserializeLayerHierarchy(old_root, root_node);
+
+  // The new root should not be the same as the old root.
+  EXPECT_EQ(root_node.id(), new_root->id());
+  ASSERT_EQ(2u, new_root->children().size());
+  scoped_refptr<Layer> child_a = new_root->children()[0];
+  scoped_refptr<Layer> child_b = new_root->children()[1];
+
+  EXPECT_EQ(child_a_node->id(), child_a->id());
+  EXPECT_EQ(child_b_node->id(), child_b->id());
+
+  EXPECT_EQ(0u, child_a->children().size());
+  ASSERT_EQ(1u, child_b->children().size());
+
+  scoped_refptr<Layer> child_c = child_b->children()[0];
+  EXPECT_EQ(child_c_node->id(), child_c->id());
+}
+
+}  // namespace cc
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index d81463d3..12aa514 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -10,6 +10,7 @@
 #include "cc/layers/layer_impl.h"
 #include "cc/output/copy_output_request.h"
 #include "cc/output/copy_output_result.h"
+#include "cc/proto/layer.pb.h"
 #include "cc/test/animation_test_common.h"
 #include "cc/test/fake_impl_task_runner_provider.h"
 #include "cc/test/fake_layer_tree_host_client.h"
@@ -1349,5 +1350,222 @@
   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
 }
 
+TEST_F(LayerTest, RecursiveHierarchySerialization) {
+  /* Testing serialization and deserialization of a tree that looks like this:
+          root
+          /  \
+         a    b
+               \
+                c
+     Layer c also has a mask layer and a replica layer.
+  */
+  scoped_refptr<Layer> layer_src_root = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_a = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_b = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_c = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_c_mask = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_c_replica = Layer::Create(LayerSettings());
+  layer_src_root->AddChild(layer_src_a);
+  layer_src_root->AddChild(layer_src_b);
+  layer_src_b->AddChild(layer_src_c);
+  layer_src_c->SetMaskLayer(layer_src_c_mask.get());
+  layer_src_c->SetReplicaLayer(layer_src_c_replica.get());
+
+  proto::LayerNode proto;
+  layer_src_root->ToLayerNodeProto(&proto);
+
+  Layer::LayerIdMap empty_dest_layer_map;
+  scoped_refptr<Layer> layer_dest_root = Layer::Create(LayerSettings());
+  layer_dest_root->FromLayerNodeProto(proto, empty_dest_layer_map);
+
+  EXPECT_EQ(layer_src_root->id(), layer_dest_root->id());
+  EXPECT_EQ(nullptr, layer_dest_root->parent());
+  ASSERT_EQ(2u, layer_dest_root->children().size());
+
+  scoped_refptr<Layer> layer_dest_a = layer_dest_root->children()[0];
+  EXPECT_EQ(layer_src_a->id(), layer_dest_a->id());
+  EXPECT_EQ(layer_src_root->id(), layer_dest_a->parent()->id());
+  EXPECT_EQ(0u, layer_dest_a->children().size());
+
+  scoped_refptr<Layer> layer_dest_b = layer_dest_root->children()[1];
+  EXPECT_EQ(layer_src_b->id(), layer_dest_b->id());
+  EXPECT_EQ(layer_src_root->id(), layer_dest_b->parent()->id());
+  ASSERT_EQ(1u, layer_dest_b->children().size());
+
+  scoped_refptr<Layer> layer_dest_c = layer_dest_b->children()[0];
+  EXPECT_EQ(layer_src_c->id(), layer_dest_c->id());
+  EXPECT_EQ(layer_src_b->id(), layer_dest_c->parent()->id());
+  EXPECT_EQ(0u, layer_dest_c->children().size());
+  EXPECT_EQ(layer_src_c_mask->id(), layer_dest_c->mask_layer()->id());
+  EXPECT_EQ(layer_src_c_replica->id(), layer_dest_c->replica_layer()->id());
+}
+
+TEST_F(LayerTest, RecursiveHierarchySerializationWithNodeReuse) {
+  /* Testing serialization and deserialization of a tree that initially looks
+     like this:
+          root
+          /
+         a
+     The source tree is then updated by adding layer |b|:
+          root
+          /  \
+         a    b
+     The deserialization should then re-use the Layers from last
+     deserialization.
+  */
+  scoped_refptr<Layer> layer_src_root = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_a = Layer::Create(LayerSettings());
+  layer_src_root->AddChild(layer_src_a);
+
+  proto::LayerNode root_proto_1;
+  layer_src_root->ToLayerNodeProto(&root_proto_1);
+
+  Layer::LayerIdMap dest_layer_map_1;
+  scoped_refptr<Layer> layer_dest_root = Layer::Create(LayerSettings());
+  layer_dest_root->FromLayerNodeProto(root_proto_1, dest_layer_map_1);
+
+  EXPECT_EQ(layer_src_root->id(), layer_dest_root->id());
+  ASSERT_EQ(1u, layer_dest_root->children().size());
+  scoped_refptr<Layer> layer_dest_a_1 = layer_dest_root->children()[0];
+  EXPECT_EQ(layer_src_a->id(), layer_dest_a_1->id());
+
+  // Setup new destination layer map.
+  Layer::LayerIdMap dest_layer_map_2;
+  dest_layer_map_2[layer_dest_root->id()] = layer_dest_root;
+  dest_layer_map_2[layer_dest_a_1->id()] = layer_dest_a_1;
+
+  // Add Layer |b|.
+  scoped_refptr<Layer> layer_src_b = Layer::Create(LayerSettings());
+  layer_src_root->AddChild(layer_src_b);
+
+  // Second serialization.
+  proto::LayerNode root_proto_2;
+  layer_src_root->ToLayerNodeProto(&root_proto_2);
+
+  // Second deserialization.
+  layer_dest_root->FromLayerNodeProto(root_proto_2, dest_layer_map_2);
+
+  EXPECT_EQ(layer_src_root->id(), layer_dest_root->id());
+  ASSERT_EQ(2u, layer_dest_root->children().size());
+
+  scoped_refptr<Layer> layer_dest_a_2 = layer_dest_root->children()[0];
+  EXPECT_EQ(layer_src_a->id(), layer_dest_a_2->id());
+  EXPECT_EQ(layer_src_root->id(), layer_dest_a_2->parent()->id());
+  EXPECT_EQ(0u, layer_dest_a_2->children().size());
+
+  scoped_refptr<Layer> layer_dest_b_2 = layer_dest_root->children()[1];
+  EXPECT_EQ(layer_src_b->id(), layer_dest_b_2->id());
+  EXPECT_EQ(layer_src_root->id(), layer_dest_b_2->parent()->id());
+  EXPECT_EQ(0u, layer_dest_b_2->children().size());
+
+  // Layer |a| should be the same.
+  EXPECT_EQ(layer_dest_a_1.get(), layer_dest_a_2.get());
+}
+
+TEST_F(LayerTest, DeletingSubtreeDeletesLayers) {
+  /* Testing serialization and deserialization of a tree that initially
+     looks like this:
+          root
+          /  \
+         a    b
+               \
+                c
+                 \
+                  d
+     Then the subtree rooted at node |b| is deleted in the next update.
+  */
+  scoped_refptr<Layer> layer_src_root = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_a = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_b = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_c = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_d = Layer::Create(LayerSettings());
+  layer_src_root->AddChild(layer_src_a);
+  layer_src_root->AddChild(layer_src_b);
+  layer_src_b->AddChild(layer_src_c);
+  layer_src_c->AddChild(layer_src_d);
+
+  // Serialization 1.
+  proto::LayerNode proto1;
+  layer_src_root->ToLayerNodeProto(&proto1);
+
+  // Deserialization 1.
+  Layer::LayerIdMap empty_dest_layer_map;
+  scoped_refptr<Layer> layer_dest_root = Layer::Create(LayerSettings());
+  layer_dest_root->FromLayerNodeProto(proto1, empty_dest_layer_map);
+
+  EXPECT_EQ(layer_src_root->id(), layer_dest_root->id());
+  ASSERT_EQ(2u, layer_dest_root->children().size());
+  scoped_refptr<Layer> layer_dest_a = layer_dest_root->children()[0];
+  scoped_refptr<Layer> layer_dest_b = layer_dest_root->children()[1];
+  ASSERT_EQ(1u, layer_dest_b->children().size());
+  scoped_refptr<Layer> layer_dest_c = layer_dest_b->children()[0];
+  ASSERT_EQ(1u, layer_dest_c->children().size());
+  scoped_refptr<Layer> layer_dest_d = layer_dest_c->children()[0];
+
+  // Delete the Layer |b| subtree.
+  layer_src_b->RemoveAllChildren();
+
+  // Serialization 2.
+  proto::LayerNode proto2;
+  layer_src_root->ToLayerNodeProto(&proto2);
+
+  // Deserialization 2.
+  Layer::LayerIdMap dest_layer_map_2;
+  dest_layer_map_2[layer_dest_root->id()] = layer_dest_root;
+  dest_layer_map_2[layer_dest_a->id()] = layer_dest_a;
+  dest_layer_map_2[layer_dest_b->id()] = layer_dest_b;
+  layer_dest_root->FromLayerNodeProto(proto2, dest_layer_map_2);
+
+  EXPECT_EQ(0u, layer_dest_a->children().size());
+  EXPECT_EQ(0u, layer_dest_b->children().size());
+}
+
+TEST_F(LayerTest, DeleteMaskAndReplicaLayer) {
+  scoped_refptr<Layer> layer_src_root = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_mask = Layer::Create(LayerSettings());
+  scoped_refptr<Layer> layer_src_replica = Layer::Create(LayerSettings());
+  layer_src_root->SetMaskLayer(layer_src_mask.get());
+  layer_src_root->SetReplicaLayer(layer_src_replica.get());
+
+  // Serialization 1.
+  proto::LayerNode proto1;
+  layer_src_root->ToLayerNodeProto(&proto1);
+
+  // Deserialization 1.
+  Layer::LayerIdMap dest_layer_map;
+  scoped_refptr<Layer> layer_dest_root = Layer::Create(LayerSettings());
+  layer_dest_root->FromLayerNodeProto(proto1, dest_layer_map);
+
+  EXPECT_EQ(layer_src_root->id(), layer_dest_root->id());
+  ASSERT_TRUE(layer_dest_root->mask_layer());
+  ASSERT_TRUE(layer_dest_root->replica_layer());
+  EXPECT_EQ(layer_src_root->mask_layer()->id(),
+            layer_dest_root->mask_layer()->id());
+  // TODO(nyquist): Add test for is_mask_ when PictureLayer is supported.
+  EXPECT_EQ(layer_src_root->replica_layer()->id(),
+            layer_dest_root->replica_layer()->id());
+
+  // Store the newly constructed layer structure in the id map.
+  dest_layer_map[layer_dest_root->id()] = layer_dest_root;
+  dest_layer_map[layer_dest_root->mask_layer()->id()] =
+      layer_dest_root->mask_layer();
+  dest_layer_map[layer_dest_root->replica_layer()->id()] =
+      layer_dest_root->replica_layer();
+
+  // Clear mask and replica layers.
+  layer_src_root->mask_layer()->RemoveFromParent();
+  layer_src_root->replica_layer()->RemoveFromParent();
+
+  // Serialization 2.
+  proto::LayerNode proto2;
+  layer_src_root->ToLayerNodeProto(&proto2);
+
+  // Deserialization 2.
+  layer_dest_root->FromLayerNodeProto(proto2, dest_layer_map);
+
+  EXPECT_EQ(nullptr, layer_dest_root->mask_layer());
+  EXPECT_EQ(nullptr, layer_dest_root->replica_layer());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc
index 03425cf5..0a66eea2 100644
--- a/cc/output/direct_renderer.cc
+++ b/cc/output/direct_renderer.cc
@@ -240,7 +240,8 @@
   // otherwise the framebuffer will be missing the overlay contents.
   if (root_render_pass->copy_requests.empty()) {
     overlay_processor_->ProcessForOverlays(
-        resource_provider_, render_passes_in_draw_order, &frame.overlay_list);
+        resource_provider_, render_passes_in_draw_order, &frame.overlay_list,
+        &frame.root_damage_rect);
   }
 
   for (size_t i = 0; i < render_passes_in_draw_order->size(); ++i) {
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 6af531c..92fcd3c 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -2014,10 +2014,11 @@
    public:
     Strategy() {}
     ~Strategy() override {}
-    MOCK_METHOD3(Attempt,
+    MOCK_METHOD4(Attempt,
                  bool(ResourceProvider* resource_provider,
                       RenderPassList* render_passes,
-                      OverlayCandidateList* candidates));
+                      OverlayCandidateList* candidates,
+                      gfx::Rect* damage_rect));
   };
 
   explicit TestOverlayProcessor(OutputSurface* surface)
@@ -2095,7 +2096,7 @@
   // added a fake strategy, so checking for Attempt calls checks if there was
   // any attempt to overlay, which there shouldn't be. We can't use the quad
   // list because the render pass is cleaned up by DrawFrame.
-  EXPECT_CALL(*processor->strategy_, Attempt(_, _, _)).Times(0);
+  EXPECT_CALL(*processor->strategy_, Attempt(_, _, _, _)).Times(0);
   renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, viewport_rect,
                      viewport_rect, false);
   Mock::VerifyAndClearExpectations(processor->strategy_);
@@ -2112,7 +2113,7 @@
                        gfx::PointF(1, 1), SK_ColorTRANSPARENT, vertex_opacity,
                        flipped, nearest_neighbor);
 
-  EXPECT_CALL(*processor->strategy_, Attempt(_, _, _)).Times(1);
+  EXPECT_CALL(*processor->strategy_, Attempt(_, _, _, _)).Times(1);
   renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, viewport_rect,
                      viewport_rect, false);
 }
diff --git a/cc/output/overlay_processor.cc b/cc/output/overlay_processor.cc
index 69368a1..a97623a 100644
--- a/cc/output/overlay_processor.cc
+++ b/cc/output/overlay_processor.cc
@@ -27,10 +27,13 @@
 
 void OverlayProcessor::ProcessForOverlays(ResourceProvider* resource_provider,
                                           RenderPassList* render_passes,
-                                          OverlayCandidateList* candidates) {
+                                          OverlayCandidateList* candidates,
+                                          gfx::Rect* damage_rect) {
   for (auto strategy : strategies_) {
-    if (strategy->Attempt(resource_provider, render_passes, candidates))
+    if (strategy->Attempt(resource_provider, render_passes, candidates,
+                          damage_rect)) {
       return;
+    }
   }
 }
 
diff --git a/cc/output/overlay_processor.h b/cc/output/overlay_processor.h
index 48ffe6b..26bfe16 100644
--- a/cc/output/overlay_processor.h
+++ b/cc/output/overlay_processor.h
@@ -23,10 +23,13 @@
     // Returns false if the strategy cannot be made to work with the
     // current set of render passes. Returns true if the strategy was successful
     // and adds any additional passes necessary to represent overlays to
-    // |render_passes|.
+    // |render_passes|. Strategy can also optimize |damage_rect| as it seems
+    // fit to reduce GL composition, in case |damage_rect| is obscured by
+    // overlays.
     virtual bool Attempt(ResourceProvider* resource_provider,
                          RenderPassList* render_passes,
-                         OverlayCandidateList* candidates) = 0;
+                         OverlayCandidateList* candidates,
+                         gfx::Rect* damage_rect) = 0;
   };
   typedef ScopedPtrVector<Strategy> StrategyList;
 
@@ -37,7 +40,8 @@
 
   void ProcessForOverlays(ResourceProvider* resource_provider,
                           RenderPassList* render_passes,
-                          OverlayCandidateList* candidates);
+                          OverlayCandidateList* candidates,
+                          gfx::Rect* damage_rect);
 
  protected:
   StrategyList strategies_;
diff --git a/cc/output/overlay_strategy_all_or_nothing.cc b/cc/output/overlay_strategy_all_or_nothing.cc
index 40c58cd0..8181e29 100644
--- a/cc/output/overlay_strategy_all_or_nothing.cc
+++ b/cc/output/overlay_strategy_all_or_nothing.cc
@@ -19,7 +19,8 @@
 
 bool OverlayStrategyAllOrNothing::Attempt(ResourceProvider* resource_provider,
                                           RenderPassList* render_passes,
-                                          OverlayCandidateList* candidates) {
+                                          OverlayCandidateList* candidates,
+                                          gfx::Rect* damage_rect) {
   QuadList& quad_list = render_passes->back()->quad_list;
   OverlayCandidateList new_candidates;
   int next_z_order = -1;
diff --git a/cc/output/overlay_strategy_all_or_nothing.h b/cc/output/overlay_strategy_all_or_nothing.h
index 94d88f03..23d2aa3 100644
--- a/cc/output/overlay_strategy_all_or_nothing.h
+++ b/cc/output/overlay_strategy_all_or_nothing.h
@@ -22,7 +22,8 @@
 
   bool Attempt(ResourceProvider* resource_provider,
                RenderPassList* render_passes,
-               OverlayCandidateList* candidate_list) override;
+               OverlayCandidateList* candidate_list,
+               gfx::Rect* damage_rect) override;
 
  private:
   OverlayCandidateValidator* capability_checker_;  // Weak.
diff --git a/cc/output/overlay_strategy_sandwich.cc b/cc/output/overlay_strategy_sandwich.cc
index 79279adb..cacb696 100644
--- a/cc/output/overlay_strategy_sandwich.cc
+++ b/cc/output/overlay_strategy_sandwich.cc
@@ -42,7 +42,8 @@
 
 bool OverlayStrategySandwich::Attempt(ResourceProvider* resource_provider,
                                       RenderPassList* render_passes,
-                                      OverlayCandidateList* candidate_list) {
+                                      OverlayCandidateList* candidate_list,
+                                      gfx::Rect* damage_rect) {
   QuadList& quad_list = render_passes->back()->quad_list;
   for (auto it = quad_list.begin(); it != quad_list.end();) {
     OverlayCandidate candidate;
diff --git a/cc/output/overlay_strategy_sandwich.h b/cc/output/overlay_strategy_sandwich.h
index 076ea9de..0bdd2d2 100644
--- a/cc/output/overlay_strategy_sandwich.h
+++ b/cc/output/overlay_strategy_sandwich.h
@@ -23,7 +23,8 @@
 
   bool Attempt(ResourceProvider* resource_provider,
                RenderPassList* render_passes,
-               OverlayCandidateList* candidate_list) override;
+               OverlayCandidateList* candidate_list,
+               gfx::Rect* damage_rect) override;
 
  private:
   QuadList::Iterator TryOverlay(RenderPass* render_pass,
diff --git a/cc/output/overlay_strategy_single_on_top.cc b/cc/output/overlay_strategy_single_on_top.cc
index ca254b2..7a35d1d 100644
--- a/cc/output/overlay_strategy_single_on_top.cc
+++ b/cc/output/overlay_strategy_single_on_top.cc
@@ -7,6 +7,7 @@
 #include "cc/base/math_util.h"
 #include "cc/output/overlay_candidate_validator.h"
 #include "cc/quads/draw_quad.h"
+#include "ui/gfx/geometry/rect_conversions.h"
 
 namespace cc {
 
@@ -20,12 +21,13 @@
 
 bool OverlayStrategySingleOnTop::Attempt(ResourceProvider* resource_provider,
                                          RenderPassList* render_passes,
-                                         OverlayCandidateList* candidate_list) {
+                                         OverlayCandidateList* candidate_list,
+                                         gfx::Rect* damage_rect) {
   QuadList* quad_list = &render_passes->back()->quad_list;
   for (auto it = quad_list->begin(); it != quad_list->end(); ++it) {
     OverlayCandidate candidate;
     if (OverlayCandidate::FromDrawQuad(resource_provider, *it, &candidate) &&
-        TryOverlay(quad_list, candidate_list, candidate, it)) {
+        TryOverlay(quad_list, candidate_list, candidate, it, damage_rect)) {
       return true;
     }
   }
@@ -37,7 +39,8 @@
     QuadList* quad_list,
     OverlayCandidateList* candidate_list,
     const OverlayCandidate& candidate,
-    QuadList::Iterator candidate_iterator) {
+    QuadList::Iterator candidate_iterator,
+    gfx::Rect* damage_rect) {
   // Check that no prior quads overlap it.
   for (auto overlap_iter = quad_list->cbegin();
        overlap_iter != candidate_iterator; ++overlap_iter) {
@@ -57,10 +60,12 @@
   // Check for support.
   capability_checker_->CheckOverlaySupport(&new_candidate_list);
 
+  const OverlayCandidate& overlay_candidate = new_candidate_list.back();
   // If the candidate can be handled by an overlay, create a pass for it.
-  if (new_candidate_list.back().overlay_handled) {
+  if (overlay_candidate.overlay_handled) {
     quad_list->EraseAndInvalidateAllPointers(candidate_iterator);
     candidate_list->swap(new_candidate_list);
+    damage_rect->Subtract(ToEnclosedRect(overlay_candidate.display_rect));
     return true;
   }
 
diff --git a/cc/output/overlay_strategy_single_on_top.h b/cc/output/overlay_strategy_single_on_top.h
index bdf2cc2f..29d98de7 100644
--- a/cc/output/overlay_strategy_single_on_top.h
+++ b/cc/output/overlay_strategy_single_on_top.h
@@ -19,13 +19,15 @@
 
   bool Attempt(ResourceProvider* resource_provider,
                RenderPassList* render_passes,
-               OverlayCandidateList* candidate_list) override;
+               OverlayCandidateList* candidate_list,
+               gfx::Rect* damage_rect) override;
 
  private:
   bool TryOverlay(QuadList* quad_list,
                   OverlayCandidateList* candidate_list,
                   const OverlayCandidate& candidate,
-                  QuadList::Iterator candidate_iterator);
+                  QuadList::Iterator candidate_iterator,
+                  gfx::Rect* damage_rect);
 
   OverlayCandidateValidator* capability_checker_;  // Weak.
 
diff --git a/cc/output/overlay_strategy_underlay.cc b/cc/output/overlay_strategy_underlay.cc
index 9a8a3628..5f3f907 100644
--- a/cc/output/overlay_strategy_underlay.cc
+++ b/cc/output/overlay_strategy_underlay.cc
@@ -20,7 +20,8 @@
 
 bool OverlayStrategyUnderlay::Attempt(ResourceProvider* resource_provider,
                                       RenderPassList* render_passes,
-                                      OverlayCandidateList* candidate_list) {
+                                      OverlayCandidateList* candidate_list,
+                                      gfx::Rect* damage_rect) {
   QuadList& quad_list = render_passes->back()->quad_list;
   for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
     OverlayCandidate candidate;
diff --git a/cc/output/overlay_strategy_underlay.h b/cc/output/overlay_strategy_underlay.h
index f276c1c..ac20051 100644
--- a/cc/output/overlay_strategy_underlay.h
+++ b/cc/output/overlay_strategy_underlay.h
@@ -24,7 +24,8 @@
 
   bool Attempt(ResourceProvider* resource_provider,
                RenderPassList* render_passes,
-               OverlayCandidateList* candidate_list) override;
+               OverlayCandidateList* candidate_list,
+               gfx::Rect* damage_rect) override;
 
  private:
   OverlayCandidateValidator* capability_checker_;  // Weak.
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index 824b7fe..8c9efc75 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -364,6 +364,7 @@
   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
   scoped_ptr<ResourceProvider> resource_provider_;
   scoped_ptr<OverlayProcessor> overlay_processor_;
+  gfx::Rect damage_rect_;
 };
 
 typedef OverlayTest<SingleOnTopOverlayValidator> SingleOverlayOnTopTest;
@@ -417,7 +418,7 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
 
   ASSERT_EQ(1U, pass_list.size());
   ASSERT_EQ(1U, candidate_list.size());
@@ -459,7 +460,7 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
 
   // Ensure that the display and uv rects have cropping applied to them.
   ASSERT_EQ(1U, pass_list.size());
@@ -488,7 +489,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
 
   // Both candidates should become overlays.
   EXPECT_EQ(1u, pass_list.size());
@@ -522,7 +523,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
 
   // Only one of the candidates should become an overlay.
   EXPECT_EQ(1u, pass_list.size());
@@ -557,8 +558,7 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
-
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   ASSERT_EQ(2U, candidate_list.size());
 
@@ -613,7 +613,7 @@
   OverlayCandidateList candidate_list;
   EXPECT_EQ(4U, main_pass->quad_list.size());
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   ASSERT_EQ(3U, candidate_list.size());
 
@@ -645,6 +645,39 @@
   DCHECK(covered_region == overlay_region);
 }
 
+TEST_F(SandwichTest, DamageRect) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateQuad(resource_provider_.get(),
+                                pass->shared_quad_state_list.back(),
+                                pass.get());
+
+  damage_rect_ = kOverlayRect;
+
+  // Add something behind it.
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  // Check for potential candidates.
+  OverlayCandidateList candidate_list;
+
+  // Primary plane.
+  OverlayCandidate output_surface_plane;
+  output_surface_plane.display_rect = gfx::RectF(kOverlayRect);
+  output_surface_plane.quad_rect_in_target_space = kOverlayRect;
+  output_surface_plane.use_output_surface_for_resource = true;
+  output_surface_plane.overlay_handled = true;
+  candidate_list.push_back(output_surface_plane);
+
+  overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
+                                         &candidate_list, &damage_rect_);
+  DCHECK(!damage_rect_.IsEmpty());
+}
+
 TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) {
   scoped_ptr<RenderPass> pass = CreateRenderPass();
   TextureDrawQuad* original_quad =
@@ -665,7 +698,7 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
 
   ASSERT_EQ(1U, pass_list.size());
   ASSERT_EQ(1U, candidate_list.size());
@@ -684,6 +717,38 @@
   EXPECT_EQ(original_resource_id, candidate_list.back().resource_id);
 }
 
+TEST_F(SingleOverlayOnTopTest, DamageRect) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateQuad(resource_provider_.get(),
+                                pass->shared_quad_state_list.back(),
+                                pass.get());
+  damage_rect_ = kOverlayRect;
+
+  // Add something behind it.
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  // Check for potential candidates.
+  OverlayCandidateList candidate_list;
+
+  // Primary plane.
+  OverlayCandidate output_surface_plane;
+  output_surface_plane.display_rect = gfx::RectF(kOverlayRect);
+  output_surface_plane.quad_rect_in_target_space = kOverlayRect;
+  output_surface_plane.use_output_surface_for_resource = true;
+  output_surface_plane.overlay_handled = true;
+  candidate_list.push_back(output_surface_plane);
+
+  overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
+                                         &candidate_list, &damage_rect_);
+  DCHECK(damage_rect_.IsEmpty());
+}
+
 TEST_F(SingleOverlayOnTopTest, NoCandidates) {
   scoped_ptr<RenderPass> pass = CreateRenderPass();
   CreateFullscreenOpaqueQuad(resource_provider_.get(),
@@ -699,7 +764,7 @@
 
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(0U, candidate_list.size());
   // There should be nothing new here.
   CompareRenderPassLists(pass_list, original_pass_list);
@@ -724,7 +789,7 @@
 
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(0U, candidate_list.size());
   // There should be nothing new here.
   CompareRenderPassLists(pass_list, original_pass_list);
@@ -754,7 +819,7 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(1U, candidate_list.size());
 
   // This should be the same.
@@ -773,7 +838,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(1U, pass_list.size());
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -790,7 +855,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -807,7 +872,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -823,7 +888,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -839,7 +904,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -856,7 +921,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -873,7 +938,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -892,7 +957,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL,
@@ -913,7 +978,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL,
@@ -933,7 +998,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -951,7 +1016,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_90, candidate_list.back().transform);
@@ -970,7 +1035,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_180, candidate_list.back().transform);
@@ -989,7 +1054,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_270, candidate_list.back().transform);
@@ -1013,7 +1078,7 @@
 
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(1U, pass_list.size());
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1037,7 +1102,7 @@
 
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(1U, pass_list.size());
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1059,7 +1124,7 @@
 
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(1U, pass_list.size());
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1083,7 +1148,7 @@
 
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(1U, pass_list.size());
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1105,7 +1170,7 @@
 
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(1U, pass_list.size());
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1120,7 +1185,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1135,7 +1200,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1150,7 +1215,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1165,7 +1230,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1180,7 +1245,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   ASSERT_EQ(1U, pass_list.size());
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1198,7 +1263,7 @@
 
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(1U, pass_list.size());
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(-1, candidate_list[0].plane_z_order);
@@ -1221,7 +1286,7 @@
 
   OverlayCandidateList candidate_list;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidate_list);
+                                         &candidate_list, &damage_rect_);
   EXPECT_EQ(1U, pass_list.size());
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(-1, candidate_list[0].plane_z_order);
@@ -1229,6 +1294,39 @@
   EXPECT_EQ(pass_list[0]->quad_list.front()->material, DrawQuad::SOLID_COLOR);
 }
 
+TEST_F(UnderlayTest, DamageRect) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateQuad(resource_provider_.get(),
+                                pass->shared_quad_state_list.back(),
+                                pass.get());
+
+  damage_rect_ = kOverlayRect;
+
+  // Add something behind it.
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  // Check for potential candidates.
+  OverlayCandidateList candidate_list;
+
+  // Primary plane.
+  OverlayCandidate output_surface_plane;
+  output_surface_plane.display_rect = gfx::RectF(kOverlayRect);
+  output_surface_plane.quad_rect_in_target_space = kOverlayRect;
+  output_surface_plane.use_output_surface_for_resource = true;
+  output_surface_plane.overlay_handled = true;
+  candidate_list.push_back(output_surface_plane);
+
+  overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
+                                         &candidate_list, &damage_rect_);
+  DCHECK(!damage_rect_.IsEmpty());
+}
+
 TEST_F(AllOrNothingOverlayTest, SuccessfulOverlappingOverlays) {
   scoped_ptr<RenderPass> pass = CreateRenderPass();
 
@@ -1244,7 +1342,7 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidates;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidates);
+                                         &candidates, &damage_rect_);
 
   // Both quads should become overlays.
   EXPECT_EQ(2u, candidates.size());
@@ -1275,13 +1373,46 @@
   pass_list.push_back(pass.Pass());
   OverlayCandidateList candidates;
   overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
-                                         &candidates);
+                                         &candidates, &damage_rect_);
 
   // No quads should become overlays.
   EXPECT_EQ(0u, candidates.size());
   EXPECT_EQ(2u, pass_list.back()->quad_list.size());
 }
 
+TEST_F(AllOrNothingOverlayTest, DamageRect) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateQuad(resource_provider_.get(),
+                                pass->shared_quad_state_list.back(),
+                                pass.get());
+
+  damage_rect_ = kOverlayRect;
+
+  // Add something behind it.
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  // Check for potential candidates.
+  OverlayCandidateList candidate_list;
+
+  // Primary plane.
+  OverlayCandidate output_surface_plane;
+  output_surface_plane.display_rect = gfx::RectF(kOverlayRect);
+  output_surface_plane.quad_rect_in_target_space = kOverlayRect;
+  output_surface_plane.use_output_surface_for_resource = true;
+  output_surface_plane.overlay_handled = true;
+  candidate_list.push_back(output_surface_plane);
+
+  overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list,
+                                         &candidate_list, &damage_rect_);
+  DCHECK(!damage_rect_.IsEmpty());
+}
+
 class OverlayInfoRendererGL : public GLRenderer {
  public:
   OverlayInfoRendererGL(RendererClient* client,
@@ -1312,7 +1443,7 @@
     }
 
     ASSERT_EQ(2U, frame->overlay_list.size());
-    EXPECT_NE(0U, frame->overlay_list.back().resource_id);
+    EXPECT_GE(frame->overlay_list.back().resource_id, 0U);
   }
 
   void set_expect_overlays(bool expect_overlays) {
@@ -1383,10 +1514,9 @@
 
   scoped_ptr<RenderPass> pass = CreateRenderPass();
 
-  CreateFullscreenCandidateQuad(resource_provider_.get(),
-                                pass->shared_quad_state_list.back(),
-                                pass.get());
-
+  CreateCandidateQuadAt(resource_provider_.get(),
+                        pass->shared_quad_state_list.back(), pass.get(),
+                        kOverlayBottomRightRect);
   CreateFullscreenOpaqueQuad(resource_provider_.get(),
                              pass->shared_quad_state_list.back(), pass.get());
   CreateFullscreenOpaqueQuad(resource_provider_.get(),
@@ -1402,9 +1532,9 @@
               Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, _,
                        gfx::Rect(kDisplaySize), gfx::RectF(0, 0, 1, 1)))
       .Times(1);
-  EXPECT_CALL(scheduler_,
-              Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _, kOverlayRect,
-                       BoundingRect(kUVTopLeft, kUVBottomRight)))
+  EXPECT_CALL(scheduler_, Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _,
+                                   kOverlayBottomRightRect,
+                                   BoundingRect(kUVTopLeft, kUVBottomRight)))
       .Times(1);
   renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
 
diff --git a/cc/proto/BUILD.gn b/cc/proto/BUILD.gn
index dcd4214..31d3cd5 100644
--- a/cc/proto/BUILD.gn
+++ b/cc/proto/BUILD.gn
@@ -30,6 +30,7 @@
     # TODO(dtrainor): Move protos to their correct packages once it's possible
     # to include protos from other directories/targets (crbug.com/542423).
     "display_item.proto",
+    "layer.proto",
     "point.proto",
     "pointf.proto",
     "rect.proto",
diff --git a/cc/proto/layer.proto b/cc/proto/layer.proto
new file mode 100644
index 0000000..74a243b4f
--- /dev/null
+++ b/cc/proto/layer.proto
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+package cc.proto;
+
+option optimize_for = LITE_RUNTIME;
+
+// Identifies the type of cc:Layer a LayerNode represents. It is used to
+// facilitate reconstruction of a Layer of the correct type on the client.
+enum LayerType {
+  Base = 1;
+
+  // TODO(nyquist): Add the rest of the necessary LayerTypes.
+};
+
+// Hierarchical structure for serializing the Layer tree.
+message LayerNode {
+  // required
+  optional int32 id = 1;
+  // required
+  optional LayerType type = 2;
+  optional int32 parent_id = 3;
+  // A List of all the children of the current LayerNode.
+  repeated LayerNode children = 4;
+  optional LayerNode mask_layer = 5;
+  optional LayerNode replica_layer = 6;
+}
diff --git a/cc/quads/draw_polygon.cc b/cc/quads/draw_polygon.cc
index 9ff1af6..02c12838 100644
--- a/cc/quads/draw_polygon.cc
+++ b/cc/quads/draw_polygon.cc
@@ -16,7 +16,7 @@
 // This threshold controls how "thick" a plane is. If a point's distance is
 // <= |compare_threshold|, then it is considered on the plane. Only when this
 // boundary is crossed do we consider doing splitting.
-static const float compare_threshold = 1.0f;
+static const float compare_threshold = 0.1f;
 // |split_threshold| is lower in this case because we want the points created
 // during splitting to be well within the range of |compare_threshold| for
 // comparison purposes. The splitting operation will produce intersection points
@@ -27,7 +27,7 @@
 // this range.
 // This is really supposd to be compare_threshold / 2.0f, but that would
 // create another static initializer.
-static const float split_threshold = 0.5f;
+static const float split_threshold = 0.05f;
 
 static const float normalized_threshold = 0.001f;
 }  // namespace
diff --git a/cc/quads/draw_polygon_unittest.cc b/cc/quads/draw_polygon_unittest.cc
index 517e131..caf0f27 100644
--- a/cc/quads/draw_polygon_unittest.cc
+++ b/cc/quads/draw_polygon_unittest.cc
@@ -32,6 +32,27 @@
   }
 }
 
+// Two quads are nearly touching but definitely ordered. Second one should
+// compare in front.
+TEST(DrawPolygonSplitTest, NearlyTouchingOrder) {
+  std::vector<gfx::Point3F> vertices_a;
+  vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f));
+  vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f));
+  vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f));
+  vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f));
+  std::vector<gfx::Point3F> vertices_b;
+  vertices_b.push_back(gfx::Point3F(0.0f, 10.0f, -1.0f));
+  vertices_b.push_back(gfx::Point3F(0.0f, 0.0f, -1.0f));
+  vertices_b.push_back(gfx::Point3F(10.0f, 0.0f, -1.0f));
+  vertices_b.push_back(gfx::Point3F(10.0f, 10.0f, -1.0f));
+  gfx::Vector3dF normal(0.0f, 0.0f, 1.0f);
+
+  CREATE_NEW_DRAW_POLYGON(polygon_a, vertices_a, normal, 0);
+  CREATE_NEW_DRAW_POLYGON(polygon_b, vertices_b, normal, 1);
+
+  EXPECT_EQ(BSP_BACK, DrawPolygon::SideCompare(polygon_b, polygon_a));
+}
+
 // Two quads are definitely not touching and so no split should occur.
 TEST(DrawPolygonSplitTest, NotTouchingNoSplit) {
   std::vector<gfx::Point3F> vertices_a;
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index 1f59140..5ada4f000 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -39,6 +39,13 @@
     const TransformNode* transform_node =
         transform_tree.Node(layer->transform_tree_index());
     if (!is_unclipped && !fully_visible) {
+      // The entire layer is visible if it has copy requests.
+      if (layer->HasCopyRequest()) {
+        layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds));
+        layer->set_clip_rect_in_target_space_from_property_trees(gfx::Rect());
+        continue;
+      }
+
       const TransformNode* target_node =
           non_root_surfaces_enabled
               ? transform_tree.Node(transform_node->data.content_target_id)
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index 4d14ff7..649f6c2 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -489,6 +489,10 @@
       layer->drawable_content_rect().IsEmpty())
     return gfx::Rect();
 
+  // The layer is fully visible if it has copy requests.
+  if (layer->HasCopyRequest())
+    return gfx::Rect(layer->bounds());
+
   // Compute visible bounds in target surface space.
   gfx::Rect visible_rect_in_target_surface_space =
       layer->drawable_content_rect();
@@ -2050,8 +2054,8 @@
     gfx::Rect clipped_content_rect = local_drawable_content_rect_of_subtree;
 
     // Don't clip if the layer is reflected as the reflection shouldn't be
-    // clipped.
-    if (!layer->replica_layer()) {
+    // clipped. Also, don't clip if the layer has copy requests.
+    if (!layer->replica_layer() && !layer->HasCopyRequest()) {
       // Note, it is correct to use data_from_ancestor.ancestor_clips_subtree
       // here, because we are looking at this layer's render_surface, not the
       // layer itself.
@@ -2596,7 +2600,8 @@
         if (layer->DrawsContent())
           surface_content_rect.Union(layer->drawable_content_rect());
 
-        if (!layer->replica_layer() && layer->render_surface()->is_clipped()) {
+        if (!layer->replica_layer() && !layer->HasCopyRequest() &&
+            layer->render_surface()->is_clipped()) {
           // Here, we clip the render surface's content rect with its clip rect.
           // As the clip rect of render surface is in the surface's target
           // space, we first map the content rect into the target space,
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index 2ea5b2ad..e42460d 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -5449,13 +5449,13 @@
   inputs.can_adjust_raster_scales = true;
   LayerTreeHostCommon::CalculateDrawProperties(&inputs);
 
-  // We should have one render surface, as the others are clipped out.
-  ASSERT_EQ(1u, render_surface_layer_list.size());
+  // We should have two render surface, as the others are clipped out.
+  ASSERT_EQ(2u, render_surface_layer_list.size());
   EXPECT_EQ(root->id(), render_surface_layer_list.at(0)->id());
 
-  // The root render surface should only have 1 contributing layer, since the
+  // The root render surface should only have 2 contributing layer, since the
   // other layers are empty/clipped away.
-  ASSERT_EQ(1u, root->render_surface()->layer_list().size());
+  ASSERT_EQ(2u, root->render_surface()->layer_list().size());
   EXPECT_EQ(root->id(), root->render_surface()->layer_list().at(0)->id());
 }
 
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc
index 802a014..0ddc7b7 100644
--- a/cc/trees/layer_tree_host_unittest_copyrequest.cc
+++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -473,10 +473,10 @@
   }
 
   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
-    // We should still get a callback with no output if the copy requested layer
-    // was completely clipped away.
+    // We should still get the content even if the copy requested layer was
+    // completely clipped away.
     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
-    EXPECT_EQ(gfx::Size().ToString(), result->size().ToString());
+    EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString());
     EndTest();
   }
 
diff --git a/chrome/android/java/res/layout/physical_web_list_item_nearby_url.xml b/chrome/android/java/res/layout/physical_web_list_item_nearby_url.xml
index e4311e9..4eec849 100644
--- a/chrome/android/java/res/layout/physical_web_list_item_nearby_url.xml
+++ b/chrome/android/java/res/layout/physical_web_list_item_nearby_url.xml
@@ -4,26 +4,29 @@
      found in the LICENSE file. -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:padding="18dp"
+    android:paddingTop="16dp"
+    android:paddingBottom="20dp"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
     <ImageView
         android:id="@+id/nearby_urls_icon"
-        android:layout_width="24dp"
-        android:layout_height="24dp"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
         android:layout_marginTop="6dp"
         android:layout_alignParentTop="true"
-        android:layout_alignParentEnd="true"
+        android:layout_alignParentStart="true"
         android:contentDescription="@null">
     </ImageView>
     <TextView
         android:id="@+id/nearby_urls_title"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_marginStart="66dp"
         android:layout_alignParentTop="true"
-        android:layout_toStartOf="@id/nearby_urls_icon"
         android:layout_alignParentStart="true"
-        android:textSize="20sp"
+        android:textSize="16sp"
         android:textColor="@color/nearby_urls_header_color"
         android:singleLine="true"
         android:ellipsize="end">
@@ -32,11 +35,11 @@
         android:id="@+id/nearby_urls_url"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_marginStart="66dp"
         android:layout_below="@id/nearby_urls_title"
-        android:layout_toStartOf="@id/nearby_urls_icon"
         android:layout_alignParentStart="true"
         android:textSize="14sp"
-        android:textColor="@color/nearby_urls_url_color"
+        android:textColor="@color/nearby_urls_subheader_color"
         android:singleLine="true"
         android:ellipsize="end">
     </TextView>
@@ -44,10 +47,11 @@
         android:id="@+id/nearby_urls_description"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_marginStart="66dp"
         android:layout_below="@id/nearby_urls_url"
         android:layout_alignParentStart="true"
         android:textSize="14sp"
-        android:textColor="@color/nearby_urls_description_color"
+        android:textColor="@color/nearby_urls_subheader_color"
         android:lines="2"
         android:ellipsize="end"
         android:lineSpacingExtra="1.5dp">
diff --git a/chrome/android/java/res/layout/physical_web_list_urls_activity.xml b/chrome/android/java/res/layout/physical_web_list_urls_activity.xml
index a57e8c7..09ba4c4 100644
--- a/chrome/android/java/res/layout/physical_web_list_urls_activity.xml
+++ b/chrome/android/java/res/layout/physical_web_list_urls_activity.xml
@@ -3,16 +3,25 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<LinearLayout
+<RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
     <ListView
         android:id="@android:id/list"
         android:layout_height="match_parent"
-        android:layout_width="match_parent">
-    </ListView>
+        android:layout_width="match_parent"
+        android:divider="@null"/>
+    <TextView
+        android:id="@android:id/empty"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:text="@string/physical_web_empty_list_scanning"
+        android:textSize="16sp"
+        android:textColor="@color/physical_web_no_urls_text_color"
+        android:layout_alignParentBottom="true"
+        android:layout_marginBottom="260dp"
+        android:layout_centerHorizontal="true"/>
 
-</LinearLayout>
+</RelativeLayout>
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml
index 9cd38408..c2086d8 100644
--- a/chrome/android/java/res/values-v17/styles.xml
+++ b/chrome/android/java/res/values-v17/styles.xml
@@ -449,8 +449,10 @@
     </style>
 
     <!-- Physical Web styles -->
-    <style name="PhysicalWebNearbyUrlsListStyle">
+    <style name="PhysicalWebNearbyUrlsListStyle" parent="Theme.AppCompat.Light">
         <item name="android:windowBackground">@color/nearby_urls_background_color</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">match_parent</item>
     </style>
 
     <!-- Misc styles -->
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index 9a3aff5..0fab231 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -161,9 +161,9 @@
     <color name="smart_lock_auto_signin_snackbar_background_color">#2196F3</color>
 
     <!-- Physical Web Nearby URLs colors -->
-    <color name="nearby_urls_header_color">#1c47c1</color>
-    <color name="nearby_urls_url_color">#099f39</color>
-    <color name="nearby_urls_description_color">#545454</color>
+    <color name="nearby_urls_header_color">#444</color>
+    <color name="nearby_urls_subheader_color">#777</color>
     <color name="nearby_urls_background_color">#fff</color>
+    <color name="physical_web_no_urls_text_color">#5a5a5a</color>
 
 </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index e71c16e..db8abd8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -70,6 +70,7 @@
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager.ContextualSearchTabPromotionDelegate;
+import org.chromium.chrome.browser.datausage.DataUseTabUIManager;
 import org.chromium.chrome.browser.device.DeviceClassManager;
 import org.chromium.chrome.browser.dom_distiller.DistilledPagePrefsView;
 import org.chromium.chrome.browser.dom_distiller.ReaderModeActivityDelegate;
@@ -96,6 +97,7 @@
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.printing.TabPrinter;
 import org.chromium.chrome.browser.share.ShareHelper;
+import org.chromium.chrome.browser.snackbar.DataUseSnackbarController;
 import org.chromium.chrome.browser.snackbar.LoFiBarPopupController;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable;
@@ -204,6 +206,7 @@
     private ReaderModeActivityDelegate mReaderModeActivityDelegate;
     private SnackbarManager mSnackbarManager;
     private LoFiBarPopupController mLoFiBarPopupController;
+    private DataUseSnackbarController mDataUseSnackbarController;
     private ChromeAppMenuPropertiesDelegate mAppMenuPropertiesDelegate;
     private AppMenuHandler mAppMenuHandler;
     private ToolbarManager mToolbarManager;
@@ -253,6 +256,7 @@
         mWindowAndroid.restoreInstanceState(getSavedInstanceState());
         mSnackbarManager = new SnackbarManager(getWindow());
         mLoFiBarPopupController = new LoFiBarPopupController(this, getSnackbarManager());
+        mDataUseSnackbarController = new DataUseSnackbarController(this, getSnackbarManager());
 
         mAssistStatusHandler = createAssistStatusHandler();
         if (mAssistStatusHandler != null) {
@@ -454,6 +458,17 @@
         if (mTabModelSelectorTabObserver != null) mTabModelSelectorTabObserver.destroy();
         mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(tabModelSelector) {
             @Override
+            public void onPageLoadStarted(Tab tab, String url) {
+                if (DataUseTabUIManager.hasDataUseTrackingStarted(tab)) {
+                    mDataUseSnackbarController.showDataUseTrackingStartedBar();
+                }
+
+                if (DataUseTabUIManager.hasDataUseTrackingEnded(tab)) {
+                    mDataUseSnackbarController.showDataUseTrackingEndedBar();
+                }
+            }
+
+            @Override
             public void didFirstVisuallyNonEmptyPaint(Tab tab) {
                 if (!tab.isNativePage() && !tab.isIncognito()
                         && DataReductionProxySettings.getInstance().wasLoFiModeActiveOnMainFrame()
@@ -482,11 +497,13 @@
             @Override
             public void onHidden(Tab tab) {
                 mLoFiBarPopupController.dismissLoFiBar();
+                mDataUseSnackbarController.dismissDataUseBar();
             }
 
             @Override
             public void onDestroyed(Tab tab) {
                 mLoFiBarPopupController.dismissLoFiBar();
+                mDataUseSnackbarController.dismissDataUseBar();
             }
 
             @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datausage/DataUseTabUIManager.java b/chrome/android/java/src/org/chromium/chrome/browser/datausage/DataUseTabUIManager.java
new file mode 100644
index 0000000..a19d99f
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/datausage/DataUseTabUIManager.java
@@ -0,0 +1,40 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.datausage;
+
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.sessions.SessionTabHelper;
+import org.chromium.chrome.browser.tab.Tab;
+
+/**
+ * Entry point to manage all UI details for measuring data use within a Tab.
+ */
+public class DataUseTabUIManager {
+
+    /**
+     * Returns true if data use tracking has started within a Tab.
+     *
+     * @param tab The tab to see if tracking has started in.
+     * @return If data use tracking has started.
+     */
+    public static boolean hasDataUseTrackingStarted(Tab tab) {
+        return nativeHasDataUseTrackingStarted(
+                SessionTabHelper.sessionIdForTab(tab.getWebContents()), tab.getProfile());
+    }
+
+    /**
+     * Returns true if data use tracking has ended within a Tab.
+     *
+     * @param tab The tab to see if tracking has ended in.
+     * @return If data use tracking has ended.
+     */
+    public static boolean hasDataUseTrackingEnded(Tab tab) {
+        return nativeHasDataUseTrackingEnded(
+                SessionTabHelper.sessionIdForTab(tab.getWebContents()), tab.getProfile());
+    }
+
+    private static native boolean nativeHasDataUseTrackingStarted(int tabId, Profile profile);
+    private static native boolean nativeHasDataUseTrackingEnded(int tabId, Profile profile);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
index f8e16113..bb36d375 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
@@ -31,6 +31,7 @@
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable;
 import org.chromium.components.bookmarks.BookmarkId;
+import org.chromium.components.variations.VariationsAssociatedData;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
@@ -49,6 +50,8 @@
 public class EnhancedBookmarkManager implements EnhancedBookmarkDelegate {
     private static final String PREF_LAST_USED_URL = "enhanced_bookmark_last_used_url";
     private static final int FAVICON_MAX_CACHE_SIZE_BYTES = 10 * 1024 * 1024; // 10MB
+    private static final String FIELD_TRIAL_NAME = "EnhancedBookmarks";
+    private static final String DEFAULT_FOLDER = "default_folder";
 
     private Activity mActivity;
     private ViewGroup mMainView;
@@ -542,7 +545,14 @@
             state.mUrl = url;
 
             if (url.equals(UrlConstants.BOOKMARKS_URL)) {
-                state.mState = STATE_ALL_BOOKMARKS;
+                if (VariationsAssociatedData
+                        .getVariationParamValue(FIELD_TRIAL_NAME, DEFAULT_FOLDER)
+                        .equals("mobile")) {
+                    state.mFolder = bookmarkModel.getMobileFolderId();
+                    state.mState = STATE_FOLDER;
+                } else {
+                    state.mState = STATE_ALL_BOOKMARKS;
+                }
             } else if (url.startsWith(UrlConstants.BOOKMARKS_FOLDER_URL)) {
                 String suffix = decodeSuffix(url, UrlConstants.BOOKMARKS_FOLDER_URL);
                 if (!suffix.isEmpty()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateAlwaysPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateAlwaysPanel.java
index 506211f..700ecd6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateAlwaysPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateAlwaysPanel.java
@@ -48,7 +48,7 @@
      */
     static InfoBarControlLayout createAlwaysToggle(Context context, TranslateOptions options) {
         InfoBarControlLayout controlLayout = new InfoBarControlLayout(context);
-        controlLayout.addSwitch(-1,
+        controlLayout.addSwitch(0,
                 context.getString(R.string.translate_always_text, options.sourceLanguage()),
                 R.id.translate_infobar_always_toggle,
                 options.alwaysTranslateLanguageState());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivity.java
index 4a1b0bc9..f20dff2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivity.java
@@ -4,14 +4,17 @@
 
 package org.chromium.chrome.browser.physicalweb;
 
-import android.app.ListActivity;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.SystemClock;
+import android.support.v7.app.AppCompatActivity;
 import android.view.View;
+import android.widget.AdapterView;
 import android.widget.ListView;
+import android.widget.TextView;
 
 import org.chromium.chrome.R;
 
@@ -22,10 +25,15 @@
  * This activity displays a list of nearby URLs as stored in the {@link UrlManager}.
  * This activity does not and should not rely directly or indirectly on the native library.
  */
-public class ListUrlsActivity extends ListActivity {
+public class ListUrlsActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
     private static final String TAG = "PhysicalWeb";
+    private static final long SCAN_TIMEOUT_MILLIS = 5000; // 5 seconds
     private NearbyUrlsAdapter mAdapter;
     private PwsClient mPwsClient;
+    private Handler mTimerHandler;
+    private Runnable mTimerCallback;
+    private ListView mListView;
+    private TextView mEmptyView;
     private boolean mDisplayRecorded;
 
     @Override
@@ -34,7 +42,12 @@
         setContentView(R.layout.physical_web_list_urls_activity);
 
         mAdapter = new NearbyUrlsAdapter(this);
-        setListAdapter(mAdapter);
+
+        mListView = (ListView) findViewById(android.R.id.list);
+        mEmptyView = (TextView) findViewById(android.R.id.empty);
+        mListView.setEmptyView(mEmptyView);
+        mListView.setAdapter(mAdapter);
+        mListView.setOnItemClickListener(this);
 
         mPwsClient = new PwsClient();
         int referer = getIntent().getIntExtra(UrlManager.REFERER_KEY, 0);
@@ -43,6 +56,14 @@
             PhysicalWebUma.onNotificationPressed();
         }
         mDisplayRecorded = false;
+
+        mTimerHandler = new Handler();
+        mTimerCallback = new Runnable() {
+            @Override
+            public void run() {
+                updateEmptyListMessage(false);
+            }
+        };
     }
 
     @Override
@@ -80,17 +101,23 @@
                 }
             }
         });
+
+        // Nearby doesn't tell us when it's finished but it usually only
+        // takes a few seconds.
+        updateEmptyListMessage(true);
+        mTimerHandler.removeCallbacks(mTimerCallback);
+        mTimerHandler.postDelayed(mTimerCallback, SCAN_TIMEOUT_MILLIS);
     }
 
     /**
      * Handle a click event.
-     * @param l The ListView.
-     * @param v The View that was clicked inside the ListView.
+     * @param adapterView The AdapterView where the click happened.
+     * @param view The View that was clicked inside the AdapterView.
      * @param position The position of the clicked element in the list.
      * @param id The row id of the clicked element in the list.
      */
     @Override
-    public void onListItemClick(ListView l, View v, int position, long id) {
+    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
         PhysicalWebUma.onUrlSelected();
         PwsResult pwsResult = mAdapter.getItem(position);
         Intent intent = createNavigateToUrlIntent(pwsResult);
@@ -106,6 +133,15 @@
         });
     }
 
+    private void updateEmptyListMessage(boolean isScanning) {
+        int messageId = R.string.physical_web_empty_list;
+        if (isScanning) {
+            messageId = R.string.physical_web_empty_list_scanning;
+        }
+
+        mEmptyView.setText(messageId);
+    }
+
     private static Intent createNavigateToUrlIntent(PwsResult pwsResult) {
         String url = pwsResult.siteUrl;
         if (url == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PwsClient.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PwsClient.java
index 5e661ea..7fff8c24b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PwsClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PwsClient.java
@@ -9,6 +9,8 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.GoogleAPIKeys;
+import org.chromium.chrome.browser.ChromeVersionInfo;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -23,7 +25,8 @@
  */
 class PwsClient {
     private static final String TAG = "PhysicalWeb";
-    private static final String ENDPOINT_URL = "https://url-caster.appspot.com/resolve-scan";
+    private static final String ENDPOINT_URL =
+            "https://physicalweb.googleapis.com/v1alpha1/urls:resolve";
 
     /**
      * Callback that is run after the PWS sends a response to a resolve-scan request.
@@ -48,6 +51,14 @@
         public void onIconReceived(String iconUrl, Bitmap iconBitmap);
     }
 
+    private String getApiKey() {
+        if (ChromeVersionInfo.isStableBuild()) {
+            return GoogleAPIKeys.GOOGLE_API_KEY;
+        } else {
+            return GoogleAPIKeys.GOOGLE_API_KEY_PHYSICAL_WEB_TEST;
+        }
+    }
+
     private static JSONObject createResolveScanPayload(Collection<String> urls)
             throws JSONException {
         // Encode the urls.
@@ -60,7 +71,7 @@
 
         // Organize the data into a single object.
         JSONObject jsonObject = new JSONObject();
-        jsonObject.put("objects", objects);
+        jsonObject.put("urls", objects);
         return jsonObject;
     }
 
@@ -69,9 +80,9 @@
         Collection<PwsResult> pwsResults = new ArrayList<>();
         JSONArray metadata;
         try {
-            metadata = result.getJSONArray("metadata");
+            metadata = result.getJSONArray("results");
         } catch (JSONException e) {
-            Log.e(TAG, "PWS returned invalid metadata", e);
+            Log.e(TAG, "PWS returned invalid data", e);
             return pwsResults;
         }
 
@@ -79,14 +90,15 @@
         for (int i = 0; i < metadata.length(); i++) {
             try {
                 JSONObject obj = metadata.getJSONObject(i);
-                String requestUrl = obj.getString("id");
-                String siteUrl = obj.getString("url");
-                String iconUrl = obj.optString("icon", null);
-                String title = obj.optString("title", "");
-                String description = obj.optString("description", "");
-                pwsResults.add(new PwsResult(requestUrl, siteUrl, iconUrl, title, description));
+                JSONObject pageInfo = obj.getJSONObject("pageInfo");
+                String scannedUrl = obj.getString("scannedUrl");
+                String resolvedUrl = obj.getString("resolvedUrl");
+                String iconUrl = pageInfo.optString("icon", null);
+                String title = pageInfo.optString("title", "");
+                String description = pageInfo.optString("description", "");
+                pwsResults.add(new PwsResult(scannedUrl, resolvedUrl, iconUrl, title, description));
             } catch (JSONException e) {
-                Log.e(TAG, "PWS returned invalid metadata", e);
+                Log.e(TAG, "PWS returned invalid data", e);
                 continue;
             }
         }
@@ -126,7 +138,8 @@
         HttpRequest request = null;
         try {
             JSONObject payload = createResolveScanPayload(broadcastUrls);
-            request = new JsonObjectHttpRequest(ENDPOINT_URL, payload, requestCallback);
+            String url = ENDPOINT_URL + "?key=" + getApiKey();
+            request = new JsonObjectHttpRequest(url, payload, requestCallback);
         } catch (MalformedURLException e) {
             Log.e(TAG, "Error creating PWS HTTP request", e);
             return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java
index fb0c42b..f590848 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java
@@ -12,6 +12,7 @@
 import android.content.res.Resources;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.app.NotificationManagerCompat;
+import android.text.TextUtils;
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.notifications.NotificationConstants;
@@ -132,28 +133,41 @@
                     }
                 }
 
-                if (siteUrls.isEmpty()) {
+                int urlCount = siteUrls.size();
+
+                if (urlCount == 0) {
                     mNotificationManager.cancel(NotificationConstants.NOTIFICATION_ID_PHYSICAL_WEB);
                 } else {
-                    String displayUrl = siteUrls.iterator().next();
-                    createNotification(displayUrl, siteUrls.size());
+                    Resources resources = mContext.getResources();
+                    String title = resources.getQuantityString(
+                            R.plurals.physical_web_notification_title, urlCount, urlCount);
+                    String text = null;
+
+                    // when only one URL is found, display its title and description in the
+                    // notification (but avoid displaying a blank notification)
+                    if (urlCount == 1) {
+                        PwsResult onlyResult = pwsResults.iterator().next();
+                        if (!TextUtils.isEmpty(onlyResult.title)) {
+                            title = onlyResult.title;
+                            text = onlyResult.description;
+                        }
+                    }
+
+                    createNotification(title, text);
                 }
             }
         });
     }
 
-    private void createNotification(String displayUrl, int urlCount) {
+    private void createNotification(String title, String text) {
         // Get values to display.
-        Resources resources = mContext.getResources();
-        String title = resources.getQuantityString(R.plurals.physical_web_notification_title,
-                                                   urlCount, urlCount);
         PendingIntent pendingIntent = createListUrlsIntent();
 
         // Create the notification.
         Notification notification = new NotificationCompat.Builder(mContext)
                 .setSmallIcon(R.drawable.ic_physical_web_notification)
                 .setContentTitle(title)
-                .setContentText(displayUrl)
+                .setContentText(text)
                 .setContentIntent(pendingIntent)
                 .setPriority(NotificationCompat.PRIORITY_MIN)
                 .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/DataUseSnackbarController.java b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/DataUseSnackbarController.java
new file mode 100644
index 0000000..944ef2b
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/DataUseSnackbarController.java
@@ -0,0 +1,68 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.snackbar;
+
+import android.content.Context;
+
+import org.chromium.chrome.R;
+
+/**
+ * The controller for the data use snackbars. This handles two snackbars:
+ *
+ * 1. When Chrome starts tracking data use in a Tab, it shows a snackbar informing the user that
+ * data use tracking has started.
+ *
+ * 2. When Chrome stops tracking data use in a Tab, it shows a snackbar informing the user that
+ * data use tracking has ended.
+ */
+public class DataUseSnackbarController implements SnackbarManager.SnackbarController {
+    private final SnackbarManager mSnackbarManager;
+    private final Context mContext;
+
+    /**
+     * Creates an instance of a {@link DataUseBarPopupController}.
+     * @param context The {@link Context} in which snackbar is shown.
+     * @param snackbarManager The manager that helps to show up snackbar.
+     */
+    public DataUseSnackbarController(Context context, SnackbarManager snackbarManager) {
+        mSnackbarManager = snackbarManager;
+        mContext = context;
+    }
+
+    public void showDataUseTrackingStartedBar() {
+        mSnackbarManager.showSnackbar(Snackbar.make(
+                mContext.getString(R.string.data_use_tracking_started_snackbar_message), this)
+                .setAction(mContext.getString(R.string.data_use_tracking_started_snackbar_action),
+                        null));
+        // TODO(megjablon): Add metrics.
+    }
+
+    public void showDataUseTrackingEndedBar() {
+        mSnackbarManager.showSnackbar(Snackbar.make(
+                mContext.getString(R.string.data_use_tracking_ended_title), this));
+        // TODO(megjablon): Add metrics.
+    }
+
+    /**
+     * Dismisses the snackbar.
+     */
+    public void dismissDataUseBar() {
+        if (mSnackbarManager.isShowing()) mSnackbarManager.dismissSnackbars(this);
+    }
+
+    /**
+     * Loads the "Learn more" page.
+     */
+    @Override
+    public void onAction(Object actionData) {
+        // TODO(megjablon): Load the more page and add metrics.
+    }
+
+    @Override
+    public void onDismissNoAction(Object actionData) {}
+
+    @Override
+    public void onDismissForEachType(boolean isTimeout) {}
+}
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 84b49fe9..658c77a9 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -776,6 +776,17 @@
         Data Saver is on. Manage it in Settings.
       </message>
 
+      <!-- Data Use -->
+      <message name="IDS_DATA_USE_TRACKING_STARTED_SNACKBAR_MESSAGE" desc="Message shown when data use tracking begins.">
+        Your data use is being tracked
+      </message>
+      <message name="IDS_DATA_USE_TRACKING_STARTED_SNACKBAR_ACTION" desc="Button to learn more when data use tracking begins.">
+        More
+      </message>
+      <message name="IDS_DATA_USE_TRACKING_ENDED_TITLE" desc="Message shown when data use tracking has ended. Used by both the snackbar and dialog.">
+        Data use tracking has ended
+      </message>
+
       <!-- About Chrome preferences -->
       <message name="IDS_PREFS_ABOUT_CHROME" desc="Title for the About Chrome page. [CHAR-LIMIT=32]">
         About Chrome
@@ -2289,12 +2300,18 @@
 
       <!-- Physical Web strings -->
       <message name="IDS_PHYSICAL_WEB_LIST_URLS_ACTIVITY_TITLE" desc="The title for a dialog that shows a list of URLs broadcasted from nearby devices.">
-        Nearby URLs
+        The Physical Web
       </message>
       <message name="IDS_PHYSICAL_WEB_NOTIFICATION_TITLE" desc="Description of quantity of discovered URLs nearby.">
         {NUM_URLS, plural,
-         =1 {1 URL nearby}
-         other {# URLs nearby}}
+         =1 {1 Physical Web link nearby}
+         other {# Physical Web links nearby}}
+      </message>
+      <message name="IDS_PHYSICAL_WEB_EMPTY_LIST" desc="The message displayed in place of a list of nearby URLs when there are no URLs to display.">
+        There are no nearby web pages found
+      </message>
+      <message name="IDS_PHYSICAL_WEB_EMPTY_LIST_SCANNING" desc="The message displayed in place of a list of nearby URLs while still scanning for nearby URLs.">
+        Looking for nearby web pages
       </message>
     </messages>
   </release>
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java
index 7803b6a..7e5fad85 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java
@@ -13,14 +13,18 @@
 import android.app.Activity;
 import android.os.Bundle;
 
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
 import org.chromium.base.BaseChromiumApplication;
 import org.chromium.base.test.util.Feature;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.annotation.Config;
+import org.robolectric.util.ActivityController;
 
 /**
  * Tests FirstRunFlowSequencer which contains the core logic of what should be shown during the
@@ -118,12 +122,23 @@
         }
     }
 
+    ActivityController<Activity> mActivityController;
     TestFirstRunFlowSequencer mSequencer;
 
     @Before
     public void setUp() throws Exception {
-        Activity activity = Robolectric.setupActivity(Activity.class);
-        mSequencer = new TestFirstRunFlowSequencer(activity, new Bundle());
+        mActivityController = Robolectric.buildActivity(Activity.class);
+        mSequencer = new TestFirstRunFlowSequencer(mActivityController.setup().get(), new Bundle());
+    }
+
+    @After
+    public void tearDown() {
+        mActivityController.pause().stop().destroy();
+
+        // TODO(jbudorick): Remove this once we roll to Robolectric 3.0, which should contain
+        //  https://github.com/robolectric/robolectric/pull/1479
+        ApplicationStatus.onStateChangeForTesting(mActivityController.get(),
+                ActivityState.DESTROYED);
     }
 
     @Test
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_content_setting_bubble.png b/chrome/app/theme/default_100_percent/common/omnibox_content_setting_bubble.png
deleted file mode 100644
index 43b9453d..0000000
--- a/chrome/app/theme/default_100_percent/common/omnibox_content_setting_bubble.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_ev_bubble.png b/chrome/app/theme/default_100_percent/common/omnibox_ev_bubble.png
deleted file mode 100644
index 145ac7f..0000000
--- a/chrome/app/theme/default_100_percent/common/omnibox_ev_bubble.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_ev_bubble_https_valid.png b/chrome/app/theme/default_100_percent/common/omnibox_ev_bubble_https_valid.png
deleted file mode 100644
index 765756e..0000000
--- a/chrome/app/theme/default_100_percent/common/omnibox_ev_bubble_https_valid.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_selected_keyword_bubble.png b/chrome/app/theme/default_100_percent/common/omnibox_selected_keyword_bubble.png
deleted file mode 100644
index b1c04dd5..0000000
--- a/chrome/app/theme/default_100_percent/common/omnibox_selected_keyword_bubble.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_selected_keyword_bubble_search.png b/chrome/app/theme/default_100_percent/common/omnibox_selected_keyword_bubble_search.png
deleted file mode 100644
index 98d6dd1..0000000
--- a/chrome/app/theme/default_100_percent/common/omnibox_selected_keyword_bubble_search.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_content_setting_bubble.png b/chrome/app/theme/default_200_percent/common/omnibox_content_setting_bubble.png
deleted file mode 100644
index 66ac837..0000000
--- a/chrome/app/theme/default_200_percent/common/omnibox_content_setting_bubble.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_ev_bubble.png b/chrome/app/theme/default_200_percent/common/omnibox_ev_bubble.png
deleted file mode 100644
index 74d46041..0000000
--- a/chrome/app/theme/default_200_percent/common/omnibox_ev_bubble.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_ev_bubble_https_valid.png b/chrome/app/theme/default_200_percent/common/omnibox_ev_bubble_https_valid.png
deleted file mode 100644
index a8c89b4..0000000
--- a/chrome/app/theme/default_200_percent/common/omnibox_ev_bubble_https_valid.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_selected_keyword_bubble.png b/chrome/app/theme/default_200_percent/common/omnibox_selected_keyword_bubble.png
deleted file mode 100644
index 89cdd64..0000000
--- a/chrome/app/theme/default_200_percent/common/omnibox_selected_keyword_bubble.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_selected_keyword_bubble_search.png b/chrome/app/theme/default_200_percent/common/omnibox_selected_keyword_bubble_search.png
deleted file mode 100644
index 3a86607..0000000
--- a/chrome/app/theme/default_200_percent/common/omnibox_selected_keyword_bubble_search.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 91913337..ac2ad6b4 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -483,9 +483,6 @@
       <structure type="chrome_scaled_image" name="IDR_NOTIFIER_BLOCK_BUTTON" file="common/block_notifier.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_BORDER" file="common/omnibox_border.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_CALCULATOR_SELECTED" file="common/omnibox_calculator_selected.png" />
-      <if expr="enable_topchrome_md">
-        <structure type="chrome_scaled_image" name="IDR_OMNIBOX_CONTENT_SETTING_BUBBLE" file="common/omnibox_content_setting_bubble.png" />
-      </if>
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_BOTTOM" file="common/omnibox_content_setting_bubble_bottom.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_BOTTOM_LEFT" file="common/omnibox_content_setting_bubble_bottom_left.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_BOTTOM_RIGHT" file="common/omnibox_content_setting_bubble_bottom_right.png" />
@@ -498,8 +495,6 @@
       <if expr="enable_topchrome_md">
         <structure type="chrome_scaled_image" name="IDR_OMNIBOX_DROPDOWN_SHADOW_BOTTOM" file="common/omnibox_dropdown_shadow_bottom.png" />
         <structure type="chrome_scaled_image" name="IDR_OMNIBOX_DROPDOWN_SHADOW_TOP" file="common/omnibox_dropdown_shadow_top.png" />
-        <structure type="chrome_scaled_image" name="IDR_OMNIBOX_EV_BUBBLE" file="common/omnibox_ev_bubble.png" />
-        <structure type="chrome_scaled_image" name="IDR_OMNIBOX_EV_BUBBLE_HTTPS_VALID" file="common/omnibox_ev_bubble_https_valid.png" />
       </if>
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_EV_BUBBLE_BOTTOM" file="common/omnibox_ev_bubble_bottom.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_EV_BUBBLE_BOTTOM_LEFT" file="common/omnibox_ev_bubble_bottom_left.png" />
@@ -535,10 +530,6 @@
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SEARCH_BUTTON_LOUPE" file="common/omnibox_search_button_loupe.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SEARCH_SECURED" file="common/omnibox_search_secured.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SEARCH_SELECTED" file="common/omnibox_search_selected.png" />
-      <if expr="enable_topchrome_md">
-        <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE" file="common/omnibox_selected_keyword_bubble.png" />
-        <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_SEARCH" file="common/omnibox_selected_keyword_bubble_search.png" />
-      </if>
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_BOTTOM" file="common/omnibox_selected_keyword_bubble_bottom.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_BOTTOM_LEFT" file="common/omnibox_selected_keyword_bubble_bottom_left.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_BOTTOM_RIGHT" file="common/omnibox_selected_keyword_bubble_bottom_right.png" />
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 458e3f9b..720aff7d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1880,11 +1880,12 @@
      ENABLE_DISABLE_VALUE_TYPE(switches::kV8PacMojoOutOfProcess,
                                switches::kDisableOutOfProcessPac)},
 #if defined(ENABLE_MEDIA_ROUTER) && !defined(OS_ANDROID)
-    {"enable-media-router",
+    {"media-router",
      IDS_FLAGS_ENABLE_MEDIA_ROUTER_NAME,
      IDS_FLAGS_ENABLE_MEDIA_ROUTER_DESCRIPTION,
      kOsDesktop,
-     SINGLE_VALUE_TYPE(switches::kEnableMediaRouter)},
+     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(
+         switches::kMediaRouter, "1", switches::kMediaRouter, "0")},
 #endif  // defined(ENABLE_MEDIA_ROUTER) && !defined(OS_ANDROID)
 // Since Drive Search is not available when app list is disabled, flag guard
 // enable-drive-search-in-chrome-launcher flag.
@@ -2561,10 +2562,9 @@
         break;
       case FeatureEntry::MULTI_VALUE:
       case FeatureEntry::ENABLE_DISABLE_VALUE:
+      case FeatureEntry::FEATURE_VALUE:
         data->Set("choices", CreateChoiceData(entry, enabled_entries));
         break;
-      default:
-        NOTREACHED();
     }
 
     bool supported = (entry.supported_platforms & current_platform) != 0;
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index 4620a16f..41e6895 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -31,6 +31,7 @@
 #include "chrome/browser/android/contextualsearch/contextual_search_manager.h"
 #include "chrome/browser/android/contextualsearch/contextual_search_tab_helper.h"
 #include "chrome/browser/android/cookies/cookies_fetcher.h"
+#include "chrome/browser/android/data_usage/data_use_tab_ui_manager_android.h"
 #include "chrome/browser/android/data_usage/external_data_use_observer.h"
 #include "chrome/browser/android/dev_tools_server.h"
 #include "chrome/browser/android/document/document_web_contents_delegate.h"
@@ -238,6 +239,7 @@
     {"CreditCardScanner", autofill::CreditCardScannerViewAndroid::Register},
     {"DataReductionProxyInfoBarDelegate", DataReductionProxyInfoBar::Register},
     {"DataReductionProxySettings", DataReductionProxySettingsAndroid::Register},
+    {"DataUseTabUIManager", RegisterDataUseTabUIManager},
     {"DevToolsServer", RegisterDevToolsServer},
     {"DocumentWebContentsDelegate", DocumentWebContentsDelegate::Register},
     {"DomDistillerServiceFactory",
diff --git a/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.cc b/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.cc
new file mode 100644
index 0000000..0f14228
--- /dev/null
+++ b/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.cc
@@ -0,0 +1,35 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/data_usage/data_use_tab_ui_manager_android.h"
+
+#include "base/android/jni_android.h"
+#include "chrome/browser/profiles/profile_android.h"
+#include "jni/DataUseTabUIManager_jni.h"
+
+// static
+jboolean HasDataUseTrackingStarted(JNIEnv* env,
+                                   const JavaParamRef<jclass>& clazz,
+                                   jint tab_id,
+                                   const JavaParamRef<jobject>& jprofile) {
+  // TODO(megjablon): Get the DataUseTabUIManager which is a keyed service and
+  // ask it if data use tracking has started.
+  // Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
+  return false;
+}
+
+// static
+jboolean HasDataUseTrackingEnded(JNIEnv* env,
+                                 const JavaParamRef<jclass>& clazz,
+                                 jint tab_id,
+                                 const JavaParamRef<jobject>& jprofile) {
+  // TODO(megjablon): Get the DataUseTabUIManager which is a keyed service and
+  // ask it if data use tracking has ended.
+  // Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
+  return false;
+}
+
+bool RegisterDataUseTabUIManager(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
diff --git a/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.h b/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.h
new file mode 100644
index 0000000..b2444c3
--- /dev/null
+++ b/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.h
@@ -0,0 +1,13 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ANDROID_DATA_USAGE_DATA_USE_TAB_UI_MANAGER_ANDROID_H_
+#define CHROME_BROWSER_ANDROID_DATA_USAGE_DATA_USE_TAB_UI_MANAGER_ANDROID_H_
+
+#include <jni.h>
+
+// Registers the RegisterDataUseTabUIManager's native methods through JNI.
+bool RegisterDataUseTabUIManager(JNIEnv* env);
+
+#endif  // CHROME_BROWSER_ANDROID_DATA_USAGE_DATA_USE_TAB_UI_MANAGER_ANDROID_H_
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 7eb4155..fb60c29 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -152,6 +152,8 @@
         <include name="IDR_MD_EXTENSIONS_ITEM_CSS" file="resources\md_extensions\item.css" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_ITEM_HTML" file="resources\md_extensions\item.html" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_ITEM_JS" file="resources\md_extensions\item.js" type="BINDATA" />
+        <include name="IDR_MD_EXTENSIONS_SERVICE_HTML" file="resources\md_extensions\service.html" type="BINDATA" />
+        <include name="IDR_MD_EXTENSIONS_SERVICE_JS" file="resources\md_extensions\service.js" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_SIDEBAR_CSS" file="resources\md_extensions\sidebar.css" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_SIDEBAR_HTML" file="resources\md_extensions\sidebar.html" type="BINDATA" />
         <include name="IDR_MD_EXTENSIONS_SIDEBAR_JS" file="resources\md_extensions\sidebar.js" type="BINDATA" />
diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc
index fa7e869..7dae55e9 100644
--- a/chrome/browser/extensions/api/preference/preference_api.cc
+++ b/chrome/browser/extensions/api/preference/preference_api.cc
@@ -119,10 +119,15 @@
     {"translationServiceEnabled", prefs::kEnableTranslate,
      APIPermission::kPrivacy, APIPermission::kPrivacy},
 #if defined(ENABLE_WEBRTC)
+    // webRTCMultipleRoutesEnabled and webRTCNonProxiedUdpEnabled have been
+    // replaced by webRTCIPHandlingPolicy. Leaving it for backward
+    // compatibility. TODO(guoweis): Remove this in M50.
     {"webRTCMultipleRoutesEnabled", prefs::kWebRTCMultipleRoutesEnabled,
      APIPermission::kPrivacy, APIPermission::kPrivacy},
     {"webRTCNonProxiedUdpEnabled", prefs::kWebRTCNonProxiedUdpEnabled,
      APIPermission::kPrivacy, APIPermission::kPrivacy},
+    {"webRTCIPHandlingPolicy", prefs::kWebRTCIPHandlingPolicy,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
 #endif
     // accessibilityFeatures.animationPolicy is available for
     // all platforms but the others from accessibilityFeatures
diff --git a/chrome/browser/extensions/api/preference/preference_apitest.cc b/chrome/browser/extensions/api/preference/preference_apitest.cc
index f9461a4..8fef0e45d 100644
--- a/chrome/browser/extensions/api/preference/preference_apitest.cc
+++ b/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -21,6 +21,7 @@
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/translate/core/common/translate_pref_names.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/common/webrtc_ip_handling_policy.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/test_extension_registry_observer.h"
 #include "extensions/test/extension_test_message_listener.h"
@@ -127,6 +128,8 @@
 #if defined(ENABLE_WEBRTC)
   prefs->SetBoolean(prefs::kWebRTCMultipleRoutesEnabled, false);
   prefs->SetBoolean(prefs::kWebRTCNonProxiedUdpEnabled, false);
+  prefs->SetString(prefs::kWebRTCIPHandlingPolicy,
+                   content::kWebRTCIPHandlingDefaultPublicInterfaceOnly);
 #endif
 
   const char kExtensionPath[] = "preference/standard";
diff --git a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc b/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc
index 01f9a6e0..f627e22 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc
+++ b/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <algorithm>
 #include <vector>
diff --git a/chrome/browser/plugins/plugin_power_saver_browsertest.cc b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
index dff34a9..55ec053 100644
--- a/chrome/browser/plugins/plugin_power_saver_browsertest.cc
+++ b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
@@ -249,7 +249,9 @@
 class PluginPowerSaverBrowserTest : public InProcessBrowserTest {
  public:
   void SetUp() override {
-    EnablePixelOutput();
+    if (PixelTestsEnabled())
+      EnablePixelOutput();
+
     InProcessBrowserTest::SetUp();
   }
 
@@ -281,12 +283,14 @@
 
  protected:
   void LoadHTML(const std::string& html) {
-    gfx::Rect bounds(gfx::Rect(0, 0, kBrowserWidth, kBrowserHeight));
-    gfx::Rect screen_bounds =
-        gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().bounds();
-    ASSERT_GT(screen_bounds.width(), kBrowserWidth);
-    ASSERT_GT(screen_bounds.height(), kBrowserHeight);
-    browser()->window()->SetBounds(bounds);
+    if (PixelTestsEnabled()) {
+      gfx::Rect bounds(gfx::Rect(0, 0, kBrowserWidth, kBrowserHeight));
+      gfx::Rect screen_bounds =
+          gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().bounds();
+      ASSERT_GT(screen_bounds.width(), kBrowserWidth);
+      ASSERT_GT(screen_bounds.height(), kBrowserHeight);
+      browser()->window()->SetBounds(bounds);
+    }
 
     ASSERT_TRUE(embedded_test_server()->Started());
     embedded_test_server()->RegisterRequestHandler(
@@ -323,12 +327,8 @@
   }
 
   bool VerifySnapshot(const base::FilePath::StringType& expected_filename) {
-#if defined(OS_CHROMEOS) && defined(MEMORY_SANITIZER)
-    // Because we cannot use hardware OpenGL under MSan, but also cannot use
-    // software rendering under ChromeOS, we skip this portion of the test.
-    // See crbug.com/512140
-    return true;
-#endif
+    if (!PixelTestsEnabled())
+      return true;
 
     base::FilePath reference = ui_test_utils::GetTestFilePath(
         base::FilePath(FILE_PATH_LITERAL("plugin_power_saver")),
@@ -358,6 +358,21 @@
 
     return snapshot_matches;
   }
+
+  // TODO(tommycli): Remove this once all flakiness resolved.
+  bool PixelTestsEnabled() {
+#if defined(OS_WIN) || defined(ADDRESS_SANITIZER)
+    // Flaky on Windows and Asan bots. See crbug.com/549285.
+    return false;
+#elif defined(OS_CHROMEOS) && defined(MEMORY_SANITIZER)
+    // Because we cannot use hardware OpenGL under MSan, but also cannot use
+    // software rendering under ChromeOS, we skip this portion of the test.
+    // See crbug.com/512140
+    return false;
+#else
+    return true;
+#endif
+  }
 };
 
 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, SmallSameOrigin) {
diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc
index f7628fed..89b7d77 100644
--- a/chrome/browser/renderer_preferences_util.cc
+++ b/chrome/browser/renderer_preferences_util.cc
@@ -11,6 +11,7 @@
 #include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/renderer_preferences.h"
+#include "content/public/common/webrtc_ip_handling_policy.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 #if defined(OS_LINUX) || defined(OS_ANDROID)
@@ -42,10 +43,22 @@
   prefs->enable_do_not_track =
       pref_service->GetBoolean(prefs::kEnableDoNotTrack);
 #if defined(ENABLE_WEBRTC)
-  prefs->enable_webrtc_multiple_routes =
-      pref_service->GetBoolean(prefs::kWebRTCMultipleRoutesEnabled);
-  prefs->enable_webrtc_nonproxied_udp =
-      pref_service->GetBoolean(prefs::kWebRTCNonProxiedUdpEnabled);
+  prefs->webrtc_ip_handling_policy = std::string();
+  // Handling the backward compatibility of previous boolean verions of policy
+  // controls.
+  if (!pref_service->HasPrefPath(prefs::kWebRTCIPHandlingPolicy)) {
+    if (!pref_service->GetBoolean(prefs::kWebRTCNonProxiedUdpEnabled)) {
+      prefs->webrtc_ip_handling_policy =
+          content::kWebRTCIPHandlingDisableNonProxiedUdp;
+    } else if (!pref_service->GetBoolean(prefs::kWebRTCMultipleRoutesEnabled)) {
+      prefs->webrtc_ip_handling_policy =
+          content::kWebRTCIPHandlingDefaultPublicInterfaceOnly;
+    }
+  }
+  if (prefs->webrtc_ip_handling_policy.empty()) {
+    prefs->webrtc_ip_handling_policy =
+        pref_service->GetString(prefs::kWebRTCIPHandlingPolicy);
+  }
 #endif
 
   double default_zoom_level = 0;
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/kbexplorer.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/kbexplorer.js
index 730f6e7..c648f29 100644
--- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/kbexplorer.js
+++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/kbexplorer.js
@@ -23,19 +23,40 @@
  * Initialize keyboard explorer.
  */
 cvox.KbExplorer.init = function() {
+  var backgroundWindow = chrome.extension.getBackgroundPage();
   document.addEventListener('keydown', cvox.KbExplorer.onKeyDown, false);
+  backgroundWindow.addEventListener(
+      'keydown', cvox.KbExplorer.onKeyDown, false);
   document.addEventListener('keyup', cvox.KbExplorer.onKeyUp, false);
+  backgroundWindow.addEventListener('keyup', cvox.KbExplorer.onKeyUp, false);
   document.addEventListener('keypress', cvox.KbExplorer.onKeyPress, false);
+  backgroundWindow.addEventListener(
+      'keypress', cvox.KbExplorer.onKeyPress, false);
+
+  window.onbeforeunload = function(evt) {
+    backgroundWindow.removeEventListener(
+        'keydown', cvox.KbExplorer.onKeyDown, false);
+    backgroundWindow.removeEventListener(
+        'keyup', cvox.KbExplorer.onKeyUp, false);
+    backgroundWindow.removeEventListener(
+        'keypress', cvox.KbExplorer.onKeyPress, false);
+  };
 };
 
 
 /**
  * Handles keydown events by speaking the human understandable name of the key.
  * @param {Event} evt key event.
+ * @return {boolean} True if the default action should be performed.
  */
 cvox.KbExplorer.onKeyDown = function(evt) {
   chrome.extension.getBackgroundPage()['speak'](
       cvox.KeyUtil.getReadableNameForKeyCode(evt.keyCode), false, {});
+
+  // Allow Ctrl+W to be handled.
+  if (evt.keyCode == 87 && evt.ctrlKey) {
+    return true;
+  }
   evt.preventDefault();
   evt.stopPropagation();
 };
diff --git a/chrome/browser/resources/chromeos/chromevox/common/key_util.js b/chrome/browser/resources/chromeos/chromevox/common/key_util.js
index 5ff64d0..6299067 100644
--- a/chrome/browser/resources/chromeos/chromevox/common/key_util.js
+++ b/chrome/browser/resources/chromeos/chromevox/common/key_util.js
@@ -11,6 +11,7 @@
 goog.provide('cvox.KeyUtil');
 goog.provide('cvox.SimpleKeyEvent');
 
+goog.require('Msgs');
 goog.require('cvox.ChromeVox');
 goog.require('cvox.KeySequence');
 
@@ -243,6 +244,8 @@
  * @return {string} Returns a string description.
  */
 cvox.KeyUtil.getReadableNameForKeyCode = function(keyCode) {
+  var msg = Msgs.getMsg.bind(Msgs);
+  var cros = cvox.ChromeVox.isChromeOS;
   if (keyCode == 0) {
     return 'Power button';
   } else if (keyCode == 17) {
@@ -254,7 +257,7 @@
   } else if (keyCode == 9) {
     return 'Tab';
   } else if ((keyCode == 91) || (keyCode == 93)) {
-    if (cvox.ChromeVox.isChromeOS) {
+    if (cros) {
       return 'Search';
     } else if (cvox.ChromeVox.isMac) {
       return 'Cmd';
@@ -284,25 +287,25 @@
   } else if (keyCode == 27) {
     return 'Escape';
   } else if (keyCode == 112) {
-    return cvox.ChromeVox.isChromeOS ? 'Back' : 'F1';
+    return cros ? msg('back_key') : 'F1';
   } else if (keyCode == 113) {
-    return cvox.ChromeVox.isChromeOS ? 'Forward' : 'F2';
+    return cros ? msg('forward_key') : 'F2';
   } else if (keyCode == 114) {
-    return cvox.ChromeVox.isChromeOS ? 'Refresh' : 'F3';
+    return cros ? msg('refresh_key') : 'F3';
   } else if (keyCode == 115) {
-    return cvox.ChromeVox.isChromeOS ? 'Toggle full screen' : 'F4';
+    return cros ? msg('toggle_full_screen_key') : 'F4';
   } else if (keyCode == 116) {
-    return 'F5';
+    return cros ? msg('window_overview_key') : 'F5';
   } else if (keyCode == 117) {
-    return 'F6';
+    return cros ? msg('brightness_down_key') : 'F6';
   } else if (keyCode == 118) {
-    return 'F7';
+    return cros ? msg('brightness_up_key') : 'F7';
   } else if (keyCode == 119) {
-    return 'F8';
+    return cros ? msg('volume_mute_key') : 'F8';
   } else if (keyCode == 120) {
-    return 'F9';
+    return cros ? msg('volume_down_key') : 'F9';
   } else if (keyCode == 121) {
-    return 'F10';
+    return cros ? msg('volume_up_key') : 'F10';
   } else if (keyCode == 122) {
     return 'F11';
   } else if (keyCode == 123) {
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
index 28dfed8..b46310f 100644
--- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
+++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -2365,6 +2365,38 @@
       <message desc="Message spoken to user when switching to a mode where searching is case-sensitive." name="IDS_CHROMEVOX_CASE_SENSITIVE">
         Case sensitive.
       </message>
+
+      <!-- Keyboard Explorer -->
+      <message desc="Describes the back key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_BACK_KEY">
+        back
+      </message>
+      <message desc="Describes the forward key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_FORWARD_KEY">
+        forward
+      </message>
+      <message desc="Describes the refresh key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_REFRESH_KEY">
+        refresh
+      </message>
+      <message desc="Describes the key to toggle full screen  in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_TOGGLE_FULL_SCREEN_KEY">
+        toggle full screen
+      </message>
+      <message desc="Describes the key to toggle window overview in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_WINDOW_OVERVIEW_KEY">
+        window overview
+      </message>
+      <message desc="Describes the brightness down key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_BRIGHTNESS_DOWN_KEY">
+        Brightness down
+      </message>
+      <message desc="Describes the brightness up key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_BRIGHTNESS_UP_KEY">
+        Brightness up
+      </message>
+      <message desc="Describes the volume mute key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_MUTE_KEY">
+        volume mute
+      </message>
+      <message desc="Describes the volume down key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_DOWN_KEY">
+        volume down
+      </message>
+      <message desc="Describes the volume up key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_UP_KEY">
+        volume up
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/chrome/browser/resources/md_extensions/compiled_resources.gyp b/chrome/browser/resources/md_extensions/compiled_resources.gyp
index d947ed44..50f7a41f 100644
--- a/chrome/browser/resources/md_extensions/compiled_resources.gyp
+++ b/chrome/browser/resources/md_extensions/compiled_resources.gyp
@@ -13,11 +13,15 @@
           '../../../../ui/webui/resources/js/cr.js',
           '../../../../ui/webui/resources/js/i18n_behavior.js',
           'item.js',
+          'manager.js',
+          'service.js',
+          'sidebar.js',
           'toolbar.js',
         ],
         'externs': [
           '<(EXTERNS_DIR)/chrome_send.js',
           '<(EXTERNS_DIR)/developer_private.js',
+          '<(EXTERNS_DIR)/management.js',
         ],
       },
       'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
diff --git a/chrome/browser/resources/md_extensions/item.js b/chrome/browser/resources/md_extensions/item.js
index b2d00abf6..df6e718 100644
--- a/chrome/browser/resources/md_extensions/item.js
+++ b/chrome/browser/resources/md_extensions/item.js
@@ -7,9 +7,7 @@
   var ItemDelegate = function() {};
 
   ItemDelegate.prototype = {
-    /**
-     * @param {string} id
-     */
+    /** @param {string} id */
     deleteItem: assertNotReached,
 
     /**
@@ -18,9 +16,7 @@
      */
     setItemEnabled: assertNotReached,
 
-    /**
-     * @param {string} id
-     */
+    /** @param {string} id */
     showItemDetails: assertNotReached,
 
     /**
@@ -28,6 +24,9 @@
      * @param {boolean} isAllowedIncognito
      */
     setItemAllowedIncognito: assertNotReached,
+
+    /** @return {boolean} */
+    isInDevMode: assertNotReached,
   };
 
   var Item = Polymer({
@@ -73,7 +72,9 @@
      */
     factoryImpl: function(data, delegate) {
       this.data = data;
+      this.id = data.id;
       this.delegate_ = delegate;
+      this.inDevMode = delegate.isInDevMode();
     },
 
     /** @private */
diff --git a/chrome/browser/resources/md_extensions/manager.css b/chrome/browser/resources/md_extensions/manager.css
index 3890cde..418fe5f 100644
--- a/chrome/browser/resources/md_extensions/manager.css
+++ b/chrome/browser/resources/md_extensions/manager.css
@@ -15,3 +15,8 @@
 #item-list {
   -webkit-margin-start: 250px;
 }
+
+extensions-item {
+  display: inline-block;
+  margin-top: 20px;
+}
diff --git a/chrome/browser/resources/md_extensions/manager.html b/chrome/browser/resources/md_extensions/manager.html
index 4a8c1ddc..c991723 100644
--- a/chrome/browser/resources/md_extensions/manager.html
+++ b/chrome/browser/resources/md_extensions/manager.html
@@ -2,6 +2,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html">
 <link rel="import" href="chrome://extensions/item.html">
+<link rel="import" href="chrome://extensions/service.html">
 <link rel="import" href="chrome://extensions/sidebar.html">
 <link rel="import" href="chrome://extensions/toolbar.html">
 
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js
index 729ee73..3ff4a3b 100644
--- a/chrome/browser/resources/md_extensions/manager.js
+++ b/chrome/browser/resources/md_extensions/manager.js
@@ -4,7 +4,60 @@
 
 cr.define('extensions', function() {
   var Manager = Polymer({
-    is: 'extensions-manager'
+    is: 'extensions-manager',
+
+    properties: {
+      sidebar: {
+        type: Object,
+      }
+    },
+
+    ready: function() {
+      this.sidebar = this.$$('extensions-sidebar');
+      extensions.Service.getInstance().managerReady(this);
+    },
+
+    /**
+     * Creates and adds a new extensions-item element to the list.
+     * @param {!chrome.developerPrivate.ExtensionInfo} extension The extension
+     *     the item is representing.
+     * @param {!extensions.ItemDelegate} delegate The delegate for the item.
+     * @param {!number=} opt_index The index at which to place the item. If
+     *     not present, the item is appended to the end of the list.
+     */
+    addItem: function(extension, delegate, opt_index) {
+      var extensionItem = new extensions.Item(extension, delegate);
+      var itemList = this.$['item-list'];
+      var refNode = opt_index !== undefined ?
+          itemList.children[opt_index] : undefined;
+      itemList.insertBefore(extensionItem, refNode);
+    },
+
+    /**
+     * @param {string} id The id of the extension to get the item for.
+     * @return {?extensions.Item}
+     */
+    getItem: function(id) {
+      return this.$$('#' + id);
+    },
+
+    /** @param {string} id The id of the item to remove. */
+    removeItem: function(id) {
+      var item = this.getItem(id);
+      if (item)
+        item.parentNode.removeChild(item);
+    },
+
+    /**
+     * Applies a function to each item present in the DOM.
+     * @param {!function(extensions.Item):void} callback The function to apply.
+     */
+    forEachItem: function(callback) {
+      Array.prototype.forEach.call(
+          /** @type {Array<extensions.Item>} */(
+              Polymer.dom(this.root).querySelectorAll('extensions-item')),
+          callback);
+     },
   });
 
   return {Manager: Manager};
diff --git a/chrome/browser/resources/md_extensions/service.html b/chrome/browser/resources/md_extensions/service.html
new file mode 100644
index 0000000..fe1be3f
--- /dev/null
+++ b/chrome/browser/resources/md_extensions/service.html
@@ -0,0 +1,5 @@
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://extensions/service.html">
+<link rel="import" href="chrome://extensions/item.html">
+<script src="chrome://extensions/service.js"></script>
diff --git a/chrome/browser/resources/md_extensions/service.js b/chrome/browser/resources/md_extensions/service.js
new file mode 100644
index 0000000..368c41d4
--- /dev/null
+++ b/chrome/browser/resources/md_extensions/service.js
@@ -0,0 +1,175 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('extensions', function() {
+  'use strict';
+
+  /**
+   * Compares two extensions to determine which should come first in the list.
+   * @param {chrome.developerPrivate.ExtensionInfo} a
+   * @param {chrome.developerPrivate.ExtensionInfo} b
+   * @return {number}
+   */
+  var compareExtensions = function(a, b) {
+    function compare(x, y) {
+      return x < y ? -1 : (x > y ? 1 : 0);
+    }
+    function compareLocation(x, y) {
+      if (x.location == y.location)
+        return 0;
+      if (x.location == chrome.developerPrivate.Location.UNPACKED)
+        return -1;
+      if (y.location == chrome.developerPrivate.Location.UNPACKED)
+        return 1;
+      return 0;
+    }
+    return compareLocation(a, b) ||
+           compare(a.name.toLowerCase(), b.name.toLowerCase()) ||
+           compare(a.id, b.id);
+  };
+
+  /**
+   * @constructor
+   * @implements {extensions.ItemDelegate}
+   * @implements {extensions.SidebarDelegate}
+   */
+  function Service() {}
+
+  Service.prototype = {
+    /** @private {boolean} */
+    promptIsShowing_: false,
+
+    /** @param {extensions.Manager} manager */
+    managerReady: function(manager) {
+      this.manager_ = manager;
+      this.sidebar_ = manager.sidebar;
+      this.sidebar_.setDelegate(this);
+      chrome.developerPrivate.onProfileStateChanged.addListener(
+          this.onProfileStateChanged_.bind(this));
+      chrome.developerPrivate.onItemStateChanged.addListener(
+          this.onItemStateChanged_.bind(this));
+      chrome.developerPrivate.getExtensionsInfo(
+          {includeDisabled: true, includeTerminated: true},
+          function(extensions) {
+        extensions.sort(compareExtensions);
+        this.extensions_ = extensions;
+        for (let extension of extensions)
+          this.manager_.addItem(extension, this);
+      }.bind(this));
+      chrome.developerPrivate.getProfileConfiguration(
+          this.onProfileStateChanged_.bind(this));
+    },
+
+    /**
+     * @param {chrome.developerPrivate.ProfileInfo} profileInfo
+     * @private
+     */
+    onProfileStateChanged_: function(profileInfo) {
+      this.profileInfo_ = profileInfo;
+      this.sidebar_.inDevMode = profileInfo.inDeveloperMode;
+      this.manager_.forEachItem(function(item) {
+        item.inDevMode = profileInfo.inDeveloperMode;
+      });
+    },
+
+    /**
+     * @param {chrome.developerPrivate.EventData} eventData
+     * @private
+     */
+    onItemStateChanged_: function(eventData) {
+      var EventType = chrome.developerPrivate.EventType;
+      switch (eventData.event_type) {
+        case EventType.VIEW_REGISTERED:
+        case EventType.VIEW_UNREGISTERED:
+        case EventType.INSTALLED:
+        case EventType.LOADED:
+        case EventType.UNLOADED:
+        case EventType.ERROR_ADDED:
+        case EventType.ERRORS_REMOVED:
+        case EventType.PREFS_CHANGED:
+          // |extensionInfo| can be undefined in the case of an extension
+          // being unloaded right before uninstallation. There's nothing to do
+          // here.
+          if (!eventData.extensionInfo)
+            break;
+
+          var existing = this.manager_.getItem(eventData.extensionInfo.id);
+          if (existing) {
+            existing.data = eventData.extensionInfo;
+          } else {
+            // If there's no existing item in the list, there shouldn't be an
+            // extension with the same id in the data.
+            var currentIndex = this.extensions_.findIndex(function(extension) {
+              return extension.id == eventData.extensionInfo.id;
+            });
+            assert(currentIndex == -1);
+            var newIndex = this.extensions_.findIndex(function(extension) {
+              return compareExtensions(extension,
+                                       assert(eventData.extensionInfo)) > 0;
+            });
+            newIndex = newIndex == -1 ? this.extensions_.length : newIndex;
+            this.extensions_.splice(newIndex, 0, eventData.extensionInfo);
+            this.manager_.addItem(eventData.extensionInfo, this, newIndex);
+          }
+          break;
+        case EventType.UNINSTALLED:
+          var currentIndex = this.extensions_.findIndex(function(extension) {
+            return extension.id == eventData.item_id;
+          });
+          this.extensions_.splice(currentIndex, 1);
+          this.manager_.removeItem(eventData.item_id);
+          break;
+        default:
+          assertNotReached();
+      }
+    },
+
+    /** @override */
+    deleteItem: function(id) {
+      if (this.promptIsShowing_)
+        return;
+      this.promptIsShowing_ = true;
+      chrome.management.uninstall(id, {showConfirmDialog: true}, function() {
+        // The "last error" was almost certainly the user canceling the dialog.
+        // Do nothing. We only check it so we don't get noisy logs.
+        /** @suppress {suspiciousCode} */
+        chrome.runtime.lastError;
+        this.promptIsShowing_ = false;
+      }.bind(this));
+    },
+
+    /** @override */
+    setItemEnabled: function(id, isEnabled) {
+      chrome.management.setEnabled(id, isEnabled);
+    },
+
+    /** @override */
+    showItemDetails: function(id) {},
+
+    /** @override */
+    setItemAllowedIncognito: function(id, isAllowedIncognito) {
+      chrome.developerPrivate.updateExtensionConfiguration({
+        extensionId: id,
+        incognitoAccess: isAllowedIncognito,
+      });
+    },
+
+    /** @override */
+    isInDevMode: function() {
+      // It's possible this could be called before the profileInfo is
+      // initialized; that's fine, because we'll update the items when it is.
+      return !!this.profileInfo_ && this.profileInfo_.inDeveloperMode;
+    },
+
+    /** @override */
+    setProfileInDevMode: function(inDevMode) {
+      chrome.developerPrivate.updateProfileConfiguration(
+          {inDeveloperMode: inDevMode});
+    },
+  };
+
+  cr.addSingletonGetter(Service);
+
+  return {Service: Service};
+});
diff --git a/chrome/browser/resources/md_extensions/sidebar.html b/chrome/browser/resources/md_extensions/sidebar.html
index 9bb9b02..765eaa7 100644
--- a/chrome/browser/resources/md_extensions/sidebar.html
+++ b/chrome/browser/resources/md_extensions/sidebar.html
@@ -22,7 +22,9 @@
     </paper-menu>
     <paper-item id="developer-mode">
       <span i18n-content="developerMode"></span>
-      <paper-checkbox id="developer-mode-checkbox"></paper-checkbox>
+      <paper-checkbox id="developer-mode-checkbox"
+          checked="[[inDevMode]]"
+          on-change="onDevModeChange_"></paper-checkbox>
     </paper-item>
     <paper-item id="more-extensions" i18n-content="getMoreExtensions">
     </paper-item>
diff --git a/chrome/browser/resources/md_extensions/sidebar.js b/chrome/browser/resources/md_extensions/sidebar.js
index 10dfdf6..45bb7d3 100644
--- a/chrome/browser/resources/md_extensions/sidebar.js
+++ b/chrome/browser/resources/md_extensions/sidebar.js
@@ -3,10 +3,41 @@
 // found in the LICENSE file.
 
 cr.define('extensions', function() {
+  /** @interface */
+  var SidebarDelegate = function() {};
+
+  SidebarDelegate.prototype = {
+    /**
+     * Toggles whether or not the profile is in developer mode.
+     * @param {boolean} inDevMode
+     */
+    setProfileInDevMode: assertNotReached,
+  };
+
   var Sidebar = Polymer({
     is: 'extensions-sidebar',
+
+    properties: {
+      inDevMode: {
+        type: Boolean,
+        value: false,
+      },
+    },
+
+    /** @param {extensions.SidebarDelegate} delegate */
+    setDelegate: function(delegate) {
+      this.delegate_ = delegate;
+    },
+
+    onDevModeChange_: function() {
+      this.delegate_.setProfileInDevMode(
+          this.$['developer-mode-checkbox'].checked);
+    },
   });
 
-  return {Sidebar: Sidebar};
+  return {
+    Sidebar: Sidebar,
+    SidebarDelegate: SidebarDelegate,
+  };
 });
 
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html
index 0c23613..807d57e 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html
+++ b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html
@@ -1,6 +1,6 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-slider/paper-slider.html">
-<link rel="import" href="appearance_font_menu.html">
+<link rel="import" href="chrome://md-settings/controls/settings_dropdown_menu.html">
 
 <dom-module id="settings-appearance-fonts-page">
   <link rel="import" type="css"
@@ -18,11 +18,11 @@
       </paper-slider>
     </div>
     <div class="control-row">
-      <settings-appearance-font-menu id="standardFont"
+      <settings-dropdown-menu id="standardFont"
           i18n-values="label:standardFont"
           pref="{{prefs.webkit.webprefs.fonts.standard.Zyyy}}"
           menuOptions="[[fontOptions_]]">
-      </settings-appearance-font-menu>
+      </settings-dropdown-menu>
       <div class="control-column"
           style$="[[computeStyle_(defaultFontSize_,
               prefs.webkit.webprefs.fonts.standard.Zyyy.value)]]">
@@ -31,11 +31,11 @@
       </div>
     </div>
     <div class="control-row">
-      <settings-appearance-font-menu id="serifFont"
+      <settings-dropdown-menu id="serifFont"
           i18n-values="label:serifFont"
           pref="{{prefs.webkit.webprefs.fonts.serif.Zyyy}}"
           menuOptions="[[fontOptions_]]">
-      </settings-appearance-font-menu>
+      </settings-dropdown-menu>
       <div class="control-column"
           style$="[[computeStyle_(defaultFontSize_,
               prefs.webkit.webprefs.fonts.serif.Zyyy.value)]]">
@@ -44,11 +44,11 @@
       </div>
     </div>
     <div class="control-row">
-      <settings-appearance-font-menu id="sansSerifFont"
+      <settings-dropdown-menu id="sansSerifFont"
           i18n-values="label:sansSerifFont"
           pref="{{prefs.webkit.webprefs.fonts.sansserif.Zyyy}}"
           menuOptions="[[fontOptions_]]">
-      </settings-appearance-font-menu>
+      </settings-dropdown-menu>
       <div class="control-column"
           style$="{{computeStyle_(defaultFontSize_,
               prefs.webkit.webprefs.fonts.sansserif.Zyyy.value)}}">
@@ -57,11 +57,11 @@
       </div>
     </div>
     <div class="control-row">
-      <settings-appearance-font-menu id="fixedFont"
+      <settings-dropdown-menu id="fixedFont"
           i18n-values="label:fixedWidthFont"
           pref="{{prefs.webkit.webprefs.fonts.fixed.Zyyy}}"
           menuOptions="[[fontOptions_]]">
-      </settings-appearance-font-menu>
+      </settings-dropdown-menu>
       <div class="control-column"
           style$="[[computeStyle_(defaultFontSize_,
               prefs.webkit.webprefs.fonts.fixed.Zyyy.value)]]">
@@ -85,11 +85,11 @@
       </div>
     </div>
     <div class="control-row">
-      <settings-appearance-font-menu id="encoding"
+      <settings-dropdown-menu id="encoding"
           i18n-values="label:encoding"
           pref="{{prefs.intl.charset_default}}"
           menuOptions="[[encodingOptions_]]">
-      </settings-appearance-font-menu>
+      </settings-dropdown-menu>
     </div>
   </template>
   <script src="appearance_fonts_page.js"></script>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html
index 57731b5e..5a36a7095 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -74,10 +74,10 @@
         </div>
         <div class="settings-row">
           <div i18n-content="fontSize"></div>
-          <settings-appearance-font-menu id="defaultFontSize" disabled
+          <settings-dropdown-menu id="defaultFontSize" disabled
               pref="{{prefs.webkit.webprefs.default_font_size}}"
               menuOptions="[[fontSizeOptions_]]">
-          </settings-appearance-font-menu>
+          </settings-dropdown-menu>
         </div>
         <div class="settings-row">
           <div class="flex" i18n-content="customizeFonts"></div>
@@ -86,10 +86,10 @@
         </div>
         <div class="settings-row">
           <div i18n-content="pageZoom"></div>
-          <settings-appearance-font-menu id="pageZoom" disabled
+          <settings-dropdown-menu id="pageZoom" disabled
               pref="{{prefs.partition.default_zoom_level}}"
               menuOptions="[[pageZoomOptions_]]">
-          </settings-appearance-font-menu>
+          </settings-dropdown-menu>
         </div>
       </neon-animatable>
       <neon-animatable id="appearance-fonts">
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.js b/chrome/browser/resources/settings/appearance_page/appearance_page.js
index 0ae02f6e..09a8aad 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.js
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -30,15 +30,6 @@
     },
 
     /**
-     * Preferences state.
-     */
-    allowResetTheme_: {
-      notify: true,
-      type: Boolean,
-      value: false,
-    },
-
-    /**
      * @private
      */
     allowResetTheme_: {
diff --git a/chrome/browser/resources/settings/appearance_page/compiled_resources.gyp b/chrome/browser/resources/settings/appearance_page/compiled_resources.gyp
new file mode 100644
index 0000000..7e7c57b7
--- /dev/null
+++ b/chrome/browser/resources/settings/appearance_page/compiled_resources.gyp
@@ -0,0 +1,48 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'targets': [
+    {
+      'target_name': 'appearance_fonts_page',
+      'variables': {
+        'depends': [
+          '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
+          '../../../../../ui/webui/resources/js/compiled_resources.gyp:cr',
+          '../../../../../ui/webui/resources/js/cr.js',
+          '../../../../../ui/webui/resources/js/i18n_behavior.js',
+          '../../../../../third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/iron-a11y-keys-behavior-extracted.js',
+          '../../../../../third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js',
+          '../../../../../third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-control-state-extracted.js',
+          '../../../../../third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/iron-form-element-behavior-extracted.js',
+          '../../../../../third_party/polymer/v1_0/components-chromium/iron-range-behavior/iron-range-behavior-extracted.js',
+          '../../../../../third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-inky-focus-behavior-extracted.js',
+          '../../../../../third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js',
+          '../../../../../third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple-extracted.js',
+          '../../../../../third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js',
+        ],
+        'externs': [
+          '../../../../../third_party/closure_compiler/externs/settings_private.js'
+        ],
+      },
+      'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
+    },
+    {
+      'target_name': 'appearance_page',
+      'variables': {
+        'depends': [
+          '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert',
+          '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
+          '../../../../../ui/webui/resources/js/cr.js',
+          '../../../../../ui/webui/resources/js/i18n_behavior.js',
+          '../settings_page/settings_animated_pages.js'
+        ],
+        'externs': [
+          '../../../../../third_party/closure_compiler/externs/settings_private.js',
+          '../../../../../third_party/closure_compiler/externs/chrome_send.js',
+        ],
+      },
+      'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
+    },
+  ],
+}
diff --git a/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.html b/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.html
index 03d9915..398eb62 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.html
+++ b/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.html
@@ -4,57 +4,74 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-dropdown-menu/paper-dropdown-menu.html">
 <link rel="import" href="chrome://md-settings/controls/settings_checkbox.html">
+<link rel="import" href="chrome://md-settings/controls/settings_dropdown_menu.html">
 
 <dom-module id="settings-clear-browsing-data-page">
+  <link rel="import" type="css"
+      href="chrome://md-settings/settings_page/settings_page.css">
   <link rel="import" type="css" href="clear_browsing_data_page.css">
   <template>
-    <div>
+    <div class="settings-row">
       <span i18n-content="clearFollowingItemsFrom"></span>
-      <paper-dropdown-menu>
-        <paper-menu class="dropdown-content"
-            selected="{{prefs.browser.clear_data.time_period.value}}">
-          <template is="dom-repeat" items="[[clearFromOptions_]]">
-            <paper-item>[[item]]</paper-item>
-          </template>
-        </paper-menu>
-      </paper-dropdown-menu>
+      <settings-dropdown-menu id="clearFrom"
+          pref="{{prefs.browser.clear_data.time_period}}"
+          menuOptions="[[clearFromOptions_]]" disabled>
+      </settings-dropdown-menu>
+    </div>
+    <div class="settings-row">
       <settings-checkbox id="browsingCheckbox"
           pref="{{prefs.browser.clear_data.browsing_history}}"
           i18n-values="label:clearBrowsingHistory">
       </settings-checkbox>
+    </div>
+    <div class="settings-row">
       <settings-checkbox id="downloadCheckbox"
           pref="{{prefs.browser.clear_data.download_history}}"
           i18n-values="label:clearDownloadHistory">
       </settings-checkbox>
+    </div>
+    <div class="settings-row">
       <settings-checkbox
           pref="{{prefs.browser.clear_data.cache}}"
           i18n-values="label:clearCache">
       </settings-checkbox>
+    </div>
+    <div class="settings-row">
       <settings-checkbox
           pref="{{prefs.browser.clear_data.cookies}}"
           i18n-values="label:clearCookies">
       </settings-checkbox>
+    </div>
+    <div class="settings-row">
       <settings-checkbox
           pref="{{prefs.browser.clear_data.passwords}}"
           i18n-values="label:clearPasswords">
       </settings-checkbox>
+    </div>
+    <div class="settings-row">
       <settings-checkbox
           pref="{{prefs.browser.clear_data.form_data}}"
           i18n-values="label:clearFormData">
       </settings-checkbox>
+    </div>
+    <div class="settings-row">
       <settings-checkbox
           pref="{{prefs.browser.clear_data.hosted_apps_data}}"
           i18n-values="label:clearHostedAppData">
       </settings-checkbox>
+    </div>
+    <div class="settings-row">
       <settings-checkbox
           pref="{{prefs.browser.clear_data.content_licenses}}"
           i18n-values="label:clearDeauthorizeContentLicenses">
       </settings-checkbox>
     </div>
-    <paper-button id="clearDataButton"
-        on-tap="onPerformClearBrowsingDataTap_"
-        raised i18n-content="clearBrowsingData">
-    </paper-button>
+    <div class="settings-row">
+      <paper-button id="clearDataButton"
+          on-tap="onPerformClearBrowsingDataTap_"
+          raised i18n-content="clearBrowsingData">
+      </paper-button>
+    </div>
   </template>
   <script src="clear_browsing_data_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.js b/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.js
index 7e76486..b60dd612 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.js
+++ b/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.js
@@ -42,20 +42,25 @@
      * List of options for the dropdown menu.
      * The order of entries in this array matches the
      * prefs.browser.clear_data.time_period.value enum.
+     * @private {!Array<!Array<number, string>>}
      */
     clearFromOptions_: {
       readOnly: true,
       type: Array,
       value: [
-        loadTimeData.getString('clearDataHour'),
-        loadTimeData.getString('clearDataDay'),
-        loadTimeData.getString('clearDataWeek'),
-        loadTimeData.getString('clearData4Weeks'),
-        loadTimeData.getString('clearDataEverything'),
+        [0, loadTimeData.getString('clearDataHour')],
+        [1, loadTimeData.getString('clearDataDay')],
+        [2, loadTimeData.getString('clearDataWeek')],
+        [3, loadTimeData.getString('clearData4Weeks')],
+        [4, loadTimeData.getString('clearDataEverything')],
       ],
     },
   },
 
+  ready: function() {
+    this.$.clearFrom.menuOptions = this.clearFromOptions_;
+  },
+
   attached: function() {
     var self = this;
     cr.define('SettingsClearBrowserData', function() {
diff --git a/chrome/browser/resources/settings/compiled_resources.gyp b/chrome/browser/resources/settings/compiled_resources.gyp
index ebd8c28..ae8f25e 100644
--- a/chrome/browser/resources/settings/compiled_resources.gyp
+++ b/chrome/browser/resources/settings/compiled_resources.gyp
@@ -7,6 +7,7 @@
       'target_name': 'settings_resources',
       'type': 'none',
       'dependencies': [
+        'appearance_page/compiled_resources.gyp:*',
         'internet_page/compiled_resources.gyp:*',
         'languages_page/compiled_resources.gyp:*',
         'on_startup_page/compiled_resources.gyp:*',
diff --git a/chrome/browser/resources/settings/controls/settings_checkbox.html b/chrome/browser/resources/settings/controls/settings_checkbox.html
index d9b1bc3..1e5b2cf 100644
--- a/chrome/browser/resources/settings/controls/settings_checkbox.html
+++ b/chrome/browser/resources/settings/controls/settings_checkbox.html
@@ -6,6 +6,7 @@
 <link rel="import" href="chrome://md-settings/pref_tracker/pref_tracker.html">
 
 <dom-module id="settings-checkbox">
+  <link rel="import" type="css" href="chrome://resources/cr_elements/shared.css">
   <link rel="import" type="css" href="settings_checkbox.css">
   <template>
     <cr-events id="events"></cr-events>
@@ -14,8 +15,8 @@
     <div id="outerDiv" class="layout horizontal center">
       <paper-checkbox id="checkbox" checked="{{checked}}"
           disabled="[[checkboxDisabled_(disabled, pref)]]">
-        <span id="mainLabel">{{label}}</span>
-        <span id="subLabel">{{subLabel}}</span>
+        <div id="mainLabel">{{label}}</div>
+        <div id="subLabel">{{subLabel}}</div>
       </paper-checkbox>
       <cr-policy-pref-indicator pref="[[pref]]"></cr-policy-pref-indicator>
     </div>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_font_menu.html b/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
similarity index 82%
rename from chrome/browser/resources/settings/appearance_page/appearance_font_menu.html
rename to chrome/browser/resources/settings/controls/settings_dropdown_menu.html
index 5c89494..c061826 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_font_menu.html
+++ b/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
@@ -4,11 +4,9 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 
-<dom-module id="settings-appearance-font-menu">
+<dom-module id="settings-dropdown-menu">
   <link rel="import" type="css"
       href="chrome://md-settings/settings_page/settings_page.css">
-  <link rel="import" type="css"
-      href="chrome://md-settings/appearance_page/appearance_shared.css">
   <template>
     <paper-dropdown-menu id="dropdownMenu"
         label="[[menuLabel_]]" disabled>
@@ -22,5 +20,5 @@
       </paper-menu>
     </paper-dropdown-menu>
   </template>
-  <script src="appearance_font_menu.js"></script>
+  <script src="settings_dropdown_menu.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_font_menu.js b/chrome/browser/resources/settings/controls/settings_dropdown_menu.js
similarity index 91%
rename from chrome/browser/resources/settings/appearance_page/appearance_font_menu.js
rename to chrome/browser/resources/settings/controls/settings_dropdown_menu.js
index d8a8cc2..28bddf2 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_font_menu.js
+++ b/chrome/browser/resources/settings/controls/settings_dropdown_menu.js
@@ -3,19 +3,19 @@
 // found in the LICENSE file.
 
 /**
- * 'settings-appearance-font-menu' is a control for displaying font options
- * in the appearance settings.
+ * 'settings-dropdown-menu' is a control for displaying options
+ * in the settings.
  *
  * Example:
  *
- *   <settings-appearance-font-menu pref="{{prefs.foo}}">
- *   </settings-appearance-font-menu>
+ *   <settings-dropdown-menu pref="{{prefs.foo}}">
+ *   </settings-dropdown-menu>
  *
  * @group Chrome Settings Elements
- * @element settings-appearance-font-menu
+ * @element settings-dropdown-menu
  */
 Polymer({
-  is: 'settings-appearance-font-menu',
+  is: 'settings-dropdown-menu',
 
   properties: {
     /**
@@ -83,7 +83,7 @@
     },
 
     /**
-     * Whether to show the custom font size menu item.
+     * Whether to show the 'custom' item.
      * @private
      */
     showNotFoundValue_: {
diff --git a/chrome/browser/resources/settings/controls/settings_input.html b/chrome/browser/resources/settings/controls/settings_input.html
index 66d9b3c9..99dac0f 100644
--- a/chrome/browser/resources/settings/controls/settings_input.html
+++ b/chrome/browser/resources/settings/controls/settings_input.html
@@ -6,6 +6,7 @@
 <link rel="import" href="chrome://md-settings/pref_tracker/pref_tracker.html">
 
 <dom-module id="settings-input">
+  <link rel="import" type="css" href="chrome://resources/cr_elements/shared.css">
   <link rel="import" type="css" href="settings_input.css">
   <template>
     <cr-events id="events"></cr-events>
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index 78382605..5096068 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -43,13 +43,6 @@
       <structure name="IDR_SETTINGS_CR_SETTINGS_ANIMATED_PAGES_JS"
                  file="settings_page/settings_animated_pages.js"
                  type="chrome_html" />
-      <structure name="IDR_SETTINGS_APPEARANCE_FONT_MENU_HTML"
-                 file="appearance_page/appearance_font_menu.html"
-                 type="chrome_html"
-                 allowexternalscript="true" />
-      <structure name="IDR_SETTINGS_APPEARANCE_FONT_MENU_JS"
-                 file="appearance_page/appearance_font_menu.js"
-                 type="chrome_html" />
       <structure name="IDR_SETTINGS_APPEARANCE_FONTS_PAGE_HTML"
                  file="appearance_page/appearance_fonts_page.html"
                  type="chrome_html"
@@ -184,6 +177,12 @@
       <structure name="IDR_SETTINGS_CONTROLS_CHECKBOX_CSS"
                  file="controls/settings_checkbox.css"
                  type="chrome_html" />
+      <structure name="IDR_SETTINGS_CONTROLS_DROPDOWN_MENU_HTML"
+                 file="controls/settings_dropdown_menu.html"
+                 type="chrome_html" />
+      <structure name="IDR_SETTINGS_CONTROLS_DROPDOWN_MENU_JS"
+                 file="controls/settings_dropdown_menu.js"
+                 type="chrome_html" />
       <structure name="IDR_SETTINGS_CONTROLS_INPUT_HTML"
                  file="controls/settings_input.html"
                  type="chrome_html" />
@@ -211,7 +210,7 @@
                    type="chrome_html"
                    flattenhtml="true"
                    allowexternalscript="true" />
-        <structure name="IDR_SETTINGS_DEFAULT_BROWSERE_PAGE_JS"
+        <structure name="IDR_SETTINGS_DEFAULT_BROWSER_PAGE_JS"
                    file="default_browser_page/default_browser_page.js"
                    type="chrome_html" />
       </if>
diff --git a/chrome/browser/sessions/tab_loader.cc b/chrome/browser/sessions/tab_loader.cc
index f645c86e..61e86ebb 100644
--- a/chrome/browser/sessions/tab_loader.cc
+++ b/chrome/browser/sessions/tab_loader.cc
@@ -146,6 +146,11 @@
   // LoadNextTab should only get called after we have started the tab
   // loading.
   CHECK(delegate_);
+
+  // Abort if loading is not enabled.
+  if (!loading_enabled_)
+    return;
+
   if (!tabs_to_load_.empty()) {
     // Check the memory pressure before restoring the next tab, and abort if
     // there is pressure. This is important on the Mac because of the sometimes
@@ -231,7 +236,7 @@
 
 void TabLoader::HandleTabClosedOrLoaded(NavigationController* controller) {
   RemoveTab(controller);
-  if (delegate_ && loading_enabled_)
+  if (delegate_)
     LoadNextTab();
 }
 
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index f4cec94..a5541045 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -2576,6 +2576,8 @@
   CheckSecurityState(contents, CertError::NONE,
                      content::SECURITY_STYLE_AUTHENTICATED, AuthState::NONE);
   replacements.SetHostStr("mail.example.com");
+  // blink strips the ref from requests.
+  replacements.ClearRef();
   GURL https_server_new_url = https_server_url.ReplaceComponents(replacements);
   // Verify that the current URL is the suggested URL.
   EXPECT_EQ(https_server_new_url.spec(),
diff --git a/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc b/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc
index 13caca8..befa35ba 100644
--- a/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/sync/glue/sync_backend_host_impl.h"
+#include "components/sync_driver/glue/sync_backend_host_impl.h"
 
 #include <cstddef>
 
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.cc b/chrome/browser/sync/profile_sync_components_factory_impl.cc
index 8da98d2..a7123e7 100644
--- a/chrome/browser/sync/profile_sync_components_factory_impl.cc
+++ b/chrome/browser/sync/profile_sync_components_factory_impl.cc
@@ -11,8 +11,6 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "chrome/browser/sync/glue/sync_backend_host_impl.h"
 #include "chrome/browser/sync/glue/theme_data_type_controller.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/common/channel_info.h"
@@ -37,6 +35,8 @@
 #include "components/sync_driver/data_type_manager_impl.h"
 #include "components/sync_driver/device_info_data_type_controller.h"
 #include "components/sync_driver/glue/chrome_report_unrecoverable_error.h"
+#include "components/sync_driver/glue/sync_backend_host.h"
+#include "components/sync_driver/glue/sync_backend_host_impl.h"
 #include "components/sync_driver/local_device_info_provider_impl.h"
 #include "components/sync_driver/proxy_data_type_controller.h"
 #include "components/sync_driver/sync_client.h"
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 1e4140ef..e574bf9a 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -27,8 +27,6 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "chrome/browser/sync/glue/sync_backend_host_impl.h"
 #include "chrome/browser/sync/sync_type_preference_provider.h"
 #include "components/autofill/core/common/autofill_pref_names.h"
 #include "components/browser_sync/common/browser_sync_switches.h"
@@ -46,6 +44,8 @@
 #include "components/sync_driver/data_type_controller.h"
 #include "components/sync_driver/device_info.h"
 #include "components/sync_driver/glue/chrome_report_unrecoverable_error.h"
+#include "components/sync_driver/glue/sync_backend_host.h"
+#include "components/sync_driver/glue/sync_backend_host_impl.h"
 #include "components/sync_driver/pref_names.h"
 #include "components/sync_driver/signin_manager_wrapper.h"
 #include "components/sync_driver/sync_api_component_factory.h"
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 3d14332..67e91aa4 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -22,7 +22,6 @@
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/signin/core/browser/signin_manager_base.h"
 #include "components/sync_driver/backup_rollback_controller.h"
@@ -31,6 +30,7 @@
 #include "components/sync_driver/data_type_manager_observer.h"
 #include "components/sync_driver/data_type_status_table.h"
 #include "components/sync_driver/device_info_sync_service.h"
+#include "components/sync_driver/glue/sync_backend_host.h"
 #include "components/sync_driver/local_device_info_provider.h"
 #include "components/sync_driver/protocol_event_observer.h"
 #include "components/sync_driver/startup_controller.h"
diff --git a/chrome/browser/sync/profile_sync_service_startup_unittest.cc b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
index a113b53..ac3fde9 100644
--- a/chrome/browser/sync/profile_sync_service_startup_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/chrome_sync_client.h"
-#include "chrome/browser/sync/glue/sync_backend_host_mock.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
@@ -29,6 +28,7 @@
 #include "components/signin/core/common/signin_pref_names.h"
 #include "components/sync_driver/data_type_manager.h"
 #include "components/sync_driver/data_type_manager_mock.h"
+#include "components/sync_driver/glue/sync_backend_host_mock.h"
 #include "components/sync_driver/pref_names.h"
 #include "components/sync_driver/sync_api_component_factory_mock.h"
 #include "components/sync_driver/sync_prefs.h"
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
index 2c8568b..326b0cd6 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -28,7 +28,6 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/abstract_profile_sync_service_test.h"
 #include "chrome/browser/sync/chrome_sync_client.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index 34c3d1b..7ec32ea 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/chrome_sync_client.h"
-#include "chrome/browser/sync/glue/sync_backend_host_mock.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
 #include "chrome/common/channel_info.h"
@@ -41,6 +40,7 @@
 #include "components/sync_driver/data_type_manager.h"
 #include "components/sync_driver/data_type_manager_observer.h"
 #include "components/sync_driver/fake_data_type_controller.h"
+#include "components/sync_driver/glue/sync_backend_host_mock.h"
 #include "components/sync_driver/pref_names.h"
 #include "components/sync_driver/signin_manager_wrapper.h"
 #include "components/sync_driver/sync_api_component_factory_mock.h"
diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc
index 606d9e5..ea7778be 100644
--- a/chrome/browser/sync/test_profile_sync_service.cc
+++ b/chrome/browser/sync/test_profile_sync_service.cc
@@ -14,14 +14,14 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/chrome_sync_client.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "chrome/browser/sync/glue/sync_backend_host_core.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
 #include "chrome/browser/sync/test/test_http_bridge_factory.h"
 #include "chrome/common/channel_info.h"
 #include "components/invalidation/impl/profile_invalidation_provider.h"
 #include "components/signin/core/browser/signin_manager.h"
+#include "components/sync_driver/glue/sync_backend_host.h"
+#include "components/sync_driver/glue/sync_backend_host_core.h"
 #include "components/sync_driver/signin_manager_wrapper.h"
 #include "components/sync_driver/sync_api_component_factory_mock.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index f6caf97b..25771b0 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -10,10 +10,10 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/sync/glue/sync_backend_host_impl.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync_driver/data_type_manager_impl.h"
+#include "components/sync_driver/glue/sync_backend_host_impl.h"
 #include "components/sync_driver/sync_client.h"
 #include "components/sync_driver/sync_prefs.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc
index 1b25184c..6fef9f74 100644
--- a/chrome/browser/ui/browser_ui_prefs.cc
+++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -12,6 +12,7 @@
 #include "chrome/common/pref_names.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/translate/core/common/translate_pref_names.h"
+#include "content/public/common/webrtc_ip_handling_policy.h"
 
 namespace chrome {
 
@@ -102,8 +103,11 @@
       false,
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
 #if defined(ENABLE_WEBRTC)
+  // TODO(guoweis): Remove next 2 options at M50.
   registry->RegisterBooleanPref(prefs::kWebRTCMultipleRoutesEnabled, true);
   registry->RegisterBooleanPref(prefs::kWebRTCNonProxiedUdpEnabled, true);
+  registry->RegisterStringPref(prefs::kWebRTCIPHandlingPolicy,
+                               content::kWebRTCIPHandlingDefault);
 #endif
 
   // Dictionaries to keep track of default tasks in the file browser.
diff --git a/chrome/browser/ui/cocoa/confirm_bubble_controller.h b/chrome/browser/ui/cocoa/confirm_bubble_controller.h
index cb6f6263..3887e00 100644
--- a/chrome/browser/ui/cocoa/confirm_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/confirm_bubble_controller.h
@@ -41,7 +41,7 @@
 - (BOOL)hasOkButton;
 - (BOOL)hasCancelButton;
 
-// Handle actions from the ConfirmBubbleCocoa objet.
+// Handle actions from the ConfirmBubbleCocoa object.
 - (void)accept;
 - (void)cancel;
 - (void)linkClicked;
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
index 1870844..5d17e1c9 100644
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
+++ b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
@@ -174,6 +174,9 @@
   [[self window] setContentMinSize:
       NSMakeSize(kMinimumContentWidth, kMinimumContentHeight)];
   [[[self window] contentView] setAutoresizesSubviews:YES];
+
+  // Make sourceBrowser_ get keyboard focus.
+  [[self window] makeFirstResponder:sourceBrowser_];
 }
 
 - (void)showWindow:(id)sender {
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc
index 5cb2d6e..1eb12687 100644
--- a/chrome/browser/ui/prefs/prefs_tab_helper.cc
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc
@@ -339,6 +339,8 @@
                                renderer_callback);
     pref_change_registrar_.Add(prefs::kWebRTCNonProxiedUdpEnabled,
                                renderer_callback);
+    pref_change_registrar_.Add(prefs::kWebRTCIPHandlingPolicy,
+                               renderer_callback);
 #endif
 
 #if !defined(OS_MACOSX)
diff --git a/chrome/browser/ui/toolbar/toolbar_model_impl.cc b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
index 3bdae4a..4af29ad 100644
--- a/chrome/browser/ui/toolbar/toolbar_model_impl.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
@@ -19,6 +19,7 @@
 #include "components/omnibox/browser/autocomplete_classifier.h"
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/autocomplete_match.h"
+#include "components/url_formatter/elide_url.h"
 #include "components/url_formatter/url_formatter.h"
 #include "content/public/browser/cert_store.h"
 #include "content/public/browser/navigation_controller.h"
@@ -33,6 +34,7 @@
 #include "net/cert/x509_certificate.h"
 #include "net/ssl/ssl_connection_status_flags.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/text_elider.h"
 
 using content::NavigationController;
 using content::NavigationEntry;
@@ -61,16 +63,26 @@
     languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
 
   GURL url(GetURL());
-  if (url.spec().length() > content::kMaxURLDisplayChars)
-    url = url.IsStandard() ? url.GetOrigin() : GURL(url.scheme() + ":");
   // Note that we can't unescape spaces here, because if the user copies this
   // and pastes it into another program, that program may think the URL ends at
   // the space.
-  return AutocompleteInput::FormattedStringWithEquivalentMeaning(
-      url, url_formatter::FormatUrl(
-               url, languages, url_formatter::kFormatUrlOmitAll,
-               net::UnescapeRule::NORMAL, nullptr, prefix_end, nullptr),
-      ChromeAutocompleteSchemeClassifier(profile));
+  const base::string16 formatted_text =
+      AutocompleteInput::FormattedStringWithEquivalentMeaning(
+          url, url_formatter::FormatUrl(
+                   url, languages, url_formatter::kFormatUrlOmitAll,
+                   net::UnescapeRule::NORMAL, nullptr, prefix_end, nullptr),
+          ChromeAutocompleteSchemeClassifier(profile));
+  if (formatted_text.length() <= content::kMaxURLDisplayChars)
+    return formatted_text;
+
+  // Truncating the URL breaks editing and then pressing enter, but hopefully
+  // people won't try to do much with such enormous URLs anyway. If this becomes
+  // a real problem, we could perhaps try to keep some sort of different "elided
+  // visible URL" where editing affects and reloads the "real underlying URL",
+  // but this seems very tricky for little gain.
+  return gfx::TruncateString(formatted_text, content::kMaxURLDisplayChars - 1,
+                             gfx::CHARACTER_BREAK) +
+         gfx::kEllipsisUTF16;
 }
 
 base::string16 ToolbarModelImpl::GetCorpusNameForMobile() const {
diff --git a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
index 4963fb4..44eeb9e3 100644
--- a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/metrics/field_trial.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
 #include "chrome/browser/search/search.h"
@@ -20,9 +21,10 @@
 #include "components/toolbar/toolbar_model.h"
 #include "components/variations/entropy_provider.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/ssl_status.h"
 #include "content/public/common/url_constants.h"
-
+#include "ui/gfx/text_elider.h"
 
 // Test data ------------------------------------------------------------------
 
@@ -153,6 +155,7 @@
                             const base::string16& expected_text,
                             bool would_perform_search_term_replacement,
                             bool should_display_url);
+  void NavigateAndCheckElided(const GURL& https_url);
 
  private:
   scoped_ptr<base::FieldTrialList> field_trial_list_;
@@ -224,6 +227,27 @@
   toolbar_model->set_input_in_progress(false);
 }
 
+void ToolbarModelTest::NavigateAndCheckElided(const GURL& url) {
+  // Check while loading.
+  content::NavigationController* controller =
+      &browser()->tab_strip_model()->GetWebContentsAt(0)->GetController();
+  controller->LoadURL(url, content::Referrer(), ui::PAGE_TRANSITION_LINK,
+                      std::string());
+  ToolbarModel* toolbar_model = browser()->toolbar_model();
+  const base::string16 toolbar_text_before(toolbar_model->GetText());
+  EXPECT_LT(toolbar_text_before.size(), url.spec().size());
+  EXPECT_TRUE(base::EndsWith(toolbar_text_before,
+                             base::string16(gfx::kEllipsisUTF16),
+                             base::CompareCase::SENSITIVE));
+  // Check after commit.
+  CommitPendingLoad(controller);
+  const base::string16 toolbar_text_after(toolbar_model->GetText());
+  EXPECT_LT(toolbar_text_after.size(), url.spec().size());
+  EXPECT_TRUE(base::EndsWith(toolbar_text_after,
+                             base::string16(gfx::kEllipsisUTF16),
+                             base::CompareCase::SENSITIVE));
+}
+
 class PopupToolbarModelTest : public ToolbarModelTest {
  public:
   PopupToolbarModelTest();
@@ -328,6 +352,14 @@
       base::ASCIIToUTF16("tractor supply"), true, true);
 }
 
+TEST_F(ToolbarModelTest, ShouldElideLongURLs) {
+  AddTab(browser(), GURL(url::kAboutBlankURL));
+  const std::string long_text(content::kMaxURLDisplayChars + 1024, '0');
+  NavigateAndCheckElided(
+      GURL(std::string("https://www.foo.com/?") + long_text));
+  NavigateAndCheckElided(GURL(std::string("data:abc") + long_text));
+}
+
 // Test that URL display in a popup respects the query extraction flag.
 TEST_F(PopupToolbarModelTest, ShouldDisplayURL) {
   AddTab(browser(), GURL(url::kAboutBlankURL));
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index dc7d06c..c4a9c0da 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -365,9 +365,10 @@
   const int kPreMDToolbarTopEdgeExclusion = 2;
   if (browser_view()->IsTabStripVisible())
     dest_y += kPreMDToolbarTopEdgeExclusion;
-  canvas->TileImageInt(*theme_toolbar, x + GetThemeBackgroundXInset(),
-                       dest_y - GetTopInset(), x, dest_y, w,
-                       theme_toolbar->height());
+  canvas->TileImageInt(
+      *theme_toolbar, x + GetThemeBackgroundXInset(),
+      dest_y - GetTopInset() + Tab::GetYOffsetForActiveTabBackground(),
+      x, dest_y, w, theme_toolbar->height());
 
   // Toolbar edges.
   if (browser_view()->IsTabStripVisible()) {
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index 72b4334b..daa3b3a 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -686,10 +686,10 @@
   // Tile the toolbar image starting at the frame edge on the left and where the
   // horizontal tabstrip is (or would be) on the top.
   gfx::ImageSkia* theme_toolbar = tp->GetImageSkiaNamed(IDR_THEME_TOOLBAR);
-  canvas->TileImageInt(*theme_toolbar,
-                       x + GetThemeBackgroundXInset(),
-                       bottom_y - GetTopInset(),
-                       x, bottom_y, w, theme_toolbar->height());
+  canvas->TileImageInt(
+      *theme_toolbar, x + GetThemeBackgroundXInset(),
+      bottom_y - GetTopInset() + Tab::GetYOffsetForActiveTabBackground(),
+      x, bottom_y, w, theme_toolbar->height());
 
   // Draw rounded corners for the tab.
   gfx::ImageSkia* toolbar_left_mask =
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
index 28410ee..f5863c9e 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -15,6 +15,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/material_design/material_design_controller.h"
 #include "ui/base/theme_provider.h"
+#include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
@@ -51,13 +52,7 @@
       pause_animation_(false),
       pause_animation_state_(0.0),
       bubble_widget_(NULL) {
-  if (ui::MaterialDesignController::IsModeMaterial()) {
-    // The insets for IDR_OMNIBOX_CONTENT_SETTING_BUBBLE for which to perfom
-    // nine-slicing.
-    static const int kImageInset = 4;
-    gfx::Insets insets(kImageInset, kImageInset, kImageInset, kImageInset);
-    SetBackgroundImageWithInsets(IDR_OMNIBOX_CONTENT_SETTING_BUBBLE, insets);
-  } else {
+  if (!ui::MaterialDesignController::IsModeMaterial()) {
     static const int kBackgroundImages[] =
         IMAGE_GRID(IDR_OMNIBOX_CONTENT_SETTING_BUBBLE);
     SetBackgroundImageGrid(kBackgroundImages);
@@ -113,6 +108,15 @@
       content_setting_image_model_->get_content_settings_type());
 }
 
+SkColor ContentSettingImageView::GetTextColor() const {
+  return GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_TextfieldDefaultColor);
+}
+
+SkColor ContentSettingImageView::GetBorderColor() const {
+  return gfx::kGoogleYellow700;
+}
+
 bool ContentSettingImageView::ShouldShowBackground() const {
   return slide_animator_.is_animating() || pause_animation_;
 }
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.h b/chrome/browser/ui/views/location_bar/content_setting_image_view.h
index f68232f..ec4c5b1 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.h
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.h
@@ -37,6 +37,7 @@
                                 public gfx::AnimationDelegate,
                                 public views::WidgetObserver {
  public:
+  // TODO(estade): remove |text_color| because it isn't necessary for MD.
   ContentSettingImageView(ContentSettingsType content_type,
                           LocationBarView* parent,
                           const gfx::FontList& font_list,
@@ -56,7 +57,9 @@
   // intervening "stay open" period.
   static const int kAnimationDurationMS;
 
-  // IconLabelBubbleView::
+  // IconLabelBubbleView:
+  SkColor GetTextColor() const override;
+  SkColor GetBorderColor() const override;
   bool ShouldShowBackground() const override;
   double WidthMultiplier() const override;
 
diff --git a/chrome/browser/ui/views/location_bar/ev_bubble_view.cc b/chrome/browser/ui/views/location_bar/ev_bubble_view.cc
index 1e4312d1..32a5a3d 100644
--- a/chrome/browser/ui/views/location_bar/ev_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/ev_bubble_view.cc
@@ -17,13 +17,9 @@
                           text_color,
                           parent_background_color,
                           true),
+      text_color_(text_color),
       page_info_helper_(this, location_bar) {
-  if (ui::MaterialDesignController::IsModeMaterial()) {
-    // The insets for IDR_OMNIBOX_EV_BUBBLE for which to perfom nine-slicing.
-    static const int kImageInset = 4;
-    gfx::Insets insets(kImageInset, kImageInset, kImageInset, kImageInset);
-    SetBackgroundImageWithInsets(IDR_OMNIBOX_EV_BUBBLE, insets);
-  } else {
+  if (!ui::MaterialDesignController::IsModeMaterial()) {
     static const int kBackgroundImages[] = IMAGE_GRID(IDR_OMNIBOX_EV_BUBBLE);
     SetBackgroundImageGrid(kBackgroundImages);
   }
@@ -32,6 +28,14 @@
 EVBubbleView::~EVBubbleView() {
 }
 
+SkColor EVBubbleView::GetTextColor() const {
+  return text_color_;
+}
+
+SkColor EVBubbleView::GetBorderColor() const {
+  return GetTextColor();
+}
+
 gfx::Size EVBubbleView::GetMinimumSize() const {
   return GetMinimumSizeForPreferredSize(GetPreferredSize());
 }
diff --git a/chrome/browser/ui/views/location_bar/ev_bubble_view.h b/chrome/browser/ui/views/location_bar/ev_bubble_view.h
index aae2353..1874047 100644
--- a/chrome/browser/ui/views/location_bar/ev_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/ev_bubble_view.h
@@ -20,6 +20,10 @@
   ~EVBubbleView() override;
 
   // IconLabelBubbleView:
+  SkColor GetTextColor() const override;
+  SkColor GetBorderColor() const override;
+
+  // views::View:
   gfx::Size GetMinimumSize() const override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   void OnMouseReleased(const ui::MouseEvent& event) override;
@@ -32,6 +36,10 @@
   // Returns what the minimum size would be if the preferred size were |size|.
   gfx::Size GetMinimumSizeForPreferredSize(gfx::Size size) const;
 
+  // TODO(estade): this should be gleaned from the theme instead of hardcoded in
+  // location_bar_view.cc and cached here.
+  SkColor text_color_;
+
   PageInfoHelper page_info_helper_;
 
   DISALLOW_COPY_AND_ASSIGN(EVBubbleView);
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
index 3331425..12a9e1b 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -6,6 +6,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/views/layout_constants.h"
+#include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
 #include "ui/base/resource/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
@@ -69,16 +70,6 @@
   SetLabelBackgroundColor(CalculateImageColor(background_image));
 }
 
-void IconLabelBubbleView::SetBackgroundImageWithInsets(int background_image_id,
-                                                       gfx::Insets& insets) {
-  gfx::ImageSkia* background_image =
-      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-          background_image_id);
-  background_painter_.reset(
-      views::Painter::CreateImagePainter(*background_image, insets));
-  SetLabelBackgroundColor(CalculateImageColor(background_image));
-}
-
 void IconLabelBubbleView::SetLabel(const base::string16& label) {
   label_->SetText(label);
 }
@@ -119,6 +110,19 @@
                     height());
 }
 
+void IconLabelBubbleView::OnNativeThemeChanged(
+    const ui::NativeTheme* native_theme) {
+  if (!ui::MaterialDesignController::IsModeMaterial())
+    return;
+
+  label_->SetEnabledColor(GetTextColor());
+  SkColor border_color = GetBorderColor();
+  SkColor background_color = SkColorSetA(border_color, 0x13);
+  set_background(
+      new BackgroundWith1PxBorder(background_color, border_color, false));
+  SetLabelBackgroundColor(background_color);
+}
+
 gfx::Size IconLabelBubbleView::GetSizeForLabelWidth(int width) const {
   gfx::Size size(image_->GetPreferredSize());
   if (ShouldShowBackground()) {
@@ -129,16 +133,22 @@
         (image_width ? (image_width + padding) : 0) +
         GetBubbleOuterPadding(false);
     size = gfx::Size(WidthMultiplier() * (width + non_label_width), 0);
-    size.SetToMax(background_painter_->GetMinimumSize());
+    if (!ui::MaterialDesignController::IsModeMaterial())
+      size.SetToMax(background_painter_->GetMinimumSize());
   }
 
   return size;
 }
 
-int IconLabelBubbleView::GetBubbleOuterPadding(bool by_icon) const {
+int IconLabelBubbleView::GetBubbleOuterPadding(bool start) const {
+  // When the image is empty, leading and trailing padding are equal.
+  const int extra_padding =
+      image_->GetPreferredSize().IsEmpty() || !start
+          ? GetLayoutConstant(ICON_LABEL_VIEW_TRAILING_PADDING)
+          : 0;
   return GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING) -
-      GetLayoutConstant(LOCATION_BAR_BUBBLE_HORIZONTAL_PADDING) +
-      (by_icon ? 0 : GetLayoutConstant(ICON_LABEL_VIEW_TRAILING_PADDING));
+         GetLayoutConstant(LOCATION_BAR_BUBBLE_HORIZONTAL_PADDING) +
+         extra_padding;
 }
 
 void IconLabelBubbleView::SetLabelBackgroundColor(
@@ -164,4 +174,6 @@
     return;
   if (background_painter_)
     background_painter_->Paint(canvas, size());
+  if (background())
+    background()->Paint(canvas, this);
 }
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
index 11b66726..3f74609 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
@@ -30,6 +30,7 @@
 // content settings.
 class IconLabelBubbleView : public views::View {
  public:
+  // TODO(estade): remove |text_color| which is not used for MD.
   IconLabelBubbleView(int contained_image,
                       const gfx::FontList& font_list,
                       SkColor text_color,
@@ -42,13 +43,6 @@
   // construction.
   void SetBackgroundImageGrid(const int background_images[]);
 
-  // Divides the image designated by |background_image_id| into nine regions.
-  // The four corners are specified by |insets|, the remainder are stretched to
-  // fill the background. Subclasses are required to call this or
-  // SetBackgroundImageGrid during construction.
-  void SetBackgroundImageWithInsets(int background_image_id,
-                                    gfx::Insets& insets);
-
   void SetLabel(const base::string16& label);
   void SetImage(const gfx::ImageSkia& image);
   void set_is_extension_icon(bool is_extension_icon) {
@@ -59,6 +53,13 @@
   views::ImageView* image() { return image_; }
   views::Label* label() { return label_; }
 
+  // Gets the color for displaying text.
+  virtual SkColor GetTextColor() const = 0;
+
+  // Gets the color for the border (a more transparent version of
+  // which is used for the background).
+  virtual SkColor GetBorderColor() const = 0;
+
   // Returns true when the background should be rendered.
   virtual bool ShouldShowBackground() const;
 
@@ -70,18 +71,17 @@
   // views::View:
   gfx::Size GetPreferredSize() const override;
   void Layout() override;
+  void OnNativeThemeChanged(const ui::NativeTheme* native_theme) override;
 
   const gfx::FontList& font_list() const { return label_->font_list(); }
 
   gfx::Size GetSizeForLabelWidth(int width) const;
 
  private:
-  // Amount of padding at the edges of the bubble.  If |by_icon| is true, this
-  // is the padding next to the icon; otherwise it's the padding next to the
-  // label.  (We increase padding next to the label by the amount of padding
-  // "built in" to the icon in order to make the bubble appear to have
-  // symmetrical padding.)
-  int GetBubbleOuterPadding(bool by_icon) const;
+  // Amount of padding at the edges of the bubble.  If |start| is true, this
+  // is the padding at the beginning of the bubble (left in LTR), otherwise it's
+  // the end padding.
+  int GetBubbleOuterPadding(bool start) const;
 
   // Sets a background color on |label_| based on |background_image_color| and
   // |parent_background_color_|.
@@ -91,7 +91,7 @@
   const char* GetClassName() const override;
   void OnPaint(gfx::Canvas* canvas) override;
 
-  // For painting the background.
+  // For painting the background. TODO(estade): remove post MD launch.
   scoped_ptr<views::Painter> background_painter_;
 
   // The contents of the bubble.
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
index eb28b33..02d1ff61 100644
--- a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
+++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
@@ -11,29 +11,84 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
+#include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/search_engines/template_url_service.h"
 #include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
+#include "ui/strings/grit/ui_strings.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 
+namespace {
+
+// For MD, the tab key looks just like other omnibox chips.
+class TabKeyBubbleView : public IconLabelBubbleView {
+ public:
+  TabKeyBubbleView(const gfx::FontList& font_list,
+                   SkColor text_color,
+                   SkColor background_color);
+  ~TabKeyBubbleView() override;
+
+ private:
+  // IconLabelBubbleView:
+  SkColor GetTextColor() const override;
+  SkColor GetBorderColor() const override;
+
+  SkColor text_color_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabKeyBubbleView);
+};
+
+TabKeyBubbleView::TabKeyBubbleView(const gfx::FontList& font_list,
+                                   SkColor text_color,
+                                   SkColor background_color)
+    : IconLabelBubbleView(0, font_list, SK_ColorRED, background_color, false),
+      text_color_(text_color) {
+  SetLabel(l10n_util::GetStringUTF16(IDS_APP_TAB_KEY));
+}
+
+TabKeyBubbleView::~TabKeyBubbleView() {}
+
+SkColor TabKeyBubbleView::GetTextColor() const {
+  return text_color_;
+}
+
+SkColor TabKeyBubbleView::GetBorderColor() const {
+  return text_color_;
+}
+
+}  // namespace
 
 KeywordHintView::KeywordHintView(Profile* profile,
                                  const gfx::FontList& font_list,
+                                 const gfx::FontList& bubble_font_list,
+                                 int bubble_height,
                                  SkColor text_color,
                                  SkColor background_color)
     : profile_(profile),
-      tab_image_(new views::ImageView()) {
+      leading_label_(nullptr),
+      tab_key_view_(nullptr),
+      trailing_label_(nullptr),
+      tab_key_height_(bubble_height) {
   leading_label_ =
       CreateLabel(font_list, text_color, background_color);
-  tab_image_->SetImage(
-      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-          IDR_OMNIBOX_KEYWORD_HINT_TAB));
-  AddChildView(tab_image_);
+  if (ui::MaterialDesignController::IsModeMaterial()) {
+    tab_key_view_ =
+        new TabKeyBubbleView(bubble_font_list, text_color, background_color);
+  } else {
+    views::ImageView* tab_image = new views::ImageView();
+    tab_image->SetImage(
+        ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+            IDR_OMNIBOX_KEYWORD_HINT_TAB));
+    tab_key_view_ = tab_image;
+  }
+  AddChildView(tab_key_view_);
   trailing_label_ =
       CreateLabel(font_list, text_color, background_color);
 }
@@ -68,28 +123,28 @@
 gfx::Size KeywordHintView::GetPreferredSize() const {
   // Height will be ignored by the LocationBarView.
   return gfx::Size(leading_label_->GetPreferredSize().width() +
-                       tab_image_->GetPreferredSize().width() +
+                       tab_key_view_->GetPreferredSize().width() +
                        trailing_label_->GetPreferredSize().width(),
                    0);
 }
 
 gfx::Size KeywordHintView::GetMinimumSize() const {
   // Height will be ignored by the LocationBarView.
-  return tab_image_->GetPreferredSize();
+  return tab_key_view_->GetPreferredSize();
 }
 
 void KeywordHintView::Layout() {
-  int tab_width = tab_image_->GetPreferredSize().width();
+  int tab_width = tab_key_view_->GetPreferredSize().width();
   bool show_labels = (width() != tab_width);
   gfx::Size leading_size(leading_label_->GetPreferredSize());
   leading_label_->SetBounds(0, 0, show_labels ? leading_size.width() : 0,
                             height());
-  tab_image_->SetBounds(leading_label_->bounds().right(), 0, tab_width,
-                        height());
+  tab_key_view_->SetBounds(leading_label_->bounds().right(),
+                           (height() - tab_key_height_) / 2, tab_width,
+                           tab_key_height_);
   gfx::Size trailing_size(trailing_label_->GetPreferredSize());
-  trailing_label_->SetBounds(tab_image_->bounds().right(), 0,
-                             show_labels ? trailing_size.width() : 0,
-                             height());
+  trailing_label_->SetBounds(tab_key_view_->bounds().right(), 0,
+                             show_labels ? trailing_size.width() : 0, height());
 }
 
 const char* KeywordHintView::GetClassName() const {
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.h b/chrome/browser/ui/views/location_bar/keyword_hint_view.h
index 94bdaf9..dfde9f29 100644
--- a/chrome/browser/ui/views/location_bar/keyword_hint_view.h
+++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.h
@@ -34,6 +34,8 @@
  public:
   KeywordHintView(Profile* profile,
                   const gfx::FontList& font_list,
+                  const gfx::FontList& bubble_font_list,
+                  int tab_key_height,
                   SkColor text_color,
                   SkColor background_color);
   ~KeywordHintView() override;
@@ -54,9 +56,14 @@
                             SkColor background_color);
 
   Profile* profile_;
+
   views::Label* leading_label_;
-  views::ImageView* tab_image_;
+  views::View* tab_key_view_;
   views::Label* trailing_label_;
+
+  // Height of the tab key view (only used in MD).
+  int tab_key_height_;
+
   base::string16 keyword_;
 
   DISALLOW_COPY_AND_ASSIGN(KeywordHintView);
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 4eee58e1..533fef3f 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -82,6 +82,7 @@
 #include "ui/events/event.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/canvas.h"
+#include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_skia_operations.h"
@@ -259,10 +260,7 @@
   ime_inline_autocomplete_view_->SetVisible(false);
   AddChildView(ime_inline_autocomplete_view_);
 
-  const SkColor selected_text_color = GetColor(
-      SecurityStateModel::NONE, ui::MaterialDesignController::IsModeMaterial()
-                                    ? KEYWORD_SEARCH_TEXT
-                                    : TEXT);
+  const SkColor selected_text_color = GetColor(SecurityStateModel::NONE, TEXT);
   selected_keyword_view_ = new SelectedKeywordView(
       bubble_font_list, selected_text_color, background_color, profile());
   AddChildView(selected_keyword_view_);
@@ -276,7 +274,8 @@
   AddChildView(suggested_text_view_);
 
   keyword_hint_view_ = new KeywordHintView(
-      profile(), font_list,
+      profile(), font_list, bubble_font_list,
+      bubble_height + 2 * kBubbleInteriorVerticalPadding,
       GetColor(SecurityStateModel::NONE, LocationBarView::DEEMPHASIZED_TEXT),
       background_color);
   AddChildView(keyword_hint_view_);
@@ -366,10 +365,8 @@
       switch (security_level) {
         case SecurityStateModel::EV_SECURE:
         case SecurityStateModel::SECURE:
-          if (ui::MaterialDesignController::IsModeMaterial())
-            color = SkColorSetRGB(11, 128, 67);
-          else
-            color = SkColorSetRGB(7, 149, 0);
+          color = ui::MaterialDesignController::IsModeMaterial() ?
+              gfx::kGoogleGreen700 : SkColorSetRGB(7, 149, 0);
           break;
 
         case SecurityStateModel::SECURITY_POLICY_WARNING:
@@ -377,7 +374,8 @@
           break;
 
         case SecurityStateModel::SECURITY_ERROR:
-          color = SkColorSetRGB(162, 0, 0);
+          color = ui::MaterialDesignController::IsModeMaterial() ?
+              gfx::kGoogleRed700 : SkColorSetRGB(162, 0, 0);
           break;
 
         case SecurityStateModel::SECURITY_WARNING:
@@ -392,9 +390,6 @@
           color, GetColor(security_level, BACKGROUND));
     }
 
-    case KEYWORD_SEARCH_TEXT:
-      return SkColorSetRGB(51, 103, 214);
-
     default:
       NOTREACHED();
       return GetColor(security_level, TEXT);
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index 9d4d1bc..ebd57552 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -125,7 +125,6 @@
     SELECTED_TEXT,
     DEEMPHASIZED_TEXT,
     SECURITY_TEXT,
-    KEYWORD_SEARCH_TEXT,
   };
 
   LocationBarView(Browser* browser,
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
index ccf8207b..15eea50 100644
--- a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
+++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
@@ -32,13 +32,7 @@
                           parent_background_color,
                           false),
       profile_(profile) {
-  if (ui::MaterialDesignController::IsModeMaterial()) {
-    // The inset for IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE for which to perfom
-    // nine-slicing.
-    static const int kImageInset = 4;
-    gfx::Insets insets(kImageInset, kImageInset, kImageInset, kImageInset);
-    SetBackgroundImageWithInsets(IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE, insets);
-  } else {
+  if (!ui::MaterialDesignController::IsModeMaterial()) {
     static const int kBackgroundImages[] =
         IMAGE_GRID(IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE);
     SetBackgroundImageGrid(kBackgroundImages);
@@ -54,15 +48,22 @@
 
 void SelectedKeywordView::ResetImage() {
   if (ui::MaterialDesignController::IsModeMaterial()) {
-    SkColor link_color =
-        GetNativeTheme()->GetSystemColor(ui::NativeTheme::kColorId_LinkEnabled);
     SetImage(gfx::CreateVectorIcon(gfx::VectorIconId::KEYWORD_SEARCH, 16,
-                                   link_color));
+                                   GetTextColor()));
   } else {
     SetImage(*GetThemeProvider()->GetImageSkiaNamed(IDR_OMNIBOX_SEARCH));
   }
 }
 
+SkColor SelectedKeywordView::GetTextColor() const {
+  return GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_LinkEnabled);
+}
+
+SkColor SelectedKeywordView::GetBorderColor() const {
+  return GetTextColor();
+}
+
 gfx::Size SelectedKeywordView::GetPreferredSize() const {
   // Height will be ignored by the LocationBarView.
   return GetSizeForLabelWidth(full_label_.GetPreferredSize().width());
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.h b/chrome/browser/ui/views/location_bar/selected_keyword_view.h
index 974ead1a..3db92b3 100644
--- a/chrome/browser/ui/views/location_bar/selected_keyword_view.h
+++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.h
@@ -31,6 +31,10 @@
   void ResetImage();
 
   // IconLabelBubbleView:
+  SkColor GetTextColor() const override;
+  SkColor GetBorderColor() const override;
+
+  // views::View:
   gfx::Size GetPreferredSize() const override;
   gfx::Size GetMinimumSize() const override;
   void Layout() override;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 91b8d2a..ccd5786c 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -625,6 +625,17 @@
   return kImmersiveTabHeight;
 }
 
+// static
+int Tab::GetYOffsetForActiveTabBackground() {
+  // The computed value here is strangely less than the height of the area atop
+  // the tab that doesn't get a background painted; otherwise, we could compute
+  // the value by simply using GetLayoutInsets(TAB).top().  My suspicion is that
+  // originally there was some sort of off-by-one error in how this background
+  // was painted, and theme authors compensated; now we're stuck perpetuating it
+  // as a result.
+  return -GetLayoutConstant(TAB_TOP_EXCLUSION_HEIGHT) - 1;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Tab, AnimationDelegate overrides:
 
@@ -1130,9 +1141,10 @@
   const int kActiveTabFillId = IDR_THEME_TOOLBAR;
   const bool has_custom_image =
       GetThemeProvider()->HasCustomImage(kActiveTabFillId);
+  const int y_offset = GetYOffsetForActiveTabBackground();
   if (IsActive()) {
     PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId,
-                                  has_custom_image, 0);
+                                  has_custom_image, y_offset);
   } else {
     if (pinned_title_change_animation_ &&
         pinned_title_change_animation_->is_animating())
@@ -1145,7 +1157,7 @@
       canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff),
                              GetLocalBounds());
       PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId,
-                                    has_custom_image, 0);
+                                    has_custom_image, y_offset);
       canvas->Restore();
     }
   }
@@ -1187,7 +1199,7 @@
   // should be at the top of the tab. Otherwise, we assume that the background
   // image is a composited foreground + frame image.
   const int y_offset = GetThemeProvider()->HasCustomImage(fill_id) ?
-      0 : background_offset_.y();
+      -GetLayoutConstant(TAB_TOP_EXCLUSION_HEIGHT) : background_offset_.y();
 
   // We only cache the image when it's the default image and we're not hovered,
   // to avoid caching a background image that isn't the same for all tabs.
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index 38ea62c..7b42ee6f 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -154,6 +154,15 @@
   // Returns the height for immersive mode tabs.
   static int GetImmersiveHeight();
 
+  // Returns the Y offset within the tab background image to begin drawing at
+  // the top of the active tab bounds.  This is a negative value, which will
+  // result in the top of the tab background image being drawn below the top of
+  // the tab.  None of this offset area is actually visible.
+  //
+  // This is necessary for correct vertical alignment of the frame, tab, and
+  // toolbar images with custom themes.
+  static int GetYOffsetForActiveTabBackground();
+
  private:
   friend class TabTest;
   FRIEND_TEST_ALL_PREFIXES(TabTest, CloseButtonLayout);
diff --git a/chrome/browser/ui/views/uninstall_view.cc b/chrome/browser/ui/views/uninstall_view.cc
index b8f4b845..5c2bd6a 100644
--- a/chrome/browser/ui/views/uninstall_view.cc
+++ b/chrome/browser/ui/views/uninstall_view.cc
@@ -80,8 +80,10 @@
   if (dist->GetDefaultBrowserControlPolicy() !=
           BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED &&
       ShellIntegration::GetDefaultBrowser() == ShellIntegration::IS_DEFAULT &&
-      (ShellIntegration::CanSetAsDefaultBrowser() !=
-          ShellIntegration::SET_DEFAULT_INTERACTIVE)) {
+      (ShellIntegration::CanSetAsDefaultBrowser() ==
+          ShellIntegration::SET_DEFAULT_NOT_ALLOWED ||
+       ShellIntegration::CanSetAsDefaultBrowser() ==
+          ShellIntegration::SET_DEFAULT_UNATTENDED)) {
     browsers_.reset(new BrowsersMap());
     ShellUtil::GetRegisteredBrowsers(dist, browsers_.get());
     if (!browsers_->empty()) {
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index 5422199..cb5719e 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -63,6 +63,8 @@
   source->AddResourcePath("item.css", IDR_MD_EXTENSIONS_ITEM_CSS);
   source->AddResourcePath("item.html", IDR_MD_EXTENSIONS_ITEM_HTML);
   source->AddResourcePath("item.js", IDR_MD_EXTENSIONS_ITEM_JS);
+  source->AddResourcePath("service.html", IDR_MD_EXTENSIONS_SERVICE_HTML);
+  source->AddResourcePath("service.js", IDR_MD_EXTENSIONS_SERVICE_JS);
   source->AddResourcePath("sidebar.css", IDR_MD_EXTENSIONS_SIDEBAR_CSS);
   source->AddResourcePath("sidebar.html", IDR_MD_EXTENSIONS_SIDEBAR_HTML);
   source->AddResourcePath("sidebar.js", IDR_MD_EXTENSIONS_SIDEBAR_JS);
diff --git a/chrome/browser/ui/webui/options/certificate_manager_handler.cc b/chrome/browser/ui/webui/options/certificate_manager_handler.cc
index cf03f83..2502cd98 100644
--- a/chrome/browser/ui/webui/options/certificate_manager_handler.cc
+++ b/chrome/browser/ui/webui/options/certificate_manager_handler.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/webui/options/certificate_manager_handler.h"
 
+#include <errno.h>
+
 #include <algorithm>
 #include <map>
 
diff --git a/chrome/browser/ui/webui/options/create_profile_handler.cc b/chrome/browser/ui/webui/options/create_profile_handler.cc
index f90d2c9a..33f38cf 100644
--- a/chrome/browser/ui/webui/options/create_profile_handler.cc
+++ b/chrome/browser/ui/webui/options/create_profile_handler.cc
@@ -12,6 +12,7 @@
 #include "base/value_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_metrics.h"
 #include "chrome/browser/profiles/profiles_state.h"
@@ -86,11 +87,16 @@
   profile_creation_start_time_ = base::TimeTicks::Now();
 
   base::string16 name;
-  std::string icon;
+  std::string icon_url;
   bool create_shortcut = false;
-  if (args->GetString(0, &name) && args->GetString(1, &icon)) {
+  if (args->GetString(0, &name) && args->GetString(1, &icon_url)) {
+    DCHECK(base::IsStringASCII(icon_url));
     base::TrimWhitespace(name, base::TRIM_ALL, &name);
     CHECK(!name.empty());
+#ifndef NDEBUG
+    size_t icon_index;
+    DCHECK(profiles::IsDefaultAvatarIconUrl(icon_url, &icon_index));
+#endif
     args->GetBoolean(2, &create_shortcut);
   }
   std::string supervised_user_id;
@@ -102,7 +108,7 @@
   ProfileMetrics::LogProfileAddNewUser(ProfileMetrics::ADD_NEW_USER_DIALOG);
 
   profile_path_being_created_ = ProfileManager::CreateMultiProfileAsync(
-      name, icon,
+      name, icon_url,
       base::Bind(&CreateProfileHandler::OnProfileCreated,
                  weak_ptr_factory_.GetWeakPtr(),
                  create_shortcut,
diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.cc b/chrome/browser/ui/webui/options/manage_profile_handler.cc
index 04754bb..e9125964 100644
--- a/chrome/browser/ui/webui/options/manage_profile_handler.cc
+++ b/chrome/browser/ui/webui/options/manage_profile_handler.cc
@@ -297,19 +297,23 @@
   base::ListValue image_url_list;
   base::ListValue default_name_list;
 
-  // First add the GAIA picture if it's available.
   const ProfileInfoCache& cache =
       g_browser_process->profile_manager()->GetProfileInfoCache();
-  Profile* profile = Profile::FromWebUI(web_ui());
-  size_t profile_index = cache.GetIndexOfProfileWithPath(profile->GetPath());
-  if (profile_index != std::string::npos) {
-    const gfx::Image* icon =
-        cache.GetGAIAPictureOfProfileAtIndex(profile_index);
-    if (icon) {
-      gfx::Image icon2 = profiles::GetAvatarIconForWebUI(*icon, true);
-      gaia_picture_url_ = webui::GetBitmapDataUrl(icon2.AsBitmap());
-      image_url_list.AppendString(gaia_picture_url_);
-      default_name_list.AppendString(std::string());
+
+  // In manage mode, first add the GAIA picture if it is available. No GAIA
+  // picture in create mode.
+  if (mode.GetString() == kManageProfileIdentifier) {
+    Profile* profile = Profile::FromWebUI(web_ui());
+    size_t profile_index = cache.GetIndexOfProfileWithPath(profile->GetPath());
+    if (profile_index != std::string::npos) {
+      const gfx::Image* icon =
+          cache.GetGAIAPictureOfProfileAtIndex(profile_index);
+      if (icon) {
+        gfx::Image icon2 = profiles::GetAvatarIconForWebUI(*icon, true);
+        gaia_picture_url_ = webui::GetBitmapDataUrl(icon2.AsBitmap());
+        image_url_list.AppendString(gaia_picture_url_);
+        default_name_list.AppendString(std::string());
+      }
     }
   }
 
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 43257cf..3855ee3 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -870,6 +870,8 @@
     'chrome_browser_android_sources': [
       'browser/android/background_sync_launcher_android.cc',
       'browser/android/background_sync_launcher_android.h',
+      'browser/android/data_usage/data_use_tab_ui_manager_android.cc',
+      'browser/android/data_usage/data_use_tab_ui_manager_android.h',
       'browser/download/download_request_infobar_delegate_android.cc',
       'browser/download/download_request_infobar_delegate_android.h',
       'browser/geolocation/geolocation_infobar_delegate_android.cc',
@@ -1781,9 +1783,10 @@
       'android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java',
       'android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java',
       'android/java/src/org/chromium/chrome/browser/cookies/CookiesFetcher.java',
-      'android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java',
       'android/java/src/org/chromium/chrome/browser/DevToolsServer.java',
       'android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java',
+      'android/java/src/org/chromium/chrome/browser/datausage/DataUseTabUIManager.java',
+      'android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java',
       'android/java/src/org/chromium/chrome/browser/document/DocumentWebContentsDelegate.java',
       'android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerServiceFactory.java',
       'android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerTabUtils.java',
@@ -2877,12 +2880,6 @@
       'browser/sync/chrome_sync_client.h',
       'browser/sync/glue/extensions_activity_monitor.cc',
       'browser/sync/glue/extensions_activity_monitor.h',
-      'browser/sync/glue/sync_backend_host.cc',
-      'browser/sync/glue/sync_backend_host.h',
-      'browser/sync/glue/sync_backend_host_core.cc',
-      'browser/sync/glue/sync_backend_host_core.h',
-      'browser/sync/glue/sync_backend_host_impl.cc',
-      'browser/sync/glue/sync_backend_host_impl.h',
       'browser/sync/glue/sync_start_util.cc',
       'browser/sync/glue/sync_start_util.h',
       'browser/sync/glue/synced_tab_delegate_android.cc',
diff --git a/chrome/chrome_repack_locales.gni b/chrome/chrome_repack_locales.gni
index 955c5f1..47a431d6 100644
--- a/chrome/chrome_repack_locales.gni
+++ b/chrome/chrome_repack_locales.gni
@@ -86,19 +86,23 @@
     if (is_chrome_branded) {
       sources += [
         "${root_gen_dir}/chrome/google_chrome_strings_${locale}.pak",
+        "${root_gen_dir}/chrome/settings_google_chrome_strings.pak",
         "${root_gen_dir}/components/strings/components_google_chrome_strings_${locale}.pak",
       ]
       deps += [
         "//chrome/app:google_chrome_strings",
+        "//chrome/app:settings_google_chrome_strings",
         "//components/strings:components_google_chrome_strings",
       ]
     } else {
       sources += [
         "${root_gen_dir}/chrome/chromium_strings_${locale}.pak",
+        "${root_gen_dir}/chrome/settings_chromium_strings.pak",
         "${root_gen_dir}/components/strings/components_chromium_strings_${locale}.pak",
       ]
       deps += [
         "//chrome/app:chromium_strings",
+        "//chrome/app:settings_chromium_strings",
         "//components/strings:components_chromium_strings",
       ]
     }
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index e56355dc..129e1be 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -959,6 +959,7 @@
       'test/data/webui/async_gen.js',
       'test/data/webui/certificate_viewer_dialog_test.js',
       'test/data/webui/chrome_send_browsertest.js',
+      'test/data/webui/extensions/cr_extensions_browsertest.js',
       'test/data/webui/history_browsertest.js',
       'test/data/webui/md_downloads/downloads_browsertest.js',
       'test/data/webui/mock4js_browsertest.js',
@@ -3190,7 +3191,7 @@
           'conditions': [
             ['OS=="linux" or OS=="mac"', {
               'dependencies': [
-                '../breakpad/breakpad.gyp:dump_syms',
+                '../breakpad/breakpad.gyp:dump_syms#host',
               ],
             }],
             ['OS=="mac"', {
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 5f3f0f4d..6a96a8f 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -223,8 +223,6 @@
       'browser/sync/backend_migrator_unittest.cc',
       'browser/sync/glue/search_engine_data_type_controller_unittest.cc',
       'browser/sync/glue/sync_backend_host_impl_unittest.cc',
-      'browser/sync/glue/sync_backend_host_mock.cc',
-      'browser/sync/glue/sync_backend_host_mock.h',
       'browser/sync/profile_sync_auth_provider_unittest.cc',
       'browser/sync/profile_sync_components_factory_impl_unittest.cc',
       'browser/sync/profile_sync_service_autofill_unittest.cc',
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index bb46d0e..a38c2552 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -201,13 +201,15 @@
 }
 
 content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
-                                                const std::string& version) {
+                                                const std::string& version,
+                                                bool is_debug) {
   content::PepperPluginInfo plugin;
 
   plugin.is_out_of_process = true;
   plugin.name = content::kFlashPluginName;
   plugin.path = path;
   plugin.permissions = chrome::kPepperFlashPermissions;
+  plugin.is_debug = is_debug;
 
   std::vector<std::string> flash_version_numbers = base::SplitString(
       version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
@@ -250,7 +252,7 @@
           switches::kPpapiFlashVersion);
 
   plugins->push_back(
-      CreatePepperFlashInfo(base::FilePath(flash_path), flash_version));
+      CreatePepperFlashInfo(base::FilePath(flash_path), flash_version, false));
 }
 
 #if defined(OS_LINUX)
@@ -284,7 +286,7 @@
                         "bundled or system plugin.";
         return false;
       }
-      *plugin = CreatePepperFlashInfo(flash_path, version);
+      *plugin = CreatePepperFlashInfo(flash_path, version, false);
       return true;
     }
     LOG(ERROR)
@@ -313,14 +315,13 @@
   if (!PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &flash_path))
     return false;
 
-  *plugin = CreatePepperFlashInfo(flash_path, FLAPPER_VERSION_STRING);
+  *plugin = CreatePepperFlashInfo(flash_path, FLAPPER_VERSION_STRING, false);
   return true;
 #else
   return false;
 #endif  // FLAPPER_AVAILABLE
 }
 
-#if defined(FLAPPER_AVAILABLE)
 bool IsSystemFlashScriptDebuggerPresent() {
 #if defined(OS_WIN)
   const wchar_t kFlashRegistryRoot[] =
@@ -338,18 +339,19 @@
   return false;
 #endif
 }
-#endif
 
 bool GetSystemPepperFlash(content::PepperPluginInfo* plugin) {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  bool system_flash_is_debug = IsSystemFlashScriptDebuggerPresent();
 
 #if defined(FLAPPER_AVAILABLE)
   // If flapper is available, only try the system plugin if either:
   // --disable-bundled-ppapi-flash is specified, or the system debugger is the
   // Flash Script Debugger.
-  if (!command_line->HasSwitch(switches::kDisableBundledPpapiFlash) &&
-      !IsSystemFlashScriptDebuggerPresent())
+  if (!(command_line->HasSwitch(switches::kDisableBundledPpapiFlash) ||
+        system_flash_is_debug)) {
     return false;
+  }
 #endif  // defined(FLAPPER_AVAILABLE)
 
   // Do not try and find System Pepper Flash if there is a specific path on
@@ -383,7 +385,8 @@
   if (!chrome::CheckPepperFlashManifest(*manifest, &version))
     return false;
 
-  *plugin = CreatePepperFlashInfo(flash_filename, version.GetString());
+  *plugin = CreatePepperFlashInfo(flash_filename, version.GetString(),
+                                  system_flash_is_debug);
   return true;
 }
 #endif  //  defined(ENABLE_PLUGINS)
@@ -467,7 +470,10 @@
       plugins.begin(), plugins.end(),
       [](content::PepperPluginInfo* x, content::PepperPluginInfo* y) {
         Version version_x(x->version);
-        DCHECK(version_x.IsValid());
+        Version version_y(y->version);
+        DCHECK(version_x.IsValid() && version_y.IsValid());
+        if (version_x.Equals(version_y))
+          return !x->is_debug && y->is_debug;
         return version_x.IsOlderThan(y->version);
       });
   return it != plugins.end() ? *it : nullptr;
diff --git a/chrome/common/chrome_content_client.h b/chrome/common/chrome_content_client.h
index 9a4db246..51f13112 100644
--- a/chrome/common/chrome_content_client.h
+++ b/chrome/common/chrome_content_client.h
@@ -44,7 +44,9 @@
       content::PepperPluginInfo::PPP_InitializeModuleFunc initialize_module,
       content::PepperPluginInfo::PPP_ShutdownModuleFunc shutdown_module);
 
-  // This returns the most recent plugin based on the plugin versions.
+  // This returns the most recent plugin based on the plugin versions. In the
+  // event of a tie, a debug plugin will be considered more recent than a
+  // non-debug plugin.
   // It does not make sense to call this on a vector that contains more than one
   // plugin type. This function may return a nullptr if given an empty vector.
   // The method is only visible for testing purposes.
diff --git a/chrome/common/chrome_content_client_unittest.cc b/chrome/common/chrome_content_client_unittest.cc
index 62591a9d..2456a93 100644
--- a/chrome/common/chrome_content_client_unittest.cc
+++ b/chrome/common/chrome_content_client_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
 #include "base/strings/string_split.h"
 #include "content/public/common/content_switches.h"
 #include "extensions/common/constants.h"
@@ -91,39 +90,75 @@
 
 #if defined(ENABLE_PLUGINS)
 TEST(ChromeContentClientTest, FindMostRecent) {
-  ScopedVector<content::PepperPluginInfo> vector1;
+  std::vector<content::PepperPluginInfo*> version_vector;
   // Test an empty vector.
-  EXPECT_EQ(ChromeContentClient::FindMostRecentPlugin(vector1.get()), nullptr);
+  EXPECT_EQ(nullptr, ChromeContentClient::FindMostRecentPlugin(version_vector));
 
   // Now test the vector with one element.
-  content::PepperPluginInfo* info1 = new content::PepperPluginInfo();
-  info1->version = "1.0.0.0";
-  vector1.push_back(info1);
-  EXPECT_EQ(ChromeContentClient::FindMostRecentPlugin(vector1.get()), info1);
+  content::PepperPluginInfo info1;
+  info1.version = "1.0.0.0";
+  version_vector.push_back(&info1);
+
+  content::PepperPluginInfo* most_recent =
+      ChromeContentClient::FindMostRecentPlugin(version_vector);
+  EXPECT_EQ("1.0.0.0", most_recent->version);
 
   // Now do the generic test of a complex vector.
-  content::PepperPluginInfo* info2 = new content::PepperPluginInfo();
-  info2->version = "2.0.0.1";
-  content::PepperPluginInfo* info3 = new content::PepperPluginInfo();
-  info3->version = "3.5.6.7";
-  content::PepperPluginInfo* info4 = new content::PepperPluginInfo();
-  info4->version = "4.0.0.153";
-  content::PepperPluginInfo* info5 = new content::PepperPluginInfo();
-  info5->version = "5.0.12.1";
-  content::PepperPluginInfo* info6_12 = new content::PepperPluginInfo();
-  info6_12->version = "6.0.0.12";
-  content::PepperPluginInfo* info6_13 = new content::PepperPluginInfo();
-  info6_13->version = "6.0.0.13";
+  content::PepperPluginInfo info2;
+  info2.version = "2.0.0.1";
+  content::PepperPluginInfo info3;
+  info3.version = "3.5.6.7";
+  content::PepperPluginInfo info4;
+  info4.version = "4.0.0.153";
+  content::PepperPluginInfo info5;
+  info5.version = "5.0.12.1";
+  content::PepperPluginInfo info6_12;
+  info6_12.version = "6.0.0.12";
+  content::PepperPluginInfo info6_13;
+  info6_13.version = "6.0.0.13";
+  content::PepperPluginInfo info6_13_d;
+  info6_13_d.version = "6.0.0.13";
+  info6_13_d.is_debug = true;
 
-  ScopedVector<content::PepperPluginInfo> vector2;
-  vector2.push_back(info4);
-  vector2.push_back(info2);
-  vector2.push_back(info6_13);
-  vector2.push_back(info3);
-  vector2.push_back(info5);
-  vector2.push_back(info6_12);
+  version_vector.clear();
+  version_vector.push_back(&info4);
+  version_vector.push_back(&info2);
+  version_vector.push_back(&info6_13);
+  version_vector.push_back(&info3);
+  version_vector.push_back(&info5);
+  version_vector.push_back(&info6_12);
+  version_vector.push_back(&info6_13_d);
 
-  EXPECT_EQ(ChromeContentClient::FindMostRecentPlugin(vector2.get()), info6_13);
+  most_recent = ChromeContentClient::FindMostRecentPlugin(version_vector);
+  EXPECT_EQ("6.0.0.13", most_recent->version);
+  EXPECT_EQ(true, most_recent->is_debug);
+
+  // Check vector order doesn't matter.
+  version_vector.clear();
+  version_vector.push_back(&info6_13_d);
+  version_vector.push_back(&info6_12);
+  version_vector.push_back(&info5);
+  version_vector.push_back(&info3);
+  version_vector.push_back(&info6_13);
+  version_vector.push_back(&info2);
+  version_vector.push_back(&info4);
+
+  most_recent = ChromeContentClient::FindMostRecentPlugin(version_vector);
+  EXPECT_EQ("6.0.0.13", most_recent->version);
+  EXPECT_EQ(true, most_recent->is_debug);
+
+  // Check higher versions still trump debugger.
+  content::PepperPluginInfo info5_d;
+  info5_d.version = "5.0.12.1";
+  info5_d.is_debug = true;
+
+  version_vector.clear();
+  version_vector.push_back(&info5_d);
+  version_vector.push_back(&info6_12);
+
+  most_recent = ChromeContentClient::FindMostRecentPlugin(version_vector);
+  EXPECT_EQ("6.0.0.12", most_recent->version);
+  EXPECT_EQ(false, most_recent->is_debug);
 }
 #endif  // defined(ENABLE_PLUGINS)
 
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index bf78d6317..a76cc807 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -436,9 +436,6 @@
 // Enables the Material Design policy page at chrome://md-policy.
 const char kEnableMaterialDesignPolicyPage[]  = "enable-md-policy-page";
 
-// Enables Media Router.
-const char kEnableMediaRouter[]             = "enable-media-router";
-
 // Runs the Native Client inside the renderer process and enables GPU plugin
 // (internally adds lEnableGpuPlugin to the command line).
 const char kEnableNaCl[]                    = "enable-nacl";
@@ -720,6 +717,9 @@
 // Forces the maximum disk space to be used by the media cache, in bytes.
 const char kMediaCacheSize[]                = "media-cache-size";
 
+// Enables Media Router.
+const char kMediaRouter[]                   = "media-router";
+
 // Enables histograming of tasks served by MessageLoop. See
 // about:histograms/Loop for results, which show frequency of messages on each
 // thread, including APC count, object signalling count, etc.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 59d930ab..bb2ccdec 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -125,7 +125,6 @@
 extern const char kEnableMaterialDesignDownloads[];
 extern const char kEnableMaterialDesignExtensions[];
 extern const char kEnableMaterialDesignPolicyPage[];
-extern const char kEnableMediaRouter[];
 extern const char kEnableNaCl[];
 extern const char kEnableNavigationTracing[];
 extern const char kEnableNetBenchmarking[];
@@ -202,6 +201,7 @@
 extern const char kMarkNonSecureAsNeutral[];
 extern const char kMarkNonSecureAsNonSecure[];
 extern const char kMediaCacheSize[];
+extern const char kMediaRouter[];
 extern const char kMessageLoopHistogrammer[];
 extern const char kMetricsRecordingOnly[];
 extern const char kMonitoringDestinationID[];
diff --git a/chrome/common/extensions/api/privacy.json b/chrome/common/extensions/api/privacy.json
index 70140c6..f235aaf 100644
--- a/chrome/common/extensions/api/privacy.json
+++ b/chrome/common/extensions/api/privacy.json
@@ -6,6 +6,14 @@
   {
     "namespace": "privacy",
     "description": "Use the <code>chrome.privacy</code> API to control usage of the features in Chrome that can affect a user's privacy. This API relies on the <a href='types#ChromeSetting'>ChromeSetting prototype of the type API</a> for getting and setting Chrome's configuration.",
+    "types": [
+      {
+        "id": "IPHandlingPolicy",
+        "type": "string",
+        "enum": ["default", "default_public_and_private_interfaces", "default_public_interface_only", "disable_non_proxied_udp"],
+        "description": "The IP handling policy of WebRTC."
+      }
+    ],
     "properties": {
       "network": {
         "type": "object",
@@ -20,12 +28,19 @@
           "webRTCMultipleRoutesEnabled": {
             "$ref": "types.ChromeSetting",
             "value": ["webRTCMultipleRoutesEnabled", {"type":"boolean"}],
+            "deprecated": "Please use privacy.network.webRTCIPHandlingPolicy. This remains for backward compatibility in this release and will be removed in the future.",
             "description": "If enabled, Chrome will explore all possible routing options when using WebRTC to find the most performant path, possibly exposing user's private IP address. Otherwise, WebRTC traffic will be routed the same way as regular HTTP. This preference's value is a boolean, defaulting to <code>true</code>."
           },
           "webRTCNonProxiedUdpEnabled": {
             "$ref": "types.ChromeSetting",
             "value": ["webRTCNonProxiedUdpEnabled", {"type":"boolean"}],
+            "deprecated": "Please use privacy.network.webRTCIPHandlingPolicy. This remains for backward compatibility in this release and will be removed in the future.",
             "description": "If enabled, Chrome is allowed to use non-proxied UDP to connect to peers or TURN servers when using WebRTC. Since most proxy servers don't handle UDP, using UDP possibly exposes user's IP address. Turning this off effectively forces WebRTC to only use TCP for now, until UDP proxy support is available in Chrome and such proxies are widely deployed. As a result, it also might hurt media performance and increase the load for proxy servers. This preference's value is a boolean, defaulting to <code>true</code>."
+          },
+          "webRTCIPHandlingPolicy": {
+            "$ref": "types.ChromeSetting",
+            "value": ["webRTCIPHandlingPolicy", {"$ref":"IPHandlingPolicy"}],
+            "description": "Allow users to specify the media performance/privacy tradeoffs which impacts how WebRTC traffic will be routed and how much local address information is exposed. This preference's value is of type IPHandlingPolicy, defaulting to <code>default</code>."
           }
         }
       },
diff --git a/chrome/common/mac/mock_launchd.cc b/chrome/common/mac/mock_launchd.cc
index 3af8aef..4956747 100644
--- a/chrome/common/mac/mock_launchd.cc
+++ b/chrome/common/mac/mock_launchd.cc
@@ -5,6 +5,7 @@
 #include "chrome/common/mac/mock_launchd.h"
 
 #include <CoreFoundation/CoreFoundation.h>
+#include <errno.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 511f1972..51736d9 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1197,14 +1197,19 @@
 
 #if defined(ENABLE_WEBRTC)
 // Whether WebRTC should bind to individual NICs to explore all possible routing
-// options. Default is true.
+// options. Default is true. This has become obsoleted and replaced by
+// kWebRTCIPHandlingPolicy. TODO(guoweis): Remove this at M50.
 const char kWebRTCMultipleRoutesEnabled[] = "webrtc.multiple_routes_enabled";
 // Whether WebRTC should use non-proxied UDP. If false, WebRTC will not send UDP
 // unless it goes through a proxy (i.e RETURN when it's available).  If no UDP
 // proxy is configured, it will not send UDP.  If true, WebRTC will send UDP
-// regardless of whether or not a proxy is configured.
+// regardless of whether or not a proxy is configured. TODO(guoweis): Remove
+// this at M50.
 const char kWebRTCNonProxiedUdpEnabled[] =
     "webrtc.nonproxied_udp_enabled";
+// Define the IP handling policy override that WebRTC should follow. When not
+// set, it defaults to "default".
+const char kWebRTCIPHandlingPolicy[] = "webrtc.ip_handling_policy";
 #endif
 
 // *************** LOCAL STATE ***************
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 63e3dfa..00c8080 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -407,6 +407,7 @@
 #if defined(ENABLE_WEBRTC)
 extern const char kWebRTCMultipleRoutesEnabled[];
 extern const char kWebRTCNonProxiedUdpEnabled[];
+extern const char kWebRTCIPHandlingPolicy[];
 #endif
 
 extern const char kGLVendorString[];
diff --git a/chrome/installer/util/channel_info.cc b/chrome/installer/util/channel_info.cc
index 5180fcf..ca181d3 100644
--- a/chrome/installer/util/channel_info.cc
+++ b/chrome/installer/util/channel_info.cc
@@ -5,6 +5,8 @@
 #include "chrome/installer/util/channel_info.h"
 
 #include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
 #include "base/win/registry.h"
 #include "chrome/installer/util/google_update_constants.h"
 #include "chrome/installer/util/util_constants.h"
@@ -24,12 +26,6 @@
 const wchar_t kSfxMigrating[] = L"-migrating";
 const wchar_t kSfxMultiFail[] = L"-multifail";
 
-const wchar_t* const kChannels[] = {
-  installer::kChromeChannelBeta,
-  installer::kChromeChannelDev,
-  installer::kChromeChannelStableExplicit
-};
-
 const wchar_t* const kModifiers[] = {
   kModStage,
   kModMultiInstall,
@@ -135,6 +131,31 @@
   return false;
 }
 
+// Returns the position of the first case-insensitive match of |pattern| found
+// in |str|, or base::string16::npos if none found. |pattern| must be non-empty
+// lower-case ASCII, and may contain any number of '.' wildcard characters.
+size_t FindSubstringMatch(const base::string16& str,
+                          base::StringPiece16 pattern) {
+  DCHECK(!pattern.empty());
+  DCHECK(base::IsStringASCII(pattern));
+  DCHECK(pattern == base::StringPiece16(base::ToLowerASCII(pattern)));
+
+  if (str.size() < pattern.size())
+    return base::string16::npos;
+
+  for (size_t i = 0; i < str.size() - pattern.size() + 1; ++i) {
+    size_t j = 0;
+    while (j < pattern.size() &&
+           (pattern[j] == L'.' ||
+            pattern[j] == base::ToLowerASCII(str[i+j]))) {
+      ++j;
+    }
+    if (j == pattern.size())
+      return i;
+  }
+  return base::string16::npos;
+}
+
 }  // namespace
 
 namespace installer {
@@ -159,33 +180,49 @@
 }
 
 bool ChannelInfo::GetChannelName(base::string16* channel_name) const {
+  static const wchar_t kChromeChannelBetaPattern[] = L"1.1-";
+  static const wchar_t kChromeChannelBetaX64Pattern[] = L"x64-beta";
+  static const wchar_t kChromeChannelDevPattern[] = L"2.0-d";
+  static const wchar_t kChromeChannelDevX64Pattern[] = L"x64-dev";
+
   DCHECK(channel_name);
-  if (value_.empty()) {
+  // Report channels that are empty string or contain "stable" as stable
+  // (empty string).
+  if (value_.empty() || value_.find(installer::kChromeChannelStableExplicit) !=
+      base::string16::npos) {
     channel_name->erase();
     return true;
-  } else {
-    for (const wchar_t* const* scan = &kChannels[0],
-             *const* end = &kChannels[arraysize(kChannels)]; scan != end;
-         ++scan) {
-      if (value_.find(*scan) != base::string16::npos) {
-        // Report channels with "stable" in them as stable (empty string).
-        if (*scan == installer::kChromeChannelStableExplicit)
-          channel_name->erase();
-        else
-          channel_name->assign(*scan);
-        return true;
-      }
-    }
-    // There may be modifiers present.  Strip them off and see if we're left
-    // with the empty string (stable channel).
-    base::string16 tmp_value = value_;
-    for (int i = 0; i != NUM_MODIFIERS; ++i) {
-      SetModifier(static_cast<ModifierIndex>(i), false, &tmp_value);
-    }
-    if (tmp_value.empty()) {
-      channel_name->erase();
-      return true;
-    }
+  }
+  // Report channels that match "/^2.0-d.*/i" as dev.
+  if (FindSubstringMatch(value_, kChromeChannelDevPattern) == 0) {
+    channel_name->assign(installer::kChromeChannelDev);
+    return true;
+  }
+  // Report channels that match "/.*x64-dev.*/" as dev.
+  if (value_.find(kChromeChannelDevX64Pattern) != base::string16::npos) {
+    channel_name->assign(installer::kChromeChannelDev);
+    return true;
+  }
+  // Report channels that match "/^1.1-.*/i" as beta.
+  if (FindSubstringMatch(value_, kChromeChannelBetaPattern) == 0) {
+    channel_name->assign(installer::kChromeChannelBeta);
+    return true;
+  }
+  // Report channels that match "/.*x64-beta.*/" as beta.
+  if (value_.find(kChromeChannelBetaX64Pattern) != base::string16::npos) {
+    channel_name->assign(installer::kChromeChannelBeta);
+    return true;
+  }
+
+  // There may be modifiers present. Strip them off and see if we're left
+  // with the empty string (stable channel).
+  base::string16 tmp_value = value_;
+  for (int i = 0; i != NUM_MODIFIERS; ++i) {
+    SetModifier(static_cast<ModifierIndex>(i), false, &tmp_value);
+  }
+  if (tmp_value.empty()) {
+    channel_name->erase();
+    return true;
   }
 
   return false;
diff --git a/chrome/installer/util/channel_info_unittest.cc b/chrome/installer/util/channel_info_unittest.cc
index dd50c38..10f6763e 100644
--- a/chrome/installer/util/channel_info_unittest.cc
+++ b/chrome/installer/util/channel_info_unittest.cc
@@ -31,38 +31,74 @@
   EXPECT_TRUE(ci.GetChannelName(&channel));
   EXPECT_EQ(kChannelStable, channel);
 
+  ci.set_value(L"1.1-beta");
+  EXPECT_TRUE(ci.GetChannelName(&channel));
+  EXPECT_EQ(kChannelBeta, channel);
+  ci.set_value(L"1.1-beta-foo");
+  EXPECT_TRUE(ci.GetChannelName(&channel));
+  EXPECT_EQ(kChannelBeta, channel);
+  ci.set_value(L"1.1-bar");
+  EXPECT_TRUE(ci.GetChannelName(&channel));
+  EXPECT_EQ(kChannelBeta, channel);
+  ci.set_value(L"1n1-foobar");
+  EXPECT_TRUE(ci.GetChannelName(&channel));
+  EXPECT_EQ(kChannelBeta, channel);
+  ci.set_value(L"foo-1.1-beta");
+  EXPECT_FALSE(ci.GetChannelName(&channel));
   ci.set_value(L"2.0-beta");
-  EXPECT_TRUE(ci.GetChannelName(&channel));
-  EXPECT_EQ(kChannelBeta, channel);
-  ci.set_value(L"2.0-beta-spam");
-  EXPECT_TRUE(ci.GetChannelName(&channel));
-  EXPECT_EQ(kChannelBeta, channel);
-  ci.set_value(L"2.0-spam-beta");
-  EXPECT_TRUE(ci.GetChannelName(&channel));
-  EXPECT_EQ(kChannelBeta, channel);
+  EXPECT_FALSE(ci.GetChannelName(&channel));
 
   ci.set_value(L"2.0-dev");
   EXPECT_TRUE(ci.GetChannelName(&channel));
   EXPECT_EQ(kChannelDev, channel);
-  ci.set_value(L"2.0-kinda-dev");
+  ci.set_value(L"2.0-DEV");
   EXPECT_TRUE(ci.GetChannelName(&channel));
   EXPECT_EQ(kChannelDev, channel);
   ci.set_value(L"2.0-dev-eloper");
   EXPECT_TRUE(ci.GetChannelName(&channel));
   EXPECT_EQ(kChannelDev, channel);
+  ci.set_value(L"2.0-doom");
+  EXPECT_TRUE(ci.GetChannelName(&channel));
+  EXPECT_EQ(kChannelDev, channel);
+  ci.set_value(L"250-doom");
+  EXPECT_TRUE(ci.GetChannelName(&channel));
+  EXPECT_EQ(kChannelDev, channel);
+  ci.set_value(L"bar-2.0-dev");
+  EXPECT_FALSE(ci.GetChannelName(&channel));
+  ci.set_value(L"1.0-dev");
+  EXPECT_FALSE(ci.GetChannelName(&channel));
 
   ci.set_value(L"x64-dev");
   EXPECT_TRUE(ci.GetChannelName(&channel));
   EXPECT_EQ(kChannelDev, channel);
+  ci.set_value(L"foo-x64-dev");
+  EXPECT_TRUE(ci.GetChannelName(&channel));
+  EXPECT_EQ(kChannelDev, channel);
+  ci.set_value(L"x64-Dev");
+  EXPECT_FALSE(ci.GetChannelName(&channel));
+
   ci.set_value(L"x64-beta");
   EXPECT_TRUE(ci.GetChannelName(&channel));
   EXPECT_EQ(kChannelBeta, channel);
+  ci.set_value(L"bar-x64-beta");
+  EXPECT_TRUE(ci.GetChannelName(&channel));
+  EXPECT_EQ(kChannelBeta, channel);
+  ci.set_value(L"x64-Beta");
+  EXPECT_FALSE(ci.GetChannelName(&channel));
+
   ci.set_value(L"x64-stable");
   EXPECT_TRUE(ci.GetChannelName(&channel));
   EXPECT_EQ(kChannelStable, channel);
+  ci.set_value(L"baz-x64-stable");
+  EXPECT_TRUE(ci.GetChannelName(&channel));
+  EXPECT_EQ(kChannelStable, channel);
+  ci.set_value(L"x64-Stable");
+  EXPECT_FALSE(ci.GetChannelName(&channel));
 
   ci.set_value(L"fuzzy");
   EXPECT_FALSE(ci.GetChannelName(&channel));
+  ci.set_value(L"foo");
+  EXPECT_FALSE(ci.GetChannelName(&channel));
 }
 
 TEST(ChannelInfoTest, FullInstall) {
diff --git a/chrome/installer/util/google_update_settings_unittest.cc b/chrome/installer/util/google_update_settings_unittest.cc
index 314084b..d89c43f 100644
--- a/chrome/installer/util/google_update_settings_unittest.cc
+++ b/chrome/installer/util/google_update_settings_unittest.cc
@@ -96,20 +96,20 @@
   }
 
   // Tests setting the ap= value to various combinations of values with
-  // prefixes and suffixes, while asserting on the correct channel value.
-  // Note that any non-empty ap= value that doesn't match ".*-{dev|beta}.*"
-  // will return the "unknown" channel.
+  // suffixes, while asserting on the correct channel value.
+  // Note that ap= value has to match "^2.0-d.*" or ".*x64-dev.*" and "^1.1-.*"
+  // or ".*x64-beta.*" for dev and beta channels respectively.
   void TestCurrentChromeChannelWithVariousApValues(SystemUserInstall install) {
     static struct Expectations {
       const wchar_t* ap_value;
       const wchar_t* channel;
+      bool supports_prefixes;
     } expectations[] = {
-      { L"dev", installer::kChromeChannelDev },
-      { L"-dev", installer::kChromeChannelDev },
-      { L"-developer", installer::kChromeChannelDev },
-      { L"beta", installer::kChromeChannelBeta },
-      { L"-beta", installer::kChromeChannelBeta },
-      { L"-betamax", installer::kChromeChannelBeta },
+      { L"2.0-dev", installer::kChromeChannelDev, false},
+      { L"1.1-beta", installer::kChromeChannelBeta, false},
+      { L"x64-dev", installer::kChromeChannelDev, true},
+      { L"x64-beta", installer::kChromeChannelBeta, true},
+      { L"x64-stable", installer::kChromeChannelStable, true},
     };
     bool is_system = install == SYSTEM_INSTALL;
     const wchar_t* prefixes[] = {
@@ -135,10 +135,19 @@
           base::string16 ret_channel;
 
           EXPECT_TRUE(GoogleUpdateSettings::GetChromeChannelAndModifiers(
-              is_system, &ret_channel));
-          EXPECT_STREQ(channel, ret_channel.c_str())
-              << "Expecting channel \"" << channel
-              << "\" for ap=\"" << ap << "\"";
+            is_system, &ret_channel));
+
+          // If prefixes are not supported for a channel, we expect the channel
+          // to be "unknown" if a non-empty prefix is present in ap_value.
+          if (!expectations[j].supports_prefixes && wcslen(prefixes[i]) > 0) {
+            EXPECT_STREQ(installer::kChromeChannelUnknown, ret_channel.c_str())
+                << "Expecting channel \"" << installer::kChromeChannelUnknown
+                << "\" for ap=\"" << ap << "\"";
+          } else {
+            EXPECT_STREQ(channel, ret_channel.c_str())
+                << "Expecting channel \"" << channel
+                << "\" for ap=\"" << ap << "\"";
+          }
         }
       }
     }
diff --git a/chrome/test/data/extensions/api_test/preference/standard/test.js b/chrome/test/data/extensions/api_test/preference/standard/test.js
index 8fdff45..5ffc6403 100644
--- a/chrome/test/data/extensions/api_test/preference/standard/test.js
+++ b/chrome/test/data/extensions/api_test/preference/standard/test.js
@@ -3,8 +3,9 @@
 // found in the LICENSE file.
 
 // Preferences API test
-// Run with browser_tests --gtest_filter=ExtensionApiTest.PreferenceApi
+// Run with browser_tests --gtest_filter=ExtensionPreferenceApiTest.Standard
 
+var pn = chrome.privacy.network;
 var preferences_to_test = [
   {
     root: chrome.privacy.network,
@@ -86,5 +87,28 @@
       preferences_to_test[i].preferences.forEach(
           prefSetter.bind(preferences_to_test[i].root));
     }
+  },
+  // Set the WebRTCIPHhandlingPolicy and verify it in the get function.
+  function testWebRTCIPHandlingPolicy() {
+    if (pn.webRTCIPHandlingPolicy == undefined) {
+      chrome.test.callbackPass();
+      return;
+    }
+    pn.webRTCIPHandlingPolicy.get(
+      {},
+      expect(
+        {value: chrome.privacy.IPHandlingPolicy.DEFAULT_PUBLIC_INTERFACE_ONLY,
+         levelOfControl: 'controllable_by_this_extension'},
+        'should receive default_public_interface_only.'));
+
+    pn.webRTCIPHandlingPolicy.set(
+      {value: chrome.privacy.IPHandlingPolicy.DISABLE_NON_PROXIED_UDP});
+
+    pn.webRTCIPHandlingPolicy.get(
+      {},
+      expect(
+        {value: chrome.privacy.IPHandlingPolicy.DISABLE_NON_PROXIED_UDP,
+         levelOfControl: 'controlled_by_this_extension'},
+        'should receive disable_non_proxied_udp.'));
   }
 ]);
diff --git a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
new file mode 100644
index 0000000..e194af3d
--- /dev/null
+++ b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
@@ -0,0 +1,75 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @fileoverview Runs the Polymer Settings tests. */
+
+/** @const {string} Path to source root. */
+var ROOT_PATH = '../../../../../';
+
+// Polymer BrowserTest fixture.
+GEN_INCLUDE([
+    ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']);
+GEN('#include "base/command_line.h"');
+GEN('#include "chrome/browser/ui/webui/extensions/' +
+    'extension_settings_browsertest.h"');
+
+/**
+ * Test fixture for Polymer Settings elements.
+ * @constructor
+ * @extends {PolymerTest}
+*/
+function CrExtensionsBrowserTest() {}
+
+CrExtensionsBrowserTest.prototype = {
+  __proto__: PolymerTest.prototype,
+
+  /** @override */
+  browsePreload: 'chrome://extensions/',
+
+  /** @override */
+  commandLineSwitches: [{
+    switchName: 'enable-md-extensions',
+  }],
+
+  /** @override */
+  extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([
+    'extension_service_test.js',
+  ]),
+
+  /** @override */
+  typedefCppFixture: 'ExtensionSettingsUIBrowserTest',
+};
+
+function CrExtensionsBrowserTestWithInstalledExtension() {}
+
+CrExtensionsBrowserTestWithInstalledExtension.prototype = {
+  __proto__: CrExtensionsBrowserTest.prototype,
+
+  /** @override */
+  testGenPreamble: function() {
+    GEN('  InstallGoodExtension();');
+    GEN('  SetAutoConfirmUninstall();');
+  },
+};
+
+TEST_F('CrExtensionsBrowserTestWithInstalledExtension',
+       'ExtensionServiceToggleEnableTest', function() {
+  extension_service_tests.registerToggleEnableTests();
+  mocha.run();
+});
+TEST_F('CrExtensionsBrowserTestWithInstalledExtension',
+       'ExtensionServiceToggleIncognitoTest', function() {
+  extension_service_tests.registerToggleIncognitoTests();
+  mocha.run();
+});
+TEST_F('CrExtensionsBrowserTestWithInstalledExtension',
+       'ExtensionServiceUninstallTest', function() {
+  extension_service_tests.registerUninstallTests();
+  mocha.run();
+});
+TEST_F('CrExtensionsBrowserTestWithInstalledExtension',
+       'ExtensionServiceProfileSettingsTest', function() {
+  extension_service_tests.registerProfileSettingsTests();
+  mocha.run();
+});
diff --git a/chrome/test/data/webui/extensions/extension_service_test.js b/chrome/test/data/webui/extensions/extension_service_test.js
new file mode 100644
index 0000000..7be85466
--- /dev/null
+++ b/chrome/test/data/webui/extensions/extension_service_test.js
@@ -0,0 +1,239 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @fileoverview Suite of tests for extension-item. */
+cr.define('extension_service_tests', function() {
+  /** @const */
+  var kExtensionId = 'ldnnhddmnhbkjipkidpdiheffobcpfmf';
+
+  /** @const */
+  var EventType = chrome.developerPrivate.EventType;
+
+  /** @const */
+  var ExtensionState = chrome.developerPrivate.ExtensionState;
+
+  /** @constructor */
+  function ChangeListener() {}
+
+  ChangeListener.prototype = {
+    /**
+     * @param {!ChromeEvent} chromeEvent
+     * @param {!function(...):boolean} matchFunction
+     */
+    init_: function(chromeEvent, matchFunction) {
+      this.onUpdate = new Promise(function(resolve, reject) {
+        this.resolvePromise_ = resolve;
+      }.bind(this));
+      this.listener_ = this.onChanged_.bind(this);
+      this.event_ = chromeEvent;
+      this.matches_ = matchFunction;
+      this.event_.addListener(this.listener_);
+    },
+
+    /** @private */
+    onChanged_: function() {
+      if (this.matches_.apply(null, arguments)) {
+        setTimeout(function() {
+          this.event_.removeListener(this.listener_);
+          this.resolvePromise_();
+        }.bind(this));
+      }
+    },
+  };
+
+  /**
+   * @param {string} id The id of the item to watch.
+   * @param {chrome.developerPrivate.EventType} eventType The type of event
+   *     to wait for.
+   * @extends {extension_service_tests.ChangeListener}
+   * @constructor
+   */
+  function ItemChangedListener(id, eventType) {
+    this.__proto__ = ChangeListener.prototype,
+    this.init_(chrome.developerPrivate.onItemStateChanged,
+               function(data) {
+      return data.event_type == eventType && data.item_id == id;
+    });
+  }
+
+  /**
+   * @extends {extension_service_tests.ChangeListener}
+   * @constructor
+   */
+  function ProfileChangedListener() {
+    this.__proto__ = ChangeListener.prototype,
+    this.init_(chrome.developerPrivate.onProfileStateChanged,
+               function() { return true; });
+  }
+
+  function registerToggleEnableTests() {
+    suite('ExtensionServiceTest', function() {
+      // The 2-second timeout that Mocha has by default isn't nearly enough for
+      // our slower bots, like Dr. Memory. Just disable Mocha timeouts and let
+      // the C++ fixtures handle it.
+      this.timeout(0);
+
+      var service;
+      var manager;
+
+      suiteSetup(function() {
+        return PolymerTest.importHtml('chrome://extensions/service.html');
+      });
+
+      // Initialize an extension item before each test.
+      setup(function() {
+        service = extensions.Service.getInstance();
+        manager = document.getElementsByTagName('extensions-manager')[0];
+      });
+
+      test('Test extension service enable and disable', function(done) {
+        var item = manager.getItem(kExtensionId);
+        assertTrue(!!item);
+        expectEquals(kExtensionId, item.id);
+        expectEquals('My extension 1', item.data.name);
+        expectEquals(ExtensionState.ENABLED, item.data.state);
+
+        var disabledListener =
+            new ItemChangedListener(kExtensionId, EventType.UNLOADED);
+        service.setItemEnabled(kExtensionId, false);
+        disabledListener.onUpdate.then(function() {
+          expectEquals(ExtensionState.DISABLED, item.data.state);
+
+          enabledListener =
+              new ItemChangedListener(kExtensionId, EventType.LOADED);
+          service.setItemEnabled(kExtensionId, true);
+          return enabledListener.onUpdate;
+        }).then(function() {
+          expectEquals(ExtensionState.ENABLED, item.data.state);
+          done();
+        });
+      });
+    });
+  }
+
+  function registerToggleIncognitoTests() {
+    suite('ExtensionServiceToggleIncognitoTest', function() {
+      this.timeout(0);
+
+      var service;
+      var manager;
+
+      suiteSetup(function() {
+        return PolymerTest.importHtml('chrome://extensions/service.html');
+      });
+
+      // Initialize an extension item before each test.
+      setup(function() {
+        service = extensions.Service.getInstance();
+        manager = document.getElementsByTagName('extensions-manager')[0];
+      });
+
+      test('Test extension service toggle incognito mode', function(done) {
+        var item = manager.getItem(kExtensionId);
+        assertTrue(!!item);
+        expectTrue(item.data.incognitoAccess.isEnabled);
+        expectFalse(item.data.incognitoAccess.isActive);
+
+        var incognitoListener =
+            new ItemChangedListener(kExtensionId, EventType.LOADED);
+        chrome.test.runWithUserGesture(function() {
+          service.setItemAllowedIncognito(kExtensionId, true);
+        });
+        incognitoListener.onUpdate.then(function() {
+          expectTrue(item.data.incognitoAccess.isActive);
+
+          var disabledIncognitoListener =
+              new ItemChangedListener(kExtensionId, EventType.LOADED);
+          chrome.test.runWithUserGesture(function() {
+            service.setItemAllowedIncognito(kExtensionId, false);
+          });
+          return disabledIncognitoListener.onUpdate;
+        }).then(function() {
+          expectFalse(item.data.incognitoAccess.isActive);
+          done();
+        });
+      });
+    });
+  }
+
+  function registerUninstallTests() {
+    suite('ExtensionServiceUninstallTest', function() {
+      this.timeout(0);
+
+      var service;
+      var manager;
+
+      suiteSetup(function() {
+        return PolymerTest.importHtml('chrome://extensions/service.html');
+      });
+
+      // Initialize an extension item before each test.
+      setup(function() {
+        service = extensions.Service.getInstance();
+        manager = document.querySelector('extensions-manager');
+      });
+
+      test('Test extension service uninstall', function(done) {
+        var item = manager.getItem(kExtensionId);
+        assertTrue(!!item);
+        var uninstallListener =
+            new ItemChangedListener(kExtensionId, EventType.UNINSTALLED);
+        chrome.test.runWithUserGesture(function() {
+          service.deleteItem(kExtensionId);
+        });
+        uninstallListener.onUpdate.then(function() {
+          expectFalse(!!manager.getItem(kExtensionId));
+          done();
+        });
+      });
+    });
+  }
+
+  function registerProfileSettingsTests() {
+    suite('ExtensionServiceProfileSettingsTest', function() {
+      this.timeout(0);
+
+      var service;
+      var manager;
+
+      suiteSetup(function() {
+        return PolymerTest.importHtml('chrome://extensions/service.html');
+      });
+
+      // Initialize an extension item before each test.
+      setup(function() {
+        service = extensions.Service.getInstance();
+        manager = document.getElementsByTagName('extensions-manager')[0];
+      });
+
+      test('Test extension service profile settings', function(done) {
+        var item = manager.getItem(kExtensionId);
+        assertTrue(!!item);
+        expectFalse(item.inDevMode);
+
+        var profileListener = new ProfileChangedListener();
+        service.setProfileInDevMode(true);
+
+        profileListener.onUpdate.then(function() {
+          expectTrue(item.inDevMode);
+
+          var noDevModeProfileListener = new ProfileChangedListener();
+          service.setProfileInDevMode(false);
+          return noDevModeProfileListener.onUpdate;
+        }).then(function() {
+          expectFalse(item.inDevMode);
+          done();
+        });
+      });
+    });
+  }
+
+  return {
+    ChangeListener: ChangeListener,
+    registerToggleEnableTests: registerToggleEnableTests,
+    registerToggleIncognitoTests: registerToggleIncognitoTests,
+    registerUninstallTests: registerUninstallTests,
+    registerProfileSettingsTests: registerProfileSettingsTests,
+  };
+});
diff --git a/chrome/test/data/webui/media_router/media_router_elements_browsertest.js b/chrome/test/data/webui/media_router/media_router_elements_browsertest.js
index 4672ed4..799315e2 100644
--- a/chrome/test/data/webui/media_router/media_router_elements_browsertest.js
+++ b/chrome/test/data/webui/media_router/media_router_elements_browsertest.js
@@ -25,7 +25,7 @@
   browsePreload: 'chrome://media-router/',
 
   commandLineSwitches: [{
-    switchName: 'enable-media-router',
+    switchName: 'media-router', switchValue: '1'
   }],
 
   // List tests for individual elements.
diff --git a/chrome/test/data/webui/mocha_adapter.js b/chrome/test/data/webui/mocha_adapter.js
index 8f85410..6d05f78 100644
--- a/chrome/test/data/webui/mocha_adapter.js
+++ b/chrome/test/data/webui/mocha_adapter.js
@@ -59,4 +59,8 @@
   ui: 'tdd',
   // Use custom reporter to interface with BrowserTests.
   reporter: BrowserTestReporter,
+  // Mocha timeouts are set to 2 seconds initially. This isn't nearly enough for
+  // slower bots (e.g., Dr. Memory). Disable timeouts globally, because the C++
+  // will handle it (and has scaled timeouts for slower bots).
+  enableTimeouts: false,
 });
diff --git a/chrome/test/media_router/media_router_e2e_browsertest.cc b/chrome/test/media_router/media_router_e2e_browsertest.cc
index 465030f..256f26d90 100644
--- a/chrome/test/media_router/media_router_e2e_browsertest.cc
+++ b/chrome/test/media_router/media_router_e2e_browsertest.cc
@@ -29,7 +29,7 @@
 //   --enable-logging=stderr
 //   --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo
 //   --ui-test-action-timeout=200000
-//   --enable-media-router
+//   --media-router=1
 
 namespace {
 // Command line argument to specify receiver,
diff --git a/chromecast/base/error_codes.cc b/chromecast/base/error_codes.cc
index e26a820..95a42c5c 100644
--- a/chromecast/base/error_codes.cc
+++ b/chromecast/base/error_codes.cc
@@ -4,6 +4,7 @@
 
 #include "chromecast/base/error_codes.h"
 
+#include <errno.h>
 #include <fcntl.h>
 
 #include <string>
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 4e1ba18..bb9b317f 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -45,7 +45,6 @@
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "media/audio/audio_manager.h"
 #include "media/audio/audio_manager_factory.h"
-#include "media/base/browser_cdm_factory.h"
 #include "media/base/media.h"
 #include "ui/compositor/compositor_switches.h"
 
@@ -311,12 +310,6 @@
   const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
 #if defined(OS_ANDROID)
   ::media::SetMediaClientAndroid(new media::CastMediaClientAndroid());
-#else
-  if (cmd_line->HasSwitch(switches::kEnableCmaMediaPipeline)) {
-    scoped_ptr<::media::BrowserCdmFactory> cdm_factory =
-        cast_browser_process_->browser_client()->CreateBrowserCdmFactory();
-    ::media::SetBrowserCdmFactory(cdm_factory.release());
-  }
 #endif  // defined(OS_ANDROID)
 
   cast_browser_process_->SetConnectivityChecker(
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 14ff5c2..49294bd1 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -90,11 +90,6 @@
 CastContentBrowserClient::CreateCmaMediaPipelineClient() {
   return make_scoped_refptr(new media::CmaMediaPipelineClient());
 }
-
-scoped_ptr<::media::BrowserCdmFactory>
-CastContentBrowserClient::CreateBrowserCdmFactory() {
-  return make_scoped_ptr(new media::CastBrowserCdmFactory());
-}
 #endif  // OS_ANDROID
 
 void CastContentBrowserClient::ProcessExiting() {
@@ -364,6 +359,7 @@
 }
 
 #if defined(OS_ANDROID)
+
 void CastContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
     const base::CommandLine& command_line,
     int child_process_id,
@@ -389,7 +385,18 @@
     }
   }
 }
+
 #else
+
+scoped_ptr<::media::CdmFactory> CastContentBrowserClient::CreateCdmFactory() {
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableCmaMediaPipeline)) {
+    return make_scoped_ptr(new media::CastBrowserCdmFactory());
+  }
+
+  return nullptr;
+}
+
 void CastContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
     const base::CommandLine& command_line,
     int child_process_id,
@@ -399,6 +406,7 @@
     mappings->Share(kCrashDumpSignal, crash_signal_fd);
   }
 }
+
 #endif  // defined(OS_ANDROID)
 
 #if defined(OS_ANDROID) && defined(VIDEO_HOLE)
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 11763b8b..12129e3 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -71,10 +71,6 @@
   // instance.
   virtual scoped_refptr<media::CmaMediaPipelineClient>
   CreateCmaMediaPipelineClient();
-
-  // Creates and returns a factory used for creating BrowserCdm instances for
-  // playing protected content. This is called once per browser lifetime.
-  virtual scoped_ptr<::media::BrowserCdmFactory> CreateBrowserCdmFactory();
 #endif
 
   // Performs cleanup for process exit (but before AtExitManager cleanup).
@@ -150,6 +146,7 @@
       content::FileDescriptorInfo* mappings,
       std::map<int, base::MemoryMappedFile::Region>* regions) override;
 #else
+  scoped_ptr<::media::CdmFactory> CreateCdmFactory() override;
   void GetAdditionalMappedFilesForChildProcess(
       const base::CommandLine& command_line,
       int child_process_id,
diff --git a/chromecast/browser/media/cast_browser_cdm_factory.cc b/chromecast/browser/media/cast_browser_cdm_factory.cc
index e93927b..c657a691d 100644
--- a/chromecast/browser/media/cast_browser_cdm_factory.cc
+++ b/chromecast/browser/media/cast_browser_cdm_factory.cc
@@ -10,51 +10,60 @@
 #include "chromecast/media/base/media_message_loop.h"
 #include "chromecast/media/cdm/browser_cdm_cast.h"
 #include "media/base/bind_to_current_loop.h"
+#include "media/base/cdm_config.h"
 #include "media/base/cdm_key_information.h"
 
 namespace chromecast {
 namespace media {
 
-scoped_refptr<::media::MediaKeys> CastBrowserCdmFactory::CreateBrowserCdm(
-    const std::string& key_system_name,
-    bool use_hw_secure_codecs,
+void CastBrowserCdmFactory::Create(
+    const std::string& key_system,
+    const GURL& security_origin,
+    const ::media::CdmConfig& cdm_config,
     const ::media::SessionMessageCB& session_message_cb,
     const ::media::SessionClosedCB& session_closed_cb,
     const ::media::LegacySessionErrorCB& legacy_session_error_cb,
     const ::media::SessionKeysChangeCB& session_keys_change_cb,
-    const ::media::SessionExpirationUpdateCB& session_expiration_update_cb) {
-  DCHECK(!use_hw_secure_codecs)
+    const ::media::SessionExpirationUpdateCB& session_expiration_update_cb,
+    const ::media::CdmCreatedCB& cdm_created_cb) {
+  // Bound |cdm_created_cb| so we always fire it asynchronously.
+  ::media::CdmCreatedCB bound_cdm_created_cb =
+      ::media::BindToCurrentLoop(cdm_created_cb);
+
+  DCHECK(!cdm_config.use_hw_secure_codecs)
       << "Chromecast does not use |use_hw_secure_codecs|";
 
-  CastKeySystem key_system(GetKeySystemByName(key_system_name));
+  CastKeySystem cast_key_system(GetKeySystemByName(key_system));
 
   scoped_refptr<chromecast::media::BrowserCdmCast> browser_cdm;
-  if (key_system == chromecast::media::KEY_SYSTEM_CLEAR_KEY) {
+  if (cast_key_system == chromecast::media::KEY_SYSTEM_CLEAR_KEY) {
     // TODO(gunsch): handle ClearKey decryption. See crbug.com/441957
   } else {
-    browser_cdm = CreatePlatformBrowserCdm(key_system);
+    browser_cdm = CreatePlatformBrowserCdm(cast_key_system);
   }
 
-  if (browser_cdm) {
-    MediaMessageLoop::GetTaskRunner()->PostTask(
-        FROM_HERE,
-        base::Bind(&BrowserCdmCast::Initialize,
-                   base::Unretained(browser_cdm.get()),
-                   ::media::BindToCurrentLoop(session_message_cb),
-                   ::media::BindToCurrentLoop(session_closed_cb),
-                   ::media::BindToCurrentLoop(legacy_session_error_cb),
-                   ::media::BindToCurrentLoop(session_keys_change_cb),
-                   ::media::BindToCurrentLoop(session_expiration_update_cb)));
-    return scoped_refptr<::media::MediaKeys>(
-        new BrowserCdmCastUi(browser_cdm, MediaMessageLoop::GetTaskRunner()));
+  if (!browser_cdm) {
+    LOG(INFO) << "No matching key system found: " << cast_key_system;
+    bound_cdm_created_cb.Run(nullptr, "No matching key system found.");
+    return;
   }
 
-  LOG(INFO) << "No matching key system found.";
-  return nullptr;
+  MediaMessageLoop::GetTaskRunner()->PostTask(
+      FROM_HERE,
+      base::Bind(&BrowserCdmCast::Initialize,
+                 base::Unretained(browser_cdm.get()),
+                 ::media::BindToCurrentLoop(session_message_cb),
+                 ::media::BindToCurrentLoop(session_closed_cb),
+                 ::media::BindToCurrentLoop(legacy_session_error_cb),
+                 ::media::BindToCurrentLoop(session_keys_change_cb),
+                 ::media::BindToCurrentLoop(session_expiration_update_cb)));
+
+  bound_cdm_created_cb.Run(
+      new BrowserCdmCastUi(browser_cdm, MediaMessageLoop::GetTaskRunner()), "");
 }
 
 scoped_refptr<BrowserCdmCast> CastBrowserCdmFactory::CreatePlatformBrowserCdm(
-    const CastKeySystem& key_system) {
+    const CastKeySystem& cast_key_system) {
   return nullptr;
 }
 
diff --git a/chromecast/browser/media/cast_browser_cdm_factory.h b/chromecast/browser/media/cast_browser_cdm_factory.h
index c55b8fa..22c31bc 100644
--- a/chromecast/browser/media/cast_browser_cdm_factory.h
+++ b/chromecast/browser/media/cast_browser_cdm_factory.h
@@ -6,7 +6,7 @@
 #define CHROMECAST_BROWSER_MEDIA_CAST_BROWSER_CDM_FACTORY_H_
 
 #include "chromecast/media/base/key_systems_common.h"
-#include "media/base/browser_cdm_factory.h"
+#include "media/base/cdm_factory.h"
 #include "media/base/media_keys.h"
 
 namespace chromecast {
@@ -14,25 +14,26 @@
 
 class BrowserCdmCast;
 
-class CastBrowserCdmFactory : public ::media::BrowserCdmFactory {
+class CastBrowserCdmFactory : public ::media::CdmFactory {
  public:
   CastBrowserCdmFactory() {}
   ~CastBrowserCdmFactory() override {};
 
-  // ::media::BrowserCdmFactory implementation:
-  scoped_refptr<::media::MediaKeys> CreateBrowserCdm(
+  // ::media::CdmFactory implementation:
+  void Create(
       const std::string& key_system,
-      bool use_hw_secure_codecs,
+      const GURL& security_origin,
+      const ::media::CdmConfig& cdm_config,
       const ::media::SessionMessageCB& session_message_cb,
       const ::media::SessionClosedCB& session_closed_cb,
       const ::media::LegacySessionErrorCB& legacy_session_error_cb,
       const ::media::SessionKeysChangeCB& session_keys_change_cb,
-      const ::media::SessionExpirationUpdateCB& session_expiration_update_cb)
-      override;
+      const ::media::SessionExpirationUpdateCB& session_expiration_update_cb,
+      const ::media::CdmCreatedCB& cdm_created_cb) override;
 
   // Provides a platform-specific BrowserCdm instance.
   virtual scoped_refptr<BrowserCdmCast> CreatePlatformBrowserCdm(
-      const CastKeySystem& key_system);
+      const CastKeySystem& cast_key_system);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(CastBrowserCdmFactory);
diff --git a/chromecast/crash/linux/crash_util.cc b/chromecast/crash/linux/crash_util.cc
index 74348f48..bfcb8f5 100644
--- a/chromecast/crash/linux/crash_util.cc
+++ b/chromecast/crash/linux/crash_util.cc
@@ -52,7 +52,8 @@
                         AppStateTracker::GetCurrentApp(),
                         AppStateTracker::GetLastLaunchedApp(),
                         CAST_BUILD_RELEASE,
-                        CAST_BUILD_INCREMENTAL);
+                        CAST_BUILD_INCREMENTAL,
+                        ""  /* reason */);
   DummyMinidumpGenerator minidump_generator(existing_minidump_path);
 
   base::FilePath filename = base::FilePath(existing_minidump_path).BaseName();
diff --git a/chromecast/crash/linux/dump_info.cc b/chromecast/crash/linux/dump_info.cc
index 6dca890..2b99604 100644
--- a/chromecast/crash/linux/dump_info.cc
+++ b/chromecast/crash/linux/dump_info.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 #include "chromecast/crash/linux/dump_info.h"
 
+#include <errno.h>
 #include <stdlib.h>
 
 #include "base/logging.h"
@@ -28,6 +29,7 @@
 const char kLastAppNameKey[] = "last_app_name";
 const char kReleaseVersionKey[] = "release_version";
 const char kBuildNumberKey[] = "build_number";
+const char kReasonKey[] = "reason";
 
 }  // namespace
 
@@ -82,6 +84,7 @@
   entry->SetString(kLastAppNameKey, params_.last_app_name);
   entry->SetString(kReleaseVersionKey, params_.cast_release_version);
   entry->SetString(kBuildNumberKey, params_.cast_build_number);
+  entry->SetString(kReasonKey, params_.reason);
 
   return result;
 }
@@ -89,71 +92,57 @@
 bool DumpInfo::ParseEntry(const base::Value* entry) {
   valid_ = false;
 
-  if (!entry) {
+  if (!entry)
     return false;
-  }
 
   const base::DictionaryValue* dict;
-  if (!entry->GetAsDictionary(&dict)) {
+  if (!entry->GetAsDictionary(&dict))
     return false;
-  }
 
   // Extract required fields.
-  if (!dict->GetString(kNameKey, &params_.process_name)) {
+  if (!dict->GetString(kNameKey, &params_.process_name))
     return false;
-  }
 
   std::string dump_time;
-  if (!dict->GetString(kDumpTimeKey, &dump_time)) {
+  if (!dict->GetString(kDumpTimeKey, &dump_time))
     return false;
-  }
-  if (!SetDumpTimeFromString(dump_time)) {
+  if (!SetDumpTimeFromString(dump_time))
     return false;
-  }
 
-  if (!dict->GetString(kDumpKey, &crashed_process_dump_)) {
+  if (!dict->GetString(kDumpKey, &crashed_process_dump_))
     return false;
-  }
 
   std::string uptime;
-  if (!dict->GetString(kUptimeKey, &uptime)) {
+  if (!dict->GetString(kUptimeKey, &uptime))
     return false;
-  }
   errno = 0;
   params_.process_uptime = strtoull(uptime.c_str(), nullptr, 0);
-  if (errno != 0) {
+  if (errno != 0)
     return false;
-  }
 
-  if (!dict->GetString(kLogfileKey, &logfile_)) {
+  if (!dict->GetString(kLogfileKey, &logfile_))
     return false;
-  }
   size_t num_params = kNumRequiredParams;
 
   // Extract all other optional fields.
-  if (dict->GetString(kSuffixKey, &params_.suffix)) {
+  if (dict->GetString(kSuffixKey, &params_.suffix))
     ++num_params;
-  }
-  if (dict->GetString(kPrevAppNameKey, &params_.previous_app_name)) {
+  if (dict->GetString(kPrevAppNameKey, &params_.previous_app_name))
     ++num_params;
-  }
-  if (dict->GetString(kCurAppNameKey, &params_.current_app_name)) {
+  if (dict->GetString(kCurAppNameKey, &params_.current_app_name))
     ++num_params;
-  }
-  if (dict->GetString(kLastAppNameKey, &params_.last_app_name)) {
+  if (dict->GetString(kLastAppNameKey, &params_.last_app_name))
     ++num_params;
-  }
-  if (dict->GetString(kReleaseVersionKey, &params_.cast_release_version)) {
+  if (dict->GetString(kReleaseVersionKey, &params_.cast_release_version))
     ++num_params;
-  }
-  if (dict->GetString(kBuildNumberKey, &params_.cast_build_number)) {
+  if (dict->GetString(kBuildNumberKey, &params_.cast_build_number))
     ++num_params;
-  }
+  if (dict->GetString(kReasonKey, &params_.reason))
+    ++num_params;
 
   // Disallow extraneous params
-  if (dict->size() != num_params) {
+  if (dict->size() != num_params)
     return false;
-  }
 
   valid_ = true;
   return true;
diff --git a/chromecast/crash/linux/dump_info.h b/chromecast/crash/linux/dump_info.h
index eb1f429..a225636 100644
--- a/chromecast/crash/linux/dump_info.h
+++ b/chromecast/crash/linux/dump_info.h
@@ -58,6 +58,7 @@
   //   "last_app_name": <last_app_name>,
   //   "release_version": <release_version>,
   //   "build_number": <build_number>
+  //   "reason": <reason>
   // }
   scoped_ptr<base::Value> GetAsValue() const;
   const MinidumpParams& params() const { return params_; }
diff --git a/chromecast/crash/linux/dump_info_unittest.cc b/chromecast/crash/linux/dump_info_unittest.cc
index c567e8e..dfa7e5d 100644
--- a/chromecast/crash/linux/dump_info_unittest.cc
+++ b/chromecast/crash/linux/dump_info_unittest.cc
@@ -117,7 +117,8 @@
       "\"cur_app_name\": \"current_app\","
       "\"last_app_name\": \"last_app\","
       "\"release_version\": \"RELEASE\","
-      "\"build_number\": \"BUILD_NUMBER\""
+      "\"build_number\": \"BUILD_NUMBER\","
+      "\"reason\": \"foo\""
       "}"));
   struct tm tm = {0};
   tm.tm_isdst = 0;
@@ -140,6 +141,7 @@
   ASSERT_EQ("previous_app", info->params().previous_app_name);
   ASSERT_EQ("current_app", info->params().current_app_name);
   ASSERT_EQ("last_app", info->params().last_app_name);
+  ASSERT_EQ("foo", info->params().reason);
 }
 
 TEST(DumpInfoTest, SomeOptionalFieldsIsValid) {
@@ -174,7 +176,7 @@
   ASSERT_EQ("previous_app", info->params().previous_app_name);
 }
 
-TEST(DumpInfoTest, TooManyFieldsIsNotValid) {
+TEST(DumpInfoTest, ExtraFieldsIsNotValid) {
   scoped_ptr<DumpInfo> info(CreateDumpInfo(
       "{"
       "\"name\": \"name\","
diff --git a/chromecast/crash/linux/minidump_params.cc b/chromecast/crash/linux/minidump_params.cc
index 3d532830..32be9168 100644
--- a/chromecast/crash/linux/minidump_params.cc
+++ b/chromecast/crash/linux/minidump_params.cc
@@ -13,7 +13,8 @@
                                const std::string& p_current_app_name,
                                const std::string& p_last_app_name,
                                const std::string& p_cast_release_version,
-                               const std::string& p_cast_build_number)
+                               const std::string& p_cast_build_number,
+                               const std::string& p_reason)
     : process_name(p_process_name),
       process_uptime(p_process_uptime),
       suffix(p_suffix),
@@ -21,7 +22,8 @@
       current_app_name(p_current_app_name),
       last_app_name(p_last_app_name),
       cast_release_version(p_cast_release_version),
-      cast_build_number(p_cast_build_number) {
+      cast_build_number(p_cast_build_number),
+      reason(p_reason) {
 }
 
 MinidumpParams::MinidumpParams() : process_uptime(0) {
diff --git a/chromecast/crash/linux/minidump_params.h b/chromecast/crash/linux/minidump_params.h
index 1a1c1551..1a1fc6b 100644
--- a/chromecast/crash/linux/minidump_params.h
+++ b/chromecast/crash/linux/minidump_params.h
@@ -18,7 +18,8 @@
                  const std::string& p_current_app_name,
                  const std::string& p_last_app_name,
                  const std::string& p_cast_release_version,
-                 const std::string& p_cast_build_number);
+                 const std::string& p_cast_build_number,
+                 const std::string& p_reason);
   MinidumpParams(const MinidumpParams& params);
   ~MinidumpParams();
 
@@ -32,6 +33,8 @@
   std::string cast_release_version;
   // Build number is numerical string such as "20000".
   std::string cast_build_number;
+  // Reason for crash, if one is available.
+  std::string reason;
 };
 
 }  // namespace chromecast
diff --git a/components/autofill/OWNERS b/components/autofill/OWNERS
index 018ffa4..6fa01ea0 100644
--- a/components/autofill/OWNERS
+++ b/components/autofill/OWNERS
@@ -1,5 +1,6 @@
 estade@chromium.org
 isherman@chromium.org
+vabr@chromium.org
 
 # Owners for password autofill/generation only.
 # TODO(gcasto): Change to per-file ownership after http://crbug.com/235756
diff --git a/components/cronet/android/api/src/org/chromium/net/CronetEngine.java b/components/cronet/android/api/src/org/chromium/net/CronetEngine.java
index e6f3161..89c4c89 100644
--- a/components/cronet/android/api/src/org/chromium/net/CronetEngine.java
+++ b/components/cronet/android/api/src/org/chromium/net/CronetEngine.java
@@ -181,6 +181,7 @@
          * @deprecated Marked as deprecated because @hide doesn't properly hide but
          *         javadocs are built with nodeprecated="yes".
          */
+        @SuppressWarnings("DepAnn")
         public Builder setDataReductionProxyOptions(
                 String primaryProxy, String fallbackProxy, String secureProxyCheckUrl) {
             if (primaryProxy.isEmpty() || fallbackProxy.isEmpty()
@@ -200,6 +201,7 @@
                 HTTP_CACHE_DISABLED, HTTP_CACHE_IN_MEMORY, HTTP_CACHE_DISK_NO_HTTP, HTTP_CACHE_DISK,
         })
         @Retention(RetentionPolicy.SOURCE)
+        @SuppressWarnings("DepAnn")
         public @interface HttpCacheSetting {}
 
         /**
@@ -611,7 +613,7 @@
      *         javadocs are built with nodeprecated="yes".
      *         TODO(pauljensen): Expose once implemented, http://crbug.com/418111
      */
-    public abstract URLConnection openConnection(URL url, Proxy proxy);
+    @SuppressWarnings("DepAnn") public abstract URLConnection openConnection(URL url, Proxy proxy);
 
     /**
      * Creates a {@link URLStreamHandlerFactory} to handle HTTP and HTTPS
diff --git a/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java b/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java
index 6c2f168d..b1fe24d 100644
--- a/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java
+++ b/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java
@@ -11,6 +11,7 @@
  * the first byte of the response is received.
  * @deprecated not really deprecated but hidden for now as it's a prototype.
  */
+@SuppressWarnings("DepAnn")
 public interface NetworkQualityRttListener {
     /**
      * Reports a new round trip time observation.
diff --git a/components/cronet/android/api/src/org/chromium/net/NetworkQualityThroughputListener.java b/components/cronet/android/api/src/org/chromium/net/NetworkQualityThroughputListener.java
index 1c9bbdae1..0930eb6 100644
--- a/components/cronet/android/api/src/org/chromium/net/NetworkQualityThroughputListener.java
+++ b/components/cronet/android/api/src/org/chromium/net/NetworkQualityThroughputListener.java
@@ -8,6 +8,7 @@
  * Interface to watch for observations of throughput.
  * @deprecated not really deprecated but hidden for now as it's a prototype.
  */
+@SuppressWarnings("DepAnn")
 public interface NetworkQualityThroughputListener {
     /**
      * Reports a new throughput observation.
diff --git a/components/cronet/android/api/src/org/chromium/net/UrlRequest.java b/components/cronet/android/api/src/org/chromium/net/UrlRequest.java
index a484ef4d..3d5a5e9 100644
--- a/components/cronet/android/api/src/org/chromium/net/UrlRequest.java
+++ b/components/cronet/android/api/src/org/chromium/net/UrlRequest.java
@@ -132,6 +132,7 @@
                 REQUEST_PRIORITY_MEDIUM, REQUEST_PRIORITY_HIGHEST,
         })
         @Retention(RetentionPolicy.SOURCE)
+        @SuppressWarnings("DepAnn")
         public @interface RequestPriority {}
 
         /**
@@ -336,6 +337,7 @@
                 READING_RESPONSE,
         })
         @Retention(RetentionPolicy.SOURCE)
+        @SuppressWarnings("DepAnn")
         public @interface StatusValues {}
 
         /**
diff --git a/components/cronet/android/api/src/org/chromium/net/UrlRequestContextConfig.java b/components/cronet/android/api/src/org/chromium/net/UrlRequestContextConfig.java
index 0e55fc6..2ecc2c4 100644
--- a/components/cronet/android/api/src/org/chromium/net/UrlRequestContextConfig.java
+++ b/components/cronet/android/api/src/org/chromium/net/UrlRequestContextConfig.java
@@ -9,6 +9,7 @@
  * CronetEngine.
  * @deprecated use {@link CronetEngine.Builder} instead.
  */
+@Deprecated
 public class UrlRequestContextConfig extends CronetEngine.Builder {
     public UrlRequestContextConfig() {
         // Context will be passed in later when the ChromiumUrlRequestFactory
diff --git a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java
index 03a3df54..41b0fc7 100644
--- a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java
+++ b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java
@@ -32,6 +32,7 @@
  * requests and receive responses.
  * @deprecated use {@link CronetEngine#openConnection}.
  */
+@Deprecated
 public class CronetHttpURLConnection extends HttpURLConnection {
     private static final String TAG = "cr.CronetHttpURLConn";
     private static final String CONTENT_LENGTH = "Content-Length";
diff --git a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java
index b798f27..71bf3eb 100644
--- a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java
+++ b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java
@@ -39,8 +39,8 @@
  *
  * @deprecated use {@link CronetEngine#createURLStreamHandlerFactory}.
  */
-public class CronetURLStreamHandlerFactory
-        implements URLStreamHandlerFactory {
+@Deprecated
+public class CronetURLStreamHandlerFactory implements URLStreamHandlerFactory {
     private final CronetEngine mCronetEngine;
 
     /**
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/TestDataProvider.java b/components/cronet/android/test/javatests/src/org/chromium/net/TestUploadDataProvider.java
similarity index 100%
rename from components/cronet/android/test/javatests/src/org/chromium/net/TestDataProvider.java
rename to components/cronet/android/test/javatests/src/org/chromium/net/TestUploadDataProvider.java
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLConnectionTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLConnectionTest.java
index 5fd501d..3507a49 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLConnectionTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLConnectionTest.java
@@ -101,23 +101,6 @@
 
     @SmallTest
     @Feature({"Cronet"})
-    @OnlyRunCronetHttpURLConnection
-    // TODO(xunjieli): Change the test after chunked support is added.
-    public void testPostChunked() throws Exception {
-        URL url = new URL(NativeTestServer.getEchoBodyURL());
-        HttpURLConnection connection =
-                (HttpURLConnection) url.openConnection();
-        connection.setDoOutput(true);
-        connection.setRequestMethod("POST");
-        try {
-            connection.setChunkedStreamingMode(0);
-        } catch (UnsupportedOperationException e) {
-            assertEquals("Chunked mode not supported yet", e.getMessage());
-        }
-    }
-
-    @SmallTest
-    @Feature({"Cronet"})
     @CompareDefaultWithCronet
     public void testNotFoundURLRequest() throws Exception {
         URL url = new URL(NativeTestServer.getFileURL("/notfound.html"));
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn
index 4fc54ed..0940bc89 100644
--- a/components/html_viewer/BUILD.gn
+++ b/components/html_viewer/BUILD.gn
@@ -332,6 +332,7 @@
     "//gin",
     "//mojo/converters/input_events",
     "//mojo/gles2",
+    "//mojo/platform_handle:platform_handle_impl",
     "//testing/gtest:gtest",
     "//third_party/mojo/src/mojo/edk/system",
     "//ui/base",
diff --git a/components/invalidation/public/invalidator_state.cc b/components/invalidation/public/invalidator_state.cc
index d7f7e39..34df6f4b 100644
--- a/components/invalidation/public/invalidator_state.cc
+++ b/components/invalidation/public/invalidator_state.cc
@@ -16,6 +16,8 @@
       return "INVALIDATION_CREDENTIALS_REJECTED";
     case INVALIDATIONS_ENABLED:
       return "INVALIDATIONS_ENABLED";
+    case INVALIDATOR_SHUTTING_DOWN:
+      return "INVALIDATOR_SHUTTING_DOWN";
     default:
       NOTREACHED();
       return "UNKNOWN_INVALIDATOR_STATE";
diff --git a/components/mus/example/BUILD.gn b/components/mus/example/BUILD.gn
index e1f46ab..03dd4b3 100644
--- a/components/mus/example/BUILD.gn
+++ b/components/mus/example/BUILD.gn
@@ -34,5 +34,6 @@
     "//base/test:test_config",
     "//base/test:test_support",
     "//components/mus/example/wm:unittests",
+    "//mojo/platform_handle:platform_handle_impl",
   ]
 }
diff --git a/components/mus/example/wm/non_client_frame_controller.cc b/components/mus/example/wm/non_client_frame_controller.cc
index 8cd5add4..fba2aef 100644
--- a/components/mus/example/wm/non_client_frame_controller.cc
+++ b/components/mus/example/wm/non_client_frame_controller.cc
@@ -5,6 +5,7 @@
 #include "components/mus/example/wm/non_client_frame_controller.h"
 
 #include "components/mus/example/wm/non_client_frame_view_impl.h"
+#include "components/mus/example/wm/property_util.h"
 #include "components/mus/public/cpp/window.h"
 #include "ui/views/mus/native_widget_mus.h"
 #include "ui/views/widget/widget.h"
@@ -29,6 +30,9 @@
         static_cast<views::internal::NativeWidgetPrivate*>(this)->GetWidget());
     return frame_view;
   }
+  void CenterWindow(const gfx::Size& size) override {
+    // Do nothing. The client controls the size, not us.
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(WmNativeWidgetMus);
@@ -37,17 +41,51 @@
 }  // namespace
 
 NonClientFrameController::NonClientFrameController(mojo::Shell* shell,
-                                                   mus::Window* window) {
-  views::Widget* widget = new views::Widget;
+                                                   mus::Window* window)
+    : widget_(new views::Widget), window_(window) {
+  window_->AddObserver(this);
+
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
   params.delegate = this;
-  params.native_widget = new WmNativeWidgetMus(widget, shell, window);
-  widget->Init(params);
-  widget->Show();
+  params.native_widget = new WmNativeWidgetMus(widget_, shell, window);
+  widget_->Init(params);
+  widget_->Show();
 }
 
-NonClientFrameController::~NonClientFrameController() {}
+NonClientFrameController::~NonClientFrameController() {
+  if (window_)
+    window_->RemoveObserver(this);
+}
 
 views::View* NonClientFrameController::GetContentsView() {
   return this;
 }
+
+bool NonClientFrameController::CanResize() const {
+  return (GetResizeBehavior(window_) &
+          mus::mojom::RESIZE_BEHAVIOR_CAN_RESIZE) != 0;
+}
+
+bool NonClientFrameController::CanMaximize() const {
+  return (GetResizeBehavior(window_) &
+          mus::mojom::RESIZE_BEHAVIOR_CAN_MAXIMIZE) != 0;
+}
+
+bool NonClientFrameController::CanMinimize() const {
+  return (GetResizeBehavior(window_) &
+          mus::mojom::RESIZE_BEHAVIOR_CAN_MINIMIZE) != 0;
+}
+
+void NonClientFrameController::OnWindowSharedPropertyChanged(
+    mus::Window* window,
+    const std::string& name,
+    const std::vector<uint8_t>* old_data,
+    const std::vector<uint8_t>* new_data) {
+  if (name == mus::mojom::WindowManager::kResizeBehavior_Property)
+    widget_->OnSizeConstraintsChanged();
+}
+
+void NonClientFrameController::OnWindowDestroyed(mus::Window* window) {
+  window_->RemoveObserver(this);
+  window_ = nullptr;
+}
diff --git a/components/mus/example/wm/non_client_frame_controller.h b/components/mus/example/wm/non_client_frame_controller.h
index 914f7eb..7b101be 100644
--- a/components/mus/example/wm/non_client_frame_controller.h
+++ b/components/mus/example/wm/non_client_frame_controller.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_MUS_EXAMPLE_WM_NON_CLIENT_FRAME_CONTROLLER_H_
 
 #include "base/macros.h"
+#include "components/mus/public/cpp/window_observer.h"
 #include "ui/views/widget/widget_delegate.h"
 
 namespace mojo {
@@ -17,7 +18,8 @@
 }
 
 // Provides the non-client frame for mus Windows.
-class NonClientFrameController : public views::WidgetDelegateView {
+class NonClientFrameController : public views::WidgetDelegateView,
+                                 public mus::WindowObserver {
  public:
   // NonClientFrameController deletes itself when |window| is destroyed.
   NonClientFrameController(mojo::Shell* shell, mus::Window* window);
@@ -27,6 +29,20 @@
 
   // views::WidgetDelegateView:
   views::View* GetContentsView() override;
+  bool CanResize() const override;
+  bool CanMaximize() const override;
+  bool CanMinimize() const override;
+
+  // mus::WindowObserver:
+  void OnWindowSharedPropertyChanged(
+      mus::Window* window,
+      const std::string& name,
+      const std::vector<uint8_t>* old_data,
+      const std::vector<uint8_t>* new_data) override;
+  void OnWindowDestroyed(mus::Window* window) override;
+
+  views::Widget* widget_;
+  mus::Window* window_;
 
   DISALLOW_COPY_AND_ASSIGN(NonClientFrameController);
 };
diff --git a/components/mus/example/wm/property_util.cc b/components/mus/example/wm/property_util.cc
index b4a838c9..3d0b173 100644
--- a/components/mus/example/wm/property_util.cc
+++ b/components/mus/example/wm/property_util.cc
@@ -61,3 +61,13 @@
   }
   return ash::mojom::CONTAINER_USER_WINDOWS;
 }
+
+mus::mojom::ResizeBehavior GetResizeBehavior(const mus::Window* window) {
+  if (window->HasSharedProperty(
+          mus::mojom::WindowManager::kResizeBehavior_Property)) {
+    return static_cast<mus::mojom::ResizeBehavior>(
+        window->GetSharedProperty<int32_t>(
+            mus::mojom::WindowManager::kResizeBehavior_Property));
+  }
+  return mus::mojom::RESIZE_BEHAVIOR_NONE;
+}
diff --git a/components/mus/example/wm/property_util.h b/components/mus/example/wm/property_util.h
index 8939bf7..c20fea4 100644
--- a/components/mus/example/wm/property_util.h
+++ b/components/mus/example/wm/property_util.h
@@ -7,6 +7,7 @@
 
 #include "components/mus/example/wm/public/interfaces/container.mojom.h"
 #include "components/mus/public/interfaces/window_manager.mojom.h"
+#include "components/mus/public/interfaces/window_manager_constants.mojom.h"
 
 namespace gfx {
 class Rect;
@@ -30,4 +31,6 @@
 
 ash::mojom::Container GetRequestedContainer(mus::Window* window);
 
+mus::mojom::ResizeBehavior GetResizeBehavior(const mus::Window* window);
+
 #endif  // COMPONENTS_MUS_EXAMPLE_WM_PROPERTY_UTIL_H_
diff --git a/components/mus/example/wm/window_manager_impl.cc b/components/mus/example/wm/window_manager_impl.cc
index 6039472..5cc668da 100644
--- a/components/mus/example/wm/window_manager_impl.cc
+++ b/components/mus/example/wm/window_manager_impl.cc
@@ -85,10 +85,13 @@
     mus::Id window_id,
     mojo::SizePtr size,
     const WindowManagerErrorCodeCallback& callback) {
-  SetWindowPreferredSize(state_->GetWindowById(window_id),
-                         size.To<gfx::Size>());
+  mus::Window* window = state_->GetWindowById(window_id);
+  if (window)
+    SetWindowPreferredSize(window, size.To<gfx::Size>());
 
-  callback.Run(mus::mojom::WINDOW_MANAGER_ERROR_CODE_SUCCESS);
+  callback.Run(window
+                   ? mus::mojom::WINDOW_MANAGER_ERROR_CODE_SUCCESS
+                   : mus::mojom::WINDOW_MANAGER_ERROR_CODE_ERROR_ACCESS_DENIED);
 }
 
 void WindowManagerImpl::SetBounds(
@@ -96,8 +99,11 @@
     mojo::RectPtr bounds,
     const WindowManagerErrorCodeCallback& callback) {
   mus::Window* window = state_->root()->GetChildById(window_id);
-  window->SetBounds(bounds->To<gfx::Rect>());
-  callback.Run(mus::mojom::WINDOW_MANAGER_ERROR_CODE_SUCCESS);
+  if (window)
+    window->SetBounds(bounds->To<gfx::Rect>());
+  callback.Run(window
+                   ? mus::mojom::WINDOW_MANAGER_ERROR_CODE_SUCCESS
+                   : mus::mojom::WINDOW_MANAGER_ERROR_CODE_ERROR_ACCESS_DENIED);
 }
 
 void WindowManagerImpl::SetShowState(
@@ -105,9 +111,23 @@
     mus::mojom::ShowState show_state,
     const WindowManagerErrorCodeCallback& callback){
   mus::Window* window = state_->GetWindowById(window_id);
-  window->SetSharedProperty<int32_t>(
-      mus::mojom::WindowManager::kShowState_Property, show_state);
-  callback.Run(mus::mojom::WINDOW_MANAGER_ERROR_CODE_SUCCESS);
+  if (window) {
+    window->SetSharedProperty<int32_t>(
+        mus::mojom::WindowManager::kShowState_Property, show_state);
+  }
+  callback.Run(window
+                   ? mus::mojom::WINDOW_MANAGER_ERROR_CODE_SUCCESS
+                   : mus::mojom::WINDOW_MANAGER_ERROR_CODE_ERROR_ACCESS_DENIED);
+}
+
+void WindowManagerImpl::SetResizeBehavior(
+    uint32_t window_id,
+    mus::mojom::ResizeBehavior resize_behavior) {
+  mus::Window* window = state_->GetWindowById(window_id);
+  if (window) {
+    window->SetSharedProperty<int32_t>(
+        mus::mojom::WindowManager::kResizeBehavior_Property, resize_behavior);
+  }
 }
 
 void WindowManagerImpl::GetConfig(const GetConfigCallback& callback) {
diff --git a/components/mus/example/wm/window_manager_impl.h b/components/mus/example/wm/window_manager_impl.h
index 3df0aa2..b956fae 100644
--- a/components/mus/example/wm/window_manager_impl.h
+++ b/components/mus/example/wm/window_manager_impl.h
@@ -39,6 +39,8 @@
   void SetShowState(mus::Id window_id,
                     mus::mojom::ShowState show_state,
                     const WindowManagerErrorCodeCallback& callback) override;
+  void SetResizeBehavior(uint32_t window_id,
+                         mus::mojom::ResizeBehavior resize_behavior) override;
   void GetConfig(const GetConfigCallback& callback) override;
 
   // mus::WindowObserver:
diff --git a/components/mus/public/cpp/lib/window.cc b/components/mus/public/cpp/lib/window.cc
index a8cd5219..7d960fd 100644
--- a/components/mus/public/cpp/lib/window.cc
+++ b/components/mus/public/cpp/lib/window.cc
@@ -373,6 +373,12 @@
         ->SetShowState(id_, show_state);
 }
 
+void Window::SetResizeBehavior(mojom::ResizeBehavior resize_behavior) {
+  if (connection_)
+    static_cast<WindowTreeClientImpl*>(connection_)
+        ->SetResizeBehavior(id_, resize_behavior);
+}
+
 void Window::SetFocus() {
   if (connection_)
     static_cast<WindowTreeClientImpl*>(connection_)->SetFocus(id_);
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.cc b/components/mus/public/cpp/lib/window_tree_client_impl.cc
index b869e442..3bff852 100644
--- a/components/mus/public/cpp/lib/window_tree_client_impl.cc
+++ b/components/mus/public/cpp/lib/window_tree_client_impl.cc
@@ -276,6 +276,12 @@
                       base::Bind(&WindowManagerCallback));
 }
 
+void WindowTreeClientImpl::SetResizeBehavior(
+    Id window_id,
+    mojom::ResizeBehavior resize_behavior) {
+  tree_->SetResizeBehavior(window_id, resize_behavior);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // WindowTreeClientImpl, WindowTreeConnection implementation:
 
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.h b/components/mus/public/cpp/lib/window_tree_client_impl.h
index 4b8baeac..97a2e07 100644
--- a/components/mus/public/cpp/lib/window_tree_client_impl.h
+++ b/components/mus/public/cpp/lib/window_tree_client_impl.h
@@ -93,6 +93,7 @@
 
   void SetPreferredSize(Id window_id, const gfx::Size& size);
   void SetShowState(Id window_id, mojom::ShowState show_state);
+  void SetResizeBehavior(Id window_id, mojom::ResizeBehavior resize_behavior);
 
  private:
   typedef std::map<Id, Window*> IdToWindowMap;
diff --git a/components/mus/public/cpp/window.h b/components/mus/public/cpp/window.h
index f3e39e8a..1b68e10 100644
--- a/components/mus/public/cpp/window.h
+++ b/components/mus/public/cpp/window.h
@@ -156,6 +156,7 @@
   // window_manager.mojom for details.
   void SetPreferredSize(const gfx::Size& size);
   void SetShowState(mojom::ShowState show_state);
+  void SetResizeBehavior(mojom::ResizeBehavior resize_behavior);
 
   // Focus.
   void SetFocus();
diff --git a/components/mus/public/interfaces/window_manager.mojom b/components/mus/public/interfaces/window_manager.mojom
index 140e455a..97e0292 100644
--- a/components/mus/public/interfaces/window_manager.mojom
+++ b/components/mus/public/interfaces/window_manager.mojom
@@ -26,9 +26,10 @@
   const string kPreferredSize_Property = "prop:preferred-size";
   // The window's show state. Type: ShowState.
   const string kShowState_Property = "prop:show-state";
+  // The window's resize behavior. Type: ResizeBehavior.
+  const string kResizeBehavior_Property = "prop:resize-behavior";
 
-  OpenWindow(WindowTreeClient client,
-             map<string, array<uint8>> properties);
+  OpenWindow(WindowTreeClient client, map<string, array<uint8>> properties);
 
   // Updates the window's preferred size and triggers a relayout of the window
   // within its container.
@@ -41,5 +42,7 @@
   SetShowState(uint32 window_id, ShowState show_state) =>
       (WindowManagerErrorCode result);
 
+  SetResizeBehavior(uint32 window_id, ResizeBehavior resize_behavior);
+
   GetConfig() => (WindowManagerConfig config);
 };
diff --git a/components/mus/public/interfaces/window_manager_constants.mojom b/components/mus/public/interfaces/window_manager_constants.mojom
index 47d0b4d7..1c0f44d7 100644
--- a/components/mus/public/interfaces/window_manager_constants.mojom
+++ b/components/mus/public/interfaces/window_manager_constants.mojom
@@ -26,6 +26,13 @@
   VALUE_270,
 };
 
+enum ResizeBehavior {
+  NONE = 0,
+  CAN_RESIZE = 1,
+  CAN_MAXIMIZE = 2,
+  CAN_MINIMIZE = 4,
+};
+
 struct Display {
   int64 id;
   mojo.Rect bounds;
diff --git a/components/mus/public/interfaces/window_tree.mojom b/components/mus/public/interfaces/window_tree.mojom
index 67a2f3a..7c2f99c 100644
--- a/components/mus/public/interfaces/window_tree.mojom
+++ b/components/mus/public/interfaces/window_tree.mojom
@@ -196,6 +196,7 @@
       (WindowManagerErrorCode result);
   SetShowState(uint32 window_id, ShowState show_state) =>
       (WindowManagerErrorCode result);
+  SetResizeBehavior(uint32 window_id, ResizeBehavior resize_behavior);
 };
 
 // Changes to windows are not sent to the connection that originated the
diff --git a/components/mus/ws/window_tree_impl.cc b/components/mus/ws/window_tree_impl.cc
index d8872fd..85c6e50 100644
--- a/components/mus/ws/window_tree_impl.cc
+++ b/components/mus/ws/window_tree_impl.cc
@@ -739,22 +739,27 @@
     uint32_t window_id,
     mojo::SizePtr size,
     const SetPreferredSizeCallback& callback) {
-  if (!GetHost() || !GetHost()->window_manager())
-    return;
-
-  // TODO(sky): verify window_id is valid for the client.
-  GetHost()->window_manager()->SetPreferredSize(window_id, size.Pass(),
-                                                callback);
+  ServerWindow* window = GetWindow(WindowIdFromTransportId(window_id));
+  if (window && ShouldRouteToWindowManager(window)) {
+    GetHost()->window_manager()->SetPreferredSize(window_id, size.Pass(),
+                                                  callback);
+  }
 }
 
 void WindowTreeImpl::SetShowState(uint32_t window_id,
                                   mojom::ShowState show_state,
                                   const SetShowStateCallback& callback) {
-  if (!GetHost() || !GetHost()->window_manager())
-    return;
+  ServerWindow* window = GetWindow(WindowIdFromTransportId(window_id));
+  if (window && ShouldRouteToWindowManager(window))
+    GetHost()->window_manager()->SetShowState(window_id, show_state, callback);
+}
 
-  // TODO(sky): verify window_id is valid for the client.
-  GetHost()->window_manager()->SetShowState(window_id, show_state, callback);
+void WindowTreeImpl::SetResizeBehavior(
+    uint32_t window_id,
+    mus::mojom::ResizeBehavior resize_behavior) {
+  ServerWindow* window = GetWindow(WindowIdFromTransportId(window_id));
+  if (window && ShouldRouteToWindowManager(window))
+    GetHost()->window_manager()->SetResizeBehavior(window_id, resize_behavior);
 }
 
 bool WindowTreeImpl::IsRootForAccessPolicy(const WindowId& id) const {
diff --git a/components/mus/ws/window_tree_impl.h b/components/mus/ws/window_tree_impl.h
index c8c7f8c..6c22ae6 100644
--- a/components/mus/ws/window_tree_impl.h
+++ b/components/mus/ws/window_tree_impl.h
@@ -228,6 +228,8 @@
   void SetShowState(uint32_t window_id,
                     mus::mojom::ShowState show_state,
                     const SetShowStateCallback& callback) override;
+  void SetResizeBehavior(uint32_t window_id,
+                         mus::mojom::ResizeBehavior resize_behavior) override;
 
   // AccessPolicyDelegate:
   bool IsRootForAccessPolicy(const WindowId& id) const override;
diff --git a/components/resource_provider/file_utils.cc b/components/resource_provider/file_utils.cc
index 5aeccdf..b4be730 100644
--- a/components/resource_provider/file_utils.cc
+++ b/components/resource_provider/file_utils.cc
@@ -27,16 +27,20 @@
 }  // namespace
 
 base::FilePath GetPathForApplicationUrl(const std::string& application_url) {
-// We don't want to use GURL because it can behave differently depending on
+  // We don't want to use GURL because it can behave differently depending on
   // whether mojo:// has been registered as a standard scheme or not. Also, we
   // can get mojo:foo or mojo://foo urls here.
   std::string path = application_url;
-  if (!base::StartsWith(path, "mojo:", base::CompareCase::INSENSITIVE_ASCII) &&
-      !base::StartsWith(path, "exe:", base::CompareCase::INSENSITIVE_ASCII))
+  const bool is_mojo =
+      base::StartsWith(path, "mojo:", base::CompareCase::INSENSITIVE_ASCII);
+  const bool is_exe =
+      !is_mojo &&
+      base::StartsWith(path, "exe:", base::CompareCase::INSENSITIVE_ASCII);
+  if (!is_mojo && !is_exe)
     return base::FilePath();
   if (path.find('.') != std::string::npos)
     return base::FilePath();
-  if (base::StartsWith(path, "mojo:", base::CompareCase::INSENSITIVE_ASCII))
+  if (is_mojo)
     path.erase(path.begin(), path.begin() + 5);
   else
     path.erase(path.begin(), path.begin() + 4);
@@ -49,7 +53,7 @@
   //             executable name in the exe dir and the resource package dir on
   //             non-Windows systems. Arbitrary exes should probably load their
   //             resources themselves rather than use resource provider.
-  if (base::StartsWith(path, "exe:", base::CompareCase::INSENSITIVE_ASCII))
+  if (is_exe)
     path += "_res";
 
   if (!IsPathNameValid(path))
diff --git a/components/resource_provider/public/cpp/BUILD.gn b/components/resource_provider/public/cpp/BUILD.gn
index 5d21378..ad13d1f 100644
--- a/components/resource_provider/public/cpp/BUILD.gn
+++ b/components/resource_provider/public/cpp/BUILD.gn
@@ -14,7 +14,7 @@
     "//mojo/application/public/cpp",
     "//mojo/application/public/interfaces",
     "//mojo/common",
-    "//mojo/platform_handle:for_shared_library",
+    "//mojo/platform_handle",
     "//third_party/mojo/src/mojo/public/cpp/bindings",
     "//third_party/mojo/src/mojo/public/cpp/system",
   ]
diff --git a/components/sync_driver.gypi b/components/sync_driver.gypi
index e0787f3..2a326d2 100644
--- a/components/sync_driver.gypi
+++ b/components/sync_driver.gypi
@@ -15,6 +15,7 @@
         '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation',
         '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_proto_cpp',
         '../ui/gfx/gfx.gyp:gfx',
+        'data_use_measurement_core',
         'invalidation_public',
         'os_crypt',
         'signin_core_browser',
@@ -68,6 +69,12 @@
         'sync_driver/glue/browser_thread_model_worker.h',
         'sync_driver/glue/chrome_report_unrecoverable_error.cc',
         'sync_driver/glue/chrome_report_unrecoverable_error.h',
+        'sync_driver/glue/sync_backend_host.cc',
+        'sync_driver/glue/sync_backend_host.h',
+        'sync_driver/glue/sync_backend_host_core.cc',
+        'sync_driver/glue/sync_backend_host_core.h',
+        'sync_driver/glue/sync_backend_host_impl.cc',
+        'sync_driver/glue/sync_backend_host_impl.h',
         'sync_driver/glue/sync_backend_registrar.cc',
         'sync_driver/glue/sync_backend_registrar.h',
         'sync_driver/glue/synced_session.cc',
@@ -196,6 +203,8 @@
         'sync_driver/fake_sync_service.h',
         'sync_driver/frontend_data_type_controller_mock.cc',
         'sync_driver/frontend_data_type_controller_mock.h',
+        'sync_driver/glue/sync_backend_host_mock.cc',
+        'sync_driver/glue/sync_backend_host_mock.h',
         'sync_driver/local_device_info_provider_mock.cc',
         'sync_driver/local_device_info_provider_mock.h',
         'sync_driver/model_associator_mock.cc',
diff --git a/components/sync_driver/BUILD.gn b/components/sync_driver/BUILD.gn
index ebd1a72d..da46e626 100644
--- a/components/sync_driver/BUILD.gn
+++ b/components/sync_driver/BUILD.gn
@@ -49,6 +49,12 @@
     "glue/browser_thread_model_worker.h",
     "glue/chrome_report_unrecoverable_error.cc",
     "glue/chrome_report_unrecoverable_error.h",
+    "glue/sync_backend_host.cc",
+    "glue/sync_backend_host.h",
+    "glue/sync_backend_host_core.cc",
+    "glue/sync_backend_host_core.h",
+    "glue/sync_backend_host_impl.cc",
+    "glue/sync_backend_host_impl.h",
     "glue/sync_backend_registrar.cc",
     "glue/sync_backend_registrar.h",
     "glue/synced_session.cc",
@@ -126,6 +132,7 @@
     "//base",
     "//base:prefs",
     "//base/third_party/dynamic_annotations",
+    "//components/data_use_measurement/core",
     "//components/invalidation/public",
     "//components/os_crypt",
     "//components/pref_registry",
@@ -172,6 +179,8 @@
     "fake_sync_service.h",
     "frontend_data_type_controller_mock.cc",
     "frontend_data_type_controller_mock.h",
+    "glue/sync_backend_host_mock.cc",
+    "glue/sync_backend_host_mock.h",
     "local_device_info_provider_mock.cc",
     "local_device_info_provider_mock.h",
     "model_associator_mock.cc",
diff --git a/components/sync_driver/DEPS b/components/sync_driver/DEPS
index 21a3935..a9469a4 100644
--- a/components/sync_driver/DEPS
+++ b/components/sync_driver/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+components/autofill/core/browser",
+  "+components/data_use_measurement/core",
   "+components/invalidation",
   "+components/os_crypt",
   "+components/password_manager/core/browser",
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/components/sync_driver/glue/sync_backend_host.cc
similarity index 66%
rename from chrome/browser/sync/glue/sync_backend_host.cc
rename to components/sync_driver/glue/sync_backend_host.cc
index b45142a..d9ffea6b 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/components/sync_driver/glue/sync_backend_host.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 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 "chrome/browser/sync/glue/sync_backend_host.h"
+#include "components/sync_driver/glue/sync_backend_host.h"
 
 namespace browser_sync {
 
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/components/sync_driver/glue/sync_backend_host.h
similarity index 97%
rename from chrome/browser/sync/glue/sync_backend_host.h
rename to components/sync_driver/glue/sync_backend_host.h
index f2eee5c7..7dfe96e 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/components/sync_driver/glue/sync_backend_host.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 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 CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
-#define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
+#ifndef COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_H_
+#define COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_H_
 
 #include <string>
 
@@ -227,9 +227,10 @@
   virtual void ClearServerData(
       const syncer::SyncManager::ClearServerDataCallback& callback) = 0;
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(SyncBackendHost);
 };
 
 }  // namespace browser_sync
 
-#endif  // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
+#endif  // COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_H_
diff --git a/chrome/browser/sync/glue/sync_backend_host_core.cc b/components/sync_driver/glue/sync_backend_host_core.cc
similarity index 99%
rename from chrome/browser/sync/glue/sync_backend_host_core.cc
rename to components/sync_driver/glue/sync_backend_host_core.cc
index feaf26c..31181ebc 100644
--- a/chrome/browser/sync/glue/sync_backend_host_core.cc
+++ b/components/sync_driver/glue/sync_backend_host_core.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/sync/glue/sync_backend_host_core.h"
+#include "components/sync_driver/glue/sync_backend_host_core.h"
 
 #include "base/bind.h"
 #include "base/files/file_util.h"
@@ -194,7 +194,7 @@
     backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES;
   } else if (!has_sync_setup_completed_ && restored_types.Empty()) {
     backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES;
-  } else { // (!has_sync_setup_completed_ && !restored_types.Empty())
+  } else {  // (!has_sync_setup_completed_ && !restored_types.Empty())
     backend_init_state = FIRST_SETUP_RESTORED_TYPES;
   }
 
diff --git a/chrome/browser/sync/glue/sync_backend_host_core.h b/components/sync_driver/glue/sync_backend_host_core.h
similarity index 97%
rename from chrome/browser/sync/glue/sync_backend_host_core.h
rename to components/sync_driver/glue/sync_backend_host_core.h
index 2229eed..9fcd0fab 100644
--- a/chrome/browser/sync/glue/sync_backend_host_core.h
+++ b/components/sync_driver/glue/sync_backend_host_core.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_CORE_H_
-#define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_CORE_H_
+#ifndef COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_CORE_H_
+#define COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_CORE_H_
 
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
-
 #include "base/timer/timer.h"
-#include "chrome/browser/sync/glue/sync_backend_host_impl.h"
 #include "components/invalidation/public/invalidation.h"
+#include "components/sync_driver/glue/sync_backend_host_impl.h"
 #include "components/sync_driver/system_encryptor.h"
 #include "sync/internal_api/public/base/cancelation_signal.h"
 #include "sync/internal_api/public/sessions/type_debug_info_observer.h"
@@ -329,4 +329,4 @@
 
 }  // namespace browser_sync
 
-#endif  // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_CORE_H_
+#endif  // COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_CORE_H_
diff --git a/chrome/browser/sync/glue/sync_backend_host_impl.cc b/components/sync_driver/glue/sync_backend_host_impl.cc
similarity index 99%
rename from chrome/browser/sync/glue/sync_backend_host_impl.cc
rename to components/sync_driver/glue/sync_backend_host_impl.cc
index 2a32857..eeb4712 100644
--- a/chrome/browser/sync/glue/sync_backend_host_impl.cc
+++ b/components/sync_driver/glue/sync_backend_host_impl.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/sync/glue/sync_backend_host_impl.h"
+#include "components/sync_driver/glue/sync_backend_host_impl.h"
 
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
-#include "chrome/browser/sync/glue/sync_backend_host_core.h"
 #include "components/invalidation/public/invalidation_service.h"
 #include "components/invalidation/public/object_id_invalidation_map.h"
 #include "components/signin/core/browser/signin_client.h"
+#include "components/sync_driver/glue/sync_backend_host_core.h"
 #include "components/sync_driver/glue/sync_backend_registrar.h"
 #include "components/sync_driver/invalidation_helper.h"
 #include "components/sync_driver/sync_client.h"
diff --git a/chrome/browser/sync/glue/sync_backend_host_impl.h b/components/sync_driver/glue/sync_backend_host_impl.h
similarity index 98%
rename from chrome/browser/sync/glue/sync_backend_host_impl.h
rename to components/sync_driver/glue/sync_backend_host_impl.h
index 30d2aa8..c8d5968 100644
--- a/chrome/browser/sync/glue/sync_backend_host_impl.h
+++ b/components/sync_driver/glue/sync_backend_host_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_IMPL_H_
-#define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_IMPL_H_
+#ifndef COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_IMPL_H_
+#define COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_IMPL_H_
 
 #include <string>
 
@@ -13,9 +13,9 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
 #include "components/invalidation/public/invalidation_handler.h"
 #include "components/sync_driver/backend_data_type_configurer.h"
+#include "components/sync_driver/glue/sync_backend_host.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/internal_api/public/configure_reason.h"
 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
@@ -375,4 +375,4 @@
 
 }  // namespace browser_sync
 
-#endif  // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_IMPL_H_
+#endif  // COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_IMPL_H_
diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.cc b/components/sync_driver/glue/sync_backend_host_mock.cc
similarity index 98%
rename from chrome/browser/sync/glue/sync_backend_host_mock.cc
rename to components/sync_driver/glue/sync_backend_host_mock.cc
index 59c015d..dd7a4dd9 100644
--- a/chrome/browser/sync/glue/sync_backend_host_mock.cc
+++ b/components/sync_driver/glue/sync_backend_host_mock.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/sync/glue/sync_backend_host_mock.h"
+#include "components/sync_driver/glue/sync_backend_host_mock.h"
 
 #include "components/sync_driver/sync_frontend.h"
 #include "sync/internal_api/public/activation_context.h"
@@ -104,7 +104,7 @@
 }
 
 bool SyncBackendHostMock::IsNigoriEnabled() const {
- return true;
+  return true;
 }
 
 syncer::PassphraseType SyncBackendHostMock::GetPassphraseType() const {
diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.h b/components/sync_driver/glue/sync_backend_host_mock.h
similarity index 94%
rename from chrome/browser/sync/glue/sync_backend_host_mock.h
rename to components/sync_driver/glue/sync_backend_host_mock.h
index 913ad60..1359f35e 100644
--- a/chrome/browser/sync/glue/sync_backend_host_mock.h
+++ b/components/sync_driver/glue/sync_backend_host_mock.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_MOCK_H_
-#define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_MOCK_H_
+#ifndef COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_MOCK_H_
+#define COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_MOCK_H_
 
 #include <string>
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
+#include "components/sync_driver/glue/sync_backend_host.h"
 #include "sync/internal_api/public/util/weak_handle.h"
 
 namespace browser_sync {
@@ -128,4 +128,4 @@
 
 }  // namespace browser_sync
 
-#endif  // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_MOCK_H_
+#endif  // COMPONENTS_SYNC_DRIVER_GLUE_SYNC_BACKEND_HOST_MOCK_H_
diff --git a/components/tracing/trace_config_file.cc b/components/tracing/trace_config_file.cc
index 769d527..f1df192 100644
--- a/components/tracing/trace_config_file.cc
+++ b/components/tracing/trace_config_file.cc
@@ -109,9 +109,9 @@
   if (startup_duration_ < 0)
       startup_duration_ = 0;
 
-  std::string result_file_str;
+  base::FilePath::StringType result_file_str;
   if (dict->GetString(kResultFileParam, &result_file_str))
-    result_file_ = base::FilePath().AppendASCII(result_file_str);
+    result_file_ = base::FilePath(result_file_str);
 
   return true;
 }
@@ -130,7 +130,7 @@
   return startup_duration_;
 }
 
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) || defined(USE_AURA)
 base::FilePath TraceConfigFile::GetResultFile() const {
   DCHECK(IsEnabled());
   return result_file_;
diff --git a/components/tracing/trace_config_file.h b/components/tracing/trace_config_file.h
index 863fee4..0834fc2 100644
--- a/components/tracing/trace_config_file.h
+++ b/components/tracing/trace_config_file.h
@@ -70,7 +70,7 @@
   bool IsEnabled() const;
   base::trace_event::TraceConfig GetTraceConfig() const;
   int GetStartupDuration() const;
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) || defined(USE_AURA)
   base::FilePath GetResultFile() const;
 #endif
 
diff --git a/components/tracing/trace_config_file_unittest.cc b/components/tracing/trace_config_file_unittest.cc
index d62c4d4..d7d355a 100644
--- a/components/tracing/trace_config_file_unittest.cc
+++ b/components/tracing/trace_config_file_unittest.cc
@@ -146,6 +146,37 @@
             TraceConfigFile::GetInstance()->GetResultFile());
 }
 
+TEST(TraceConfigFileTest, ContentWithAbsoluteResultFilePath) {
+  base::ShadowingAtExitManager sem;
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  const base::FilePath result_file_path =
+      temp_dir.path().Append(FILE_PATH_LITERAL("trace_result_file.log"));
+  ASSERT_TRUE(result_file_path.IsAbsolute());
+
+  std::string result_file_path_str = result_file_path.AsUTF8Unsafe();
+  auto it = std::find(
+      result_file_path_str.begin(), result_file_path_str.end(), '\\');
+  while (it != result_file_path_str.end()) {
+    auto it2 = result_file_path_str.insert(it, '\\');
+    it = std::find(it2+2, result_file_path_str.end(), '\\');
+  }
+  std::string content = GetTraceConfigFileContent(
+      kTraceConfig, "10", result_file_path_str);
+
+  base::FilePath trace_config_file;
+  ASSERT_TRUE(
+      base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file));
+  ASSERT_NE(-1, base::WriteFile(
+      trace_config_file, content.c_str(), (int)content.length()));
+  base::CommandLine::ForCurrentProcess()->AppendSwitchPath(
+      switches::kTraceConfigFile, trace_config_file);
+
+  ASSERT_TRUE(TraceConfigFile::GetInstance()->IsEnabled());
+  EXPECT_EQ(result_file_path, TraceConfigFile::GetInstance()->GetResultFile());
+}
+
 TEST(TraceConfigFileTest, ContentWithNegtiveDuration) {
   base::ShadowingAtExitManager sem;
   std::string content = GetTraceConfigFileContent(kTraceConfig, "-1", "");
diff --git a/components/url_formatter/BUILD.gn b/components/url_formatter/BUILD.gn
index 3b777de..b74ef78 100644
--- a/components/url_formatter/BUILD.gn
+++ b/components/url_formatter/BUILD.gn
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/ui.gni")
+
 source_set("url_formatter") {
   sources = [
     "elide_url.cc",
@@ -22,7 +24,7 @@
     "//url",
   ]
 
-  if (!is_android) {
+  if (!is_android || use_aura) {
     deps += [ "//ui/gfx" ]
   }
 }
@@ -40,11 +42,10 @@
     "//base",
     "//net",
     "//testing/gtest",
-    "//ui/gfx",
     "//url",
   ]
 
-  if (is_android) {
-    deps -= [ "//ui/gfx" ]
+  if (!is_android || use_aura) {
+    deps += [ "//ui/gfx" ]
   }
 }
diff --git a/components/url_formatter/elide_url.cc b/components/url_formatter/elide_url.cc
index 80e7866..3d216a6f 100644
--- a/components/url_formatter/elide_url.cc
+++ b/components/url_formatter/elide_url.cc
@@ -13,14 +13,14 @@
 #include "url/gurl.h"
 #include "url/url_constants.h"
 
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) || defined(USE_AURA)
 #include "ui/gfx/text_elider.h"  // nogncheck
 #include "ui/gfx/text_utils.h"  // nogncheck
-#endif
+#endif  // !defined(OS_ANDROID) || defined(USE_AURA)
 
 namespace {
 
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) || defined(USE_AURA)
 const base::char16 kDot = '.';
 
 // Build a path from the first |num_components| elements in |path_elements|.
@@ -102,7 +102,7 @@
   }
 }
 
-#endif  // !defined(OS_ANDROID)
+#endif  // !defined(OS_ANDROID) || defined(USE_AURA)
 
 base::string16 FormatUrlForSecurityDisplayInternal(const GURL& url,
                                                    const std::string& languages,
@@ -154,7 +154,7 @@
 
 namespace url_formatter {
 
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) || defined(USE_AURA)
 
 // TODO(pkasting): http://crbug.com/77883 This whole function gets
 // kerning/ligatures/etc. issues potentially wrong by assuming that the width of
@@ -354,7 +354,7 @@
   return elided_subdomain + url_domain;
 }
 
-#endif  // !defined(OS_ANDROID)
+#endif  // !defined(OS_ANDROID) || defined(USE_AURA)
 
 base::string16 FormatUrlForSecurityDisplay(const GURL& url,
                                            const std::string& languages) {
diff --git a/components/url_formatter/elide_url.h b/components/url_formatter/elide_url.h
index 74777de..73c0baa 100644
--- a/components/url_formatter/elide_url.h
+++ b/components/url_formatter/elide_url.h
@@ -21,7 +21,7 @@
 
 // ElideUrl and Elide host require
 // gfx::GetStringWidthF which is not implemented in Android
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) || defined(USE_AURA)
 // This function takes a GURL object and elides it. It returns a string
 // which composed of parts from subdomain, domain, path, filename and query.
 // A "..." is added automatically at the end if the elided string is bigger
@@ -49,7 +49,7 @@
 base::string16 ElideHost(const GURL& host_url,
                          const gfx::FontList& font_list,
                          float available_pixel_width);
-#endif  // !defined(OS_ANDROID)
+#endif  // !defined(OS_ANDROID) || defined(USE_AURA)
 
 // This is a convenience function for formatting a URL in a concise and
 // human-friendly way, to help users make security-related decisions (or in
diff --git a/components/url_formatter/url_formatter.gyp b/components/url_formatter/url_formatter.gyp
index 9375e96..304c545 100644
--- a/components/url_formatter/url_formatter.gyp
+++ b/components/url_formatter/url_formatter.gyp
@@ -28,7 +28,7 @@
       'msvs_disabled_warnings': [4267, ],
 
       'conditions': [
-        ['OS != "android"', {
+        ['OS!="android" or use_aura==1', {
           'dependencies': [
             '../../ui/gfx/gfx.gyp:gfx',
           ]
diff --git a/content/app/android/library_loader_hooks.cc b/content/app/android/library_loader_hooks.cc
index 6f9d939..0d36b85 100644
--- a/content/app/android/library_loader_hooks.cc
+++ b/content/app/android/library_loader_hooks.cc
@@ -33,7 +33,10 @@
 #include "ui/events/android/events_jni_registrar.h"
 #include "ui/gfx/android/gfx_jni_registrar.h"
 #include "ui/gl/android/gl_jni_registrar.h"
+
+#if !defined(USE_AURA)
 #include "ui/shell_dialogs/android/shell_dialogs_jni_registrar.h"
+#endif
 
 namespace content {
 
@@ -59,8 +62,10 @@
     if (!ui::events::android::RegisterJni(env))
       return false;
 
+#if !defined(USE_AURA)
     if (!ui::shell_dialogs::RegisterJni(env))
       return false;
+#endif
 
     if (!content::android::RegisterCommonJni(env))
       return false;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index b0a2263..b05a0c84 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -328,10 +328,6 @@
     sources += rebase_path(content_browser_gypi_values.android_browser_sources,
                            ".",
                            "//content")
-    sources += rebase_path(
-            content_browser_gypi_values.android_in_process_browser_sources,
-            ".",
-            "//content")
     sources -= [
       "browser_ipc_logging.cc",
       "device_sensors/data_fetcher_shared_memory_default.cc",
@@ -341,7 +337,6 @@
       "geolocation/network_location_request.h",
       "power_usage_monitor_impl.cc",
       "power_usage_monitor_impl.h",
-      "renderer_host/begin_frame_observer_proxy.cc",
       "tracing/tracing_ui.cc",
       "tracing/tracing_ui.h",
 
@@ -367,6 +362,19 @@
       "speech/speech_recognizer_impl.cc",
       "speech/speech_recognizer_impl.h",
     ]
+
+    if (!use_aura) {
+      sources += rebase_path(
+              content_browser_gypi_values.android_non_aura_browser_sources,
+              ".",
+              "//content")
+      sources += rebase_path(
+              content_browser_gypi_values.android_in_process_browser_sources,
+              ".",
+              "//content")
+      sources -= [ "renderer_host/begin_frame_observer_proxy.cc" ]
+    }
+
     deps -= [ "//device/battery" ]
     deps += [
       "//content/public/android:jni",
diff --git a/content/browser/accessibility/accessibility_tree_formatter.cc b/content/browser/accessibility/accessibility_tree_formatter.cc
index 9d786338f..a60db9a 100644
--- a/content/browser/accessibility/accessibility_tree_formatter.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter.cc
@@ -98,10 +98,7 @@
   }
 }
 
-#if !defined(OS_WIN) && \
-    !defined(OS_MACOSX) && \
-    !defined(OS_ANDROID) && \
-    !(defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_X11))
+#if !defined(PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL)
 void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
                                                base::DictionaryValue* dict) {
   dict->SetInteger("id", node.GetId());
@@ -142,7 +139,7 @@
 const std::string AccessibilityTreeFormatter::GetDenyString() {
   return std::string();
 }
-#endif
+#endif  // PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL
 
 void AccessibilityTreeFormatter::SetFilters(
     const std::vector<Filter>& filters) {
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 3e15a385..bf9faf2 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -16,12 +16,7 @@
 
 namespace content {
 
-#if !defined(OS_WIN) && \
-    !defined(OS_MACOSX) && \
-    !defined(OS_ANDROID) && \
-    !(defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_X11))
-// We have subclassess of BrowserAccessibility on some platforms.
-// On other platforms, instantiate the base class.
+#if !defined(PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL)
 // static
 BrowserAccessibility* BrowserAccessibility::Create() {
   return new BrowserAccessibility();
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index fd4d679..d820508 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -19,6 +19,27 @@
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/ax_text_utils.h"
 
+// Set PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL if this platform has
+// a platform-specific subclass of BrowserAccessibility and
+// BrowserAccessibilityManager.
+#undef PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL
+
+#if defined(OS_WIN)
+#define PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL 1
+#endif
+
+#if defined(OS_MACOSX)
+#define PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL 1
+#endif
+
+#if defined(OS_ANDROID) && !defined(USE_AURA)
+#define PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL 1
+#endif
+
+#if defined(OS_LINUX) && defined(USE_X11) && !defined(OS_CHROMEOS)
+#define PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL 1
+#endif
+
 #if defined(OS_MACOSX) && __OBJC__
 @class BrowserAccessibilityCocoa;
 #endif
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index b47fb827a..8e8eabd 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -75,7 +75,12 @@
 }
 
 BrowserAccessibility* BrowserAccessibilityFactory::Create() {
+  // TODO(mfomitchev): Accessibility on Android Aura - crbug.com/543262.
+#if defined(OS_ANDROID) && defined(USE_AURA)
+  return nullptr;
+#else
   return BrowserAccessibility::Create();
+#endif
 }
 
 BrowserAccessibilityFindInPageInfo::BrowserAccessibilityFindInPageInfo()
@@ -87,12 +92,7 @@
       end_offset(-1),
       active_request_id(-1) {}
 
-#if !defined(OS_WIN) && \
-    !defined(OS_MACOSX) && \
-    !defined(OS_ANDROID) && \
-    !(defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_X11))
-// We have subclassess of BrowserAccessibility on some platforms.
-// For other platforms, instantiate the base class.
+#if !defined(PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL)
 // static
 BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
     const ui::AXTreeUpdate& initial_tree,
diff --git a/content/browser/android/browser_jni_registrar.cc b/content/browser/android/browser_jni_registrar.cc
index 557c8f3..d8bed79 100644
--- a/content/browser/android/browser_jni_registrar.cc
+++ b/content/browser/android/browser_jni_registrar.cc
@@ -6,14 +6,22 @@
 
 #include "base/android/jni_android.h"
 #include "base/android/jni_registrar.h"
+#include "content/browser/android/browser_startup_controller.h"
+#include "content/browser/android/child_process_launcher_android.h"
+#include "content/browser/android/content_video_view.h"
+#include "content/browser/media/android/media_drm_credential_manager.h"
+#include "content/browser/media/android/media_resource_getter_impl.h"
+#include "content/browser/media/android/media_session.h"
+#include "content/browser/mojo/service_registrar_android.h"
+#include "content/browser/mojo/service_registry_android.h"
+#include "mojo/android/system/core_impl.h"
+
+#if !defined(USE_AURA)
 #include "content/browser/accessibility/browser_accessibility_android.h"
 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
 #include "content/browser/android/background_sync_network_observer_android.h"
-#include "content/browser/android/browser_startup_controller.h"
-#include "content/browser/android/child_process_launcher_android.h"
 #include "content/browser/android/composited_touch_handle_drawable.h"
 #include "content/browser/android/content_readback_handler.h"
-#include "content/browser/android/content_video_view.h"
 #include "content/browser/android/content_view_core_impl.h"
 #include "content/browser/android/content_view_render_view.h"
 #include "content/browser/android/content_view_statics.h"
@@ -28,11 +36,6 @@
 #include "content/browser/frame_host/navigation_controller_android.h"
 #include "content/browser/gamepad/gamepad_platform_data_fetcher_android.h"
 #include "content/browser/geolocation/location_api_adapter_android.h"
-#include "content/browser/media/android/media_drm_credential_manager.h"
-#include "content/browser/media/android/media_resource_getter_impl.h"
-#include "content/browser/media/android/media_session.h"
-#include "content/browser/mojo/service_registrar_android.h"
-#include "content/browser/mojo/service_registry_android.h"
 #include "content/browser/power_save_blocker_android.h"
 #include "content/browser/renderer_host/ime_adapter_android.h"
 #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
@@ -41,10 +44,20 @@
 #include "content/browser/time_zone_monitor_android.h"
 #include "content/browser/vr/android/cardboard/cardboard_vr_device.h"
 #include "content/browser/web_contents/web_contents_android.h"
-#include "mojo/android/system/core_impl.h"
+#endif
 
 namespace {
 base::android::RegistrationMethod kContentRegisteredMethods[] = {
+    {"BrowserStartupController", content::RegisterBrowserStartupController},
+    {"ChildProcessLauncher", content::RegisterChildProcessLauncher},
+    {"ContentVideoView", content::ContentVideoView::RegisterContentVideoView},
+    {"CoreImpl", mojo::android::RegisterCoreImpl},
+    {"MediaDrmCredentialManager",
+     content::MediaDrmCredentialManager::RegisterMediaDrmCredentialManager},
+    {"MediaResourceGetterImpl",
+     content::MediaResourceGetterImpl::RegisterMediaResourceGetter},
+    {"MediaSession", content::MediaSession::RegisterMediaSession},
+#if !defined(USE_AURA)
     {"AndroidLocationApiAdapter",
      content::AndroidLocationApiAdapter::RegisterGeolocationService},
     {"BackgroundSyncNetworkObserverAndroid",
@@ -52,19 +65,15 @@
          RegisterNetworkObserver},
     {"BrowserAccessibilityManager",
      content::RegisterBrowserAccessibilityManager},
-    {"BrowserStartupController", content::RegisterBrowserStartupController},
 #if defined(ENABLE_WEBVR)
     {"CardboardVRDevice",
      content::CardboardVRDevice::RegisterCardboardVRDevice},
 #endif
-    {"ChildProcessLauncher", content::RegisterChildProcessLauncher},
     {"ContentReadbackHandler",
      content::ContentReadbackHandler::RegisterContentReadbackHandler},
-    {"ContentVideoView", content::ContentVideoView::RegisterContentVideoView},
     {"ContentViewCore", content::RegisterContentViewCore},
     {"ContentViewRenderView",
      content::ContentViewRenderView::RegisterContentViewRenderView},
-    {"CoreImpl", mojo::android::RegisterCoreImpl},
     {"DateTimePickerAndroid", content::RegisterDateTimeChooserAndroid},
     {"DownloadControllerAndroidImpl",
      content::DownloadControllerAndroidImpl::RegisterDownloadController},
@@ -77,11 +86,6 @@
      content::InterstitialPageDelegateAndroid::
          RegisterInterstitialPageDelegateAndroid},
     {"LoadUrlParams", content::RegisterLoadUrlParams},
-    {"MediaDrmCredentialManager",
-     content::MediaDrmCredentialManager::RegisterMediaDrmCredentialManager},
-    {"MediaResourceGetterImpl",
-     content::MediaResourceGetterImpl::RegisterMediaResourceGetter},
-    {"MediaSession", content::MediaSession::RegisterMediaSession},
     {"MotionEventSynthesizer",
      content::SyntheticGestureTargetAndroid::RegisterMotionEventSynthesizer},
     {"NavigationControllerAndroid",
@@ -102,6 +106,7 @@
     {"WebContentsAndroid", content::WebContentsAndroid::Register},
     {"WebContentsObserver", content::RegisterWebContentsObserverProxy},
     {"WebViewStatics", content::RegisterWebViewStatics},
+#endif  // !USE_AURA
 };
 
 }  // namespace
diff --git a/content/browser/android/child_process_launcher_android.cc b/content/browser/android/child_process_launcher_android.cc
index 07490433..94ce411e 100644
--- a/content/browser/android/child_process_launcher_android.cc
+++ b/content/browser/android/child_process_launcher_android.cc
@@ -36,6 +36,7 @@
     base::ProcessHandle render_process_handle,
     int render_frame_id,
     int player_id) {
+#if !defined(USE_AURA)
   int render_process_id = 0;
   RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
   while (!it.IsAtEnd()) {
@@ -77,6 +78,9 @@
     gfx::ScopedJavaSurface scoped_surface(surface);
     player->SetVideoSurface(scoped_surface.Pass());
   }
+#else
+  NOTREACHED();
+#endif
 }
 
 }  // anonymous namespace
diff --git a/content/browser/android/content_startup_flags.cc b/content/browser/android/content_startup_flags.cc
index a775b14..8c2e541b 100644
--- a/content/browser/android/content_startup_flags.cc
+++ b/content/browser/android/content_startup_flags.cc
@@ -80,11 +80,13 @@
         switches::kProfilerTiming, switches::kProfilerTimingDisabledValue);
   }
 
+#if !defined(USE_AURA)
   cc::LayerSettings layer_settings;
   if (parsed_command_line->HasSwitch(
           switches::kEnableAndroidCompositorAnimationTimelines))
     layer_settings.use_compositor_animation_timelines = true;
   Compositor::SetLayerSettings(layer_settings);
+#endif
 }
 
 }  // namespace content
diff --git a/content/browser/android/content_video_view.cc b/content/browser/android/content_video_view.cc
index 8a9eb429..24d4647e 100644
--- a/content/browser/android/content_video_view.cc
+++ b/content/browser/android/content_video_view.cc
@@ -8,7 +8,6 @@
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
-#include "content/browser/android/content_view_core_impl.h"
 #include "content/browser/media/android/browser_media_player_manager.h"
 #include "content/browser/power_save_blocker_impl.h"
 #include "content/common/android/surface_texture_peer.h"
@@ -16,6 +15,10 @@
 #include "content/public/common/content_switches.h"
 #include "jni/ContentVideoView_jni.h"
 
+#if !defined(USE_AURA)
+#include "content/browser/android/content_view_core_impl.h"
+#endif
+
 using base::android::AttachCurrentThread;
 using base::android::CheckException;
 using base::android::ScopedJavaGlobalRef;
@@ -198,11 +201,17 @@
 }
 
 JavaObjectWeakGlobalRef ContentVideoView::CreateJavaObject() {
-  ContentViewCore* content_view_core = manager_->GetContentViewCore();
-  JNIEnv* env = AttachCurrentThread();
 
-  base::android::ScopedJavaLocalRef<jobject> j_content_view_core =
-      content_view_core->GetJavaObject();
+  JNIEnv* env = AttachCurrentThread();
+  base::android::ScopedJavaLocalRef<jobject> j_content_view_core;
+
+  // TODO(mfomitchev): Support fullscreen video underlay on Android Aura.
+  // crbug.com/548024
+#if !defined(USE_AURA)
+  ContentViewCore* content_view_core = manager_->GetContentViewCore();
+  j_content_view_core = content_view_core->GetJavaObject();
+#endif
+
   if (j_content_view_core.is_null())
     return JavaObjectWeakGlobalRef(env, nullptr);
 
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 9d49564..94dd29d5 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -616,7 +616,8 @@
           BrowserSurfaceTextureManager::GetInstance());
     }
   }
-
+  // TODO(mfomitchev): Screen Orientation APIs on Aura - crbug.com/546719.
+#if !defined(USE_AURA)
   if (!parsed_command_line_.HasSwitch(
       switches::kDisableScreenOrientationLock)) {
     TRACE_EVENT0("startup",
@@ -626,6 +627,7 @@
     ScreenOrientationProvider::SetDelegate(screen_orientation_delegate_.get());
   }
 #endif
+#endif
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
   {
@@ -1179,7 +1181,7 @@
 
   bool always_uses_gpu = true;
   bool established_gpu_channel = false;
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   // TODO(crbug.com/439322): This should be set to |true|.
   established_gpu_channel = false;
   BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
@@ -1381,7 +1383,7 @@
       return trace_file;
 
     if (trace_file.empty()) {
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
       TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
 #else
       // Default to saving the startup trace into the current dir.
@@ -1389,7 +1391,7 @@
 #endif
     }
   } else {
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
     TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
 #else
     trace_file = tracing::TraceConfigFile::GetInstance()->GetResultFile();
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc
index b19fc6950b..63200ca7 100644
--- a/content/browser/browser_main_runner.cc
+++ b/content/browser/browser_main_runner.cc
@@ -264,7 +264,7 @@
     } else if (tracing::TraceConfigFile::GetInstance()->IsEnabled() &&
                TracingController::GetInstance()->IsRecording()) {
       base::FilePath result_file;
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
       TracingControllerAndroid::GenerateTracingFilePath(&result_file);
 #else
       result_file = tracing::TraceConfigFile::GetInstance()->GetResultFile();
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index b74845f..7e2c513b9 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -133,11 +133,16 @@
 
 scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
 GpuProcessTransportFactory::CreateOffscreenCommandBufferContext() {
+#if defined(OS_ANDROID)
+  // TODO(mfomitchev): crbug.com/546716
+  return CreateContextCommon(scoped_refptr<GpuChannelHost>(nullptr), 0);
+#else
   CauseForGpuLaunch cause =
       CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
   scoped_refptr<GpuChannelHost> gpu_channel_host(
       BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync(cause));
   return CreateContextCommon(gpu_channel_host, 0);
+#endif  // OS_ANDROID
 }
 
 scoped_ptr<cc::SoftwareOutputDevice>
diff --git a/content/browser/compositor/surface_utils.cc b/content/browser/compositor/surface_utils.cc
index 78f63a0..772199dcc 100644
--- a/content/browser/compositor/surface_utils.cc
+++ b/content/browser/compositor/surface_utils.cc
@@ -6,7 +6,7 @@
 
 #include "cc/surfaces/surface_id_allocator.h"
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
 #include "content/browser/renderer_host/compositor_impl_android.h"
 #else
 #include "content/browser/compositor/image_transport_factory.h"
@@ -16,7 +16,7 @@
 namespace content {
 
 scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() {
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   return CompositorImpl::CreateSurfaceIdAllocator();
 #else
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
@@ -25,7 +25,7 @@
 }
 
 cc::SurfaceManager* GetSurfaceManager() {
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   return CompositorImpl::GetSurfaceManager();
 #else
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 2a7bf35..f8cae1a 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -470,4 +470,16 @@
   EXPECT_TRUE(success);
 }
 
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ReloadBlankPage) {
+  Shell* window =  Shell::CreateNewWindow(
+      shell()->web_contents()->GetBrowserContext(),
+      GURL("javascript:x=1"),
+      nullptr,
+      gfx::Size());
+  WaitForLoadStop(window->web_contents());
+  Attach();
+  SendCommand("Page.reload", nullptr, false);
+  // Should not crash at this point.
+}
+
 }  // namespace content
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc
index c1e8816..73c4c8ea 100644
--- a/content/browser/devtools/protocol/page_handler.cc
+++ b/content/browser/devtools/protocol/page_handler.cc
@@ -214,7 +214,8 @@
     return Response::InternalError("Could not connect to view");
 
   if (web_contents->IsCrashed() ||
-      web_contents->GetController().GetVisibleEntry()->IsViewSourceMode()) {
+      (web_contents->GetController().GetVisibleEntry() &&
+       web_contents->GetController().GetVisibleEntry()->IsViewSourceMode())) {
     web_contents->GetController().Reload(false);
     return Response::OK();
   } else {
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index f2c387c..fb191fb 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -446,7 +446,8 @@
 
   frame_trace_recorder_.reset(new DevToolsFrameTraceRecorder());
 
-#if defined(OS_ANDROID)
+  //TODO(mfomitchev): Support PowerSaveBlocker on Aura - crbug.com/546718.
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   power_save_blocker_.reset(static_cast<PowerSaveBlockerImpl*>(
       PowerSaveBlocker::Create(
           PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
diff --git a/content/browser/frame_host/frame_tree.cc b/content/browser/frame_host/frame_tree.cc
index 911ae0d..651599b 100644
--- a/content/browser/frame_host/frame_tree.cc
+++ b/content/browser/frame_host/frame_tree.cc
@@ -287,8 +287,8 @@
     }
   }
 
-  node->set_last_focus_time(base::TimeTicks::Now());
   focused_frame_tree_node_id_ = node->frame_tree_node_id();
+  node->DidFocus();
 }
 
 void FrameTree::SetFrameRemoveListener(
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc
index 4ef98a19f..13d3621a 100644
--- a/content/browser/frame_host/frame_tree_node.cc
+++ b/content/browser/frame_host/frame_tree_node.cc
@@ -386,4 +386,9 @@
   return true;
 }
 
+void FrameTreeNode::DidFocus() {
+  last_focus_time_ = base::TimeTicks::Now();
+  FOR_EACH_OBSERVER(Observer, observers_, OnFrameTreeNodeFocused(this));
+}
+
 }  // namespace content
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h
index 3db6cb45..bc1a9304 100644
--- a/content/browser/frame_host/frame_tree_node.h
+++ b/content/browser/frame_host/frame_tree_node.h
@@ -37,6 +37,9 @@
     // Invoked when a FrameTreeNode is being destroyed.
     virtual void OnFrameTreeNodeDestroyed(FrameTreeNode* node) {}
 
+    // Invoked when a FrameTreeNode becomes focused.
+    virtual void OnFrameTreeNodeFocused(FrameTreeNode* node) {}
+
     virtual ~Observer() {}
   };
 
@@ -216,9 +219,10 @@
 
   // Returns the time this frame was last focused.
   base::TimeTicks last_focus_time() const { return last_focus_time_; }
-  void set_last_focus_time(const base::TimeTicks& last_focus_time) {
-    last_focus_time_ = last_focus_time;
-  }
+
+  // Called when this node becomes focused.  Updates the node's last focused
+  // time and notifies observers.
+  void DidFocus();
 
  private:
   class OpenerDestroyedObserver;
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc
index 1324f77..5e001bf 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -472,8 +472,13 @@
 BrowserAccessibilityManager*
 RenderWidgetHostViewChildFrame::CreateBrowserAccessibilityManager(
     BrowserAccessibilityDelegate* delegate) {
+  // TODO(mfomitchev): Accessibility on Android Aura: crbug.com/543262
+#if defined(OS_ANDROID) && defined(USE_AURA)
+  return nullptr;
+#else
   return BrowserAccessibilityManager::Create(
       BrowserAccessibilityManager::GetEmptyDocument(), delegate);
+#endif
 }
 
 void RenderWidgetHostViewChildFrame::ClearCompositorSurfaceIfNecessary() {
diff --git a/content/browser/media/cdm/browser_cdm_manager.cc b/content/browser/media/cdm/browser_cdm_manager.cc
index 6ba327b..1b7f5522 100644
--- a/content/browser/media/cdm/browser_cdm_manager.cc
+++ b/content/browser/media/cdm/browser_cdm_manager.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/lazy_instance.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/task_runner.h"
@@ -19,12 +20,14 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_process_host_observer.h"
 #include "content/public/browser/web_contents.h"
-#include "media/base/browser_cdm_factory.h"
+#include "media/base/cdm_config.h"
+#include "media/base/cdm_factory.h"
 #include "media/base/cdm_promise.h"
 #include "media/base/limits.h"
 
 #if defined(OS_ANDROID)
 #include "content/public/common/renderer_preferences.h"
+#include "media/base/android/android_cdm_factory.h"
 #endif
 
 namespace content {
@@ -269,6 +272,20 @@
                                 system_code, error_message));
 }
 
+media::CdmFactory* BrowserCdmManager::GetCdmFactory() {
+  if (!cdm_factory_) {
+    // Create a new CdmFactory.
+    cdm_factory_ = GetContentClient()->browser()->CreateCdmFactory();
+
+#if defined(OS_ANDROID)
+    if (!cdm_factory_)
+      cdm_factory_.reset(new media::AndroidCdmFactory());
+#endif
+  }
+
+  return cdm_factory_.get();
+}
+
 void BrowserCdmManager::OnSessionMessage(int render_frame_id,
                                          int cdm_id,
                                          const std::string& session_id,
@@ -327,20 +344,52 @@
                                           new_expiry_time));
 }
 
+// Use a weak pointer here instead of |this| to avoid circular references.
+#define BROWSER_CDM_MANAGER_CB(func, ...)                              \
+  base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \
+             render_frame_id, cdm_id, ##__VA_ARGS__)
+
 void BrowserCdmManager::OnInitializeCdm(
     int render_frame_id,
     int cdm_id,
     uint32_t promise_id,
     const CdmHostMsg_InitializeCdm_Params& params) {
+  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(!GetCdm(render_frame_id, cdm_id));
+
+  scoped_ptr<SimplePromise> promise(new SimplePromise(
+      weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
+
   if (params.key_system.size() > media::limits::kMaxKeySystemLength) {
     NOTREACHED() << "Invalid key system: " << params.key_system;
-    RejectPromise(render_frame_id, cdm_id, promise_id,
-                  MediaKeys::INVALID_ACCESS_ERROR, 0, "Invalid key system.");
+    promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Invalid key system.");
     return;
   }
 
-  AddCdm(render_frame_id, cdm_id, promise_id, params.key_system,
-         params.security_origin, params.use_hw_secure_codecs);
+  if (!GetCdmFactory()) {
+    NOTREACHED() << "CDM not supported.";
+    promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "CDM not supported.");
+    return;
+  }
+
+  // The render process makes sure |allow_distinctive_identifier| and
+  // |allow_persistent_state| are true. See RenderCdmFactory::Create().
+  // TODO(xhwang): Pass |allow_distinctive_identifier| and
+  // |allow_persistent_state| from the render process.
+  media::CdmConfig cdm_config;
+  cdm_config.allow_distinctive_identifier = true;
+  cdm_config.allow_persistent_state = true;
+  cdm_config.use_hw_secure_codecs = params.use_hw_secure_codecs;
+
+  GetCdmFactory()->Create(
+      params.key_system, params.security_origin, cdm_config,
+      BROWSER_CDM_MANAGER_CB(OnSessionMessage),
+      BROWSER_CDM_MANAGER_CB(OnSessionClosed),
+      BROWSER_CDM_MANAGER_CB(OnLegacySessionError),
+      BROWSER_CDM_MANAGER_CB(OnSessionKeysChange),
+      BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate),
+      BROWSER_CDM_MANAGER_CB(OnCdmCreated, params.security_origin,
+                             base::Passed(&promise)));
 }
 
 void BrowserCdmManager::OnSetServerCertificate(
@@ -522,34 +571,16 @@
   RemoveCdm(GetId(render_frame_id, cdm_id));
 }
 
-// Use a weak pointer here instead of |this| to avoid circular references.
-#define BROWSER_CDM_MANAGER_CB(func)                                   \
-  base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \
-             render_frame_id, cdm_id)
-
-void BrowserCdmManager::AddCdm(int render_frame_id,
-                               int cdm_id,
-                               uint32_t promise_id,
-                               const std::string& key_system,
-                               const GURL& security_origin,
-                               bool use_hw_secure_codecs) {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
-  DCHECK(!GetCdm(render_frame_id, cdm_id));
-
-  scoped_ptr<SimplePromise> promise(new SimplePromise(
-      weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
-
-  scoped_refptr<MediaKeys> cdm(media::CreateBrowserCdm(
-      key_system, use_hw_secure_codecs,
-      BROWSER_CDM_MANAGER_CB(OnSessionMessage),
-      BROWSER_CDM_MANAGER_CB(OnSessionClosed),
-      BROWSER_CDM_MANAGER_CB(OnLegacySessionError),
-      BROWSER_CDM_MANAGER_CB(OnSessionKeysChange),
-      BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate)));
-
+void BrowserCdmManager::OnCdmCreated(
+    int render_frame_id,
+    int cdm_id,
+    const GURL& security_origin,
+    scoped_ptr<media::SimpleCdmPromise> promise,
+    const scoped_refptr<media::MediaKeys>& cdm,
+    const std::string& error_message) {
   if (!cdm) {
-    DVLOG(1) << "failed to create CDM.";
-    promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "Failed to create CDM.");
+    DVLOG(1) << "Failed to create CDM: " << error_message;
+    promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, error_message);
     return;
   }
 
diff --git a/content/browser/media/cdm/browser_cdm_manager.h b/content/browser/media/cdm/browser_cdm_manager.h
index fd2168d..521de14a 100644
--- a/content/browser/media/cdm/browser_cdm_manager.h
+++ b/content/browser/media/cdm/browser_cdm_manager.h
@@ -26,6 +26,10 @@
 
 struct CdmHostMsg_CreateSessionAndGenerateRequest_Params;
 
+namespace media {
+class CdmFactory;
+}
+
 namespace content {
 
 // This class manages all CDM objects. It receives control operations from the
@@ -79,6 +83,10 @@
   ~BrowserCdmManager() override;
 
  private:
+  // Returns the CdmFactory that can be used to create CDMs. Returns null if
+  // CDM is not supported.
+  media::CdmFactory* GetCdmFactory();
+
   // CDM callbacks.
   void OnSessionMessage(int render_frame_id,
                         int cdm_id,
@@ -137,14 +145,13 @@
                        const std::string& session_id);
   void OnDestroyCdm(int render_frame_id, int cdm_id);
 
-  // Adds a new CDM identified by |cdm_id| for the given |key_system| and
-  // |security_origin|.
-  void AddCdm(int render_frame_id,
-              int cdm_id,
-              uint32_t promise_id,
-              const std::string& key_system,
-              const GURL& security_origin,
-              bool use_hw_secure_codecs);
+  // Callback for CDM creation.
+  void OnCdmCreated(int render_frame_id,
+                    int cdm_id,
+                    const GURL& security_origin,
+                    scoped_ptr<media::SimpleCdmPromise> promise,
+                    const scoped_refptr<media::MediaKeys>& cdm,
+                    const std::string& error_message);
 
   // Removes all CDMs associated with |render_frame_id|.
   void RemoveAllCdmForFrame(int render_frame_id);
@@ -193,6 +200,8 @@
   // dispatched to the browser UI thread.
   scoped_refptr<base::TaskRunner> task_runner_;
 
+  scoped_ptr<media::CdmFactory> cdm_factory_;
+
   // The key in the following maps is a combination of |render_frame_id| and
   // |cdm_id|.
 
diff --git a/content/browser/power_save_blocker_impl.cc b/content/browser/power_save_blocker_impl.cc
index 416ddb33..97e37f5 100644
--- a/content/browser/power_save_blocker_impl.cc
+++ b/content/browser/power_save_blocker_impl.cc
@@ -13,8 +13,13 @@
     PowerSaveBlockerType type,
     Reason reason,
     const std::string& description) {
+  //TODO(mfomitchev): Support PowerSaveBlocker on Aura - crbug.com/546718.
+#if defined(OS_ANDROID) && defined(USE_AURA)
+  return nullptr;
+#else
   return scoped_ptr<PowerSaveBlocker>(
       new PowerSaveBlockerImpl(type, reason, description));
+#endif
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index a47b7534..e12d55b0 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -991,7 +991,8 @@
   AddFilter(new MemoryMessageFilter());
   AddFilter(new PushMessagingMessageFilter(
       GetID(), storage_partition_impl_->GetServiceWorkerContext()));
-#if defined(OS_ANDROID)
+  // TODO(mfomitchev): Screen Orientation APIs on Aura - crbug.com/546719.
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   AddFilter(new ScreenOrientationMessageFilterAndroid());
 #endif
   AddFilter(new GeofencingDispatcherHost(
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 882e9856..c4349df6 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1392,6 +1392,8 @@
 #if defined(OS_WIN)
   manager = new BrowserAccessibilityManagerWin(
       BrowserAccessibilityManagerWin::GetEmptyDocument(), delegate);
+#elif defined (OS_ANDROID)
+  // TODO(mfomitchev): Accessibility on Android Aura: crbug.com/543262
 #else
   manager = BrowserAccessibilityManager::Create(
       BrowserAccessibilityManager::GetEmptyDocument(), delegate);
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 51cd0d4..b295f43 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -380,6 +380,39 @@
   }
 }
 
+// This observer is used to wait for its owner FrameTreeNode to become focused.
+class FrameFocusedObserver : public FrameTreeNode::Observer {
+ public:
+  FrameFocusedObserver(FrameTreeNode* owner)
+      : owner_(owner), message_loop_runner_(new MessageLoopRunner) {
+    owner->AddObserver(this);
+  }
+
+  ~FrameFocusedObserver() override { owner_->RemoveObserver(this); }
+
+  void Wait() { message_loop_runner_->Run(); }
+
+ private:
+  // FrameTreeNode::Observer
+  void OnFrameTreeNodeFocused(FrameTreeNode* node) override {
+    if (node == owner_)
+      message_loop_runner_->Quit();
+  }
+
+  FrameTreeNode* owner_;
+  scoped_refptr<MessageLoopRunner> message_loop_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(FrameFocusedObserver);
+};
+
+// Helper function to focus a frame by sending it a mouse click and then
+// waiting for it to become focused.
+void FocusFrame(FrameTreeNode* frame) {
+  FrameFocusedObserver focus_observer(frame);
+  SimulateMouseClick(frame->current_frame_host()->GetRenderWidgetHost(), 1, 1);
+  focus_observer.Wait();
+}
+
 // A WebContentsDelegate that catches messages sent to the console.
 class ConsoleObserverDelegate : public WebContentsDelegate {
  public:
@@ -3763,37 +3796,12 @@
   // The main frame should be focused to start with.
   EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame());
 
-  DOMMessageQueue msg_queue;
-
-  // Register focus and blur events that will send messages when main frame's
-  // document body gets or loses focus.
-  std::string setup_focus_events =
-      "document.body.onfocus = function() { "
-      "  domAutomationController.setAutomationId(0);"
-      "  domAutomationController.send('got-focus');"
-      "};"
-      "document.body.onblur = function() { "
-      "  domAutomationController.setAutomationId(0);"
-      "  domAutomationController.send('lost-focus');"
-      "};";
-  EXPECT_TRUE(ExecuteScript(shell()->web_contents(), setup_focus_events));
-
-  // Click on the b.com frame.
-  SimulateMouseClick(child->current_frame_host()->GetRenderWidgetHost(), 1, 1);
-
-  // Wait for the main frame to lose focus and fire a blur event on its
-  // document body.
-  std::string status;
-  while (msg_queue.WaitForMessage(&status)) {
-    if (status == "\"lost-focus\"")
-      break;
-  }
-
-  // The b.com frame should now be focused.
+  // Focus the b.com frame.
+  FocusFrame(child);
   EXPECT_EQ(child, root->frame_tree()->GetFocusedFrame());
 
-  // Helper function to check a property of document.activeElement in the main
-  // frame.
+  // Helper function to check a property of document.activeElement in the
+  // specified frame.
   auto verify_active_element_property = [](RenderFrameHost* rfh,
                                            const std::string& property,
                                            const std::string& expected_value) {
@@ -3805,33 +3813,21 @@
     EXPECT_EQ(expected_value, base::ToLowerASCII(result));
   };
 
-  // Verify that document.activeElement points to the <iframe> element for the
-  // b.com frame.
+  // Verify that document.activeElement on main frame points to the <iframe>
+  // element for the b.com frame.
   RenderFrameHost* root_rfh = root->current_frame_host();
   verify_active_element_property(root_rfh, "tagName", "iframe");
   verify_active_element_property(root_rfh, "src", child->current_url().spec());
 
-  // Click on the main frame and wait for it to be focused again.
-  SimulateMouseClick(
-      shell()->web_contents()->GetRenderViewHost()->GetWidget(), 1, 1);
-  while (msg_queue.WaitForMessage(&status)) {
-    if (status == "\"got-focus\"")
-      break;
-  }
+  // Focus the a.com main frame again.
+  FocusFrame(root);
   EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame());
 
   // Main frame document's <body> should now be the active element.
   verify_active_element_property(root_rfh, "tagName", "body");
 
-  // Click on the grandchild frame to focus it.
-  SimulateMouseClick(
-      grandchild->current_frame_host()->GetRenderWidgetHost(), 1, 1);
-
-  // Wait for main frame to lose focus.
-  while (msg_queue.WaitForMessage(&status)) {
-    if (status == "\"lost-focus\"")
-      break;
-  }
+  // Now shift focus from main frame to c.com frame.
+  FocusFrame(grandchild);
 
   // Check document.activeElement in main frame.  It should still point to
   // <iframe> for the b.com frame, since Blink computes the focused iframe
@@ -3969,12 +3965,9 @@
   NavigateFrameToURL(root->child_at(0), frame_url);
   EXPECT_TRUE(WaitForRenderFrameReady(root->child_at(0)->current_frame_host()));
 
-  // Click on the subframe to focus it.
-  SimulateMouseClick(
-      root->child_at(0)->current_frame_host()->GetRenderWidgetHost(), 1, 1);
-
-  // Focus the input field in the subframe.  The return value "input-focus"
-  // will be sent once the input field's focus event fires.
+  // Focus the subframe and then its input field.  The return value
+  // "input-focus" will be sent once the input field's focus event fires.
+  FocusFrame(root->child_at(0));
   std::string result;
   EXPECT_TRUE(ExecuteScriptAndExtractString(
       root->child_at(0)->current_frame_host(), "focusInputField()", &result));
diff --git a/content/browser/wake_lock/wake_lock_service_context.cc b/content/browser/wake_lock/wake_lock_service_context.cc
index 582ea58d..8143dc4 100644
--- a/content/browser/wake_lock/wake_lock_service_context.cc
+++ b/content/browser/wake_lock/wake_lock_service_context.cc
@@ -62,7 +62,8 @@
       PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
       PowerSaveBlocker::kReasonOther, "Wake Lock API");
 
-#if defined(OS_ANDROID)
+  //TODO(mfomitchev): Support PowerSaveBlocker on Aura - crbug.com/546718.
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   // On Android, additionaly associate the blocker with this WebContents.
   DCHECK(web_contents());
 
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 41a6084..27a226f 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -121,10 +121,13 @@
 
 #if defined(OS_ANDROID)
 #include "content/browser/android/content_video_view.h"
-#include "content/browser/android/date_time_chooser_android.h"
 #include "content/browser/media/android/media_session.h"
+#endif  // OS_ANDROID
+
+#if defined(OS_ANDROID) && !defined(USE_AURA)
+#include "content/browser/android/date_time_chooser_android.h"
 #include "content/browser/web_contents/web_contents_android.h"
-#endif
+#endif  // OS_ANDROID && !USE_AURA
 
 #if defined(OS_MACOSX)
 #include "base/mac/foundation_util.h"
@@ -652,7 +655,7 @@
                         OnHideValidationMessage)
     IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage,
                         OnMoveValidationMessage)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
     IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply,
                         OnFindMatchRectsReply)
     IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog,
@@ -1387,7 +1390,7 @@
 
   manifest_manager_host_.reset(new ManifestManagerHost(this));
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   date_time_chooser_.reset(new DateTimeChooserAndroid());
 #endif
 
@@ -3195,7 +3198,7 @@
   }
 }
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
 void WebContentsImpl::OnFindMatchRectsReply(
     int version,
     const std::vector<gfx::RectF>& rects,
@@ -3358,8 +3361,9 @@
   video_power_save_blocker_ = PowerSaveBlocker::Create(
       PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
       PowerSaveBlocker::kReasonVideoPlayback, "Playing video");
-#if defined(OS_ANDROID)
-  static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
+  //TODO(mfomitchev): Support PowerSaveBlocker on Aura - crbug.com/546718.
+#if defined(OS_ANDROID) && !defined(USE_AURA)
+static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
       ->InitDisplaySleepBlocker(this);
 #endif
 }
@@ -4468,7 +4472,7 @@
   return true;
 }
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
 
 base::android::ScopedJavaLocalRef<jobject>
 WebContentsImpl::GetJavaWebContents() {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 0bd9c5c..5755f31 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -81,7 +81,7 @@
 struct ResourceRedirectDetails;
 struct ResourceRequestDetails;
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
 class WebContentsAndroid;
 #endif
 
@@ -127,7 +127,7 @@
   // Returns the SavePackage which manages the page saving job. May be NULL.
   SavePackage* save_package() const { return save_package_.get(); }
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   // In Android WebView, the RenderView needs created even there is no
   // navigation entry, this allows Android WebViews to use
   // javascript: URLs that load into the DOMWindow before the first page
@@ -378,9 +378,10 @@
   void ResumeMediaSession() override;
   void SuspendMediaSession() override;
   void StopMediaSession() override;
-
+#if !defined(USE_AURA)
   base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() override;
   virtual WebContentsAndroid* GetWebContentsAndroid();
+#endif  // !USE_AURA
 #elif defined(OS_MACOSX)
   void SetAllowOtherViews(bool allow) override;
   bool GetAllowOtherViews() override;
@@ -852,7 +853,7 @@
                    const gfx::Rect& selection_rect,
                    int active_match_ordinal,
                    bool final_update);
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   void OnFindMatchRectsReply(int version,
                              const std::vector<gfx::RectF>& rects,
                              const gfx::RectF& active_rect);
@@ -1209,7 +1210,7 @@
   // this overrides |preferred_size_|.
   gfx::Size preferred_size_for_capture_;
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   // Date time chooser opened by this tab.
   // Only used in Android since all other platforms use a multi field UI.
   scoped_ptr<DateTimeChooserAndroid> date_time_chooser_;
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn
index 6878985..02dec55 100644
--- a/content/child/BUILD.gn
+++ b/content/child/BUILD.gn
@@ -56,6 +56,10 @@
 
   if (enable_plugins) {
     deps += [ "//ppapi/proxy" ]
+
+    if (is_win || is_android || !use_aura) {
+      sources -= [ "npapi/webplugin_delegate_impl_aura.cc" ]
+    }
   } else {
     sources -= [
       "browser_font_resource_trusted.cc",
@@ -99,9 +103,7 @@
     } else if (is_android) {
       sources -= [ "npapi/webplugin_delegate_impl_android.cc" ]
     }
-    if (use_aura) {
-      sources -= [ "npapi/webplugin_delegate_impl_aura.cc" ]
-    }
+    sources -= [ "npapi/webplugin_delegate_impl_aura.cc" ]
   }
 
   configs += [
@@ -131,8 +133,4 @@
     # This file is already excluded on non-Mac.
     sources -= [ "npapi/webplugin_delegate_impl_mac.mm" ]
   }
-
-  if (is_win || !use_aura) {
-    sources -= [ "npapi/webplugin_delegate_impl_aura.cc" ]
-  }
 }
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index f7fe02a..f4fb6a4 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -242,8 +242,7 @@
   IPC_STRUCT_TRAITS_MEMBER(use_custom_colors)
   IPC_STRUCT_TRAITS_MEMBER(enable_referrers)
   IPC_STRUCT_TRAITS_MEMBER(enable_do_not_track)
-  IPC_STRUCT_TRAITS_MEMBER(enable_webrtc_multiple_routes)
-  IPC_STRUCT_TRAITS_MEMBER(enable_webrtc_nonproxied_udp)
+  IPC_STRUCT_TRAITS_MEMBER(webrtc_ip_handling_policy)
   IPC_STRUCT_TRAITS_MEMBER(default_zoom_level)
   IPC_STRUCT_TRAITS_MEMBER(user_agent_override)
   IPC_STRUCT_TRAITS_MEMBER(accept_languages)
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 3ee12f48..7cc9fa2 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -313,7 +313,6 @@
       'browser/accessibility/accessibility_mode_helper.h',
       'browser/accessibility/accessibility_tree_formatter.cc',
       'browser/accessibility/accessibility_tree_formatter.h',
-      'browser/accessibility/accessibility_tree_formatter_android.cc',
       'browser/accessibility/accessibility_tree_formatter_mac.mm',
       'browser/accessibility/accessibility_tree_formatter_utils_win.cc',
       'browser/accessibility/accessibility_tree_formatter_utils_win.h',
@@ -324,16 +323,12 @@
       'browser/accessibility/ax_tree_id_registry.h',
       'browser/accessibility/browser_accessibility.cc',
       'browser/accessibility/browser_accessibility.h',
-      'browser/accessibility/browser_accessibility_android.cc',
-      'browser/accessibility/browser_accessibility_android.h',
       'browser/accessibility/browser_accessibility_cocoa.h',
       'browser/accessibility/browser_accessibility_cocoa.mm',
       'browser/accessibility/browser_accessibility_mac.h',
       'browser/accessibility/browser_accessibility_mac.mm',
       'browser/accessibility/browser_accessibility_manager.cc',
       'browser/accessibility/browser_accessibility_manager.h',
-      'browser/accessibility/browser_accessibility_manager_android.cc',
-      'browser/accessibility/browser_accessibility_manager_android.h',
       'browser/accessibility/browser_accessibility_manager_mac.h',
       'browser/accessibility/browser_accessibility_manager_mac.mm',
       'browser/accessibility/browser_accessibility_manager_win.cc',
@@ -355,46 +350,18 @@
       'browser/android/browser_surface_texture_manager.h',
       'browser/android/child_process_launcher_android.cc',
       'browser/android/child_process_launcher_android.h',
-      'browser/android/composited_touch_handle_drawable.cc',
-      'browser/android/composited_touch_handle_drawable.h',
       'browser/android/content_protocol_handler_impl.cc',
       'browser/android/content_protocol_handler_impl.h',
-      'browser/android/content_readback_handler.cc',
-      'browser/android/content_readback_handler.h',
       'browser/android/content_startup_flags.cc',
       'browser/android/content_startup_flags.h',
       'browser/android/content_video_view.cc',
       'browser/android/content_video_view.h',
-      'browser/android/content_view_core_impl.cc',
-      'browser/android/content_view_core_impl.h',
-      'browser/android/content_view_render_view.cc',
-      'browser/android/content_view_render_view.h',
-      'browser/android/content_view_statics.cc',
-      'browser/android/content_view_statics.h',
-      'browser/android/date_time_chooser_android.cc',
-      'browser/android/date_time_chooser_android.h',
-      'browser/android/deferred_download_observer.cc',
-      'browser/android/deferred_download_observer.h',
       'browser/android/devtools_auth.cc',
-      'browser/android/download_controller_android_impl.cc',
-      'browser/android/download_controller_android_impl.h',
       'browser/android/in_process_surface_texture_manager.cc',
       'browser/android/in_process_surface_texture_manager.h',
-      'browser/android/interstitial_page_delegate_android.cc',
-      'browser/android/interstitial_page_delegate_android.h',
-      'browser/android/load_url_params.cc',
-      'browser/android/load_url_params.h',
       'public/browser/android/download_controller_android.h',
-      'browser/android/overscroll_controller_android.cc',
-      'browser/android/overscroll_controller_android.h',
-      'browser/android/popup_touch_handle_drawable.cc',
-      'browser/android/popup_touch_handle_drawable.h',
-      'browser/android/tracing_controller_android.cc',
-      'browser/android/tracing_controller_android.h',
       'browser/android/url_request_content_job.cc',
       'browser/android/url_request_content_job.h',
-      'browser/android/web_contents_observer_proxy.cc',
-      'browser/android/web_contents_observer_proxy.h',
       'browser/appcache/appcache.cc',
       'browser/appcache/appcache.h',
       'browser/appcache/appcache_backend_impl.cc',
@@ -1098,7 +1065,6 @@
       'browser/permissions/permission_service_impl.h',
       'browser/power_monitor_message_broadcaster.cc',
       'browser/power_monitor_message_broadcaster.h',
-      'browser/power_save_blocker_android.cc',
       'browser/power_save_blocker_android.h',
       'browser/power_save_blocker_chromeos.cc',
       'browser/power_save_blocker_impl.cc',
@@ -1129,8 +1095,6 @@
       'browser/renderer_host/clipboard_message_filter.cc',
       'browser/renderer_host/clipboard_message_filter.h',
       'browser/renderer_host/clipboard_message_filter_mac.mm',
-      'browser/renderer_host/compositor_impl_android.cc',
-      'browser/renderer_host/compositor_impl_android.h',
       'browser/renderer_host/compositor_resize_lock_aura.cc',
       'browser/renderer_host/compositor_resize_lock_aura.h',
       'browser/renderer_host/database_message_filter.cc',
@@ -1150,8 +1114,6 @@
       'browser/renderer_host/gamepad_browser_message_filter.h',
       'browser/renderer_host/gpu_message_filter.cc',
       'browser/renderer_host/gpu_message_filter.h',
-      'browser/renderer_host/ime_adapter_android.cc',
-      'browser/renderer_host/ime_adapter_android.h',
       'browser/renderer_host/input/gesture_event_queue.cc',
       'browser/renderer_host/input/gesture_event_queue.h',
       'browser/renderer_host/input/input_ack_handler.h',
@@ -1174,8 +1136,6 @@
       'browser/renderer_host/input/synthetic_gesture_controller.cc',
       'browser/renderer_host/input/synthetic_gesture_controller.h',
       'browser/renderer_host/input/synthetic_gesture_target.h',
-      'browser/renderer_host/input/synthetic_gesture_target_android.cc',
-      'browser/renderer_host/input/synthetic_gesture_target_android.h',
       'browser/renderer_host/input/synthetic_gesture_target_aura.cc',
       'browser/renderer_host/input/synthetic_gesture_target_aura.h',
       'browser/renderer_host/input/synthetic_gesture_target_base.cc',
@@ -1267,7 +1227,6 @@
       'browser/renderer_host/media/video_capture_manager.h',
       'browser/renderer_host/memory_benchmark_message_filter.cc',
       'browser/renderer_host/memory_benchmark_message_filter.h',
-      'browser/renderer_host/native_web_keyboard_event_android.cc',
       'browser/renderer_host/native_web_keyboard_event_aura.cc',
       'browser/renderer_host/native_web_keyboard_event_mac.mm',
       'browser/renderer_host/overscroll_configuration.cc',
@@ -1296,8 +1255,6 @@
       'browser/renderer_host/render_widget_host_input_event_router.cc',
       'browser/renderer_host/render_widget_host_input_event_router.h',
       'browser/renderer_host/render_widget_host_owner_delegate.h',
-      'browser/renderer_host/render_widget_host_view_android.cc',
-      'browser/renderer_host/render_widget_host_view_android.h',
       'browser/renderer_host/render_widget_host_view_aura.cc',
       'browser/renderer_host/render_widget_host_view_aura.h',
       'browser/renderer_host/render_widget_host_view_base.cc',
@@ -1335,12 +1292,8 @@
       'browser/resource_context_impl.h',
       'browser/safe_util_win.cc',
       'browser/safe_util_win.h',
-      'browser/screen_orientation/screen_orientation_delegate_android.cc',
-      'browser/screen_orientation/screen_orientation_delegate_android.h',
       'browser/screen_orientation/screen_orientation_dispatcher_host_impl.cc',
       'browser/screen_orientation/screen_orientation_dispatcher_host_impl.h',
-      'browser/screen_orientation/screen_orientation_message_filter_android.cc',
-      'browser/screen_orientation/screen_orientation_message_filter_android.h',
       'browser/service_worker/embedded_worker_instance.cc',
       'browser/service_worker/embedded_worker_instance.h',
       'browser/service_worker/embedded_worker_registry.cc',
@@ -1545,13 +1498,9 @@
       'browser/web_contents/aura/overscroll_window_delegate.h',
       'browser/web_contents/aura/shadow_layer_delegate.cc',
       'browser/web_contents/aura/shadow_layer_delegate.h',
-      'browser/web_contents/web_contents_android.cc',
-      'browser/web_contents/web_contents_android.h',
       'browser/web_contents/web_contents_impl.cc',
       'browser/web_contents/web_contents_impl.h',
       'browser/web_contents/web_contents_view.h',
-      'browser/web_contents/web_contents_view_android.cc',
-      'browser/web_contents/web_contents_view_android.h',
       'browser/web_contents/web_contents_view_aura.cc',
       'browser/web_contents/web_contents_view_aura.h',
       'browser/web_contents/web_contents_view_guest.cc',
@@ -1627,6 +1576,59 @@
       'browser/android/synchronous_compositor_host.cc',
       'browser/android/synchronous_compositor_host.h',
     ],
+    'android_non_aura_browser_sources': [
+        'browser/accessibility/accessibility_tree_formatter_android.cc',
+        'browser/accessibility/browser_accessibility_android.cc',
+        'browser/accessibility/browser_accessibility_android.h',
+        'browser/accessibility/browser_accessibility_manager_android.cc',
+        'browser/accessibility/browser_accessibility_manager_android.h',
+        'browser/android/composited_touch_handle_drawable.cc',
+        'browser/android/composited_touch_handle_drawable.h',
+        'browser/android/content_readback_handler.cc',
+        'browser/android/content_readback_handler.h',
+        'browser/android/content_view_core_impl.cc',
+        'browser/android/content_view_core_impl.h',
+        'browser/android/content_view_render_view.cc',
+        'browser/android/content_view_render_view.h',
+        'browser/android/content_view_statics.cc',
+        'browser/android/content_view_statics.h',
+        'browser/android/date_time_chooser_android.cc',
+        'browser/android/date_time_chooser_android.h',
+        'browser/android/deferred_download_observer.cc',
+        'browser/android/deferred_download_observer.h',
+        'browser/android/download_controller_android_impl.cc',
+        'browser/android/download_controller_android_impl.h',
+        'browser/android/interstitial_page_delegate_android.cc',
+        'browser/android/interstitial_page_delegate_android.h',
+        'browser/android/load_url_params.cc',
+        'browser/android/load_url_params.h',
+        'browser/android/overscroll_controller_android.cc',
+        'browser/android/overscroll_controller_android.h',
+        'browser/android/popup_touch_handle_drawable.cc',
+        'browser/android/popup_touch_handle_drawable.h',
+        'browser/android/tracing_controller_android.cc',
+        'browser/android/tracing_controller_android.h',
+        'browser/android/web_contents_observer_proxy.cc',
+        'browser/android/web_contents_observer_proxy.h',
+        'browser/power_save_blocker_android.cc',
+        'browser/renderer_host/compositor_impl_android.cc',
+        'browser/renderer_host/compositor_impl_android.h',
+        'browser/renderer_host/ime_adapter_android.cc',
+        'browser/renderer_host/ime_adapter_android.h',
+        'browser/renderer_host/input/synthetic_gesture_target_android.cc',
+        'browser/renderer_host/input/synthetic_gesture_target_android.h',
+        'browser/renderer_host/native_web_keyboard_event_android.cc',
+        'browser/renderer_host/render_widget_host_view_android.cc',
+        'browser/renderer_host/render_widget_host_view_android.h',
+        'browser/screen_orientation/screen_orientation_delegate_android.cc',
+        'browser/screen_orientation/screen_orientation_delegate_android.h',
+        'browser/screen_orientation/screen_orientation_message_filter_android.cc',
+        'browser/screen_orientation/screen_orientation_message_filter_android.h',
+        'browser/web_contents/web_contents_android.cc',
+        'browser/web_contents/web_contents_android.h',
+        'browser/web_contents/web_contents_view_android.cc',
+        'browser/web_contents/web_contents_view_android.h',
+    ],
     'auralinux_browser_sources': [
       'browser/accessibility/accessibility_tree_formatter_auralinux.cc',
       'browser/accessibility/browser_accessibility_auralinux.cc',
@@ -2034,10 +2036,7 @@
         ['exclude', '^browser/tracing/trace_uploader\\.(cc|h)$'],
         ['exclude', '^browser/tracing/tracing_ui\\.(cc|h)$'],
       ],
-      'sources': [
-        '<@(android_browser_sources)',
-        '<@(android_in_process_browser_sources)',
-      ],
+      'sources': [ '<@(android_browser_sources)', ],
       'sources!': [
         'browser/browser_ipc_logging.cc',
         'browser/geolocation/device_data_provider.cc',
@@ -2045,9 +2044,17 @@
         'browser/geolocation/wifi_data_provider_common.cc',
         'browser/power_usage_monitor_impl.cc',
         'browser/power_usage_monitor_impl.h',
-        'browser/renderer_host/begin_frame_observer_proxy.cc',
         'browser/renderer_host/native_web_keyboard_event.cc',
-      ]
+      ],
+      'conditions': [
+        ['use_aura == 0', {
+          'sources': [
+            '<@(android_in_process_browser_sources)',
+            '<@(android_non_aura_browser_sources)',
+          ],
+          'sources!': [ 'browser/renderer_host/begin_frame_observer_proxy.cc', ],
+        }],
+      ],
     }],
     ['OS=="mac"', {
       'sources/': [
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 6330237b..f9236da8 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -816,6 +816,10 @@
       'dependencies': [
         '../third_party/libjingle/libjingle.gyp:libjingle',
       ],
+      'sources': [
+        'public/common/webrtc_ip_handling_policy.cc',
+        'public/common/webrtc_ip_handling_policy.h',
+      ],
     }],
     ['use_v4lplugin==1 and chromeos==1', {
       'defines': [
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java
index b6d94a2..c9661f0d 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java
@@ -12,6 +12,7 @@
 import android.text.TextUtils;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.content.browser.test.util.Criteria;
@@ -427,8 +428,12 @@
         assertNotSame(mContentViewCore.getSelectedText(), "SampleTextToCopy");
     }
 
-    @SmallTest
-    @Feature({"TextInput"})
+    /**
+     * Disabled due to being flaky. crbug.com/552387
+     * @SmallTest
+     * @Feature({"TextInput"})
+     */
+    @DisabledTest
     public void testSelectActionBarInputPaste() throws Exception {
         copyStringToClipboard("SampleTextToCopy");
         DOMUtils.longPressNode(this, mContentViewCore, "input_text");
diff --git a/content/public/browser/DEPS b/content/public/browser/DEPS
index ce66e26a..d9b1c76 100644
--- a/content/public/browser/DEPS
+++ b/content/public/browser/DEPS
@@ -1,5 +1,6 @@
 specific_include_rules = {
   ".*\.cc": [
     "+content/browser",
+    "+media/base",  # For CdmFactory.
   ],
 }
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 8f92ff3..3be2a8f 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -7,6 +7,7 @@
 #include "base/files/file_path.h"
 #include "content/public/browser/client_certificate_delegate.h"
 #include "content/public/common/sandbox_type.h"
+#include "media/base/cdm_factory.h"
 #include "storage/browser/quota/quota_manager.h"
 #include "ui/gfx/image/image_skia.h"
 #include "url/gurl.h"
@@ -113,6 +114,10 @@
   return false;
 }
 
+scoped_ptr<media::CdmFactory> ContentBrowserClient::CreateCdmFactory() {
+  return nullptr;
+}
+
 bool ContentBrowserClient::ShouldSwapProcessesForRedirect(
     ResourceContext* resource_context, const GURL& current_url,
     const GURL& new_url) {
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index fe3538f..a4bad09 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -54,6 +54,10 @@
 class ImageSkia;
 }
 
+namespace media {
+class CdmFactory;
+}
+
 namespace mojo {
 class ApplicationDelegate;
 }
@@ -709,6 +713,10 @@
   virtual ScopedVector<NavigationThrottle> CreateThrottlesForNavigation(
       NavigationHandle* navigation_handle);
 
+  // Creates and returns a factory used for creating CDM instances for playing
+  // protected content.
+  virtual scoped_ptr<media::CdmFactory> CreateCdmFactory();
+
   // Populates |mappings| with all files that need to be mapped before launching
   // a child process.
 #if defined(OS_ANDROID)
diff --git a/content/public/browser/native_web_keyboard_event.h b/content/public/browser/native_web_keyboard_event.h
index 4bbb119..cf19bcbe 100644
--- a/content/public/browser/native_web_keyboard_event.h
+++ b/content/public/browser/native_web_keyboard_event.h
@@ -26,7 +26,7 @@
   NativeWebKeyboardEvent();
 
   explicit NativeWebKeyboardEvent(gfx::NativeEvent native_event);
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && !defined(USE_AURA)
   NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
                          int modifiers,
                          double time_secs,
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index cda64874..a0ea79f 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -684,10 +684,11 @@
   virtual void SuspendMediaSession() = 0;
   // Requests to stop the current media session.
   virtual void StopMediaSession() = 0;
-
+#if !defined(USE_AURA)
   CONTENT_EXPORT static WebContents* FromJavaWebContents(
       jobject jweb_contents_android);
   virtual base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() = 0;
+#endif  // !USE_AURA
 #elif defined(OS_MACOSX)
   // Allowing other views disables optimizations which assume that only a single
   // WebContents is present.
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn
index 5328de0..193520d 100644
--- a/content/public/common/BUILD.gn
+++ b/content/public/common/BUILD.gn
@@ -92,6 +92,13 @@
       "pepper_plugin_info.h",
     ]
   }
+
+  if (enable_webrtc) {
+    sources += [
+      "webrtc_ip_handling_policy.cc",
+      "webrtc_ip_handling_policy.h",
+    ]
+  }
 }
 
 mojom("mojo_bindings") {
diff --git a/content/public/common/pepper_plugin_info.cc b/content/public/common/pepper_plugin_info.cc
index 018bf18..25b00c3 100644
--- a/content/public/common/pepper_plugin_info.cc
+++ b/content/public/common/pepper_plugin_info.cc
@@ -17,6 +17,7 @@
 PepperPluginInfo::PepperPluginInfo()
     : is_internal(false),
       is_out_of_process(false),
+      is_debug(false),
       permissions(0) {
 }
 
diff --git a/content/public/common/pepper_plugin_info.h b/content/public/common/pepper_plugin_info.h
index 0c202f9..893e28a 100644
--- a/content/public/common/pepper_plugin_info.h
+++ b/content/public/common/pepper_plugin_info.h
@@ -54,6 +54,10 @@
   std::string version;
   std::vector<WebPluginMimeType> mime_types;
 
+  // True when the plugin has been detected as the debug version.
+  // Defaults to false.
+  bool is_debug;
+
   // When is_internal is set, this contains the function pointers to the
   // entry points for the internal plugins.
   EntryPoints internal_entry_points;
diff --git a/content/public/common/renderer_preferences.cc b/content/public/common/renderer_preferences.cc
index ae88b6b..02cd4394 100644
--- a/content/public/common/renderer_preferences.cc
+++ b/content/public/common/renderer_preferences.cc
@@ -30,8 +30,6 @@
       use_custom_colors(true),
       enable_referrers(true),
       enable_do_not_track(false),
-      enable_webrtc_multiple_routes(true),
-      enable_webrtc_nonproxied_udp(true),
       default_zoom_level(0),
       report_frame_name_changes(false),
       tap_multiple_targets_strategy(TAP_MULTIPLE_TARGETS_STRATEGY_POPUP),
diff --git a/content/public/common/renderer_preferences.h b/content/public/common/renderer_preferences.h
index 155950b8..a03b9c13 100644
--- a/content/public/common/renderer_preferences.h
+++ b/content/public/common/renderer_preferences.h
@@ -93,14 +93,10 @@
   // Set to true to indicate that the preference to set DNT to 1 is enabled.
   bool enable_do_not_track;
 
-  // Set to false to indicate that WebRTC should use the OS default routing.
-  bool enable_webrtc_multiple_routes;
-
-  // Set to false to indicate that WebRTC should not use non-proxied UDP to
-  // connect to peers and TURN servers, which effectively disables all WebRTC's
-  // UDP traffic for now, until UDP-based proxy support is available in
-  // Chromium. Default is true.
-  bool enable_webrtc_nonproxied_udp;
+  // This is the IP handling policy override for WebRTC. The value must be one
+  // of the strings defined in privacy.json. The allowed values are specified
+  // in webrtc_ip_handling_policy.h.
+  std::string webrtc_ip_handling_policy;
 
   // Default page zoom level.
   double default_zoom_level;
diff --git a/content/public/common/webrtc_ip_handling_policy.cc b/content/public/common/webrtc_ip_handling_policy.cc
new file mode 100644
index 0000000..beed096
--- /dev/null
+++ b/content/public/common/webrtc_ip_handling_policy.cc
@@ -0,0 +1,17 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/common/webrtc_ip_handling_policy.h"
+
+namespace content {
+
+// The set of strings here need to match what's specified in privacy.json.
+const char kWebRTCIPHandlingDefault[] = "default";
+const char kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces[] =
+    "default_public_and_private_interfaces";
+const char kWebRTCIPHandlingDefaultPublicInterfaceOnly[] =
+    "default_public_interface_only";
+const char kWebRTCIPHandlingDisableNonProxiedUdp[] = "disable_non_proxied_udp";
+
+}  // namespace content
diff --git a/content/public/common/webrtc_ip_handling_policy.h b/content/public/common/webrtc_ip_handling_policy.h
new file mode 100644
index 0000000..77904233
--- /dev/null
+++ b/content/public/common/webrtc_ip_handling_policy.h
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_RENDERER_WEBRTC_IP_HANDLING_POLICY_H_
+#define CONTENT_PUBLIC_RENDERER_WEBRTC_IP_HANDLING_POLICY_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// This is the default behavior of Chrome. Currently, WebRTC has the right to
+// enumerate all interfaces and bind them to discover public interfaces.
+CONTENT_EXPORT extern const char kWebRTCIPHandlingDefault[];
+
+// WebRTC should only use the default route used by http. This also exposes the
+// associated default private address. Default route is the route chosen by the
+// OS on a multi-homed endpoint.
+CONTENT_EXPORT extern const char
+    kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces[];
+
+// WebRTC should only use the default route used by http. This doesn't expose
+// any local addresses.
+CONTENT_EXPORT extern const char kWebRTCIPHandlingDefaultPublicInterfaceOnly[];
+
+// WebRTC should only use TCP to contact peers or servers unless the proxy
+// server supports UDP. This doesn't expose any local addresses either.
+CONTENT_EXPORT extern const char kWebRTCIPHandlingDisableNonProxiedUdp[];
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_RENDERER_WEBRTC_IP_HANDLING_POLICY_H_
diff --git a/content/renderer/media/media_recorder_handler.cc b/content/renderer/media/media_recorder_handler.cc
index e5c8ccfb..bc8ee78 100644
--- a/content/renderer/media/media_recorder_handler.cc
+++ b/content/renderer/media/media_recorder_handler.cc
@@ -80,14 +80,15 @@
   timeslice_ = TimeDelta::FromMilliseconds(timeslice);
   slice_origin_timestamp_ = TimeTicks::Now();
 
-  webm_muxer_.reset(
-      new media::WebmMuxer(use_vp9_ ? media::kCodecVP9 : media::kCodecVP8,
-                           base::Bind(&MediaRecorderHandler::WriteData,
-                                      weak_factory_.GetWeakPtr())));
-
   blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
   media_stream_.videoTracks(video_tracks);
 
+  webm_muxer_.reset(new media::WebmMuxer(
+      use_vp9_ ? media::kCodecVP9 : media::kCodecVP8, video_tracks.size() > 0,
+      false /* no audio for now - http://crbug.com/528519 */,
+      base::Bind(&MediaRecorderHandler::WriteData,
+                 weak_factory_.GetWeakPtr())));
+
   if (video_tracks.isEmpty()) {
     // TODO(mcasas): Add audio_tracks and update the code in this function
     // correspondingly, see http://crbug.com/528519. As of now, only video
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 1f281c7..68e5268f 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -17,6 +17,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/renderer_preferences.h"
+#include "content/public/common/webrtc_ip_handling_policy.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/renderer/media/media_stream.h"
 #include "content/renderer/media/media_stream_audio_processor.h"
@@ -64,6 +65,28 @@
 
 namespace content {
 
+namespace {
+
+enum WebRTCIPHandlingPolicy {
+  DEFAULT,
+  DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES,
+  DEFAULT_PUBLIC_INTERFACE_ONLY,
+  DISABLE_NON_PROXIED_UDP,
+};
+
+WebRTCIPHandlingPolicy GetWebRTCIPHandlingPolicy(
+    const std::string& preference) {
+  if (preference == kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces)
+    return DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES;
+  if (preference == kWebRTCIPHandlingDefaultPublicInterfaceOnly)
+    return DEFAULT_PUBLIC_INTERFACE_ONLY;
+  if (preference == kWebRTCIPHandlingDisableNonProxiedUdp)
+    return DISABLE_NON_PROXIED_UDP;
+  return DEFAULT;
+}
+
+}  // namespace
+
 // Map of corresponding media constraints and platform effects.
 struct {
   const char* constraint;
@@ -456,14 +479,32 @@
         // |request_multiple_routes|. Whether local IP addresses could be
         // collected depends on if mic/camera permission is granted for this
         // origin.
-        port_config.enable_multiple_routes =
-            renderer_view_impl->renderer_preferences()
-                .enable_webrtc_multiple_routes;
-        port_config.enable_nonproxied_udp =
-            renderer_view_impl->renderer_preferences()
-                .enable_webrtc_nonproxied_udp;
-        VLOG(3) << "WebRTC routing preferences: multiple_routes: "
-                << port_config.enable_multiple_routes
+        std::string mode = renderer_view_impl->renderer_preferences()
+                               .webrtc_ip_handling_policy;
+        switch (GetWebRTCIPHandlingPolicy(mode)) {
+          // TODO(guoweis): specify the flag of disabling local candidate
+          // collection when webrtc is updated.
+          case DEFAULT_PUBLIC_INTERFACE_ONLY:
+          case DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES:
+            port_config.enable_multiple_routes = false;
+            port_config.enable_nonproxied_udp = true;
+            break;
+          case DISABLE_NON_PROXIED_UDP:
+            port_config.enable_multiple_routes = false;
+            port_config.enable_nonproxied_udp = false;
+            break;
+          case DEFAULT:
+            port_config.enable_multiple_routes = true;
+            port_config.enable_nonproxied_udp = true;
+            break;
+          default:
+            NOTREACHED();
+            break;
+        }
+
+        VLOG(3) << "WebRTC routing preferences: "
+                << "policy: " << mode
+                << ", multiple_routes: " << port_config.enable_multiple_routes
                 << ", nonproxied_udp: " << port_config.enable_nonproxied_udp;
       }
     }
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc
index 7d8ac38..0e8b8b73 100644
--- a/content/shell/browser/shell.cc
+++ b/content/shell/browser/shell.cc
@@ -22,6 +22,7 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/renderer_preferences.h"
+#include "content/public/common/webrtc_ip_handling_policy.h"
 #include "content/shell/browser/blink_test_controller.h"
 #include "content/shell/browser/layout_test/layout_test_bluetooth_chooser_factory.h"
 #include "content/shell/browser/layout_test/layout_test_devtools_frontend.h"
@@ -120,8 +121,8 @@
 #if defined(ENABLE_WEBRTC)
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableWebRtcMultipleRoutes)) {
-    web_contents->GetMutableRendererPrefs()->enable_webrtc_multiple_routes =
-        false;
+    web_contents->GetMutableRendererPrefs()->webrtc_ip_handling_policy =
+        kWebRTCIPHandlingDefaultPublicInterfaceOnly;
   }
 #endif
 
diff --git a/courgette/assembly_program.cc b/courgette/assembly_program.cc
index 965f457..f050390 100644
--- a/courgette/assembly_program.cc
+++ b/courgette/assembly_program.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/logging.h"
+#include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 
 #include "courgette/courgette.h"
@@ -19,39 +20,6 @@
 
 namespace courgette {
 
-// Opcodes of simple assembly language
-enum OP {
-  ORIGIN,         // ORIGIN <rva> - set current address for assembly.
-  MAKEPERELOCS,   // Generates a base relocation table.
-  MAKEELFRELOCS,  // Generates a base relocation table.
-  DEFBYTE,        // DEFBYTE <value> - emit a byte literal.
-  REL32,          // REL32 <label> - emit a rel32 encoded reference to 'label'.
-  ABS32,          // ABS32 <label> - emit an abs32 encoded reference to 'label'.
-  REL32ARM,       // REL32ARM <c_op> <label> - arm-specific rel32 reference
-  MAKEELFARMRELOCS,  // Generates a base relocation table.
-  DEFBYTES,       // Emits any number of byte literals
-  ABS64,          // ABS64 <label> - emit an abs64 encoded reference to 'label'.
-  LAST_OP
-};
-
-// Base class for instructions.  Because we have so many instructions we want to
-// keep them as small as possible.  For this reason we avoid virtual functions.
-//
-class Instruction {
- public:
-  OP op() const { return static_cast<OP>(op_); }
-
- protected:
-  explicit Instruction(OP op) : op_(op), info_(0) {}
-  Instruction(OP op, unsigned int info) : op_(op), info_(info) {}
-
-  uint32 op_   : 4;    // A few bits to store the OP code.
-  uint32 info_ : 28;   // Remaining bits in first word available to subclass.
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Instruction);
-};
-
 namespace {
 
 // Sets the current address for the emitting instructions.
@@ -142,64 +110,67 @@
 
 static void DeleteContainedLabels(const RVAToLabel& labels) {
   for (RVAToLabel::const_iterator p = labels.begin();  p != labels.end();  ++p)
-    delete p->second;
+    UncheckedDelete(p->second);
 }
 
 AssemblyProgram::~AssemblyProgram() {
   for (size_t i = 0;  i < instructions_.size();  ++i) {
     Instruction* instruction = instructions_[i];
-    if (instruction->op() != DEFBYTE)  // Will be in byte_instruction_cache_.
-      delete instruction;
+    if (instruction->op() != DEFBYTE)  // Owned by byte_instruction_cache_.
+      UncheckedDelete(instruction);
   }
   if (byte_instruction_cache_.get()) {
     for (size_t i = 0;  i < 256;  ++i)
-      delete byte_instruction_cache_[i];
+      UncheckedDelete(byte_instruction_cache_[i]);
   }
   DeleteContainedLabels(rel32_labels_);
   DeleteContainedLabels(abs32_labels_);
 }
 
 CheckBool AssemblyProgram::EmitPeRelocsInstruction() {
-  return Emit(new(std::nothrow) PeRelocsInstruction());
+  return Emit(ScopedInstruction(UncheckedNew<PeRelocsInstruction>()));
 }
 
 CheckBool AssemblyProgram::EmitElfRelocationInstruction() {
-  return Emit(new(std::nothrow) ElfRelocsInstruction());
+  return Emit(ScopedInstruction(UncheckedNew<ElfRelocsInstruction>()));
 }
 
 CheckBool AssemblyProgram::EmitElfARMRelocationInstruction() {
-  return Emit(new(std::nothrow) ElfARMRelocsInstruction());
+  return Emit(ScopedInstruction(UncheckedNew<ElfARMRelocsInstruction>()));
 }
 
 CheckBool AssemblyProgram::EmitOriginInstruction(RVA rva) {
-  return Emit(new(std::nothrow) OriginInstruction(rva));
+  return Emit(ScopedInstruction(UncheckedNew<OriginInstruction>(rva)));
 }
 
 CheckBool AssemblyProgram::EmitByteInstruction(uint8 byte) {
-  return Emit(GetByteInstruction(byte));
+  return EmitShared(GetByteInstruction(byte));
 }
 
 CheckBool AssemblyProgram::EmitBytesInstruction(const uint8* values,
                                                 size_t len) {
-  return Emit(new(std::nothrow) BytesInstruction(values, len));
+  return Emit(ScopedInstruction(UncheckedNew<BytesInstruction>(values, len)));
 }
 
 CheckBool AssemblyProgram::EmitRel32(Label* label) {
-  return Emit(new(std::nothrow) InstructionWithLabel(REL32, label));
+  return Emit(
+      ScopedInstruction(UncheckedNew<InstructionWithLabel>(REL32, label)));
 }
 
 CheckBool AssemblyProgram::EmitRel32ARM(uint16 op, Label* label,
                                         const uint8* arm_op, uint16 op_size) {
-  return Emit(new(std::nothrow) InstructionWithLabelARM(REL32ARM, op, label,
-                                                        arm_op, op_size));
+  return Emit(ScopedInstruction(UncheckedNew<InstructionWithLabelARM>(
+      REL32ARM, op, label, arm_op, op_size)));
 }
 
 CheckBool AssemblyProgram::EmitAbs32(Label* label) {
-  return Emit(new(std::nothrow) InstructionWithLabel(ABS32, label));
+  return Emit(
+      ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS32, label)));
 }
 
 CheckBool AssemblyProgram::EmitAbs64(Label* label) {
-  return Emit(new (std::nothrow) InstructionWithLabel(ABS64, label));
+  return Emit(
+      ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS64, label)));
 }
 
 Label* AssemblyProgram::FindOrMakeAbs32Label(RVA rva) {
@@ -249,19 +220,23 @@
   return NULL;
 }
 
-CheckBool AssemblyProgram::Emit(Instruction* instruction) {
-  if (!instruction)
+CheckBool AssemblyProgram::Emit(ScopedInstruction instruction) {
+  if (!instruction || !instructions_.push_back(instruction.get()))
     return false;
-  bool ok = instructions_.push_back(instruction);
-  if (!ok)
-    delete instruction;
-  return ok;
+  // Ownership successfully passed to instructions_.
+  ignore_result(instruction.release());
+  return true;
+}
+
+CheckBool AssemblyProgram::EmitShared(Instruction* instruction) {
+  DCHECK(!instruction || instruction->op() == DEFBYTE);
+  return instruction && instructions_.push_back(instruction);
 }
 
 Label* AssemblyProgram::FindLabel(RVA rva, RVAToLabel* labels) {
   Label*& slot = (*labels)[rva];
   if (slot == NULL) {
-    slot = new(std::nothrow) Label(rva);
+    slot = UncheckedNew<Label>(rva);
     if (slot == NULL)
       return NULL;
   }
@@ -401,9 +376,7 @@
 }
 
 EncodedProgram* AssemblyProgram::Encode() const {
-  scoped_ptr<EncodedProgram> encoded(new(std::nothrow) EncodedProgram());
-  if (!encoded.get())
-    return NULL;
+  scoped_ptr<EncodedProgram> encoded(new EncodedProgram());
 
   encoded->set_image_base(image_base_);
 
@@ -494,19 +467,22 @@
 }
 
 Instruction* AssemblyProgram::GetByteInstruction(uint8 byte) {
-  if (!byte_instruction_cache_.get()) {
-    byte_instruction_cache_.reset(new(std::nothrow) Instruction*[256]);
-    if (!byte_instruction_cache_.get())
-      return NULL;
+  if (!byte_instruction_cache_) {
+    Instruction** ram = nullptr;
+    if (!base::UncheckedMalloc(sizeof(Instruction*) * 256,
+                               reinterpret_cast<void**>(&ram))) {
+      return nullptr;
+    }
+    byte_instruction_cache_.reset(ram);
 
     for (int i = 0; i < 256; ++i) {
       byte_instruction_cache_[i] =
-          new(std::nothrow) ByteInstruction(static_cast<uint8>(i));
+          UncheckedNew<ByteInstruction>(static_cast<uint8>(i));
       if (!byte_instruction_cache_[i]) {
         for (int j = 0; j < i; ++j)
-          delete byte_instruction_cache_[j];
+          UncheckedDelete(byte_instruction_cache_[j]);
         byte_instruction_cache_.reset();
-        return NULL;
+        return nullptr;
       }
     }
   }
@@ -531,6 +507,10 @@
   RVAToLabel::iterator it = rel32_labels_.begin();
   while (it != rel32_labels_.end()) {
     if (it->second->count_ <= lower_limit) {
+      // Note: it appears to me (grt) that this leaks the Label instances. I
+      // *think* the right thing would be to add it->second to a collection for
+      // which all elements are freed via UncheckedDelete after the instruction
+      // fixup loop below.
       rel32_labels_.erase(it++);
     } else {
       ++it;
@@ -553,10 +533,10 @@
 
           if (op_size < 1)
             return false;
-          BytesInstruction* new_instruction =
-            new(std::nothrow) BytesInstruction(arm_op, op_size);
-          instructions_[i] = new_instruction;
-          delete instruction;
+          UncheckedDelete(instruction);
+          instructions_[i] = UncheckedNew<BytesInstruction>(arm_op, op_size);
+          if (!instructions_[i])
+            return false;
         }
         break;
       }
diff --git a/courgette/assembly_program.h b/courgette/assembly_program.h
index 096cc4d4..ba7ad59f18 100644
--- a/courgette/assembly_program.h
+++ b/courgette/assembly_program.h
@@ -18,9 +18,6 @@
 namespace courgette {
 
 class EncodedProgram;
-class Instruction;
-
-typedef NoThrowBuffer<Instruction*> InstructionVector;
 
 // A Label is a symbolic reference to an address.  Unlike a conventional
 // assembly language, we always know the address.  The address will later be
@@ -41,6 +38,40 @@
 
 typedef std::map<RVA, Label*> RVAToLabel;
 
+// Opcodes of simple assembly language
+enum OP {
+  ORIGIN,         // ORIGIN <rva> - set current address for assembly.
+  MAKEPERELOCS,   // Generates a base relocation table.
+  MAKEELFRELOCS,  // Generates a base relocation table.
+  DEFBYTE,        // DEFBYTE <value> - emit a byte literal.
+  REL32,          // REL32 <label> - emit a rel32 encoded reference to 'label'.
+  ABS32,          // ABS32 <label> - emit an abs32 encoded reference to 'label'.
+  REL32ARM,       // REL32ARM <c_op> <label> - arm-specific rel32 reference
+  MAKEELFARMRELOCS,  // Generates a base relocation table.
+  DEFBYTES,       // Emits any number of byte literals
+  ABS64,          // ABS64 <label> - emit an abs64 encoded reference to 'label'.
+  LAST_OP
+};
+
+// Base class for instructions.  Because we have so many instructions we want to
+// keep them as small as possible.  For this reason we avoid virtual functions.
+class Instruction {
+ public:
+  OP op() const { return static_cast<OP>(op_); }
+
+ protected:
+  explicit Instruction(OP op) : op_(op), info_(0) {}
+  Instruction(OP op, unsigned int info) : op_(op), info_(info) {}
+
+  uint32 op_   : 4;    // A few bits to store the OP code.
+  uint32 info_ : 28;   // Remaining bits in first word available to subclass.
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Instruction);
+};
+
+typedef NoThrowBuffer<Instruction*> InstructionVector;
+
 // An AssemblyProgram is the result of disassembling an executable file.
 //
 // * The disassembler creates labels in the AssemblyProgram and emits
@@ -137,9 +168,13 @@
   CheckBool TrimLabels();
 
  private:
+  using ScopedInstruction =
+      scoped_ptr<Instruction, UncheckedDeleter<Instruction>>;
+
   ExecutableType kind_;
 
-  CheckBool Emit(Instruction* instruction) WARN_UNUSED_RESULT;
+  CheckBool Emit(ScopedInstruction instruction) WARN_UNUSED_RESULT;
+  CheckBool EmitShared(Instruction* instruction) WARN_UNUSED_RESULT;
 
   static const int kLabelLowerLimit;
 
@@ -153,7 +188,7 @@
 
   // Sharing instructions that emit a single byte saves a lot of space.
   Instruction* GetByteInstruction(uint8 byte);
-  scoped_ptr<Instruction*[]> byte_instruction_cache_;
+  scoped_ptr<Instruction* [], base::FreeDeleter> byte_instruction_cache_;
 
   uint64 image_base_;  // Desired or mandated base address of image.
 
diff --git a/courgette/memory_allocator.h b/courgette/memory_allocator.h
index 15b709e9..7161592 100644
--- a/courgette/memory_allocator.h
+++ b/courgette/memory_allocator.h
@@ -5,12 +5,14 @@
 #ifndef COURGETTE_MEMORY_ALLOCATOR_H_
 #define COURGETTE_MEMORY_ALLOCATOR_H_
 
-#include <memory>
+#include <stdlib.h>
 
 #include "base/basictypes.h"
+#include "base/compiler_specific.h"
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/process/memory.h"
 
 #ifndef NDEBUG
 
@@ -55,6 +57,31 @@
 
 namespace courgette {
 
+// Allocates memory for an instance of type T, instantiates an object in that
+// memory with arguments |args| (of type ArgTypes), and returns the constructed
+// instance. Returns null if allocation fails.
+template <class T, class... ArgTypes>
+T* UncheckedNew(ArgTypes... args) {
+  void* ram = nullptr;
+  return base::UncheckedMalloc(sizeof(T), &ram) ? new (ram) T(args...)
+                                                : nullptr;
+}
+
+// Complement of UncheckedNew(): destructs |object| and releases its memory.
+template <class T>
+void UncheckedDelete(T* object) {
+  if (object) {
+    object->T::~T();
+    free(object);
+  }
+}
+
+// A deleter for scoped_ptr that will delete the object via UncheckedDelete().
+template <class T>
+struct UncheckedDeleter {
+  inline void operator()(T* ptr) const { UncheckedDelete(ptr); }
+};
+
 #if defined(OS_WIN)
 
 // Manages a read/write virtual mapping of a physical file.
@@ -170,11 +197,10 @@
     uint8* mem = reinterpret_cast<uint8*>(ptr);
     mem -= sizeof(T);
     if (mem[0] == HEAP_ALLOCATION) {
-      delete [] mem;
+      free(mem);
     } else {
       DCHECK_EQ(static_cast<uint8>(FILE_ALLOCATION), mem[0]);
-      TempMapping* mapping = TempMapping::GetMappingFromPtr(mem);
-      delete mapping;
+      UncheckedDelete(TempMapping::GetMappingFromPtr(mem));
     }
   }
 
@@ -192,17 +218,20 @@
     uint8* mem = NULL;
 
     // First see if we can do this allocation on the heap.
-    if (count < kMaxHeapAllocationSize)
-      mem = new(std::nothrow) uint8[bytes];
-    if (mem != NULL) {
+    if (count < kMaxHeapAllocationSize &&
+        base::UncheckedMalloc(bytes, reinterpret_cast<void**>(&mem))) {
       mem[0] = static_cast<uint8>(HEAP_ALLOCATION);
     } else {
-      // If either the heap allocation failed or the request exceeds the
-      // max heap allocation threshold, we back the allocation with a temp file.
-      TempMapping* mapping = new(std::nothrow) TempMapping();
-      if (mapping && mapping->Initialize(bytes)) {
-        mem = reinterpret_cast<uint8*>(mapping->memory());
-        mem[0] = static_cast<uint8>(FILE_ALLOCATION);
+      // Back the allocation with a temp file if either the request exceeds the
+      // max heap allocation threshold or the heap allocation failed.
+      TempMapping* mapping = UncheckedNew<TempMapping>();
+      if (mapping) {
+        if (mapping->Initialize(bytes)) {
+          mem = reinterpret_cast<uint8*>(mapping->memory());
+          mem[0] = static_cast<uint8>(FILE_ALLOCATION);
+        } else {
+          UncheckedDelete(mapping);
+        }
       }
     }
     return mem ? reinterpret_cast<pointer>(mem + sizeof(T)) : NULL;
@@ -260,15 +289,16 @@
   ~MemoryAllocator() {
   }
 
-  void deallocate(pointer ptr, size_type size) {
-    delete [] ptr;
-  }
+  void deallocate(pointer ptr, size_type size) { free(ptr); }
 
   pointer allocate(size_type count) {
     if (count > max_size())
       return NULL;
-    return reinterpret_cast<pointer>(
-        new(std::nothrow) uint8[count * sizeof(T)]);
+    pointer result = nullptr;
+    return base::UncheckedMalloc(count * sizeof(T),
+                                 reinterpret_cast<void**>(&result))
+               ? result
+               : nullptr;
   }
 
   pointer allocate(size_type count, const void* hint) {
diff --git a/courgette/third_party/paged_array.h b/courgette/third_party/paged_array.h
index b12b695..76cb879b 100644
--- a/courgette/third_party/paged_array.h
+++ b/courgette/third_party/paged_array.h
@@ -7,13 +7,12 @@
 // PagedArray is a work-around to allow large arrays to be allocated when there
 // is too much address space fragmentation for allocating the large arrays as
 // contigous arrays.
+
 #ifndef COURGETTE_BSDIFF_PAGED_ARRAY_H_
 #define COURGETTE_BSDIFF_PAGED_ARRAY_H_
 
-// For std::nothrow:
-#include <new>
-
 #include "base/basictypes.h"
+#include "base/process/memory.h"
 
 namespace courgette {
 
@@ -44,13 +43,15 @@
   bool Allocate(size_t size) {
     clear();
     size_t pages_needed = (size + kPageSize - 1) >> kLogPageSize;
-    pages_ = new(std::nothrow) T*[pages_needed];
-    if (pages_ == NULL)
+    if (!base::UncheckedMalloc(sizeof(T*) * pages_needed,
+                               reinterpret_cast<void**>(&pages_))) {
       return false;
+    }
 
     for (page_count_ = 0; page_count_ < pages_needed; ++page_count_) {
-      T* block = new(std::nothrow) T[kPageSize];
-      if (block == NULL) {
+      T* block = nullptr;
+      if (!base::UncheckedMalloc(sizeof(T) * kPageSize,
+                                 reinterpret_cast<void**>(&block))) {
         clear();
         return false;
       }
@@ -64,9 +65,9 @@
     if (pages_ != NULL) {
       while (page_count_ != 0) {
         --page_count_;
-        delete[] pages_[page_count_];
+        free(pages_[page_count_]);
       }
-      delete[] pages_;
+      free(pages_);
       pages_ = NULL;
     }
   }
diff --git a/extensions/browser/api/webcam_private/v4l2_webcam.cc b/extensions/browser/api/webcam_private/v4l2_webcam.cc
index e99cc0ca..fc5ba22 100644
--- a/extensions/browser/api/webcam_private/v4l2_webcam.cc
+++ b/extensions/browser/api/webcam_private/v4l2_webcam.cc
@@ -4,6 +4,7 @@
 
 #include "extensions/browser/api/webcam_private/v4l2_webcam.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <linux/uvcvideo.h>
 #include <linux/videodev2.h>
diff --git a/extensions/common/feature_switch.cc b/extensions/common/feature_switch.cc
index a8e1d82..81d4347 100644
--- a/extensions/common/feature_switch.cc
+++ b/extensions/common/feature_switch.cc
@@ -48,7 +48,7 @@
                                    FeatureSwitch::DEFAULT_DISABLED),
         trace_app_source(switches::kTraceAppSource,
                          FeatureSwitch::DEFAULT_ENABLED),
-        // The switch enable-media-router is defined in
+        // The switch media-router is defined in
         // chrome/common/chrome_switches.cc, but we can't depend on chrome here.
         media_router("media-router",
                      kEnableMediaRouterExperiment,
diff --git a/extensions/renderer/module_system.cc b/extensions/renderer/module_system.cc
index b828ca0..3e3da6a 100644
--- a/extensions/renderer/module_system.cc
+++ b/extensions/renderer/module_system.cc
@@ -161,10 +161,8 @@
 
   v8::Local<v8::Object> global(context->v8_context()->Global());
   v8::Isolate* isolate = context->isolate();
-  global->SetHiddenValue(ToV8StringUnsafe(isolate, kModulesField),
-                         v8::Object::New(isolate));
-  global->SetHiddenValue(ToV8StringUnsafe(isolate, kModuleSystem),
-                         v8::External::New(isolate, this));
+  SetPrivate(global, kModulesField, v8::Object::New(isolate));
+  SetPrivate(global, kModuleSystem, v8::External::New(isolate, this));
 
   gin::ModuleRegistry::From(context->v8_context())->AddObserver(this);
   if (context_->GetRenderFrame()) {
@@ -182,8 +180,8 @@
   {
     v8::HandleScope scope(GetIsolate());
     v8::Local<v8::Object> global = context()->v8_context()->Global();
-    global->DeleteHiddenValue(ToV8StringUnsafe(GetIsolate(), kModulesField));
-    global->DeleteHiddenValue(ToV8StringUnsafe(GetIsolate(), kModuleSystem));
+    DeletePrivate(global, kModulesField);
+    DeletePrivate(global, kModuleSystem);
   }
 
   // Invalidate all active and clobbered NativeHandlers we own.
@@ -244,9 +242,9 @@
   // The module system might have been deleted. This can happen if a different
   // context keeps a reference to us, but our frame is destroyed (e.g.
   // background page keeps reference to chrome object in a closed popup).
-  v8::Local<v8::Value> modules_value = global->GetHiddenValue(
-      ToV8StringUnsafe(GetIsolate(), kModulesField));
-  if (modules_value.IsEmpty() || modules_value->IsUndefined()) {
+  v8::Local<v8::Value> modules_value;
+  if (!GetPrivate(global, kModulesField, &modules_value) ||
+      modules_value->IsUndefined()) {
     Warn(GetIsolate(), "Extension view no longer exists");
     return v8::Undefined(GetIsolate());
   }
@@ -383,17 +381,18 @@
     RequireFunction require_function) {
   CHECK(!info.Data().IsEmpty());
   CHECK(info.Data()->IsObject());
-  v8::HandleScope handle_scope(info.GetIsolate());
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::HandleScope handle_scope(isolate);
   v8::Local<v8::Object> parameters = v8::Local<v8::Object>::Cast(info.Data());
   // This context should be the same as context()->v8_context().
   v8::Local<v8::Context> context = parameters->CreationContext();
   v8::Local<v8::Object> global(context->Global());
-  v8::Local<v8::Value> module_system_value = global->GetHiddenValue(
-      ToV8StringUnsafe(info.GetIsolate(), kModuleSystem));
-  if (module_system_value.IsEmpty() || !module_system_value->IsExternal()) {
+  v8::Local<v8::Value> module_system_value;
+  if (!GetPrivate(context, global, kModuleSystem, &module_system_value) ||
+      !module_system_value->IsExternal()) {
     // ModuleSystem has been deleted.
     // TODO(kalman): See comment in header file.
-    Warn(info.GetIsolate(),
+    Warn(isolate,
          "Module system has been deleted, does extension view exist?");
     return;
   }
@@ -403,7 +402,7 @@
 
   v8::Local<v8::Value> v8_module_name;
   if (!GetProperty(context, parameters, kModuleName, &v8_module_name)) {
-    Warn(info.GetIsolate(), "Cannot find module.");
+    Warn(isolate, "Cannot find module.");
     return;
   }
   std::string name = *v8::String::Utf8Value(v8_module_name);
@@ -413,7 +412,7 @@
   v8::Context::Scope context_scope(context);
   NativesEnabledScope natives_enabled_scope(module_system);
 
-  v8::TryCatch try_catch(info.GetIsolate());
+  v8::TryCatch try_catch(isolate);
   v8::Local<v8::Value> module_value;
   if (!(module_system->*require_function)(name).ToLocal(&module_value)) {
     module_system->HandleException(try_catch);
@@ -611,17 +610,15 @@
     return;
   }
   v8::Local<v8::Object> obj = args[0].As<v8::Object>();
-  v8::Local<v8::String> privates_key =
-      ToV8StringUnsafe(GetIsolate(), "privates");
-  v8::Local<v8::Value> privates = obj->GetHiddenValue(privates_key);
-  if (privates.IsEmpty()) {
+  v8::Local<v8::Value> privates;
+  if (!GetPrivate(obj, "privates", &privates) || !privates->IsObject()) {
     privates = v8::Object::New(args.GetIsolate());
     if (privates.IsEmpty()) {
       GetIsolate()->ThrowException(
           ToV8StringUnsafe(GetIsolate(), "Failed to create privates"));
       return;
     }
-    obj->SetHiddenValue(privates_key, privates);
+    SetPrivate(obj, "privates", privates);
   }
   args.GetReturnValue().Set(privates);
 }
diff --git a/extensions/renderer/object_backed_native_handler.cc b/extensions/renderer/object_backed_native_handler.cc
index 45d2dd3d..421b273 100644
--- a/extensions/renderer/object_backed_native_handler.cc
+++ b/extensions/renderer/object_backed_native_handler.cc
@@ -37,17 +37,17 @@
 // static
 void ObjectBackedNativeHandler::Router(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::HandleScope handle_scope(args.GetIsolate());
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope handle_scope(isolate);
   v8::Local<v8::Object> data = args.Data().As<v8::Object>();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
 
-  v8::Local<v8::Value> handler_function_value =
-      data->GetHiddenValue(
-          v8::String::NewFromUtf8(args.GetIsolate(), kHandlerFunction));
+  v8::Local<v8::Value> handler_function_value;
   // See comment in header file for why we do this.
-  if (handler_function_value.IsEmpty() ||
+  if (!GetPrivate(context, data, kHandlerFunction, &handler_function_value) ||
       handler_function_value->IsUndefined()) {
-    ScriptContext* script_context = ScriptContextSet::GetContextByV8Context(
-        args.GetIsolate()->GetCurrentContext());
+    ScriptContext* script_context =
+        ScriptContextSet::GetContextByV8Context(context);
     console::Error(script_context ? script_context->GetRenderFrame() : nullptr,
                    "Extension view no longer exists");
     return;
@@ -67,9 +67,8 @@
   v8::Context::Scope context_scope(context_->v8_context());
 
   v8::Local<v8::Object> data = v8::Object::New(isolate);
-  data->SetHiddenValue(
-      v8::String::NewFromUtf8(isolate, kHandlerFunction),
-      v8::External::New(isolate, new HandlerFunction(handler_function)));
+  SetPrivate(data, kHandlerFunction,
+             v8::External::New(isolate, new HandlerFunction(handler_function)));
   v8::Local<v8::FunctionTemplate> function_template =
       v8::FunctionTemplate::New(isolate, Router, data);
   v8::Local<v8::ObjectTemplate>::New(isolate, object_template_)
@@ -88,13 +87,11 @@
 
   for (size_t i = 0; i < router_data_.Size(); i++) {
     v8::Local<v8::Object> data = router_data_.Get(i);
-    v8::Local<v8::Value> handler_function_value =
-        data->GetHiddenValue(
-            v8::String::NewFromUtf8(isolate, kHandlerFunction));
-    CHECK(!handler_function_value.IsEmpty());
+    v8::Local<v8::Value> handler_function_value;
+    CHECK(GetPrivate(data, kHandlerFunction, &handler_function_value));
     delete static_cast<HandlerFunction*>(
         handler_function_value.As<v8::External>()->Value());
-    data->DeleteHiddenValue(v8::String::NewFromUtf8(isolate, kHandlerFunction));
+    DeletePrivate(data, kHandlerFunction);
   }
 
   router_data_.Clear();
@@ -103,4 +100,56 @@
   NativeHandler::Invalidate();
 }
 
+void ObjectBackedNativeHandler::SetPrivate(v8::Local<v8::Object> obj,
+                                           const char* key,
+                                           v8::Local<v8::Value> value) {
+  SetPrivate(context_->v8_context(), obj, key, value);
+}
+
+// static
+void ObjectBackedNativeHandler::SetPrivate(v8::Local<v8::Context> context,
+                                           v8::Local<v8::Object> obj,
+                                           const char* key,
+                                           v8::Local<v8::Value> value) {
+  obj->SetPrivate(context, v8::Private::ForApi(context->GetIsolate(),
+                                               v8::String::NewFromUtf8(
+                                                   context->GetIsolate(), key)),
+                  value)
+      .FromJust();
+}
+
+bool ObjectBackedNativeHandler::GetPrivate(v8::Local<v8::Object> obj,
+                                           const char* key,
+                                           v8::Local<v8::Value>* result) {
+  return GetPrivate(context_->v8_context(), obj, key, result);
+}
+
+// static
+bool ObjectBackedNativeHandler::GetPrivate(v8::Local<v8::Context> context,
+                                           v8::Local<v8::Object> obj,
+                                           const char* key,
+                                           v8::Local<v8::Value>* result) {
+  return obj->GetPrivate(context,
+                         v8::Private::ForApi(context->GetIsolate(),
+                                             v8::String::NewFromUtf8(
+                                                 context->GetIsolate(), key)))
+      .ToLocal(result);
+}
+
+void ObjectBackedNativeHandler::DeletePrivate(v8::Local<v8::Object> obj,
+                                              const char* key) {
+  DeletePrivate(context_->v8_context(), obj, key);
+}
+
+// static
+void ObjectBackedNativeHandler::DeletePrivate(v8::Local<v8::Context> context,
+                                              v8::Local<v8::Object> obj,
+                                              const char* key) {
+  obj->DeletePrivate(context,
+                     v8::Private::ForApi(
+                         context->GetIsolate(),
+                         v8::String::NewFromUtf8(context->GetIsolate(), key)))
+      .FromJust();
+}
+
 }  // namespace extensions
diff --git a/extensions/renderer/object_backed_native_handler.h b/extensions/renderer/object_backed_native_handler.h
index e4e13a5..a60a33a 100644
--- a/extensions/renderer/object_backed_native_handler.h
+++ b/extensions/renderer/object_backed_native_handler.h
@@ -49,6 +49,27 @@
 
   void Invalidate() override;
 
+  // The following methods are convenience wrappers for methods on v8::Object
+  // with the corresponding names.
+  void SetPrivate(v8::Local<v8::Object> obj,
+                  const char* key,
+                  v8::Local<v8::Value> value);
+  static void SetPrivate(v8::Local<v8::Context> context,
+                         v8::Local<v8::Object> obj,
+                         const char* key,
+                         v8::Local<v8::Value> value);
+  bool GetPrivate(v8::Local<v8::Object> obj,
+                  const char* key,
+                  v8::Local<v8::Value>* result);
+  static bool GetPrivate(v8::Local<v8::Context> context,
+                         v8::Local<v8::Object> obj,
+                         const char* key,
+                         v8::Local<v8::Value>* result);
+  void DeletePrivate(v8::Local<v8::Object> obj, const char* key);
+  static void DeletePrivate(v8::Local<v8::Context> context,
+                            v8::Local<v8::Object> obj,
+                            const char* key);
+
  private:
   // Callback for RouteFunction which routes the V8 call to the correct
   // base::Bound callback.
diff --git a/extensions/renderer/safe_builtins.cc b/extensions/renderer/safe_builtins.cc
index bf44e96..3bfa01a 100644
--- a/extensions/renderer/safe_builtins.cc
+++ b/extensions/renderer/safe_builtins.cc
@@ -125,23 +125,27 @@
     "\n"
     "}());\n";
 
-v8::Local<v8::String> MakeKey(const char* name, v8::Isolate* isolate) {
-  return ToV8StringUnsafe(isolate,
-                          base::StringPrintf("%s::%s", kClassName, name));
+v8::Local<v8::Private> MakeKey(const char* name, v8::Isolate* isolate) {
+  return v8::Private::ForApi(
+      isolate, ToV8StringUnsafe(
+                   isolate, base::StringPrintf("%s::%s", kClassName, name)));
 }
 
 void SaveImpl(const char* name,
               v8::Local<v8::Value> value,
               v8::Local<v8::Context> context) {
   CHECK(!value.IsEmpty() && value->IsObject()) << name;
-  context->Global()->SetHiddenValue(MakeKey(name, context->GetIsolate()),
-                                    value);
+  context->Global()
+      ->SetPrivate(context, MakeKey(name, context->GetIsolate()), value)
+      .FromJust();
 }
 
 v8::Local<v8::Object> Load(const char* name, v8::Local<v8::Context> context) {
   v8::Local<v8::Value> value =
-      context->Global()->GetHiddenValue(MakeKey(name, context->GetIsolate()));
-  CHECK(!value.IsEmpty() && value->IsObject()) << name;
+      context->Global()
+          ->GetPrivate(context, MakeKey(name, context->GetIsolate()))
+          .ToLocalChecked();
+  CHECK(value->IsObject()) << name;
   return v8::Local<v8::Object>::Cast(value);
 }
 
diff --git a/extensions/renderer/wake_event_page.cc b/extensions/renderer/wake_event_page.cc
index 7a64d1a..ae98acc 100644
--- a/extensions/renderer/wake_event_page.cc
+++ b/extensions/renderer/wake_event_page.cc
@@ -115,12 +115,13 @@
 
   // Cache the imported function as a hidden property on the global object of
   // |v8_context|. Creating it isn't free.
-  v8::Local<v8::String> kWakeEventPageKey =
-      ToV8StringUnsafe(isolate, "WakeEventPage");
-  v8::Local<v8::Value> wake_event_page =
-      v8_context->Global()->GetHiddenValue(kWakeEventPageKey);
-
-  if (wake_event_page.IsEmpty()) {
+  v8::Local<v8::Private> kWakeEventPageKey =
+      v8::Private::ForApi(isolate, ToV8StringUnsafe(isolate, "WakeEventPage"));
+  v8::Local<v8::Value> wake_event_page;
+  if (!v8_context->Global()
+           ->GetPrivate(v8_context, kWakeEventPageKey)
+           .ToLocal(&wake_event_page) ||
+      wake_event_page->IsUndefined()) {
     // Implement this using a NativeHandler, which requires a function name
     // (arbitrary in this case). Handles own lifetime.
     const char* kFunctionName = "WakeEventPage";
@@ -132,7 +133,9 @@
     // Extract and cache the wake-event-page function from the native handler.
     wake_event_page = GetPropertyUnsafe(
         v8_context, native_handler->NewInstance(), kFunctionName);
-    v8_context->Global()->SetHiddenValue(kWakeEventPageKey, wake_event_page);
+    v8_context->Global()
+        ->SetPrivate(v8_context, kWakeEventPageKey, wake_event_page)
+        .FromJust();
   }
 
   CHECK(wake_event_page->IsFunction());
diff --git a/gin/modules/timer.cc b/gin/modules/timer.cc
index 8aac8a64..26b5c75e 100644
--- a/gin/modules/timer.cc
+++ b/gin/modules/timer.cc
@@ -12,8 +12,8 @@
 
 namespace {
 
-v8::Local<v8::String> GetHiddenPropertyName(v8::Isolate* isolate) {
-  return gin::StringToSymbol(isolate, "::gin::Timer");
+v8::Local<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) {
+  return v8::Private::ForApi(isolate, gin::StringToV8(isolate, "::gin::Timer"));
 }
 
 }  // namespace
@@ -45,8 +45,10 @@
       runner_(PerContextData::From(
           isolate->GetCurrentContext())->runner()->GetWeakPtr()),
       weak_factory_(this) {
-  GetWrapper(runner_->GetContextHolder()->isolate())->SetHiddenValue(
-      GetHiddenPropertyName(isolate), function);
+  GetWrapper(runner_->GetContextHolder()->isolate())
+      ->SetPrivate(isolate->GetCurrentContext(), GetHiddenPropertyName(isolate),
+                   function)
+      .FromJust();
   timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
                base::Bind(&Timer::OnTimerFired, weak_factory_.GetWeakPtr()));
 }
@@ -65,7 +67,10 @@
   Runner::Scope scope(runner_.get());
   v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
   v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
-      GetWrapper(isolate)->GetHiddenValue(GetHiddenPropertyName(isolate)));
+      GetWrapper(isolate)
+          ->GetPrivate(runner_->GetContextHolder()->context(),
+                       GetHiddenPropertyName(isolate))
+          .ToLocalChecked());
   runner_->Call(function, v8::Undefined(isolate), 0, NULL);
 }
 
diff --git a/google_apis/google_api_keys.py b/google_apis/google_api_keys.py
index ef40ff5f..0f98c79 100755
--- a/google_apis/google_api_keys.py
+++ b/google_apis/google_api_keys.py
@@ -70,6 +70,11 @@
   return _GetToken('GOOGLE_API_KEY')
 
 
+def GetAPIKeyPhysicalWebTest():
+  """Returns the API key to test Physical Web service."""
+  return _GetToken('GOOGLE_API_KEY_PHYSICAL_WEB_TEST')
+
+
 def GetAPIKeyRemoting():
   """Returns the simple API key."""
   return _GetToken('GOOGLE_API_KEY_REMOTING')
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index 01674866..cb649fed 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -40,6 +40,7 @@
       builders { name: "chromeos_x86-generic_chromium_compile_only_ng" }
       builders { name: "chromium_presubmit" }
       builders { name: "linux_android_rel_ng" }
+      builders { name: "linux_blink_oilpan_rel" }
       builders { name: "linux_chromium_asan_rel_ng" }
       builders { name: "linux_chromium_chromeos_compile_dbg_ng" }
       builders { name: "linux_chromium_chromeos_ozone_rel_ng" }
@@ -50,10 +51,6 @@
       builders { name: "linux_chromium_gn_chromeos_rel" }
       builders { name: "linux_chromium_rel_ng" }
       builders {
-        name: "linux_blink_oilpan_rel"
-        experiment_percentage: 50
-      }
-      builders {
         name: "linux_chromium_chromeos_asan_rel_ng"
         experiment_percentage: 10
       }
diff --git a/ios/build/bots/chromium.fyi/ClangToTiOS.json b/ios/build/bots/chromium.fyi/ClangToTiOS.json
index b5a9e2a..5af1ebed 100644
--- a/ios/build/bots/chromium.fyi/ClangToTiOS.json
+++ b/ios/build/bots/chromium.fyi/ClangToTiOS.json
@@ -5,7 +5,7 @@
   "comments": [
     "Clang tip-of-tree builder for iOS."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "clang_use_chrome_plugins": "0",
@@ -17,7 +17,7 @@
   },
   "compiler": "ninja",
   "configuration": "Release",
-  "sdk": "iphoneos8.3",
+  "sdk": "iphoneos9.0",
   "tests": [
   ]
 }
diff --git a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
index cb02ed1..d28fa43 100644
--- a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
+++ b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
@@ -25,6 +25,7 @@
 #include "ios/chrome/browser/history/web_history_service_factory.h"
 #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
 #include "ios/chrome/browser/search_engines/template_url_service_factory.h"
+#include "ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.h"
 #include "ios/chrome/browser/signin/about_signin_internals_factory.h"
 #include "ios/chrome/browser/signin/account_consistency_service_factory.h"
 #include "ios/chrome/browser/signin/account_fetcher_service_factory.h"
@@ -78,6 +79,7 @@
   ios::TopSitesFactory::GetInstance();
   ios::WebDataServiceFactory::GetInstance();
   ios::WebHistoryServiceFactory::GetInstance();
+  IOSChromeGCMProfileServiceFactory::GetInstance();
   IOSChromeLargeIconCacheFactory::GetInstance();
   IOSChromeLargeIconServiceFactory::GetInstance();
   IOSChromeFaviconLoaderFactory::GetInstance();
diff --git a/ios/chrome/browser/services/OWNERS b/ios/chrome/browser/services/OWNERS
new file mode 100644
index 0000000..e42d91c7
--- /dev/null
+++ b/ios/chrome/browser/services/OWNERS
@@ -0,0 +1 @@
+zea@chromium.org
diff --git a/ios/chrome/browser/services/gcm/OWNERS b/ios/chrome/browser/services/gcm/OWNERS
new file mode 100644
index 0000000..0f8cc7a
--- /dev/null
+++ b/ios/chrome/browser/services/gcm/OWNERS
@@ -0,0 +1,4 @@
+dimich@chromium.org
+fgorski@chromium.org
+jianli@chromium.org
+zea@chromium.org
diff --git a/ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.cc b/ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.cc
new file mode 100644
index 0000000..13a660c
--- /dev/null
+++ b/ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.cc
@@ -0,0 +1,67 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "components/gcm_driver/gcm_client_factory.h"
+#include "components/gcm_driver/gcm_profile_service.h"
+#include "components/keyed_service/ios/browser_state_dependency_manager.h"
+#include "components/signin/core/browser/profile_identity_provider.h"
+#include "components/signin/core/browser/signin_manager.h"
+#include "ios/chrome/browser/signin/oauth2_token_service_factory.h"
+#include "ios/chrome/browser/signin/signin_manager_factory.h"
+#include "ios/chrome/common/channel_info.h"
+#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/web/public/web_thread.h"
+
+// static
+gcm::GCMProfileService* IOSChromeGCMProfileServiceFactory::GetForBrowserState(
+    ios::ChromeBrowserState* browser_state) {
+  return static_cast<gcm::GCMProfileService*>(
+      GetInstance()->GetServiceForBrowserState(browser_state, true));
+}
+
+// static
+IOSChromeGCMProfileServiceFactory*
+IOSChromeGCMProfileServiceFactory::GetInstance() {
+  return base::Singleton<IOSChromeGCMProfileServiceFactory>::get();
+}
+
+IOSChromeGCMProfileServiceFactory::IOSChromeGCMProfileServiceFactory()
+    : BrowserStateKeyedServiceFactory(
+          "GCMProfileService",
+          BrowserStateDependencyManager::GetInstance()) {
+  DependsOn(ios::SigninManagerFactory::GetInstance());
+  DependsOn(OAuth2TokenServiceFactory::GetInstance());
+}
+
+IOSChromeGCMProfileServiceFactory::~IOSChromeGCMProfileServiceFactory() {}
+
+scoped_ptr<KeyedService>
+IOSChromeGCMProfileServiceFactory::BuildServiceInstanceFor(
+    web::BrowserState* context) const {
+  DCHECK(!context->IsOffTheRecord());
+
+  base::SequencedWorkerPool* worker_pool = web::WebThread::GetBlockingPool();
+  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner(
+      worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
+          worker_pool->GetSequenceToken(),
+          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
+  ios::ChromeBrowserState* browser_state =
+      ios::ChromeBrowserState::FromBrowserState(context);
+  return make_scoped_ptr(new gcm::GCMProfileService(
+      browser_state->GetPrefs(), browser_state->GetStatePath(),
+      browser_state->GetRequestContext(), ::GetChannel(),
+      make_scoped_ptr(new ProfileIdentityProvider(
+          ios::SigninManagerFactory::GetForBrowserState(browser_state),
+          OAuth2TokenServiceFactory::GetForBrowserState(browser_state),
+          base::Closure())),
+      make_scoped_ptr(new gcm::GCMClientFactory),
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::UI),
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::IO),
+      blocking_task_runner));
+}
diff --git a/ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.h b/ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.h
new file mode 100644
index 0000000..93794fcc
--- /dev/null
+++ b/ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.h
@@ -0,0 +1,48 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_SERVICES_GCM_IOS_CHROME_GCM_PROFILE_SERVICE_FACTORY_H_
+#define IOS_CHROME_BROWSER_SERVICES_GCM_IOS_CHROME_GCM_PROFILE_SERVICE_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+namespace gcm {
+class GCMProfileService;
+}
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+// Singleton that owns all GCMProfileService and associates them with
+// ios::ChromeBrowserState.
+class IOSChromeGCMProfileServiceFactory
+    : public BrowserStateKeyedServiceFactory {
+ public:
+  static gcm::GCMProfileService* GetForBrowserState(
+      ios::ChromeBrowserState* browser_state);
+
+  static IOSChromeGCMProfileServiceFactory* GetInstance();
+
+ private:
+  friend struct base::DefaultSingletonTraits<IOSChromeGCMProfileServiceFactory>;
+
+  IOSChromeGCMProfileServiceFactory();
+  ~IOSChromeGCMProfileServiceFactory() override;
+
+  // BrowserStateKeyedServiceFactory:
+  scoped_ptr<KeyedService> BuildServiceInstanceFor(
+      web::BrowserState* context) const override;
+
+  DISALLOW_COPY_AND_ASSIGN(IOSChromeGCMProfileServiceFactory);
+};
+
+#endif  // IOS_CHROME_BROWSER_SERVICES_GCM_IOS_CHROME_GCM_PROFILE_SERVICE_FACTORY_H_
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp
index 3981dcd..74e7156d 100644
--- a/ios/chrome/ios_chrome.gyp
+++ b/ios/chrome/ios_chrome.gyp
@@ -369,6 +369,8 @@
         'browser/search_engines/template_url_service_factory.h',
         'browser/search_engines/ui_thread_search_terms_data.cc',
         'browser/search_engines/ui_thread_search_terms_data.h',
+        'browser/services/gcm/ios_chrome_gcm_profile_service_factory.cc',
+        'browser/services/gcm/ios_chrome_gcm_profile_service_factory.h',
         'browser/sessions/ios_chrome_session_tab_helper.cc',
         'browser/sessions/ios_chrome_session_tab_helper.h',
         'browser/sessions/ios_chrome_tab_restore_service_client.cc',
diff --git a/ipc/attachment_broker.cc b/ipc/attachment_broker.cc
index 148e0d5b..50e3e2d9 100644
--- a/ipc/attachment_broker.cc
+++ b/ipc/attachment_broker.cc
@@ -6,6 +6,10 @@
 
 #include <algorithm>
 
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/sequenced_task_runner.h"
+
 namespace {
 IPC::AttachmentBroker* g_attachment_broker = nullptr;
 }
@@ -25,7 +29,7 @@
   return g_attachment_broker;
 }
 
-AttachmentBroker::AttachmentBroker() {}
+AttachmentBroker::AttachmentBroker() : last_unique_id_(0) {}
 AttachmentBroker::~AttachmentBroker() {}
 
 bool AttachmentBroker::GetAttachmentWithId(
@@ -43,16 +47,29 @@
   return false;
 }
 
-void AttachmentBroker::AddObserver(AttachmentBroker::Observer* observer) {
+void AttachmentBroker::AddObserver(
+    AttachmentBroker::Observer* observer,
+    const scoped_refptr<base::SequencedTaskRunner>& runner) {
   base::AutoLock auto_lock(*get_lock());
-  auto it = std::find(observers_.begin(), observers_.end(), observer);
-  if (it == observers_.end())
-    observers_.push_back(observer);
+  auto it = std::find_if(observers_.begin(), observers_.end(),
+                      [observer](const ObserverInfo& info) {
+                        return info.observer == observer;
+                      });
+  if (it == observers_.end()) {
+    ObserverInfo info;
+    info.observer = observer;
+    info.runner = runner;
+    info.unique_id = ++last_unique_id_;
+    observers_.push_back(info);
+  }
 }
 
 void AttachmentBroker::RemoveObserver(AttachmentBroker::Observer* observer) {
   base::AutoLock auto_lock(*get_lock());
-  auto it = std::find(observers_.begin(), observers_.end(), observer);
+  auto it = std::find_if(observers_.begin(), observers_.end(),
+                      [observer](const ObserverInfo& info) {
+                        return info.observer == observer;
+                      });
   if (it != observers_.end())
     observers_.erase(it);
 }
@@ -76,16 +93,40 @@
 
 void AttachmentBroker::NotifyObservers(
     const BrokerableAttachment::AttachmentId& id) {
-  // Make a copy of observers_ to avoid mutations during iteration.
-  std::vector<Observer*> observers;
-  {
-    base::AutoLock auto_lock(*get_lock());
-    observers = observers_;
-  }
+  base::AutoLock auto_lock(*get_lock());
 
-  for (Observer* observer : observers) {
-    observer->ReceivedBrokerableAttachmentWithId(id);
+  // Dispatch notifications onto the appropriate task runners. This has two
+  // effects:
+  //   1. Ensures that the notification is posted from the right task runner.
+  //   2. Avoids any complications from re-entrant functions, since one of the
+  //   observers may be halfway through processing some messages.
+  for (const auto& info : observers_) {
+    info.runner->PostTask(
+        FROM_HERE, base::Bind(&AttachmentBroker::NotifyObserver,
+                              base::Unretained(this), info.unique_id, id));
   }
 }
 
+void AttachmentBroker::NotifyObserver(
+    int unique_id,
+    const BrokerableAttachment::AttachmentId& id) {
+  Observer* observer = nullptr;
+  {
+    // Check that the same observer is still registered.
+    base::AutoLock auto_lock(*get_lock());
+    auto it = std::find_if(observers_.begin(), observers_.end(),
+                           [unique_id](const ObserverInfo& info) {
+                             return info.unique_id == unique_id;
+                           });
+    if (it == observers_.end())
+      return;
+    observer = it->observer;
+  }
+
+  observer->ReceivedBrokerableAttachmentWithId(id);
+}
+
+AttachmentBroker::ObserverInfo::ObserverInfo() {}
+AttachmentBroker::ObserverInfo::~ObserverInfo() {}
+
 }  // namespace IPC
diff --git a/ipc/attachment_broker.h b/ipc/attachment_broker.h
index 273d7644..06688921 100644
--- a/ipc/attachment_broker.h
+++ b/ipc/attachment_broker.h
@@ -24,6 +24,10 @@
 #define USE_ATTACHMENT_BROKER 0
 #endif  // defined(OS_WIN)
 
+namespace base {
+class SequencedTaskRunner;
+};
+
 namespace IPC {
 
 class AttachmentBroker;
@@ -77,7 +81,10 @@
                            scoped_refptr<BrokerableAttachment>* attachment);
 
   // Any given observer should only ever add itself once to the observer list.
-  void AddObserver(Observer* observer);
+  // Notifications to |observer| will be posted to |runner|.
+  // The |observer| is expected to call RemoveObserver() before being destroyed.
+  void AddObserver(Observer* observer,
+                   const scoped_refptr<base::SequencedTaskRunner>& runner);
   void RemoveObserver(Observer* observer);
 
   // These two methods should only be called by the broker process.
@@ -99,6 +106,11 @@
   // Informs the observers that a new BrokerableAttachment has been received.
   void NotifyObservers(const BrokerableAttachment::AttachmentId& id);
 
+  // Informs the observer identified by |unique_id| that a new
+  // BrokerableAttachment has been received.
+  void NotifyObserver(int unique_id,
+                      const BrokerableAttachment::AttachmentId& id);
+
   // This method is exposed for testing only.
   AttachmentVector* get_attachments() { return &attachments_; }
 
@@ -119,7 +131,20 @@
   // better performance.
   AttachmentVector attachments_;
 
-  std::vector<Observer*> observers_;
+  struct ObserverInfo {
+    ObserverInfo();
+    ~ObserverInfo();
+
+    Observer* observer;
+    int unique_id;
+
+    // Notifications must be dispatched onto |runner|.
+    scoped_refptr<base::SequencedTaskRunner> runner;
+  };
+  std::vector<ObserverInfo> observers_;
+
+  // This member holds the last id given to an ObserverInfo.
+  int last_unique_id_;
 
   // The AttachmentBroker can be accessed from any thread, so modifications to
   // internal state must be guarded by a lock.
diff --git a/ipc/attachment_broker_mac_unittest.cc b/ipc/attachment_broker_mac_unittest.cc
index e3062b58..3188640 100644
--- a/ipc/attachment_broker_mac_unittest.cc
+++ b/ipc/attachment_broker_mac_unittest.cc
@@ -395,7 +395,7 @@
     if (!broker_.get())
       SetBroker(new IPC::AttachmentBrokerUnprivilegedMac);
 
-    broker_->AddObserver(&observer_);
+    broker_->AddObserver(&observer_, task_runner());
     CreateChannel(&proxy_listener_);
     broker_->DesignateBrokerCommunicationChannel(channel());
     ASSERT_TRUE(ConnectChannel());
@@ -856,10 +856,16 @@
     IPC::Message* message =
         new TestSharedMemoryHandleMsg1(100, shared_memory->handle(), 200);
     sender()->Send(message);
+
+    // Wait until the child process has sent this process a message.
     base::MessageLoop::current()->Run();
 
+    // Wait for any asynchronous activity to complete.
+    base::MessageLoop::current()->RunUntilIdle();
+
     // Get the received attachment.
     IPC::BrokerableAttachment::AttachmentId* id = get_observer()->get_id();
+    ASSERT_TRUE(id);
     scoped_refptr<IPC::BrokerableAttachment> received_attachment;
     get_broker()->GetAttachmentWithId(*id, &received_attachment);
     ASSERT_NE(received_attachment.get(), nullptr);
@@ -898,7 +904,7 @@
   MachPreForkSetUp();
 
   SetBroker(new IPC::AttachmentBrokerUnprivilegedMac);
-  get_broker()->AddObserver(get_observer());
+  get_broker()->AddObserver(get_observer(), task_runner());
 
   scoped_ptr<base::Thread> thread(
       new base::Thread("ChannelProxyTestServerThread"));
diff --git a/ipc/attachment_broker_privileged_win_unittest.cc b/ipc/attachment_broker_privileged_win_unittest.cc
index b0353d6..b5e1e98 100644
--- a/ipc/attachment_broker_privileged_win_unittest.cc
+++ b/ipc/attachment_broker_privileged_win_unittest.cc
@@ -225,7 +225,7 @@
   void CommonSetUp() {
     if (!broker_.get())
       set_broker(new IPC::AttachmentBrokerUnprivilegedWin);
-    broker_->AddObserver(&observer_);
+    broker_->AddObserver(&observer_, task_runner());
     CreateChannel(&proxy_listener_);
     broker_->DesignateBrokerCommunicationChannel(channel());
     ASSERT_TRUE(ConnectChannel());
diff --git a/ipc/ipc_channel_posix_unittest.cc b/ipc/ipc_channel_posix_unittest.cc
index 5dc4de46..44c7b37 100644
--- a/ipc/ipc_channel_posix_unittest.cc
+++ b/ipc/ipc_channel_posix_unittest.cc
@@ -6,8 +6,10 @@
 
 #include "ipc/ipc_channel_posix.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <stdint.h>
+#include <string.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <unistd.h>
diff --git a/ipc/ipc_channel_reader.cc b/ipc/ipc_channel_reader.cc
index e0cb2bf..f03f0022 100644
--- a/ipc/ipc_channel_reader.cc
+++ b/ipc/ipc_channel_reader.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/message_loop/message_loop.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_logging.h"
 #include "ipc/ipc_message.h"
@@ -311,7 +312,8 @@
 
 void ChannelReader::StartObservingAttachmentBroker() {
 #if USE_ATTACHMENT_BROKER
-  GetAttachmentBroker()->AddObserver(this);
+  GetAttachmentBroker()->AddObserver(
+      this, base::MessageLoopForIO::current()->task_runner());
 #endif  // USE_ATTACHMENT_BROKER
 }
 
diff --git a/ipc/ipc_channel_reader_unittest.cc b/ipc/ipc_channel_reader_unittest.cc
index f49c275..ee29072c8 100644
--- a/ipc/ipc_channel_reader_unittest.cc
+++ b/ipc/ipc_channel_reader_unittest.cc
@@ -7,6 +7,7 @@
 #include <limits>
 #include <set>
 
+#include "base/run_loop.h"
 #include "ipc/attachment_broker.h"
 #include "ipc/brokerable_attachment.h"
 #include "ipc/ipc_channel_reader.h"
@@ -151,6 +152,8 @@
 }
 
 TEST(ChannelReaderTest, AttachmentNotYetBrokered) {
+  scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoopForIO());
+
   MockAttachmentBroker broker;
   MockChannelReader reader;
   reader.set_broker(&broker);
@@ -166,6 +169,9 @@
   EXPECT_EQ(nullptr, reader.get_last_dispatched_message());
 
   broker.AddAttachment(attachment);
+  base::RunLoop run_loop;
+  run_loop.RunUntilIdle();
+
   EXPECT_EQ(m, reader.get_last_dispatched_message());
 }
 
diff --git a/media/BUILD.gn b/media/BUILD.gn
index a7dac69..f191317 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -215,6 +215,8 @@
     "filters/ivf_parser.h",
     "filters/jpeg_parser.cc",
     "filters/jpeg_parser.h",
+    "filters/opus_constants.cc",
+    "filters/opus_constants.h",
     "filters/source_buffer_range.cc",
     "filters/source_buffer_range.h",
     "filters/source_buffer_stream.cc",
@@ -387,8 +389,6 @@
       "capture/video/android/video_capture_device_android.h",
       "capture/video/android/video_capture_device_factory_android.cc",
       "capture/video/android/video_capture_device_factory_android.h",
-      "cdm/android_cdm_factory.cc",
-      "cdm/android_cdm_factory.h",
     ]
     sources -= [
       "filters/decrypting_audio_decoder.cc",
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index e872ada..890dc56b 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -13,6 +13,7 @@
 #include "base/metrics/histogram.h"
 #include "base/nix/xdg_util.h"
 #include "base/stl_util.h"
+#include "base/sys_info.h"
 #include "chromeos/audio/audio_device.h"
 #include "chromeos/audio/cras_audio_handler.h"
 #include "media/audio/cras/cras_input.h"
@@ -58,8 +59,12 @@
 }
 
 bool IsBeamformingDefaultEnabled() {
-  return base::FieldTrialList::FindFullName("ChromebookBeamforming") ==
-         "Enabled";
+  if (base::FieldTrialList::FindFullName("ChromebookBeamforming") ==
+      "Enabled") {
+    return true;
+  }
+  const std::string& board = base::SysInfo::GetLsbReleaseBoard();
+  return board.find("buddy") != std::string::npos;
 }
 
 void AddDefaultDevice(AudioDeviceNames* device_names) {
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index c6705a0..2cf8802 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -238,13 +238,6 @@
     deps += [ "//third_party/ffmpeg" ]
   }
 
-  if (enable_browser_cdms) {
-    sources += [
-      "browser_cdm_factory.cc",
-      "browser_cdm_factory.h",
-    ]
-  }
-
   if (is_android) {
     public_deps = [
       "//media/base/android",
@@ -474,6 +467,7 @@
     "//media",
     "//testing/gmock",
     "//testing/gtest",
+    "//third_party/libyuv",
   ]
 
   if (media_use_ffmpeg) {
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn
index 65ce1fc4..392d58f 100644
--- a/media/base/android/BUILD.gn
+++ b/media/base/android/BUILD.gn
@@ -14,10 +14,10 @@
   sources = [
     "access_unit_queue.cc",
     "access_unit_queue.h",
+    "android_cdm_factory.cc",
+    "android_cdm_factory.h",
     "audio_decoder_job.cc",
     "audio_decoder_job.h",
-    "browser_cdm_factory_android.cc",
-    "browser_cdm_factory_android.h",
     "demuxer_android.h",
     "demuxer_stream_player_params.cc",
     "demuxer_stream_player_params.h",
diff --git a/media/base/android/android_cdm_factory.cc b/media/base/android/android_cdm_factory.cc
new file mode 100644
index 0000000..45bfad54
--- /dev/null
+++ b/media/base/android/android_cdm_factory.cc
@@ -0,0 +1,85 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/android/android_cdm_factory.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "media/base/android/media_drm_bridge.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/cdm_config.h"
+#include "media/base/key_systems.h"
+#include "third_party/widevine/cdm/widevine_cdm_common.h"
+#include "url/gurl.h"
+
+namespace media {
+
+AndroidCdmFactory::AndroidCdmFactory() {}
+
+AndroidCdmFactory::~AndroidCdmFactory() {}
+
+void AndroidCdmFactory::Create(
+    const std::string& key_system,
+    const GURL& security_origin,
+    const CdmConfig& cdm_config,
+    const SessionMessageCB& session_message_cb,
+    const SessionClosedCB& session_closed_cb,
+    const LegacySessionErrorCB& legacy_session_error_cb,
+    const SessionKeysChangeCB& session_keys_change_cb,
+    const SessionExpirationUpdateCB& session_expiration_update_cb,
+    const CdmCreatedCB& cdm_created_cb) {
+  // Bound |cdm_created_cb| so we always fire it asynchronously.
+  CdmCreatedCB bound_cdm_created_cb = BindToCurrentLoop(cdm_created_cb);
+
+  if (!security_origin.is_valid()) {
+    bound_cdm_created_cb.Run(nullptr, "Invalid origin.");
+    return;
+  }
+
+  std::string error_message;
+
+  if (!MediaDrmBridge::IsKeySystemSupported(key_system)) {
+    error_message = "Key system not supported unexpectedly: " + key_system;
+    NOTREACHED() << error_message;
+    bound_cdm_created_cb.Run(nullptr, error_message);
+    return;
+  }
+
+  scoped_refptr<MediaDrmBridge> cdm(
+      MediaDrmBridge::Create(key_system, session_message_cb, session_closed_cb,
+                             legacy_session_error_cb, session_keys_change_cb,
+                             session_expiration_update_cb));
+  if (!cdm) {
+    error_message = "MediaDrmBridge cannot be created for " + key_system;
+    NOTREACHED() << error_message;
+    bound_cdm_created_cb.Run(nullptr, error_message);
+    return;
+  }
+
+  if (key_system == kWidevineKeySystem) {
+    MediaDrmBridge::SecurityLevel security_level =
+        cdm_config.use_hw_secure_codecs ? MediaDrmBridge::SECURITY_LEVEL_1
+                                        : MediaDrmBridge::SECURITY_LEVEL_3;
+    if (!cdm->SetSecurityLevel(security_level)) {
+      error_message =
+          "failed to set security level " + base::IntToString(security_level);
+      DVLOG(1) << error_message;
+      bound_cdm_created_cb.Run(nullptr, error_message);
+      return;
+    }
+  } else if (!cdm_config.use_hw_secure_codecs) {
+    // Assume other key systems require hardware-secure codecs and thus do not
+    // support full compositing.
+    error_message =
+        key_system +
+        " may require use_video_overlay_for_embedded_encrypted_video";
+    NOTREACHED() << error_message;
+    bound_cdm_created_cb.Run(nullptr, error_message);
+    return;
+  }
+
+  // Success!
+  bound_cdm_created_cb.Run(cdm, "");
+}
+
+}  // namespace media
diff --git a/media/cdm/android_cdm_factory.h b/media/base/android/android_cdm_factory.h
similarity index 79%
rename from media/cdm/android_cdm_factory.h
rename to media/base/android/android_cdm_factory.h
index b0ee4bbf..c469af8c 100644
--- a/media/cdm/android_cdm_factory.h
+++ b/media/base/android/android_cdm_factory.h
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef MEDIA_CDM_ANDROID_CDM_FACTORY_H_
-#define MEDIA_CDM_ANDROID_CDM_FACTORY_H_
+#ifndef MEDIA_BASE_ANDROID_ANDROID_CDM_FACTORY_H_
+#define MEDIA_BASE_ANDROID_ANDROID_CDM_FACTORY_H_
 
 #include "base/macros.h"
 #include "media/base/cdm_factory.h"
+#include "media/base/media_export.h"
 
 namespace media {
 
 struct CdmConfig;
 
-class AndroidCdmFactory : public CdmFactory {
+class MEDIA_EXPORT AndroidCdmFactory : public CdmFactory {
  public:
   AndroidCdmFactory();
   ~AndroidCdmFactory() final;
@@ -34,4 +35,4 @@
 
 }  // namespace media
 
-#endif  // MEDIA_CDM_ANDROID_CDM_FACTORY_H_
+#endif  // MEDIA_BASE_ANDROID_ANDROID_CDM_FACTORY_H_
diff --git a/media/base/android/browser_cdm_factory_android.cc b/media/base/android/browser_cdm_factory_android.cc
deleted file mode 100644
index 9b43379..0000000
--- a/media/base/android/browser_cdm_factory_android.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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 "media/base/android/browser_cdm_factory_android.h"
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "media/base/android/media_drm_bridge.h"
-#include "media/base/media_switches.h"
-#include "third_party/widevine/cdm/widevine_cdm_common.h"
-
-namespace media {
-
-scoped_refptr<MediaKeys> BrowserCdmFactoryAndroid::CreateBrowserCdm(
-    const std::string& key_system,
-    bool use_hw_secure_codecs,
-    const SessionMessageCB& session_message_cb,
-    const SessionClosedCB& session_closed_cb,
-    const LegacySessionErrorCB& legacy_session_error_cb,
-    const SessionKeysChangeCB& session_keys_change_cb,
-    const SessionExpirationUpdateCB& session_expiration_update_cb) {
-  if (!MediaDrmBridge::IsKeySystemSupported(key_system)) {
-    NOTREACHED() << "Key system not supported unexpectedly: " << key_system;
-    return nullptr;
-  }
-
-  scoped_refptr<MediaDrmBridge> cdm(
-      MediaDrmBridge::Create(key_system, session_message_cb, session_closed_cb,
-                             legacy_session_error_cb, session_keys_change_cb,
-                             session_expiration_update_cb));
-  if (!cdm) {
-    NOTREACHED() << "MediaDrmBridge cannot be created for " << key_system;
-    return nullptr;
-  }
-
-  if (key_system == kWidevineKeySystem) {
-    MediaDrmBridge::SecurityLevel security_level =
-        use_hw_secure_codecs ? MediaDrmBridge::SECURITY_LEVEL_1
-                          : MediaDrmBridge::SECURITY_LEVEL_3;
-    if (!cdm->SetSecurityLevel(security_level)) {
-      DVLOG(1) << "failed to set security level " << security_level;
-      return nullptr;
-    }
-  } else {
-    // Assume other key systems require hardware-secure codecs and thus do not
-    // support full compositing.
-    if (!use_hw_secure_codecs) {
-      NOTREACHED()
-          << key_system
-          << " may require use_video_overlay_for_embedded_encrypted_video";
-      return nullptr;
-    }
-  }
-
-  return cdm;
-}
-
-}  // namespace media
diff --git a/media/base/android/browser_cdm_factory_android.h b/media/base/android/browser_cdm_factory_android.h
deleted file mode 100644
index babae75..0000000
--- a/media/base/android/browser_cdm_factory_android.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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 MEDIA_BASE_BROWSER_CDM_FACTORY_ANDROID_H_
-#define MEDIA_BASE_BROWSER_CDM_FACTORY_ANDROID_H_
-
-#include "base/macros.h"
-#include "media/base/browser_cdm_factory.h"
-#include "media/base/media_export.h"
-
-namespace media {
-
-class MEDIA_EXPORT BrowserCdmFactoryAndroid : public BrowserCdmFactory {
- public:
-  BrowserCdmFactoryAndroid() {}
-  ~BrowserCdmFactoryAndroid() final {};
-
-  scoped_refptr<MediaKeys> CreateBrowserCdm(
-      const std::string& key_system,
-      bool use_hw_secure_codecs,
-      const SessionMessageCB& session_message_cb,
-      const SessionClosedCB& session_closed_cb,
-      const LegacySessionErrorCB& legacy_session_error_cb,
-      const SessionKeysChangeCB& session_keys_change_cb,
-      const SessionExpirationUpdateCB& session_expiration_update_cb) final;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(BrowserCdmFactoryAndroid);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_BASE_BROWSER_CDM_FACTORY_ANDROID_H_
diff --git a/media/base/browser_cdm_factory.cc b/media/base/browser_cdm_factory.cc
deleted file mode 100644
index 69a6a02..0000000
--- a/media/base/browser_cdm_factory.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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 "media/base/browser_cdm_factory.h"
-
-#include "base/logging.h"
-
-#if defined(OS_ANDROID)
-#include "media/base/android/browser_cdm_factory_android.h"
-#endif
-
-namespace media {
-
-namespace {
-BrowserCdmFactory* g_cdm_factory = NULL;
-}
-
-void SetBrowserCdmFactory(BrowserCdmFactory* factory) {
-  DCHECK(!g_cdm_factory);
-  g_cdm_factory = factory;
-}
-
-scoped_refptr<MediaKeys> CreateBrowserCdm(
-    const std::string& key_system,
-    bool use_hw_secure_codecs,
-    const SessionMessageCB& session_message_cb,
-    const SessionClosedCB& session_closed_cb,
-    const LegacySessionErrorCB& legacy_session_error_cb,
-    const SessionKeysChangeCB& session_keys_change_cb,
-    const SessionExpirationUpdateCB& session_expiration_update_cb) {
-  if (!g_cdm_factory) {
-#if defined(OS_ANDROID)
-    SetBrowserCdmFactory(new BrowserCdmFactoryAndroid());
-#else
-    LOG(ERROR) << "Cannot create BrowserCdm: no BrowserCdmFactory available!";
-    return nullptr;
-#endif
-  }
-
-  return g_cdm_factory->CreateBrowserCdm(
-      key_system, use_hw_secure_codecs, session_message_cb, session_closed_cb,
-      legacy_session_error_cb, session_keys_change_cb,
-      session_expiration_update_cb);
-}
-
-}  // namespace media
diff --git a/media/base/browser_cdm_factory.h b/media/base/browser_cdm_factory.h
deleted file mode 100644
index 8a05a67..0000000
--- a/media/base/browser_cdm_factory.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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 MEDIA_BASE_BROWSER_CDM_FACTORY_H_
-#define MEDIA_BASE_BROWSER_CDM_FACTORY_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "media/base/media_export.h"
-#include "media/base/media_keys.h"
-
-namespace media {
-
-// TODO(xhwang): Merge this with media::CdmFactory.
-class MEDIA_EXPORT BrowserCdmFactory {
- public:
-  BrowserCdmFactory() {}
-  virtual ~BrowserCdmFactory() {}
-
-  virtual scoped_refptr<MediaKeys> CreateBrowserCdm(
-      const std::string& key_system,
-      bool use_hw_secure_codecs,
-      const SessionMessageCB& session_message_cb,
-      const SessionClosedCB& session_closed_cb,
-      const LegacySessionErrorCB& legacy_session_error_cb,
-      const SessionKeysChangeCB& session_keys_change_cb,
-      const SessionExpirationUpdateCB& session_expiration_update_cb) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(BrowserCdmFactory);
-};
-
-// Provides a factory for creating BrowserCdm instances. There is only one
-// BrowserCdmFactory per process.
-void SetBrowserCdmFactory(BrowserCdmFactory* factory);
-
-// Creates a MediaKeys for |key_system|. Returns NULL if the CDM cannot be
-// created.
-// |use_hw_secure_codecs| indicates that the CDM should be configured to use
-// hardware-secure codecs (for platforms that support it).
-// TODO(xhwang): Add ifdef for IPC based CDM.
-scoped_refptr<MediaKeys> MEDIA_EXPORT
-CreateBrowserCdm(const std::string& key_system,
-                 bool use_hw_secure_codecs,
-                 const SessionMessageCB& session_message_cb,
-                 const SessionClosedCB& session_closed_cb,
-                 const LegacySessionErrorCB& legacy_session_error_cb,
-                 const SessionKeysChangeCB& session_keys_change_cb,
-                 const SessionExpirationUpdateCB& session_expiration_update_cb);
-
-}  // namespace media
-
-#endif  // MEDIA_BASE_BROWSER_CDM_FACTORY_H_
diff --git a/media/base/media_client.h b/media/base/media_client.h
index 4b6bef5..dc8da49 100644
--- a/media/base/media_client.h
+++ b/media/base/media_client.h
@@ -21,7 +21,7 @@
 MEDIA_EXPORT void SetMediaClient(MediaClient* media_client);
 
 // Media's embedder API should only be used by media.
-#if defined(MEDIA_IMPLEMENTATION)
+#if defined(MEDIA_IMPLEMENTATION) || defined(MEDIA_BLINK_IMPLEMENTATION)
 // Getter for the client. Returns NULL if no customized client is needed.
 MEDIA_EXPORT MediaClient* GetMediaClient();
 #endif
diff --git a/media/base/yuv_convert_perftest.cc b/media/base/yuv_convert_perftest.cc
index d676e4e..2f6d5c1 100644
--- a/media/base/yuv_convert_perftest.cc
+++ b/media/base/yuv_convert_perftest.cc
@@ -12,6 +12,7 @@
 #include "media/base/yuv_convert.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
+#include "third_party/libyuv/include/libyuv/row.h"
 
 namespace media {
 #if !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY)
@@ -87,6 +88,73 @@
       kPerfTestIterations / total_time_seconds, "runs/s", true);
 }
 
+#ifdef HAS_I422TOARGBROW_SSSE3
+TEST_F(YUVConvertPerfTest, I422ToARGBRow_SSSE3) {
+  ASSERT_TRUE(base::CPU().has_ssse3());
+
+  base::TimeTicks start = base::TimeTicks::Now();
+  for (int i = 0; i < kPerfTestIterations; ++i) {
+    for (int row = 0; row < kSourceHeight; ++row) {
+      int chroma_row = row / 2;
+      libyuv::I422ToARGBRow_SSSE3(
+          yuv_bytes_.get() + row * kSourceWidth,
+          yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2),
+          yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2),
+          rgb_bytes_converted_.get(), &libyuv::kYuvI601Constants, kWidth);
+    }
+  }
+  double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF();
+  perf_test::PrintResult("yuv_convert_perftest", "", "I422ToARGBRow_SSSE3",
+                         kPerfTestIterations / total_time_seconds, "runs/s",
+                         true);
+}
+#endif
+
+TEST_F(YUVConvertPerfTest, ConvertYUVAToARGBRow_MMX) {
+  ASSERT_TRUE(base::CPU().has_sse());
+
+  base::TimeTicks start = base::TimeTicks::Now();
+  for (int i = 0; i < kPerfTestIterations; ++i) {
+    for (int row = 0; row < kSourceHeight; ++row) {
+      int chroma_row = row / 2;
+      ConvertYUVAToARGBRow_MMX(
+          yuv_bytes_.get() + row * kSourceWidth,
+          yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2),
+          yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2),
+          yuv_bytes_.get() + row * kSourceWidth,  // hack: use luma for alpha
+          rgb_bytes_converted_.get(), kWidth, GetLookupTable(YV12));
+    }
+  }
+  media::EmptyRegisterState();
+  double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF();
+  perf_test::PrintResult("yuv_convert_perftest", "", "ConvertYUVAToARGBRow_MMX",
+                         kPerfTestIterations / total_time_seconds, "runs/s",
+                         true);
+}
+
+#ifdef HAS_I422ALPHATOARGBROW_SSSE3
+TEST_F(YUVConvertPerfTest, I422AlphaToARGBRow_SSSE3) {
+  ASSERT_TRUE(base::CPU().has_ssse3());
+
+  base::TimeTicks start = base::TimeTicks::Now();
+  for (int i = 0; i < kPerfTestIterations; ++i) {
+    for (int row = 0; row < kSourceHeight; ++row) {
+      int chroma_row = row / 2;
+      libyuv::I422AlphaToARGBRow_SSSE3(
+          yuv_bytes_.get() + row * kSourceWidth,
+          yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2),
+          yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2),
+          yuv_bytes_.get() + row * kSourceWidth,  // hack: use luma for alpha
+          rgb_bytes_converted_.get(), &libyuv::kYuvI601Constants, kWidth);
+    }
+  }
+  double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF();
+  perf_test::PrintResult("yuv_convert_perftest", "", "I422AlphaToARGBRow_SSSE3",
+                         kPerfTestIterations / total_time_seconds, "runs/s",
+                         true);
+}
+#endif
+
 // 64-bit release + component builds on Windows are too smart and optimizes
 // away the function being tested.
 #if defined(OS_WIN) && (defined(ARCH_CPU_X86) || !defined(COMPONENT_BUILD))
@@ -135,11 +203,11 @@
           GetLookupTable(YV12));
     }
   }
+  media::EmptyRegisterState();
   double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF();
   perf_test::PrintResult(
       "yuv_convert_perftest", "", "LinearScaleYUVToRGB32Row_SSE",
       kPerfTestIterations / total_time_seconds, "runs/s", true);
-  media::EmptyRegisterState();
 }
 #endif  // defined(OS_WIN) && (ARCH_CPU_X86 || COMPONENT_BUILD)
 
diff --git a/media/blink/BUILD.gn b/media/blink/BUILD.gn
index 8819fb7..f53b422 100644
--- a/media/blink/BUILD.gn
+++ b/media/blink/BUILD.gn
@@ -23,7 +23,7 @@
     "//url",
   ]
 
-  defines = [ "MEDIA_IMPLEMENTATION" ]
+  defines = [ "MEDIA_BLINK_IMPLEMENTATION" ]
 
   sources = [
     "active_loader.cc",
@@ -43,6 +43,7 @@
     "cdm_session_adapter.h",
     "key_system_config_selector.cc",
     "key_system_config_selector.h",
+    "media_blink_export.h",
     "new_session_cdm_result_promise.cc",
     "new_session_cdm_result_promise.h",
     "texttrack_impl.cc",
diff --git a/media/blink/active_loader.h b/media/blink/active_loader.h
index d8c60df..171ad450 100644
--- a/media/blink/active_loader.h
+++ b/media/blink/active_loader.h
@@ -7,7 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "media/base/media_export.h"
+#include "media/blink/media_blink_export.h"
 
 namespace blink {
 class WebURLLoader;
@@ -18,7 +18,7 @@
 // Wraps an active WebURLLoader with some additional state.
 //
 // Handles deferring and deletion of loaders.
-class MEDIA_EXPORT ActiveLoader {
+class MEDIA_BLINK_EXPORT ActiveLoader {
  public:
   // Creates an ActiveLoader with the given loader. It is assumed that the
   // initial state of |loader| is loading and not deferred.
diff --git a/media/blink/buffered_data_source.h b/media/blink/buffered_data_source.h
index 9762050a..0c88ec8 100644
--- a/media/blink/buffered_data_source.h
+++ b/media/blink/buffered_data_source.h
@@ -13,9 +13,9 @@
 #include "base/memory/weak_ptr.h"
 #include "base/synchronization/lock.h"
 #include "media/base/data_source.h"
-#include "media/base/media_export.h"
 #include "media/base/ranges.h"
 #include "media/blink/buffered_resource_loader.h"
+#include "media/blink/media_blink_export.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -25,7 +25,7 @@
 namespace media {
 class MediaLog;
 
-class MEDIA_EXPORT BufferedDataSourceHost {
+class MEDIA_BLINK_EXPORT BufferedDataSourceHost {
  public:
   // Notify the host of the total size of the media file.
   virtual void SetTotalBytes(int64 total_bytes) = 0;
@@ -44,7 +44,7 @@
 //
 // BufferedDataSource must be created and destroyed on the thread associated
 // with the |task_runner| passed in the constructor.
-class MEDIA_EXPORT BufferedDataSource : public DataSource {
+class MEDIA_BLINK_EXPORT BufferedDataSource : public DataSource {
  public:
   // Used to specify video preload states. They are "hints" to the browser about
   // how aggressively the browser should load and buffer data.
diff --git a/media/blink/buffered_data_source_host_impl.h b/media/blink/buffered_data_source_host_impl.h
index 8dd2ab7c..d58c8c06 100644
--- a/media/blink/buffered_data_source_host_impl.h
+++ b/media/blink/buffered_data_source_host_impl.h
@@ -6,15 +6,15 @@
 #define MEDIA_BLINK_BUFFERED_DATA_SOURCE_HOST_IMPL_H_
 
 #include "base/time/time.h"
-#include "media/base/media_export.h"
 #include "media/base/ranges.h"
 #include "media/blink/buffered_data_source.h"
+#include "media/blink/media_blink_export.h"
 
 namespace media {
 
 // Provides an implementation of BufferedDataSourceHost that translates the
 // buffered byte ranges into estimated time ranges.
-class MEDIA_EXPORT BufferedDataSourceHostImpl
+class MEDIA_BLINK_EXPORT BufferedDataSourceHostImpl
     : public BufferedDataSourceHost {
  public:
   BufferedDataSourceHostImpl();
diff --git a/media/blink/buffered_resource_loader.h b/media/blink/buffered_resource_loader.h
index b4dec9a6..97c59f4 100644
--- a/media/blink/buffered_resource_loader.h
+++ b/media/blink/buffered_resource_loader.h
@@ -9,9 +9,9 @@
 
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
-#include "media/base/media_export.h"
 #include "media/base/seekable_buffer.h"
 #include "media/blink/active_loader.h"
+#include "media/blink/media_blink_export.h"
 #include "third_party/WebKit/public/platform/WebURLLoader.h"
 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
@@ -28,7 +28,7 @@
 // render thread. It wraps a WebURLLoader and does in-memory buffering,
 // pausing resource loading when the in-memory buffer is full and resuming
 // resource loading when there is available capacity.
-class MEDIA_EXPORT BufferedResourceLoader
+class MEDIA_BLINK_EXPORT BufferedResourceLoader
     : NON_EXPORTED_BASE(public blink::WebURLLoaderClient) {
  public:
   // kNeverDefer - Aggresively buffer; never defer loading while paused.
diff --git a/media/blink/cache_util.h b/media/blink/cache_util.h
index 5c59f14..033b6bd 100644
--- a/media/blink/cache_util.h
+++ b/media/blink/cache_util.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "media/base/media_export.h"
+#include "media/blink/media_blink_export.h"
 
 namespace blink {
 class WebURLResponse;
@@ -33,8 +33,8 @@
 
 // Return the logical OR of the reasons "response" cannot be used for a future
 // request (using the disk cache), or 0 if it might be useful.
-uint32 MEDIA_EXPORT GetReasonsForUncacheability(
-    const blink::WebURLResponse& response);
+uint32 MEDIA_BLINK_EXPORT
+GetReasonsForUncacheability(const blink::WebURLResponse& response);
 
 }  // namespace media
 
diff --git a/media/blink/cdm_result_promise_helper.h b/media/blink/cdm_result_promise_helper.h
index 2fe385d..e2a67c3 100644
--- a/media/blink/cdm_result_promise_helper.h
+++ b/media/blink/cdm_result_promise_helper.h
@@ -7,8 +7,8 @@
 
 #include <string>
 
-#include "media/base/media_export.h"
 #include "media/base/media_keys.h"
+#include "media/blink/media_blink_export.h"
 #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
 
 namespace media {
@@ -28,14 +28,14 @@
   NUM_RESULT_CODES
 };
 
-MEDIA_EXPORT CdmResultForUMA
-    ConvertCdmExceptionToResultForUMA(MediaKeys::Exception exception_code);
+MEDIA_BLINK_EXPORT CdmResultForUMA
+ConvertCdmExceptionToResultForUMA(MediaKeys::Exception exception_code);
 
-MEDIA_EXPORT blink::WebContentDecryptionModuleException ConvertCdmException(
-    MediaKeys::Exception exception_code);
+MEDIA_BLINK_EXPORT blink::WebContentDecryptionModuleException
+ConvertCdmException(MediaKeys::Exception exception_code);
 
-MEDIA_EXPORT void ReportCdmResultUMA(const std::string& uma_name,
-                                     CdmResultForUMA result);
+MEDIA_BLINK_EXPORT void ReportCdmResultUMA(const std::string& uma_name,
+                                           CdmResultForUMA result);
 
 }  // namespace media
 
diff --git a/media/blink/key_system_config_selector.h b/media/blink/key_system_config_selector.h
index 7a8afbf..55e6b33 100644
--- a/media/blink/key_system_config_selector.h
+++ b/media/blink/key_system_config_selector.h
@@ -13,7 +13,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "media/base/eme_constants.h"
-#include "media/base/media_export.h"
+#include "media/blink/media_blink_export.h"
 #include "third_party/WebKit/public/platform/WebVector.h"
 
 namespace blink {
@@ -31,7 +31,7 @@
 class KeySystems;
 class MediaPermission;
 
-class MEDIA_EXPORT KeySystemConfigSelector {
+class MEDIA_BLINK_EXPORT KeySystemConfigSelector {
  public:
   KeySystemConfigSelector(
       const KeySystems* key_systems,
diff --git a/media/blink/media_blink.gyp b/media/blink/media_blink.gyp
index 5e4a7384..86e5e0f 100644
--- a/media/blink/media_blink.gyp
+++ b/media/blink/media_blink.gyp
@@ -25,7 +25,7 @@
         '../../url/url.gyp:url_lib',
       ],
       'defines': [
-        'MEDIA_IMPLEMENTATION',
+        'MEDIA_BLINK_IMPLEMENTATION',
       ],
       # This sources list is duplicated in //media/blink/BUILD.gn
       'sources': [
@@ -48,6 +48,7 @@
         'encrypted_media_player_support.h',
         'key_system_config_selector.cc',
         'key_system_config_selector.h',
+        'media_blink_export.h',
         'new_session_cdm_result_promise.cc',
         'new_session_cdm_result_promise.h',
         'texttrack_impl.cc',
diff --git a/media/blink/media_blink_export.h b/media/blink/media_blink_export.h
new file mode 100644
index 0000000..42325e5
--- /dev/null
+++ b/media/blink/media_blink_export.h
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BLINK_MEDIA_BLINK_EXPORT_H_
+#define MEDIA_BLINK_MEDIA_BLINK_EXPORT_H_
+
+// Define MEDIA_BLINK_EXPORT so that functionality implemented by the
+// media/blink module can be exported to consumers.
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(MEDIA_BLINK_IMPLEMENTATION)
+#define MEDIA_BLINK_EXPORT __declspec(dllexport)
+#else
+#define MEDIA_BLINK_EXPORT __declspec(dllimport)
+#endif  // defined(MEDIA_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(MEDIA_BLINK_IMPLEMENTATION)
+#define MEDIA_BLINK_EXPORT __attribute__((visibility("default")))
+#else
+#define MEDIA_BLINK_EXPORT
+#endif
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define MEDIA_BLINK_EXPORT
+#endif
+
+#endif  // MEDIA_BLINK_MEDIA_BLINK_EXPORT_H_
diff --git a/media/blink/new_session_cdm_result_promise.h b/media/blink/new_session_cdm_result_promise.h
index 78e70b6..c26bc95 100644
--- a/media/blink/new_session_cdm_result_promise.h
+++ b/media/blink/new_session_cdm_result_promise.h
@@ -9,8 +9,8 @@
 
 #include "base/basictypes.h"
 #include "media/base/cdm_promise.h"
-#include "media/base/media_export.h"
 #include "media/base/media_keys.h"
+#include "media/blink/media_blink_export.h"
 #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
 
 namespace media {
@@ -37,7 +37,7 @@
 // promise returns the session ID (as a string), but the blink promise needs
 // to get passed a SessionStatus. This class converts the session id to a
 // SessionStatus by calling |new_session_created_cb|.
-class MEDIA_EXPORT NewSessionCdmResultPromise
+class MEDIA_BLINK_EXPORT NewSessionCdmResultPromise
     : public CdmPromiseTemplate<std::string> {
  public:
   NewSessionCdmResultPromise(
diff --git a/media/blink/video_frame_compositor.h b/media/blink/video_frame_compositor.h
index 8cadedbb..9983413 100644
--- a/media/blink/video_frame_compositor.h
+++ b/media/blink/video_frame_compositor.h
@@ -12,8 +12,8 @@
 #include "base/time/tick_clock.h"
 #include "base/timer/timer.h"
 #include "cc/layers/video_frame_provider.h"
-#include "media/base/media_export.h"
 #include "media/base/video_renderer_sink.h"
+#include "media/blink/media_blink_export.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace media {
@@ -44,7 +44,7 @@
 //
 // VideoFrameCompositor must live on the same thread as the compositor, though
 // it may be constructed on any thread.
-class MEDIA_EXPORT VideoFrameCompositor
+class MEDIA_BLINK_EXPORT VideoFrameCompositor
     : public VideoRendererSink,
       NON_EXPORTED_BASE(public cc::VideoFrameProvider) {
  public:
diff --git a/media/blink/webaudiosourceprovider_impl.h b/media/blink/webaudiosourceprovider_impl.h
index bc406e57..675be92 100644
--- a/media/blink/webaudiosourceprovider_impl.h
+++ b/media/blink/webaudiosourceprovider_impl.h
@@ -11,7 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/synchronization/lock.h"
 #include "media/base/audio_renderer_sink.h"
-#include "media/base/media_export.h"
+#include "media/blink/media_blink_export.h"
 #include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
 #include "third_party/WebKit/public/platform/WebVector.h"
 
@@ -30,7 +30,7 @@
 // sample-frames using the sink's RenderCallback to get the data.
 //
 // All calls are protected by a lock.
-class MEDIA_EXPORT WebAudioSourceProviderImpl
+class MEDIA_BLINK_EXPORT WebAudioSourceProviderImpl
     : NON_EXPORTED_BASE(public blink::WebAudioSourceProvider),
       NON_EXPORTED_BASE(public AudioRendererSink) {
  public:
diff --git a/media/blink/webcontentdecryptionmodule_impl.h b/media/blink/webcontentdecryptionmodule_impl.h
index 3567d8b..730077e 100644
--- a/media/blink/webcontentdecryptionmodule_impl.h
+++ b/media/blink/webcontentdecryptionmodule_impl.h
@@ -8,7 +8,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
-#include "media/base/media_export.h"
+#include "media/blink/media_blink_export.h"
 #include "third_party/WebKit/public/platform/WebContentDecryptionModule.h"
 #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
 
@@ -27,7 +27,7 @@
 class CdmSessionAdapter;
 class WebContentDecryptionModuleSessionImpl;
 
-class MEDIA_EXPORT WebContentDecryptionModuleImpl
+class MEDIA_BLINK_EXPORT WebContentDecryptionModuleImpl
     : public blink::WebContentDecryptionModule {
  public:
   static void Create(
diff --git a/media/blink/webencryptedmediaclient_impl.h b/media/blink/webencryptedmediaclient_impl.h
index 83197d82..a87e356 100644
--- a/media/blink/webencryptedmediaclient_impl.h
+++ b/media/blink/webencryptedmediaclient_impl.h
@@ -11,8 +11,8 @@
 #include "base/containers/scoped_ptr_hash_map.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "media/base/media_export.h"
 #include "media/blink/key_system_config_selector.h"
+#include "media/blink/media_blink_export.h"
 #include "third_party/WebKit/public/platform/WebEncryptedMediaClient.h"
 
 namespace blink {
@@ -30,7 +30,7 @@
 class KeySystems;
 class MediaPermission;
 
-class MEDIA_EXPORT WebEncryptedMediaClientImpl
+class MEDIA_BLINK_EXPORT WebEncryptedMediaClientImpl
     : public blink::WebEncryptedMediaClient {
  public:
   WebEncryptedMediaClientImpl(
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index e839268d..5b53753 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -15,13 +15,13 @@
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread.h"
 #include "media/base/cdm_factory.h"
-#include "media/base/media_export.h"
 #include "media/base/pipeline.h"
 #include "media/base/renderer_factory.h"
 #include "media/base/text_track.h"
 #include "media/blink/buffered_data_source.h"
 #include "media/blink/buffered_data_source_host_impl.h"
 #include "media/blink/encrypted_media_player_support.h"
+#include "media/blink/media_blink_export.h"
 #include "media/blink/video_frame_compositor.h"
 #include "media/blink/webmediaplayer_params.h"
 #include "media/blink/webmediaplayer_util.h"
@@ -61,7 +61,7 @@
 // The canonical implementation of blink::WebMediaPlayer that's backed by
 // Pipeline. Handles normal resource loading, Media Source, and
 // Encrypted Media.
-class MEDIA_EXPORT WebMediaPlayerImpl
+class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
     : public NON_EXPORTED_BASE(blink::WebMediaPlayer),
       public base::SupportsWeakPtr<WebMediaPlayerImpl> {
  public:
diff --git a/media/blink/webmediaplayer_params.h b/media/blink/webmediaplayer_params.h
index 7be212a..35f5134 100644
--- a/media/blink/webmediaplayer_params.h
+++ b/media/blink/webmediaplayer_params.h
@@ -7,7 +7,7 @@
 
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
-#include "media/base/media_export.h"
+#include "media/blink/media_blink_export.h"
 #include "media/filters/context_3d.h"
 
 namespace base {
@@ -28,7 +28,7 @@
 
 // Holds parameters for constructing WebMediaPlayerImpl without having
 // to plumb arguments through various abstraction layers.
-class MEDIA_EXPORT WebMediaPlayerParams {
+class MEDIA_BLINK_EXPORT WebMediaPlayerParams {
  public:
   typedef base::Callback<void(const base::Closure&)> DeferLoadCB;
   typedef base::Callback<Context3D()> Context3DCB;
diff --git a/media/blink/webmediaplayer_util.h b/media/blink/webmediaplayer_util.h
index 6359ace..7f4e7e96 100644
--- a/media/blink/webmediaplayer_util.h
+++ b/media/blink/webmediaplayer_util.h
@@ -8,9 +8,9 @@
 #include "base/time/time.h"
 #include "media/base/audio_renderer_sink.h"
 #include "media/base/eme_constants.h"
-#include "media/base/media_export.h"
 #include "media/base/pipeline_status.h"
 #include "media/base/ranges.h"
+#include "media/blink/media_blink_export.h"
 #include "third_party/WebKit/public/platform/WebEncryptedMediaTypes.h"
 #include "third_party/WebKit/public/platform/WebMediaPlayer.h"
 #include "third_party/WebKit/public/platform/WebSetSinkIdCallbacks.h"
@@ -19,29 +19,29 @@
 
 namespace media {
 
-blink::WebTimeRanges MEDIA_EXPORT ConvertToWebTimeRanges(
-    const Ranges<base::TimeDelta>& ranges);
+blink::WebTimeRanges MEDIA_BLINK_EXPORT
+ConvertToWebTimeRanges(const Ranges<base::TimeDelta>& ranges);
 
-blink::WebMediaPlayer::NetworkState MEDIA_EXPORT PipelineErrorToNetworkState(
-    PipelineStatus error);
+blink::WebMediaPlayer::NetworkState MEDIA_BLINK_EXPORT
+PipelineErrorToNetworkState(PipelineStatus error);
 
 // Report various metrics to UMA and RAPPOR.
-void MEDIA_EXPORT ReportMetrics(blink::WebMediaPlayer::LoadType load_type,
-                                const GURL& url,
-                                const GURL& origin_url);
+void MEDIA_BLINK_EXPORT ReportMetrics(blink::WebMediaPlayer::LoadType load_type,
+                                      const GURL& url,
+                                      const GURL& origin_url);
 
 // Record a RAPPOR metric for the origin of an HLS playback.
-void MEDIA_EXPORT RecordOriginOfHLSPlayback(const GURL& origin_url);
+void MEDIA_BLINK_EXPORT RecordOriginOfHLSPlayback(const GURL& origin_url);
 
 // Convert Initialization Data Types.
-EmeInitDataType MEDIA_EXPORT
+EmeInitDataType MEDIA_BLINK_EXPORT
 ConvertToEmeInitDataType(blink::WebEncryptedMediaInitDataType init_data_type);
-blink::WebEncryptedMediaInitDataType MEDIA_EXPORT
+blink::WebEncryptedMediaInitDataType MEDIA_BLINK_EXPORT
 ConvertToWebInitDataType(EmeInitDataType init_data_type);
 
 // Wraps a blink::WebSetSinkIdCallbacks into a media::SwitchOutputDeviceCB
 // and binds it to the current thread
-SwitchOutputDeviceCB MEDIA_EXPORT
+SwitchOutputDeviceCB MEDIA_BLINK_EXPORT
 ConvertToSwitchOutputDeviceCB(blink::WebSetSinkIdCallbacks* web_callbacks);
 
 }  // namespace media
diff --git a/media/blink/webmediasource_impl.h b/media/blink/webmediasource_impl.h
index 9251935..6ee8da4 100644
--- a/media/blink/webmediasource_impl.h
+++ b/media/blink/webmediasource_impl.h
@@ -8,14 +8,14 @@
 #include <string>
 #include <vector>
 
-#include "media/base/media_export.h"
 #include "media/base/media_log.h"
+#include "media/blink/media_blink_export.h"
 #include "third_party/WebKit/public/platform/WebMediaSource.h"
 
 namespace media {
 class ChunkDemuxer;
 
-class MEDIA_EXPORT WebMediaSourceImpl
+class MEDIA_BLINK_EXPORT WebMediaSourceImpl
     : NON_EXPORTED_BASE(public blink::WebMediaSource) {
  public:
   WebMediaSourceImpl(ChunkDemuxer* demuxer,
diff --git a/media/capture/webm_muxer.cc b/media/capture/webm_muxer.cc
index 31dfade5..5e569bc 100644
--- a/media/capture/webm_muxer.cc
+++ b/media/capture/webm_muxer.cc
@@ -5,12 +5,53 @@
 #include "media/capture/webm_muxer.h"
 
 #include "base/bind.h"
+#include "media/audio/audio_parameters.h"
 #include "media/base/limits.h"
 #include "media/base/video_frame.h"
+#include "media/filters/opus_constants.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace media {
 
+namespace {
+
+void WriteOpusHeader(const media::AudioParameters& params, uint8* header) {
+  // See https://wiki.xiph.org/OggOpus#ID_Header.
+  // Set magic signature.
+  std::string label = "OpusHead";
+  memcpy(header + OPUS_EXTRADATA_LABEL_OFFSET, &label, label.size());
+  // Set Opus version.
+  header[OPUS_EXTRADATA_VERSION_OFFSET] = 1;
+  // Set channel count.
+  header[OPUS_EXTRADATA_CHANNELS_OFFSET] = params.channels();
+  // Set pre-skip
+  uint16 skip = 0;
+  memcpy(header + OPUS_EXTRADATA_SKIP_SAMPLES_OFFSET, &skip, sizeof(uint16));
+  // Set original input sample rate in Hz.
+  uint32 sample_rate = params.sample_rate();
+  memcpy(header + OPUS_EXTRADATA_SAMPLE_RATE_OFFSET, &sample_rate,
+         sizeof(uint32));
+  // Set output gain in dB.
+  uint16 gain = 0;
+  memcpy(header + OPUS_EXTRADATA_GAIN_OFFSET, &gain, 2);
+
+  // Set channel mapping.
+  if (params.channels() > 2) {
+    // Also possible to have a multistream, not supported for now.
+    DCHECK_LE(params.channels(), OPUS_MAX_VORBIS_CHANNELS);
+    header[OPUS_EXTRADATA_CHANNEL_MAPPING_OFFSET] = 1;
+    // Assuming no coupled streams. This should actually be
+    // channels() - |coupled_streams|.
+    header[OPUS_EXTRADATA_NUM_STREAMS_OFFSET] = params.channels();
+    header[OPUS_EXTRADATA_NUM_COUPLED_OFFSET] = 0;
+    // Set the actual stream map.
+    memcpy(header + OPUS_EXTRADATA_STREAM_MAP_OFFSET,
+           kOpusVorbisChannelMap[params.channels() - 1], params.channels());
+  } else {
+    header[OPUS_EXTRADATA_CHANNEL_MAPPING_OFFSET] = 0;
+  }
+}
+
 static double GetFrameRate(const scoped_refptr<VideoFrame>& video_frame) {
   const double kZeroFrameRate = 0.0;
   const double kDefaultFrameRate = 30.0;
@@ -25,14 +66,32 @@
   return frame_rate;
 }
 
-WebmMuxer::WebmMuxer(VideoCodec codec, const WriteDataCB& write_data_callback)
+}  // anonymous namespace
+
+WebmMuxer::WebmMuxer(VideoCodec codec,
+                     bool has_video,
+                     bool has_audio,
+                     const WriteDataCB& write_data_callback)
     : use_vp9_(codec == kCodecVP9),
-      track_index_(0),
+      video_track_index_(0),
+      audio_track_index_(0),
+      has_video_(has_video),
+      has_audio_(has_audio),
       write_data_callback_(write_data_callback),
       position_(0) {
+  DCHECK(has_video_ || has_audio_);
   DCHECK(!write_data_callback_.is_null());
   DCHECK(codec == kCodecVP8 || codec == kCodecVP9)
       << " Only Vp8 and VP9 are supported in WebmMuxer";
+
+  segment_.Init(this);
+  segment_.set_mode(mkvmuxer::Segment::kLive);
+  segment_.OutputCues(false);
+
+  mkvmuxer::SegmentInfo* const info = segment_.GetSegmentInfo();
+  info->set_writing_app("Chrome");
+  info->set_muxing_app("Chrome");
+
   // Creation is done on a different thread than main activities.
   thread_checker_.DetachFromThread();
 }
@@ -50,54 +109,117 @@
                                bool is_key_frame) {
   DVLOG(1) << __FUNCTION__ << " - " << encoded_data->size() << "B";
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!track_index_) {
+
+  if (!video_track_index_) {
     // |track_index_|, cannot be zero (!), initialize WebmMuxer in that case.
     // http://www.matroska.org/technical/specs/index.html#Tracks
     AddVideoTrack(video_frame->visible_rect().size(),
                   GetFrameRate(video_frame));
-    first_frame_timestamp_ = timestamp;
+    if (first_frame_timestamp_.is_null())
+      first_frame_timestamp_ = timestamp;
   }
+
+  // TODO(ajose): Don't drop data. http://crbug.com/547948
+  // TODO(ajose): Update this when we support multiple tracks.
+  // http://crbug.com/528523
+  if (has_audio_ && !audio_track_index_) {
+    DVLOG(1) << __FUNCTION__ << ": delaying until audio track ready.";
+    return;
+  }
+
+  most_recent_timestamp_ =
+      std::max(most_recent_timestamp_, timestamp - first_frame_timestamp_);
   segment_.AddFrame(reinterpret_cast<const uint8_t*>(encoded_data->data()),
-                    encoded_data->size(),
-                    track_index_,
-                    (timestamp - first_frame_timestamp_).InMicroseconds() *
+                    encoded_data->size(), video_track_index_,
+                    most_recent_timestamp_.InMicroseconds() *
                         base::Time::kNanosecondsPerMicrosecond,
                     is_key_frame);
 }
 
+void WebmMuxer::OnEncodedAudio(const media::AudioParameters& params,
+                               scoped_ptr<std::string> encoded_data,
+                               base::TimeTicks timestamp) {
+  DVLOG(1) << __FUNCTION__ << " - " << encoded_data->size() << "B";
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (!audio_track_index_) {
+    AddAudioTrack(params);
+    if (first_frame_timestamp_.is_null())
+      first_frame_timestamp_ = timestamp;
+  }
+
+  // TODO(ajose): Don't drop data. http://crbug.com/547948
+  // TODO(ajose): Update this when we support multiple tracks.
+  // http://crbug.com/528523
+  if (has_video_ && !video_track_index_) {
+    DVLOG(1) << __FUNCTION__ << ": delaying until video track ready.";
+    return;
+  }
+
+  most_recent_timestamp_ =
+      std::max(most_recent_timestamp_, timestamp - first_frame_timestamp_);
+  segment_.AddFrame(reinterpret_cast<const uint8_t*>(encoded_data->data()),
+                    encoded_data->size(), audio_track_index_,
+                    most_recent_timestamp_.InMicroseconds() *
+                        base::Time::kNanosecondsPerMicrosecond,
+                    true /* is_key_frame -- always true for audio */);
+}
+
 void WebmMuxer::AddVideoTrack(const gfx::Size& frame_size, double frame_rate) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK_EQ(track_index_, 0u) << "WebmMuxer can only be initialised once.";
+  DCHECK_EQ(0u, video_track_index_)
+      << "WebmMuxer can only be initialized once.";
 
-  segment_.Init(this);
-  segment_.set_mode(mkvmuxer::Segment::kLive);
-  segment_.OutputCues(false);
-
-  mkvmuxer::SegmentInfo* const info = segment_.GetSegmentInfo();
-  info->set_writing_app("Chrome");
-  info->set_muxing_app("Chrome");
-
-  track_index_ =
+  video_track_index_ =
       segment_.AddVideoTrack(frame_size.width(), frame_size.height(), 0);
-  DCHECK_GT(track_index_, 0u);
+  DCHECK_GT(video_track_index_, 0u);
 
   mkvmuxer::VideoTrack* const video_track =
       reinterpret_cast<mkvmuxer::VideoTrack*>(
-          segment_.GetTrackByNumber(track_index_));
+          segment_.GetTrackByNumber(video_track_index_));
   DCHECK(video_track);
   video_track->set_codec_id(use_vp9_ ? mkvmuxer::Tracks::kVp9CodecId
                                      : mkvmuxer::Tracks::kVp8CodecId);
-  DCHECK_EQ(video_track->crop_right(), 0ull);
-  DCHECK_EQ(video_track->crop_left(), 0ull);
-  DCHECK_EQ(video_track->crop_top(), 0ull);
-  DCHECK_EQ(video_track->crop_bottom(), 0ull);
+  DCHECK_EQ(0ull, video_track->crop_right());
+  DCHECK_EQ(0ull, video_track->crop_left());
+  DCHECK_EQ(0ull, video_track->crop_top());
+  DCHECK_EQ(0ull, video_track->crop_bottom());
 
   video_track->set_frame_rate(frame_rate);
   video_track->set_default_duration(base::Time::kNanosecondsPerSecond /
                                     frame_rate);
   // Segment's timestamps should be in milliseconds, DCHECK it. See
   // http://www.webmproject.org/docs/container/#muxer-guidelines
-  DCHECK_EQ(segment_.GetSegmentInfo()->timecode_scale(), 1000000ull);
+  DCHECK_EQ(1000000ull, segment_.GetSegmentInfo()->timecode_scale());
+}
+
+void WebmMuxer::AddAudioTrack(const media::AudioParameters& params) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_EQ(0u, audio_track_index_)
+      << "WebmMuxer audio can only be initialised once.";
+
+  audio_track_index_ =
+      segment_.AddAudioTrack(params.sample_rate(), params.channels(), 0);
+  DCHECK_GT(audio_track_index_, 0u);
+
+  mkvmuxer::AudioTrack* const audio_track =
+      reinterpret_cast<mkvmuxer::AudioTrack*>(
+          segment_.GetTrackByNumber(audio_track_index_));
+  DCHECK(audio_track);
+  audio_track->set_codec_id(mkvmuxer::Tracks::kOpusCodecId);
+
+  DCHECK_EQ(params.sample_rate(), audio_track->sample_rate());
+  DCHECK_EQ(params.channels(), static_cast<int>(audio_track->channels()));
+
+  uint8 opus_header[OPUS_EXTRADATA_SIZE];
+  WriteOpusHeader(params, opus_header);
+
+  if (!audio_track->SetCodecPrivate(opus_header, OPUS_EXTRADATA_SIZE))
+    LOG(ERROR) << __FUNCTION__ << ": failed to set opus header.";
+
+  // Segment's timestamps should be in milliseconds, DCHECK it. See
+  // http://www.webmproject.org/docs/container/#muxer-guidelines
+  DCHECK_EQ(1000000ull, segment_.GetSegmentInfo()->timecode_scale());
 }
 
 mkvmuxer::int32 WebmMuxer::Write(const void* buf, mkvmuxer::uint32 len) {
diff --git a/media/capture/webm_muxer.h b/media/capture/webm_muxer.h
index 7196d1d4..f5171b8 100644
--- a/media/capture/webm_muxer.h
+++ b/media/capture/webm_muxer.h
@@ -21,18 +21,19 @@
 namespace media {
 
 class VideoFrame;
+class AudioParameters;
 
 // Adapter class to manage a WebM container [1], a simplified version of a
 // Matroska container [2], composed of an EBML header, and a single Segment
 // including at least a Track Section and a number of SimpleBlocks each
-// containing a single encoded video frame. WebM container has no Trailer.
-// Clients will push encoded VPx video frames one by one via OnEncodedVideo().
-// libwebm will eventually ping the WriteDataCB passed on contructor with the
-// wrapped encoded data.
-// WebmMuxer is designed for single thread use throughout.
+// containing a single encoded video or audio frame. WebM container has no
+// Trailer.
+// Clients will push encoded VPx video frames and Opus audio frames one by one
+// via OnEncoded{Video|Audio}(). libwebm will eventually ping the WriteDataCB
+// passed on contructor with the wrapped encoded data.
+// WebmMuxer is designed for use on a single thread.
 // [1] http://www.webmproject.org/docs/container/
 // [2] http://www.matroska.org/technical/specs/index.html
-// TODO(mcasas): Add support for Audio muxing.
 class MEDIA_EXPORT WebmMuxer : public NON_EXPORTED_BASE(mkvmuxer::IMkvWriter) {
  public:
   // Callback to be called when WebmMuxer is ready to write a chunk of data,
@@ -41,23 +42,32 @@
 
   // |codec| can be VP8 or VP9 and should coincide with whatever is sent in
   // OnEncodedVideo().
-  WebmMuxer(VideoCodec codec, const WriteDataCB& write_data_callback);
+  WebmMuxer(VideoCodec codec,
+            bool has_video_,
+            bool has_audio_,
+            const WriteDataCB& write_data_callback);
   ~WebmMuxer() override;
 
-  // Adds a |video_frame| with |encoded_data.data()| to WebM Segment.
+  // Functions to add video and audio frames with |encoded_data.data()|
+  // to WebM Segment.
   void OnEncodedVideo(const scoped_refptr<VideoFrame>& video_frame,
                       scoped_ptr<std::string> encoded_data,
                       base::TimeTicks timestamp,
                       bool is_key_frame);
+  void OnEncodedAudio(const media::AudioParameters& params,
+                      scoped_ptr<std::string> encoded_data,
+                      base::TimeTicks timestamp);
 
  private:
   friend class WebmMuxerTest;
 
-  // Creates and adds a new video track. Called upon receiving the first
-  // frame of a given Track, adds |frame_size| and |frame_rate| to the Segment
+  // Methods for creating and adding video and audio tracks, called upon
+  // receiving the first frame of a given Track.
+  // AddVideoTrack adds |frame_size| and |frame_rate| to the Segment
   // info, although individual frames passed to OnEncodedVideo() can have any
   // frame size.
   void AddVideoTrack(const gfx::Size& frame_size, double frame_rate);
+  void AddAudioTrack(const media::AudioParameters& params);
 
   // IMkvWriter interface.
   mkvmuxer::int32 Write(const void* buf, mkvmuxer::uint32 len) override;
@@ -73,12 +83,19 @@
   // Video Codec configured: VP9 if true, otherwise VP8 is used by default.
   const bool use_vp9_;
 
-  // A caller-side identifier to interact with |segment_|, initialised upon
-  // first frame arrival by AddVideoTrack().
-  uint64_t track_index_;
+  // Caller-side identifiers to interact with |segment_|, initialised upon
+  // first frame arrival to Add{Video, Audio}Track().
+  uint8_t video_track_index_;
+  uint8_t audio_track_index_;
 
   // Origin of times for frame timestamps.
   base::TimeTicks first_frame_timestamp_;
+  base::TimeDelta most_recent_timestamp_;
+
+  // TODO(ajose): Change these when support is added for multiple tracks.
+  // http://crbug.com/528523
+  const bool has_video_;
+  const bool has_audio_;
 
   // Callback to dump written data as being called by libwebm.
   const WriteDataCB write_data_callback_;
diff --git a/media/capture/webm_muxer_unittest.cc b/media/capture/webm_muxer_unittest.cc
index eac8a62..8b45e1df 100644
--- a/media/capture/webm_muxer_unittest.cc
+++ b/media/capture/webm_muxer_unittest.cc
@@ -7,6 +7,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/channel_layout.h"
 #include "media/base/video_frame.h"
 #include "media/capture/webm_muxer.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -16,17 +18,25 @@
 using ::testing::AtLeast;
 using ::testing::Mock;
 using ::testing::TestWithParam;
-using ::testing::Values;
+using ::testing::ValuesIn;
 using ::testing::WithArgs;
 
 namespace media {
 
-class WebmMuxerTest : public TestWithParam<VideoCodec> {
+struct kTestParams {
+  VideoCodec codec;
+  size_t num_video_tracks;
+  size_t num_audio_tracks;
+};
+
+class WebmMuxerTest : public TestWithParam<kTestParams> {
  public:
   WebmMuxerTest()
-      : webm_muxer_(
-            GetParam() /* codec */,
-            base::Bind(&WebmMuxerTest::WriteCallback, base::Unretained(this))),
+      : webm_muxer_(GetParam().codec,
+                    GetParam().num_video_tracks,
+                    GetParam().num_audio_tracks,
+                    base::Bind(&WebmMuxerTest::WriteCallback,
+                               base::Unretained(this))),
         last_encoded_length_(0),
         accumulated_position_(0) {
     EXPECT_EQ(webm_muxer_.Position(), 0);
@@ -77,6 +87,9 @@
 // This test sends two frames and checks that the WriteCallback is called with
 // appropriate params in both cases.
 TEST_P(WebmMuxerTest, OnEncodedVideoTwoFrames) {
+  if (GetParam().num_video_tracks == 0)
+    return;
+
   const gfx::Size frame_size(160, 80);
   const scoped_refptr<VideoFrame> video_frame =
       VideoFrame::CreateBlackFrame(frame_size);
@@ -118,6 +131,61 @@
             accumulated_position_);
 }
 
-INSTANTIATE_TEST_CASE_P(, WebmMuxerTest, Values(kCodecVP8, kCodecVP9));
+TEST_P(WebmMuxerTest, OnEncodedAudioTwoFrames) {
+  if (GetParam().num_audio_tracks == 0)
+    return;
+
+  int sample_rate = 48000;
+  int bits_per_sample = 16;
+  int frames_per_buffer = 480;
+  media::AudioParameters audio_params(
+      media::AudioParameters::Format::AUDIO_PCM_LOW_LATENCY,
+      media::CHANNEL_LAYOUT_MONO, sample_rate, bits_per_sample,
+      frames_per_buffer);
+
+  const std::string encoded_data("abcdefghijklmnopqrstuvwxyz");
+
+  EXPECT_CALL(*this, WriteCallback(_))
+      .Times(AtLeast(1))
+      .WillRepeatedly(
+          WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen)));
+  webm_muxer_.OnEncodedAudio(audio_params,
+                             make_scoped_ptr(new std::string(encoded_data)),
+                             base::TimeTicks::Now());
+
+  // First time around WriteCallback() is pinged a number of times to write the
+  // Matroska header, but at the end it dumps |encoded_data|.
+  EXPECT_EQ(last_encoded_length_, encoded_data.size());
+  EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_);
+  EXPECT_GE(GetWebmMuxerPosition(), static_cast<int64_t>(last_encoded_length_));
+  EXPECT_EQ(GetWebmSegmentMode(), mkvmuxer::Segment::kLive);
+
+  const int64_t begin_of_second_block = accumulated_position_;
+  EXPECT_CALL(*this, WriteCallback(_))
+      .Times(AtLeast(1))
+      .WillRepeatedly(
+          WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen)));
+  webm_muxer_.OnEncodedAudio(audio_params,
+                             make_scoped_ptr(new std::string(encoded_data)),
+                             base::TimeTicks::Now());
+
+  // The second time around the callbacks should include a SimpleBlock header,
+  // namely the track index, a timestamp and a flags byte, for a total of 6B.
+  EXPECT_EQ(last_encoded_length_, encoded_data.size());
+  EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_);
+  const uint32_t kSimpleBlockSize = 6u;
+  EXPECT_EQ(static_cast<int64_t>(begin_of_second_block + kSimpleBlockSize +
+                                 encoded_data.size()),
+            accumulated_position_);
+}
+
+const kTestParams kTestCases[] = {
+    // TODO: consider not enumerating every combination by hand.
+    {kCodecVP8, 1 /* num_video_tracks */, 0 /*num_audio_tracks*/},
+    {kCodecVP9, 1, 0},
+    {kCodecVP8, 0, 1},
+};
+
+INSTANTIATE_TEST_CASE_P(, WebmMuxerTest, ValuesIn(kTestCases));
 
 }  // namespace media
diff --git a/media/cdm/android_cdm_factory.cc b/media/cdm/android_cdm_factory.cc
deleted file mode 100644
index bf098148..0000000
--- a/media/cdm/android_cdm_factory.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/cdm/android_cdm_factory.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/thread_task_runner_handle.h"
-#include "media/base/android/media_drm_bridge.h"
-#include "media/base/key_systems.h"
-#include "url/gurl.h"
-
-namespace media {
-
-AndroidCdmFactory::AndroidCdmFactory() {}
-
-AndroidCdmFactory::~AndroidCdmFactory() {}
-
-void AndroidCdmFactory::Create(
-    const std::string& key_system,
-    const GURL& security_origin,
-    const CdmConfig& cdm_config,
-    const SessionMessageCB& session_message_cb,
-    const SessionClosedCB& session_closed_cb,
-    const LegacySessionErrorCB& legacy_session_error_cb,
-    const SessionKeysChangeCB& session_keys_change_cb,
-    const SessionExpirationUpdateCB& session_expiration_update_cb,
-    const CdmCreatedCB& cdm_created_cb) {
-  if (!security_origin.is_valid()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(cdm_created_cb, nullptr, "Invalid origin."));
-    return;
-  }
-
-  if (!MediaDrmBridge::IsKeySystemSupported(key_system)) {
-    NOTREACHED() << "Key system not supported unexpectedly: " << key_system;
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(cdm_created_cb, nullptr,
-                              "Key system not supported unexpectedly."));
-    return;
-  }
-
-  // TODO(xhwang): Currently MediaDrmBridge can only be created on the Browser
-  // UI thread. Create it here after that is fixed. See http://crbug.com/546108
-  NOTIMPLEMENTED();
-
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(cdm_created_cb, nullptr, "MediaDrmBridge cannot be created."));
-}
-
-}  // namespace media
diff --git a/media/filters/opus_audio_decoder.cc b/media/filters/opus_audio_decoder.cc
index 4095c4d..454dc29 100644
--- a/media/filters/opus_audio_decoder.cc
+++ b/media/filters/opus_audio_decoder.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 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.
 
@@ -14,6 +14,7 @@
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/decoder_buffer.h"
 #include "media/base/timestamp_constants.h"
+#include "media/filters/opus_constants.h"
 #include "third_party/opus/src/include/opus.h"
 #include "third_party/opus/src/include/opus_multistream.h"
 
@@ -29,143 +30,22 @@
 // The Opus specification is part of IETF RFC 6716:
 // http://tools.ietf.org/html/rfc6716
 
-// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
-// mappings for up to 8 channels. This information is part of the Vorbis I
-// Specification:
-// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
-static const int kMaxVorbisChannels = 8;
-
 // Maximum packet size used in Xiph's opusdec and FFmpeg's libopusdec.
 static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
 
 static void RemapOpusChannelLayout(const uint8* opus_mapping,
                                    int num_channels,
                                    uint8* channel_layout) {
-  DCHECK_LE(num_channels, kMaxVorbisChannels);
-
-  // Opus uses Vorbis channel layout.
-  const int32 num_layouts = kMaxVorbisChannels;
-  const int32 num_layout_values = kMaxVorbisChannels;
-
-  // Vorbis channel ordering for streams with >= 2 channels:
-  // 2 Channels
-  //   L, R
-  // 3 Channels
-  //   L, Center, R
-  // 4 Channels
-  //   Front L, Front R, Back L, Back R
-  // 5 Channels
-  //   Front L, Center, Front R, Back L, Back R
-  // 6 Channels (5.1)
-  //   Front L, Center, Front R, Back L, Back R, LFE
-  // 7 channels (6.1)
-  //   Front L, Front Center, Front R, Side L, Side R, Back Center, LFE
-  // 8 Channels (7.1)
-  //   Front L, Center, Front R, Side L, Side R, Back L, Back R, LFE
-  //
-  // Channel ordering information is taken from section 4.3.9 of the Vorbis I
-  // Specification:
-  // http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
-
-  // These are the FFmpeg channel layouts expressed using the position of each
-  // channel in the output stream from libopus.
-  const uint8 kFFmpegChannelLayouts[num_layouts][num_layout_values] = {
-    { 0 },
-
-    // Stereo: No reorder.
-    { 0, 1 },
-
-    // 3 Channels, from Vorbis order to:
-    //  L, R, Center
-    { 0, 2, 1 },
-
-    // 4 Channels: No reorder.
-    { 0, 1, 2, 3 },
-
-    // 5 Channels, from Vorbis order to:
-    //  Front L, Front R, Center, Back L, Back R
-    { 0, 2, 1, 3, 4 },
-
-    // 6 Channels (5.1), from Vorbis order to:
-    //  Front L, Front R, Center, LFE, Back L, Back R
-    { 0, 2, 1, 5, 3, 4 },
-
-    // 7 Channels (6.1), from Vorbis order to:
-    //  Front L, Front R, Front Center, LFE, Side L, Side R, Back Center
-    { 0, 2, 1, 6, 3, 4, 5 },
-
-    // 8 Channels (7.1), from Vorbis order to:
-    //  Front L, Front R, Center, LFE, Back L, Back R, Side L, Side R
-    { 0, 2, 1, 7, 5, 6, 3, 4 },
-  };
+  DCHECK_LE(num_channels, OPUS_MAX_VORBIS_CHANNELS);
 
   // Reorder the channels to produce the same ordering as FFmpeg, which is
   // what the pipeline expects.
-  const uint8* vorbis_layout_offset = kFFmpegChannelLayouts[num_channels - 1];
+  const uint8* vorbis_layout_offset =
+      kFFmpegChannelDecodingLayouts[num_channels - 1];
   for (int channel = 0; channel < num_channels; ++channel)
     channel_layout[channel] = opus_mapping[vorbis_layout_offset[channel]];
 }
 
-// Opus Extra Data contents:
-// - "OpusHead" (64 bits)
-// - version number (8 bits)
-// - Channels C (8 bits)
-// - Pre-skip (16 bits)
-// - Sampling rate (32 bits)
-// - Gain in dB (16 bits, S7.8)
-// - Mapping (8 bits, 0=single stream (mono/stereo) 1=Vorbis mapping,
-//            2..254: reserved, 255: multistream with no mapping)
-//
-// - if (mapping != 0)
-//    - N = totel number of streams (8 bits)
-//    - M = number of paired streams (8 bits)
-//    - C times channel origin
-//         - if (C<2*M)
-//            - stream = byte/2
-//            - if (byte&0x1 == 0)
-//                - left
-//              else
-//                - right
-//         - else
-//            - stream = byte-M
-
-// Default audio output channel layout. Used to initialize |stream_map| in
-// OpusExtraData, and passed to opus_multistream_decoder_create() when the
-// extra data does not contain mapping information. The values are valid only
-// for mono and stereo output: Opus streams with more than 2 channels require a
-// stream map.
-static const int kMaxChannelsWithDefaultLayout = 2;
-static const uint8 kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = {
-    0, 1 };
-
-// Size of the Opus extra data excluding optional mapping information.
-static const int kOpusExtraDataSize = 19;
-
-// Offset to the channel count byte in the Opus extra data.
-static const int kOpusExtraDataChannelsOffset = 9;
-
-// Offset to the pre-skip value in the Opus extra data.
-static const int kOpusExtraDataSkipSamplesOffset = 10;
-
-// Offset to the gain value in the Opus extra data.
-static const int kOpusExtraDataGainOffset = 16;
-
-// Offset to the channel mapping byte in the Opus extra data.
-static const int kOpusExtraDataChannelMappingOffset = 18;
-
-// Extra Data contains a stream map. The mapping values are in extra data beyond
-// the always present |kOpusExtraDataSize| bytes of data. The mapping data
-// contains stream count, coupling information, and per channel mapping values:
-//   - Byte 0: Number of streams.
-//   - Byte 1: Number coupled.
-//   - Byte 2: Starting at byte 2 are |extra_data->channels| uint8 mapping
-//             values.
-static const int kOpusExtraDataNumStreamsOffset = kOpusExtraDataSize;
-static const int kOpusExtraDataNumCoupledOffset =
-    kOpusExtraDataNumStreamsOffset + 1;
-static const int kOpusExtraDataStreamMapOffset =
-    kOpusExtraDataNumStreamsOffset + 2;
-
 struct OpusExtraData {
   OpusExtraData()
       : channels(0),
@@ -175,9 +55,8 @@
         num_coupled(0),
         gain_db(0),
         stream_map() {
-    memcpy(stream_map,
-           kDefaultOpusChannelLayout,
-           kMaxChannelsWithDefaultLayout);
+    memcpy(stream_map, kDefaultOpusChannelLayout,
+           OPUS_MAX_CHANNELS_WITH_DEFAULT_LAYOUT);
   }
   int channels;
   uint16 skip_samples;
@@ -185,7 +64,7 @@
   int num_streams;
   int num_coupled;
   int16 gain_db;
-  uint8 stream_map[kMaxVorbisChannels];
+  uint8 stream_map[OPUS_MAX_VORBIS_CHANNELS];
 };
 
 // Returns true when able to successfully parse and store Opus extra data in
@@ -194,28 +73,29 @@
 static bool ParseOpusExtraData(const uint8* data, int data_size,
                                const AudioDecoderConfig& config,
                                OpusExtraData* extra_data) {
-  if (data_size < kOpusExtraDataSize) {
+  if (data_size < OPUS_EXTRADATA_SIZE) {
     DLOG(ERROR) << "Extra data size is too small:" << data_size;
     return false;
   }
 
-  extra_data->channels = *(data + kOpusExtraDataChannelsOffset);
+  extra_data->channels = *(data + OPUS_EXTRADATA_CHANNELS_OFFSET);
 
-  if (extra_data->channels <= 0 || extra_data->channels > kMaxVorbisChannels) {
+  if (extra_data->channels <= 0 ||
+      extra_data->channels > OPUS_MAX_VORBIS_CHANNELS) {
     DLOG(ERROR) << "invalid channel count in extra data: "
                 << extra_data->channels;
     return false;
   }
 
   extra_data->skip_samples =
-      ReadLE16(data, data_size, kOpusExtraDataSkipSamplesOffset);
-  extra_data->gain_db = static_cast<int16>(
-      ReadLE16(data, data_size, kOpusExtraDataGainOffset));
+      ReadLE16(data, data_size, OPUS_EXTRADATA_SKIP_SAMPLES_OFFSET);
+  extra_data->gain_db =
+      static_cast<int16>(ReadLE16(data, data_size, OPUS_EXTRADATA_GAIN_OFFSET));
 
-  extra_data->channel_mapping = *(data + kOpusExtraDataChannelMappingOffset);
+  extra_data->channel_mapping = *(data + OPUS_EXTRADATA_CHANNEL_MAPPING_OFFSET);
 
   if (!extra_data->channel_mapping) {
-    if (extra_data->channels > kMaxChannelsWithDefaultLayout) {
+    if (extra_data->channels > OPUS_MAX_CHANNELS_WITH_DEFAULT_LAYOUT) {
       DLOG(ERROR) << "Invalid extra data, missing stream map.";
       return false;
     }
@@ -226,20 +106,20 @@
     return true;
   }
 
-  if (data_size < kOpusExtraDataStreamMapOffset + extra_data->channels) {
+  if (data_size < OPUS_EXTRADATA_STREAM_MAP_OFFSET + extra_data->channels) {
     DLOG(ERROR) << "Invalid stream map; insufficient data for current channel "
                 << "count: " << extra_data->channels;
     return false;
   }
 
-  extra_data->num_streams = *(data + kOpusExtraDataNumStreamsOffset);
-  extra_data->num_coupled = *(data + kOpusExtraDataNumCoupledOffset);
+  extra_data->num_streams = *(data + OPUS_EXTRADATA_NUM_STREAMS_OFFSET);
+  extra_data->num_coupled = *(data + OPUS_EXTRADATA_NUM_COUPLED_OFFSET);
 
   if (extra_data->num_streams + extra_data->num_coupled != extra_data->channels)
     DVLOG(1) << "Inconsistent channel mapping.";
 
   for (int i = 0; i < extra_data->channels; ++i)
-    extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i);
+    extra_data->stream_map[i] = *(data + OPUS_EXTRADATA_STREAM_MAP_OFFSET + i);
   return true;
 }
 
@@ -343,7 +223,7 @@
 
   const int channel_count =
       ChannelLayoutToChannelCount(config_.channel_layout());
-  if (!config_.IsValidConfig() || channel_count > kMaxVorbisChannels) {
+  if (!config_.IsValidConfig() || channel_count > OPUS_MAX_VORBIS_CHANNELS) {
     DLOG(ERROR) << "Invalid or unsupported audio stream -"
                 << " codec: " << config_.codec()
                 << " channel count: " << channel_count
@@ -383,12 +263,11 @@
     return false;
   }
 
-  uint8 channel_mapping[kMaxVorbisChannels] = {0};
-  memcpy(&channel_mapping,
-         kDefaultOpusChannelLayout,
-         kMaxChannelsWithDefaultLayout);
+  uint8 channel_mapping[OPUS_MAX_VORBIS_CHANNELS] = {0};
+  memcpy(&channel_mapping, kDefaultOpusChannelLayout,
+         OPUS_MAX_CHANNELS_WITH_DEFAULT_LAYOUT);
 
-  if (channel_count > kMaxChannelsWithDefaultLayout) {
+  if (channel_count > OPUS_MAX_CHANNELS_WITH_DEFAULT_LAYOUT) {
     RemapOpusChannelLayout(opus_extra_data.stream_map,
                            channel_count,
                            channel_mapping);
diff --git a/media/filters/opus_constants.cc b/media/filters/opus_constants.cc
new file mode 100644
index 0000000..438367d
--- /dev/null
+++ b/media/filters/opus_constants.cc
@@ -0,0 +1,57 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+#include "media/filters/opus_constants.h"
+
+namespace media {
+
+const uint8_t kDefaultOpusChannelLayout[OPUS_MAX_CHANNELS_WITH_DEFAULT_LAYOUT] =
+    {0, 1};
+
+const uint8_t kFFmpegChannelDecodingLayouts
+    [OPUS_MAX_VORBIS_CHANNELS][OPUS_MAX_VORBIS_CHANNELS] = {
+        {0},
+
+        // Stereo: No reorder.
+        {0, 1},
+
+        // 3 Channels, from Vorbis order to:
+        //  L, R, Center
+        {0, 2, 1},
+
+        // 4 Channels: No reorder.
+        {0, 1, 2, 3},
+
+        // 5 Channels, from Vorbis order to:
+        //  Front L, Front R, Center, Back L, Back R
+        {0, 2, 1, 3, 4},
+
+        // 6 Channels (5.1), from Vorbis order to:
+        //  Front L, Front R, Center, LFE, Back L, Back R
+        {0, 2, 1, 5, 3, 4},
+
+        // 7 Channels (6.1), from Vorbis order to:
+        //  Front L, Front R, Front Center, LFE, Side L, Side R, Back Center
+        {0, 2, 1, 6, 3, 4, 5},
+
+        // 8 Channels (7.1), from Vorbis order to:
+        //  Front L, Front R, Center, LFE, Back L, Back R, Side L, Side R
+        {0, 2, 1, 7, 5, 6, 3, 4},
+};
+
+const uint8_t
+    kOpusVorbisChannelMap[OPUS_MAX_VORBIS_CHANNELS][OPUS_MAX_VORBIS_CHANNELS] =
+        {
+            {0},
+            {0, 1},
+            {0, 2, 1},
+            {0, 1, 2, 3},
+            {0, 4, 1, 2, 3},
+            {0, 4, 1, 2, 3, 5},
+            {0, 4, 1, 2, 3, 5, 6},
+            {0, 6, 1, 2, 3, 4, 5, 7},
+};
+
+}  // namespace media
diff --git a/media/filters/opus_constants.h b/media/filters/opus_constants.h
new file mode 100644
index 0000000..f5ccad0
--- /dev/null
+++ b/media/filters/opus_constants.h
@@ -0,0 +1,112 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_FILTERS_OPUS_CONSTANTS_H_
+#define MEDIA_FILTERS_OPUS_CONSTANTS_H_
+
+namespace media {
+
+// The Opus specification is part of IETF RFC 6716:
+// http://tools.ietf.org/html/rfc6716
+
+// Opus Extra Data contents:
+// - "OpusHead" magic signature (64 bits)
+// - version number (8 bits)
+// - Channels C (8 bits)
+// - Pre-skip (16 bits)
+// - Sampling rate (32 bits)
+// - Gain in dB (16 bits, S7.8)
+// - Mapping (8 bits, 0=single stream (mono/stereo) 1=Vorbis mapping,
+//            2..254: reserved, 255: multistream with no mapping)
+//
+// - if (mapping != 0)
+//    - N = total number of streams (8 bits)
+//    - M = number of paired streams (8 bits)
+//    - C times channel origin
+//         - if (C<2*M)
+//            - stream = byte/2
+//            - if (byte&0x1 == 0)
+//                - left
+//              else
+//                - right
+//         - else
+//            - stream = byte-M
+
+enum {
+  // Default audio output channel layout. Used to initialize |stream_map| in
+  // OpusExtraData, and passed to opus_multistream_decoder_create() when the
+  // extra data does not contain mapping information. The values are valid only
+  // for mono and stereo output: Opus streams with more than 2 channels require
+  // a stream map.
+  OPUS_MAX_CHANNELS_WITH_DEFAULT_LAYOUT = 2,
+
+  // Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
+  // mappings for up to 8 channels. This information is part of the Vorbis I
+  // Specification:
+  // http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
+  OPUS_MAX_VORBIS_CHANNELS = 8,
+
+  // Size of the Opus extra data excluding optional mapping information.
+  OPUS_EXTRADATA_SIZE = 19,
+  // Offset for magic signature "OpusHead"
+  OPUS_EXTRADATA_LABEL_OFFSET = 0,
+  // Offset to the Opus version number
+  OPUS_EXTRADATA_VERSION_OFFSET = 8,
+  // Offset to the channel count byte in the Opus extra data
+  OPUS_EXTRADATA_CHANNELS_OFFSET = 9,
+  // Offset to the pre-skip value in the Opus extra data
+  OPUS_EXTRADATA_SKIP_SAMPLES_OFFSET = 10,
+  // Offset to the sampling rate value in the Opus extra data
+  OPUS_EXTRADATA_SAMPLE_RATE_OFFSET = 12,
+  // Offset to the gain value in the Opus extra data
+  OPUS_EXTRADATA_GAIN_OFFSET = 16,
+  // Offset to the channel mapping byte in the Opus extra data
+  OPUS_EXTRADATA_CHANNEL_MAPPING_OFFSET = 18,
+
+  // Extra Data contains a stream map, beyond the always present
+  // |OPUS_EXTRADATA_SIZE| bytes of data. The mapping data contains stream
+  // count, coupling information, and per channel mapping values:
+  //   - Byte 0: Number of streams.
+  //   - Byte 1: Number coupled.
+  //   - Byte 2: Starting at byte 2 are |extra_data->channels| uint8 mapping
+  //             values.
+  OPUS_EXTRADATA_NUM_STREAMS_OFFSET = OPUS_EXTRADATA_SIZE,
+  OPUS_EXTRADATA_NUM_COUPLED_OFFSET = OPUS_EXTRADATA_NUM_STREAMS_OFFSET + 1,
+  OPUS_EXTRADATA_STREAM_MAP_OFFSET = OPUS_EXTRADATA_NUM_STREAMS_OFFSET + 2,
+};
+
+// Vorbis channel ordering for streams with >= 2 channels:
+// 2 Channels
+//   L, R
+// 3 Channels
+//   L, Center, R
+// 4 Channels
+//   Front L, Front R, Back L, Back R
+// 5 Channels
+//   Front L, Center, Front R, Back L, Back R
+// 6 Channels (5.1)
+//   Front L, Center, Front R, Back L, Back R, LFE
+// 7 channels (6.1)
+//   Front L, Front Center, Front R, Side L, Side R, Back Center, LFE
+// 8 Channels (7.1)
+//   Front L, Center, Front R, Side L, Side R, Back L, Back R, LFE
+//
+// Channel ordering information is taken from section 4.3.9 of the Vorbis I
+// Specification:
+// http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
+extern const uint8_t
+    kDefaultOpusChannelLayout[OPUS_MAX_CHANNELS_WITH_DEFAULT_LAYOUT];
+
+// These are the FFmpeg channel layouts expressed using the position of each
+// channel in the output stream from libopus.
+extern const uint8_t kFFmpegChannelDecodingLayouts[OPUS_MAX_VORBIS_CHANNELS]
+                                                  [OPUS_MAX_VORBIS_CHANNELS];
+
+// Opus internal to Vorbis channel order mapping written in the header.
+extern const uint8_t
+    kOpusVorbisChannelMap[OPUS_MAX_VORBIS_CHANNELS][OPUS_MAX_VORBIS_CHANNELS];
+
+}  // namespace media
+
+#endif  // MEDIA_FILTERS_OPUS_CONSTANTS_H_
diff --git a/media/media.gyp b/media/media.gyp
index 2ca6e550..26760c5d 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -557,6 +557,8 @@
         'filters/jpeg_parser.h',
         'filters/opus_audio_decoder.cc',
         'filters/opus_audio_decoder.h',
+        'filters/opus_constants.cc',
+        'filters/opus_constants.h',
         'filters/source_buffer_range.cc',
         'filters/source_buffer_range.h',
         'filters/source_buffer_stream.cc',
@@ -717,12 +719,6 @@
             'capture/webm_muxer.h',
           ],
         }],
-        ['enable_browser_cdms==1', {
-          'sources': [
-            'base/browser_cdm_factory.cc',
-            'base/browser_cdm_factory.h',
-          ],
-        }],
         ['OS=="android"', {
           'dependencies': [
             'media_android_jni_headers',
@@ -1451,9 +1447,10 @@
         '../testing/gmock.gyp:gmock',
         '../testing/gtest.gyp:gtest',
         '../testing/perf/perf_test.gyp:perf_test',
+        '../third_party/libyuv/libyuv.gyp:libyuv',
         '../ui/gfx/gfx.gyp:gfx',
-        '../ui/gfx/gfx.gyp:gfx_test_support',
         '../ui/gfx/gfx.gyp:gfx_geometry',
+        '../ui/gfx/gfx.gyp:gfx_test_support',
         'media',
         'media_test_support',
         'shared_memory_support',
@@ -1842,10 +1839,10 @@
           'sources': [
             'base/android/access_unit_queue.cc',
             'base/android/access_unit_queue.h',
+            'base/android/android_cdm_factory.cc',
+            'base/android/android_cdm_factory.h',
             'base/android/audio_decoder_job.cc',
             'base/android/audio_decoder_job.h',
-            'base/android/browser_cdm_factory_android.cc',
-            'base/android/browser_cdm_factory_android.h',
             'base/android/demuxer_android.h',
             'base/android/demuxer_stream_player_params.cc',
             'base/android/demuxer_stream_player_params.h',
diff --git a/media/mojo/services/android_mojo_media_client.cc b/media/mojo/services/android_mojo_media_client.cc
index e295a73..a5ee93a 100644
--- a/media/mojo/services/android_mojo_media_client.cc
+++ b/media/mojo/services/android_mojo_media_client.cc
@@ -5,8 +5,8 @@
 #include "media/mojo/services/mojo_media_client.h"
 
 #include "base/memory/scoped_ptr.h"
+#include "media/base/android/android_cdm_factory.h"
 #include "media/base/media.h"
-#include "media/cdm/android_cdm_factory.h"
 
 namespace media {
 namespace internal {
@@ -28,4 +28,4 @@
 }
 
 }  // namespace internal
-}  // namespace media
\ No newline at end of file
+}  // namespace media
diff --git a/mojo/edk/js/waiting_callback.cc b/mojo/edk/js/waiting_callback.cc
index 0bc875dd..4d017fe 100644
--- a/mojo/edk/js/waiting_callback.cc
+++ b/mojo/edk/js/waiting_callback.cc
@@ -14,8 +14,9 @@
 
 namespace {
 
-v8::Handle<v8::String> GetHiddenPropertyName(v8::Isolate* isolate) {
-  return gin::StringToSymbol(isolate, "::mojo::js::WaitingCallback");
+v8::Handle<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) {
+  return v8::Private::ForApi(
+      isolate, gin::StringToV8(isolate, "::mojo::js::WaitingCallback"));
 }
 
 }  // namespace
@@ -56,7 +57,9 @@
   handle_wrapper_->AddCloseObserver(this);
   v8::Handle<v8::Context> context = isolate->GetCurrentContext();
   runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr();
-  GetWrapper(isolate)->SetHiddenValue(GetHiddenPropertyName(isolate), callback);
+  GetWrapper(isolate)
+      ->SetPrivate(context, GetHiddenPropertyName(isolate), callback)
+      .FromJust();
 }
 
 WaitingCallback::~WaitingCallback() {
@@ -91,7 +94,10 @@
   v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
 
   v8::Handle<v8::Value> hidden_value =
-      GetWrapper(isolate)->GetHiddenValue(GetHiddenPropertyName(isolate));
+      GetWrapper(isolate)
+          ->GetPrivate(runner_->GetContextHolder()->context(),
+                       GetHiddenPropertyName(isolate))
+          .ToLocalChecked();
   v8::Handle<v8::Function> callback;
   CHECK(gin::ConvertFromV8(isolate, hidden_value, &callback));
 
diff --git a/mojo/runner/child/BUILD.gn b/mojo/runner/child/BUILD.gn
index 0bd6786e..fe89ecb 100644
--- a/mojo/runner/child/BUILD.gn
+++ b/mojo/runner/child/BUILD.gn
@@ -25,7 +25,7 @@
     "//mojo/application/public/interfaces",
     "//mojo/gles2",
     "//mojo/message_pump",
-    "//mojo/platform_handle:for_shared_library",
+    "//mojo/platform_handle:platform_handle_impl",
     "//third_party/mojo/src/mojo/edk/system",
   ]
 }
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc
index 58a122f5..a9983f4 100644
--- a/net/base/address_tracker_linux.cc
+++ b/net/base/address_tracker_linux.cc
@@ -119,7 +119,8 @@
       connection_type_initialized_(false),
       connection_type_initialized_cv_(&connection_type_lock_),
       current_connection_type_(NetworkChangeNotifier::CONNECTION_NONE),
-      tracking_(false) {
+      tracking_(false),
+      threads_waiting_for_connection_type_initialization_(0) {
 }
 
 AddressTrackerLinux::AddressTrackerLinux(
@@ -136,7 +137,8 @@
       connection_type_initialized_(false),
       connection_type_initialized_cv_(&connection_type_lock_),
       current_connection_type_(NetworkChangeNotifier::CONNECTION_NONE),
-      tracking_(true) {
+      tracking_(true),
+      threads_waiting_for_connection_type_initialization_(0) {
   DCHECK(!address_callback.is_null());
   DCHECK(!link_callback.is_null());
 }
@@ -221,7 +223,7 @@
   {
     AddressTrackerAutoLock lock(*this, connection_type_lock_);
     connection_type_initialized_ = true;
-    connection_type_initialized_cv_.Signal();
+    connection_type_initialized_cv_.Broadcast();
   }
 
   if (tracking_) {
@@ -240,7 +242,7 @@
   AddressTrackerAutoLock lock(*this, connection_type_lock_);
   current_connection_type_ = NetworkChangeNotifier::CONNECTION_UNKNOWN;
   connection_type_initialized_ = true;
-  connection_type_initialized_cv_.Signal();
+  connection_type_initialized_cv_.Broadcast();
 }
 
 AddressTrackerLinux::AddressMap AddressTrackerLinux::GetAddressMap() const {
@@ -268,9 +270,11 @@
   base::ThreadRestrictions::ScopedAllowWait allow_wait;
   AddressTrackerAutoLock lock(*this, connection_type_lock_);
   // Make sure the initial connection type is set before returning.
+  threads_waiting_for_connection_type_initialization_++;
   while (!connection_type_initialized_) {
     connection_type_initialized_cv_.Wait();
   }
+  threads_waiting_for_connection_type_initialization_--;
   return current_connection_type_;
 }
 
@@ -467,6 +471,12 @@
   current_connection_type_ = type;
 }
 
+int AddressTrackerLinux::GetThreadsWaitingForConnectionTypeInitForTesting()
+{
+  AddressTrackerAutoLock lock(*this, connection_type_lock_);
+  return threads_waiting_for_connection_type_initialization_;
+}
+
 AddressTrackerLinux::AddressTrackerAutoLock::AddressTrackerAutoLock(
     const AddressTrackerLinux& tracker,
     base::Lock& lock)
diff --git a/net/base/address_tracker_linux.h b/net/base/address_tracker_linux.h
index 16eaad9..87e36dd 100644
--- a/net/base/address_tracker_linux.h
+++ b/net/base/address_tracker_linux.h
@@ -138,6 +138,10 @@
   // Updates current_connection_type_ based on the network list.
   void UpdateCurrentConnectionType();
 
+  // Used by AddressTrackerLinuxTest, returns the number of threads waiting
+  // for |connection_type_initialized_cv_|.
+  int GetThreadsWaitingForConnectionTypeInitForTesting();
+
   // Gets the name of an interface given the interface index |interface_index|.
   // May return empty string if it fails but should not return NULL. This is
   // overridden by tests.
@@ -165,6 +169,7 @@
   base::ConditionVariable connection_type_initialized_cv_;
   NetworkChangeNotifier::ConnectionType current_connection_type_;
   bool tracking_;
+  int threads_waiting_for_connection_type_initialization_;
 
   // Used to verify single-threaded access in non-tracking mode.
   base::ThreadChecker thread_checker_;
diff --git a/net/base/address_tracker_linux_unittest.cc b/net/base/address_tracker_linux_unittest.cc
index 694c091..53c478d 100644
--- a/net/base/address_tracker_linux_unittest.cc
+++ b/net/base/address_tracker_linux_unittest.cc
@@ -3,6 +3,9 @@
 // found in the LICENSE file.
 
 #include "base/memory/scoped_ptr.h"
+#include "base/synchronization/spin_wait.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/simple_thread.h"
 #include "net/base/address_tracker_linux.h"
 
 #include <linux/if.h>
@@ -105,6 +108,10 @@
     ignored_interfaces_.insert(interface_name);
   }
 
+  int GetThreadsWaitingForConnectionTypeInit() {
+    return tracker_->GetThreadsWaitingForConnectionTypeInitForTesting();
+  }
+
   base::hash_set<std::string> ignored_interfaces_;
   scoped_ptr<AddressTrackerLinux> tracker_;
   AddressTrackerLinux::GetInterfaceNameFunction original_get_interface_name_;
@@ -678,6 +685,53 @@
   tracker.Init();
 }
 
+class GetCurrentConnectionTypeRunner
+    : public base::DelegateSimpleThread::Delegate {
+ public:
+  explicit GetCurrentConnectionTypeRunner(AddressTrackerLinux* tracker,
+      const std::string& thread_name)
+      : tracker_(tracker), done_(true, false), thread_(this, thread_name) {
+  }
+  ~GetCurrentConnectionTypeRunner() override {}
+
+  void Run() override {
+    tracker_->GetCurrentConnectionType();
+    done_.Signal();
+  }
+
+  void Start() {
+    thread_.Start();
+  }
+
+  void VerifyCompletes() {
+    EXPECT_TRUE(done_.TimedWait(base::TimeDelta::FromSeconds(5)));
+    thread_.Join();
+  }
+
+ private:
+  AddressTrackerLinux* const tracker_;
+  base::WaitableEvent done_;
+  base::DelegateSimpleThread thread_;
+};
+
+TEST_F(AddressTrackerLinuxTest, BroadcastInit) {
+  InitializeAddressTracker(true);
+
+  GetCurrentConnectionTypeRunner runner1(tracker_.get(), "waiter_thread_1");
+  GetCurrentConnectionTypeRunner runner2(tracker_.get(), "waiter_thread_2");
+
+  runner1.Start();
+  runner2.Start();
+
+  SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(
+      GetThreadsWaitingForConnectionTypeInit() == 2);
+
+  tracker_->Init();
+
+  runner1.VerifyCompletes();
+  runner2.VerifyCompletes();
+}
+
 }  // namespace
 
 }  // namespace internal
diff --git a/net/base/network_change_notifier_mac.cc b/net/base/network_change_notifier_mac.cc
index 4468c0bc..bd1f2d8a 100644
--- a/net/base/network_change_notifier_mac.cc
+++ b/net/base/network_change_notifier_mac.cc
@@ -157,7 +157,7 @@
     base::AutoLock lock(connection_type_lock_);
     connection_type_ = connection_type;
     connection_type_initialized_ = true;
-    initial_connection_type_cv_.Signal();
+    initial_connection_type_cv_.Broadcast();
   }
 }
 
diff --git a/net/disk_cache/net_log_parameters.cc b/net/disk_cache/net_log_parameters.cc
index 8234ced..53c873f 100644
--- a/net/disk_cache/net_log_parameters.cc
+++ b/net/disk_cache/net_log_parameters.cc
@@ -53,13 +53,13 @@
 
 scoped_ptr<base::Value> NetLogSparseOperationCallback(
     int64 offset,
-    int buff_len,
+    int buf_len,
     net::NetLogCaptureMode /* capture_mode */) {
   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
   // Values can only be created with at most 32-bit integers.  Using a string
   // instead circumvents that restriction.
   dict->SetString("offset", base::Int64ToString(offset));
-  dict->SetInteger("buff_len", buff_len);
+  dict->SetInteger("buf_len", buf_len);
   return dict.Pass();
 }
 
@@ -114,8 +114,8 @@
 
 net::NetLog::ParametersCallback CreateNetLogSparseOperationCallback(
     int64 offset,
-    int buff_len) {
-  return base::Bind(&NetLogSparseOperationCallback, offset, buff_len);
+    int buf_len) {
+  return base::Bind(&NetLogSparseOperationCallback, offset, buf_len);
 }
 
 net::NetLog::ParametersCallback CreateNetLogSparseReadWriteCallback(
diff --git a/net/disk_cache/net_log_parameters.h b/net/disk_cache/net_log_parameters.h
index 6e144201..082390b9 100644
--- a/net/disk_cache/net_log_parameters.h
+++ b/net/disk_cache/net_log_parameters.h
@@ -43,7 +43,7 @@
 // operation is started.
 net::NetLog::ParametersCallback CreateNetLogSparseOperationCallback(
     int64 offset,
-    int buff_len);
+    int buf_len);
 
 // Creates a NetLog callback that returns parameters for when a read or write
 // for a sparse entry's child is started.
diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc
index 01296060..b431549f 100644
--- a/net/http/http_stream_parser_unittest.cc
+++ b/net/http/http_stream_parser_unittest.cc
@@ -146,16 +146,15 @@
 }
 
 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) {
+  // Create an empty temporary file.
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath temp_file_path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &temp_file_path));
+
   {
     ScopedVector<UploadElementReader> element_readers;
 
-    // Create an empty temporary file.
-    base::ScopedTempDir temp_dir;
-    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-    base::FilePath temp_file_path;
-    ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(),
-                                               &temp_file_path));
-
     element_readers.push_back(
         new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
                                     temp_file_path, 0, 0, base::Time()));
@@ -169,6 +168,7 @@
     ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
         "some header", body.get()));
   }
+
   // UploadFileElementReaders may post clean-up tasks on destruction.
   base::RunLoop().RunUntilIdle();
 }
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h
index db79648..5056ad1 100644
--- a/net/log/net_log_event_type_list.h
+++ b/net/log/net_log_event_type_list.h
@@ -926,7 +926,7 @@
 // For the BEGIN phase, the following parameters are attached:
 //   {
 //     "offset": <Offset at which to start reading>,
-//     "buff_len": <Bytes to read/write>,
+//     "buf_len": <Bytes to read/write>,
 //   }
 EVENT_TYPE(SPARSE_READ)
 EVENT_TYPE(SPARSE_WRITE)
@@ -945,7 +945,7 @@
 //
 // For the BEGIN phase, the following parameters are attached:
 //   {
-//     "buff_len": <Bytes to read/write>,
+//     "buf_len": <Bytes to read/write>,
 //     "offset": <Offset at which to start reading>,
 //   }
 //
diff --git a/net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc b/net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc
index 78c988d..abe86d2a 100644
--- a/net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc
+++ b/net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc
@@ -16,8 +16,12 @@
 
 }  // namespace
 
+// QUIC currently uses the draft-agl-tls-chacha20poly1305-04 ChaCha20-Poly1305
+// construction rather than RFC 7539.
 ChaCha20Poly1305Decrypter::ChaCha20Poly1305Decrypter()
-    : AeadBaseDecrypter(EVP_aead_chacha20_poly1305(), kKeySize, kAuthTagSize,
+    : AeadBaseDecrypter(EVP_aead_chacha20_poly1305_old(),
+                        kKeySize,
+                        kAuthTagSize,
                         kNoncePrefixSize) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
@@ -30,11 +34,11 @@
 bool ChaCha20Poly1305Decrypter::IsSupported() { return true; }
 
 const char* ChaCha20Poly1305Decrypter::cipher_name() const {
-  return TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305;
+  return TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_OLD;
 }
 
 uint32 ChaCha20Poly1305Decrypter::cipher_id() const {
-  return TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305;
+  return TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD;
 }
 
 }  // namespace net
diff --git a/net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc b/net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc
index 91e75d0..3d01ab9e 100644
--- a/net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc
+++ b/net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc
@@ -15,8 +15,12 @@
 
 }  // namespace
 
+// QUIC currently uses the draft-agl-tls-chacha20poly1305-04 ChaCha20-Poly1305
+// construction rather than RFC 7539.
 ChaCha20Poly1305Encrypter::ChaCha20Poly1305Encrypter()
-    : AeadBaseEncrypter(EVP_aead_chacha20_poly1305(), kKeySize, kAuthTagSize,
+    : AeadBaseEncrypter(EVP_aead_chacha20_poly1305_old(),
+                        kKeySize,
+                        kAuthTagSize,
                         kNoncePrefixSize) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index e29130a..fc68aa4c 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -301,6 +301,7 @@
       overall_connection_timeout_(QuicTime::Delta::Infinite()),
       time_of_last_received_packet_(clock_->ApproximateNow()),
       time_of_last_sent_new_packet_(clock_->ApproximateNow()),
+      last_send_for_timeout_(clock_->ApproximateNow()),
       packet_number_of_last_sent_packet_(0),
       sent_packet_manager_(
           perspective,
@@ -1002,6 +1003,7 @@
 
   ClearLastFrames();
   MaybeCloseIfTooManyOutstandingPackets();
+  MaybeProcessRevivedPacket();
 }
 
 void QuicConnection::MaybeQueueAck() {
@@ -1256,7 +1258,6 @@
 
   ++stats_.packets_processed;
   MaybeProcessUndecryptablePackets();
-  MaybeProcessRevivedPacket();
   MaybeSendInResponseToPacket();
   SetPingAlarm();
 }
@@ -1582,6 +1583,10 @@
   }
   if (packet->transmission_type == NOT_RETRANSMISSION) {
     time_of_last_sent_new_packet_ = packet_send_time;
+    if (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA &&
+        last_send_for_timeout_ <= time_of_last_received_packet_) {
+      last_send_for_timeout_ = packet_send_time;
+    }
   }
   SetPingAlarm();
   MaybeSetFecAlarm(packet_number);
@@ -2083,8 +2088,14 @@
 
 void QuicConnection::CheckForTimeout() {
   QuicTime now = clock_->ApproximateNow();
-  QuicTime time_of_last_packet = max(time_of_last_received_packet_,
-                                     time_of_last_sent_new_packet_);
+  QuicTime time_of_last_packet = QuicTime::Zero();
+  if (!FLAGS_quic_use_new_idle_timeout) {
+    time_of_last_packet =
+        max(time_of_last_received_packet_, time_of_last_sent_new_packet_);
+  } else {
+    time_of_last_packet =
+        max(time_of_last_received_packet_, last_send_for_timeout_);
+  }
 
   // |delta| can be < 0 as |now| is approximate time but |time_of_last_packet|
   // is accurate time. However, this should not change the behavior of
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 674c5ff..6a9d162 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -916,6 +916,10 @@
   // packet.
   QuicTime time_of_last_sent_new_packet_;
 
+  // The the send time of the first retransmittable packet sent after
+  // |time_of_last_received_packet_|.
+  QuicTime last_send_for_timeout_;
+
   // packet number of the last sent packet.  Packets are guaranteed to be sent
   // in packet number order.
   QuicPacketNumber packet_number_of_last_sent_packet_;
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 765b5698..e79ed5a 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -774,6 +774,27 @@
     return serialized_packet.entropy_hash;
   }
 
+  QuicPacketEntropyHash ProcessFramePacketAtLevel(QuicPacketNumber number,
+                                                  QuicFrame frame,
+                                                  EncryptionLevel level) {
+    QuicPacketHeader header;
+    header.public_header.connection_id = connection_id_;
+    header.public_header.packet_number_length = packet_number_length_;
+    header.public_header.connection_id_length = connection_id_length_;
+    header.packet_number = number;
+    QuicFrames frames;
+    frames.push_back(frame);
+    scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames));
+
+    char buffer[kMaxPacketSize];
+    size_t encrypted_length =
+        framer_.EncryptPayload(level, number, *packet, buffer, kMaxPacketSize);
+    connection_.ProcessUdpPacket(
+        kSelfAddress, kPeerAddress,
+        QuicEncryptedPacket(buffer, encrypted_length, false));
+    return encrypted_length;
+  }
+
   size_t ProcessDataPacket(QuicPacketNumber number,
                            QuicFecGroupNumber fec_group,
                            bool entropy_flag) {
@@ -810,11 +831,20 @@
   size_t ProcessFecProtectedPacket(QuicPacketNumber number,
                                    bool expect_revival,
                                    bool entropy_flag) {
+    return ProcessFecProtectedPacketAtLevel(number, 1, expect_revival,
+                                            entropy_flag, ENCRYPTION_NONE);
+  }
+
+  size_t ProcessFecProtectedPacketAtLevel(QuicPacketNumber number,
+                                          QuicFecGroupNumber fec_group,
+                                          bool expect_revival,
+                                          bool entropy_flag,
+                                          EncryptionLevel level) {
     if (expect_revival) {
       EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
     }
     EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1).RetiresOnSaturation();
-    return ProcessDataPacket(number, 1, entropy_flag);
+    return ProcessDataPacketAtLevel(number, fec_group, entropy_flag, level);
   }
 
   // Processes an FEC packet that covers the packets that would have been
@@ -824,6 +854,18 @@
                           bool expect_revival,
                           bool entropy_flag,
                           QuicPacket* packet) {
+    return ProcessFecPacketAtLevel(number, min_protected_packet, expect_revival,
+                                   entropy_flag, packet, ENCRYPTION_NONE);
+  }
+
+  // Processes an FEC packet that covers the packets that would have been
+  // received.
+  size_t ProcessFecPacketAtLevel(QuicPacketNumber number,
+                                 QuicPacketNumber min_protected_packet,
+                                 bool expect_revival,
+                                 bool entropy_flag,
+                                 QuicPacket* packet,
+                                 EncryptionLevel level) {
     if (expect_revival) {
       EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
     }
@@ -864,8 +906,8 @@
     scoped_ptr<QuicPacket> fec_packet(
         framer_.BuildFecPacket(header, data_packet->FecProtectedData()));
     char buffer[kMaxPacketSize];
-    size_t encrypted_length = framer_.EncryptPayload(
-        ENCRYPTION_NONE, number, *fec_packet, buffer, kMaxPacketSize);
+    size_t encrypted_length = framer_.EncryptPayload(level, number, *fec_packet,
+                                                     buffer, kMaxPacketSize);
 
     connection_.ProcessUdpPacket(
         kSelfAddress, kPeerAddress,
@@ -910,6 +952,14 @@
     return ProcessFramePacket(QuicFrame(frame));
   }
 
+  QuicPacketEntropyHash ProcessStopWaitingPacketAtLevel(
+      QuicPacketNumber number,
+      QuicStopWaitingFrame* frame,
+      EncryptionLevel level) {
+    return ProcessFramePacketAtLevel(number, QuicFrame(frame),
+                                     ENCRYPTION_INITIAL);
+  }
+
   QuicPacketEntropyHash ProcessGoAwayPacket(QuicGoAwayFrame* frame) {
     return ProcessFramePacket(QuicFrame(frame));
   }
@@ -3070,6 +3120,43 @@
   ProcessDataPacketAtLevel(3, 0, kEntropyFlag, ENCRYPTION_INITIAL);
 }
 
+TEST_P(QuicConnectionTest, ProcessBufferedFECGroup) {
+  // SetFromConfig is always called after construction from InitializeSession.
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+  config.set_max_undecryptable_packets(100);
+  connection_.SetFromConfig(config);
+  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+  use_tagging_decrypter();
+
+  const uint8 tag = 0x07;
+  framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+
+  // Don't send packet 1 and buffer initially encrypted packets.
+  ProcessFecProtectedPacketAtLevel(2, 1, false, !kEntropyFlag,
+                                   ENCRYPTION_INITIAL);
+  ProcessFecPacketAtLevel(3, 1, false, kEntropyFlag, nullptr,
+                          ENCRYPTION_INITIAL);
+  // Since the packets were buffered, no FEC group should be open.
+  ASSERT_EQ(0u, connection_.NumFecGroups());
+
+  // Now send non-fec protected ack packet and close the group.
+  QuicStopWaitingFrame frame = InitStopWaitingFrame(4);
+  ProcessStopWaitingPacketAtLevel(4, &frame, ENCRYPTION_INITIAL);
+
+  // Transition to the new encryption state and process another encrypted packet
+  // which should result in the original packets being processed. The missing
+  // packet should be revived before the STOP_WAITING packet is processed.
+  connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
+  connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+  connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+
+  EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(2).RetiresOnSaturation();
+  ProcessDataPacketAtLevel(5, 0, kEntropyFlag, ENCRYPTION_INITIAL);
+  const QuicConnectionStats& stats = connection_.GetStats();
+  EXPECT_EQ(1u, stats.packets_revived);
+}
+
 TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
   // SetFromConfig is always called after construction from InitializeSession.
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
@@ -3562,7 +3649,8 @@
   EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet());
 }
 
-TEST_P(QuicConnectionTest, TimeoutAfterSend) {
+TEST_P(QuicConnectionTest, OldTimeoutAfterSend) {
+  FLAGS_quic_use_new_idle_timeout = false;
   EXPECT_TRUE(connection_.connected());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
@@ -3602,7 +3690,8 @@
   EXPECT_FALSE(connection_.connected());
 }
 
-TEST_P(QuicConnectionTest, TimeoutAfterSendSilentClose) {
+TEST_P(QuicConnectionTest, OldTimeoutAfterSendSilentClose) {
+  FLAGS_quic_use_new_idle_timeout = false;
   // Same test as above, but complete a handshake which enables silent close,
   // causing no connection close packet to be sent.
   EXPECT_TRUE(connection_.connected());
@@ -3660,6 +3749,220 @@
   EXPECT_FALSE(connection_.connected());
 }
 
+TEST_P(QuicConnectionTest, TimeoutAfterSend) {
+  FLAGS_quic_use_new_idle_timeout = true;
+  EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+  connection_.SetFromConfig(config);
+  EXPECT_FALSE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_));
+
+  const QuicTime::Delta initial_idle_timeout =
+      QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1);
+  const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5);
+  QuicTime default_timeout = clock_.ApproximateNow().Add(initial_idle_timeout);
+
+  // When we send a packet, the timeout will change to 5ms +
+  // kInitialIdleTimeoutSecs.
+  clock_.AdvanceTime(five_ms);
+  SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr);
+  EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+
+  // Now send more data. This will not move the timeout becase
+  // no data has been recieved since the previous write.
+  clock_.AdvanceTime(five_ms);
+  SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr);
+  EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+
+  // The original alarm will fire.  We should not time out because we had a
+  // network event at t=5ms.  The alarm will reregister.
+  clock_.AdvanceTime(initial_idle_timeout.Subtract(five_ms).Subtract(five_ms));
+  EXPECT_EQ(default_timeout, clock_.ApproximateNow());
+  connection_.GetTimeoutAlarm()->Fire();
+  EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
+  EXPECT_TRUE(connection_.connected());
+  EXPECT_EQ(default_timeout.Add(five_ms).Add(five_ms),
+            connection_.GetTimeoutAlarm()->deadline());
+
+  // This time, we should time out.
+  EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  clock_.AdvanceTime(five_ms);
+  EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow());
+  connection_.GetTimeoutAlarm()->Fire();
+  EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
+  EXPECT_FALSE(connection_.connected());
+}
+
+TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
+  FLAGS_quic_use_new_idle_timeout = true;
+  // Same test as above, but complete a handshake which enables silent close,
+  // causing no connection close packet to be sent.
+  EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+
+  // Create a handshake message that also enables silent close.
+  CryptoHandshakeMessage msg;
+  string error_details;
+  QuicConfig client_config;
+  client_config.SetInitialStreamFlowControlWindowToSend(
+      kInitialStreamFlowControlWindowForTest);
+  client_config.SetInitialSessionFlowControlWindowToSend(
+      kInitialSessionFlowControlWindowForTest);
+  client_config.SetIdleConnectionStateLifetime(
+      QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs),
+      QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs));
+  client_config.ToHandshakeMessage(&msg);
+  const QuicErrorCode error =
+      config.ProcessPeerHello(msg, CLIENT, &error_details);
+  EXPECT_EQ(QUIC_NO_ERROR, error);
+
+  connection_.SetFromConfig(config);
+  EXPECT_TRUE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_));
+
+  const QuicTime::Delta default_idle_timeout =
+      QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs - 1);
+  const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5);
+  QuicTime default_timeout = clock_.ApproximateNow().Add(default_idle_timeout);
+
+  // When we send a packet, the timeout will change to 5ms +
+  // kInitialIdleTimeoutSecs.
+  clock_.AdvanceTime(five_ms);
+  SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr);
+  EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+
+  // Now send more data. This will not move the timeout becase
+  // no data has been recieved since the previous write.
+  clock_.AdvanceTime(five_ms);
+  SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr);
+  EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+
+  // The original alarm will fire.  We should not time out because we had a
+  // network event at t=5ms.  The alarm will reregister.
+  clock_.AdvanceTime(default_idle_timeout.Subtract(five_ms).Subtract(five_ms));
+  EXPECT_EQ(default_timeout, clock_.ApproximateNow());
+  connection_.GetTimeoutAlarm()->Fire();
+  EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
+  EXPECT_TRUE(connection_.connected());
+  EXPECT_EQ(default_timeout.Add(five_ms).Add(five_ms),
+            connection_.GetTimeoutAlarm()->deadline());
+
+  // This time, we should time out.
+  EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+  clock_.AdvanceTime(five_ms);
+  EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow());
+  connection_.GetTimeoutAlarm()->Fire();
+  EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
+  EXPECT_FALSE(connection_.connected());
+}
+
+TEST_P(QuicConnectionTest, TimeoutAfterReceive) {
+  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+  EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+  connection_.SetFromConfig(config);
+  EXPECT_FALSE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_));
+
+  const QuicTime::Delta initial_idle_timeout =
+      QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1);
+  const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5);
+  QuicTime default_timeout = clock_.ApproximateNow().Add(initial_idle_timeout);
+
+  connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin,
+                                       nullptr);
+  connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, !kFin,
+                                       nullptr);
+
+  EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+  clock_.AdvanceTime(five_ms);
+
+  // When we receive a packet, the timeout will change to 5ms +
+  // kInitialIdleTimeoutSecs.
+  QuicAckFrame ack = InitAckFrame(2);
+  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
+  ProcessAckPacket(&ack);
+
+  // The original alarm will fire.  We should not time out because we had a
+  // network event at t=5ms.  The alarm will reregister.
+  clock_.AdvanceTime(initial_idle_timeout.Subtract(five_ms));
+  EXPECT_EQ(default_timeout, clock_.ApproximateNow());
+  connection_.GetTimeoutAlarm()->Fire();
+  EXPECT_TRUE(connection_.connected());
+  EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
+  EXPECT_EQ(default_timeout.Add(five_ms),
+            connection_.GetTimeoutAlarm()->deadline());
+
+  // This time, we should time out.
+  EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  clock_.AdvanceTime(five_ms);
+  EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow());
+  connection_.GetTimeoutAlarm()->Fire();
+  EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
+  EXPECT_FALSE(connection_.connected());
+}
+
+TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
+  FLAGS_quic_use_new_idle_timeout = true;
+  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+  EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+  connection_.SetFromConfig(config);
+  EXPECT_FALSE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_));
+
+  const QuicTime::Delta initial_idle_timeout =
+      QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1);
+  connection_.SetNetworkTimeouts(
+      QuicTime::Delta::Infinite(),
+      initial_idle_timeout.Add(QuicTime::Delta::FromSeconds(1)));
+  const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5);
+  QuicTime default_timeout = clock_.ApproximateNow().Add(initial_idle_timeout);
+
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin,
+                                       nullptr);
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, !kFin,
+                                       nullptr);
+
+  EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+
+  clock_.AdvanceTime(five_ms);
+
+  // When we receive a packet, the timeout will change to 5ms +
+  // kInitialIdleTimeoutSecs.
+  QuicAckFrame ack = InitAckFrame(2);
+  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
+  ProcessAckPacket(&ack);
+
+  // The original alarm will fire.  We should not time out because we had a
+  // network event at t=5ms.  The alarm will reregister.
+  clock_.AdvanceTime(initial_idle_timeout.Subtract(five_ms));
+  EXPECT_EQ(default_timeout, clock_.ApproximateNow());
+  connection_.GetTimeoutAlarm()->Fire();
+  EXPECT_TRUE(connection_.connected());
+  EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
+  EXPECT_EQ(default_timeout.Add(five_ms),
+            connection_.GetTimeoutAlarm()->deadline());
+
+  // Now, send packets while advancing the time and verify that the connection
+  // eventually times out.
+  EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
+  for (int i = 0; i < 100 && connection_.connected(); ++i) {
+    VLOG(1) << "sending data packet";
+    connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin,
+                                         nullptr);
+    connection_.GetTimeoutAlarm()->Fire();
+    clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+  }
+  EXPECT_FALSE(connection_.connected());
+  EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
+}
+
 TEST_P(QuicConnectionTest, SendScheduler) {
   // Test that if we send a packet without delay, it is not queued.
   QuicPacket* packet = ConstructDataPacket(1, 0, !kEntropyFlag);
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc
index 767c1db..fc005c12 100644
--- a/net/quic/quic_flags.cc
+++ b/net/quic/quic_flags.cc
@@ -115,3 +115,7 @@
 // If true, only migrate QUIC connections when client address changes are
 // considered to be caused by NATs.
 bool FLAGS_quic_disable_non_nat_address_migration = true;
+
+// If true, QUIC connections will timeout when packets are not being recieved,
+// even if they are being sent.
+bool FLAGS_quic_use_new_idle_timeout = true;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h
index a0e242a..1d48642 100644
--- a/net/quic/quic_flags.h
+++ b/net/quic/quic_flags.h
@@ -36,5 +36,6 @@
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_count_unfinished_as_open_streams;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_packet_creator_prefetch;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_disable_non_nat_address_migration;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_new_idle_timeout;
 
 #endif  // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index 0d39f64..59d170778 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -9,7 +9,9 @@
 
 #include <errno.h>
 #include <openssl/bio.h>
+#include <openssl/bytestring.h>
 #include <openssl/err.h>
+#include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <openssl/ssl.h>
 #include <string.h>
@@ -82,6 +84,15 @@
 // Default size of the internal BoringSSL buffers.
 const int KDefaultOpenSSLBufferSize = 17 * 1024;
 
+// TLS extension number use for Token Binding.
+const unsigned int kTbExtNum = 30033;
+
+// Token Binding ProtocolVersions supported.
+const uint8_t kTbProtocolVersionMajor = 0;
+const uint8_t kTbProtocolVersionMinor = 3;
+const uint8_t kTbMinProtocolVersionMajor = 0;
+const uint8_t kTbMinProtocolVersionMinor = 2;
+
 void FreeX509Stack(STACK_OF(X509)* ptr) {
   sk_X509_pop_free(ptr, X509_free);
 }
@@ -194,6 +205,18 @@
     LAZY_INSTANCE_INITIALIZER;
 #endif
 
+class ScopedCBB {
+ public:
+  ScopedCBB() { CBB_zero(&cbb_); }
+  ~ScopedCBB() { CBB_cleanup(&cbb_); }
+
+  CBB* get() { return &cbb_; }
+
+ private:
+  CBB cbb_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedCBB);
+};
+
 }  // namespace
 
 class SSLClientSocketOpenSSL::SSLContext {
@@ -243,6 +266,47 @@
     SSL_CTX_set_session_cache_mode(
         ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
     SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallback);
+
+    if (!SSL_CTX_add_client_custom_ext(ssl_ctx_.get(), kTbExtNum,
+                                       &TokenBindingAddCallback,
+                                       &TokenBindingFreeCallback, nullptr,
+                                       &TokenBindingParseCallback, nullptr)) {
+      NOTREACHED();
+    }
+  }
+
+  static int TokenBindingAddCallback(SSL* ssl,
+                                     unsigned int extension_value,
+                                     const uint8_t** out,
+                                     size_t* out_len,
+                                     int* out_alert_value,
+                                     void* add_arg) {
+    DCHECK_EQ(extension_value, kTbExtNum);
+    SSLClientSocketOpenSSL* socket =
+        SSLClientSocketOpenSSL::SSLContext::GetInstance()
+            ->GetClientSocketFromSSL(ssl);
+    return socket->TokenBindingAdd(out, out_len, out_alert_value);
+  }
+
+  static void TokenBindingFreeCallback(SSL* ssl,
+                                       unsigned extension_value,
+                                       const uint8_t* out,
+                                       void* add_arg) {
+    DCHECK_EQ(extension_value, kTbExtNum);
+    OPENSSL_free(const_cast<unsigned char*>(out));
+  }
+
+  static int TokenBindingParseCallback(SSL* ssl,
+                                       unsigned int extension_value,
+                                       const uint8_t* contents,
+                                       size_t contents_len,
+                                       int* out_alert_value,
+                                       void* parse_arg) {
+    DCHECK_EQ(extension_value, kTbExtNum);
+    SSLClientSocketOpenSSL* socket =
+        SSLClientSocketOpenSSL::SSLContext::GetInstance()
+            ->GetClientSocketFromSSL(ssl);
+    return socket->TokenBindingParse(contents, contents_len, out_alert_value);
   }
 
   static int ClientCertRequestCallback(SSL* ssl, void* arg) {
@@ -431,6 +495,8 @@
       cert_verifier_(context.cert_verifier),
       cert_transparency_verifier_(context.cert_transparency_verifier),
       channel_id_service_(context.channel_id_service),
+      tb_was_negotiated_(false),
+      tb_negotiated_param_(TB_PARAM_ECDSAP256),
       ssl_(NULL),
       transport_bio_(NULL),
       transport_(transport_socket.Pass()),
@@ -607,6 +673,7 @@
   npn_proto_.clear();
 
   channel_id_sent_ = false;
+  tb_was_negotiated_ = false;
   session_pending_ = false;
   certificate_verified_ = false;
   channel_id_request_.Cancel();
@@ -704,6 +771,8 @@
   ssl_info->client_cert_sent =
       ssl_config_.send_client_cert && ssl_config_.client_cert.get();
   ssl_info->channel_id_sent = channel_id_sent_;
+  ssl_info->token_binding_negotiated = tb_was_negotiated_;
+  ssl_info->token_binding_key_param = tb_negotiated_param_;
   ssl_info->pinning_failure_log = pinning_failure_log_;
 
   AddSCTInfoToSSLInfo(ssl_info);
@@ -1099,6 +1168,11 @@
     return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION;
   }
 
+  // Check that if token binding was negotiated, then extended master secret
+  // must also be negotiated.
+  if (tb_was_negotiated_ && !SSL_get_extms_support(ssl_))
+    return ERR_SSL_PROTOCOL_ERROR;
+
   // SSL handshake is completed. If NPN wasn't negotiated, see if ALPN was.
   if (npn_status_ == kNextProtoUnsupported) {
     const uint8_t* alpn_proto = NULL;
@@ -2061,6 +2135,9 @@
 }
 
 bool SSLClientSocketOpenSSL::IsRenegotiationAllowed() const {
+  if (tb_was_negotiated_)
+    return false;
+
   if (npn_status_ == kNextProtoUnsupported)
     return ssl_config_.renego_allowed_default;
 
@@ -2161,4 +2238,83 @@
   PumpReadWriteEvents();
 }
 
+int SSLClientSocketOpenSSL::TokenBindingAdd(const uint8_t** out,
+                                            size_t* out_len,
+                                            int* out_alert_value) {
+  if (ssl_config_.token_binding_params.empty()) {
+    return 0;
+  }
+  ScopedCBB output;
+  CBB parameters_list;
+  if (!CBB_init(output.get(), 7) ||
+      !CBB_add_u8(output.get(), kTbProtocolVersionMajor) ||
+      !CBB_add_u8(output.get(), kTbProtocolVersionMinor) ||
+      !CBB_add_u8_length_prefixed(output.get(), &parameters_list)) {
+    *out_alert_value = SSL_AD_INTERNAL_ERROR;
+    return -1;
+  }
+  for (size_t i = 0; i < ssl_config_.token_binding_params.size(); ++i) {
+    if (!CBB_add_u8(&parameters_list, ssl_config_.token_binding_params[i])) {
+      *out_alert_value = SSL_AD_INTERNAL_ERROR;
+      return -1;
+    }
+  }
+  // |*out| will be freed by TokenBindingFreeCallback.
+  if (!CBB_finish(output.get(), const_cast<uint8_t**>(out), out_len)) {
+    *out_alert_value = SSL_AD_INTERNAL_ERROR;
+    return -1;
+  }
+
+  return 1;
+}
+
+int SSLClientSocketOpenSSL::TokenBindingParse(const uint8_t* contents,
+                                              size_t contents_len,
+                                              int* out_alert_value) {
+  if (completed_connect_) {
+    // Token Binding may only be negotiated on the initial handshake.
+    *out_alert_value = SSL_AD_ILLEGAL_PARAMETER;
+    return 0;
+  }
+
+  CBS extension;
+  CBS_init(&extension, contents, contents_len);
+
+  CBS parameters_list;
+  uint8_t version_major, version_minor, param;
+  if (!CBS_get_u8(&extension, &version_major) ||
+      !CBS_get_u8(&extension, &version_minor) ||
+      !CBS_get_u8_length_prefixed(&extension, &parameters_list) ||
+      !CBS_get_u8(&parameters_list, &param) || CBS_len(&parameters_list) > 0 ||
+      CBS_len(&extension) > 0) {
+    *out_alert_value = SSL_AD_DECODE_ERROR;
+    return 0;
+  }
+  // The server-negotiated version must be less than or equal to our version.
+  if (version_major > kTbProtocolVersionMajor ||
+      (version_minor > kTbProtocolVersionMinor &&
+       version_major == kTbProtocolVersionMajor)) {
+    *out_alert_value = SSL_AD_ILLEGAL_PARAMETER;
+    return 0;
+  }
+  // If the version the server negotiated is older than we support, don't fail
+  // parsing the extension, but also don't set |negotiated_|.
+  if (version_major < kTbMinProtocolVersionMajor ||
+      (version_minor < kTbMinProtocolVersionMinor &&
+       version_major == kTbMinProtocolVersionMajor)) {
+    return 1;
+  }
+
+  for (size_t i = 0; i < ssl_config_.token_binding_params.size(); ++i) {
+    if (param == ssl_config_.token_binding_params[i]) {
+      tb_negotiated_param_ = ssl_config_.token_binding_params[i];
+      tb_was_negotiated_ = true;
+      return 1;
+    }
+  }
+
+  *out_alert_value = SSL_AD_ILLEGAL_PARAMETER;
+  return 0;
+}
+
 }  // namespace net
diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h
index dbceeafa..9acb728 100644
--- a/net/socket/ssl_client_socket_openssl.h
+++ b/net/socket/ssl_client_socket_openssl.h
@@ -210,6 +210,13 @@
   void OnPrivateKeySignComplete(Error error,
                                 const std::vector<uint8_t>& signature);
 
+  int TokenBindingAdd(const uint8_t** out,
+                      size_t* out_len,
+                      int* out_alert_value);
+  int TokenBindingParse(const uint8_t* contents,
+                        size_t contents_len,
+                        int* out_alert_value);
+
   bool transport_send_busy_;
   bool transport_recv_busy_;
 
@@ -281,6 +288,8 @@
 
   // The service for retrieving Channel ID keys.  May be NULL.
   ChannelIDService* channel_id_service_;
+  bool tb_was_negotiated_;
+  TokenBindingParam tb_negotiated_param_;
 
   // OpenSSL stuff
   SSL* ssl_;
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 06be299..a9f1fde 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -2584,6 +2584,52 @@
   EXPECT_EQ(ERR_SSL_VERSION_OR_CIPHER_MISMATCH, rv);
 }
 
+TEST_F(SSLClientSocketTest, TokenBindingEnabled) {
+  SpawnedTestServer::SSLOptions ssl_options;
+  ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256);
+  ASSERT_TRUE(StartTestServer(ssl_options));
+
+  SSLConfig ssl_config;
+  ssl_config.token_binding_params.push_back(TB_PARAM_ECDSAP256);
+
+  int rv;
+  ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+  EXPECT_EQ(OK, rv);
+  SSLInfo info;
+  EXPECT_TRUE(sock_->GetSSLInfo(&info));
+  EXPECT_TRUE(info.token_binding_negotiated);
+  EXPECT_EQ(TB_PARAM_ECDSAP256, info.token_binding_key_param);
+}
+
+TEST_F(SSLClientSocketTest, TokenBindingFailsWithEmsDisabled) {
+  SpawnedTestServer::SSLOptions ssl_options;
+  ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256);
+  ssl_options.disable_extended_master_secret = true;
+  ASSERT_TRUE(StartTestServer(ssl_options));
+
+  SSLConfig ssl_config;
+  ssl_config.token_binding_params.push_back(TB_PARAM_ECDSAP256);
+
+  int rv;
+  ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+  EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
+}
+
+TEST_F(SSLClientSocketTest, TokenBindingEnabledWithoutServerSupport) {
+  SpawnedTestServer::SSLOptions ssl_options;
+  ASSERT_TRUE(StartTestServer(ssl_options));
+
+  SSLConfig ssl_config;
+  ssl_config.token_binding_params.push_back(TB_PARAM_ECDSAP256);
+
+  int rv;
+  ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+  EXPECT_EQ(OK, rv);
+  SSLInfo info;
+  EXPECT_TRUE(sock_->GetSSLInfo(&info));
+  EXPECT_FALSE(info.token_binding_negotiated);
+}
+
 // In tests requiring NPN, client_config.alpn_protos and
 // client_config.npn_protos both need to be set when using NSS, otherwise NPN is
 // disabled due to quirks of the implementation.
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index d442a47..c874e0ae 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -188,14 +188,16 @@
 
 // Combines the given SpdyFrames into the given char array and returns
 // the total length.
-int CombineFrames(const SpdyFrame** frames, int num_frames,
-                  char* buff, int buff_len) {
+int CombineFrames(const SpdyFrame** frames,
+                  int num_frames,
+                  char* buf,
+                  int buf_len) {
   int total_len = 0;
   for (int i = 0; i < num_frames; ++i) {
     total_len += frames[i]->size();
   }
-  DCHECK_LE(total_len, buff_len);
-  char* ptr = buff;
+  DCHECK_LE(total_len, buf_len);
+  char* ptr = buf;
   for (int i = 0; i < num_frames; ++i) {
     int len = frames[i]->size();
     memcpy(ptr, frames[i]->data(), len);
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h
index 7a3d272c..a73a413 100644
--- a/net/spdy/spdy_test_util_common.h
+++ b/net/spdy/spdy_test_util_common.h
@@ -101,8 +101,10 @@
 
 // Combines the given SpdyFrames into the given char array and returns
 // the total length.
-int CombineFrames(const SpdyFrame** frames, int num_frames,
-                  char* buff, int buff_len);
+int CombineFrames(const SpdyFrame** frames,
+                  int num_frames,
+                  char* buf,
+                  int buf_len);
 
 // Returns the SpdyPriority embedded in the given frame.  Returns true
 // and fills in |priority| on success.
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h
index 25a66f7..877fe744577 100644
--- a/net/ssl/ssl_config.h
+++ b/net/ssl/ssl_config.h
@@ -27,6 +27,12 @@
   SSL_PROTOCOL_VERSION_TLS1_2 = 0x0303,
 };
 
+enum TokenBindingParam {
+  TB_PARAM_RSA2048_PKCS15 = 0,
+  TB_PARAM_RSA2048_PSS = 1,
+  TB_PARAM_ECDSAP256 = 2,
+};
+
 // Default minimum protocol version.
 NET_EXPORT extern const uint16_t kDefaultSSLVersionMin;
 
@@ -123,6 +129,11 @@
   bool rc4_enabled;
 
   bool channel_id_enabled;   // True if TLS channel ID extension is enabled.
+
+  // List of Token Binding key parameters supported by the client. If empty,
+  // Token Binding will be disabled, even if token_binding_enabled is true.
+  std::vector<TokenBindingParam> token_binding_params;
+
   bool false_start_enabled;  // True if we'll use TLS False Start.
   // True if the Certificate Transparency signed_certificate_timestamp
   // TLS extension is enabled.
diff --git a/net/ssl/ssl_info.cc b/net/ssl/ssl_info.cc
index d3aae9d8..82d4a62 100644
--- a/net/ssl/ssl_info.cc
+++ b/net/ssl/ssl_info.cc
@@ -32,6 +32,8 @@
   is_issued_by_known_root = info.is_issued_by_known_root;
   client_cert_sent = info.client_cert_sent;
   channel_id_sent = info.channel_id_sent;
+  token_binding_negotiated = info.token_binding_negotiated;
+  token_binding_key_param = info.token_binding_key_param;
   handshake_type = info.handshake_type;
   public_key_hashes = info.public_key_hashes;
   signed_certificate_timestamps = info.signed_certificate_timestamps;
@@ -50,6 +52,8 @@
   is_issued_by_known_root = false;
   client_cert_sent = false;
   channel_id_sent = false;
+  token_binding_negotiated = false;
+  token_binding_key_param = TB_PARAM_ECDSAP256;
   handshake_type = HANDSHAKE_UNKNOWN;
   public_key_hashes.clear();
   signed_certificate_timestamps.clear();
diff --git a/net/ssl/ssl_info.h b/net/ssl/ssl_info.h
index 28ce82d0..b18b526 100644
--- a/net/ssl/ssl_info.h
+++ b/net/ssl/ssl_info.h
@@ -13,6 +13,7 @@
 #include "net/cert/sct_status_flags.h"
 #include "net/cert/x509_cert_types.h"
 #include "net/ssl/signed_certificate_timestamp_and_status.h"
+#include "net/ssl/ssl_config.h"
 
 namespace net {
 
@@ -82,6 +83,15 @@
   // True if a channel ID was sent to the server.
   bool channel_id_sent;
 
+  // True if Token Binding was negotiated with the server and we agreed on a
+  // version and key params.
+  bool token_binding_negotiated;
+
+  // Only valid if |token_binding_negotiated| is true. Contains the key param
+  // negotiated by the client and server in the Token Binding Negotiation TLS
+  // extension.
+  TokenBindingParam token_binding_key_param;
+
   HandshakeType handshake_type;
 
   // The hashes, in several algorithms, of the SubjectPublicKeyInfos from
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 256f3d10..0d82d6d 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -179,7 +179,6 @@
                   client_supports_stateless_rejects,
                   server_uses_stateless_rejects_if_peer_supported,
                   congestion_control_tag, auto_tune_flow_control_window));
-#if 0
               if (client_supports_stateless_rejects &&
                   server_uses_stateless_rejects_if_peer_supported) {
                 // TODO(b/23745998) Make stateless reject work with version
@@ -201,7 +200,6 @@
                     server_uses_stateless_rejects_if_peer_supported,
                     congestion_control_tag, auto_tune_flow_control_window));
               }
-#endif
             }
           }
         }
diff --git a/net/url_request/url_request_file_job_unittest.cc b/net/url_request/url_request_file_job_unittest.cc
index 06acd32..458728cd2 100644
--- a/net/url_request/url_request_file_job_unittest.cc
+++ b/net/url_request/url_request_file_job_unittest.cc
@@ -182,51 +182,55 @@
   ASSERT_TRUE(directory.CreateUniqueTempDir());
   base::FilePath path;
   ASSERT_TRUE(CreateTempFileWithContent(content, directory, &path));
-  CallbacksJobFactory factory(path, &observer_);
-  context_.set_job_factory(&factory);
 
-  scoped_ptr<URLRequest> request(context_.CreateRequest(
-      FilePathToFileURL(path), DEFAULT_PRIORITY, &delegate_));
-  if (range) {
-    ASSERT_GE(range->start, 0);
-    ASSERT_GE(range->end, 0);
-    ASSERT_LE(range->start, range->end);
-    ASSERT_LT(static_cast<unsigned int>(range->end), content.length());
-    std::string range_value =
-        base::StringPrintf("bytes=%d-%d", range->start, range->end);
-    request->SetExtraRequestHeaderByName(
-        HttpRequestHeaders::kRange, range_value, true /*overwrite*/);
+  {
+    CallbacksJobFactory factory(path, &observer_);
+    context_.set_job_factory(&factory);
+
+    scoped_ptr<URLRequest> request(context_.CreateRequest(
+        FilePathToFileURL(path), DEFAULT_PRIORITY, &delegate_));
+    if (range) {
+      ASSERT_GE(range->start, 0);
+      ASSERT_GE(range->end, 0);
+      ASSERT_LE(range->start, range->end);
+      ASSERT_LT(static_cast<unsigned int>(range->end), content.length());
+      std::string range_value =
+          base::StringPrintf("bytes=%d-%d", range->start, range->end);
+      request->SetExtraRequestHeaderByName(HttpRequestHeaders::kRange,
+                                           range_value, true /*overwrite*/);
+    }
+    request->Start();
+
+    base::RunLoop().Run();
+
+    EXPECT_FALSE(delegate_.request_failed());
+    int expected_length =
+        range ? (range->end - range->start + 1) : content.length();
+    EXPECT_EQ(delegate_.bytes_received(), expected_length);
+
+    std::string expected_content;
+    if (range) {
+      expected_content.insert(0, content, range->start, expected_length);
+    } else {
+      expected_content = content;
+    }
+    EXPECT_TRUE(delegate_.data_received() == expected_content);
+
+    ASSERT_EQ(observer_.jobs().size(), 1u);
+    ASSERT_EQ(observer_.jobs().at(0)->seek_position(),
+              range ? range->start : 0);
+
+    std::string observed_content;
+    const std::vector<std::string>& chunks =
+        observer_.jobs().at(0)->data_chunks();
+    for (std::vector<std::string>::const_iterator i = chunks.begin();
+         i != chunks.end(); ++i) {
+      observed_content.append(*i);
+    }
+    EXPECT_EQ(expected_content, observed_content);
   }
-  request->Start();
 
-  base::RunLoop loop;
-  loop.Run();
-
-  EXPECT_FALSE(delegate_.request_failed());
-  int expected_length =
-      range ? (range->end - range->start + 1) : content.length();
-  EXPECT_EQ(delegate_.bytes_received(), expected_length);
-
-  std::string expected_content;
-  if (range) {
-    expected_content.insert(0, content, range->start, expected_length);
-  } else {
-    expected_content = content;
-  }
-  EXPECT_TRUE(delegate_.data_received() == expected_content);
-
-  ASSERT_EQ(observer_.jobs().size(), 1u);
-  ASSERT_EQ(observer_.jobs().at(0)->seek_position(), range ? range->start : 0);
-
-  std::string observed_content;
-  const std::vector<std::string>& chunks =
-      observer_.jobs().at(0)->data_chunks();
-  for (std::vector<std::string>::const_iterator i = chunks.begin();
-       i != chunks.end();
-       ++i) {
-    observed_content.append(*i);
-  }
-  EXPECT_EQ(expected_content, observed_content);
+  base::RunLoop().RunUntilIdle();
 }
 
 // Helper function to make a character array filled with |size| bytes of
diff --git a/remoting/host/token_validator_base.cc b/remoting/host/token_validator_base.cc
index d1a8ee7a..a035f41 100644
--- a/remoting/host/token_validator_base.cc
+++ b/remoting/host/token_validator_base.cc
@@ -117,7 +117,15 @@
   client_cert_store = new net::ClientCertStoreNSS(
       net::ClientCertStoreNSS::PasswordDelegateFactory());
 #elif defined(OS_WIN)
-  client_cert_store = new net::ClientCertStoreWin();
+  // The network process is running as "Local Service" whose "Current User"
+  // cert store doesn't contain any certificates. Use the "Local Machine"
+  // store instead.
+  // The ACL on the private key of the machine certificate in the "Local
+  // Machine" cert store needs to allow access by "Local Service".
+  HCERTSTORE cert_store = ::CertOpenStore(
+      CERT_STORE_PROV_SYSTEM, 0, NULL,
+      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, L"MY");
+  client_cert_store = new net::ClientCertStoreWin(cert_store);
 #elif defined(OS_MACOSX)
   client_cert_store = new net::ClientCertStoreMac();
 #elif defined(USE_OPENSSL)
diff --git a/remoting/host/win/unprivileged_process_delegate.cc b/remoting/host/win/unprivileged_process_delegate.cc
index f9afd6c..ef6d6b3 100644
--- a/remoting/host/win/unprivileged_process_delegate.cc
+++ b/remoting/host/win/unprivileged_process_delegate.cc
@@ -87,23 +87,44 @@
   if (restricted_token.Init(token.Get()) != ERROR_SUCCESS)
     return false;
 
-  // Remove all privileges in the token.
-  if (restricted_token.DeleteAllPrivileges(nullptr) != ERROR_SUCCESS)
-    return false;
-
-  // Set low integrity level if supported by the OS.
   if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+    // "SeChangeNotifyPrivilege" is needed to access the machine certificate
+    // (including its private key) in the "Local Machine" cert store. This is
+    // needed for HTTPS client third-party authentication . But the presence of
+    // "SeChangeNotifyPrivilege" also allows it to open and manipulate objects
+    // owned by the same user. This risk is only mitigated by setting the
+    // process integrity level to Low, which is why it is unsafe to enable
+    // "SeChangeNotifyPrivilege" on Windows XP where we don't have process
+    // integrity to protect us.
+    std::vector<base::string16> exceptions;
+    exceptions.push_back(base::string16(L"SeChangeNotifyPrivilege"));
+
+    // Remove privileges in the token.
+    if (restricted_token.DeleteAllPrivileges(&exceptions) != ERROR_SUCCESS)
+      return false;
+
+    // Set low integrity level if supported by the OS.
     if (restricted_token.SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW)
         != ERROR_SUCCESS) {
       return false;
     }
+  } else {
+    // Remove all privileges in the token.
+    // Since "SeChangeNotifyPrivilege" is among the privileges being removed,
+    // the network process won't be able to acquire certificates from the local
+    // machine store. This means third-party authentication won't work.
+    if (restricted_token.DeleteAllPrivileges(nullptr) != ERROR_SUCCESS)
+      return false;
   }
 
   // Return the resulting token.
-  if (restricted_token.GetRestrictedToken(token_out) ==  ERROR_SUCCESS)
-    return true;
+  DWORD result = restricted_token.GetRestrictedToken(token_out);
+  if (result != ERROR_SUCCESS) {
+    LOG(ERROR) << "Failed to get the restricted token: " << result;
+    return false;
+  }
 
-  return false;
+  return true;
 }
 
 // Creates a window station with a given name and the default desktop giving
diff --git a/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
index 9aa3209..09f2d58b 100644
--- a/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
+++ b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <errno.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fcntl.h>
 #include <unistd.h>
 
 #include <vector>
diff --git a/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
index 5fdee6c4..3fe404c 100644
--- a/sandbox/linux/seccomp-bpf/syscall_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
@@ -5,6 +5,7 @@
 #include "sandbox/linux/seccomp-bpf/syscall.h"
 
 #include <asm/unistd.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/syscall.h>
diff --git a/sandbox/linux/services/yama.cc b/sandbox/linux/services/yama.cc
index 151f4bd3..274443c 100644
--- a/sandbox/linux/services/yama.cc
+++ b/sandbox/linux/services/yama.cc
@@ -4,6 +4,7 @@
 
 #include "sandbox/linux/services/yama.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <sys/prctl.h>
 #include <sys/stat.h>
diff --git a/sandbox/linux/syscall_broker/broker_host.cc b/sandbox/linux/syscall_broker/broker_host.cc
index e5957ed..8b78b1b 100644
--- a/sandbox/linux/syscall_broker/broker_host.cc
+++ b/sandbox/linux/syscall_broker/broker_host.cc
@@ -4,6 +4,7 @@
 
 #include "sandbox/linux/syscall_broker/broker_host.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
diff --git a/third_party/WebKit/.clang-format b/third_party/WebKit/.clang-format
index 11d0dcd..5b512523d 100644
--- a/third_party/WebKit/.clang-format
+++ b/third_party/WebKit/.clang-format
@@ -1 +1,6 @@
 BasedOnStyle: WebKit
+# This defaults to 'Auto'. Explicitly set it for a while, so that
+# 'vector<vector<int> >' in existing files gets formatted to
+# 'vector<vector<int>>'. ('Auto' means that clang-format will only use
+# 'int>>' if the file already contains at least one such instance.)
+Standard: Cpp11
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 5d6f81f..514bd01 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -259,6 +259,8 @@
 
 crbug.com/535408 fast/js/function-bind.html [ NeedsManualRebaseline ]
 
+crbug.com/552574 fast/js/regexp-caching.html [ NeedsManualRebaseline ]
+
 crbug.com/552456 [ Linux ] fast/mediarecorder/MediaRecorder-basic-video.html [ Pass Failure ]
 crbug.com/552456 [ Linux ] fast/mediarecorder/MediaRecorder-creation.html [ Pass Failure ]
 crbug.com/552456 [ Linux ] fast/mediarecorder/MediaRecorder-events-and-exceptions.html [ Pass Failure ]
@@ -362,10 +364,12 @@
 
 crbug.com/548904 [ Linux Win7 ] fast/writing-mode/Kusa-Makura-background-canvas.html [ Failure Pass ]
 
+crbug.com/552643 compositing/perpendicular-layer-sorting.html [ Pass Failure ]
+
 crbug.com/552433 svg/W3C-SVG-1.1/coords-units-02-b.svg [ Pass Failure ]
-crbug.com/552433 svg/dom/length-list-parser.html [ Pass Failure ]
-crbug.com/552433 svg/transforms/text-with-pattern-with-svg-transform.svg [ Pass Failure ]
-crbug.com/552433 svg/hixie/perf/006.xml [ Pass Failure ]
+crbug.com/552433 [ Linux Mac Win10 Win7 ] svg/dom/length-list-parser.html [ Failure Pass ]
+crbug.com/552433 [ Linux Mac Win10 Win7 ] svg/transforms/text-with-pattern-with-svg-transform.svg [ Failure Pass ]
+crbug.com/552433 [ Linux Mac Win10 Win7 ] svg/hixie/perf/006.xml [ Failure Pass ]
 
 crbug.com/441840 [ Mac XP ] cssom/ahem-ex-units.html [ Failure ]
 
@@ -481,6 +485,15 @@
 crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/styles/test-010.html [ Failure Crash ]
 crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html [ Failure Crash ]
 
+crbug.com/552532 [ Win10 ] fast/replaced/no-focus-ring-embed.html [ Pass Crash ]
+crbug.com/552532 [ Win10 ] fast/replaced/no-focus-ring-object.html [ Pass Crash ]
+crbug.com/552532 [ Win10 ] plugins/focus.html [ Pass Crash ]
+crbug.com/552532 [ Win10 ] plugins/keyboard-events.html [ Pass Crash ]
+crbug.com/552532 [ Win10 ] plugins/mouse-events-fixedpos.html [ Pass Crash ]
+crbug.com/552532 [ Win10 ] plugins/mouse-events.html [ Pass Crash ]
+crbug.com/552532 [ Win10 ] plugins/plugin-initiate-popup-window.html [ Pass Crash ]
+crbug.com/552532 [ Win10 ] plugins/tabindex.html [ Pass Crash ]
+
 crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html [ Failure ]
 crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html [ Failure ]
 crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/accessibility/contenteditable-caret-position.html b/third_party/WebKit/LayoutTests/accessibility/contenteditable-caret-position.html
new file mode 100644
index 0000000..7a53eb7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/accessibility/contenteditable-caret-position.html
@@ -0,0 +1,282 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<div id="main" role="main">
+
+    <div id="contenteditable-textbox" role="textbox" contenteditable="true">
+        <div id="contenteditable-line1">Line 1</div>
+        <textarea id="contenteditable-line2" rows="1" cols="40">Line 2</textarea>
+    </div>
+
+    <div id="contenteditable-div" contenteditable>
+        <p id="paragraph1">Line 1<br>
+            Line 2</p>
+        <p id="paragraph2">Line 3</p>
+    </div>
+
+</div>
+
+<script>
+    test(function()
+    {
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+
+        assert_equals(mainAccessible.selectionStart, 0);
+        assert_equals(mainAccessible.selectionEnd, 0);
+    }, "Initially there should be no selection under the main object.");
+</script>
+
+<script>
+    test(function()
+    {
+        var rootAccessible = accessibilityController.rootElement;
+
+        assert_equals(rootAccessible.selectionAnchorObject, null);
+        assert_equals(rootAccessible.selectionAnchorOffset, -1);
+        assert_equals(rootAccessible.selectionFocusObject, null);
+        assert_equals(rootAccessible.selectionFocusOffset, -1);
+    }, "Initially there should be no selection on the root object.");
+</script>
+
+<script>
+    test(function()
+    {
+        var textbox = document.getElementById("contenteditable-textbox");
+        textbox.focus();
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+
+        assert_equals(textboxAccessible.selectionStart, 0);
+        assert_equals(textboxAccessible.selectionEnd, 0);
+    }, "Moving the focus to an ARIA textbox should place the caret at its beginning.");
+</script>
+
+<script>
+    test(function()
+    {
+        var selection = window.getSelection();
+        var selectionRange = document.createRange();
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+        var line1 = document.getElementById("contenteditable-line1");
+        var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1");
+        var line1TextAccessible = line1Accessible.childAtIndex(0);
+
+        selectionRange.setStart(line1.firstChild, 1);
+        selectionRange.setEnd(line1.firstChild, 1);
+        selection.removeAllRanges();
+        selection.addRange(selectionRange);
+
+        assert_equals(textboxAccessible.selectionStart, 1);
+        assert_equals(textboxAccessible.selectionEnd, 1);
+
+        assert_equals(mainAccessible.selectionStart, 1);
+        assert_equals(mainAccessible.selectionEnd, 1);
+
+        assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible);
+        assert_equals(rootAccessible.selectionAnchorOffset, 1);
+        assert_equals(rootAccessible.selectionFocusObject, line1TextAccessible);
+        assert_equals(rootAccessible.selectionFocusOffset, 1);
+    }, "Setting a new caret position in the ARIA textbox should be reflected in the accessibility APIs.");
+</script>
+
+<script>
+    test(function()
+    {
+        var selection = window.getSelection();
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+
+        selection.removeAllRanges();
+
+        assert_equals(textboxAccessible.selectionStart, 0);
+        assert_equals(textboxAccessible.selectionEnd, 0);
+
+        assert_equals(mainAccessible.selectionStart, 0);
+        assert_equals(mainAccessible.selectionEnd, 0);
+
+        assert_equals(rootAccessible.selectionAnchorObject, null);
+        assert_equals(rootAccessible.selectionAnchorOffset, -1);
+        assert_equals(rootAccessible.selectionFocusObject, null);
+        assert_equals(rootAccessible.selectionFocusOffset, -1);
+    }, "Removing the selection should remove the caret completely.");
+</script>
+
+<script>
+    test(function()
+    {
+        var selection = window.getSelection();
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+        var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1");
+        var line1TextAccessible = line1Accessible.childAtIndex(0);
+
+        line1TextAccessible.setSelectedTextRange(2, 0);
+
+        assert_equals(textboxAccessible.selectionStart, 2);
+        assert_equals(textboxAccessible.selectionEnd, 2);
+
+        assert_equals(mainAccessible.selectionStart, 2);
+        assert_equals(mainAccessible.selectionEnd, 2);
+
+        assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible);
+        assert_equals(rootAccessible.selectionAnchorOffset, 2);
+        assert_equals(rootAccessible.selectionFocusObject, line1TextAccessible);
+        assert_equals(rootAccessible.selectionFocusOffset, 2);
+    }, "Positioning the caret using the accessibility API instead of the DOM should work.");
+</script>
+
+<script>
+    test(function()
+    {
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var line2 = document.getElementById("contenteditable-line2");
+        line2.focus();
+
+        assert_equals(textboxAccessible.selectionStart, 0);
+        assert_equals(textboxAccessible.selectionEnd, 0);
+
+        assert_equals(mainAccessible.selectionStart, 0);
+        assert_equals(mainAccessible.selectionEnd, 0);
+    }, "Moving the focus into a textarea should remove the caret from the ARIA textbox.");
+</script>
+
+<script>
+    test(function()
+    {
+        var rootAccessible = accessibilityController.rootElement;
+        var line2Accessible = accessibilityController.focusedElement;
+
+        assert_equals(rootAccessible.selectionAnchorObject, line2Accessible);
+        assert_equals(rootAccessible.selectionAnchorOffset, 0);
+        assert_equals(rootAccessible.selectionFocusObject, line2Accessible);
+        assert_equals(rootAccessible.selectionFocusOffset, 0);
+
+        assert_equals(line2Accessible.selectionStart, 0);
+        assert_equals(line2Accessible.selectionEnd, 0);
+    }, "Standard text fields start with the caret at the beginning of their contents.");
+</script>
+
+<script>
+    test(function()
+    {
+        var line2 = document.getElementById("contenteditable-line2");
+        var line2Accessible = accessibilityController.focusedElement;
+
+        line2.setSelectionRange(3, 3);
+
+        assert_equals(line2Accessible.selectionStart, 3);
+        assert_equals(line2Accessible.selectionEnd, 3);
+    }, "Setting a new caret position in the textarea should be exposed in the accessibility APIs.");
+</script>
+
+<script>
+    test(function()
+    {
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+        var line2Accessible = accessibilityController.focusedElement;
+
+        assert_equals(textboxAccessible.selectionStart, 3);
+        assert_equals(textboxAccessible.selectionEnd, 3);
+
+        assert_equals(mainAccessible.selectionStart, 3);
+        assert_equals(mainAccessible.selectionEnd, 3);
+
+        assert_equals(rootAccessible.selectionAnchorObject, line2Accessible);
+        assert_equals(rootAccessible.selectionAnchorOffset, 3);
+        assert_equals(rootAccessible.selectionFocusObject, line2Accessible);
+        assert_equals(rootAccessible.selectionFocusOffset, 3);
+    }, "Offsets in text fields should be reported from the beginning of the field and not from the top of the container.");
+</script>
+
+<script>
+    test(function()
+    {
+        var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1");
+        var line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2");
+
+        assert_equals(line1Accessible.selectionAnchorObject, line2Accessible);
+        assert_equals(line1Accessible.selectionAnchorOffset, 3);
+        assert_equals(line1Accessible.selectionFocusObject, line2Accessible);
+        assert_equals(line1Accessible.selectionFocusOffset, 3);
+        assert_equals(line2Accessible.selectionAnchorObject, line2Accessible);
+        assert_equals(line2Accessible.selectionAnchorOffset, 3);
+        assert_equals(line2Accessible.selectionFocusObject, line2Accessible);
+        assert_equals(line2Accessible.selectionFocusOffset, 3);
+    }, "The caret position should be retrievable from any object.");
+</script>
+
+<script>
+    test(function()
+    {
+        var selection = window.getSelection();
+        var selectionRange = document.createRange();
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+
+        var contenteditable = document.getElementById("contenteditable-div");
+        contenteditable.focus();
+        // The offset from the beginning of the main div to the first character of
+        // contenteditable-div.
+        var mainOffset = 9;
+        // The offset from the newline character between the two lines of the
+        // first paragraph to the first character of its second line.
+        // (Needed for skipping wide space.)
+        var line2Offset = 13;
+
+        var line1 = document.getElementById("paragraph1").firstChild;
+        var line2 = document.getElementById("paragraph1").lastChild;
+        var line3 = document.getElementById("paragraph2").firstChild;
+        var contenteditableLines = [ line1, line2, line3 ];
+        var contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div");
+
+        for (var lineNumber = 0; lineNumber < 3; ++lineNumber) {
+            var lineOffset = lineNumber * 7;
+            // Paragraphs should be separated by an empty line.
+            if (lineNumber == 2)
+                ++lineOffset;
+
+            for (var characterOffset = 0; characterOffset < 7; ++characterOffset) {
+                // Any widespace in the DOM should be stripped out.
+                var selectionOffset = characterOffset;
+                if (lineNumber == 1)
+                    selectionOffset += line2Offset;
+                var caretPosition = lineOffset + characterOffset;
+
+                selectionRange.setStart(contenteditableLines[lineNumber], selectionOffset);
+                selectionRange.setEnd(contenteditableLines[lineNumber], selectionOffset);
+                selection.removeAllRanges();
+                selection.addRange(selectionRange);
+
+                assert_equals(contenteditableAccessible.selectionStart, caretPosition);
+                assert_equals(contenteditableAccessible.selectionEnd, caretPosition);
+
+                assert_equals(mainAccessible.selectionStart,
+                    mainOffset + caretPosition);
+                assert_equals(mainAccessible.selectionEnd,
+                    mainOffset + caretPosition);
+
+                assert_equals(rootAccessible.selectionAnchorObject.stringValue,
+                    "AXValue: " + contenteditableLines[lineNumber].textContent.trim());
+                assert_equals(rootAccessible.selectionAnchorOffset,
+                    characterOffset);
+                assert_equals(rootAccessible.selectionFocusObject.stringValue,
+                    "AXValue: " + contenteditableLines[lineNumber].textContent.trim());
+                assert_equals(rootAccessible.selectionFocusOffset,
+                    characterOffset);
+            }
+        }
+
+    }, "Test moving the caret across two paragraphs.");
+</script>
+
+<script>
+    if (window.testRunner)
+        document.getElementById("main").style.display = "none";;
+</script>
diff --git a/third_party/WebKit/LayoutTests/accessibility/contenteditable-line-for-index-expected.txt b/third_party/WebKit/LayoutTests/accessibility/contenteditable-line-for-index-expected.txt
deleted file mode 100644
index e361c58..0000000
--- a/third_party/WebKit/LayoutTests/accessibility/contenteditable-line-for-index-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-This tests that the line number of a character offset is computed correctly for content editable elements.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS axEditable.lineForIndex(index) is 0
-PASS axEditable.lineForIndex(index) is 0
-PASS axEditable.lineForIndex(index) is 0
-PASS axEditable.lineForIndex(index) is 0
-PASS axEditable.lineForIndex(index) is 0
-PASS axEditable.lineForIndex(index) is 0
-PASS axEditable.lineForIndex(index) is 0
-PASS axEditable.lineForIndex(index) is 1
-PASS axEditable.lineForIndex(index) is 1
-PASS axEditable.lineForIndex(index) is 1
-PASS axEditable.lineForIndex(index) is 1
-PASS axEditable.lineForIndex(index) is 1
-PASS axEditable.lineForIndex(index) is 1
-PASS axEditable.lineForIndex(index) is 1
-PASS axEditable.lineForIndex(index) is 2
-PASS axEditable.lineForIndex(index) is 2
-PASS axEditable.lineForIndex(index) is 2
-PASS axEditable.lineForIndex(index) is 2
-PASS axEditable.lineForIndex(index) is 2
-PASS axEditable.lineForIndex(index) is 2
-PASS axEditable.lineForIndex(index) is 2
-PASS textLength is 20
-PASS axEditable.lineForIndex(textLength) is 2
-PASS successfullyParsed is true
-
-TEST COMPLETE
-line 1
-line 2
-line 3
diff --git a/third_party/WebKit/LayoutTests/accessibility/contenteditable-line-for-index.html b/third_party/WebKit/LayoutTests/accessibility/contenteditable-line-for-index.html
deleted file mode 100644
index fe61c29..0000000
--- a/third_party/WebKit/LayoutTests/accessibility/contenteditable-line-for-index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <script src="../resources/js-test.js"></script>
-  </head>
-  <body>
-
-    <div id="editable-div" contenteditable>
-      <div>line 1</div>
-      <p>line 2<br>line 3</p>
-    </div>
-
-    <script>
-        description("This tests that the line number of a character offset is computed correctly for content editable elements.");
-
-        if (window.accessibilityController) {
-
-            var div = document.getElementById("editable-div");
-            div.focus();
-            var axEditable = accessibilityController.focusedElement;
-
-            for (var line = 0; line < 3; ++line) {
-                for (var character = 0; character < 7; ++character) {
-                    var index = line * 7 + character;
-                    shouldBeEqualToNumber("axEditable.lineForIndex(index)", line);
-                }
-            }
-
-            // Placing the caret after the last character should not change the line.
-            var textLength = div.innerText.length;
-            shouldBeEqualToNumber("textLength", 20);
-            shouldBeEqualToNumber("axEditable.lineForIndex(textLength)", 2);
-
-        }
-    </script>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/accessibility/contenteditable-selection.html b/third_party/WebKit/LayoutTests/accessibility/contenteditable-selection.html
new file mode 100644
index 0000000..7879baa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/accessibility/contenteditable-selection.html
@@ -0,0 +1,257 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<div id="main" role="main">
+
+    <div id="contenteditable-textbox" role="textbox" contenteditable="true">
+        <div id="contenteditable-line1">Line 1</div>
+        <textarea id="contenteditable-line2" rows="1" cols="40">Line 2</textarea>
+    </div>
+
+    <div id="contenteditable-div" contenteditable>
+        <p id="paragraph1">Line 1<br>Line 2</p>
+        <p id="paragraph2">Line 3</p>
+    </div>
+
+</div>
+
+<script>
+    test(function()
+    {
+        var selection = window.getSelection();
+        var selectionRange = document.createRange();
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+
+        var textbox = document.getElementById("contenteditable-textbox");
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1");
+        var line1TextAccessible = line1Accessible.childAtIndex(0);
+
+        // Select the entire contents of the outer ARIA textbox.
+        // These include another ARIA textbox and a textarea node
+        // taking up three lines.
+        textbox.focus();
+        selectionRange.selectNodeContents(textbox);
+        selection.removeAllRanges();
+        selection.addRange(selectionRange);
+
+        assert_equals(textboxAccessible.selectionStart, 0);
+        // 7 for the "Line 1" text div + 1 for the textarea node.
+        // (The textarea node should be treated as a single unit.)
+        assert_equals(textboxAccessible.selectionEnd, 8);
+
+        // Selection offsets should be the same when retrieved from the parent object.
+        assert_equals(mainAccessible.selectionStart, 0);
+        assert_equals(mainAccessible.selectionEnd, 8);
+
+        assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible);
+        assert_equals(rootAccessible.selectionAnchorOffset, 0);
+        assert_equals(rootAccessible.selectionFocusObject, textboxAccessible);
+        assert_equals(rootAccessible.selectionFocusOffset, 8);
+    }, "Test selectNodeContents on an ARIA textbox.");
+</script>
+
+<script>
+    test(function()
+    {
+        var selection = window.getSelection();
+        var selectionRange = document.createRange();
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+
+        var contenteditable = document.getElementById("contenteditable-div");
+        var line1 = document.getElementById("paragraph1").firstChild;
+        var line3 = document.getElementById("paragraph2").firstChild;
+        var contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div");
+
+        // Select the entire contents of the second content editable.
+        contenteditable.focus();
+        selectionRange.selectNodeContents(contenteditable);
+        selection.removeAllRanges();
+        selection.addRange(selectionRange);
+
+        assert_equals(contenteditableAccessible.selectionStart, 0);
+        assert_equals(contenteditableAccessible.selectionEnd, 21);
+
+        // 7 for line1 + 1 for the textarea + 1 for the blank line.
+        assert_equals(mainAccessible.selectionStart, 9);
+        assert_equals(mainAccessible.selectionEnd, 30);
+
+        assert_equals(rootAccessible.selectionAnchorObject.stringValue,
+            "AXValue: " + line1.textContent);
+        assert_equals(rootAccessible.selectionAnchorOffset, 0);
+        assert_equals(rootAccessible.selectionFocusObject.stringValue,
+            "AXValue: " + line3.textContent);
+        assert_equals(rootAccessible.selectionFocusOffset, 6);
+    }, "Test selectNodeContents on a contenteditable.");
+</script>
+
+<script>
+    test(function()
+    {
+        var selection = window.getSelection();
+        var selectionRange = document.createRange();
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var line1 = document.getElementById("contenteditable-line1");
+        var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1");
+        var line1TextAccessible = line1Accessible.childAtIndex(0);
+
+        // Select only the first line of the ARIA textbox.
+        selectionRange.setStart(line1.firstChild, 0);
+        selectionRange.setEnd(line1.firstChild, 6);
+        selection.removeAllRanges();
+        selection.addRange(selectionRange);
+
+        assert_equals(textboxAccessible.selectionStart, 0);
+        assert_equals(textboxAccessible.selectionEnd, 6);
+
+        assert_equals(mainAccessible.selectionStart, 0);
+        assert_equals(mainAccessible.selectionEnd, 6);
+
+        assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible);
+        assert_equals(rootAccessible.selectionAnchorOffset, 0);
+        assert_equals(rootAccessible.selectionFocusObject, line1TextAccessible);
+        assert_equals(rootAccessible.selectionFocusOffset, 6);
+    }, "The effects of the setStart and setEnd methods should be reflected in the accessibility API.");
+</script>
+
+<script>
+    test(function()
+    {
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var rootAccessible = accessibilityController.rootElement;
+        var line2 = document.getElementById("contenteditable-line2");
+        var line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2");
+
+        line2.focus();
+
+        // The selection should have been removed from the line1 div
+        // due to the focus being moved.
+        assert_equals(textboxAccessible.selectionStart, 0);
+        assert_equals(textboxAccessible.selectionEnd, 0);
+        assert_equals(rootAccessible.selectionAnchorObject, line2Accessible);
+        assert_equals(rootAccessible.selectionAnchorOffset, 0);
+        assert_equals(rootAccessible.selectionFocusObject, line2Accessible);
+        assert_equals(rootAccessible.selectionFocusOffset, 0);
+    }, "Verify that changing the focus removes the selection.");
+</script>
+
+<script>
+    test(function()
+    {
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+        var line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2");
+        var line2 = document.getElementById("contenteditable-line2");
+
+        // Select only the second line of the ARIA textbox, that is,
+        // the one found in the textarea.
+        line2.setSelectionRange(0, line2.textLength);
+
+        assert_equals(line2Accessible.selectionStart, 0);
+        assert_equals(line2Accessible.selectionEnd, line2.textLength);
+
+        // Unlike for other elements, offsets in text fields should be
+        // reported from the beginning of the field and not from the top of the
+        // container on which the API was called.
+        assert_equals(textboxAccessible.selectionStart, 0);
+        assert_equals(textboxAccessible.selectionEnd, line2.textLength);
+
+        assert_equals(mainAccessible.selectionStart, 0);
+        assert_equals(mainAccessible.selectionEnd, line2.textLength);
+
+        assert_equals(rootAccessible.selectionAnchorObject, line2Accessible);
+        assert_equals(rootAccessible.selectionAnchorOffset, 0);
+        assert_equals(rootAccessible.selectionFocusObject, line2Accessible);
+        assert_equals(rootAccessible.selectionFocusOffset, line2.textLength);
+    }, "The effects of the textarea.setSelectionRange method should be reflected in the accessibility API.");
+</script>
+
+<script>
+    test(function()
+    {
+        var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox");
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+        var line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2");
+
+        // Selection can also be set via the accessibility API.
+        line2Accessible.setSelectedTextRange(2, 3);
+
+        assert_equals(line2Accessible.selectionStart, 2);
+        assert_equals(line2Accessible.selectionEnd, 5);
+
+        assert_equals(textboxAccessible.selectionStart, 2);
+        assert_equals(textboxAccessible.selectionEnd, 5);
+
+        assert_equals(mainAccessible.selectionStart, 2);
+        assert_equals(mainAccessible.selectionEnd, 5);
+
+        assert_equals(rootAccessible.selectionAnchorObject, line2Accessible);
+        assert_equals(rootAccessible.selectionAnchorOffset, 2);
+        assert_equals(rootAccessible.selectionFocusObject, line2Accessible);
+        assert_equals(rootAccessible.selectionFocusOffset, 5);
+    }, "Test the setSelectedTextRange accessibility API function.");
+</script>
+
+<script>
+    test(function()
+    {
+        var selection = window.getSelection();
+        var selectionRange = document.createRange();
+        var mainAccessible = accessibilityController.accessibleElementById("main");
+        var rootAccessible = accessibilityController.rootElement;
+
+        var contenteditable = document.getElementById("contenteditable-div");
+        var line1 = document.getElementById("paragraph1").firstChild;
+        var line2 = document.getElementById("paragraph1").lastChild;
+        var line3 = document.getElementById("paragraph2").firstChild;
+        var contenteditableLines = [ line1, line2, line3 ];
+        var contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div");
+
+        // Select entire lines in the second content editable.
+        for (var testCase = 0; testCase < 2; ++testCase) {
+
+            for (var i = 0; i < contenteditableLines.length; ++i) {
+                var start = i * 7;
+                var end = i * 7 + 6;
+                if (i == 2) {
+                    // Paragraphs have a blank line between them.
+                    ++start;
+                    ++end;
+                }
+
+                selectionRange.selectNode(contenteditableLines[i]);
+                selection.removeAllRanges();
+                selection.addRange(selectionRange);
+
+                assert_equals(contenteditableAccessible.selectionStart, start);
+                assert_equals(contenteditableAccessible.selectionEnd, end);
+
+                assert_equals(mainAccessible.selectionStart, start + 9);
+                assert_equals(mainAccessible.selectionEnd, end + 9);
+
+                assert_equals(rootAccessible.selectionAnchorObject.stringValue,
+                    "AXValue: " + contenteditableLines[i].textContent);
+                assert_equals(rootAccessible.selectionAnchorOffset, 0);
+                assert_equals(rootAccessible.selectionFocusObject.stringValue,
+                    "AXValue: " + contenteditableLines[i].textContent);
+                assert_equals(rootAccessible.selectionFocusOffset, 6);
+            }
+
+            // For a sanity check, try the same test with contenteditable="false".
+            contenteditable.contenteditable = false;
+        }
+
+    }, "The effects of the selectNode method should be reflected in the accessibility API.");
+</script>
+
+<script>
+    if (window.testRunner)
+        document.getElementById("main").style.display = "none";;
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding-exact-fit-expected.txt b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding-exact-fit-expected.txt
new file mode 100644
index 0000000..29e989e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding-exact-fit-expected.txt
@@ -0,0 +1,6 @@
+When its first line needs a column break, we should push the entire block to the next column, also when it just barely fits.
+
+There should be a blue square below.
+
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding-exact-fit.html b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding-exact-fit.html
new file mode 100644
index 0000000..005f1210
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding-exact-fit.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script src="../../resources/check-layout.js"></script>
+<p>When its first line needs a column break, we should push the entire block to the next column, also when it just barely fits.</p>
+<p>There should be a blue square below.</p>
+<div id="multicol" style="position:relative; -webkit-columns:2; -webkit-column-gap:0; column-fill:auto; width:80px; height:40px; line-height:30px;">
+    <div style="height:10px;"></div>
+    <div data-offset-x="40" data-offset-y="0" style="padding-top:10px; background:blue;"><br></div>
+</div>
+<script>
+    checkLayout("#multicol");
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/selector-line-sourcemap-header-deprecated.html b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/selector-line-sourcemap-header-deprecated.html
index dccab1a5..ac7c1b5 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/selector-line-sourcemap-header-deprecated.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/selector-line-sourcemap-header-deprecated.html
@@ -15,7 +15,7 @@
 function test()
 {
     WebInspector.settingForTest("cssSourceMapsEnabled").set(true);
-    InspectorTest.addSniffer(WebInspector.SASSSourceMapping.prototype, "_bindUISourceCode", step1);
+    InspectorTest.addSniffer(WebInspector.CSSWorkspaceBinding.prototype, "pushSourceMapping", step1);
     InspectorTest.evaluateInPage("addStylesheet()");
 
     function step1()
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html
index ed5a470..f74f4bb 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html
@@ -25,7 +25,6 @@
     {
         InspectorTest.addResult("Loading raw css with mapping...");
         InspectorTest.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, styleSheetAdded);
-        InspectorTest.addSniffer(WebInspector.SASSSourceMapping.prototype, "_bindUISourceCode", afterBind);
         InspectorTest.evaluateInPage("loadCSS()");
     }
 
@@ -37,6 +36,7 @@
         var header = event.data;
         var cssLocation = new WebInspector.CSSLocation(header.cssModel(), header.id, header.sourceURL, 0, 1);
         liveLocation = WebInspector.cssWorkspaceBinding.createLiveLocation(cssLocation, function() {});
+        InspectorTest.addSniffer(WebInspector.CSSWorkspaceBinding.prototype, "pushSourceMapping", afterBind);
         dumpLiveLocation();
     }
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/security-test.js
new file mode 100644
index 0000000..ce3b0c2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security-test.js
@@ -0,0 +1,24 @@
+var initialize_SecurityTest = function() {
+
+InspectorTest.preloadPanel("security");
+
+InspectorTest.dumpSecurityPanelSidebarOrigins = function() {
+    for (var key in WebInspector.SecurityPanelSidebarTree.OriginGroupName) {
+        var originGroupName = WebInspector.SecurityPanelSidebarTree.OriginGroupName[key];
+        var originTitles = WebInspector.SecurityPanel._instance()._sidebarTree._originGroups.get(originGroupName).childrenListElement.getElementsByClassName("title");
+        if (originTitles.length > 0) {
+            InspectorTest.addResult("Group: " + originGroupName);
+            for (var originTitle of originTitles)
+                InspectorTest.dumpDeepInnerHTML(originTitle);
+        }
+    }
+}
+
+/**
+ * @param {!WebInspector.NetworkRequest} request
+ */
+InspectorTest.dispatchRequestFinished = function(request) {
+    InspectorTest.networkManager.dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestFinished, request);
+}
+
+}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blank-origins-not-shown.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blank-origins-not-shown.html
index 6e760de7..e8f725e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blank-origins-not-shown.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blank-origins-not-shown.html
@@ -1,28 +1,17 @@
 <html>
 <head>
 <script src="../inspector-test.js"></script>
+<script src="../security-test.js"></script>
 <script>
-var initialize_SecurityTest = function() {
-    InspectorTest.preloadPanel("security");
-}
-
 function test()
 {
-    var targets = WebInspector.targetManager.targets();
-    var request1 = new WebInspector.NetworkRequest(targets[0], 0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
-    targets[0].model(WebInspector.NetworkManager).dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestFinished, request1);
-    var request2 = new WebInspector.NetworkRequest(targets[0], 0, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAKCAYAAABmBXS+AAAAPElEQVR42mNgQAMZGRn/GfABkIIdO3b8x6kQpgAEsCpEVgADKAqxKcBQCCLwARRFIBodYygiyiSCighhAO4e2jskhrm3AAAAAElFTkSuQmCC", "https://foo.test", 0, 0, null);
-    targets[0].model(WebInspector.NetworkManager).dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestFinished, request2);
+    var request1 = new WebInspector.NetworkRequest(InspectorTest.mainTarget, 0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
+    InspectorTest.dispatchRequestFinished(request1);
 
-    for (var key in WebInspector.SecurityPanelSidebarTree.OriginGroupName) {
-        var originGroupName = WebInspector.SecurityPanelSidebarTree.OriginGroupName[key];
-        var originTitles = WebInspector.SecurityPanel._instance()._sidebarTree._originGroups.get(originGroupName).childrenListElement.getElementsByClassName("title");
-        if (originTitles.length > 0) {
-            InspectorTest.addResult("Group: " + originGroupName);
-            for (var originTitle of originTitles)
-                InspectorTest.dumpDeepInnerHTML(originTitle);
-        }
-    }
+    var request2 = new WebInspector.NetworkRequest(InspectorTest.mainTarget, 0, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAKCAYAAABmBXS+AAAAPElEQVR42mNgQAMZGRn/GfABkIIdO3b8x6kQpgAEsCpEVgADKAqxKcBQCCLwARRFIBodYygiyiSCighhAO4e2jskhrm3AAAAAElFTkSuQmCC", "https://foo.test", 0, 0, null);
+    InspectorTest.dispatchRequestFinished(request2);
+
+    InspectorTest.dumpSecurityPanelSidebarOrigins();
 
     InspectorTest.completeTest();
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/failed-request.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/failed-request.html
index 63c60290..36c4fb1 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/failed-request.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/failed-request.html
@@ -1,30 +1,19 @@
 <html>
 <head>
 <script src="../inspector-test.js"></script>
+<script src="../security-test.js"></script>
 <script>
-var initialize_SecurityTest = function() {
-    InspectorTest.preloadPanel("security");
-}
-
 function test()
 {
-    var targets = WebInspector.targetManager.targets();
-    var request1 = new WebInspector.NetworkRequest(targets[0], 0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
+    var request1 = new WebInspector.NetworkRequest(InspectorTest.mainTarget, 0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
     request1.setSecurityState(SecurityAgent.SecurityState.Secure);
-    targets[0].model(WebInspector.NetworkManager).dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestFinished, request1);
-    var request2 = new WebInspector.NetworkRequest(targets[0], 0, "https://does-not-resolve.test", "https://does-not-resolve.test", 0, 0, null);
-    // Leave the security state unknown.
-    targets[0].model(WebInspector.NetworkManager).dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestFinished, request2);
+    InspectorTest.dispatchRequestFinished(request1);
 
-    for (var key in WebInspector.SecurityPanelSidebarTree.OriginGroupName) {
-        var originGroupName = WebInspector.SecurityPanelSidebarTree.OriginGroupName[key];
-        var originTitles = WebInspector.SecurityPanel._instance()._sidebarTree._originGroups.get(originGroupName).childrenListElement.getElementsByClassName("title");
-        if (originTitles.length > 0) {
-            InspectorTest.addResult("Group: " + originGroupName);
-            for (var originTitle of originTitles)
-                InspectorTest.dumpDeepInnerHTML(originTitle);
-        }
-    }
+    var request2 = new WebInspector.NetworkRequest(InspectorTest.mainTarget, 0, "https://does-not-resolve.test", "https://does-not-resolve.test", 0, 0, null);
+    // Leave the security state unknown.
+    InspectorTest.dispatchRequestFinished(request2);
+
+    InspectorTest.dumpSecurityPanelSidebarOrigins();
 
     InspectorTest.completeTest();
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/origin-group-names-unique.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/origin-group-names-unique.html
index a5f81aa1..e4282b56 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/origin-group-names-unique.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/origin-group-names-unique.html
@@ -1,12 +1,8 @@
 <html>
 <head>
 <script src="../inspector-test.js"></script>
+<script src="../security-test.js"></script>
 <script>
-var initialize_SecurityTest = function()
-{
-    InspectorTest.preloadPanel("security");
-}
-
 function test()
 {
     var originGroupNameSize = Object.keys(WebInspector.SecurityPanelSidebarTree.OriginGroupName).length;
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html
index 7078bc2..649896c 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html
@@ -1,20 +1,16 @@
 <html>
 <head>
 <script src="../inspector-test.js"></script>
+<script src="../security-test.js"></script>
 <script>
-var initialize_SecurityTest = function() {
-    InspectorTest.preloadPanel("security");
-}
-
 function test()
 {
     var mixedContentStatus = { ranInsecureContent: false, displayedInsecureContent: false};
 
-    var targets = WebInspector.targetManager.targets();
-    targets[0].model(WebInspector.SecurityModel).dispatchEventToListeners(WebInspector.SecurityModel.EventTypes.SecurityStateChanged, new WebInspector.PageSecurityState(SecurityAgent.SecurityState.Secure, [], mixedContentStatus, true));
+    InspectorTest.mainTarget.model(WebInspector.SecurityModel).dispatchEventToListeners(WebInspector.SecurityModel.EventTypes.SecurityStateChanged, new WebInspector.PageSecurityState(SecurityAgent.SecurityState.Secure, [], mixedContentStatus, true));
 
-    var request = new WebInspector.NetworkRequest(targets[0], 0, "http://foo.test", "https://foo.test", 0, 0, null);
-    targets[0].model(WebInspector.NetworkManager).dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestFinished, request);
+    var request = new WebInspector.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    InspectorTest.dispatchRequestFinished(request);
 
     var explanations = WebInspector.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
     for (var i = 0; i < explanations.length; i++)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content.html
index 412fcc2a..a21191a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content.html
@@ -1,22 +1,18 @@
 <html>
 <head>
 <script src="../inspector-test.js"></script>
+<script src="../security-test.js"></script>
 <script>
-var initialize_SecurityTest = function() {
-    InspectorTest.preloadPanel("security");
-}
-
 function test()
 {
     /** @type {!SecurityAgent.MixedContentStatus} */
     var mixedContentStatus = { ranInsecureContent: false, displayedInsecureContent: false, ranInsecureContentStyle: SecurityAgent.SecurityState.Insecure, displayedInsecureContentStyle: SecurityAgent.SecurityState.Neutral };
-    var targets = WebInspector.targetManager.targets();
-    targets[0].model(WebInspector.SecurityModel).dispatchEventToListeners(WebInspector.SecurityModel.EventTypes.SecurityStateChanged, new WebInspector.PageSecurityState(SecurityAgent.SecurityState.Secure, [], mixedContentStatus, true));
+    InspectorTest.mainTarget.model(WebInspector.SecurityModel).dispatchEventToListeners(WebInspector.SecurityModel.EventTypes.SecurityStateChanged, new WebInspector.PageSecurityState(SecurityAgent.SecurityState.Secure, [], mixedContentStatus, true));
 
-    var request = new WebInspector.NetworkRequest(targets[0], 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new WebInspector.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
     request.setBlockedReason(NetworkAgent.BlockedReason.MixedContent);
     request.mixedContentType = "blockable";
-    targets[0].model(WebInspector.NetworkManager).dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestFinished, request);
+    InspectorTest.dispatchRequestFinished(request);
 
     var explanations = WebInspector.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
     for (var i = 0; i < explanations.length; i++)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-state-comparator.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-state-comparator.html
index 2cad95d..31362e3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-state-comparator.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-state-comparator.html
@@ -1,12 +1,8 @@
 <html>
 <head>
 <script src="../inspector-test.js"></script>
+<script src="../security-test.js"></script>
 <script>
-var initialize_SecurityTest = function()
-{
-    InspectorTest.preloadPanel("security");
-}
-
 function test()
 {
     var ordering = [
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/stylesheet-source-mapping.html b/third_party/WebKit/LayoutTests/http/tests/inspector/stylesheet-source-mapping.html
index 927bacee..e82b82c 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/stylesheet-source-mapping.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/stylesheet-source-mapping.html
@@ -5,7 +5,6 @@
 <script src="workspace-test.js"></script>
 
 <script>
-
 function test()
 {
     var contentReceived;
@@ -18,9 +17,8 @@
     const styleSheetURL = "http://localhost:8000/inspector/resources/example.css";
     const sourceMapURL = "example.css.map";
     const styleSheetId = 1;
-    InspectorTest.addMockUISourceCodeToWorkspace(styleSheetURL, WebInspector.resourceTypes.Stylesheet, "");
 
-    InspectorTest.addSniffer(WebInspector.CSSWorkspaceBinding.prototype, "updateLocations", locationsUpdated, true);
+    InspectorTest.addSniffer(WebInspector.CSSWorkspaceBinding.HeaderInfo.prototype, "_updateLocations", locationsUpdated, true);
     cssModel._styleSheetAdded(createMockStyleSheetHeader(styleSheetURL, sourceMapURL));
 
     function locationsUpdated()
@@ -70,7 +68,7 @@
     function scssUISourceCodeAdded(uiSourceCode)
     {
         InspectorTest.addResult("Added SCSS uiSourceCode: " + uiSourceCode.uri());
-        afterStyleSheetAdded();
+        setImmediate(afterStyleSheetAdded);
     }
 
     function rawLocationToUILocation(line, column)
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/307-after-303-after-post-expected.txt b/third_party/WebKit/LayoutTests/http/tests/loading/307-after-303-after-post-expected.txt
index f386fc0..60b89d8 100644
--- a/third_party/WebKit/LayoutTests/http/tests/loading/307-after-303-after-post-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/loading/307-after-303-after-post-expected.txt
@@ -5,10 +5,10 @@
 main frame - didFinishLoadForFrame
 main frame - didStartProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/post-to-303-target.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/post-to-303-target.php, main document URL http://127.0.0.1:8000/loading/resources/post-to-303-target.php, http method POST> redirectResponse (null)
-main frame - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/post-to-303-target.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/303-to-307-target.php, main document URL http://127.0.0.1:8000/loading/resources/303-to-307-target.php, http method GET> redirectResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/post-to-303-target.php, http status code 303>
 main frame - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/post-to-303-target.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/307-post-output-target.php, main document URL http://127.0.0.1:8000/loading/resources/307-post-output-target.php, http method GET> redirectResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/303-to-307-target.php, http status code 307>
+main frame - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/post-to-303-target.php - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/307-post-output-target.php, http status code 200>
 main frame - didCommitLoadForFrame
 http://127.0.0.1:8000/loading/resources/post-to-303-target.php - didFinishLoading
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/redirect-methods-expected.txt b/third_party/WebKit/LayoutTests/http/tests/loading/redirect-methods-expected.txt
index f861015..28026fd 100644
--- a/third_party/WebKit/LayoutTests/http/tests/loading/redirect-methods-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/loading/redirect-methods-expected.txt
@@ -18,8 +18,8 @@
 frame "0" - didFinishLoadForFrame
 frame "0" - didStartProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> redirectResponse (null)
-frame "0" - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET> redirectResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, http status code 301>
+frame "0" - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200>
 frame "0" - didCommitLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - didFinishLoading
@@ -41,8 +41,8 @@
 frame "1" - didFinishLoadForFrame
 frame "1" - didStartProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> redirectResponse (null)
-frame "1" - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET> redirectResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, http status code 302>
+frame "1" - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200>
 frame "1" - didCommitLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - didFinishLoading
@@ -64,8 +64,8 @@
 frame "2" - didFinishLoadForFrame
 frame "2" - didStartProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> redirectResponse (null)
-frame "2" - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET> redirectResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, http status code 303>
+frame "2" - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200>
 frame "2" - didCommitLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - didFinishLoading
@@ -87,8 +87,8 @@
 frame "3" - didFinishLoadForFrame
 frame "3" - didStartProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> redirectResponse (null)
-frame "3" - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> redirectResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, http status code 307>
+frame "3" - didReceiveServerRedirectForProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200>
 frame "3" - didCommitLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - didFinishLoading
diff --git a/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt b/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
index 2b065982..f6a72e0a 100644
--- a/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
@@ -1,20 +1,20 @@
 Test that if a profiler is working all the agents are disabled.
 
 --> WebInspector.targetManager.suspendAllTargets();
+frontend: {"id":<number>,"method":"Worker.setAutoconnectToWorkers","params":{"value":false}}
 frontend: {"id":<number>,"method":"Debugger.disable"}
 frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"maxDepth":0}}
 frontend: {"id":<number>,"method":"Page.setOverlayMessage"}
 frontend: {"id":<number>,"method":"DOM.disable"}
 frontend: {"id":<number>,"method":"CSS.disable"}
-frontend: {"id":<number>,"method":"Worker.setAutoconnectToWorkers","params":{"value":false}}
 
 --> WebInspector.targetManager.resumeAllTargets();
+frontend: {"id":<number>,"method":"Worker.setAutoconnectToWorkers","params":{"value":true}}
 frontend: {"id":<number>,"method":"Debugger.enable"}
 frontend: {"id":<number>,"method":"Debugger.setPauseOnExceptions","params":{"state":"none"}}
 frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"maxDepth":4}}
 frontend: {"id":<number>,"method":"DOM.enable"}
 frontend: {"id":<number>,"method":"CSS.enable"}
-frontend: {"id":<number>,"method":"Worker.setAutoconnectToWorkers","params":{"value":true}}
 
 --> done
 
diff --git a/third_party/WebKit/LayoutTests/inspector/profiler/cpu-profiler-stopped-removed-race-expected.txt b/third_party/WebKit/LayoutTests/inspector/profiler/cpu-profiler-stopped-removed-race-expected.txt
index 5fb762a..a224b4c 100644
--- a/third_party/WebKit/LayoutTests/inspector/profiler/cpu-profiler-stopped-removed-race-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/profiler/cpu-profiler-stopped-removed-race-expected.txt
@@ -3,9 +3,10 @@
 Profiler was enabled.
 
 Running: testProfiling
+Suspending targets
 Stop recording command issued.
-resumed
 Recording stopped. profile (should be null): null
+Resuming targets
 
 Profiler was disabled.
 
diff --git a/third_party/WebKit/LayoutTests/inspector/profiler/cpu-profiler-stopped-removed-race.html b/third_party/WebKit/LayoutTests/inspector/profiler/cpu-profiler-stopped-removed-race.html
index 2c5694b..f537f5e 100644
--- a/third_party/WebKit/LayoutTests/inspector/profiler/cpu-profiler-stopped-removed-race.html
+++ b/third_party/WebKit/LayoutTests/inspector/profiler/cpu-profiler-stopped-removed-race.html
@@ -11,6 +11,7 @@
         {
             var cpuProfiler = WebInspector.targetManager.mainTarget().cpuProfilerModel;
             var targetManager = WebInspector.targetManager;
+            targetManager.addEventListener(WebInspector.TargetManager.Events.SuspendStateChanged, onSuspendStateChanged);
             var profilesPanel = WebInspector.panels.profiles;
             InspectorTest.addSniffer(cpuProfiler, "stopRecording", stopRecording);
             InspectorTest.addSniffer(profilesPanel, "_addProfileHeader", onAddProfileHeader);
@@ -18,14 +19,18 @@
 
             function onAddProfileHeader()
             {
-	        targetManager.addEventListener(WebInspector.TargetManager.Events.SuspendStateChanged, stateChanged);
-	        profilesPanel.toggleRecordButton();  // Stop profiling.
-	        profilesPanel._reset();  // ... and remove the profile before it actually stopped.
+                profilesPanel.toggleRecordButton();  // Stop profiling.
+                profilesPanel._reset();  // ... and remove the profile before it actually stopped.
             }
 
-            function stateChanged()
+            function onSuspendStateChanged()
             {
-                InspectorTest.addResult("resumed");
+                if (WebInspector.targetManager.allTargetsSuspended()) {
+                    InspectorTest.addResult("Suspending targets");
+                    return;
+                }
+                InspectorTest.addResult("Resuming targets");
+                InspectorTest.completeProfilerTest();
             }
 
             function stopRecording(resultPromise)
@@ -37,7 +42,6 @@
             function didStopRecording(profile)
             {
                 InspectorTest.addResult("Recording stopped. profile (should be null): " + profile);
-                InspectorTest.completeProfilerTest();
             }
         }
     ]);
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-checkContent.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-checkContent.html
index 3254bcac..6c0dee8 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-checkContent.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-checkContent.html
@@ -26,7 +26,7 @@
     function onContentAvailable()
     {
         uiSourceCode.setWorkingCopy("var a = 0;");
-        uiSourceCode.checkContentUpdated(onUpdated);
+        uiSourceCode.checkContentUpdated(true, onUpdated);
     }
 
     function confirmOverride()
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-node-reference.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-node-reference.html
index 06d5e69..df48149 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-node-reference.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-node-reference.html
@@ -28,7 +28,7 @@
     function clickValueLink(record, row)
     {
         var panel = WebInspector.panels.timeline;
-        WebInspector.TimelineUIUtils.buildTraceEventDetails(record.traceEvent(), panel._model, new WebInspector.Linkifier(), onDetailsContentReady);
+        WebInspector.TimelineUIUtils.buildTraceEventDetails(record.traceEvent(), panel._model, new WebInspector.Linkifier(), true, onDetailsContentReady);
 
         function onDetailsContentReady(element)
         {
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/svg/dom/length-list-parser-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/svg/dom/length-list-parser-expected.txt
deleted file mode 100644
index 18152a17..0000000
--- a/third_party/WebKit/LayoutTests/platform/win-xp/svg/dom/length-list-parser-expected.txt
+++ /dev/null
@@ -1,326 +0,0 @@
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e,-.e+968,52e,78-.,e809423-e7\t,8695e3"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0e-8"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 072"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="84e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t73+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="010--613506-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-\t8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198\t50"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3.3+945-.+.5,6-19 ,666,+1+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161ee002+3+5"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1e, -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017e0-342114,6\t879-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018e5.\t+0e 10+ -719.e75"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="9-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\t0,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4-5,6e5-28026,66-1 6 1e8-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161 -0 8,1 7+0,573 0\te,9ee\t2+5e,-.e+968,52e,78-.,e809423-e7\t,8695e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e7e+ -27e\t\t3-20256803-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="564281 0ee51+ e \t378584833\t,.141\te8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\t8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608\t9 367 ..81e9e539\te 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="-8e8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.\t-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9\te 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 07238"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="e-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 362+-.1+1e0 4 4e 28\t-8 -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,47"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35\t+684 +\t159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960\t1-9 289\t"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="3+.47e19353 2+\t77+6 ,-+47 ,7428.6ee52.9  .-e6"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-.e1"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="61822,15-00.166.7 "
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="2\t.5,658-7 e ,8477553"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="7-3469.43,+,0\t 1-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015181-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001. -869+.. +31\t8,514\t0. 8 e37e"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147322\t6\t\t2 50635- 385\t5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001949,-"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="8 2 589\t-45e58 -4\t-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-\t.765+-87 e. 68\t9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1\t+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="1+.5-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+7+"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="+08-14\t4- .57-\t -0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017+ -1-.0e+7-1--0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+\te.96-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,488e16414,,.+ 15"
-CONSOLE ERROR: Error: Invalid value for <text> attribute x="\u0000"
-This test fuzzes the length list parser with semi-random attribute values and dumps the results of any values that parse successfully.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Parsed as 1 length(s) [ 8.847 ]: 8.847
-Parsed as 1 length(s) [ 8.62569e+6 ]: 8625686 3.0-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 90,e4997..,782-4326e.	-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013e,+e9	e 4829.,063721-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e6 072
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-Parsed as 1 length(s) [ 1 ]: 1,.,+.833+.004 2-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+.9-	8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.7980-555-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-198	50
-Parsed as 1 length(s) [ 564281 ]: 564281 0ee51+ e 	378584833	,.141	e8-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-53. 88530-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010	8.-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018.847e28886-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014e85 .-1-
-Parsed as 3 length(s) [ 0, 9, 367 ]: -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001608	9 367 ..81e9e539	e 4 e-17 6911-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e88. 965---39 0
-Parsed as 4 length(s) [ 4, 0, 35, 684 ]: 04,-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001993,35	+684 +	159e   +.3-e0+,812-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001728-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014+,--1-26e666460-79.5-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000169603-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010641,,572-960	1-9 289	
-Parsed as 1 length(s) [ 61822 ]: 61822,15-00.166.7 
-Parsed as 2 length(s) [ 2, 0.5 ]: 2	.5,658-7 e ,8477553
-Parsed as 3 length(s) [ 8, 2, 589 ]: 8 2 589	-45e58 -4	-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e58-++689.-98-,42 94564.,967-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011+ ,9+6-	.765+-87 e. 68	9452182-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016.. 1	+
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/svg/hixie/perf/006-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/svg/hixie/perf/006-expected.png
index 84bf7778..bffbf23b 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/svg/hixie/perf/006-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/svg/hixie/perf/006-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/svg/transforms/text-with-pattern-with-svg-transform-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/svg/transforms/text-with-pattern-with-svg-transform-expected.png
index 0e88219..77ae78a3 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/svg/transforms/text-with-pattern-with-svg-transform-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/svg/transforms/text-with-pattern-with-svg-transform-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/storage/indexeddb/error-attributes.html b/third_party/WebKit/LayoutTests/storage/indexeddb/error-attributes.html
new file mode 100644
index 0000000..8fef2dd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/storage/indexeddb/error-attributes.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>IndexedDB: Error attributes are DOMExceptions</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="resources/testharness-helpers.js"></script>
+<script>
+indexeddb_test(
+    function(t, db) {
+        db.createObjectStore('store');
+    },
+    function(t, db) {
+        var tx = db.transaction('store', 'readwrite');
+        var store = tx.objectStore('store');
+        var r1 = store.add('value', 'key');
+        r1.onerror = t.unreached_func('first add should succeed');
+
+        var r2 = store.add('value', 'key');
+        r2.onsuccess = t.unreached_func('second add should fail');
+
+        r2.onerror = t.step_func(function() {
+            assert_true(r2.error instanceof DOMException);
+            assert_equals(r2.error.name, 'ConstraintError');
+        });
+
+        tx.oncomplete = t.unreached_func('transaction should not complete');
+        tx.onabort = t.step_func(function() {
+            assert_true(tx.error instanceof DOMException);
+            assert_equals(tx.error.name, 'ConstraintError');
+            t.done();
+        });
+    },
+    'IDBRequest and IDBTransaction error properties should be DOMExceptions'
+);
+</script>
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index bcc8ea01..5cb63c4d 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -1516,7 +1516,6 @@
     CSSValueID id = range.peek().id();
     if (id == CSSValueNone)
         return consumeIdent(range);
-
     // FIXME: Add support for <url>, <basic-shape>, <geometry-box>.
     if (range.peek().functionId() != CSSValuePath)
         return nullptr;
@@ -1554,6 +1553,32 @@
     return list.release();
 }
 
+static PassRefPtrWillBeRawPtr<CSSValue> consumeTextEmphasisStyle(CSSParserTokenRange& range)
+{
+    CSSValueID id = range.peek().id();
+    if (id == CSSValueNone)
+        return consumeIdent(range);
+
+    if (RefPtrWillBeRawPtr<CSSValue> textEmphasisStyle = consumeString(range))
+        return textEmphasisStyle.release();
+
+    RefPtrWillBeRawPtr<CSSPrimitiveValue> fill = consumeIdent<CSSValueFilled, CSSValueOpen>(range);
+    RefPtrWillBeRawPtr<CSSPrimitiveValue> shape = consumeIdent<CSSValueDot, CSSValueCircle, CSSValueDoubleCircle, CSSValueTriangle, CSSValueSesame>(range);
+    if (!fill)
+        fill = consumeIdent<CSSValueFilled, CSSValueOpen>(range);
+    if (fill && shape) {
+        RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
+        parsedValues->append(fill.release());
+        parsedValues->append(shape.release());
+        return parsedValues.release();
+    }
+    if (fill)
+        return fill.release();
+    if (shape)
+        return shape.release();
+    return nullptr;
+}
+
 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID unresolvedProperty)
 {
     CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty);
@@ -1656,6 +1681,7 @@
         return consumeColor(m_range, m_context);
     case CSSPropertyWebkitTextFillColor:
     case CSSPropertyWebkitTapHighlightColor:
+    case CSSPropertyWebkitTextEmphasisColor:
         return consumeColor(m_range, m_context);
     case CSSPropertyColor:
         return consumeColor(m_range, m_context, inQuirksMode());
@@ -1679,6 +1705,8 @@
     case CSSPropertyMotionRotation:
         ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled());
         return consumeMotionRotation(m_range, m_context.mode());
+    case CSSPropertyWebkitTextEmphasisStyle:
+        return consumeTextEmphasisStyle(m_range);
     default:
         return nullptr;
     }
@@ -2155,6 +2183,8 @@
     case CSSPropertyMotion:
         ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled());
         return consumeShorthandGreedily(motionShorthand(), important);
+    case CSSPropertyWebkitTextEmphasis:
+        return consumeShorthandGreedily(webkitTextEmphasisShorthand(), important);
     default:
         m_currentShorthand = oldShorthand;
         return false;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
index 31906a4..99f4731 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
@@ -236,8 +236,6 @@
     PassRefPtrWillBeRawPtr<CSSValueList> parseTransform(bool useLegacyParsing);
     PassRefPtrWillBeRawPtr<CSSValue> parseTransformValue(bool useLegacyParsing, CSSParserValue*);
 
-    PassRefPtrWillBeRawPtr<CSSValue> parseTextEmphasisStyle();
-
     bool parseCalculation(CSSParserValue*, ValueRange);
 
     bool parseGeneratedImage(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&);
diff --git a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
index 64afe47..8c378d59 100644
--- a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
@@ -437,7 +437,6 @@
     case CSSPropertyWebkitBorderBeforeColor:
     case CSSPropertyWebkitBorderAfterColor:
     case CSSPropertyWebkitColumnRuleColor:
-    case CSSPropertyWebkitTextEmphasisColor:
     case CSSPropertyWebkitTextStrokeColor:
         parsedValue = parseColor(m_valueList->current(), acceptQuirkyColors(propId));
         if (parsedValue)
@@ -1051,13 +1050,6 @@
     case CSSPropertyInvalid:
         return false;
     // CSS Text Layout Module Level 3: Vertical writing support
-    case CSSPropertyWebkitTextEmphasis:
-        return parseShorthand(propId, webkitTextEmphasisShorthand(), important);
-
-    case CSSPropertyWebkitTextEmphasisStyle:
-        parsedValue = parseTextEmphasisStyle();
-        break;
-
     case CSSPropertyWebkitTextOrientation:
         // FIXME: For now just support sideways, sideways-right, upright and vertical-right.
         if (id == CSSValueSideways || id == CSSValueSidewaysRight || id == CSSValueVerticalRight || id == CSSValueUpright)
@@ -1193,6 +1185,9 @@
     case CSSPropertyMotionOffset:
     case CSSPropertyMotionRotation:
     case CSSPropertyMotion:
+    case CSSPropertyWebkitTextEmphasisColor:
+    case CSSPropertyWebkitTextEmphasisStyle:
+    case CSSPropertyWebkitTextEmphasis:
         validPrimitive = false;
         break;
 
@@ -5376,53 +5371,6 @@
     return list.release();
 }
 
-PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTextEmphasisStyle()
-{
-    RefPtrWillBeRawPtr<CSSPrimitiveValue> fill = nullptr;
-    RefPtrWillBeRawPtr<CSSPrimitiveValue> shape = nullptr;
-
-    for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
-        if (value->m_unit == CSSParserValue::String) {
-            if (fill || shape)
-                return nullptr;
-            m_valueList->next();
-            return createPrimitiveStringValue(value);
-        }
-
-        if (value->id == CSSValueNone) {
-            if (fill || shape)
-                return nullptr;
-            m_valueList->next();
-            return cssValuePool().createIdentifierValue(CSSValueNone);
-        }
-
-        if (value->id == CSSValueOpen || value->id == CSSValueFilled) {
-            if (fill)
-                return nullptr;
-            fill = cssValuePool().createIdentifierValue(value->id);
-        } else if (value->id == CSSValueDot || value->id == CSSValueCircle || value->id == CSSValueDoubleCircle || value->id == CSSValueTriangle || value->id == CSSValueSesame) {
-            if (shape)
-                return nullptr;
-            shape = cssValuePool().createIdentifierValue(value->id);
-        } else {
-            break;
-        }
-    }
-
-    if (fill && shape) {
-        RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
-        parsedValues->append(fill.release());
-        parsedValues->append(shape.release());
-        return parsedValues.release();
-    }
-    if (fill)
-        return fill.release();
-    if (shape)
-        return shape.release();
-
-    return nullptr;
-}
-
 bool CSSPropertyParser::parseCalculation(CSSParserValue* value, ValueRange range)
 {
     ASSERT(isCalculation(value));
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
index 4fde5b99..16804d7 100644
--- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp
+++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -48,7 +48,6 @@
 #include "core/page/Page.h"
 #include "core/svg/SVGStyleElement.h"
 #include "platform/TraceEvent.h"
-#include "platform/fonts/FontCache.h"
 
 namespace blink {
 
@@ -493,7 +492,6 @@
     m_fontSelector->updateGenericFontFamilySettings(*m_document);
     if (m_resolver)
         m_resolver->invalidateMatchedPropertiesCache();
-    FontCache::fontCache()->invalidateShapeCache();
 }
 
 void StyleEngine::removeFontFaceRules(const WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace>>& fontFaceRules)
diff --git a/third_party/WebKit/Source/core/fetch/FetchContext.cpp b/third_party/WebKit/Source/core/fetch/FetchContext.cpp
index 34ad58aa..f7917ff 100644
--- a/third_party/WebKit/Source/core/fetch/FetchContext.cpp
+++ b/third_party/WebKit/Source/core/fetch/FetchContext.cpp
@@ -90,7 +90,7 @@
 {
 }
 
-void FetchContext::willStartLoadingResource(ResourceRequest&)
+void FetchContext::willStartLoadingResource(ResourceRequest&, FetchResourceType)
 {
 }
 
diff --git a/third_party/WebKit/Source/core/fetch/FetchContext.h b/third_party/WebKit/Source/core/fetch/FetchContext.h
index 22869f1..0dc4864 100644
--- a/third_party/WebKit/Source/core/fetch/FetchContext.h
+++ b/third_party/WebKit/Source/core/fetch/FetchContext.h
@@ -83,7 +83,7 @@
     virtual void dispatchDidFail(unsigned long identifier, const ResourceError&, bool isInternalRequest);
 
     virtual bool shouldLoadNewResource(Resource::Type) const { return false; }
-    virtual void willStartLoadingResource(ResourceRequest&);
+    virtual void willStartLoadingResource(ResourceRequest&, FetchResourceType);
     virtual void didLoadResource();
 
     virtual void addResourceTiming(const ResourceTimingInfo&);
diff --git a/third_party/WebKit/Source/core/fetch/RawResource.cpp b/third_party/WebKit/Source/core/fetch/RawResource.cpp
index 945a349..4ae099d 100644
--- a/third_party/WebKit/Source/core/fetch/RawResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/RawResource.cpp
@@ -134,14 +134,6 @@
     Resource::willFollowRedirect(newRequest, redirectResponse);
 }
 
-void RawResource::updateRequest(const ResourceRequest& request)
-{
-    ResourcePtr<RawResource> protect(this);
-    ResourceClientWalker<RawResourceClient> w(m_clients);
-    while (RawResourceClient* c = w.next())
-        c->updateRequest(this, request);
-}
-
 void RawResource::responseReceived(const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle)
 {
     InternalResourcePtr protect(this);
diff --git a/third_party/WebKit/Source/core/fetch/RawResource.h b/third_party/WebKit/Source/core/fetch/RawResource.h
index bb3546db..ad95b133 100644
--- a/third_party/WebKit/Source/core/fetch/RawResource.h
+++ b/third_party/WebKit/Source/core/fetch/RawResource.h
@@ -74,7 +74,6 @@
     bool shouldIgnoreHTTPStatusCodeErrors() const override { return true; }
 
     void willFollowRedirect(ResourceRequest&, const ResourceResponse&) override;
-    void updateRequest(const ResourceRequest&) override;
     void responseReceived(const ResourceResponse&, PassOwnPtr<WebDataConsumerHandle>) override;
     void setSerializedCachedMetadata(const char*, size_t) override;
     void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override;
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp
index aade7d7..de290b6 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/core/fetch/Resource.cpp
@@ -175,13 +175,8 @@
     if (m_resourceRequest.url().protocolIsInHTTPFamily())
         m_cacheHandler = CacheHandler::create(this);
 
-    if (!m_resourceRequest.url().hasFragmentIdentifier())
-        return;
-    KURL urlForCache = MemoryCache::removeFragmentIdentifierIfNeeded(m_resourceRequest.url());
-    if (urlForCache.hasFragmentIdentifier())
-        return;
-    m_fragmentIdentifierForRequest = m_resourceRequest.url().fragmentIdentifier();
-    m_resourceRequest.setURL(urlForCache);
+    if (!accept().isEmpty())
+        m_resourceRequest.setHTTPAccept(accept());
 }
 
 Resource::~Resource()
@@ -213,28 +208,23 @@
 {
     m_options = options;
     m_loading = true;
-
-    ResourceRequest request(m_revalidatingRequest.isNull() ? m_resourceRequest : m_revalidatingRequest);
-    if (!accept().isEmpty())
-        request.setHTTPAccept(accept());
-
-    // FIXME: It's unfortunate that the cache layer and below get to know anything about fragment identifiers.
-    // We should look into removing the expectation of that knowledge from the platform network stacks.
-    if (!m_fragmentIdentifierForRequest.isNull()) {
-        KURL url = request.url();
-        url.setFragmentIdentifier(m_fragmentIdentifierForRequest);
-        request.setURL(url);
-        m_fragmentIdentifierForRequest = String();
-    }
     m_status = Pending;
+
     if (m_loader) {
         ASSERT(m_revalidatingRequest.isNull());
         RELEASE_ASSERT(m_options.synchronousPolicy == RequestSynchronously);
         m_loader->changeToSynchronous();
         return;
     }
-    m_loader = ResourceLoader::create(fetcher, this, request, options);
+
+    ResourceRequest& request(m_revalidatingRequest.isNull() ? m_resourceRequest : m_revalidatingRequest);
+    ResourceRequest requestCopy(m_revalidatingRequest.isNull() ? m_resourceRequest : m_revalidatingRequest);
+    m_loader = ResourceLoader::create(fetcher, this, requestCopy, options);
     m_loader->start();
+
+    // Headers might have been modified during load start. Copy them over so long as the url didn't change.
+    if (request.url() == requestCopy.url())
+        request = requestCopy;
 }
 
 void Resource::checkNotify()
diff --git a/third_party/WebKit/Source/core/fetch/Resource.h b/third_party/WebKit/Source/core/fetch/Resource.h
index 89a88ea..589bb3a 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.h
+++ b/third_party/WebKit/Source/core/fetch/Resource.h
@@ -198,7 +198,6 @@
 
     virtual void willFollowRedirect(ResourceRequest&, const ResourceResponse&);
 
-    virtual void updateRequest(const ResourceRequest&) { }
     virtual void responseReceived(const ResourceResponse&, PassOwnPtr<WebDataConsumerHandle>);
     void setResponse(const ResourceResponse& response) { m_response = response; }
     const ResourceResponse& response() const { return m_response; }
@@ -381,8 +380,6 @@
     void clearCachedMetadata(CachedMetadataHandler::CacheType);
     CachedMetadata* cachedMetadata(unsigned dataTypeID) const;
 
-    String m_fragmentIdentifierForRequest;
-
     RefPtr<CachedMetadata> m_cachedMetadata;
     OwnPtrWillBeMember<CacheHandler> m_cacheHandler;
 
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
index 56768741..d52c3ef 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -472,6 +472,8 @@
     if (type == Resource::LinkPrefetch || type == Resource::LinkSubresource)
         request.setHTTPHeaderField("Purpose", "prefetch");
 
+    request.setURL(MemoryCache::removeFragmentIdentifierIfNeeded(request.url()));
+
     context().addAdditionalRequestHeaders(request, (type == Resource::MainResource) ? FetchMainResource : FetchSubresource);
 }
 
@@ -977,7 +979,7 @@
 
 void ResourceFetcher::willStartLoadingResource(Resource* resource, ResourceRequest& request)
 {
-    context().willStartLoadingResource(request);
+    context().willStartLoadingResource(request, resource->type() == Resource::MainResource ? FetchMainResource : FetchSubresource);
     storeResourceTimingInitiatorInformation(resource);
     TRACE_EVENT_ASYNC_BEGIN2("blink.net", "Resource", resource, "url", resource->url().string().ascii(), "priority", resource->resourceRequest().priority());
 }
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
index 6107296..a549bf6 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
@@ -51,7 +51,7 @@
 
 namespace blink {
 
-ResourceLoader* ResourceLoader::create(ResourceFetcher* fetcher, Resource* resource, const ResourceRequest& request, const ResourceLoaderOptions& options)
+ResourceLoader* ResourceLoader::create(ResourceFetcher* fetcher, Resource* resource, ResourceRequest& request, const ResourceLoaderOptions& options)
 {
     ResourceLoader* loader = new ResourceLoader(fetcher, resource, options);
     loader->init(request);
@@ -103,15 +103,13 @@
     m_fetcher.clear();
 }
 
-void ResourceLoader::init(const ResourceRequest& passedRequest)
+void ResourceLoader::init(ResourceRequest& request)
 {
     ASSERT(m_state != Terminated);
-    ResourceRequest request(passedRequest);
     m_fetcher->willSendRequest(m_resource->identifier(), request, ResourceResponse(), m_options.initiatorInfo);
     ASSERT(m_state != Terminated);
     ASSERT(!request.isNull());
-    m_originalRequest = m_request = applyOptions(request);
-    m_resource->updateRequest(request);
+    m_request = applyOptions(request);
     ASSERT(m_state != Terminated);
     m_fetcher->didInitializeResourceLoader(this);
 }
@@ -276,15 +274,10 @@
 
     applyOptions(newRequest); // canAccessRedirect() can modify m_options so we should re-apply it.
     m_fetcher->redirectReceived(m_resource, redirectResponse);
-    ASSERT(m_state != Terminated);
+    m_fetcher->willSendRequest(m_resource->identifier(), newRequest, redirectResponse, m_options.initiatorInfo);
     m_resource->willFollowRedirect(newRequest, redirectResponse);
     if (newRequest.isNull() || m_state == Terminated)
         return;
-
-    m_fetcher->willSendRequest(m_resource->identifier(), newRequest, redirectResponse, m_options.initiatorInfo);
-    ASSERT(m_state != Terminated);
-    ASSERT(!newRequest.isNull());
-    m_resource->updateRequest(newRequest);
     m_request = newRequest;
 }
 
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoader.h b/third_party/WebKit/Source/core/fetch/ResourceLoader.h
index 5077de7a..e0b42db 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceLoader.h
+++ b/third_party/WebKit/Source/core/fetch/ResourceLoader.h
@@ -47,7 +47,7 @@
 
 class CORE_EXPORT ResourceLoader final : public GarbageCollectedFinalized<ResourceLoader>, protected WebURLLoaderClient {
 public:
-    static ResourceLoader* create(ResourceFetcher*, Resource*, const ResourceRequest&, const ResourceLoaderOptions&);
+    static ResourceLoader* create(ResourceFetcher*, Resource*, ResourceRequest&, const ResourceLoaderOptions&);
     ~ResourceLoader() override;
     DECLARE_TRACE();
 
@@ -59,7 +59,6 @@
     void cancelIfNotFinishing();
 
     Resource* cachedResource() { return m_resource; }
-    const ResourceRequest& originalRequest() const { return m_originalRequest; }
 
     void setDefersLoading(bool);
     bool defersLoading() const { return m_defersLoading; }
@@ -85,14 +84,13 @@
     bool isLoadedBy(ResourceFetcher*) const;
 
     bool reachedTerminalState() const { return m_state == Terminated; }
-    const ResourceRequest& request() const { return m_request; }
 
     bool loadingMultipartContent() const { return m_loadingMultipartContent; }
 
 private:
     ResourceLoader(ResourceFetcher*, Resource*, const ResourceLoaderOptions&);
 
-    void init(const ResourceRequest&);
+    void init(ResourceRequest&);
     void requestSynchronously();
 
     void didFinishLoadingOnePart(double finishTime, int64_t encodedDataLength);
@@ -105,7 +103,6 @@
     Member<ResourceFetcher> m_fetcher;
 
     ResourceRequest m_request;
-    ResourceRequest m_originalRequest; // Before redirects.
 
     bool m_notifiedLoadComplete;
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
index a79de16..9eb7a10 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -920,7 +920,7 @@
     inspectorStyleSheet->getText(result);
 }
 
-void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text)
+void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text, TypeBuilder::OptOutput<String>* sourceMapURL)
 {
     FrontendOperationScope scope;
     InspectorStyleSheetBase* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
@@ -932,6 +932,8 @@
     TrackExceptionState exceptionState;
     m_domAgent->history()->perform(adoptRefWillBeNoop(new SetStyleSheetTextAction(inspectorStyleSheet, text)), exceptionState);
     *errorString = InspectorDOMAgent::toErrorString(exceptionState);
+    if (!inspectorStyleSheet->sourceMapURL().isEmpty())
+        *sourceMapURL = inspectorStyleSheet->sourceMapURL();
 }
 
 static bool extractRangeComponent(ErrorString* errorString, const RefPtr<JSONObject>& range, const String& component, unsigned& result)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h
index 517bede..e36ad82 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h
@@ -134,7 +134,7 @@
     void getMatchedStylesForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributesStyle, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch>>& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoElementMatches>>&, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry>>& inheritedEntries) override;
     void getCSSAnimationsForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSKeyframesRule>>& cssKeyframesRules) override;
     void getStyleSheetText(ErrorString*, const String& styleSheetId, String* result) override;
-    void setStyleSheetText(ErrorString*, const String& styleSheetId, const String& text) override;
+    void setStyleSheetText(ErrorString*, const String& styleSheetId, const String& text, TypeBuilder::OptOutput<String>* sourceMapURL) override;
     void setRuleSelector(ErrorString*, const String& styleSheetId, const RefPtr<JSONObject>& range, const String& selector, RefPtr<TypeBuilder::CSS::SelectorList>& result) override;
     void setStyleText(ErrorString*, const String& styleSheetId, const RefPtr<JSONObject>& range, const String& text, RefPtr<TypeBuilder::CSS::CSSStyle>& result) override;
     void setMediaText(ErrorString*, const String& styleSheetId, const RefPtr<JSONObject>& range, const String& text, RefPtr<TypeBuilder::CSS::CSSMedia>& result) override;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.h b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.h
index 80c701a..a07e152d 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.h
@@ -94,6 +94,7 @@
 
     virtual bool setText(const String&, ExceptionState&) = 0;
     virtual bool getText(String* result) = 0;
+    virtual String sourceMapURL() { return String(); }
 
     PassRefPtr<TypeBuilder::CSS::CSSStyle> buildObjectForStyle(CSSStyleDeclaration*);
     PassRefPtr<TypeBuilder::CSS::SourceRange> buildSourceRangeObject(const SourceRange&);
@@ -145,6 +146,7 @@
     bool isInlineStyle() override { return false; }
     const CSSRuleVector& flatRules();
     RefPtrWillBeRawPtr<CSSRuleSourceData> sourceDataForRule(RefPtrWillBeRawPtr<CSSRule>);
+    String sourceMapURL() override;
 
 protected:
     PassRefPtrWillBeRawPtr<InspectorStyle> inspectorStyle(RefPtrWillBeRawPtr<CSSStyleDeclaration>) override;
@@ -158,7 +160,6 @@
     CSSStyleRule* insertCSSOMRuleInStyleSheet(CSSRule* insertBefore, const String& ruleText, ExceptionState&);
     CSSStyleRule* insertCSSOMRuleInMediaRule(CSSMediaRule*, CSSRule* insertBefore, const String& ruleText, ExceptionState&);
     CSSStyleRule* insertCSSOMRuleBySourceRange(const SourceRange&, const String& ruleText, ExceptionState&);
-    String sourceMapURL();
     String sourceURL();
     void remapSourceDataToCSSOMIfNecessary();
     void mapSourceDataToCSSOM();
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 862f15a..a2126f158 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -756,7 +756,7 @@
         LayoutUnit pageLogicalHeightAtNewOffset = block.pageLogicalHeightForOffset(lineLogicalOffset + remainingLogicalHeight);
         // It's rather pointless to break before the block if the current line isn't going to
         // fit in the same column or page, so check that as well.
-        if (totalLogicalHeight < pageLogicalHeightAtNewOffset)
+        if (totalLogicalHeight <= pageLogicalHeightAtNewOffset)
             wantsStrutOnBlock = true;
     }
     return wantsStrutOnBlock && block.allowsPaginationStrut();
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index 01b2985..2c84b0d 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -95,10 +95,11 @@
     , m_documentLoadTiming(*this)
     , m_timeOfLastDataReceived(0.0)
     , m_applicationCacheHost(ApplicationCacheHost::create(this))
-    , m_state(NotStarted)
+    , m_state(Provisional)
     , m_inDataReceived(false)
     , m_dataBuffer(SharedBuffer::create())
 {
+    timing().markNavigationStart();
 }
 
 FrameLoader* DocumentLoader::frameLoader() const
@@ -250,7 +251,7 @@
     if (document() && document()->hasActiveParser())
         return true;
 
-    return (m_state > NotStarted && m_state < MainResourceDone) || m_fetcher->isFetching();
+    return m_state < MainResourceDone || m_fetcher->isFetching();
 }
 
 void DocumentLoader::notifyFinished(Resource* resource)
@@ -312,60 +313,38 @@
 void DocumentLoader::redirectReceived(Resource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
 {
     ASSERT_UNUSED(resource, resource == m_mainResource);
-    willSendRequest(request, redirectResponse);
-}
-
-void DocumentLoader::updateRequest(Resource* resource, const ResourceRequest& request)
-{
-    ASSERT_UNUSED(resource, resource == m_mainResource);
-    m_request = request;
-}
-
-static bool isFormSubmission(NavigationType type)
-{
-    return type == NavigationTypeFormSubmitted || type == NavigationTypeFormResubmitted;
-}
-
-void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
-{
-    // Note that there are no asserts here as there are for the other callbacks. This is due to the
-    // fact that this "callback" is sent when starting every load, and the state of callback
-    // deferrals plays less of a part in this function in preventing the bad behavior deferring
-    // callbacks is meant to prevent.
-    ASSERT(!newRequest.isNull());
-    if (isFormSubmission(m_navigationType) && !m_frame->document()->contentSecurityPolicy()->allowFormAction(newRequest.url())) {
-        cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
-        return;
-    }
-
-    ASSERT(timing().fetchStart());
-    if (!redirectResponse.isNull()) {
-        // If the redirecting url is not allowed to display content from the target origin,
-        // then block the redirect.
-        RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
-        if (!redirectingOrigin->canDisplay(newRequest.url())) {
-            FrameLoader::reportLocalLoadFailed(m_frame, newRequest.url().string());
-            cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
-            return;
-        }
-        timing().addRedirect(redirectResponse.url(), newRequest.url());
-    }
 
     // If we're fielding a redirect in response to a POST, force a load from origin, since
     // this is a common site technique to return to a page viewing some data that the POST
     // just modified.
-    if (newRequest.cachePolicy() == UseProtocolCachePolicy && isRedirectAfterPost(newRequest, redirectResponse))
-        newRequest.setCachePolicy(ReloadBypassingCache);
+    if (request.cachePolicy() == UseProtocolCachePolicy && isRedirectAfterPost(request, redirectResponse))
+        request.setCachePolicy(ReloadBypassingCache);
 
-    m_request = newRequest;
+    m_request = request;
 
-    if (redirectResponse.isNull())
+    // Add the fragment to the new request url. Note that this is only done on m_request,
+    // not on the request that will be passed back out of blink. The network stack doesn't care
+    // about the fragment, and doesn't expect the URL to change unless it is invalidated.
+    KURL url = request.url();
+    if (m_originalRequest.url().hasFragmentIdentifier()) {
+        url.setFragmentIdentifier(m_originalRequest.url().fragmentIdentifier());
+        m_request.setURL(url);
+    }
+
+    // If the redirecting url is not allowed to display content from the target origin,
+    // then block the redirect.
+    RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
+    if (!redirectingOrigin->canDisplay(url)) {
+        FrameLoader::reportLocalLoadFailed(m_frame, url.string());
+        cancelMainResourceLoad(ResourceError::cancelledError(url));
         return;
+    }
 
-    appendRedirect(newRequest.url());
+    timing().addRedirect(redirectResponse.url(), url);
+    appendRedirect(url);
     frameLoader()->receivedMainResourceRedirect(m_request.url());
-    if (!frameLoader()->shouldContinueForNavigationPolicy(newRequest, SubstituteData(), this, CheckContentSecurityPolicy, m_navigationType, NavigationPolicyCurrentTab, replacesCurrentHistoryItem()))
-        cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
+    if (!frameLoader()->shouldContinueForNavigationPolicy(request, SubstituteData(), this, CheckContentSecurityPolicy, m_navigationType, NavigationPolicyCurrentTab, replacesCurrentHistoryItem()))
+        cancelMainResourceLoad(ResourceError::cancelledError(url));
 }
 
 static bool canShowMIMEType(const String& mimeType, Page* page)
@@ -722,53 +701,35 @@
 void DocumentLoader::startLoadingMainResource()
 {
     RefPtrWillBeRawPtr<DocumentLoader> protect(this);
-    m_mainDocumentError = ResourceError();
-    timing().markNavigationStart();
-    ASSERT(!m_mainResource);
-    ASSERT(m_state == NotStarted);
-    m_state = Provisional;
+    ASSERT(m_state == Provisional);
 
     if (maybeLoadEmpty())
         return;
 
-    ASSERT(timing().navigationStart());
     ASSERT(!timing().fetchStart());
     timing().markFetchStart();
-    willSendRequest(m_request, ResourceResponse());
-
-    // willSendRequest() may lead to our LocalFrame being detached or cancelling the load via nulling the ResourceRequest.
-    if (!m_frame || m_request.isNull())
-        return;
-
-    m_applicationCacheHost->willStartLoadingMainResource(m_request);
     prepareSubframeArchiveLoadIfNeeded();
 
-    ResourceRequest request(m_request);
     DEFINE_STATIC_LOCAL(ResourceLoaderOptions, mainResourceLoadOptions,
         (DoNotBufferData, AllowStoredCredentials, ClientRequestedCredentials, CheckContentSecurityPolicy, DocumentContext));
-    FetchRequest cachedResourceRequest(request, FetchInitiatorTypeNames::document, mainResourceLoadOptions);
-    m_mainResource = RawResource::fetchMainResource(cachedResourceRequest, fetcher(), m_substituteData);
+    FetchRequest fetchRequest(m_request, FetchInitiatorTypeNames::document, mainResourceLoadOptions);
+
+    m_mainResource = RawResource::fetchMainResource(fetchRequest, fetcher(), m_substituteData);
     if (!m_mainResource) {
         m_request = ResourceRequest();
-        // If the load was aborted by clearing m_request, it's possible the ApplicationCacheHost
-        // is now in a state where starting an empty load will be inconsistent. Replace it with
-        // a new ApplicationCacheHost.
-        if (m_applicationCacheHost)
-            m_applicationCacheHost->detachFromDocumentLoader();
-        m_applicationCacheHost = ApplicationCacheHost::create(this);
         maybeLoadEmpty();
         return;
     }
+
     m_mainResource->addClient(this);
+    if (!m_mainResource)
+        return;
 
     // A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those.
-    if (mainResourceLoader())
-        request = mainResourceLoader()->originalRequest();
-    // If there was a fragment identifier on m_request, the cache will have stripped it. m_request should include
-    // the fragment identifier, so add that back in.
-    if (equalIgnoringFragmentIdentifier(m_request.url(), request.url()))
-        request.setURL(m_request.url());
-    m_request = request;
+    // However, if there was a fragment identifier on m_request, the cache will have stripped it. m_request should include
+    // the fragment identifier, so reset the url.
+    m_request = m_mainResource->resourceRequest();
+    m_request.setURL(m_originalRequest.url());
 }
 
 void DocumentLoader::cancelMainResourceLoad(const ResourceError& resourceError)
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.h b/third_party/WebKit/Source/core/loader/DocumentLoader.h
index 163a511d..126c313 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.h
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.h
@@ -174,12 +174,10 @@
 
     void prepareSubframeArchiveLoadIfNeeded();
 
-    void willSendRequest(ResourceRequest&, const ResourceResponse&);
     void finishedLoading(double finishTime);
     void mainReceivedError(const ResourceError&);
     void cancelLoadAfterXFrameOptionsOrCSPDenied(const ResourceResponse&);
     void redirectReceived(Resource*, ResourceRequest&, const ResourceResponse&) final;
-    void updateRequest(Resource*, const ResourceRequest&) final;
     void responseReceived(Resource*, const ResourceResponse&, PassOwnPtr<WebDataConsumerHandle>) final;
     void dataReceived(Resource*, const char* data, unsigned length) final;
     void processData(const char* data, unsigned length);
@@ -232,7 +230,6 @@
     InitialScrollState m_initialScrollState;
 
     enum State {
-        NotStarted,
         Provisional,
         Committed,
         DataReceived,
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index ff2440b7..6630e9b 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -309,10 +309,13 @@
     return m_documentLoader == frame()->loader().documentLoader();
 }
 
-void FrameFetchContext::willStartLoadingResource(ResourceRequest& request)
+void FrameFetchContext::willStartLoadingResource(ResourceRequest& request, FetchResourceType type)
 {
-    if (m_documentLoader)
-        m_documentLoader->applicationCacheHost()->willStartLoadingResource(request);
+    if (!m_documentLoader)
+        return;
+    if (type == FetchMainResource)
+        m_documentLoader->applicationCacheHost()->willStartLoadingMainResource(request);
+    m_documentLoader->applicationCacheHost()->willStartLoadingResource(request);
 }
 
 void FrameFetchContext::didLoadResource()
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
index c2cbc75..3d870404 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -80,7 +80,7 @@
     void dispatchDidFail(unsigned long identifier, const ResourceError&, bool isInternalRequest) override;
 
     bool shouldLoadNewResource(Resource::Type) const override;
-    void willStartLoadingResource(ResourceRequest&) override;
+    void willStartLoadingResource(ResourceRequest&, FetchResourceType) override;
     void didLoadResource() override;
 
     void addResourceTiming(const ResourceTimingInfo&) override;
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
index 9e12e0e2..bc5e3c2b 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -96,8 +96,8 @@
     {
         dummyPageHolder = DummyPageHolder::create(IntSize(500, 500));
         dummyPageHolder->page().setDeviceScaleFactor(1.0);
-        documentLoader = DocumentLoader::create(&dummyPageHolder->frame(), ResourceRequest("http://www.example.com"), SubstituteData());
         document = toHTMLDocument(&dummyPageHolder->document());
+        documentLoader = document->loader();
         fetchContext = static_cast<FrameFetchContext*>(&documentLoader->fetcher()->context());
         owner = StubFrameOwner::create();
         FrameFetchContext::provideDocumentToContext(*fetchContext, document.get());
@@ -105,11 +105,9 @@
 
     void TearDown() override
     {
-        documentLoader->detachFromFrame();
         documentLoader.clear();
 
         if (childFrame) {
-            childDocumentLoader->detachFromFrame();
             childDocumentLoader.clear();
             childFrame->detach(FrameDetachType::Remove);
         }
@@ -121,8 +119,8 @@
         childFrame = LocalFrame::create(childClient.get(), document->frame()->host(), owner.get());
         childFrame->setView(FrameView::create(childFrame.get(), IntSize(500, 500)));
         childFrame->init();
-        childDocumentLoader = DocumentLoader::create(childFrame.get(), ResourceRequest("http://www.example.com"), SubstituteData());
         childDocument = childFrame->document();
+        childDocumentLoader = childDocument->loader();
         FrameFetchContext* childFetchContext = static_cast<FrameFetchContext*>(&childDocumentLoader->fetcher()->context());
         FrameFetchContext::provideDocumentToContext(*childFetchContext, childDocument.get());
         return childFetchContext;
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index 7851ab8b..71a27dae 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1331,6 +1331,10 @@
         return false;
     }
 
+    bool isFormSubmission = type == NavigationTypeFormSubmitted || type == NavigationTypeFormResubmitted;
+    if (isFormSubmission && !m_frame->document()->contentSecurityPolicy()->allowFormAction(request.url()))
+        return false;
+
     policy = client()->decidePolicyForNavigation(request, loader, type, policy, replacesCurrentHistoryItem);
     if (policy == NavigationPolicyCurrentTab)
         return true;
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index f3b10cc..21d9172 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -276,10 +276,10 @@
         GraphicsLayer::unregisterContentsLayer(scrollbarLayer->layer());
 }
 
-static PassOwnPtr<WebScrollbarLayer> createScrollbarLayer(Scrollbar* scrollbar)
+static PassOwnPtr<WebScrollbarLayer> createScrollbarLayer(Scrollbar* scrollbar, float deviceScaleFactor)
 {
     ScrollbarTheme* theme = scrollbar->theme();
-    WebScrollbarThemePainter painter(theme, scrollbar);
+    WebScrollbarThemePainter painter(theme, scrollbar, deviceScaleFactor);
     OwnPtr<WebScrollbarThemeGeometry> geometry(WebScrollbarThemeGeometryNative::create(theme));
 
     OwnPtr<WebScrollbarLayer> scrollbarLayer = adoptPtr(Platform::current()->compositorSupport()->createScrollbarLayer(WebScrollbarImpl::create(scrollbar), painter, geometry.leakPtr()));
@@ -367,7 +367,7 @@
                 ASSERT(RuntimeEnabledFeatures::overlayScrollbarsEnabled());
                 webScrollbarLayer = createSolidColorScrollbarLayer(orientation, scrollbar->theme()->thumbThickness(scrollbar), scrollbar->theme()->trackPosition(scrollbar), scrollableArea->shouldPlaceVerticalScrollbarOnLeft());
             } else {
-                webScrollbarLayer = createScrollbarLayer(scrollbar);
+                webScrollbarLayer = createScrollbarLayer(scrollbar, m_page->deviceScaleFactor());
             }
             scrollbarLayer = addWebScrollbarLayer(scrollableArea, orientation, webScrollbarLayer.release());
         }
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js b/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js
index 383ac172..45aa19b 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js
@@ -301,6 +301,8 @@
      */
     _pushSourceMapping: function(sourceMapping)
     {
+        if (this._sourceMappings.indexOf(sourceMapping) !== -1)
+            return;
         this._sourceMappings.push(sourceMapping);
         this._updateLocations();
     }
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/NetworkProject.js b/third_party/WebKit/Source/devtools/front_end/bindings/NetworkProject.js
index 2c49bb4..ef4089f 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/NetworkProject.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/NetworkProject.js
@@ -267,8 +267,12 @@
     /**
      * @param {string} url
      */
-    _removeFileForURL: function(url)
+    removeFileForURL: function(url)
     {
+        if (!this._processedURLs[url])
+            return;
+        delete this._processedURLs[url];
+
         var splitURL = WebInspector.ParsedURL.splitURLIntoPathComponents(url);
         var projectURL = splitURL[0];
         var path = splitURL.slice(1).join("/");
@@ -335,7 +339,7 @@
         if (header.isInline && !header.hasSourceURL && header.origin !== "inspector")
             return;
 
-        this._removeFile(header.resourceURL());
+        this.removeFileForURL(header.resourceURL());
     },
 
     /**
@@ -393,17 +397,6 @@
         uiSourceCode[WebInspector.NetworkProject._contentTypeSymbol] = type;
     },
 
-    /**
-     * @param {string} url
-     */
-    _removeFile: function(url)
-    {
-        if (!this._processedURLs[url])
-            return;
-        delete this._processedURLs[url];
-        this._removeFileForURL(url);
-    },
-
     _dispose: function()
     {
         this._reset();
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
index ffe5d5a..c64106d4 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
@@ -301,6 +301,7 @@
 
     this._resourceScriptMapping = resourceScriptMapping;
     this._uiSourceCode = uiSourceCode;
+    this._uiSourceCode.forceLoadOnCheckContent();
 
     if (this._uiSourceCode.contentType() === WebInspector.resourceTypes.Script)
         this._script = scripts[0];
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/SASSSourceMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/SASSSourceMapping.js
index 1748214..946653a 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/SASSSourceMapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/SASSSourceMapping.js
@@ -41,14 +41,9 @@
     this._cssModel = cssModel;
     this._workspace = workspace;
     this._networkProject = networkProject;
-    this._addingRevisionCounter = 0;
-    this._pollManager = new WebInspector.SASSSourceMapping.PollManager(this._cssModel, networkMapping, this._updateCSSRevision.bind(this));
     this._reset();
-    WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.SavedURL, this._fileSaveFinished, this);
     WebInspector.moduleSetting("cssSourceMapsEnabled").addChangeListener(this._toggleSourceMapSupport, this);
     this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this);
-    this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
-    this._workspace.addEventListener(WebInspector.Workspace.Events.WorkingCopyCommitted, this._uiSourceCodeContentCommitted, this);
     this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._reset, this);
     this._networkMapping = networkMapping;
 }
@@ -60,15 +55,11 @@
     _styleSheetChanged: function(event)
     {
         var id = /** @type {!CSSAgent.StyleSheetId} */ (event.data.styleSheetId);
-        if (this._addingRevisionCounter) {
-            --this._addingRevisionCounter;
-            return;
-        }
         var header = this._cssModel.styleSheetHeaderForId(id);
         if (!header)
             return;
-
         this.removeHeader(header);
+        this.addHeader(header);
     },
 
     /**
@@ -87,39 +78,6 @@
     },
 
     /**
-     * @param {!WebInspector.Event} event
-     */
-    _fileSaveFinished: function(event)
-    {
-        var sassURL = /** @type {string} */ (event.data);
-        var cssURLs = this._sassURLToCSSURLs.get(sassURL).valuesArray();
-        this._pollManager.sassFileChanged(sassURL, cssURLs, false);
-    },
-
-    /**
-     * @param {!WebInspector.UISourceCode} cssUISourceCode
-     * @param {string} content
-     * @return {boolean}
-     */
-    _updateCSSRevision: function(cssUISourceCode, content)
-    {
-        ++this._addingRevisionCounter;
-        cssUISourceCode.addRevision(content);
-        var cssURL = this._networkMapping.networkURL(cssUISourceCode);
-        var completeSourceMapURL = this._completeSourceMapURLForCSSURL[cssURL];
-        if (!completeSourceMapURL)
-            return false;
-        var ids = this._cssModel.styleSheetIdsForURL(cssURL);
-        if (!ids)
-            return false;
-        var headers = [];
-        for (var i = 0; i < ids.length; ++i)
-            headers.push(this._cssModel.styleSheetHeaderForId(ids[i]));
-        this._loadSourceMapAndBindUISourceCode(headers, true, completeSourceMapURL);
-        return true;
-    },
-
-    /**
      * @param {!WebInspector.CSSStyleSheetHeader} header
      */
     addHeader: function(header)
@@ -129,43 +87,7 @@
         var completeSourceMapURL = WebInspector.ParsedURL.completeURL(header.sourceURL, header.sourceMapURL);
         if (!completeSourceMapURL)
             return;
-        this._completeSourceMapURLForCSSURL[header.sourceURL] = completeSourceMapURL;
-        this._loadSourceMapAndBindUISourceCode([header], false, completeSourceMapURL);
-    },
-
-    /**
-     * @param {!WebInspector.CSSStyleSheetHeader} header
-     */
-    removeHeader: function(header)
-    {
-        var sourceURL = header.sourceURL;
-        if (!sourceURL || !header.sourceMapURL || !this._completeSourceMapURLForCSSURL[sourceURL])
-            return;
-        var sourceMap = this._sourceMapByStyleSheetURL[sourceURL];
-        if (sourceMap) {
-            var sources = sourceMap.sources();
-            for (var i = 0; i < sources.length; ++i)
-                this._sassURLToCSSURLs.remove(sources[i], sourceURL);
-        }
-        delete this._sourceMapByStyleSheetURL[sourceURL];
-        delete this._completeSourceMapURLForCSSURL[sourceURL];
-
-        var completeSourceMapURL = WebInspector.ParsedURL.completeURL(sourceURL, header.sourceMapURL);
-        if (completeSourceMapURL)
-            delete this._sourceMapByURL[completeSourceMapURL];
-        WebInspector.cssWorkspaceBinding.updateLocations(header);
-    },
-
-    /**
-     * @param {!Array.<!WebInspector.CSSStyleSheetHeader>} headersWithSameSourceURL
-     * @param {boolean} forceRebind
-     * @param {string} completeSourceMapURL
-     */
-    _loadSourceMapAndBindUISourceCode: function(headersWithSameSourceURL, forceRebind, completeSourceMapURL)
-    {
-        console.assert(headersWithSameSourceURL.length);
-        var sourceURL = headersWithSameSourceURL[0].sourceURL;
-        this._loadSourceMapForStyleSheet(completeSourceMapURL, sourceURL, forceRebind, sourceMapLoaded.bind(this));
+        this._loadSourceMap(completeSourceMapURL, header.sourceURL, sourceMapLoaded.bind(this));
 
         /**
          * @param {?WebInspector.SourceMap} sourceMap
@@ -173,29 +95,35 @@
          */
         function sourceMapLoaded(sourceMap)
         {
-            if (!sourceMap)
-                return;
-
-            this._sourceMapByStyleSheetURL[sourceURL] = sourceMap;
-            for (var i = 0; i < headersWithSameSourceURL.length; ++i) {
-                if (forceRebind)
-                    WebInspector.cssWorkspaceBinding.updateLocations(headersWithSameSourceURL[i]);
-                else
-                    this._bindUISourceCode(headersWithSameSourceURL[i], sourceMap);
-            }
+            if (sourceMap)
+                this._sourceMapByStyleSheetURL[header.sourceURL] = sourceMap;
+            else
+                delete this._sourceMapByStyleSheetURL[header.sourceURL];
+            WebInspector.cssWorkspaceBinding.pushSourceMapping(header, this);
         }
+
+    },
+
+    /**
+     * @param {!WebInspector.CSSStyleSheetHeader} header
+     */
+    removeHeader: function(header)
+    {
+        if (!header.sourceURL)
+            return;
+        delete this._sourceMapByStyleSheetURL[header.sourceURL];
+        WebInspector.cssWorkspaceBinding.updateLocations(header);
     },
 
     /**
      * @param {string} completeSourceMapURL
-     * @param {string} completeStyleSheetURL
-     * @param {boolean} forceReload
+     * @param {string} sourceURL
      * @param {function(?WebInspector.SourceMap)} callback
      */
-    _loadSourceMapForStyleSheet: function(completeSourceMapURL, completeStyleSheetURL, forceReload, callback)
+    _loadSourceMap: function(completeSourceMapURL, sourceURL, callback)
     {
         var sourceMap = this._sourceMapByURL[completeSourceMapURL];
-        if (sourceMap && !forceReload) {
+        if (sourceMap) {
             callback(sourceMap);
             return;
         }
@@ -209,7 +137,7 @@
         pendingCallbacks = [callback];
         this._pendingSourceMapLoadingCallbacks[completeSourceMapURL] = pendingCallbacks;
 
-        WebInspector.SourceMap.load(completeSourceMapURL, completeStyleSheetURL, sourceMapLoaded.bind(this));
+        WebInspector.SourceMap.load(completeSourceMapURL, sourceURL, sourceMapLoaded.bind(this));
 
         /**
          * @param {?WebInspector.SourceMap} sourceMap
@@ -219,33 +147,26 @@
         {
             var callbacks = this._pendingSourceMapLoadingCallbacks[completeSourceMapURL];
             delete this._pendingSourceMapLoadingCallbacks[completeSourceMapURL];
-            if (!callbacks)
-                return;
+
             if (sourceMap)
                 this._sourceMapByURL[completeSourceMapURL] = sourceMap;
             else
                 delete this._sourceMapByURL[completeSourceMapURL];
-            for (var i = 0; i < callbacks.length; ++i)
-                callbacks[i](sourceMap);
-        }
-    },
 
-    /**
-     * @param {!WebInspector.CSSStyleSheetHeader} header
-     * @param {!WebInspector.SourceMap} sourceMap
-     */
-    _bindUISourceCode: function(header, sourceMap)
-    {
-        WebInspector.cssWorkspaceBinding.pushSourceMapping(header, this);
-        var cssURL = header.sourceURL;
-        var sources = sourceMap.sources();
-        for (var i = 0; i < sources.length; ++i) {
-            var sassURL = sources[i];
-            this._sassURLToCSSURLs.set(sassURL, cssURL);
-            if (!this._networkMapping.hasMappingForURL(sassURL) && !this._networkMapping.uiSourceCodeForURL(sassURL, header.target())) {
-                var contentProvider = sourceMap.sourceContentProvider(sassURL, WebInspector.resourceTypes.Stylesheet);
-                this._networkProject.addFileForURL(sassURL, contentProvider);
+            // Then report sources.
+            var sources = sourceMap ? sourceMap.sources() : [];
+            for (var i = 0; i < sources.length; ++i) {
+                var sassURL = sources[i];
+                if (!this._networkMapping.hasMappingForURL(sassURL)) {
+                    var contentProvider = sourceMap.sourceContentProvider(sassURL, WebInspector.resourceTypes.Stylesheet);
+                    // Override source map content providers.
+                    this._networkProject.removeFileForURL(sassURL);
+                    this._networkProject.addFileForURL(sassURL, contentProvider);
+                }
             }
+
+            for (var i = 0; callbacks && i < callbacks.length; ++i)
+                callbacks[i](sourceMap);
         }
     },
 
@@ -308,340 +229,12 @@
         return this._cssModel.target();
     },
 
-    /**
-     * @param {!WebInspector.Event} event
-     */
-    _uiSourceCodeAdded: function(event)
-    {
-        var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
-        var networkURL = this._networkMapping.networkURL(uiSourceCode);
-        var cssURLs = this._sassURLToCSSURLs.get(networkURL).valuesArray();
-        if (!cssURLs)
-            return;
-        for (var i = 0; i < cssURLs.length; ++i) {
-            var ids = this._cssModel.styleSheetIdsForURL(cssURLs[i]);
-            for (var j = 0; j < ids.length; ++j) {
-                var header = this._cssModel.styleSheetHeaderForId(ids[j]);
-                console.assert(header);
-                WebInspector.cssWorkspaceBinding.updateLocations(/** @type {!WebInspector.CSSStyleSheetHeader} */ (header));
-            }
-        }
-    },
-
-    /**
-     * @param {!WebInspector.Event} event
-     */
-    _uiSourceCodeContentCommitted: function(event)
-    {
-        var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiSourceCode);
-        if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem) {
-            var networkURL = this._networkMapping.networkURL(uiSourceCode);
-            var cssURLs = this._sassURLToCSSURLs.get(networkURL).valuesArray();
-            this._pollManager.sassFileChanged(networkURL, cssURLs, true);
-        }
-    },
-
     _reset: function()
     {
-        this._addingRevisionCounter = 0;
-        this._completeSourceMapURLForCSSURL = {};
-        /** @type {!Multimap<string, string>} */
-        this._sassURLToCSSURLs = new Multimap();
         /** @type {!Object.<string, !Array.<function(?WebInspector.SourceMap)>>} */
         this._pendingSourceMapLoadingCallbacks = {};
         /** @type {!Object.<string, !WebInspector.SourceMap>} */
         this._sourceMapByURL = {};
         this._sourceMapByStyleSheetURL = {};
-        this._pollManager.reset();
     }
 }
-
-/**
- * @constructor
- * @param {!WebInspector.CSSStyleModel} cssModel
- * @param {!WebInspector.NetworkMapping} networkMapping
- * @param {function(!WebInspector.UISourceCode, string):boolean} callback
- */
-WebInspector.SASSSourceMapping.PollManager = function(cssModel, networkMapping, callback)
-{
-    this.pollPeriodMs = 30 * 1000;
-    this.pollIntervalMs = 200;
-    this._networkMapping = networkMapping;
-    this._callback = callback;
-    this._cssModel = cssModel;
-    this.reset();
-}
-
-WebInspector.SASSSourceMapping.PollManager.prototype = {
-    reset: function()
-    {
-        /** @type {!Object.<string, !{deadlineMs: number, dataByURL: !Object.<string, !{timer: number, previousPoll: number}>}>} */
-        this._pollDataForSASSURL = {};
-    },
-
-    /**
-     * @param {string} headerName
-     * @param {!Object.<string, string>} headers
-     * @return {?string}
-     */
-    _headerValue: function(headerName, headers)
-    {
-        headerName = headerName.toLowerCase();
-        var value = null;
-        for (var name in headers) {
-            if (name.toLowerCase() === headerName) {
-                value = headers[name];
-                break;
-            }
-        }
-        return value;
-    },
-
-    /**
-     * @param {!Object.<string, string>} headers
-     * @return {?Date}
-     */
-    _lastModified: function(headers)
-    {
-        var lastModifiedHeader = this._headerValue("last-modified", headers);
-        if (!lastModifiedHeader)
-            return null;
-        var lastModified = new Date(lastModifiedHeader);
-        if (isNaN(lastModified.getTime()))
-            return null;
-        return lastModified;
-    },
-
-    /**
-     * @param {!Object.<string, string>} headers
-     * @param {string} url
-     * @return {?Date}
-     */
-    _checkLastModified: function(headers, url)
-    {
-        var lastModified = this._lastModified(headers);
-        if (lastModified)
-            return lastModified;
-
-        var etagMessage = this._headerValue("etag", headers) ? ", \"ETag\" response header found instead" : "";
-        var message = String.sprintf("The \"Last-Modified\" response header is missing or invalid for %s%s. The CSS auto-reload functionality will not work correctly.", url, etagMessage);
-        WebInspector.console.log(message);
-        return null;
-    },
-
-    /**
-     * @param {string} sassURL
-     * @param {!Array.<string>} cssURLs
-     * @param {boolean} wasLoadedFromFileSystem
-     */
-    sassFileChanged: function(sassURL, cssURLs, wasLoadedFromFileSystem)
-    {
-        if (!cssURLs)
-            return;
-        if (!WebInspector.moduleSetting("cssReloadEnabled").get())
-            return;
-
-        var sassFile = this._networkMapping.uiSourceCodeForURL(sassURL, this._cssModel.target());
-        console.assert(sassFile);
-        if (wasLoadedFromFileSystem)
-            sassFile.requestMetadata(metadataReceived.bind(this));
-        else
-            WebInspector.ResourceLoader.loadUsingTargetUA(sassURL, null, sassLoadedViaNetwork.bind(this));
-
-        /**
-         * @param {number} statusCode
-         * @param {!Object.<string, string>} headers
-         * @param {string} content
-         * @this {WebInspector.SASSSourceMapping.PollManager}
-         */
-        function sassLoadedViaNetwork(statusCode, headers, content)
-        {
-            if (statusCode >= 400) {
-                console.error("Could not load content for " + sassURL + " : " + "HTTP status code: " + statusCode);
-                return;
-            }
-            var lastModified = this._checkLastModified(headers, sassURL);
-            if (!lastModified)
-                return;
-            metadataReceived.call(this, lastModified);
-        }
-
-        /**
-         * @param {?Date} timestamp
-         * @this {WebInspector.SASSSourceMapping.PollManager}
-         */
-        function metadataReceived(timestamp)
-        {
-            if (!timestamp)
-                return;
-
-            var now = Date.now();
-            var deadlineMs = now + this.pollPeriodMs;
-            var pollData = this._pollDataForSASSURL[sassURL];
-            if (pollData) {
-                var dataByURL = pollData.dataByURL;
-                for (var url in dataByURL)
-                    clearTimeout(dataByURL[url].timer);
-            }
-            pollData = { dataByURL: {}, deadlineMs: deadlineMs, sassTimestamp: timestamp };
-            this._pollDataForSASSURL[sassURL] = pollData;
-            for (var i = 0; i < cssURLs.length; ++i) {
-                pollData.dataByURL[cssURLs[i]] = { previousPoll: now };
-                this._pollCallback(cssURLs[i], sassURL);
-            }
-        }
-    },
-
-    /**
-     * @param {string} cssURL
-     * @param {string} sassURL
-     */
-    _pollCallback: function(cssURL, sassURL)
-    {
-        var now;
-        var pollData = this._pollDataForSASSURL[sassURL];
-        if (!pollData)
-            return;
-
-        if ((now = new Date().getTime()) > pollData.deadlineMs) {
-            WebInspector.console.warn(WebInspector.UIString("%s hasn't been updated in %d seconds.", cssURL, this.pollPeriodMs / 1000));
-            this._stopPolling(cssURL, sassURL);
-            return;
-        }
-        var nextPoll = this.pollIntervalMs + pollData.dataByURL[cssURL].previousPoll;
-        var remainingTimeoutMs = Math.max(0, nextPoll - now);
-        pollData.dataByURL[cssURL].previousPoll = now + remainingTimeoutMs;
-        pollData.dataByURL[cssURL].timer = setTimeout(this._reloadCSS.bind(this, cssURL, sassURL), remainingTimeoutMs);
-    },
-
-    /**
-     * @param {string} cssURL
-     * @param {string} sassURL
-     */
-    _stopPolling: function(cssURL, sassURL)
-    {
-        var pollData = this._pollDataForSASSURL[sassURL];
-        if (!pollData)
-            return;
-        delete pollData.dataByURL[cssURL];
-        if (!Object.keys(pollData.dataByURL).length)
-            delete this._pollDataForSASSURL[sassURL];
-    },
-
-    /**
-     * @param {string} cssURL
-     * @param {string} sassURL
-     */
-    _reloadCSS: function(cssURL, sassURL)
-    {
-        var cssUISourceCode = this._networkMapping.uiSourceCodeForURL(cssURL, this._cssModel.target());
-        if (!cssUISourceCode) {
-            WebInspector.console.warn(WebInspector.UIString("%s resource missing. Please reload the page.", cssURL));
-            this._stopPolling(cssURL, sassURL)
-            return;
-        }
-
-        if (this._networkMapping.hasMappingForURL(sassURL))
-            this._reloadCSSFromFileSystem(cssUISourceCode, sassURL);
-        else
-            this._reloadCSSFromNetwork(cssUISourceCode, sassURL);
-    },
-
-    /**
-     * @param {!WebInspector.UISourceCode} cssUISourceCode
-     * @param {string} sassURL
-     */
-    _reloadCSSFromNetwork: function(cssUISourceCode, sassURL)
-    {
-        var cssURL = this._networkMapping.networkURL(cssUISourceCode);
-        var data = this._pollDataForSASSURL[sassURL];
-        if (!data) {
-            this._stopPolling(cssURL, sassURL);
-            return;
-        }
-        var headers = { "if-modified-since": new Date(data.sassTimestamp.getTime() - 1000).toUTCString() };
-        WebInspector.ResourceLoader.loadUsingTargetUA(cssURL, headers, contentLoaded.bind(this));
-
-        /**
-         * @param {number} statusCode
-         * @param {!Object.<string, string>} headers
-         * @param {string} content
-         * @this {WebInspector.SASSSourceMapping.PollManager}
-         */
-        function contentLoaded(statusCode, headers, content)
-        {
-            if (statusCode >= 400) {
-                console.error("Could not load content for " + cssURL + " : " + "HTTP status code: " + statusCode);
-                this._stopPolling(cssURL, sassURL);
-                return;
-            }
-            if (!this._pollDataForSASSURL[sassURL]) {
-                this._stopPolling(cssURL, sassURL);
-                return;
-            }
-            if (statusCode === 304) {
-                this._pollCallback(cssURL, sassURL);
-                return;
-            }
-            var lastModified = this._checkLastModified(headers, cssURL);
-            if (!lastModified) {
-                this._stopPolling(cssURL, sassURL);
-                return;
-            }
-            if (lastModified.getTime() < data.sassTimestamp.getTime()) {
-                this._pollCallback(cssURL, sassURL);
-                return;
-            }
-            if (this._callback(cssUISourceCode, content))
-                this._stopPolling(cssURL, sassURL);
-        }
-    },
-
-    /**
-     * @param {!WebInspector.UISourceCode} cssUISourceCode
-     * @param {string} sassURL
-     */
-    _reloadCSSFromFileSystem: function(cssUISourceCode, sassURL)
-    {
-        cssUISourceCode.requestMetadata(metadataCallback.bind(this));
-
-        /**
-         * @param {?Date} timestamp
-         * @this {WebInspector.SASSSourceMapping.PollManager}
-         */
-        function metadataCallback(timestamp)
-        {
-            var cssURL = this._networkMapping.networkURL(cssUISourceCode);
-            if (!timestamp) {
-                this._pollCallback(cssURL, sassURL);
-                return;
-            }
-            var cssTimestamp = timestamp.getTime();
-            var pollData = this._pollDataForSASSURL[sassURL];
-            if (!pollData) {
-                this._stopPolling(cssURL, sassURL);
-                return;
-            }
-
-            if (cssTimestamp < pollData.sassTimestamp.getTime()) {
-                this._pollCallback(cssURL, sassURL);
-                return;
-            }
-
-            cssUISourceCode.requestOriginalContent(contentCallback.bind(this));
-
-            /**
-             * @param {?string} content
-             * @this {WebInspector.SASSSourceMapping.PollManager}
-             */
-            function contentCallback(content)
-            {
-                // Empty string is a valid value, null means error.
-                if (content === null)
-                    return;
-                if (this._callback(cssUISourceCode, content))
-                    this._stopPolling(cssURL, sassURL);
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
index ba4edd05f..cb3f257 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
@@ -344,6 +344,7 @@
     this._mapping = mapping;
     this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
     this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
+    this._uiSourceCode.forceLoadOnCheckContent();
     this._commitThrottler = new WebInspector.Throttler(WebInspector.StyleFile.updateTimeout);
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
index 6b24d5b..0923787 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
@@ -528,7 +528,7 @@
  */
 WebInspector.linkifyDocumentationURLAsNode = function(article, title)
 {
-    return WebInspector.linkifyURLAsNode("https://developers.google.com/web/" + article, title, undefined, true);
+    return WebInspector.linkifyURLAsNode("https://developers.google.com/web/tools/chrome-devtools/" + article, title, undefined, true);
 }
 
 /**
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ShortcutsScreen.js b/third_party/WebKit/Source/devtools/front_end/components/ShortcutsScreen.js
index 74cd709..f3b942ef 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/ShortcutsScreen.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/ShortcutsScreen.js
@@ -75,7 +75,7 @@
             orderedSections[i].renderSection(container);
 
         var note = scrollPane.createChild("p", "help-footnote");
-        note.appendChild(WebInspector.linkifyDocumentationURLAsNode("tools/iterate/inspect-styles/shortcuts", WebInspector.UIString("Full list of DevTools keyboard shortcuts and gestures")));
+        note.appendChild(WebInspector.linkifyDocumentationURLAsNode("iterate/inspect-styles/shortcuts", WebInspector.UIString("Full list of DevTools keyboard shortcuts and gestures")));
 
         return widget;
     }
diff --git a/third_party/WebKit/Source/devtools/front_end/components/domUtils.css b/third_party/WebKit/Source/devtools/front_end/components/domUtils.css
index fb9229fbb..1286b437 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/domUtils.css
+++ b/third_party/WebKit/Source/devtools/front_end/components/domUtils.css
@@ -26,3 +26,7 @@
 .stack-preview-container > tr {
     height: 17px;
 }
+
+.stack-preview-container td {
+    white-space: nowrap;
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/OverridesView.js b/third_party/WebKit/Source/devtools/front_end/emulation/OverridesView.js
index 990534c..7d211dc 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/OverridesView.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/OverridesView.js
@@ -114,7 +114,7 @@
         fieldsetElement.appendChild(WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Shrink to fit"), WebInspector.overridesSupport.settings.deviceFitWindow, true));
 
         var footnote = container.createChild("p", "help-footnote");
-        footnote.appendChild(WebInspector.linkifyDocumentationURLAsNode("setup/remote-debugging/remote-debugging", WebInspector.UIString("More information about screen emulation")));
+        footnote.appendChild(WebInspector.linkifyDocumentationURLAsNode("iterate/device-mode/", WebInspector.UIString("More information about screen emulation")));
 
         return container;
     },
diff --git a/third_party/WebKit/Source/devtools/front_end/main/FrontendWebSocketAPI.js b/third_party/WebKit/Source/devtools/front_end/main/FrontendWebSocketAPI.js
index 2d684221..322da62 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/FrontendWebSocketAPI.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/FrontendWebSocketAPI.js
@@ -74,7 +74,7 @@
                 if (buffer !== uiSourceCode.workingCopy())
                     uiSourceCode.setWorkingCopy(buffer);
                 if (saved)
-                    uiSourceCode.checkContentUpdated();
+                    uiSourceCode.checkContentUpdated(true);
             }
             break;
         default:
diff --git a/third_party/WebKit/Source/devtools/front_end/network/RequestTimingView.js b/third_party/WebKit/Source/devtools/front_end/network/RequestTimingView.js
index 5922f70..b3fa9b1 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/RequestTimingView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/RequestTimingView.js
@@ -275,7 +275,7 @@
     var footer = tableElement.createChild("tr", "network-timing-footer");
     var note = footer.createChild("td");
     note.colSpan = 2;
-    note.appendChild(WebInspector.linkifyDocumentationURLAsNode("tools/profile-performance/network-performance/resource-loading#resource-network-timing", WebInspector.UIString("Explanation")));
+    note.appendChild(WebInspector.linkifyDocumentationURLAsNode("profile/network-performance/resource-loading#view-network-timing-details-for-a-specific-resource", WebInspector.UIString("Explanation")));
     footer.createChild("td").createTextChild(Number.secondsToString(totalDuration, true));
 
     return tableElement;
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
index 2be3dd5..89cb637e 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
@@ -525,6 +525,7 @@
             return;
         var profile = new WebInspector.CPUProfileHeader(target, this);
         this.setProfileBeingRecorded(profile);
+        WebInspector.targetManager.suspendAllTargets();
         this.addProfile(profile);
         profile.updateStatus(WebInspector.UIString("Recording\u2026"));
         this._recording = true;
@@ -537,6 +538,8 @@
         if (!this._profileBeingRecorded || !this._profileBeingRecorded.target())
             return;
 
+        var recordedProfile;
+
         /**
          * @param {?ProfilerAgent.CPUProfile} profile
          * @this {WebInspector.CPUProfileType}
@@ -548,11 +551,22 @@
             console.assert(profile);
             this._profileBeingRecorded.setProtocolProfile(profile);
             this._profileBeingRecorded.updateStatus("");
-            var recordedProfile = this._profileBeingRecorded;
+            recordedProfile = this._profileBeingRecorded;
             this.setProfileBeingRecorded(null);
+        }
+
+        /**
+         * @this {WebInspector.CPUProfileType}
+         */
+        function fireEvent()
+        {
             this.dispatchEventToListeners(WebInspector.ProfileType.Events.ProfileComplete, recordedProfile);
         }
-        this._profileBeingRecorded.target().cpuProfilerModel.stopRecording().then(didStopProfiling.bind(this));
+
+        this._profileBeingRecorded.target().cpuProfilerModel.stopRecording()
+            .then(didStopProfiling.bind(this))
+            .then(WebInspector.targetManager.resumeAllTargets.bind(WebInspector.targetManager))
+            .then(fireEvent.bind(this));
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js
index 8ed6e1e..8d3883ce 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js
@@ -242,10 +242,6 @@
      */
     setProfileBeingRecorded: function(profile)
     {
-        if (this._profileBeingRecorded && this._profileBeingRecorded.target())
-            WebInspector.targetManager.resumeAllTargets();
-        if (profile && profile.target())
-            WebInspector.targetManager.suspendAllTargets();
         this._profileBeingRecorded = profile;
     },
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfilerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfilerModel.js
index 0b5a73fb..1a2e144 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfilerModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfilerModel.js
@@ -44,8 +44,6 @@
 }
 
 WebInspector.CPUProfilerModel.EventTypes = {
-    ProfileStarted: "ProfileStarted",
-    ProfileStopped: "ProfileStopped",
     ConsoleProfileStarted: "ConsoleProfileStarted",
     ConsoleProfileFinished: "ConsoleProfileFinished"
 };
@@ -113,7 +111,6 @@
     {
         this._isRecording = true;
         this.target().profilerAgent().start();
-        this.dispatchEventToListeners(WebInspector.CPUProfilerModel.EventTypes.ProfileStarted);
         WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.ProfilesCPUProfileTaken);
     },
 
@@ -132,7 +129,6 @@
             return !error && profile ? profile : null;
         }
         this._isRecording = false;
-        this.dispatchEventToListeners(WebInspector.CPUProfilerModel.EventTypes.ProfileStopped);
         return this.target().profilerAgent().stop(extractProfile);
     },
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js
index d7d3797..7c6b009 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js
@@ -38,7 +38,6 @@
     WebInspector.SDKModel.call(this, WebInspector.CSSStyleModel, target);
     this._domModel = WebInspector.DOMModel.fromTarget(target);
     this._agent = target.cssAgent();
-    WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this);
     this._styleLoader = new WebInspector.CSSStyleModel.ComputedStyleLoader(this);
     target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this);
     target.registerCSSDispatcher(new WebInspector.CSSDispatcher(this));
@@ -459,9 +458,6 @@
      */
     _fireStyleSheetChanged: function(styleSheetId)
     {
-        if (!styleSheetId || !this.hasEventListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged))
-            return;
-
         this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId });
     },
 
@@ -567,14 +563,23 @@
             this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, headers[i]);
     },
 
-    _suspendStateChanged: function()
+    /**
+     * @override
+     * @return {!Promise}
+     */
+    suspendModel: function()
     {
-        if (WebInspector.targetManager.allTargetsSuspended()) {
-            this._agent.disable(this._resetStyleSheets.bind(this));
-            this._isEnabled = false;
-        } else {
-            this._agent.enable().then(this._wasEnabled.bind(this));
-        }
+        this._isEnabled = false;
+        return this._agent.disable().then(this._resetStyleSheets.bind(this));
+    },
+
+    /**
+     * @override
+     * @return {!Promise}
+     */
+    resumeModel: function()
+    {
+        return this._agent.enable().then(this._wasEnabled.bind(this));
     },
 
     /**
@@ -1875,14 +1880,17 @@
         newText = this._trimSourceURL(newText);
         if (this.hasSourceURL)
             newText += "\n/*# sourceURL=" + this.sourceURL + " */";
-        return this._cssModel._agent.setStyleSheetText(this.id, newText, extractProtocolError);
+        return this._cssModel._agent.setStyleSheetText(this.id, newText, callback.bind(this));
 
         /**
          * @param {?Protocol.Error} error
+         * @param {string=} sourceMapURL
          * @return {?Protocol.Error}
+         * @this {WebInspector.CSSStyleSheetHeader}
          */
-        function extractProtocolError(error)
+        function callback(error, sourceMapURL)
         {
+            this.sourceMapURL = sourceMapURL;
             return error || null;
         }
     },
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
index 8191d53..6403e58 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
@@ -1075,7 +1075,6 @@
     WebInspector.SDKModel.call(this, WebInspector.DOMModel, target);
 
     this._agent = target.domAgent();
-    WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this);
 
     /** @type {!Object.<number, !WebInspector.DOMNode>} */
     this._idToDOMNode = {};
@@ -1942,12 +1941,48 @@
             callback(null);
     },
 
-    _suspendStateChanged: function()
+    /**
+     * @override
+     * @return {!Promise}
+     */
+    suspendModel: function()
     {
-        if (WebInspector.targetManager.allTargetsSuspended()) {
-            this._agent.disable(this._setDocument.bind(this, null));
-        } else {
-            this._agent.enable();
+        return new Promise(promiseBody.bind(this));
+
+        /**
+         * @param {function()} fulfill
+         * @this {WebInspector.DOMModel}
+         */
+        function promiseBody(fulfill)
+        {
+            this._agent.disable(callback.bind(this));
+
+            /**
+             * @this {WebInspector.DOMModel}
+             */
+            function callback()
+            {
+                this._setDocument(null);
+                fulfill();
+            }
+        }
+    },
+
+    /**
+     * @override
+     * @return {!Promise}
+     */
+    resumeModel: function()
+    {
+        return new Promise(promiseBody.bind(this));
+
+        /**
+         * @param {function()} fulfill
+         * @this {WebInspector.DOMModel}
+         */
+        function promiseBody(fulfill)
+        {
+            this._agent.enable(fulfill);
         }
     },
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
index 75b4f3a..968ac81d 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -39,7 +39,6 @@
 
     target.registerDebuggerDispatcher(new WebInspector.DebuggerDispatcher(this));
     this._agent = target.debuggerAgent();
-    WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this);
     WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.TargetDisposed, this._targetDisposed, this);
 
     /** @type {?WebInspector.DebuggerPausedDetails} */
@@ -121,23 +120,35 @@
         return !!this._debuggerEnabled;
     },
 
-    enableDebugger: function()
+    /**
+     * @param {function()=} callback
+     */
+    enableDebugger: function(callback)
     {
-        if (this._debuggerEnabled)
+        if (this._debuggerEnabled) {
+            if (callback)
+                callback();
             return;
-        this._agent.enable();
+        }
+        this._agent.enable(callback);
         this._debuggerEnabled = true;
         this._pauseOnExceptionStateChanged();
         this.asyncStackTracesStateChanged();
         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasEnabled);
     },
 
-    disableDebugger: function()
+    /**
+     * @param {function()=} callback
+     */
+    disableDebugger: function(callback)
     {
-        if (!this._debuggerEnabled)
+        if (!this._debuggerEnabled) {
+            if (callback)
+                callback();
             return;
+        }
 
-        this._agent.disable();
+        this._agent.disable(callback);
         this._debuggerEnabled = false;
         this._isPausing = false;
         this.asyncStackTracesStateChanged();
@@ -185,7 +196,7 @@
     asyncStackTracesStateChanged: function()
     {
         const maxAsyncStackChainDepth = 4;
-        var enabled = WebInspector.moduleSetting("enableAsyncStackTraces").get() && !WebInspector.targetManager.allTargetsSuspended();
+        var enabled = WebInspector.moduleSetting("enableAsyncStackTraces").get() && this._debuggerEnabled;
         this._agent.setAsyncCallStackDepth(enabled ? maxAsyncStackChainDepth : 0);
     },
 
@@ -903,12 +914,40 @@
         WebInspector.moduleSetting("enableAsyncStackTraces").removeChangeListener(this.asyncStackTracesStateChanged, this);
     },
 
-    _suspendStateChanged: function()
+    /**
+     * @override
+     * @return {!Promise}
+     */
+    suspendModel: function()
     {
-        if (WebInspector.targetManager.allTargetsSuspended())
-            this.disableDebugger();
-        else
-            this.enableDebugger();
+        return new Promise(promiseBody.bind(this));
+
+        /**
+         * @param {function()} fulfill
+         * @this {WebInspector.DebuggerModel}
+         */
+        function promiseBody(fulfill)
+        {
+            this.disableDebugger(fulfill);
+        }
+    },
+
+    /**
+     * @override
+     * @return {!Promise}
+     */
+    resumeModel: function()
+    {
+        return new Promise(promiseBody.bind(this));
+
+        /**
+         * @param {function()} fulfill
+         * @this {WebInspector.DebuggerModel}
+         */
+        function promiseBody(fulfill)
+        {
+            this.enableDebugger(fulfill);
+        }
     },
 
     __proto__: WebInspector.SDKModel.prototype
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/Target.js b/third_party/WebKit/Source/devtools/front_end/sdk/Target.js
index a692d26..cb08d14 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/Target.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/Target.js
@@ -285,6 +285,22 @@
 }
 
 WebInspector.SDKModel.prototype = {
+    /**
+     * @return {!Promise}
+     */
+    suspendModel: function()
+    {
+        return Promise.resolve();
+    },
+
+    /**
+     * @return {!Promise}
+     */
+    resumeModel: function()
+    {
+        return Promise.resolve();
+    },
+
     __proto__: WebInspector.SDKObject.prototype
 }
 
@@ -302,8 +318,7 @@
     this._observerTypeSymbol = Symbol("observerType");
     /** @type {!Object.<string, !Array.<{modelClass: !Function, thisObject: (!Object|undefined), listener: function(!WebInspector.Event)}>>} */
     this._modelListeners = {};
-    /** @type {number} */
-    this._suspendCount = 0;
+    this._isSuspended = false;
 }
 
 WebInspector.TargetManager.Events = {
@@ -312,24 +327,40 @@
     Load: "Load",
     PageReloadRequested: "PageReloadRequested",
     WillReloadPage: "WillReloadPage",
-    SuspendStateChanged: "SuspendStateChanged",
-    TargetDisposed: "TargetDisposed"
+    TargetDisposed: "TargetDisposed",
+    SuspendStateChanged: "SuspendStateChanged"
 }
 
 WebInspector.TargetManager.prototype = {
     suspendAllTargets: function()
     {
-        if (this._suspendCount++)
+        if (this._isSuspended)
             return;
+        this._isSuspended = true;
         this.dispatchEventToListeners(WebInspector.TargetManager.Events.SuspendStateChanged);
+
+        for (var i = 0; i < this._targets.length; ++i) {
+            for (var model of this._targets[i]._modelByConstructor.values())
+                model.suspendModel();
+        }
     },
 
+    /**
+     * @return {!Promise}
+     */
     resumeAllTargets: function()
     {
-        console.assert(this._suspendCount > 0);
-        if (--this._suspendCount)
-            return;
+        if (!this._isSuspended)
+            throw new Error("Not suspended");
+        this._isSuspended = false;
         this.dispatchEventToListeners(WebInspector.TargetManager.Events.SuspendStateChanged);
+
+        var promises = [];
+        for (var i = 0; i < this._targets.length; ++i) {
+            for (var model of this._targets[i]._modelByConstructor.values())
+                promises.push(model.resumeModel());
+        }
+        return Promise.all(promises);
     },
 
     suspendAndResumeAllTargets: function()
@@ -343,7 +374,7 @@
      */
     allTargetsSuspended: function()
     {
-        return !!this._suspendCount;
+        return this._isSuspended;
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/AddSourceMapURLDialog.js b/third_party/WebKit/Source/devtools/front_end/sources/AddSourceMapURLDialog.js
index a68effbe..c3aea93 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/AddSourceMapURLDialog.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/AddSourceMapURLDialog.js
@@ -23,6 +23,7 @@
 
     this.setDefaultFocusedElement(this._input);
     this._callback = callback;
+    this.contentElement.tabIndex = 0;
 }
 
 /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesSearchScope.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesSearchScope.js
index b7b34cf..2520b99 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesSearchScope.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesSearchScope.js
@@ -221,7 +221,7 @@
             if (uiSourceCode.isDirty())
                 contentLoaded.call(this, uiSourceCode, uiSourceCode.workingCopy());
             else
-                uiSourceCode.checkContentUpdated(contentUpdated.bind(this, uiSourceCode));
+                uiSourceCode.checkContentUpdated(true, contentUpdated.bind(this, uiSourceCode));
         }
 
         /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
index 2f286a9..4e7cd670 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
@@ -97,7 +97,7 @@
     {
         if (!this.loaded || !this.isShowing())
             return;
-        this._uiSourceCode.checkContentUpdated();
+        this._uiSourceCode.checkContentUpdated(true);
     },
 
     commitEditing: function()
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/WorkspaceMappingTip.js b/third_party/WebKit/Source/devtools/front_end/sources/WorkspaceMappingTip.js
index bc21c973..5043d1df 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/WorkspaceMappingTip.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/WorkspaceMappingTip.js
@@ -163,7 +163,7 @@
         var uiSourceCodeFrame = this._sourcesView.viewForFile(uiSourceCode);
 
         var rowElement = infobar.createDetailsRowMessage(WebInspector.UIString("For more information on workspaces, refer to the "));
-        rowElement.appendChild(WebInspector.linkifyDocumentationURLAsNode("tools/setup/workspace/setup-workflow", WebInspector.UIString("workspaces documentation")));
+        rowElement.appendChild(WebInspector.linkifyDocumentationURLAsNode("../setup/setup-workflow", WebInspector.UIString("workspaces documentation")));
         rowElement.createTextChild(".");
         uiSourceCode[WebInspector.WorkspaceMappingTip._infobarSymbol] = infobar;
         uiSourceCodeFrame.attachInfobars([infobar]);
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
index 0c74c0e..eed17055 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
@@ -259,13 +259,6 @@
 WebInspector.TimelineEventOverview.CPUActivity = function(model)
 {
     WebInspector.TimelineEventOverview.call(this, "cpu-activity", WebInspector.UIString("CPU"), model);
-    this._fillStyles = {};
-    var categories = WebInspector.TimelineUIUtils.categories();
-    for (var category in categories) {
-        this._fillStyles[category] = categories[category].fillColorStop1;
-        categories[category].addEventListener(WebInspector.TimelineCategory.Events.VisibilityChanged, this._onCategoryVisibilityChanged, this);
-    }
-    this._disabledCategoryFillStyle = "hsl(0, 0%, 67%)";
     this._backgroundCanvas = this.element.createChild("canvas", "fill background");
 }
 
@@ -273,31 +266,6 @@
     /**
      * @override
      */
-    dispose: function()
-    {
-        WebInspector.TimelineOverviewBase.prototype.dispose.call(this);
-        var categories = WebInspector.TimelineUIUtils.categories();
-        for (var category in categories)
-            categories[category].removeEventListener(WebInspector.TimelineCategory.Events.VisibilityChanged, this._onCategoryVisibilityChanged, this);
-    },
-
-    _onCategoryVisibilityChanged: function()
-    {
-        this.update();
-    },
-
-    /**
-     * @param {!WebInspector.TimelineCategory} category
-     * @return {string}
-     */
-    _categoryColor: function(category)
-    {
-        return category.hidden ? this._disabledCategoryFillStyle : this._fillStyles[category.name];
-    },
-
-    /**
-     * @override
-     */
     resetCanvas: function()
     {
         WebInspector.TimelineEventOverview.prototype.resetCanvas.call(this);
@@ -329,14 +297,13 @@
 
         var backgroundContext = this._backgroundCanvas.getContext("2d");
         for (var thread of this._model.virtualThreads())
-            drawThreadEvents.call(this, backgroundContext, thread.events);
+            drawThreadEvents(backgroundContext, thread.events);
         applyPattern(backgroundContext);
-        drawThreadEvents.call(this, this._context, this._model.mainThreadEvents());
+        drawThreadEvents(this._context, this._model.mainThreadEvents());
 
         /**
          * @param {!CanvasRenderingContext2D} ctx
          * @param {!Array<!WebInspector.TracingModel.Event>} events
-         * @this {WebInspector.TimelineEventOverview}
          */
         function drawThreadEvents(ctx, events)
         {
@@ -388,7 +355,7 @@
             quantizer.appendInterval(timeOffset + timeSpan + quantTime, idleIndex);  // Kick drawing the last bucket.
             for (var i = categoryOrder.length - 1; i > 0; --i) {
                 paths[i].lineTo(width, height);
-                ctx.fillStyle = this._categoryColor(categories[categoryOrder[i]]);
+                ctx.fillStyle = categories[categoryOrder[i]].fillColorStop1;
                 ctx.fill(paths[i]);
             }
         }
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
index e7f7565..a567915 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -1040,11 +1040,11 @@
         case WebInspector.TimelineSelection.Type.Record:
             var record = /** @type {!WebInspector.TimelineModel.Record} */ (this._selection.object());
             var event = record.traceEvent();
-            WebInspector.TimelineUIUtils.buildTraceEventDetails(event, this._model, this._detailsLinkifier, this._appendDetailsTabsForTraceEventAndShowDetails.bind(this, event));
+            WebInspector.TimelineUIUtils.buildTraceEventDetails(event, this._model, this._detailsLinkifier, true, this._appendDetailsTabsForTraceEventAndShowDetails.bind(this, event));
             break;
         case WebInspector.TimelineSelection.Type.TraceEvent:
             var event = /** @type {!WebInspector.TracingModel.Event} */ (this._selection.object());
-            WebInspector.TimelineUIUtils.buildTraceEventDetails(event, this._model, this._detailsLinkifier, this._appendDetailsTabsForTraceEventAndShowDetails.bind(this, event));
+            WebInspector.TimelineUIUtils.buildTraceEventDetails(event, this._model, this._detailsLinkifier, true, this._appendDetailsTabsForTraceEventAndShowDetails.bind(this, event));
             break;
         case WebInspector.TimelineSelection.Type.Frame:
             var frame = /** @type {!WebInspector.TimelineFrame} */ (this._selection.object());
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
index 3ed893b..1a2ffa3 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -42,7 +42,7 @@
 
     if (Runtime.experiments.isEnabled("timelineEventsTreeView")) {
         this._detailsView = new WebInspector.VBox();
-        this._detailsView.element.classList.add("timeline-tree-view-details");
+        this._detailsView.element.classList.add("timeline-tree-view-details", "timeline-details-view-body");
         this._splitWidget.setSidebarWidget(this._detailsView);
         this._showBannerInDetails();
         this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, onSelectionChanged, this);
@@ -764,7 +764,7 @@
         var traceEvent = node.event;
         if (!traceEvent)
             return false;
-        WebInspector.TimelineUIUtils.buildTraceEventDetails(traceEvent, this._model, this._linkifier, showDetails.bind(this));
+        WebInspector.TimelineUIUtils.buildTraceEventDetails(traceEvent, this._model, this._linkifier, false, showDetails.bind(this));
         return true;
 
         /**
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
index f5f07ae..158e70c6 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -517,9 +517,10 @@
  * @param {!WebInspector.TracingModel.Event} event
  * @param {!WebInspector.TimelineModel} model
  * @param {!WebInspector.Linkifier} linkifier
+ * @param {boolean} detailed
  * @param {function(!DocumentFragment)} callback
  */
-WebInspector.TimelineUIUtils.buildTraceEventDetails = function(event, model, linkifier, callback)
+WebInspector.TimelineUIUtils.buildTraceEventDetails = function(event, model, linkifier, detailed, callback)
 {
     var target = model.target();
     if (!target) {
@@ -564,7 +565,7 @@
 
     function callbackWrapper()
     {
-        callback(WebInspector.TimelineUIUtils._buildTraceEventDetailsSynchronously(event, model, linkifier, relatedNodes));
+        callback(WebInspector.TimelineUIUtils._buildTraceEventDetailsSynchronously(event, model, linkifier, detailed, relatedNodes));
     }
 }
 
@@ -572,10 +573,11 @@
  * @param {!WebInspector.TracingModel.Event} event
  * @param {!WebInspector.TimelineModel} model
  * @param {!WebInspector.Linkifier} linkifier
+ * @param {boolean} detailed
  * @param {?Map<number, ?WebInspector.DOMNode>} relatedNodesMap
  * @return {!DocumentFragment}
  */
-WebInspector.TimelineUIUtils._buildTraceEventDetailsSynchronously = function(event, model, linkifier, relatedNodesMap)
+WebInspector.TimelineUIUtils._buildTraceEventDetailsSynchronously = function(event, model, linkifier, detailed, relatedNodesMap)
 {
     var fragment = createDocumentFragment();
     var stats = {};
@@ -589,9 +591,11 @@
     if (event.warning)
         contentHelper.appendWarningRow(event.warning, event);
 
-    contentHelper.appendTextRow(WebInspector.UIString("Type"), WebInspector.TimelineUIUtils.eventTitle(event));
-    contentHelper.appendTextRow(WebInspector.UIString("Total Time"), Number.millisToString(event.duration || 0, true));
-    contentHelper.appendTextRow(WebInspector.UIString("Self Time"), Number.millisToString(event.selfTime, true));
+    if (detailed) {
+        contentHelper.appendTextRow(WebInspector.UIString("Type"), WebInspector.TimelineUIUtils.eventTitle(event));
+        contentHelper.appendTextRow(WebInspector.UIString("Total Time"), Number.millisToString(event.duration || 0, true));
+        contentHelper.appendTextRow(WebInspector.UIString("Self Time"), Number.millisToString(event.selfTime, true));
+    }
     if (event.previewElement)
         contentHelper.appendElementRow(WebInspector.UIString("Preview"), event.previewElement);
 
@@ -748,8 +752,8 @@
     if (event.stackTrace || (event.initiator && event.initiator.stackTrace) || event.invalidationTrackingEvents)
         WebInspector.TimelineUIUtils._generateCauses(event, model.target(), contentHelper);
 
-    var hasChildren = WebInspector.TimelineUIUtils._aggregatedStatsForTraceEvent(stats, model, event);
-    if (hasChildren) {
+    var showPieChart = detailed && WebInspector.TimelineUIUtils._aggregatedStatsForTraceEvent(stats, model, event);
+    if (showPieChart) {
         var pieChart = WebInspector.TimelineUIUtils.generatePieChart(stats, WebInspector.TimelineUIUtils.eventStyle(event).category, event.selfTime);
         contentHelper.appendElementRow(WebInspector.UIString("Aggregated Time"), pieChart);
     }
@@ -2045,7 +2049,7 @@
         switch (warningType) {
         case warnings.ForcedStyle:
         case warnings.ForcedLayout:
-            span.appendChild(WebInspector.linkifyDocumentationURLAsNode("fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts",
+            span.appendChild(WebInspector.linkifyDocumentationURLAsNode("../../fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts",
                 WebInspector.UIString("Forced reflow")));
             span.createTextChild(WebInspector.UIString(" is a likely performance bottleneck."));
             break;
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
index 94e8e8b..80d1086 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -1033,3 +1033,7 @@
     background-color: rgba(255, 255, 255, 0.25);
     border-bottom-color: transparent;
 }
+
+.timeline-tree-view .timeline-details-view-body .banner {
+    background-color: inherit;
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
index c8e59cf..5e5889ba 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
@@ -254,20 +254,27 @@
     },
 
     /**
+     * @param {boolean=} forceLoad
      * @param {function()=} callback
      */
-    checkContentUpdated: function(callback)
+    checkContentUpdated: function(forceLoad, callback)
     {
         callback = callback || function() {};
+        forceLoad = forceLoad || this._forceLoadOnCheckContent;
+        if (!this.contentLoaded() && !forceLoad) {
+            callback();
+            return;
+        }
+
         if (!this._project.canSetFileContent()) {
             callback();
             return;
         }
         this._pushCheckContentUpdatedCallback(callback);
 
-        if (this._checkingContent) {
+        if (this._checkingContent)
             return;
-        }
+
         this._checkingContent = true;
         this._project.requestFileContent(this, contentLoaded.bind(this));
 
@@ -310,6 +317,11 @@
         }
     },
 
+    forceLoadOnCheckContent: function()
+    {
+        this._forceLoadOnCheckContent = true;
+    },
+
     /**
      * @param {function(?string)} callback
      */
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/Workspace.js b/third_party/WebKit/Source/devtools/front_end/workspace/Workspace.js
index 10de8f5..a81a122 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/Workspace.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/Workspace.js
@@ -306,7 +306,7 @@
     {
         var path = /** @type {string} */ (event.data);
         var uiSourceCode = this.uiSourceCode(path);
-        if (uiSourceCode && uiSourceCode.contentLoaded())
+        if (uiSourceCode)
             uiSourceCode.checkContentUpdated();
     },
 
diff --git a/third_party/WebKit/Source/devtools/protocol.json b/third_party/WebKit/Source/devtools/protocol.json
index 482956ff..47d4bac 100644
--- a/third_party/WebKit/Source/devtools/protocol.json
+++ b/third_party/WebKit/Source/devtools/protocol.json
@@ -3224,6 +3224,9 @@
                     { "name": "styleSheetId", "$ref": "StyleSheetId" },
                     { "name": "text", "type": "string" }
                 ],
+                "returns": [
+                    { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." }
+                ],
                 "description": "Sets the new stylesheet text."
             },
             {
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
index 54b384b..fb97ce9 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -401,6 +401,8 @@
     return AXNodeObject::isEditable();
 }
 
+// Requires layoutObject to be present because it relies on style
+// user-modify. Don't move this logic to AXNodeObject.
 bool AXLayoutObject::isRichlyEditable() const
 {
     if (node() && node()->isContentRichlyEditable())
@@ -1827,19 +1829,16 @@
         return AXRange();
 
     VisibleSelection selection = layoutObject()->frame()->selection().selection();
-    RefPtrWillBeRawPtr<Range> selectionRange = firstRangeOf(selection);
-    if (!selectionRange)
+    if (selection.isNone())
         return AXRange();
 
-    int anchorOffset = selectionRange->startOffset();
-    ASSERT(anchorOffset >= 0);
-    int focusOffset = selectionRange->endOffset();
-    ASSERT(focusOffset >= 0);
+    Position visibleStart = selection.visibleStart().toParentAnchoredPosition();
+    Position visibleEnd = selection.visibleEnd().toParentAnchoredPosition();
 
-    Node* anchorNode = selectionRange->startContainer();
+    Node* anchorNode = visibleStart.anchorNode();
     ASSERT(anchorNode);
 
-    AXObject* anchorObject = nullptr;
+    AXLayoutObject* anchorObject = nullptr;
     // Find the closest node that has a corresponding AXObject.
     // This is because some nodes may be aria hidden or might not even have
     // a layout object if they are part of the shadow DOM.
@@ -1853,13 +1852,11 @@
         else
             anchorNode = anchorNode->parentNode();
     }
-    if (anchorNode != selectionRange->startContainer())
-        anchorOffset = 0;
 
-    Node* focusNode = selectionRange->endContainer();
+    Node* focusNode = visibleEnd.anchorNode();
     ASSERT(focusNode);
 
-    AXObject* focusObject = nullptr;
+    AXLayoutObject* focusObject = nullptr;
     while (focusNode) {
         focusObject = getUnignoredObjectFromNode(*focusNode);
         if (focusObject)
@@ -1870,12 +1867,16 @@
         else
             focusNode = focusNode->parentNode();
     }
-    if (focusNode != selectionRange->endContainer())
-        focusOffset = 0;
 
     if (!anchorObject || !focusObject)
         return AXRange();
 
+    int anchorOffset = anchorObject->indexForVisiblePosition(
+        selection.visibleStart());
+    ASSERT(anchorOffset >= 0);
+    int focusOffset = focusObject->indexForVisiblePosition(
+        selection.visibleEnd());
+    ASSERT(focusOffset >= 0);
     return AXRange(
         anchorObject, anchorOffset,
         focusObject, focusOffset);
@@ -2160,9 +2161,6 @@
     if (m_layoutObject->isTextControl())
         return toLayoutTextControl(m_layoutObject)->textFormControlElement()->visiblePositionForIndex(index);
 
-    if (!allowsTextRanges() && !m_layoutObject->isText())
-        return VisiblePosition();
-
     Node* node = m_layoutObject->node();
     if (!node)
         return VisiblePosition();
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h
index b6db707d..576ab621 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h
@@ -74,7 +74,6 @@
 
     bool hasContentEditableAttributeSet() const;
     bool isTextControl() const override;
-    bool allowsTextRanges() const { return isTextControl(); }
     // This returns true if it's focusable but it's not content editable and it's not a control or ARIA control.
     bool isGenericFocusableElement() const;
     HTMLLabelElement* labelForElement(const Element*) const;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
index 59cead9..3b68f15f 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -1357,29 +1357,30 @@
         parent->selectionChanged();
 }
 
-int AXObject::lineForPosition(const VisiblePosition& visiblePos) const
+int AXObject::lineForPosition(const VisiblePosition& position) const
 {
-    if (visiblePos.isNull() || !node())
+    if (position.isNull() || !node())
         return -1;
 
     // If the position is not in the same editable region as this AX object, return -1.
-    Node* containerNode = visiblePos.deepEquivalent().computeContainerNode();
+    Node* containerNode = position.deepEquivalent().computeContainerNode();
     if (!containerNode->containsIncludingShadowDOM(node()) && !node()->containsIncludingShadowDOM(containerNode))
         return -1;
 
     int lineCount = -1;
-    VisiblePosition currentVisiblePos = visiblePos;
-    VisiblePosition savedVisiblePos;
+    VisiblePosition currentPosition = position;
+    VisiblePosition previousPosition;
 
     // move up until we get to the top
     // FIXME: This only takes us to the top of the rootEditableElement, not the top of the
     // top document.
     do {
-        savedVisiblePos = currentVisiblePos;
-        VisiblePosition prevVisiblePos = previousLinePosition(currentVisiblePos, 0, HasEditableAXRole);
-        currentVisiblePos = prevVisiblePos;
+        previousPosition = currentPosition;
+        currentPosition = previousLinePosition(
+            currentPosition, 0, HasEditableAXRole);
         ++lineCount;
-    } while (currentVisiblePos.isNotNull() && !(inSameLine(currentVisiblePos, savedVisiblePos)));
+    } while (currentPosition.isNotNull()
+        && !inSameLine(currentPosition, previousPosition));
 
     return lineCount;
 }
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp
index e0f24941..fd0def7 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp
@@ -31,6 +31,7 @@
 #include "bindings/core/v8/Nullable.h"
 #include "bindings/core/v8/SerializedScriptValue.h"
 #include "bindings/modules/v8/V8BindingForModules.h"
+#include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/events/EventQueue.h"
 #include "core/inspector/ScriptCallStack.h"
@@ -149,7 +150,7 @@
         closeConnection();
 }
 
-void IDBDatabase::onAbort(int64_t transactionId, DOMError* error)
+void IDBDatabase::onAbort(int64_t transactionId, DOMException* error)
 {
     ASSERT(m_transactions.contains(transactionId));
     m_transactions.get(transactionId)->onAbort(error);
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h
index 297ece41..bfa68306 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h
@@ -48,7 +48,7 @@
 
 namespace blink {
 
-class DOMError;
+class DOMException;
 class ExceptionState;
 class ExecutionContext;
 
@@ -86,7 +86,7 @@
 
     // IDBDatabaseCallbacks
     void onVersionChange(int64_t oldVersion, int64_t newVersion);
-    void onAbort(int64_t, DOMError*);
+    void onAbort(int64_t, DOMException*);
     void onComplete(int64_t);
 
     // ActiveDOMObject
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.cpp
index 2de84e8..5af0bd6 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.cpp
@@ -68,7 +68,7 @@
     m_database = database;
 }
 
-void IDBDatabaseCallbacks::onAbort(int64_t transactionId, DOMError* error)
+void IDBDatabaseCallbacks::onAbort(int64_t transactionId, DOMException* error)
 {
     if (m_database)
         m_database->onAbort(transactionId, error);
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.h b/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.h
index 722df10..58cfde86 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.h
@@ -32,7 +32,7 @@
 
 namespace blink {
 
-class DOMError;
+class DOMException;
 class IDBDatabase;
 
 class MODULES_EXPORT IDBDatabaseCallbacks : public GarbageCollectedFinalized<IDBDatabaseCallbacks> {
@@ -45,7 +45,7 @@
     virtual void onForcedClose();
     virtual void onVersionChange(int64_t oldVersion, int64_t newVersion);
 
-    virtual void onAbort(int64_t transactionId, DOMError*);
+    virtual void onAbort(int64_t transactionId, DOMException*);
     virtual void onComplete(int64_t transactionId);
 
     void connect(IDBDatabase*);
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp
index 385a831e..5801007 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp
@@ -31,6 +31,7 @@
 
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/modules/v8/V8BindingForModules.h"
+#include "core/dom/DOMException.h"
 #include "core/dom/Document.h"
 #include "core/dom/ExceptionCode.h"
 #include "modules/indexeddb/IDBDatabase.h"
@@ -83,7 +84,7 @@
     IDBRequest* request = IDBRequest::create(scriptState, IDBAny::createNull(), nullptr);
 
     if (!m_permissionClient->allowIndexedDB(scriptState->executionContext(), "Database Listing")) {
-        request->onError(DOMError::create(UnknownError, permissionDeniedErrorMessage));
+        request->onError(DOMException::create(UnknownError, permissionDeniedErrorMessage));
         return request;
     }
 
@@ -117,7 +118,7 @@
     IDBOpenDBRequest* request = IDBOpenDBRequest::create(scriptState, databaseCallbacks, transactionId, version);
 
     if (!m_permissionClient->allowIndexedDB(scriptState->executionContext(), name)) {
-        request->onError(DOMError::create(UnknownError, permissionDeniedErrorMessage));
+        request->onError(DOMException::create(UnknownError, permissionDeniedErrorMessage));
         return request;
     }
 
@@ -145,7 +146,7 @@
     IDBOpenDBRequest* request = IDBOpenDBRequest::create(scriptState, nullptr, 0, IDBDatabaseMetadata::DefaultIntVersion);
 
     if (!m_permissionClient->allowIndexedDB(scriptState->executionContext(), name)) {
-        request->onError(DOMError::create(UnknownError, permissionDeniedErrorMessage));
+        request->onError(DOMException::create(UnknownError, permissionDeniedErrorMessage));
         return request;
     }
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp
index 00ce6db..0aa9545b 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp
@@ -27,6 +27,7 @@
 #include "modules/indexeddb/IDBOpenDBRequest.h"
 
 #include "bindings/core/v8/Nullable.h"
+#include "core/dom/DOMException.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
 #include "modules/indexeddb/IDBDatabase.h"
@@ -169,7 +170,7 @@
     if (event->type() == EventTypeNames::success && resultAsAny()->type() == IDBAny::IDBDatabaseType && resultAsAny()->idbDatabase()->isClosePending()) {
         dequeueEvent(event.get());
         setResult(nullptr);
-        onError(DOMError::create(AbortError, "The connection was closed."));
+        onError(DOMException::create(AbortError, "The connection was closed."));
         return false;
     }
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
index c0109980..f7f5dc7 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
@@ -33,6 +33,8 @@
 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
 #include "bindings/modules/v8/ToV8ForModules.h"
 #include "bindings/modules/v8/V8BindingForModules.h"
+#include "core/dom/DOMException.h"
+#include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/events/EventQueue.h"
 #include "modules/IndexedDBNames.h"
@@ -98,7 +100,7 @@
     return value;
 }
 
-DOMError* IDBRequest::error(ExceptionState& exceptionState) const
+DOMException* IDBRequest::error(ExceptionState& exceptionState) const
 {
     if (m_readyState != DONE) {
         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::requestNotFinishedErrorMessage);
@@ -143,7 +145,7 @@
 
     m_error.clear();
     m_result.clear();
-    onError(DOMError::create(AbortError, "The transaction was aborted, so the request cannot be fulfilled."));
+    onError(DOMException::create(AbortError, "The transaction was aborted, so the request cannot be fulfilled."));
     m_requestAborted = true;
 }
 
@@ -220,7 +222,7 @@
     return true;
 }
 
-void IDBRequest::onError(DOMError* error)
+void IDBRequest::onError(DOMException* error)
 {
     IDB_TRACE("IDBRequest::onError()");
     if (!shouldEnqueueEvent())
@@ -488,7 +490,7 @@
 void IDBRequest::uncaughtExceptionInEventHandler()
 {
     if (m_transaction && !m_requestAborted) {
-        m_transaction->setError(DOMError::create(AbortError, "Uncaught exception in event handler."));
+        m_transaction->setError(DOMException::create(AbortError, "Uncaught exception in event handler."));
         m_transaction->abort(IGNORE_EXCEPTION);
     }
 }
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
index 6c5e1ee..6e2ed6a 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
@@ -32,7 +32,6 @@
 #include "bindings/core/v8/ScriptState.h"
 #include "bindings/core/v8/ScriptValue.h"
 #include "core/dom/ActiveDOMObject.h"
-#include "core/dom/DOMError.h"
 #include "core/dom/DOMStringList.h"
 #include "core/events/EventListener.h"
 #include "core/events/EventTarget.h"
@@ -49,6 +48,7 @@
 
 namespace blink {
 
+class DOMException;
 class ExceptionState;
 class IDBCursor;
 struct IDBDatabaseMetadata;
@@ -67,7 +67,7 @@
 
     ScriptState* scriptState() { return m_scriptState.get(); }
     ScriptValue result(ExceptionState&);
-    DOMError* error(ExceptionState&) const;
+    DOMException* error(ExceptionState&) const;
     ScriptValue source() const;
     IDBTransaction* transaction() const { return m_transaction.get(); }
 
@@ -94,7 +94,7 @@
     void setPendingCursor(IDBCursor*);
     void abort();
 
-    virtual void onError(DOMError*);
+    virtual void onError(DOMException*);
     virtual void onSuccess(const Vector<String>&);
     virtual void onSuccess(PassOwnPtr<WebIDBCursor>, IDBKey*, IDBKey* primaryKey, PassRefPtr<IDBValue>);
     virtual void onSuccess(IDBKey*);
@@ -149,7 +149,7 @@
     RefPtr<ScriptState> m_scriptState;
     Member<IDBAny> m_source;
     Member<IDBAny> m_result;
-    Member<DOMError> m_error;
+    Member<DOMException> m_error;
 
     bool m_hasPendingActivity = true;
     WillBeHeapVector<RefPtrWillBeMember<Event>> m_enqueuedEvents;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl
index 42694a9..94d76f1f 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl
@@ -42,7 +42,7 @@
     GarbageCollected,
 ] interface IDBRequest : EventTarget {
     [RaisesException=Getter, CachedAttribute=isResultDirty] readonly attribute any result;
-    [RaisesException=Getter, Measure] readonly attribute DOMError error;
+    [RaisesException=Getter] readonly attribute DOMException error;
 
     readonly attribute any source;
     readonly attribute IDBTransaction transaction;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp
index ebac0553..d55ca470 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp
@@ -29,7 +29,8 @@
 #include "bindings/core/v8/ScriptState.h"
 #include "bindings/core/v8/V8Binding.h"
 #include "bindings/core/v8/V8BindingForTesting.h"
-#include "core/dom/DOMError.h"
+#include "core/dom/DOMException.h"
+#include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/testing/NullExecutionContext.h"
 #include "modules/indexeddb/IDBDatabaseCallbacks.h"
@@ -85,7 +86,7 @@
     executionContext()->stopActiveDOMObjects();
 
     // Ensure none of the following raise assertions in stopped state:
-    request->onError(DOMError::create(AbortError, "Description goes here."));
+    request->onError(DOMException::create(AbortError, "Description goes here."));
     request->onSuccess(Vector<String>());
     request->onSuccess(nullptr, IDBKey::createInvalid(), IDBKey::createInvalid(), IDBValue::create());
     request->onSuccess(IDBKey::createInvalid());
@@ -106,7 +107,7 @@
 
     // Now simulate the back end having fired an abort error at the request to clear up any intermediaries.
     // Ensure an assertion is not raised.
-    request->onError(DOMError::create(AbortError, "Description goes here."));
+    request->onError(DOMException::create(AbortError, "Description goes here."));
 
     // Stop the request lest it be GCed and its destructor
     // finds the object in a pending state (and asserts.)
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
index b6b5e5b3..c4e4763 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
@@ -29,6 +29,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
 #include "bindings/core/v8/V8PerIsolateData.h"
+#include "core/dom/DOMException.h"
+#include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/events/EventQueue.h"
 #include "core/inspector/ScriptCallStack.h"
@@ -121,7 +123,7 @@
     ActiveDOMObject::trace(visitor);
 }
 
-void IDBTransaction::setError(DOMError* error)
+void IDBTransaction::setError(DOMException* error)
 {
     ASSERT(m_state != Finished);
     ASSERT(error);
@@ -231,7 +233,7 @@
     m_requestList.remove(request);
 }
 
-void IDBTransaction::onAbort(DOMError* error)
+void IDBTransaction::onAbort(DOMException* error)
 {
     IDB_TRACE("IDBTransaction::onAbort");
     if (m_contextStopped) {
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h
index 4e34e54..631c326 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h
@@ -28,7 +28,6 @@
 
 #include "bindings/core/v8/ScriptState.h"
 #include "core/dom/ActiveDOMObject.h"
-#include "core/dom/DOMError.h"
 #include "core/events/EventListener.h"
 #include "modules/EventModules.h"
 #include "modules/EventTargetModules.h"
@@ -42,7 +41,7 @@
 
 namespace blink {
 
-class DOMError;
+class DOMException;
 class ExceptionState;
 class IDBDatabase;
 class IDBObjectStore;
@@ -77,7 +76,7 @@
     const String& mode() const;
     PassRefPtrWillBeRawPtr<DOMStringList> objectStoreNames() const;
     IDBDatabase* db() const { return m_database.get(); }
-    DOMError* error() const { return m_error; }
+    DOMException* error() const { return m_error; }
     IDBObjectStore* objectStore(const String& name, ExceptionState&);
     void abort(ExceptionState&);
 
@@ -86,13 +85,13 @@
     void objectStoreCreated(const String&, IDBObjectStore*);
     void objectStoreDeleted(const String&);
     void setActive(bool);
-    void setError(DOMError*);
+    void setError(DOMException*);
 
     DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
     DEFINE_ATTRIBUTE_EVENT_LISTENER(complete);
     DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
 
-    void onAbort(DOMError*);
+    void onAbort(DOMException*);
     void onComplete();
 
     // EventTarget
@@ -127,7 +126,7 @@
     State m_state = Active;
     bool m_hasPendingActivity = true;
     bool m_contextStopped = false;
-    Member<DOMError> m_error;
+    Member<DOMException> m_error;
 
     HeapListHashSet<Member<IDBRequest>> m_requestList;
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.idl b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.idl
index ebd0c7e3..63e3962 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.idl
@@ -1,4 +1,4 @@
- /*
+/*
  * Copyright (C) 2010 Google Inc. All rights reserved.
  * Copyright (C) 2011 Apple Inc. All rights reserved.
  *
@@ -44,7 +44,7 @@
     [Measure] readonly attribute DOMStringList objectStoreNames;
     readonly attribute IDBTransactionMode mode;
     readonly attribute IDBDatabase db;
-    [Measure] readonly attribute DOMError error;
+    readonly attribute DOMException error;
 
     // Methods
     [RaisesException] IDBObjectStore objectStore (DOMString name);
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp
index e06abf1..45cd516 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp
@@ -32,8 +32,9 @@
 #include "modules/indexeddb/IDBTransaction.h"
 
 #include "bindings/core/v8/V8BindingForTesting.h"
-#include "core/dom/DOMError.h"
+#include "core/dom/DOMException.h"
 #include "core/dom/Document.h"
+#include "core/dom/ExceptionCode.h"
 #include "modules/indexeddb/IDBDatabase.h"
 #include "modules/indexeddb/IDBDatabaseCallbacks.h"
 #include "modules/indexeddb/MockWebIDBDatabase.h"
@@ -82,7 +83,7 @@
     static FakeIDBDatabaseCallbacks* create() { return new FakeIDBDatabaseCallbacks(); }
     void onVersionChange(int64_t oldVersion, int64_t newVersion) override { }
     void onForcedClose() override { }
-    void onAbort(int64_t transactionId, DOMError* error) override { }
+    void onAbort(int64_t transactionId, DOMException* error) override { }
     void onComplete(int64_t transactionId) override { }
 private:
     FakeIDBDatabaseCallbacks() { }
@@ -113,7 +114,7 @@
     // This will generate an abort() call to the back end which is dropped by the fake proxy,
     // so an explicit onAbort call is made.
     executionContext()->stopActiveDOMObjects();
-    transaction->onAbort(DOMError::create(AbortError, "Aborted"));
+    transaction->onAbort(DOMException::create(AbortError, "Aborted"));
     transaction.clear();
 
     Heap::collectAllGarbage();
@@ -154,7 +155,7 @@
 
     // Fire an abort to make sure this doesn't free the transaction during use. The test
     // will not fail if it is, but ASAN would notice the error.
-    db->onAbort(transactionId, DOMError::create(AbortError, "Aborted"));
+    db->onAbort(transactionId, DOMException::create(AbortError, "Aborted"));
 
     // onAbort() should have cleared the transaction's reference to the database.
     Heap::collectAllGarbage();
diff --git a/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp b/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp
index 8c0513d..eb37b681 100644
--- a/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp
@@ -29,7 +29,7 @@
 #include "config.h"
 #include "modules/indexeddb/WebIDBCallbacksImpl.h"
 
-#include "core/dom/DOMError.h"
+#include "core/dom/DOMException.h"
 #include "core/inspector/InspectorInstrumentation.h"
 #include "modules/indexeddb/IDBMetadata.h"
 #include "modules/indexeddb/IDBRequest.h"
@@ -72,7 +72,7 @@
 void WebIDBCallbacksImpl::onError(const WebIDBDatabaseError& error)
 {
     InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncCallbackStarting(m_request->executionContext(), m_asyncOperationId);
-    m_request->onError(DOMError::create(error.code(), error.message()));
+    m_request->onError(DOMException::create(error.code(), error.message()));
     InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
 }
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp b/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp
index 60b95fd3..89bf216 100644
--- a/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp
@@ -26,7 +26,7 @@
 #include "config.h"
 #include "modules/indexeddb/WebIDBDatabaseCallbacksImpl.h"
 
-#include "core/dom/DOMError.h"
+#include "core/dom/DOMException.h"
 
 namespace blink {
 
@@ -57,7 +57,7 @@
 
 void WebIDBDatabaseCallbacksImpl::onAbort(long long transactionId, const WebIDBDatabaseError& error)
 {
-    m_callbacks->onAbort(transactionId, DOMError::create(error.code(), error.message()));
+    m_callbacks->onAbort(transactionId, DOMException::create(error.code(), error.message()));
 }
 
 void WebIDBDatabaseCallbacksImpl::onComplete(long long transactionId)
diff --git a/third_party/WebKit/Source/platform/exported/WebScrollbarThemePainter.cpp b/third_party/WebKit/Source/platform/exported/WebScrollbarThemePainter.cpp
index deb9b6d..8b63bbff 100644
--- a/third_party/WebKit/Source/platform/exported/WebScrollbarThemePainter.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebScrollbarThemePainter.cpp
@@ -41,6 +41,7 @@
     // This is a pointer to a static object, so no ownership transferral.
     m_theme = painter.m_theme;
     m_scrollbar = painter.m_scrollbar;
+    m_deviceScaleFactor = painter.m_deviceScaleFactor;
 }
 
 void WebScrollbarThemePainter::reset()
@@ -55,6 +56,7 @@
 
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintScrollbarBackground(&pictureBuilder.context(), m_scrollbar.get());
     pictureBuilder.endRecording()->playback(canvas);
 }
@@ -63,6 +65,7 @@
 {
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintTrackBackground(&pictureBuilder.context(), m_scrollbar.get(), intRect);
     pictureBuilder.endRecording()->playback(canvas);
 }
@@ -71,6 +74,7 @@
 {
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintTrackPiece(&pictureBuilder.context(), m_scrollbar.get(), intRect, BackTrackPart);
     pictureBuilder.endRecording()->playback(canvas);
 }
@@ -79,6 +83,7 @@
 {
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintTrackPiece(&pictureBuilder.context(), m_scrollbar.get(), intRect, ForwardTrackPart);
     pictureBuilder.endRecording()->playback(canvas);
 }
@@ -87,6 +92,7 @@
 {
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintButton(&pictureBuilder.context(), m_scrollbar.get(), intRect, BackButtonStartPart);
     pictureBuilder.endRecording()->playback(canvas);
 }
@@ -95,6 +101,7 @@
 {
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintButton(&pictureBuilder.context(), m_scrollbar.get(), intRect, BackButtonEndPart);
     pictureBuilder.endRecording()->playback(canvas);
 }
@@ -103,6 +110,7 @@
 {
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintButton(&pictureBuilder.context(), m_scrollbar.get(), intRect, ForwardButtonStartPart);
     pictureBuilder.endRecording()->playback(canvas);
 }
@@ -111,6 +119,7 @@
 {
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintButton(&pictureBuilder.context(), m_scrollbar.get(), intRect, ForwardButtonEndPart);
     pictureBuilder.endRecording()->playback(canvas);
 }
@@ -119,6 +128,7 @@
 {
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintTickmarks(&pictureBuilder.context(), m_scrollbar.get(), intRect);
     pictureBuilder.endRecording()->playback(canvas);
 }
@@ -127,13 +137,15 @@
 {
     IntRect intRect(rect);
     SkPictureBuilder pictureBuilder(intRect);
+    pictureBuilder.context().setDeviceScaleFactor(m_deviceScaleFactor);
     m_theme->paintThumb(&pictureBuilder.context(), m_scrollbar.get(), intRect);
     pictureBuilder.endRecording()->playback(canvas);
 }
 
-WebScrollbarThemePainter::WebScrollbarThemePainter(ScrollbarTheme* theme, Scrollbar* scrollbar)
+WebScrollbarThemePainter::WebScrollbarThemePainter(ScrollbarTheme* theme, Scrollbar* scrollbar, float deviceScaleFactor)
     : m_theme(theme)
     , m_scrollbar(scrollbar)
+    , m_deviceScaleFactor(deviceScaleFactor)
 {
 }
 
diff --git a/third_party/WebKit/Source/platform/fonts/FallbackListCompositeKey.h b/third_party/WebKit/Source/platform/fonts/FallbackListCompositeKey.h
deleted file mode 100644
index b32d133d..0000000
--- a/third_party/WebKit/Source/platform/fonts/FallbackListCompositeKey.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FallbackListCompositeKey_h
-#define FallbackListCompositeKey_h
-
-#include "platform/fonts/FontCacheKey.h"
-#include "platform/fonts/FontDescription.h"
-#include "wtf/HashMap.h"
-#include "wtf/HashTableDeletedValueType.h"
-
-namespace blink {
-
-class FontDescription;
-
-// Cache key representing a font description and font fallback list combination
-// as passed into shaping. Used to look up an applicable ShapeCache instance
-// from the global FontCache.
-// TODO(eae,drott): Ideally this should be replaced by a combination of
-// FontDescription and CSSFontSelector.
-struct FallbackListCompositeKey {
-public:
-    FallbackListCompositeKey(const FontDescription& fontDescription)
-        : m_hash(fontDescription.styleHashWithoutFamilyList() << 1)
-        , m_computedSize(fontDescription.computedSize())
-        , m_letterSpacing(fontDescription.letterSpacing())
-        , m_wordSpacing(fontDescription.wordSpacing())
-        , m_bitmapFields(fontDescription.bitmapFields())
-        , m_auxiliaryBitmapFields(fontDescription.auxiliaryBitmapFields()) { }
-    FallbackListCompositeKey()
-        : m_hash(0)
-        , m_computedSize(0)
-        , m_letterSpacing(0)
-        , m_wordSpacing(0)
-        , m_bitmapFields(0)
-        , m_auxiliaryBitmapFields(0) { }
-    FallbackListCompositeKey(WTF::HashTableDeletedValueType)
-        : m_hash(s_deletedValueHash)
-        , m_computedSize(0)
-        , m_letterSpacing(0)
-        , m_wordSpacing(0)
-        , m_bitmapFields(0)
-        , m_auxiliaryBitmapFields(0) { }
-
-    void add(FontCacheKey key)
-    {
-        m_fontCacheKeys.append(key);
-        // Djb2 with the first bit reserved for deleted.
-        m_hash = (((m_hash << 5) + m_hash) + key.hash()) << 1;
-    }
-
-    unsigned hash() const { return m_hash; }
-
-    bool operator==(const FallbackListCompositeKey& other) const
-    {
-        return m_hash == other.m_hash
-            && m_computedSize == other.m_computedSize
-            && m_letterSpacing == other.m_letterSpacing
-            && m_wordSpacing == other.m_wordSpacing
-            && m_bitmapFields == other.m_bitmapFields
-            && m_auxiliaryBitmapFields == other.m_auxiliaryBitmapFields
-            && m_fontCacheKeys == other.m_fontCacheKeys;
-    }
-
-    bool isHashTableDeletedValue() const
-    {
-        return m_hash == s_deletedValueHash;
-    }
-
-private:
-    static const unsigned s_deletedValueHash = 1;
-    FontDescription m_fontDescription;
-    Vector<FontCacheKey> m_fontCacheKeys;
-    unsigned m_hash;
-
-    float m_computedSize;
-    float m_letterSpacing;
-    float m_wordSpacing;
-    unsigned m_bitmapFields;
-    unsigned m_auxiliaryBitmapFields;
-};
-
-struct FallbackListCompositeKeyHash {
-    static unsigned hash(const FallbackListCompositeKey& key)
-    {
-        return key.hash();
-    }
-
-    static bool equal(const FallbackListCompositeKey& a, const FallbackListCompositeKey& b)
-    {
-        return a == b;
-    }
-
-    static const bool safeToCompareToEmptyOrDeleted = false;
-};
-
-struct FallbackListCompositeKeyTraits : WTF::SimpleClassHashTraits<FallbackListCompositeKey> { };
-
-} // namespace blink
-
-#endif // FallbackListCompositeKey_h
diff --git a/third_party/WebKit/Source/platform/fonts/Font.cpp b/third_party/WebKit/Source/platform/fonts/Font.cpp
index 342a9dbf..5b0df14 100644
--- a/third_party/WebKit/Source/platform/fonts/Font.cpp
+++ b/third_party/WebKit/Source/platform/fonts/Font.cpp
@@ -35,7 +35,6 @@
 #include "platform/fonts/GlyphBuffer.h"
 #include "platform/fonts/GlyphPageTreeNode.h"
 #include "platform/fonts/SimpleFontData.h"
-#include "platform/fonts/shaping/CachingWordShaper.h"
 #include "platform/fonts/shaping/HarfBuzzFace.h"
 #include "platform/fonts/shaping/HarfBuzzShaper.h"
 #include "platform/fonts/shaping/SimpleShaper.h"
@@ -113,7 +112,7 @@
 {
     if (codePath(runInfo) == ComplexPath) {
         float width;
-        CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
+        CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper();
         if (emphasisData) {
             width = shaper.fillGlyphBufferForTextEmphasis(this, runInfo.run,
                 emphasisData, &glyphBuffer, runInfo.from, runInfo.to);
@@ -703,7 +702,7 @@
 
 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, FloatRect* glyphBounds) const
 {
-    CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
+    CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper();
     float width = shaper.width(this, run, fallbackFonts, glyphBounds);
     return width;
 }
@@ -712,7 +711,7 @@
 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
     bool includePartialGlyphs) const
 {
-    CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
+    CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper();
     return shaper.offsetForPosition(this, run, xFloat);
 }
 
@@ -720,7 +719,7 @@
 FloatRect Font::selectionRectForComplexText(const TextRun& run,
     const FloatPoint& point, int height, int from, int to) const
 {
-    CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
+    CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper();
     return shaper.selectionRect(this, run, point, height, from, to);
 }
 
@@ -839,5 +838,4 @@
     return !m_fontFallbackList || m_fontFallbackList->isValid();
 }
 
-
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.cpp b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
index 3a3aa14..55d3943 100644
--- a/third_party/WebKit/Source/platform/fonts/FontCache.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
@@ -43,8 +43,6 @@
 #include "platform/fonts/SimpleFontData.h"
 #include "platform/fonts/TextRenderingMode.h"
 #include "platform/fonts/opentype/OpenTypeVerticalData.h"
-#include "platform/fonts/shaping/ShapeCache.h"
-#include "public/platform/Platform.h"
 #include "wtf/HashMap.h"
 #include "wtf/ListHashSet.h"
 #include "wtf/StdLibExtras.h"
@@ -64,10 +62,8 @@
 #endif // !OS(WIN)
 
 typedef HashMap<FontCacheKey, OwnPtr<FontPlatformData>, FontCacheKeyHash, FontCacheKeyTraits> FontPlatformDataCache;
-typedef HashMap<FallbackListCompositeKey, OwnPtr<ShapeCache>, FallbackListCompositeKeyHash, FallbackListCompositeKeyTraits> FallbackListShaperCache;
 
-static FontPlatformDataCache* gFontPlatformDataCache = nullptr;
-static FallbackListShaperCache* gFallbackListShaperCache = nullptr;
+static FontPlatformDataCache* gFontPlatformDataCache = 0;
 
 #if OS(WIN)
 bool FontCache::s_useDirectWrite = false;
@@ -118,24 +114,6 @@
     return result;
 }
 
-ShapeCache* FontCache::getShapeCache(const FallbackListCompositeKey& key)
-{
-    if (!gFallbackListShaperCache)
-        gFallbackListShaperCache = new FallbackListShaperCache;
-
-    FallbackListShaperCache::iterator it = gFallbackListShaperCache->find(key);
-    ShapeCache* result = nullptr;
-    if (it == gFallbackListShaperCache->end()) {
-        result = new ShapeCache();
-        gFallbackListShaperCache->set(key, adoptPtr(result));
-    } else {
-        result = it->value.get();
-    }
-
-    ASSERT(result);
-    return result;
-}
-
 typedef HashMap<FontCache::FontFileKey, RefPtr<OpenTypeVerticalData>, IntHash<FontCache::FontFileKey>, UnsignedWithZeroKeyHashTraits<FontCache::FontFileKey>> FontVerticalDataCache;
 
 FontVerticalDataCache& fontVerticalDataCacheInstance()
@@ -237,25 +215,6 @@
     }
 }
 
-static inline void purgeFallbackListShaperCache()
-{
-    unsigned items = 0;
-    if (gFallbackListShaperCache) {
-        FallbackListShaperCache::iterator iter;
-        for (iter = gFallbackListShaperCache->begin();
-            iter != gFallbackListShaperCache->end(); ++iter) {
-            items += iter->value->size();
-        }
-        gFallbackListShaperCache->clear();
-    }
-    Platform::current()->histogramCustomCounts("Blink.Fonts.ShapeCache", items, 1, 1000000, 50);
-}
-
-void FontCache::invalidateShapeCache()
-{
-    purgeFallbackListShaperCache();
-}
-
 void FontCache::purge(PurgeSeverity PurgeSeverity)
 {
     // We should never be forcing the purge while the FontCachePurgePreventer is in scope.
@@ -268,7 +227,6 @@
 
     purgePlatformFontDataCache();
     purgeFontVerticalDataCache();
-    purgeFallbackListShaperCache();
 }
 
 static bool invalidateFontCache = false;
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.h b/third_party/WebKit/Source/platform/fonts/FontCache.h
index fc0fdc95..72cf61d 100644
--- a/third_party/WebKit/Source/platform/fonts/FontCache.h
+++ b/third_party/WebKit/Source/platform/fonts/FontCache.h
@@ -31,8 +31,6 @@
 #define FontCache_h
 
 #include "platform/PlatformExport.h"
-#include "platform/fonts/FallbackListCompositeKey.h"
-#include "platform/fonts/FontCacheKey.h"
 #include "platform/fonts/FontFaceCreationParams.h"
 #include "wtf/Forward.h"
 #include "wtf/HashMap.h"
@@ -57,7 +55,6 @@
 class FontPlatformData;
 class FontDescription;
 class OpenTypeVerticalData;
-class ShapeCache;
 class SimpleFontData;
 
 enum ShouldRetain { Retain, DoNotRetain };
@@ -84,11 +81,6 @@
     SimpleFontData* getNonRetainedLastResortFallbackFont(const FontDescription&);
     bool isPlatformFontAvailable(const FontDescription&, const AtomicString&);
 
-    // Returns the ShapeCache instance associated with the given cache key.
-    // Creates a new instance as needed and as such is guaranteed not to return
-    // a nullptr. The life time of instances are managed by the FontCache.
-    ShapeCache* getShapeCache(const FallbackListCompositeKey&);
-
     void addClient(FontCacheClient*);
 #if !ENABLE(OILPAN)
     void removeClient(FontCacheClient*);
@@ -137,8 +129,6 @@
 #endif
     PassRefPtr<SimpleFontData> fontDataFromFontPlatformData(const FontPlatformData*, ShouldRetain = Retain);
 
-    void invalidateShapeCache();
-
 private:
     FontCache();
     ~FontCache();
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescription.cpp b/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
index 36193b2..cc39aaf 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
@@ -31,10 +31,8 @@
 #include "platform/fonts/FontDescription.h"
 
 #include "platform/RuntimeEnabledFeatures.h"
-#include "wtf/StringHasher.h"
 #include "wtf/text/AtomicStringHash.h"
 #include "wtf/text/StringHash.h"
-#include <string.h>
 
 namespace blink {
 
@@ -164,20 +162,18 @@
     return floorf(computedOrAdjustedSize * FontCacheKey::precisionMultiplier()) / FontCacheKey::precisionMultiplier();
 }
 
-FontCacheKey FontDescription::cacheKey(const FontFaceCreationParams& creationParams, FontTraits desiredTraits, bool loading, unsigned version) const
+FontCacheKey FontDescription::cacheKey(const FontFaceCreationParams& creationParams, FontTraits desiredTraits) const
 {
     FontTraits fontTraits = desiredTraits.bitfield() ? desiredTraits : traits();
 
     unsigned options =
-        version << 8 | // bit 9-15
-        static_cast<unsigned>(loading ? 1 : 0) << 7 | // bit 8
         static_cast<unsigned>(m_fields.m_syntheticItalic) << 6 | // bit 7
         static_cast<unsigned>(m_fields.m_syntheticBold) << 5 | // bit 6
         static_cast<unsigned>(m_fields.m_textRendering) << 3 | // bits 4-5
         static_cast<unsigned>(m_fields.m_orientation) << 1 | // bit 2-3
         static_cast<unsigned>(m_fields.m_subpixelTextPosition); // bit 1
 
-    return FontCacheKey(creationParams, effectiveFontSize(), options | fontTraits.bitfield() << 16);
+    return FontCacheKey(creationParams, effectiveFontSize(), options | fontTraits.bitfield() << 7);
 }
 
 
@@ -242,44 +238,4 @@
     }
 }
 
-static inline void addToHash(unsigned& hash, unsigned key)
-{
-    hash = ((hash << 5) + hash) + key; // Djb2
-}
-
-static inline void addFloatToHash(unsigned& hash, float value)
-{
-    addToHash(hash, StringHasher::hashMemory(&value, sizeof(value)));
-}
-
-unsigned FontDescription::styleHashWithoutFamilyList() const
-{
-    unsigned hash = 0;
-    StringHasher stringHasher;
-    const FontFeatureSettings* settings = featureSettings();
-    if (settings) {
-        unsigned numFeatures = settings->size();
-        for (unsigned i = 0; i < numFeatures; ++i) {
-            const AtomicString& tag = settings->at(i).tag();
-            for (unsigned j = 0; j < tag.length(); j++)
-                stringHasher.addCharacter(tag[j]);
-            addToHash(hash, settings->at(i).value());
-        }
-    }
-    for (unsigned i = 0; i < m_locale.length(); i++)
-        stringHasher.addCharacter(m_locale[i]);
-    addToHash(hash, stringHasher.hash());
-
-    addFloatToHash(hash, m_specifiedSize);
-    addFloatToHash(hash, m_computedSize);
-    addFloatToHash(hash, m_adjustedSize);
-    addFloatToHash(hash, m_sizeAdjust);
-    addFloatToHash(hash, m_letterSpacing);
-    addFloatToHash(hash, m_wordSpacing);
-    addToHash(hash, m_fieldsAsUnsigned[0]);
-    addToHash(hash, m_fieldsAsUnsigned[1]);
-
-    return hash;
-}
-
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescription.h b/third_party/WebKit/Source/platform/fonts/FontDescription.h
index 5a90c97..c68cc951 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescription.h
+++ b/third_party/WebKit/Source/platform/fonts/FontDescription.h
@@ -181,7 +181,7 @@
     FontFeatureSettings* featureSettings() const { return m_featureSettings.get(); }
 
     float effectiveFontSize() const; // Returns either the computedSize or the computedPixelSize
-    FontCacheKey cacheKey(const FontFaceCreationParams&, FontTraits desiredTraits = FontTraits(0), bool loading = false, unsigned version = 0) const;
+    FontCacheKey cacheKey(const FontFaceCreationParams&, FontTraits desiredTraits = FontTraits(0)) const;
 
     void setFamily(const FontFamily& family) { m_familyList = family; }
     void setComputedSize(float s) { m_computedSize = clampTo<float>(s); }
@@ -218,10 +218,6 @@
     static void setDefaultTypesettingFeatures(TypesettingFeatures);
     static TypesettingFeatures defaultTypesettingFeatures();
 
-    unsigned styleHashWithoutFamilyList() const;
-    unsigned bitmapFields() const { return m_fieldsAsUnsigned[0]; }
-    unsigned auxiliaryBitmapFields() const { return m_fieldsAsUnsigned[1]; }
-
 private:
     FontFamily m_familyList; // The list of font families to be used.
     RefPtr<FontFeatureSettings> m_featureSettings;
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp b/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
index b1a92fd7..d0d24fd 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
@@ -27,7 +27,6 @@
 
 #include "platform/fonts/FontDescription.h"
 
-#include "wtf/Vector.h"
 #include <gtest/gtest.h>
 
 namespace blink {
@@ -119,58 +118,4 @@
     assertDescriptionMatchesMask(source, source.traits().bitfield());
 }
 
-TEST(FontDescriptionTest, TestHashCollision)
-{
-    FontWeight weights[] = {
-        FontWeight100,
-        FontWeight200,
-        FontWeight300,
-        FontWeight400,
-        FontWeight500,
-        FontWeight600,
-        FontWeight700,
-        FontWeight800,
-        FontWeight900,
-    };
-    FontStretch stretches[] {
-        FontStretchUltraCondensed,
-        FontStretchExtraCondensed,
-        FontStretchCondensed,
-        FontStretchSemiCondensed,
-        FontStretchNormal,
-        FontStretchSemiExpanded,
-        FontStretchExpanded,
-        FontStretchExtraExpanded,
-        FontStretchUltraExpanded
-    };
-    FontStyle styles[] = {
-        FontStyleNormal,
-        FontStyleOblique,
-        FontStyleItalic
-    };
-    FontVariant variants[] = {
-        FontVariantNormal,
-        FontVariantSmallCaps
-    };
-
-    FontDescription source;
-    WTF::Vector<unsigned> hashes;
-    for (size_t i = 0; i < WTF_ARRAY_LENGTH(weights); i++) {
-        source.setWeight(weights[i]);
-        for (size_t j = 0; j < WTF_ARRAY_LENGTH(stretches); j++) {
-            source.setStretch(stretches[j]);
-            for (size_t k = 0; k < WTF_ARRAY_LENGTH(styles); k++) {
-                source.setStyle(styles[k]);
-                for (size_t m = 0; m < WTF_ARRAY_LENGTH(variants); m++) {
-                    source.setVariant(variants[m]);
-                    unsigned hash = source.styleHashWithoutFamilyList();
-                    ASSERT_FALSE(hashes.contains(hash));
-                    hashes.append(hash);
-                }
-            }
-        }
-    }
-
-}
-
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp b/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
index bbb451d..284f612 100644
--- a/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
@@ -30,9 +30,7 @@
 #include "platform/fonts/FontFallbackList.h"
 
 #include "platform/FontFamilyNames.h"
-#include "platform/fonts/AlternateFontFamily.h"
 #include "platform/fonts/FontCache.h"
-#include "platform/fonts/FontCacheKey.h"
 #include "platform/fonts/FontDescription.h"
 #include "platform/fonts/FontFamily.h"
 #include "platform/fonts/SegmentedFontData.h"
@@ -64,6 +62,7 @@
         m_fontSelector = fontSelector;
     m_fontSelectorVersion = m_fontSelector ? m_fontSelector->version() : 0;
     m_generation = FontCache::fontCache()->generation();
+    m_cachingWordShaper.clear();
 }
 
 void FontFallbackList::releaseFontData()
@@ -191,36 +190,6 @@
 }
 
 
-FallbackListCompositeKey FontFallbackList::compositeKey(const FontDescription& fontDescription) const
-{
-    FallbackListCompositeKey key(fontDescription);
-    const FontFamily* currentFamily = &fontDescription.family();
-    while (currentFamily) {
-        if (currentFamily->family().length()) {
-            FontFaceCreationParams params(adjustFamilyNameToAvoidUnsupportedFonts(currentFamily->family()));
-            RefPtr<FontData> result;
-            if (m_fontSelector)
-                result = m_fontSelector->getFontData(fontDescription, currentFamily->family());
-            if (!result) {
-                if (FontPlatformData* platformData = FontCache::fontCache()->getFontPlatformData(fontDescription, params))
-                    result = FontCache::fontCache()->fontDataFromFontPlatformData(platformData);
-            }
-
-            // Include loading state and version when constructing key, that way if called when a font is loading
-            // and then again once it has been loaded or updated different keys are produced.
-            if (result) {
-                FontCacheKey cacheKey = fontDescription.cacheKey(params, FontTraits(0),
-                    result->isLoading() || result->isLoadingFallback(),
-                    m_fontSelector ? m_fontSelector->version() : 0);
-                key.add(cacheKey);
-            }
-        }
-        currentFamily = currentFamily->next();
-    }
-
-    return key;
-}
-
 const FontData* FontFallbackList::fontDataAt(const FontDescription& fontDescription, unsigned realizedFontIndex) const
 {
     if (realizedFontIndex < m_fontList.size())
diff --git a/third_party/WebKit/Source/platform/fonts/FontFallbackList.h b/third_party/WebKit/Source/platform/fonts/FontFallbackList.h
index 1ca7231..72f12681 100644
--- a/third_party/WebKit/Source/platform/fonts/FontFallbackList.h
+++ b/third_party/WebKit/Source/platform/fonts/FontFallbackList.h
@@ -21,10 +21,9 @@
 #ifndef FontFallbackList_h
 #define FontFallbackList_h
 
-#include "platform/fonts/FallbackListCompositeKey.h"
-#include "platform/fonts/FontCache.h"
 #include "platform/fonts/FontSelector.h"
 #include "platform/fonts/SimpleFontData.h"
+#include "platform/fonts/shaping/CachingWordShaper.h"
 #include "wtf/Forward.h"
 #include "wtf/MainThread.h"
 
@@ -75,13 +74,7 @@
     unsigned fontSelectorVersion() const { return m_fontSelectorVersion; }
     unsigned generation() const { return m_generation; }
 
-    ShapeCache* shapeCache(const FontDescription& fontDescription) const
-    {
-        FallbackListCompositeKey key = compositeKey(fontDescription);
-        ShapeCache* cache = FontCache::fontCache()->getShapeCache(key);
-        ASSERT(cache);
-        return cache;
-    }
+    CachingWordShaper& cachingWordShaper() const { return m_cachingWordShaper; }
 
     const SimpleFontData* primarySimpleFontData(const FontDescription& fontDescription)
     {
@@ -107,8 +100,6 @@
             m_pageZero = node;
     }
 
-    FallbackListCompositeKey compositeKey(const FontDescription&) const;
-
 private:
     FontFallbackList();
 
@@ -123,6 +114,7 @@
     GlyphPageTreeNodeBase* m_pageZero;
     mutable const SimpleFontData* m_cachedPrimarySimpleFontData;
     RefPtrWillBePersistent<FontSelector> m_fontSelector;
+    mutable CachingWordShaper m_cachingWordShaper;
     unsigned m_fontSelectorVersion;
     mutable int m_familyIndex;
     unsigned short m_generation;
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.h b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.h
index cedfe37cd..d66080e3 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.h
@@ -34,9 +34,7 @@
 
 namespace blink {
 
-class CachingWordShapeIterator final {
-    WTF_MAKE_NONCOPYABLE(CachingWordShapeIterator);
-    USING_FAST_MALLOC(CachingWordShapeIterator);
+class CachingWordShapeIterator {
 public:
     CachingWordShapeIterator(ShapeCache* cache, const TextRun& run,
         const Font* font)
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.cpp b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.cpp
index 3ba5eb88..2c1d072 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.cpp
@@ -34,13 +34,27 @@
 
 namespace blink {
 
+CachingWordShaper::CachingWordShaper()
+    : m_shapeCache(adoptPtr(new ShapeCache))
+{
+}
+
+CachingWordShaper::~CachingWordShaper()
+{
+}
+
+void CachingWordShaper::clear()
+{
+    m_shapeCache->clear();
+}
+
 float CachingWordShaper::width(const Font* font, const TextRun& run,
     HashSet<const SimpleFontData*>* fallbackFonts,
     FloatRect* glyphBounds)
 {
     float width = 0;
     RefPtr<ShapeResult> wordResult;
-    CachingWordShapeIterator iterator(m_shapeCache, run, font);
+    CachingWordShapeIterator iterator(m_shapeCache.get(), run, font);
     while (iterator.next(&wordResult)) {
         if (wordResult) {
             width += wordResult->width();
@@ -75,7 +89,7 @@
 int CachingWordShaper::offsetForPosition(const Font* font, const TextRun& run, float targetX)
 {
     Vector<RefPtr<ShapeResult>> results;
-    shapeResultsForRun(m_shapeCache, font, run, nullptr, &results);
+    shapeResultsForRun(m_shapeCache.get(), font, run, nullptr, &results);
 
     return ShapeResult::offsetForPosition(results, run, targetX);
 }
@@ -85,7 +99,7 @@
     GlyphBuffer* glyphBuffer, unsigned from, unsigned to)
 {
     Vector<RefPtr<ShapeResult>> results;
-    shapeResultsForRun(m_shapeCache, font, run, fallbackFonts, &results);
+    shapeResultsForRun(m_shapeCache.get(), font, run, fallbackFonts, &results);
 
     return ShapeResult::fillGlyphBuffer(results, glyphBuffer, run, from, to);
 }
@@ -95,7 +109,7 @@
     unsigned from, unsigned to)
 {
     Vector<RefPtr<ShapeResult>> results;
-    shapeResultsForRun(m_shapeCache, font, run, nullptr, &results);
+    shapeResultsForRun(m_shapeCache.get(), font, run, nullptr, &results);
 
     return ShapeResult::fillGlyphBufferForTextEmphasis(results, glyphBuffer,
         run, emphasisData, from, to);
@@ -105,7 +119,7 @@
     const FloatPoint& point, int height, unsigned from, unsigned to)
 {
     Vector<RefPtr<ShapeResult>> results;
-    float totalWidth = shapeResultsForRun(m_shapeCache, font, run, nullptr,
+    float totalWidth = shapeResultsForRun(m_shapeCache.get(), font, run, nullptr,
         &results);
 
     return ShapeResult::selectionRect(results, run.direction(), totalWidth,
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.h b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.h
index c0ffedc..37f750d 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.h
@@ -41,10 +41,10 @@
 struct GlyphData;
 
 class PLATFORM_EXPORT CachingWordShaper final {
-    WTF_MAKE_NONCOPYABLE(CachingWordShaper);
 public:
-    CachingWordShaper(ShapeCache* cache) : m_shapeCache(cache) { }
-    ~CachingWordShaper() { }
+    CachingWordShaper();
+    ~CachingWordShaper();
+    void clear();
 
     float width(const Font*, const TextRun&,
         HashSet<const SimpleFontData*>* fallbackFonts,
@@ -60,7 +60,7 @@
         int height, unsigned from, unsigned to);
 
 private:
-    ShapeCache* m_shapeCache;
+    OwnPtr<ShapeCache> m_shapeCache;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaperTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaperTest.cpp
index 14429b2..51d2360 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaperTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaperTest.cpp
@@ -4,8 +4,6 @@
 
 #include "config.h"
 
-#include "platform/fonts/shaping/CachingWordShaper.h"
-
 #include "platform/fonts/FontCache.h"
 #include "platform/fonts/GlyphBuffer.h"
 #include "platform/fonts/shaping/CachingWordShapeIterator.h"
@@ -21,17 +19,23 @@
         fontDescription.setScript(USCRIPT_LATIN);
         fontDescription.setGenericFamily(FontDescription::StandardFamily);
 
-        font = adoptPtr(new Font(fontDescription));
+        font = new Font(fontDescription);
         font->update(nullptr);
         ASSERT_TRUE(font->canShapeWordByWord());
         fallbackFonts = nullptr;
-        cache = adoptPtr(new ShapeCache());
+        cache = new ShapeCache();
+    }
+
+    void TearDown() override
+    {
+        delete cache;
+        delete font;
     }
 
     FontCachePurgePreventer fontCachePurgePreventer;
     FontDescription fontDescription;
-    OwnPtr<Font> font;
-    OwnPtr<ShapeCache> cache;
+    Font* font;
+    ShapeCache* cache;
     HashSet<const SimpleFontData*>* fallbackFonts;
     unsigned startIndex = 0;
     unsigned numGlyphs = 0;
@@ -43,7 +47,7 @@
     TextRun textRun(reinterpret_cast<const LChar*>("ABC DEF."), 8);
 
     RefPtr<ShapeResult> result;
-    CachingWordShapeIterator iterator(cache.get(), textRun, font.get());
+    CachingWordShapeIterator iterator(cache, textRun, font);
     ASSERT_TRUE(iterator.next(&result));
     ASSERT_TRUE(result->runInfoForTesting(0, startIndex, numGlyphs, script));
     EXPECT_EQ(0u, startIndex);
@@ -72,7 +76,7 @@
 
     unsigned offset = 0;
     RefPtr<ShapeResult> result;
-    CachingWordShapeIterator iterator(cache.get(), textRun, font.get());
+    CachingWordShapeIterator iterator(cache, textRun, font);
     ASSERT_TRUE(iterator.next(&result));
     ASSERT_TRUE(result->runInfoForTesting(0, startIndex, numGlyphs, script));
     EXPECT_EQ(0u, offset + startIndex);
@@ -106,15 +110,14 @@
     const UChar str[] = { 0x2F, 0x301, 0x2E, 0x20, 0x2E, 0x0 };
     TextRun textRun(str, 5);
 
-    CachingWordShaper shaper(cache.get());
+    CachingWordShaper shaper;
     GlyphBuffer glyphBuffer;
-    shaper.fillGlyphBuffer(font.get(), textRun, fallbackFonts, &glyphBuffer, 0, 3);
+    shaper.fillGlyphBuffer(font, textRun, fallbackFonts, &glyphBuffer, 0, 3);
 
-    OwnPtr<ShapeCache> referenceCache = adoptPtr(new ShapeCache());
-    CachingWordShaper referenceShaper(referenceCache.get());
+    CachingWordShaper referenceShaper;
     GlyphBuffer referenceGlyphBuffer;
     font->setCanShapeWordByWordForTesting(false);
-    referenceShaper.fillGlyphBuffer(font.get(), textRun, fallbackFonts,
+    referenceShaper.fillGlyphBuffer(font, textRun, fallbackFonts,
         &referenceGlyphBuffer, 0, 3);
 
     ASSERT_EQ(referenceGlyphBuffer.glyphAt(0), glyphBuffer.glyphAt(0));
@@ -131,15 +134,14 @@
     TextRun textRun(str, 6);
     textRun.setDirection(RTL);
 
-    CachingWordShaper shaper(cache.get());
+    CachingWordShaper shaper;
     GlyphBuffer glyphBuffer;
-    shaper.fillGlyphBuffer(font.get(), textRun, fallbackFonts, &glyphBuffer, 1, 6);
+    shaper.fillGlyphBuffer(font, textRun, fallbackFonts, &glyphBuffer, 1, 6);
 
-    OwnPtr<ShapeCache> referenceCache = adoptPtr(new ShapeCache());
-    CachingWordShaper referenceShaper(referenceCache.get());
+    CachingWordShaper referenceShaper;
     GlyphBuffer referenceGlyphBuffer;
     font->setCanShapeWordByWordForTesting(false);
-    referenceShaper.fillGlyphBuffer(font.get(), textRun, fallbackFonts,
+    referenceShaper.fillGlyphBuffer(font, textRun, fallbackFonts,
         &referenceGlyphBuffer, 1, 6);
 
     ASSERT_EQ(5u, referenceGlyphBuffer.size());
@@ -162,16 +164,16 @@
     };
     TextRun textRun(str, 9);
 
-    CachingWordShaper shaper(cache.get());
+    CachingWordShaper shaper;
     FloatRect glyphBounds;
-    ASSERT_GT(shaper.width(font.get(), textRun, nullptr, &glyphBounds), 0);
+    ASSERT_GT(shaper.width(font, textRun, nullptr, &glyphBounds), 0);
 
     GlyphBuffer glyphBuffer;
-    shaper.fillGlyphBuffer(font.get(), textRun, fallbackFonts, &glyphBuffer, 0, 8);
+    shaper.fillGlyphBuffer(font, textRun, fallbackFonts, &glyphBuffer, 0, 8);
 
     FloatPoint point;
     int height = 16;
-    shaper.selectionRect(font.get(), textRun, point, height, 0, 8);
+    shaper.selectionRect(font, textRun, point, height, 0, 8);
 }
 
 TEST_F(CachingWordShaperTest, TextOrientationFallbackShouldNotInFallbackList)
@@ -190,7 +192,7 @@
     verticalMixedFont->update(nullptr);
     ASSERT_TRUE(verticalMixedFont->canShapeWordByWord());
 
-    CachingWordShaper shaper(cache.get());
+    CachingWordShaper shaper;
     FloatRect glyphBounds;
     HashSet<const SimpleFontData*> fallbackFonts;
     ASSERT_GT(shaper.width(verticalMixedFont.get(), textRun, &fallbackFonts, &glyphBounds), 0);
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeCache.h b/third_party/WebKit/Source/platform/fonts/shaping/ShapeCache.h
index 1719726..ac8278c3 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeCache.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeCache.h
@@ -144,11 +144,6 @@
         m_shortStringMap.clear();
     }
 
-    unsigned size() const
-    {
-        return m_singleCharMap.size() + m_shortStringMap.size();
-    }
-
 private:
     ShapeCacheEntry* addSlowCase(const TextRun& run, ShapeCacheEntry entry)
     {
@@ -176,11 +171,14 @@
             value = &addResult.storedValue->value;
         }
 
-        if (!isNewEntry)
+        // Cache hit: ramp up by sampling the next few words.
+        if (!isNewEntry) {
             return value;
+        }
 
-        if (size() < s_maxSize)
+        if (m_singleCharMap.size() + m_shortStringMap.size() < s_maxSize) {
             return value;
+        }
 
         // No need to be fancy: we're just trying to avoid pathological growth.
         m_singleCharMap.clear();
@@ -196,10 +194,8 @@
     // cache entries is a lot lower given the average word count for a web page
     // is well below 1,000 and even full length books rarely have over 10,000
     // unique words [1]. 1: http://www.mine-control.com/zack/guttenberg/
-    // Our definition of a word is somewhat different from the norm in that we
-    // only segment on space. Thus "foo", "foo-", and "foo)" would count as
-    // three separate words. Given that 10,000 seems like a reasonable maximum.
-    static const unsigned s_maxSize = 10000;
+    // 2,500 seems like a resonable number.
+    static const unsigned s_maxSize = 2500;
 
     SingleCharMap m_singleCharMap;
     SmallStringMap m_shortStringMap;
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.cpp b/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.cpp
index fc61113..d1e16cab 100644
--- a/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.cpp
+++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.cpp
@@ -56,6 +56,7 @@
     , m_muted(false)
 {
     ASSERT(m_id.length());
+    ThreadState::current()->registerPreFinalizer(this);
 }
 
 void MediaStreamComponent::dispose()
diff --git a/third_party/WebKit/Source/web/ExternalPopupMenuTest.cpp b/third_party/WebKit/Source/web/ExternalPopupMenuTest.cpp
index 9d9f762a..0534a69 100644
--- a/third_party/WebKit/Source/web/ExternalPopupMenuTest.cpp
+++ b/third_party/WebKit/Source/web/ExternalPopupMenuTest.cpp
@@ -130,7 +130,6 @@
     FrameTestHelpers::TestWebViewClient m_webViewClient;
     ExternalPopupMenuWebFrameClient m_webFrameClient;
     FrameTestHelpers::WebViewHelper m_helper;
-    FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
 };
 
 TEST_F(ExternalPopupMenuTest, PopupAccountsForVisualViewportOffset)
diff --git a/third_party/WebKit/Source/web/LinkHighlightImplTest.cpp b/third_party/WebKit/Source/web/LinkHighlightImplTest.cpp
index 9f017935..b9754fb4 100644
--- a/third_party/WebKit/Source/web/LinkHighlightImplTest.cpp
+++ b/third_party/WebKit/Source/web/LinkHighlightImplTest.cpp
@@ -59,8 +59,6 @@
 
 TEST(LinkHighlightImplTest, verifyWebViewImplIntegration)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     const std::string baseURL("http://www.test.com/");
     const std::string fileName("test_touch_link_highlight.html");
 
@@ -131,8 +129,6 @@
 
 TEST(LinkHighlightImplTest, resetDuringNodeRemoval)
 {
-    FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
-
     const std::string baseURL("http://www.test.com/");
     const std::string fileName("test_touch_link_highlight.html");
 
@@ -215,8 +211,6 @@
 
 TEST(LinkHighlightImplTest, multipleHighlights)
 {
-    FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
-
     const std::string baseURL("http://www.test.com/");
     const std::string fileName("test_touch_link_highlight.html");
 
diff --git a/third_party/WebKit/Source/web/tests/FrameTestHelpers.h b/third_party/WebKit/Source/web/tests/FrameTestHelpers.h
index 89c8119b7..8507f93 100644
--- a/third_party/WebKit/Source/web/tests/FrameTestHelpers.h
+++ b/third_party/WebKit/Source/web/tests/FrameTestHelpers.h
@@ -72,6 +72,33 @@
     virtual void overrideSettings(WebSettings*) = 0;
 };
 
+// Forces to use mocked overlay scrollbars instead of the default native theme scrollbars to avoid
+// crash in Chromium code when it tries to load UI resources that are not available when running
+// blink unit tests, and to ensure consistent layout regardless of differences between scrollbar themes.
+// WebViewHelper includes this, so this is only needed if a test doesn't use WebViewHelper or the test
+// needs a bigger scope of mock scrollbar settings than the scope of WebViewHelper.
+class UseMockScrollbarSettings {
+public:
+    UseMockScrollbarSettings()
+        : m_originalMockScrollbarEnabled(Settings::mockScrollbarsEnabled())
+        , m_originalOverlayScrollbarsEnabled(RuntimeEnabledFeatures::overlayScrollbarsEnabled())
+    {
+        Settings::setMockScrollbarsEnabled(true);
+        RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
+        EXPECT_TRUE(ScrollbarTheme::theme()->usesOverlayScrollbars());
+    }
+
+    ~UseMockScrollbarSettings()
+    {
+        Settings::setMockScrollbarsEnabled(m_originalMockScrollbarEnabled);
+        RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(m_originalOverlayScrollbarsEnabled);
+    }
+
+private:
+    bool m_originalMockScrollbarEnabled;
+    bool m_originalOverlayScrollbarsEnabled;
+};
+
 // Convenience class for handling the lifetime of a WebView and its associated mainframe in tests.
 class WebViewHelper {
     WTF_MAKE_NONCOPYABLE(WebViewHelper);
@@ -96,6 +123,7 @@
 private:
     WebViewImpl* m_webView;
     SettingOverrider* m_settingOverrider;
+    UseMockScrollbarSettings m_mockScrollbarSettings;
 };
 
 // Minimal implementation of WebFrameClient needed for unit tests that load frames. Tests that load
@@ -146,22 +174,6 @@
     OwnPtr<WebLayerTreeView> m_layerTreeView;
 };
 
-class UseMockScrollbarSettings {
-public:
-    UseMockScrollbarSettings()
-    {
-        Settings::setMockScrollbarsEnabled(true);
-        RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
-        EXPECT_TRUE(ScrollbarTheme::theme()->usesOverlayScrollbars());
-    }
-
-    ~UseMockScrollbarSettings()
-    {
-        Settings::setMockScrollbarsEnabled(false);
-        RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(false);
-    }
-};
-
 } // namespace FrameTestHelpers
 } // namespace blink
 
diff --git a/third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp b/third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp
index f78c2d74..8f8dd26 100644
--- a/third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp
@@ -71,7 +71,6 @@
     std::string m_baseURL;
     FrameTestHelpers::WebViewHelper m_webViewHelper;
     RefPtrWillBePersistent<Document> m_document;
-    FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
 };
 
 void ImeOnFocusTest::sendGestureTap(WebView* webView, IntPoint clientPoint)
diff --git a/third_party/WebKit/Source/web/tests/LayoutGeometryMapTest.cpp b/third_party/WebKit/Source/web/tests/LayoutGeometryMapTest.cpp
index 47451764..618f854 100644
--- a/third_party/WebKit/Source/web/tests/LayoutGeometryMapTest.cpp
+++ b/third_party/WebKit/Source/web/tests/LayoutGeometryMapTest.cpp
@@ -126,7 +126,6 @@
 
     const std::string m_baseURL;
     MockWebFrameClient m_mockWebViewClient;
-    FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
 };
 
 TEST_F(LayoutGeometryMapTest, SimpleGeometryMapTest)
diff --git a/third_party/WebKit/Source/web/tests/ProgrammaticScrollTest.cpp b/third_party/WebKit/Source/web/tests/ProgrammaticScrollTest.cpp
index be14be7..22685a1 100644
--- a/third_party/WebKit/Source/web/tests/ProgrammaticScrollTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ProgrammaticScrollTest.cpp
@@ -45,7 +45,6 @@
 
     std::string m_baseURL;
     MockWebFrameClient m_mockWebFrameClient;
-    FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
 };
 
 TEST_F(ProgrammaticScrollTest, RestoreScrollPositionAndViewStateWithScale)
diff --git a/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp b/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp
index 9ffa55f..4908645 100644
--- a/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp
@@ -108,7 +108,6 @@
     }
 
     FrameTestHelpers::WebViewHelper m_helper;
-    FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
 };
 
 TEST_F(ScrollingCoordinatorTest, fastScrollingByDefault)
@@ -536,8 +535,6 @@
 
 TEST_F(ScrollingCoordinatorTest, scrollbarsForceMainThreadOrHaveWebScrollbarLayer)
 {
-    blink::FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     registerMockedHttpURLLoad("trivial-scroller.html");
     navigateTo(m_baseURL + "trivial-scroller.html");
     forceFullCompositingUpdate();
diff --git a/third_party/WebKit/Source/web/tests/TopControlsTest.cpp b/third_party/WebKit/Source/web/tests/TopControlsTest.cpp
index 04a6b48..789de568 100644
--- a/third_party/WebKit/Source/web/tests/TopControlsTest.cpp
+++ b/third_party/WebKit/Source/web/tests/TopControlsTest.cpp
@@ -120,12 +120,6 @@
 private:
     std::string m_baseURL;
     FrameTestHelpers::WebViewHelper m_helper;
-
-    // To prevent platform differences in content layout, use mock
-    // scrollbars. This is especially needed for Mac, where the presence
-    // or absence of a mouse will change frame sizes because of different
-    // scrollbar themes.
-    FrameTestHelpers::UseMockScrollbarSettings m_useMockScrollbars;
 };
 
 #define EXPECT_POINT_EQ(expected, actual)               \
diff --git a/third_party/WebKit/Source/web/tests/ViewportTest.cpp b/third_party/WebKit/Source/web/tests/ViewportTest.cpp
index cad32ce..8e7310e 100644
--- a/third_party/WebKit/Source/web/tests/ViewportTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ViewportTest.cpp
@@ -54,7 +54,6 @@
 
 namespace blink {
 
-using blink::FrameTestHelpers::UseMockScrollbarSettings;
 using blink::testing::runPendingTasks;
 
 class ViewportTest : public ::testing::Test {
@@ -111,7 +110,6 @@
 
 TEST_F(ViewportTest, viewport1)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-1.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -130,7 +128,6 @@
 
 TEST_F(ViewportTest, viewport2)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-2.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -149,7 +146,6 @@
 
 TEST_F(ViewportTest, viewport3)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-3.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -168,7 +164,6 @@
 
 TEST_F(ViewportTest, viewport4)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-4.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -187,7 +182,6 @@
 
 TEST_F(ViewportTest, viewport5)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-5.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -206,7 +200,6 @@
 
 TEST_F(ViewportTest, viewport6)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-6.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -225,7 +218,7 @@
 
 TEST_F(ViewportTest, viewport7)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
+
     registerMockedHttpURLLoad("viewport/viewport-7.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -244,7 +237,6 @@
 
 TEST_F(ViewportTest, viewport8)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-8.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -263,7 +255,6 @@
 
 TEST_F(ViewportTest, viewport9)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-9.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -282,7 +273,6 @@
 
 TEST_F(ViewportTest, viewport10)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-10.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -301,7 +291,6 @@
 
 TEST_F(ViewportTest, viewport11)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-11.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -320,7 +309,6 @@
 
 TEST_F(ViewportTest, viewport12)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-12.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -339,7 +327,6 @@
 
 TEST_F(ViewportTest, viewport13)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-13.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -358,7 +345,6 @@
 
 TEST_F(ViewportTest, viewport14)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-14.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -377,7 +363,6 @@
 
 TEST_F(ViewportTest, viewport15)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-15.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -396,7 +381,6 @@
 
 TEST_F(ViewportTest, viewport16)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-16.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -415,7 +399,6 @@
 
 TEST_F(ViewportTest, viewport17)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-17.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -434,7 +417,6 @@
 
 TEST_F(ViewportTest, viewport18)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-18.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -453,7 +435,6 @@
 
 TEST_F(ViewportTest, viewport19)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-19.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -472,7 +453,6 @@
 
 TEST_F(ViewportTest, viewport20)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-20.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -491,7 +471,6 @@
 
 TEST_F(ViewportTest, viewport21)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-21.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -510,7 +489,6 @@
 
 TEST_F(ViewportTest, viewport22)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-22.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -529,7 +507,6 @@
 
 TEST_F(ViewportTest, viewport23)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-23.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -548,7 +525,6 @@
 
 TEST_F(ViewportTest, viewport24)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-24.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -567,7 +543,6 @@
 
 TEST_F(ViewportTest, viewport25)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-25.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -586,7 +561,6 @@
 
 TEST_F(ViewportTest, viewport26)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-26.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -605,7 +579,6 @@
 
 TEST_F(ViewportTest, viewport27)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-27.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -624,7 +597,6 @@
 
 TEST_F(ViewportTest, viewport28)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-28.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -643,7 +615,6 @@
 
 TEST_F(ViewportTest, viewport29)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-29.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -662,7 +633,6 @@
 
 TEST_F(ViewportTest, viewport30)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-30.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -681,7 +651,6 @@
 
 TEST_F(ViewportTest, viewport31)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-31.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -700,7 +669,6 @@
 
 TEST_F(ViewportTest, viewport32)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-32.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -719,7 +687,6 @@
 
 TEST_F(ViewportTest, viewport33)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-33.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -738,7 +705,6 @@
 
 TEST_F(ViewportTest, viewport34)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-34.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -757,7 +723,6 @@
 
 TEST_F(ViewportTest, viewport35)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-35.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -776,7 +741,6 @@
 
 TEST_F(ViewportTest, viewport36)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-36.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -795,7 +759,6 @@
 
 TEST_F(ViewportTest, viewport37)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-37.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -814,7 +777,6 @@
 
 TEST_F(ViewportTest, viewport38)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-38.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -833,7 +795,6 @@
 
 TEST_F(ViewportTest, viewport39)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-39.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -852,7 +813,6 @@
 
 TEST_F(ViewportTest, viewport40)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-40.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -871,7 +831,6 @@
 
 TEST_F(ViewportTest, viewport41)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-41.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -890,7 +849,6 @@
 
 TEST_F(ViewportTest, viewport42)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-42.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -909,7 +867,6 @@
 
 TEST_F(ViewportTest, viewport43)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-43.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -928,7 +885,6 @@
 
 TEST_F(ViewportTest, viewport44)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-44.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -947,7 +903,6 @@
 
 TEST_F(ViewportTest, viewport45)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-45.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -966,7 +921,6 @@
 
 TEST_F(ViewportTest, viewport46)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-46.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -985,7 +939,6 @@
 
 TEST_F(ViewportTest, viewport47)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-47.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1004,7 +957,6 @@
 
 TEST_F(ViewportTest, viewport48)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-48.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1023,7 +975,6 @@
 
 TEST_F(ViewportTest, viewport49)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-49.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1042,7 +993,6 @@
 
 TEST_F(ViewportTest, viewport50)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-50.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1061,7 +1011,6 @@
 
 TEST_F(ViewportTest, viewport51)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-51.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1080,7 +1029,6 @@
 
 TEST_F(ViewportTest, viewport52)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-52.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1099,7 +1047,6 @@
 
 TEST_F(ViewportTest, viewport53)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-53.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1118,7 +1065,6 @@
 
 TEST_F(ViewportTest, viewport54)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-54.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1137,7 +1083,6 @@
 
 TEST_F(ViewportTest, viewport55)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-55.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1156,7 +1101,6 @@
 
 TEST_F(ViewportTest, viewport56)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-56.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1175,7 +1119,6 @@
 
 TEST_F(ViewportTest, viewport57)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-57.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1194,7 +1137,6 @@
 
 TEST_F(ViewportTest, viewport58)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-58.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1213,7 +1155,6 @@
 
 TEST_F(ViewportTest, viewport59)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-59.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1232,7 +1173,6 @@
 
 TEST_F(ViewportTest, viewport60)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-60.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1251,7 +1191,6 @@
 
 TEST_F(ViewportTest, viewport61)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-61.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1270,7 +1209,6 @@
 
 TEST_F(ViewportTest, viewport62)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-62.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1289,7 +1227,6 @@
 
 TEST_F(ViewportTest, viewport63)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-63.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1308,7 +1245,6 @@
 
 TEST_F(ViewportTest, viewport64)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-64.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1327,7 +1263,6 @@
 
 TEST_F(ViewportTest, viewport65)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-65.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1346,7 +1281,6 @@
 
 TEST_F(ViewportTest, viewport66)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-66.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1365,7 +1299,6 @@
 
 TEST_F(ViewportTest, viewport67)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-67.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1384,7 +1317,6 @@
 
 TEST_F(ViewportTest, viewport68)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-68.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1403,7 +1335,6 @@
 
 TEST_F(ViewportTest, viewport69)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-69.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1422,7 +1353,6 @@
 
 TEST_F(ViewportTest, viewport70)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-70.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1441,7 +1371,6 @@
 
 TEST_F(ViewportTest, viewport71)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-71.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1460,7 +1389,6 @@
 
 TEST_F(ViewportTest, viewport72)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-72.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1479,7 +1407,6 @@
 
 TEST_F(ViewportTest, viewport73)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-73.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1498,7 +1425,6 @@
 
 TEST_F(ViewportTest, viewport74)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-74.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1517,7 +1443,6 @@
 
 TEST_F(ViewportTest, viewport75)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-75.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1536,7 +1461,6 @@
 
 TEST_F(ViewportTest, viewport76)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-76.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1555,7 +1479,6 @@
 
 TEST_F(ViewportTest, viewport77)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-77.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1574,7 +1497,6 @@
 
 TEST_F(ViewportTest, viewport78)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-78.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1593,7 +1515,6 @@
 
 TEST_F(ViewportTest, viewport79)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-79.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1612,7 +1533,6 @@
 
 TEST_F(ViewportTest, viewport80)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-80.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1631,7 +1551,6 @@
 
 TEST_F(ViewportTest, viewport81)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-81.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1650,7 +1569,6 @@
 
 TEST_F(ViewportTest, viewport82)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-82.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1669,7 +1587,6 @@
 
 TEST_F(ViewportTest, viewport83)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-83.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1688,7 +1605,6 @@
 
 TEST_F(ViewportTest, viewport84)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-84.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1707,7 +1623,6 @@
 
 TEST_F(ViewportTest, viewport85)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-85.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1726,7 +1641,6 @@
 
 TEST_F(ViewportTest, viewport86)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-86.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1745,7 +1659,6 @@
 
 TEST_F(ViewportTest, viewport87)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-87.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1764,7 +1677,6 @@
 
 TEST_F(ViewportTest, viewport88)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-88.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1783,7 +1695,6 @@
 
 TEST_F(ViewportTest, viewport90)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-90.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1802,7 +1713,6 @@
 
 TEST_F(ViewportTest, viewport100)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-100.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1821,7 +1731,6 @@
 
 TEST_F(ViewportTest, viewport101)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-101.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1840,7 +1749,6 @@
 
 TEST_F(ViewportTest, viewport102)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-102.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1859,7 +1767,6 @@
 
 TEST_F(ViewportTest, viewport103)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-103.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1878,7 +1785,6 @@
 
 TEST_F(ViewportTest, viewport104)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-104.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1897,7 +1803,6 @@
 
 TEST_F(ViewportTest, viewport105)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-105.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1916,7 +1821,6 @@
 
 TEST_F(ViewportTest, viewport106)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-106.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1935,7 +1839,6 @@
 
 TEST_F(ViewportTest, viewport107)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-107.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1954,7 +1857,6 @@
 
 TEST_F(ViewportTest, viewport108)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-108.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1973,7 +1875,6 @@
 
 TEST_F(ViewportTest, viewport109)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-109.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -1992,7 +1893,6 @@
 
 TEST_F(ViewportTest, viewport110)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-110.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2011,7 +1911,6 @@
 
 TEST_F(ViewportTest, viewport111)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-111.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2030,7 +1929,6 @@
 
 TEST_F(ViewportTest, viewport112)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-112.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2049,7 +1947,6 @@
 
 TEST_F(ViewportTest, viewport113)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-113.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2068,7 +1965,6 @@
 
 TEST_F(ViewportTest, viewport114)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-114.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2087,7 +1983,6 @@
 
 TEST_F(ViewportTest, viewport115)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-115.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2106,7 +2001,6 @@
 
 TEST_F(ViewportTest, viewport116)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-116.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2125,7 +2019,6 @@
 
 TEST_F(ViewportTest, viewport117)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-117.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2144,7 +2037,6 @@
 
 TEST_F(ViewportTest, viewport118)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-118.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2163,7 +2055,6 @@
 
 TEST_F(ViewportTest, viewport119)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-119.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2182,7 +2073,6 @@
 
 TEST_F(ViewportTest, viewport120)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-120.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2201,7 +2091,6 @@
 
 TEST_F(ViewportTest, viewport121)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-121.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2220,7 +2109,6 @@
 
 TEST_F(ViewportTest, viewport122)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-122.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2239,7 +2127,6 @@
 
 TEST_F(ViewportTest, viewport123)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-123.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2258,7 +2145,6 @@
 
 TEST_F(ViewportTest, viewport124)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-124.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2277,7 +2163,6 @@
 
 TEST_F(ViewportTest, viewport125)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-125.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2296,7 +2181,6 @@
 
 TEST_F(ViewportTest, viewport126)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-126.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2315,7 +2199,6 @@
 
 TEST_F(ViewportTest, viewport127)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-127.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2334,7 +2217,6 @@
 
 TEST_F(ViewportTest, viewport129)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-129.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2353,7 +2235,6 @@
 
 TEST_F(ViewportTest, viewport130)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-130.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2372,7 +2253,6 @@
 
 TEST_F(ViewportTest, viewport131)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-131.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2391,7 +2271,6 @@
 
 TEST_F(ViewportTest, viewport132)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-132.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2410,7 +2289,6 @@
 
 TEST_F(ViewportTest, viewport133)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-133.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2429,7 +2307,6 @@
 
 TEST_F(ViewportTest, viewport134)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-134.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2448,7 +2325,6 @@
 
 TEST_F(ViewportTest, viewport135)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-135.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2467,7 +2343,6 @@
 
 TEST_F(ViewportTest, viewport136)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-136.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2486,7 +2361,6 @@
 
 TEST_F(ViewportTest, viewport137)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-137.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2523,7 +2397,6 @@
 
 TEST_F(ViewportTest, viewportLegacyHandheldFriendly)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-handheldfriendly.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2550,7 +2423,6 @@
 
 TEST_F(ViewportTest, viewportLegacyMergeQuirk1)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-merge-quirk-1.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2569,7 +2441,6 @@
 
 TEST_F(ViewportTest, viewportLegacyMergeQuirk2)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-merge-quirk-2.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2591,7 +2462,6 @@
 
 TEST_F(ViewportTest, viewportLegacyMobileOptimizedMetaWithoutContent)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-mobileoptimized.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2611,7 +2481,6 @@
 
 TEST_F(ViewportTest, viewportLegacyMobileOptimizedMetaWith0)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-mobileoptimized-2.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2631,7 +2500,6 @@
 
 TEST_F(ViewportTest, viewportLegacyMobileOptimizedMetaWith400)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-mobileoptimized-2.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2651,7 +2519,6 @@
 
 TEST_F(ViewportTest, viewportLegacyOrdering2)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-ordering-2.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2671,7 +2538,6 @@
 
 TEST_F(ViewportTest, viewportLegacyOrdering3)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-ordering-3.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2691,7 +2557,6 @@
 
 TEST_F(ViewportTest, viewportLegacyOrdering4)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-ordering-4.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2711,7 +2576,6 @@
 
 TEST_F(ViewportTest, viewportLegacyOrdering5)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-ordering-5.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2731,7 +2595,6 @@
 
 TEST_F(ViewportTest, viewportLegacyOrdering6)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-ordering-6.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2751,7 +2614,6 @@
 
 TEST_F(ViewportTest, viewportLegacyOrdering7)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-ordering-7.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2771,7 +2633,6 @@
 
 TEST_F(ViewportTest, viewportLegacyOrdering8)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-ordering-8.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2791,7 +2652,6 @@
 
 TEST_F(ViewportTest, viewportLegacyEmptyAtViewportDoesntOverrideViewportMeta)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-ordering-10.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2805,7 +2665,6 @@
 
 TEST_F(ViewportTest, viewportLegacyDefaultValueChangedByXHTMLMP)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-xhtmlmp.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2824,7 +2683,6 @@
 
 TEST_F(ViewportTest, viewportLegacyDefaultValueChangedByXHTMLMPAndOverriddenByMeta)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-xhtmlmp-misplaced-doctype.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2843,7 +2701,6 @@
 
 TEST_F(ViewportTest, viewportLegacyXHTMLMPOrdering)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-legacy-xhtmlmp-ordering.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2905,7 +2762,6 @@
 
 TEST_F(ViewportTest, viewportLimitsAdjustedForNoUserScale)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-limits-adjusted-for-no-user-scale.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2918,7 +2774,6 @@
 
 TEST_F(ViewportTest, viewportLimitsAdjustedForNoUserScaleControl)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
     registerMockedHttpURLLoad("viewport/viewport-limits-adjusted-for-no-user-scale-control.html");
 
     FrameTestHelpers::WebViewHelper webViewHelper;
@@ -2931,8 +2786,6 @@
 
 TEST_F(ViewportTest, viewportTriggersGpuRasterization)
 {
-    UseMockScrollbarSettings mockScrollbarSettings;
-
     registerMockedHttpURLLoad("viewport/viewport-gpu-rasterization.html");
     FrameTestHelpers::WebViewHelper webViewHelper;
     webViewHelper.initializeAndLoad(m_baseURL + "viewport/viewport-gpu-rasterization.html", true, 0, 0, setViewportSettings);
diff --git a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
index f5b433e..6781d0b1 100644
--- a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
+++ b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
@@ -185,12 +185,6 @@
 
 private:
     FrameTestHelpers::WebViewHelper m_helper;
-
-    // To prevent platform differneces in content layout, use mock
-    // scrollbars. This is especially needed for Mac, where the presence
-    // or absence of a mouse will change frame sizes because of different
-    // scrollbar themes.
-    FrameTestHelpers::UseMockScrollbarSettings m_useMockScrollbars;
 };
 
 typedef void (*SettingOverrideFunction)(WebSettings*);
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index b856914..b58ad9d5 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -273,7 +273,6 @@
     std::string m_baseURL;
     std::string m_notBaseURL;
     std::string m_chromeURL;
-    FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
 };
 
 enum ParameterizedWebFrameTestConfig {
diff --git a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
index 1a582387..fe14f50 100644
--- a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
@@ -66,8 +66,6 @@
 
 TEST(WebInputEventConversionTest, WebKeyboardEventBuilder)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     // Test key location conversion.
     int modifiers = getModifiersForKeyLocationCode(KeyboardEvent::DOM_KEY_LOCATION_STANDARD);
     EXPECT_FALSE(modifiers & WebInputEvent::IsKeyPad || modifiers & WebInputEvent::IsLeft || modifiers & WebInputEvent::IsRight);
@@ -87,8 +85,6 @@
 
 TEST(WebInputEventConversionTest, WebMouseEventBuilder)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     RefPtrWillBeRawPtr<TouchEvent> event = TouchEvent::create();
     WebMouseEventBuilder mouse(0, 0, *event);
     EXPECT_EQ(WebInputEvent::Undefined, mouse.type);
@@ -96,8 +92,6 @@
 
 TEST(WebInputEventConversionTest, WebTouchEventBuilder)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     const std::string baseURL("http://www.test0.com/");
     const std::string fileName("fixed_layout.html");
 
@@ -236,8 +230,6 @@
 
 TEST(WebInputEventConversionTest, InputEventsScaling)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     const std::string baseURL("http://www.test1.com/");
     const std::string fileName("fixed_layout.html");
 
@@ -492,8 +484,6 @@
 
 TEST(WebInputEventConversionTest, InputEventsTransform)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     const std::string baseURL("http://www.test2.com/");
     const std::string fileName("fixed_layout.html");
 
@@ -696,8 +686,6 @@
 
 TEST(WebInputEventConversionTest, VisualViewportOffset)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     const std::string baseURL("http://www.test4.com/");
     const std::string fileName("fixed_layout.html");
 
@@ -791,8 +779,6 @@
 
 TEST(WebInputEventConversionTest, ElasticOverscroll)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     const std::string baseURL("http://www.test5.com/");
     const std::string fileName("fixed_layout.html");
 
@@ -855,8 +841,6 @@
 // Page reload/navigation should not reset elastic overscroll.
 TEST(WebInputEventConversionTest, ElasticOverscrollWithPageReload)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     const std::string baseURL("http://www.test6.com/");
     const std::string fileName("fixed_layout.html");
 
@@ -894,8 +878,6 @@
 
 TEST(WebInputEventConversionTest, WebMouseWheelEventBuilder)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     const std::string baseURL("http://www.test7.com/");
     const std::string fileName("fixed_layout.html");
 
@@ -928,8 +910,6 @@
 
 TEST(WebInputEventConversionTest, PlatformWheelEventBuilder)
 {
-    FrameTestHelpers::UseMockScrollbarSettings mockScrollbarSettings;
-
     const std::string baseURL("http://www.test8.com/");
     const std::string fileName("fixed_layout.html");
 
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
index 79aac57..74fae38 100644
--- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
@@ -243,7 +243,6 @@
 
     std::string m_baseURL;
     FrameTestHelpers::WebViewHelper m_webViewHelper;
-    FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
 };
 
 TEST_F(WebViewTest, SaveImageAt)
diff --git a/third_party/WebKit/public/platform/WebScrollbarThemePainter.h b/third_party/WebKit/public/platform/WebScrollbarThemePainter.h
index 268d94b..6563a6e6 100644
--- a/third_party/WebKit/public/platform/WebScrollbarThemePainter.h
+++ b/third_party/WebKit/public/platform/WebScrollbarThemePainter.h
@@ -38,7 +38,7 @@
 
 class WebScrollbarThemePainter {
 public:
-    WebScrollbarThemePainter() : m_theme(0) { }
+    WebScrollbarThemePainter() : m_theme(0), m_deviceScaleFactor(1.0) { }
     WebScrollbarThemePainter(const WebScrollbarThemePainter& painter) { assign(painter); }
     virtual ~WebScrollbarThemePainter()
     {
@@ -65,7 +65,7 @@
     BLINK_PLATFORM_EXPORT void paintThumb(WebCanvas*, const WebRect&);
 
 #if INSIDE_BLINK
-    BLINK_PLATFORM_EXPORT WebScrollbarThemePainter(ScrollbarTheme*, Scrollbar*);
+    BLINK_PLATFORM_EXPORT WebScrollbarThemePainter(ScrollbarTheme*, Scrollbar*, float deviceScaleFactor);
 #endif
 
 private:
@@ -80,6 +80,8 @@
     // scrollbar (and not a WebScrollbar wrapper) due to static_casts for
     // LayoutScrollbar and pointer-based HashMap lookups for Lion scrollbars.
     WebPrivatePtr<Scrollbar> m_scrollbar;
+
+    float m_deviceScaleFactor;
 };
 
 } // namespace blink
diff --git a/third_party/mojo/src/mojo/edk/js/waiting_callback.cc b/third_party/mojo/src/mojo/edk/js/waiting_callback.cc
index 0746dfb..65833f3 100644
--- a/third_party/mojo/src/mojo/edk/js/waiting_callback.cc
+++ b/third_party/mojo/src/mojo/edk/js/waiting_callback.cc
@@ -14,8 +14,9 @@
 
 namespace {
 
-v8::Handle<v8::String> GetHiddenPropertyName(v8::Isolate* isolate) {
-  return gin::StringToSymbol(isolate, "::mojo::js::WaitingCallback");
+v8::Handle<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) {
+  return v8::Private::ForApi(
+      isolate, gin::StringToV8(isolate, "::mojo::js::WaitingCallback"));
 }
 
 }  // namespace
@@ -56,7 +57,9 @@
   handle_wrapper_->AddCloseObserver(this);
   v8::Handle<v8::Context> context = isolate->GetCurrentContext();
   runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr();
-  GetWrapper(isolate)->SetHiddenValue(GetHiddenPropertyName(isolate), callback);
+  GetWrapper(isolate)
+      ->SetPrivate(context, GetHiddenPropertyName(isolate), callback)
+      .FromJust();
 }
 
 WaitingCallback::~WaitingCallback() {
@@ -91,7 +94,10 @@
   v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
 
   v8::Handle<v8::Value> hidden_value =
-      GetWrapper(isolate)->GetHiddenValue(GetHiddenPropertyName(isolate));
+      GetWrapper(isolate)
+          ->GetPrivate(runner_->GetContextHolder()->context(),
+                       GetHiddenPropertyName(isolate))
+          .ToLocalChecked();
   v8::Handle<v8::Function> callback;
   CHECK(gin::ConvertFromV8(isolate, hidden_value, &callback));
 
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium
index e440620..0215e61f 100644
--- a/third_party/qcms/README.chromium
+++ b/third_party/qcms/README.chromium
@@ -113,6 +113,8 @@
    - https://code.google.com/p/chromium/issues/detail?id=532910
  - Store color profile version and add a version read API
    - https://code.google.com/p/chromium/issues/detail?id=532258
+ - Add support for VCGT tag formula gamma
+   - https://code.google.com/p/chromium/issues/detail?id=551568
 
 For the Chromium changes, since the import, in a patch format run:
   git diff b8456f38 src
diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c
index 40cc9fc..b62f127d 100644
--- a/third_party/qcms/src/iccread.c
+++ b/third_party/qcms/src/iccread.c
@@ -361,57 +361,99 @@
 #define MMOD_TYPE 0x6D6D6F64 // 'mmod'
 #define VCGT_TYPE 0x76636774 // 'vcgt'
 
+enum {
+	VCGT_TYPE_TABLE,
+	VCGT_TYPE_FORMULA,
+	VCGT_TYPE_LAST = VCGT_TYPE_FORMULA
+};
+
 static qcms_bool read_tag_vcgtType(qcms_profile *profile, struct mem_source *src, struct tag_index index)
 {
 	size_t tag_offset = find_tag(index, TAG_vcgt)->offset;
 	uint32_t tag_type = read_u32(src, tag_offset);
 	uint32_t vcgt_type = read_u32(src, tag_offset + 8);
-	uint16_t channels = read_u16(src, tag_offset + 12);
-	uint16_t elements = read_u16(src, tag_offset + 14);
-	uint16_t byte_depth = read_u16(src, tag_offset + 16);
-	size_t table_offset = tag_offset + 18;
-	uint32_t i;
-	uint16_t *dest;
 
 	if (!src->valid || tag_type != VCGT_TYPE)
 		goto invalid_vcgt_tag;
 
-	// Only support 3 channels.
-	if (channels != 3)
-		return true;
-	// Only support single or double byte values.
-	if (byte_depth != 1 && byte_depth != 2)
-		return true;
-	// Only support table data, not equation.
-	if (vcgt_type != 0)
-		return true;
-	// Limit the table to a sensible size; 10-bit gamma is a reasonable
-	// maximum for hardware correction.
-	if (elements > 1024)
+	// Only support table and equation types.
+	if (vcgt_type > VCGT_TYPE_LAST)
 		return true;
 
-	// Empty table is invalid.
-	if (!elements)
-		goto invalid_vcgt_tag;
-
-	profile->vcgt.length = elements;
-	profile->vcgt.data = malloc(3 * elements * sizeof(uint16_t));
-	if (!profile->vcgt.data)
-		return false;
-
-	dest = profile->vcgt.data;
-
-	for (i = 0; i < 3 * elements; ++i) {
-		if (byte_depth == 1) {
-			*dest++ = read_u8(src, table_offset) * 256;
-		} else {
-			*dest++ = read_u16(src, table_offset);
-		}
-
-		table_offset += byte_depth;
+	if (vcgt_type == VCGT_TYPE_TABLE) {
+		uint16_t channels = read_u16(src, tag_offset + 12);
+		uint16_t elements = read_u16(src, tag_offset + 14);
+		uint16_t byte_depth = read_u16(src, tag_offset + 16);
+		size_t table_offset = tag_offset + 18;
+		uint32_t i;
+		uint16_t *dest;
 
 		if (!src->valid)
 			goto invalid_vcgt_tag;
+
+		// Only support 3 channels.
+		if (channels != 3)
+			return true;
+		// Only support single or double byte values.
+		if (byte_depth != 1 && byte_depth != 2)
+			return true;
+		// Limit the table to a sensible size; 10-bit gamma is a reasonable
+		// maximum for hardware correction.
+		if (elements > 1024)
+			return true;
+
+		// Empty table is invalid.
+		if (!elements)
+			goto invalid_vcgt_tag;
+
+		profile->vcgt.length = elements;
+		profile->vcgt.data = malloc(3 * elements * sizeof(uint16_t));
+		if (!profile->vcgt.data)
+			return false;
+
+		dest = profile->vcgt.data;
+
+		for (i = 0; i < 3 * elements; ++i) {
+			if (byte_depth == 1) {
+				*dest++ = read_u8(src, table_offset) * 256;
+			} else {
+				*dest++ = read_u16(src, table_offset);
+			}
+
+			table_offset += byte_depth;
+
+			if (!src->valid)
+				goto invalid_vcgt_tag;
+		}
+	} else {
+		size_t formula_offset = tag_offset + 12;
+		int i, j;
+		uint16_t *dest;
+
+		// For formula always provide an 8-bit lut.
+		profile->vcgt.length = 256;
+		profile->vcgt.data = malloc(3 * profile->vcgt.length * sizeof(uint16_t));
+		if (!profile->vcgt.data)
+			return false;
+
+		dest = profile->vcgt.data;
+		for (i = 0; i < 3; ++i) {
+			float gamma = s15Fixed16Number_to_float(
+					read_s15Fixed16Number(src, formula_offset + 12 * i));
+			float min = s15Fixed16Number_to_float(
+					read_s15Fixed16Number(src, formula_offset + 4 + 12 * i));
+			float max = s15Fixed16Number_to_float(
+					read_s15Fixed16Number(src, formula_offset + 8 + 12 * i));
+			float range = max - min;
+
+			if (!src->valid)
+				goto invalid_vcgt_tag;
+
+			for (j = 0; j < profile->vcgt.length; ++j) {
+				*dest++ = 65535.f *
+					(min + range * pow((float)j / (profile->vcgt.length - 1), gamma));
+			}
+		}
 	}
 
 	return true;
diff --git a/tools/battor_agent/BUILD.gn b/tools/battor_agent/BUILD.gn
index c92bfa82..9b82853 100644
--- a/tools/battor_agent/BUILD.gn
+++ b/tools/battor_agent/BUILD.gn
@@ -9,6 +9,8 @@
   deps = [
     ":battor_agent_lib",
     "//base",
+    "//device/serial",
+    "//third_party/mojo/src/mojo/public/c/system:for_shared_library",
   ]
 }
 
@@ -19,5 +21,6 @@
   ]
   deps = [
     "//base",
+    "//device/serial",
   ]
 }
diff --git a/tools/battor_agent/DEPS b/tools/battor_agent/DEPS
new file mode 100644
index 0000000..3954d4f4b
--- /dev/null
+++ b/tools/battor_agent/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+device/serial",
+]
\ No newline at end of file
diff --git a/tools/battor_agent/battor_agent.cc b/tools/battor_agent/battor_agent.cc
index 73d2fc8..97fa13e 100644
--- a/tools/battor_agent/battor_agent.cc
+++ b/tools/battor_agent/battor_agent.cc
@@ -9,6 +9,9 @@
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 
+using device::serial::ReceiveError;
+using device::serial::SendError;
+
 namespace battor {
 
 BattOrAgent::BattOrAgent(const std::string& path) : path_(path) {
@@ -19,25 +22,29 @@
   // TODO(charliea): Close the serial connection with the BattOr.
 }
 
-void BattOrAgent::StartTracing() {
+void BattOrAgent::StartTracing(const SendCallback& callback) {
   // TODO(charliea): Tell the BattOr to start tracing.
+  callback.Run(device::serial::SEND_ERROR_NONE);
 }
 
 void BattOrAgent::StopTracing(std::string* trace_output,
-                              const base::Closure& callback) {
+                              const SendReceiveCallback& callback) {
   // TODO(charliea): Tell the BattOr to stop tracing.
   *trace_output = "battor trace output";
-  callback.Run();
+  callback.Run(device::serial::SEND_ERROR_NONE,
+               device::serial::RECEIVE_ERROR_NONE);
 }
 
 void BattOrAgent::RecordClockSyncMarker(const std::string& marker,
-                                        const base::Closure& callback) {
+                                        const SendReceiveCallback& callback) {
   // TODO(charliea): Tell the BattOr to record the specified clock sync marker.
-  callback.Run();
+  callback.Run(device::serial::SEND_ERROR_NONE,
+               device::serial::RECEIVE_ERROR_NONE);
 }
 
-void BattOrAgent::IssueClockSyncMarker() {
+void BattOrAgent::IssueClockSyncMarker(const SendCallback& callback) {
   // TODO(charliea): Tell atrace to issue a clock sync marker.
+  callback.Run(device::serial::SEND_ERROR_NONE);
 }
 
 }  // namespace battor
diff --git a/tools/battor_agent/battor_agent.gyp b/tools/battor_agent/battor_agent.gyp
index 45074eb..2680def9 100644
--- a/tools/battor_agent/battor_agent.gyp
+++ b/tools/battor_agent/battor_agent.gyp
@@ -12,6 +12,7 @@
       ],
       'dependencies': [
         'battor_agent_lib',
+        '../../device/serial/serial.gyp:device_serial',
       ],
       'sources': [
         'battor_agent_bin.cc',
@@ -29,6 +30,7 @@
       ],
       'dependencies': [
         '../../base/base.gyp:base',
+        '../../device/serial/serial.gyp:device_serial',
       ]
     },
   ],
diff --git a/tools/battor_agent/battor_agent.h b/tools/battor_agent/battor_agent.h
index 7b49f67..139fe1e 100644
--- a/tools/battor_agent/battor_agent.h
+++ b/tools/battor_agent/battor_agent.h
@@ -6,33 +6,39 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "device/serial/serial.mojom.h"
 
 namespace battor {
 
 class BattOrAgent {
  public:
+  typedef base::Callback<void(device::serial::SendError)> SendCallback;
+  typedef base::Callback<void(device::serial::SendError,
+                              device::serial::ReceiveError)>
+      SendReceiveCallback;
+
   explicit BattOrAgent(const std::string& path);
   virtual ~BattOrAgent();
 
-  // Tells the BattOr (using a best-effort signal) to start tracing.
-  void StartTracing();
+  // Tells the BattOr to start tracing and calls the callback when complete.
+  void StartTracing(const SendCallback& callback);
 
-  // Tells the BattOr to stop tracing and write the trace output to
-  // the specified location and calls the callback when complete.
-  void StopTracing(std::string* trace_output, const base::Closure& callback);
+  // Tells the BattOr to stop tracing and write the trace output to the
+  // specified string and calls the callback when complete.
+  void StopTracing(std::string* trace_output,
+                   const SendReceiveCallback& callback);
 
-  // Tells the BattOr to record a clock sync marker in its own trace
-  // log and calls the callback when complete.
+  // Tells the BattOr to record a clock sync marker in its own trace log and
+  // calls the callback when complete.
   void RecordClockSyncMarker(const std::string& marker,
-                             const base::Closure& callback);
+                             const SendReceiveCallback& callback);
 
-  // Tells the BattOr (using a best-effort signal) to issue clock sync
-  // markers to all other tracing agents that it's connected to.
-  void IssueClockSyncMarker();
+  // Tells the BattOr to issue clock sync markers to all other tracing agents
+  // that it's connected to and calls the callback when complete.
+  void IssueClockSyncMarker(const SendCallback& callback);
 
-  // Returns whether the BattOr is able to record clock sync markers
-  // in its own trace log.
+  // Returns whether the BattOr is able to record clock sync markers in its own
+  // trace log.
   static bool SupportsExplicitClockSync() { return true; }
 
  private:
diff --git a/tools/battor_agent/battor_agent_bin.cc b/tools/battor_agent/battor_agent_bin.cc
index 9caa3bd32..491e9c52 100644
--- a/tools/battor_agent/battor_agent_bin.cc
+++ b/tools/battor_agent/battor_agent_bin.cc
@@ -10,23 +10,28 @@
 #include <iostream>
 
 #include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "device/serial/serial.mojom.h"
 #include "tools/battor_agent/battor_agent.h"
 
 using std::cout;
 using std::endl;
 using std::string;
 
+using device::serial::ReceiveError;
+using device::serial::SendError;
+
 namespace {
 
-// An event used to signal that the BattOr Agent has finished executing its
-// command.
-base::WaitableEvent g_stop_tracing_complete_event(false, false);
+// The maximum amount of time to wait for the BattOr Agent to execute a command.
+static const base::TimeDelta COMMAND_TIMEOUT = base::TimeDelta::FromSeconds(10);
 
 void PrintUsage() {
-  cout << "Usage: battor_agent <command> <arguments>" << endl << endl
-       << "Commands:" << endl << endl
+  cout << "Usage: battor_agent <command> <arguments>" << endl
+       << endl
+       << "Commands:" << endl
+       << endl
        << "  StartTracing <path>" << endl
        << "  StopTracing <path>" << endl
        << "  SupportsExplicitClockSync" << endl
@@ -35,70 +40,133 @@
        << "  Help" << endl;
 }
 
-// Retrieves argument argnum from the argument list and stores it into value,
-// returning whether the operation was successful and printing the usage
-// guidelines if it wasn't.
-bool GetArg(int argnum, int argc, char* argv[], string* value) {
+// Retrieves argument argnum from the argument list, printing the usage
+// guidelines and exiting with an error code if the argument doesn't exist.
+string GetArg(int argnum, int argc, char* argv[]) {
   if (argnum >= argc) {
     PrintUsage();
-    return false;
+    exit(1);
   }
 
-  *value = argv[argnum];
-  return true;
+  return argv[argnum];
 }
 
-void OnCommandComplete() {
-  g_stop_tracing_complete_event.Signal();
+// Checks if a send error occurred and, if it did, prints the error and exits
+// with an error code.
+void CheckSendError(SendError error) {
+  if (error != device::serial::SEND_ERROR_NONE) {
+    printf("Error occured while sending: %d", error);
+    exit(1);
+  }
 }
 
-} // namespace
+// Checks if a receive error occurred and, if it did, prints the error and exits
+// with an error code.
+void CheckReceiveError(ReceiveError error) {
+  if (error != device::serial::RECEIVE_ERROR_NONE) {
+    cout << "Error occured while receiving: " << error << endl;
+    exit(1);
+  }
+}
+
+void OnStartTracingComplete(base::WaitableEvent* complete_event,
+                            SendError error) {
+  CheckSendError(error);
+  cout << "Tracing successfully started." << endl;
+  complete_event->Signal();
+}
+
+void OnStopTracingComplete(string* trace_output,
+                           base::WaitableEvent* complete_event,
+                           SendError send_error,
+                           ReceiveError receive_error) {
+  CheckSendError(send_error);
+  CheckReceiveError(receive_error);
+  cout << *trace_output << endl;
+  complete_event->Signal();
+}
+
+void OnRecordClockSyncMarkerComplete(base::WaitableEvent* complete_event,
+                                     SendError send_error,
+                                     ReceiveError receive_error) {
+  CheckSendError(send_error);
+  CheckReceiveError(receive_error);
+  // TODO(charliea): Write time to STDOUT.
+  cout << "Successfully recorded clock sync marker." << endl;
+  complete_event->Signal();
+}
+
+void OnIssueClockSyncMarkerComplete(base::WaitableEvent* complete_event,
+                                    SendError error) {
+  CheckSendError(error);
+  cout << "Successfully issued clock sync marker." << endl;
+  complete_event->Signal();
+}
+
+void StartTracing(int argc, char* argv[]) {
+  string path = GetArg(2, argc, argv);
+  battor::BattOrAgent agent(path);
+  base::WaitableEvent command_complete_event(false, false);
+
+  agent.StartTracing(
+      base::Bind(&OnStartTracingComplete, &command_complete_event));
+  command_complete_event.TimedWait(COMMAND_TIMEOUT);
+}
+
+void StopTracing(int argc, char* argv[]) {
+  string path = GetArg(2, argc, argv);
+  string trace_output;
+  battor::BattOrAgent agent(path);
+  base::WaitableEvent command_complete_event(false, false);
+
+  agent.StopTracing(&trace_output,
+                    base::Bind(&OnStopTracingComplete, &trace_output,
+                               &command_complete_event));
+  command_complete_event.TimedWait(COMMAND_TIMEOUT);
+}
+
+void SupportsExplicitClockSync() {
+  cout << battor::BattOrAgent::SupportsExplicitClockSync() << endl;
+}
+
+void RecordClockSyncMarker(int argc, char* argv[]) {
+  string path = GetArg(2, argc, argv);
+  string marker = GetArg(3, argc, argv);
+  base::WaitableEvent command_complete_event(false, false);
+  battor::BattOrAgent agent(path);
+
+  // TODO(charliea): Write time to STDOUT.
+  agent.RecordClockSyncMarker(
+      marker,
+      base::Bind(&OnRecordClockSyncMarkerComplete, &command_complete_event));
+  command_complete_event.TimedWait(COMMAND_TIMEOUT);
+}
+
+void IssueClockSyncMarker(int argc, char* argv[]) {
+  string path = GetArg(2, argc, argv);
+  base::WaitableEvent command_complete_event(false, false);
+  battor::BattOrAgent agent(path);
+
+  agent.IssueClockSyncMarker(
+      base::Bind(&OnIssueClockSyncMarkerComplete, &command_complete_event));
+  command_complete_event.TimedWait(COMMAND_TIMEOUT);
+}
+
+}  // namespace
 
 int main(int argc, char* argv[]) {
-  string cmd;
-  if (!GetArg(1, argc, argv, &cmd))
-    return 1;
+  string cmd = GetArg(1, argc, argv);
 
   if (cmd == "StartTracing") {
-    string path;
-    if (!GetArg(2, argc, argv, &path))
-      return 1;
-
-    cout << "Calling StartTracing()" << endl;
-    battor::BattOrAgent(path).StartTracing();
+    StartTracing(argc, argv);
   } else if (cmd == "StopTracing") {
-    string path;
-    if (!GetArg(2, argc, argv, &path))
-      return 1;
-
-    cout << "Calling StopTracing()" << endl;
-    std::string trace_output;
-    battor::BattOrAgent(path)
-        .StopTracing(&trace_output, base::Bind(&OnCommandComplete));
-    g_stop_tracing_complete_event.Wait();
-    cout << trace_output << endl;
+    StopTracing(argc, argv);
   } else if (cmd == "SupportsExplicitClockSync") {
-    cout << "Calling SupportsExplicitClockSync" << endl;
-    cout << battor::BattOrAgent::SupportsExplicitClockSync() << endl;
+    SupportsExplicitClockSync();
   } else if (cmd == "RecordClockSyncMarker") {
-    string path, marker;
-    if (!GetArg(2, argc, argv, &path) || !GetArg(3, argc, argv, &marker))
-      return 1;
-
-    cout << "Marker: " << marker << endl;
-    cout << "Calling RecordClockSyncMarker()" << endl;
-    // TODO(charliea): Write the  time to STDOUT
-    battor::BattOrAgent(path)
-        .RecordClockSyncMarker(marker, base::Bind(&OnCommandComplete));
-    g_stop_tracing_complete_event.Wait();
-    // TODO(charliea): Write the time to STDOUT
+    RecordClockSyncMarker(argc, argv);
   } else if (cmd == "IssueClockSyncMarker") {
-    string path;
-    if (!GetArg(2, argc, argv, &path))
-      return 1;
-
-    cout << "Calling IssueClockSyncMarker" << endl;
-    battor::BattOrAgent(path).IssueClockSyncMarker();
+    IssueClockSyncMarker(argc, argv);
   } else {
     PrintUsage();
     return 1;
diff --git a/tools/metrics/actions/action_utils.py b/tools/metrics/actions/action_utils.py
new file mode 100644
index 0000000..593bc90
--- /dev/null
+++ b/tools/metrics/actions/action_utils.py
@@ -0,0 +1,226 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A utility module for parsing and applying action suffixes in actions.xml.
+
+Note: There is a copy of this file used internally by the UMA processing
+infrastructure. Any changes to this file should also be done (manually) to the
+internal copy. Please contact tools/metrics/OWNERS for more details.
+"""
+
+
+class Error(Exception):
+  pass
+
+
+class UndefinedActionItemError(Error):
+  pass
+
+
+class InvalidOrderingAttributeError(Error):
+  pass
+
+
+class SuffixNameEmptyError(Error):
+  pass
+
+
+class InvalidAffecteddActionNameError(Error):
+  pass
+
+
+class Action(object):
+  """Represents Chrome user action.
+
+  Attributes:
+    name: name of the action.
+    description: description of the action.
+    owners: list of action owners
+    not_user_triggered: if action is not user triggered
+    obsolete: explanation on why user action is not being used anymore
+  """
+
+  def __init__(self, name, description, owners,
+               not_user_triggered=False, obsolete=None):
+    self.name = name
+    self.description = description
+    self.owners = owners
+    self.not_user_triggered = not_user_triggered
+    self.obsolete = obsolete
+
+
+class Suffix(object):
+  """Action suffix in actions.xml.
+
+  Attributes:
+    name: name of the suffix.
+    description: description of the suffix.
+    separator: the separator between affected action name and suffix name.
+    ordering: 'suffix' or 'prefix'. if set to prefix, suffix name will be
+              inserted after the first dot separator of affected action name.
+  """
+
+  def __init__(self, name, description, separator, ordering):
+    if not name:
+      raise SuffixNameEmptyError('Suffix name cannot be empty.')
+
+    if ordering != 'suffix' and ordering != 'prefix':
+      raise InvalidOrderingAttributeError("Ordering has to be either 'prefix' "
+                                          "or 'suffix'.")
+
+    self.name = name
+    self.description = description
+    self.separator = separator
+    self.ordering = ordering
+
+  def __repr__(self):
+    return '<%s, %s, %s, %s>' % (self.name, self.description, self.separator,
+                                 self.ordering)
+
+
+def CreateActionsFromSuffixes(actions_dict, action_suffix_nodes):
+  """Creates new actions from suffixes and adds them to actions_dict.
+
+  Args:
+    actions_dict: dict of existing action name to Action object.
+    action_suffix_nodes: a list of action-suffix nodes
+
+  Returns:
+    A dictionary of action name to list of Suffix objects for that action.
+
+  Raises:
+    UndefinedActionItemError: if an affected action name can't be found
+  """
+  action_to_suffixes_dict = _CreateActionToSuffixesDict(action_suffix_nodes)
+
+  # Some actions in action_to_suffixes_dict keys may yet to be created.
+  # Therefore, while new actions can be created and added to the existing
+  # actions keep calling _CreateActionsFromSuffixes.
+  while _CreateActionsFromSuffixes(actions_dict, action_to_suffixes_dict):
+    pass
+
+  # If action_to_suffixes_dict is not empty by the end, we have missing actions.
+  if action_to_suffixes_dict:
+    raise UndefinedActionItemError('Following actions are missing: %s.'
+                                   %(action_to_suffixes_dict.keys()))
+
+
+def _CreateActionToSuffixesDict(action_suffix_nodes):
+  """Creates a dict of action name to list of Suffix objects for that action.
+
+  Args:
+    action_suffix_nodes: a list of action-suffix nodes
+
+  Returns:
+    A dictionary of action name to list of Suffix objects for that action.
+  """
+  action_to_suffixes_dict = {}
+  for action_suffix_node in action_suffix_nodes:
+    separator = _GetAttribute(action_suffix_node, 'separator', '_')
+    ordering = _GetAttribute(action_suffix_node, 'ordering', 'suffix')
+    suffixes = [Suffix(suffix_node.getAttribute('name'),
+                       suffix_node.getAttribute('label'),
+                       separator, ordering) for suffix_node in
+                action_suffix_node.getElementsByTagName('suffix')]
+
+    action_nodes = action_suffix_node.getElementsByTagName('affected-action')
+    for action_node in action_nodes:
+      action_name = action_node.getAttribute('name')
+      # If <affected-action> has <with-suffix> child nodes, only those suffixes
+      # should be used with that action. filter the list of suffix names if so.
+      action_suffix_names = [suffix_node.getAttribute('name') for suffix_node in
+                             action_node.getElementsByTagName('with-suffix')]
+      if action_suffix_names:
+        action_suffixes = [suffix for suffix in suffixes if suffix.name in
+                           action_suffix_names]
+      else:
+        action_suffixes = list(suffixes)
+
+      if action_name in action_to_suffixes_dict:
+        action_to_suffixes_dict[action_name] += action_suffixes
+      else:
+        action_to_suffixes_dict[action_name] = action_suffixes
+
+  return action_to_suffixes_dict
+
+
+def _GetAttribute(node, attribute_name, default_value):
+  """Returns the attribute's value or default_value if attribute doesn't exist.
+
+  Args:
+    node: an XML dom element.
+    attribute_name: name of the attribute.
+    default_value: default value to return if attribute doesn't exist.
+
+  Returns:
+    The value of the attribute or default_value if attribute doesn't exist.
+  """
+  if node.hasAttribute(attribute_name):
+    return node.getAttribute(attribute_name)
+  else:
+    return default_value
+
+
+def _CreateActionsFromSuffixes(actions_dict, action_to_suffixes_dict):
+  """Creates new actions with action-suffix pairs and adds them to actions_dict.
+
+  For every key (action name) in action_to_suffixes_dict, This function looks
+  to see wether it exists in actions_dict. If so it combines the Action object
+  from actions_dict with all the Suffix objects from action_to_suffixes_dict to
+  create new Action objects. New Action objects are added to actions_dict and
+  the action name is removed from action_to_suffixes_dict.
+
+  Args:
+    actions_dict: dict of existing action name to Action object.
+    action_to_suffixes_dict: dict of action name to list of Suffix objects it
+                             will combine with.
+
+  Returns:
+    True if any new action was added, False otherwise.
+  """
+  expanded_actions = set()
+  for action_name, suffixes in action_to_suffixes_dict.iteritems():
+    if action_name in actions_dict:
+      existing_action = actions_dict[action_name]
+      for suffix in suffixes:
+        _CreateActionFromSuffix(actions_dict, existing_action, suffix)
+
+      expanded_actions.add(action_name)
+
+  for action_name in expanded_actions:
+    del action_to_suffixes_dict[action_name]
+
+  return bool(expanded_actions)
+
+
+def _CreateActionFromSuffix(actions_dict, action, suffix):
+  """Creates a new action with action and suffix and adds it to actions_dict.
+
+  Args:
+    actions_dict: dict of existing action name to Action object.
+    action: an Action object to combine with suffix.
+    suffix: a suffix object to combine with action.
+
+  Returns:
+    None.
+
+  Raises:
+    InvalidAffecteddActionNameError: if the action name does not contain a dot
+  """
+  if suffix.ordering == 'suffix':
+    new_action_name = action.name + suffix.separator + suffix.name
+  else:
+    (before, dot, after) = action.name.partition('.')
+    if not after:
+      raise InvalidAffecteddActionNameError("Action name '%s' must contain a "
+                                            "'.'.", action.name)
+    new_action_name = before + dot + suffix.name + suffix.separator + after
+
+  new_action_description = action.description + ' ' + suffix.description
+
+  actions_dict[new_action_name] = Action(new_action_name,
+                                         new_action_description,
+                                         list(action.owners),
+                                         action.not_user_triggered,
+                                         action.obsolete)
diff --git a/tools/metrics/actions/extract_actions.py b/tools/metrics/actions/extract_actions.py
index a322c5a..efb23b7 100755
--- a/tools/metrics/actions/extract_actions.py
+++ b/tools/metrics/actions/extract_actions.py
@@ -31,6 +31,7 @@
 import sys
 from xml.dom import minidom
 
+import action_utils
 import print_style
 
 sys.path.insert(1, os.path.join(sys.path[0], '..', '..', 'python'))
@@ -555,16 +556,6 @@
   return texts
 
 
-class Action(object):
-  def __init__(self, name, description, owners,
-               not_user_triggered=False, obsolete=None):
-    self.name = name
-    self.description = description
-    self.owners = owners
-    self.not_user_triggered = not_user_triggered
-    self.obsolete = obsolete
-
-
 def ParseActionFile(file_content):
   """Parse the XML data currently stored in the file.
 
@@ -579,7 +570,7 @@
 
   comment_nodes = []
   # Get top-level comments. It is assumed that all comments are placed before
-  # <acionts> tag. Therefore the loop will stop if it encounters a non-comment
+  # <actions> tag. Therefore the loop will stop if it encounters a non-comment
   # node.
   for node in dom.childNodes:
     if node.nodeType == minidom.Node.COMMENT_NODE:
@@ -587,13 +578,11 @@
     else:
       break
 
-  actions = set()
   actions_dict = {}
   # Get each user action data.
   for action_dom in dom.getElementsByTagName('action'):
     action_name = action_dom.getAttribute('name')
     not_user_triggered = bool(action_dom.getAttribute('not_user_triggered'))
-    actions.add(action_name)
 
     owners = _ExtractText(action_dom, 'owner')
     # There is only one description for each user action. Get the first element
@@ -613,9 +602,16 @@
                     ' fix.', action_name)
       sys.exit(1)
     obsolete = obsolete_list[0] if obsolete_list else None
-    actions_dict[action_name] = Action(action_name, description, owners,
-                                       not_user_triggered, obsolete)
-  return actions, actions_dict, comment_nodes
+    actions_dict[action_name] = action_utils.Action(action_name, description,
+        owners, not_user_triggered, obsolete)
+
+  try:
+    action_utils.CreateActionsFromSuffixes(actions_dict,
+        dom.getElementsByTagName('action-suffix'))
+  except action_utils.Error as e:
+    sys.exit(1)
+
+  return set(actions_dict.keys()), actions_dict, comment_nodes
 
 
 def _CreateActionTag(doc, action_name, action_object):
diff --git a/tools/metrics/actions/extract_actions_test.py b/tools/metrics/actions/extract_actions_test.py
index 8a6b942..f755cd5 100755
--- a/tools/metrics/actions/extract_actions_test.py
+++ b/tools/metrics/actions/extract_actions_test.py
@@ -126,6 +126,113 @@
     '</actions>\n'
 )
 
+BASIC_SUFFIX_EXPECTED_XML = (
+    '<actions>\n\n'
+    '<action name="action1">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description.</description>\n'
+    '</action>\n\n'
+    '<action name="action1_suffix1">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description. Suffix Description 1.</description>\n'
+    '</action>\n\n'
+    '</actions>\n'
+)
+
+MULTI_ACTION_MULTI_SUFFIX_CHAIN = (
+    '<actions>\n\n'
+    '<action name="action1">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description.</description>\n'
+    '</action>\n\n'
+    '<action name="action1_suffix1">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description. Suffix Description 1.</description>\n'
+    '</action>\n\n'
+    '<action name="action1_suffix2">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description. Suffix Description 2.</description>\n'
+    '</action>\n\n'
+    '<action name="action1_suffix2_suffix3">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>\n'
+    '    Description. Suffix Description 2. Suffix Description 3.\n'
+    '  </description>\n'
+    '</action>\n\n'
+    '<action name="action1_suffix2_suffix3_suffix4">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>\n'
+    '    Description. Suffix Description 2. Suffix Description 3. '
+    'Suffix Description\n'
+    '    4.\n'
+    '  </description>\n'
+    '</action>\n\n'
+    '<action name="action2">\n'
+    '  <owner>name2@chromium.org</owner>\n'
+    '  <description>Description.</description>\n'
+    '</action>\n\n'
+    '<action name="action2_suffix1">\n'
+    '  <owner>name2@chromium.org</owner>\n'
+    '  <description>Description. Suffix Description 1.</description>\n'
+    '</action>\n\n'
+    '<action name="action2_suffix2">\n'
+    '  <owner>name2@chromium.org</owner>\n'
+    '  <description>Description. Suffix Description 2.</description>\n'
+    '</action>\n\n'
+    '</actions>\n'
+)
+
+SUFFIX_CUSTOM_SEPARATOR = (
+    '<actions>\n\n'
+    '<action name="action1">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description.</description>\n'
+    '</action>\n\n'
+    '<action name="action1.suffix1">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description. Suffix Description 1.</description>\n'
+    '</action>\n\n'
+    '</actions>\n'
+)
+
+SUFFIX_OREDERING_PREFIX = (
+    '<actions>\n\n'
+    '<action name="action1.prefix1_remainder">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description. Prefix Description 1.</description>\n'
+    '</action>\n\n'
+    '<action name="action1.remainder">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description.</description>\n'
+    '</action>\n\n'
+    '</actions>\n'
+)
+
+AFFECTED_ACTION_WITH_SUFFIX_TAG = (
+    '<actions>\n\n'
+    '<action name="action1">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description.</description>\n'
+    '</action>\n\n'
+    '<action name="action1_suffix1">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description. Suffix Description 1.</description>\n'
+    '</action>\n\n'
+    '<action name="action1_suffix2">\n'
+    '  <owner>name1@chromium.org</owner>\n'
+    '  <description>Description. Suffix Description 2.</description>\n'
+    '</action>\n\n'
+    '<action name="action2">\n'
+    '  <owner>name2@chromium.org</owner>\n'
+    '  <description>Description.</description>\n'
+    '</action>\n\n'
+    '<action name="action2_suffix2">\n'
+    '  <owner>name2@chromium.org</owner>\n'
+    '  <description>Description. Suffix Description 2.</description>\n'
+    '</action>\n\n'
+    '</actions>\n'
+)
+
 class ActionXmlTest(unittest.TestCase):
 
   def _GetProcessedAction(self, owner, description, obsolete,
@@ -157,6 +264,19 @@
       actions.add(new_action)
     return extract_actions.PrettyPrint(actions, actions_dict, comments)
 
+  def _GetProcessedActionFromActionsXMLString(self, actions_xml):
+    """parses the given actions XML string and pretty prints it.
+
+    Args:
+      actions_xml: actions XML string.
+
+    Returns:
+      An updated and pretty-printed actions XML string.
+    """
+    actions, actions_dict, comments = extract_actions.ParseActionFile(
+        actions_xml)
+    return extract_actions.PrettyPrint(actions, actions_dict, comments)
+
   def testNoOwner(self):
     xml_result = self._GetProcessedAction(NO_VALUE, DESCRIPTION, NO_VALUE)
     self.assertEqual(NO_OWNER_EXPECTED_XML, xml_result)
@@ -215,6 +335,176 @@
                                           NOT_USER_TRIGGERED)
     self.assertEqual(NOT_USER_TRIGGERED_EXPECTED_XML, xml_result)
 
+  def testBasicSuffix(self):
+    original_xml = """
+    <actions>
+    <action name="action1">
+      <owner>name1@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+    <actions-suffixes>
+    <action-suffix>
+      <suffix name="suffix1" label="Suffix Description 1." />
+      <affected-action name="action1" />
+    </action-suffix>
+    </actions-suffixes>
+    </actions>
+    """
+    xml_result = self._GetProcessedActionFromActionsXMLString(original_xml)
+    self.assertEqual(BASIC_SUFFIX_EXPECTED_XML, xml_result)
+
+  def testMultiActionMultiSuffixChain(self):
+    original_xml = """
+    <actions>
+    <action name="action1">
+      <owner>name1@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+      <action name="action2">
+      <owner>name2@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+    <actions-suffixes>
+    <action-suffix>
+      <suffix name="suffix1" label="Suffix Description 1." />
+      <suffix name="suffix2" label="Suffix Description 2." />
+      <affected-action name="action1" />
+      <affected-action name="action2" />
+    </action-suffix>
+    <action-suffix>
+      <suffix name="suffix3" label="Suffix Description 3." />
+      <affected-action name="action1_suffix2" />
+    </action-suffix>
+    <action-suffix>
+      <suffix name="suffix4" label="Suffix Description 4." />
+      <affected-action name="action1_suffix2_suffix3" />
+    </action-suffix>
+    </actions-suffixes>
+    </actions>
+    """
+    xml_result = self._GetProcessedActionFromActionsXMLString(original_xml)
+    self.assertEqual(MULTI_ACTION_MULTI_SUFFIX_CHAIN, xml_result)
+
+  def testSuffixCustomSeparator(self):
+    original_xml = """
+    <actions>
+    <action name="action1">
+      <owner>name1@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+    <actions-suffixes>
+    <action-suffix separator='.'>
+      <suffix name="suffix1" label="Suffix Description 1." />
+      <affected-action name="action1" />
+    </action-suffix>
+    </actions-suffixes>
+    </actions>
+    """
+    xml_result = self._GetProcessedActionFromActionsXMLString(original_xml)
+    self.assertEqual(SUFFIX_CUSTOM_SEPARATOR, xml_result)
+
+  def testSuffixOrderingPrefix(self):
+    original_xml = """
+    <actions>
+    <action name="action1.remainder">
+      <owner>name1@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+    <actions-suffixes>
+    <action-suffix ordering='prefix'>
+      <suffix name="prefix1" label="Prefix Description 1." />
+      <affected-action name="action1.remainder" />
+    </action-suffix>
+    </actions-suffixes>
+    </actions>
+    """
+    xml_result = self._GetProcessedActionFromActionsXMLString(original_xml)
+    self.assertEqual(SUFFIX_OREDERING_PREFIX, xml_result)
+
+  def testAffectedActionWithSuffixTag(self):
+    original_xml = """
+    <actions>
+    <action name="action1">
+      <owner>name1@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+      <action name="action2">
+      <owner>name2@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+    <actions-suffixes>
+    <action-suffix>
+      <suffix name="suffix1" label="Suffix Description 1." />
+      <suffix name="suffix2" label="Suffix Description 2." />
+      <affected-action name="action1" />
+      <affected-action name="action2" >
+        <with-suffix name="suffix2" />
+      </affected-action>
+    </action-suffix>
+    </actions-suffixes>
+    </actions>
+    """
+    xml_result = self._GetProcessedActionFromActionsXMLString(original_xml)
+    self.assertEqual(AFFECTED_ACTION_WITH_SUFFIX_TAG, xml_result)
+
+  def testErrorActionMissing(self):
+    original_xml = """
+    <actions>
+    <action name="action1">
+      <owner>name1@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+    <actions-suffixes>
+    <action-suffix>
+      <suffix name="suffix1" label="Suffix Description 1." />
+      <affected-action name="action1" />
+      <affected-action name="action2" />
+    </action-suffix>
+    </actions-suffixes>
+    </actions>
+    """
+    with self.assertRaises(SystemExit) as cm:
+      extract_actions.ParseActionFile(original_xml)
+    self.assertEqual(cm.exception.code, 1)
+
+  def testErrorSuffixNameMissing(self):
+    original_xml = """
+    <actions>
+    <action name="action1">
+      <owner>name1@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+    <actions-suffixes>
+    <action-suffix>
+      <suffix label="Suffix Description 1." />
+      <affected-action name="action1" />
+    </action-suffix>
+    </actions-suffixes>
+    </actions>
+    """
+    with self.assertRaises(SystemExit) as cm:
+      extract_actions.ParseActionFile(original_xml)
+    self.assertEqual(cm.exception.code, 1)
+
+  def testErrorBadActionName(self):
+    original_xml = """
+    <actions>
+    <action name="action1">
+      <owner>name1@chromium.org</owner>
+      <description>Description.</description>
+    </action>
+    <actions-suffixes>
+    <action-suffix ordering='prefix'>
+      <suffix name="prefix1" label="Prefix Description 1." />
+      <affected-action name="action1" />
+    </action-suffix>
+    </actions-suffixes>
+    </actions>
+    """
+    with self.assertRaises(SystemExit) as cm:
+      extract_actions.ParseActionFile(original_xml)
+    self.assertEqual(cm.exception.code, 1)
+
   def testUserMetricsActionSpanningTwoLines(self):
     code = 'base::UserMetricsAction(\n"Foo.Bar"));'
     finder = extract_actions.ActionNameFinder('dummy', code)
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 4ee71d1..5e9d7a1 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -2848,14 +2848,6 @@
   <summary>Image codec inferred during decode.</summary>
 </histogram>
 
-<histogram name="Blink.Fonts.ShapeCache">
-  <owner>eae@chromium.org</owner>
-  <summary>
-    Total number of entires in all blink ShapeCache instances. The value is
-    reported each time the FontCache::purge() method is called.
-  </summary>
-</histogram>
-
 <histogram name="Blink.MediaElement.Autoplay" enum="MediaElementAutoPlay">
   <owner>oysteine@chromium.org</owner>
   <summary>
@@ -49606,6 +49598,15 @@
   </summary>
 </histogram>
 
+<histogram name="V8.ErrorsThrownPerContext" units="errors">
+  <owner>hablich@chromium.org</owner>
+  <summary>
+    The amount of JavaScript errors thrown by V8 per context. It does not count
+    custom errors and ignores catched errors thrown by V8. This is collected
+    after the context is detached.
+  </summary>
+</histogram>
+
 <histogram name="V8.ExecutableMemoryMax" units="bytes">
   <obsolete>
     This histogram is no longer present in V8
@@ -65505,6 +65506,7 @@
   <int value="-641719457" label="disable-compositor-touch-hit-testing"/>
   <int value="-631740127" label="inert-visual-viewport"/>
   <int value="-622685174" label="enable-pdf-material-ui"/>
+  <int value="-617452890" label="media-router"/>
   <int value="-610411643" label="enable-printer-app-search"/>
   <int value="-604814313" label="enable-pinch"/>
   <int value="-601384286" label="disable-contextual-search"/>
diff --git a/tools/perf/benchmarks/benchmark_smoke_unittest.py b/tools/perf/benchmarks/benchmark_smoke_unittest.py
index e8e7bd9c..c0a7b012 100644
--- a/tools/perf/benchmarks/benchmark_smoke_unittest.py
+++ b/tools/perf/benchmarks/benchmark_smoke_unittest.py
@@ -137,23 +137,18 @@
     # Merge decorators.
     for attribute in ['_enabled_strings', '_disabled_strings']:
       # Do set union of attributes to eliminate duplicates.
-      merged_attributes = list(set(getattr(method, attribute, []) +
-                                   getattr(benchmark, attribute, [])))
+      merged_attributes = getattr(method, attribute, set()).union(
+          getattr(benchmark, attribute, set()))
       if merged_attributes:
         setattr(method, attribute, merged_attributes)
 
-      # Handle the case where the benchmark is Enabled/Disabled everywhere.
-      if (getattr(method, attribute, None) == [] or
-          getattr(benchmark, attribute, None) == []):
-        setattr(method, attribute, [])
-
     # Disable some tests on android platform only.
     if sys.modules[benchmark.__module__] in _ANDROID_BLACK_LIST_MODULES:
-      method._disabled_strings.append('android')
+      method._disabled_strings.add('android')
 
     # TODO(bashi): Remove once crrev.com/1266833004 is landed.
     if benchmark.Name() == 'memory.blink_memory_mobile':
-      method._disabled_strings.append('android')
+      method._disabled_strings.add('android')
 
     setattr(BenchmarkSmokeTest, benchmark.Name(), method)
 
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index 8fe9b7e..eb6f745 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -308,7 +308,7 @@
 
 
 # This benchmark is for local testing, doesn't need to run on bots.
-@benchmark.Disabled()
+@benchmark.Disabled('all')
 class BlinkPerfXMLHttpRequest(perf_benchmark.PerfBenchmark):
   tag = 'xml_http_request'
   test = _BlinkPerfMeasurement
diff --git a/tools/perf/benchmarks/chrome_signin_startup.py b/tools/perf/benchmarks/chrome_signin_startup.py
index 867ac617..1b4a5355 100644
--- a/tools/perf/benchmarks/chrome_signin_startup.py
+++ b/tools/perf/benchmarks/chrome_signin_startup.py
@@ -20,7 +20,7 @@
     return startup.Startup(cold=False)
 
 
-@benchmark.Disabled  # crbug.com/551938
+@benchmark.Disabled('all')  # crbug.com/551938
 # On android logging in is done through system accounts workflow.
 @benchmark.Disabled('android',
                     'reference') # crbug.com/499312
diff --git a/tools/perf/benchmarks/draw_properties.py b/tools/perf/benchmarks/draw_properties.py
index 984df12..9889f7d9 100644
--- a/tools/perf/benchmarks/draw_properties.py
+++ b/tools/perf/benchmarks/draw_properties.py
@@ -12,7 +12,7 @@
 # This benchmark depends on tracing categories available in M43
 # This benchmark is still useful for manual testing, but need not be enabled
 # and run regularly.
-@benchmark.Disabled()
+@benchmark.Disabled('all')
 class DrawPropertiesToughScrolling(perf_benchmark.PerfBenchmark):
   test = draw_properties.DrawProperties
   page_set = page_sets.ToughScrollingCasesPageSet
@@ -24,7 +24,7 @@
 # This benchmark depends on tracing categories available in M43
 # This benchmark is still useful for manual testing, but need not be enabled
 # and run regularly.
-@benchmark.Disabled()
+@benchmark.Disabled('all')
 class DrawPropertiesTop25(perf_benchmark.PerfBenchmark):
   """Measures the performance of computing draw properties from property trees.
 
diff --git a/tools/perf/benchmarks/dromaeo.py b/tools/perf/benchmarks/dromaeo.py
index d94d43f3..3a345439 100644
--- a/tools/perf/benchmarks/dromaeo.py
+++ b/tools/perf/benchmarks/dromaeo.py
@@ -266,6 +266,7 @@
     return 'dromaeo.jslibmodifyprototype'
 
 
+@benchmark.Disabled('win')  # crbug.com/523276
 class DromaeoJslibStyleJquery(_DromaeoBenchmark):
   """Dromaeo JSLib style jquery JavaScript benchmark.
 
diff --git a/tools/perf/benchmarks/gpu_times.py b/tools/perf/benchmarks/gpu_times.py
index 089bf3d..6dfd0902 100644
--- a/tools/perf/benchmarks/gpu_times.py
+++ b/tools/perf/benchmarks/gpu_times.py
@@ -26,7 +26,7 @@
     options.SetTimelineBasedMetrics([gpu_timeline.GPUTimelineMetric()])
     return options
 
-@benchmark.Disabled  # http://crbug.com/453131, http://crbug.com/527543
+@benchmark.Disabled('all')  # http://crbug.com/453131, http://crbug.com/527543
 class GPUTimesKeyMobileSites(_GPUTimes):
   """Measures GPU timeline metric on key mobile sites."""
   page_set = page_sets.KeyMobileSitesSmoothPageSet
@@ -35,7 +35,7 @@
   def Name(cls):
     return 'gpu_times.key_mobile_sites_smooth'
 
-@benchmark.Disabled  # http://crbug.com/453131, http://crbug.com/527543
+@benchmark.Disabled('all')  # http://crbug.com/453131, http://crbug.com/527543
 class GPUTimesGpuRasterizationKeyMobileSites(_GPUTimes):
   """Measures GPU timeline metric on key mobile sites with GPU rasterization.
   """
@@ -47,7 +47,7 @@
   def Name(cls):
     return 'gpu_times.gpu_rasterization.key_mobile_sites_smooth'
 
-@benchmark.Disabled  # http://crbug.com/453131, http://crbug.com/517476
+@benchmark.Disabled('all')  # http://crbug.com/453131, http://crbug.com/517476
 class GPUTimesTop25Sites(_GPUTimes):
   """Measures GPU timeline metric for the top 25 sites."""
   page_set = page_sets.Top25SmoothPageSet
@@ -56,7 +56,7 @@
   def Name(cls):
     return 'gpu_times.top_25_smooth'
 
-@benchmark.Disabled  # http://crbug.com/453131, http://crbug.com/517476
+@benchmark.Disabled('all')  # http://crbug.com/453131, http://crbug.com/517476
 class GPUTimesGpuRasterizationTop25Sites(_GPUTimes):
   """Measures GPU timeline metric for the top 25 sites with GPU rasterization.
   """
diff --git a/tools/perf/benchmarks/maps.py b/tools/perf/benchmarks/maps.py
index 900bb90f..37db485 100644
--- a/tools/perf/benchmarks/maps.py
+++ b/tools/perf/benchmarks/maps.py
@@ -45,7 +45,7 @@
     action_runner.WaitForJavaScriptCondition('window.testDone')
 
 
-@benchmark.Disabled
+@benchmark.Disabled('all')
 class MapsBenchmark(perf_benchmark.PerfBenchmark):
   """Basic Google Maps benchmarks."""
   test = _MapsMeasurement
diff --git a/tools/perf/benchmarks/media.py b/tools/perf/benchmarks/media.py
index c6a48e8..207b2f0 100644
--- a/tools/perf/benchmarks/media.py
+++ b/tools/perf/benchmarks/media.py
@@ -60,7 +60,7 @@
     return 'media.media_cns_cases'
 
 
-@benchmark.Disabled() # crbug.com/448092
+@benchmark.Disabled('all') # crbug.com/448092
 @benchmark.Disabled('l', 'android-webview') # WebView: crbug.com/419689
 class MediaAndroid(perf_benchmark.PerfBenchmark):
   """Obtains media metrics for key user scenarios on Android."""
diff --git a/tools/perf/benchmarks/page_cycler.py b/tools/perf/benchmarks/page_cycler.py
index 826a6af..5886df2 100644
--- a/tools/perf/benchmarks/page_cycler.py
+++ b/tools/perf/benchmarks/page_cycler.py
@@ -181,7 +181,7 @@
       stories.RemoveStory(found)
     return stories
 
-@benchmark.Disabled
+@benchmark.Disabled('all')
 class PageCyclerKeyMobileSites(_PageCycler):
   """Page load time benchmark for key mobile sites."""
   page_set = page_sets.KeyMobileSitesPageSet
@@ -246,7 +246,7 @@
     return 'page_cycler.basic_oopif'
 
 
-@benchmark.Disabled  # crbug.com/443730
+@benchmark.Disabled('all')  # crbug.com/443730
 class PageCyclerBigJs(_PageCycler):
   page_set = page_sets.BigJsPageSet
   @classmethod
diff --git a/tools/perf/benchmarks/power.py b/tools/perf/benchmarks/power.py
index 1a4a3bc..dc5fbd9 100644
--- a/tools/perf/benchmarks/power.py
+++ b/tools/perf/benchmarks/power.py
@@ -39,7 +39,7 @@
 
 
 @benchmark.Enabled('android')
-@benchmark.Disabled
+@benchmark.Disabled('all')
 class PowerTypical10MobileReload(perf_benchmark.PerfBenchmark):
   """Android typical 10 mobile power reload test."""
   test = power.LoadPower
diff --git a/tools/perf/benchmarks/rasterize_and_record_micro.py b/tools/perf/benchmarks/rasterize_and_record_micro.py
index 75e95410..4e938ca5 100644
--- a/tools/perf/benchmarks/rasterize_and_record_micro.py
+++ b/tools/perf/benchmarks/rasterize_and_record_micro.py
@@ -100,7 +100,7 @@
 
 # Disabled because we do not plan on running CT benchmarks on the perf
 # waterfall any time soon.
-@benchmark.Disabled
+@benchmark.Disabled('all')
 class RasterizeAndRecordMicroCT(_RasterizeAndRecordMicro):
   """Measures rasterize and record performance for Cluster Telemetry."""
 
diff --git a/tools/perf/benchmarks/repaint.py b/tools/perf/benchmarks/repaint.py
index 569d381..472955ae 100644
--- a/tools/perf/benchmarks/repaint.py
+++ b/tools/perf/benchmarks/repaint.py
@@ -38,7 +38,7 @@
 
 #crbug.com/499320
 #@benchmark.Enabled('android')
-@benchmark.Disabled()
+@benchmark.Disabled('all')
 class RepaintKeyMobileSites(_Repaint):
   """Measures repaint performance on the key mobile sites.
 
@@ -51,7 +51,7 @@
 
 #crbug.com/502179
 @benchmark.Enabled('android')
-@benchmark.Disabled()
+@benchmark.Disabled('all')
 class RepaintGpuRasterizationKeyMobileSites(_Repaint):
   """Measures repaint performance on the key mobile sites with forced GPU
   rasterization.
@@ -68,7 +68,7 @@
 
 # Disabled because we do not plan on running CT benchmarks on the perf
 # waterfall any time soon.
-@benchmark.Disabled
+@benchmark.Disabled('all')
 class RepaintCT(_Repaint):
   """Measures repaint performance for Cluster Telemetry."""
 
diff --git a/tools/perf/benchmarks/skpicture_printer.py b/tools/perf/benchmarks/skpicture_printer.py
index 3ba8834..33b11a5 100644
--- a/tools/perf/benchmarks/skpicture_printer.py
+++ b/tools/perf/benchmarks/skpicture_printer.py
@@ -22,7 +22,7 @@
   return None
 
 
-@benchmark.Disabled
+@benchmark.Disabled('all')
 class SkpicturePrinter(perf_benchmark.PerfBenchmark):
   @classmethod
   def AddBenchmarkCommandLineArgs(cls, parser):
@@ -54,7 +54,7 @@
 
 # Disabled because we do not plan on running CT benchmarks on the perf
 # waterfall any time soon.
-@benchmark.Disabled
+@benchmark.Disabled('all')
 class SkpicturePrinterCT(perf_benchmark.PerfBenchmark):
   """Captures SKPs for Cluster Telemetry."""
 
diff --git a/tools/perf/benchmarks/tab_switching.py b/tools/perf/benchmarks/tab_switching.py
index 30b8485f..37eed56 100644
--- a/tools/perf/benchmarks/tab_switching.py
+++ b/tools/perf/benchmarks/tab_switching.py
@@ -105,7 +105,7 @@
     return 'tab_switching.tough_image_cases'
 
 
-@benchmark.Disabled
+@benchmark.Disabled('all')
 class TabSwitchingFlashEnergyCases(perf_benchmark.PerfBenchmark):
   test = tab_switching.TabSwitching
   page_set = page_sets.FlashEnergyCasesPageSet
@@ -116,7 +116,7 @@
     return 'tab_switching.flash_energy_cases'
 
 
-@benchmark.Disabled
+@benchmark.Disabled('all')
 class TabSwitchingPluginPowerSaver(perf_benchmark.PerfBenchmark):
   test = tab_switching.TabSwitching
   page_set = page_sets.FlashEnergyCasesPageSet
diff --git a/tools/perf/benchmarks/text_selection.py b/tools/perf/benchmarks/text_selection.py
index 4720c436..3108500 100644
--- a/tools/perf/benchmarks/text_selection.py
+++ b/tools/perf/benchmarks/text_selection.py
@@ -37,7 +37,7 @@
 
 
 # See crbug.com/519044
-@benchmark.Disabled()
+@benchmark.Disabled('all')
 class TextSelectionDirection(_TextSelection):
   """Measure text selection metrics while dragging a touch selection handle on a
   subset of top ten mobile sites and using the 'direction' touch selection
@@ -51,7 +51,7 @@
 
 
 # See crbug.com/519044
-@benchmark.Disabled()
+@benchmark.Disabled('all')
 class TextSelectionCharacter(_TextSelection):
   """Measure text selection metrics while dragging a touch selection handle on a
   subset of top ten mobile sites and using the 'character' touch selection
diff --git a/tools/perf/measurements/task_execution_time_unittest.py b/tools/perf/measurements/task_execution_time_unittest.py
index fd0863e..5bd95cb2 100644
--- a/tools/perf/measurements/task_execution_time_unittest.py
+++ b/tools/perf/measurements/task_execution_time_unittest.py
@@ -48,7 +48,7 @@
     self.assertGreater(len(results.all_page_specific_values), 0)
 
   # http://crbug.com/466994
-  @decorators.Disabled
+  @decorators.Disabled('all')
   def testSlicesConformToRequiredNamingConventionsUsingDummyPage(self):
     """This test ensures the presence of required keywords.
 
diff --git a/tools/perf/page_sets/android_screen_restoration_shared_state.py b/tools/perf/page_sets/android_screen_restoration_shared_state.py
index 73b4243..8b073c5 100644
--- a/tools/perf/page_sets/android_screen_restoration_shared_state.py
+++ b/tools/perf/page_sets/android_screen_restoration_shared_state.py
@@ -26,4 +26,4 @@
     return True
 
   def _EnsureScreenOn(self):
-    self.platform.android_action_runner.EnsureScreenOn()
+    self.platform.android_action_runner.TurnScreenOn()
diff --git a/tools/perf/page_sets/data/typical_10_mobile.json b/tools/perf/page_sets/data/typical_10_mobile.json
index b8e1501..52e8e21 100644
--- a/tools/perf/page_sets/data/typical_10_mobile.json
+++ b/tools/perf/page_sets/data/typical_10_mobile.json
@@ -1,17 +1,19 @@
 {
-    "description": "Describes the Web Page Replay archives for a page set. Don't edit by hand! Use record_wpr for updating.", 
+    "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
     "archives": {
         "typical_10_mobile_000.wpr": [
-            "http://m.ynet.co.il", 
-            "http://m.facebook.com/barackobama", 
-            "http://m.chiebukuro.yahoo.co.jp/detail/q10136829180", 
-            "http://m.ebay.com/itm/351157205404", 
-            "http://siriuslymeg.tumblr.com/", 
-            "http://www.rg.ru/2014/10/21/cska-site.html", 
-            "http://wapbaike.baidu.com/", 
-            "http://m.huffpost.com/us/entry/6004486", 
-            "http://www.cnn.com/2014/03/31/showbiz/tv/himym-finale/index.html", 
+            "http://m.ynet.co.il",
+            "http://m.facebook.com/barackobama",
+            "http://m.chiebukuro.yahoo.co.jp/detail/q10136829180",
+            "http://m.ebay.com/itm/351157205404",
+            "http://siriuslymeg.tumblr.com/",
+            "http://www.rg.ru/2014/10/21/cska-site.html",
+            "http://wapbaike.baidu.com/",
+            "http://m.huffpost.com/us/entry/6004486",
+            "http://www.cnn.com/2014/03/31/showbiz/tv/himym-finale/index.html"
+        ],
+        "typical_10_mobile_001.wpr": [
             "http://de.m.wikipedia.org/wiki/K%C3%B6lner_Dom"
         ]
     }
-}
\ No newline at end of file
+}
diff --git a/tools/perf/page_sets/data/typical_10_mobile_001.wpr.sha1 b/tools/perf/page_sets/data/typical_10_mobile_001.wpr.sha1
new file mode 100644
index 0000000..43b9f24
--- /dev/null
+++ b/tools/perf/page_sets/data/typical_10_mobile_001.wpr.sha1
@@ -0,0 +1 @@
+f7b8be4bccbd200712f599c1f652a78f6d4ea67b
\ No newline at end of file
diff --git a/tools/telemetry/catapult_base/dependency_manager/base_config.py b/tools/telemetry/catapult_base/dependency_manager/base_config.py
index 8450d99..785295be 100644
--- a/tools/telemetry/catapult_base/dependency_manager/base_config.py
+++ b/tools/telemetry/catapult_base/dependency_manager/base_config.py
@@ -360,7 +360,8 @@
     if not os.path.exists(file_dir):
       os.makedirs(file_dir)
     with open(file_path, 'w') as outfile:
-      json.dump(json_dict, outfile, indent=2, sort_keys=True)
+      json.dump(
+          json_dict, outfile, indent=2, sort_keys=True, separators=(',', ': '))
     return json_dict
 
   @classmethod
diff --git a/tools/telemetry/examples/benchmarks/__init__.py b/tools/telemetry/examples/benchmarks/__init__.py
new file mode 100644
index 0000000..b7bc89c1
--- /dev/null
+++ b/tools/telemetry/examples/benchmarks/__init__.py
@@ -0,0 +1,11 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+# Since this is an example of telemetry benchmarks in top level telemetry
+# folder, we include the top level telemetry dir to sys.path so we can import
+# from telemetry directly in the other modules.
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
diff --git a/tools/telemetry/examples/benchmarks/simple_story_set.py b/tools/telemetry/examples/benchmarks/simple_story_set.py
new file mode 100644
index 0000000..f33434d
--- /dev/null
+++ b/tools/telemetry/examples/benchmarks/simple_story_set.py
@@ -0,0 +1,39 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry import story
+from telemetry import page
+
+
+class ExamplePage(page.Page):
+
+  def __init__(self, page_set):
+    super(ExamplePage, self).__init__(
+        url='https://google.com/search?q=lemon',
+        page_set=page_set)
+
+  def RunPageInteractions(self, action_runner):
+    # To see all the web APIs that action_runner supports, see:
+    # telemetry.page.action_runner module.
+
+    action_runner.Wait(0.5)
+    # Create interaction record will create a region of interest in tracing that
+    # cover the wait, tap, and scroll actions nested in the block below.
+    with action_runner.CreateInteraction('Scroll-And-Tap'):
+      action_runner.Wait(0.3)
+      action_runner.ScrollPage()
+      action_runner.TapElement(text='Next')
+    action_runner.Wait(1)
+    with action_runner.CreateInteraction('Scroll'):
+      action_runner.ScrollPage()
+    with action_runner.CreateInteraction('Wait-two'):
+      action_runner.Wait(1)
+
+
+class SimpleStorySet(story.StorySet):
+  def __init__(self):
+    super(SimpleStorySet, self).__init__(
+        archive_data_file='data/simple_story_set.json',
+        cloud_storage_bucket=story.PARTNER_BUCKET)
+    self.AddStory(ExamplePage(self))
diff --git a/tools/telemetry/examples/benchmarks/v8_benchmark.py b/tools/telemetry/examples/benchmarks/v8_benchmark.py
new file mode 100644
index 0000000..fdee6670
--- /dev/null
+++ b/tools/telemetry/examples/benchmarks/v8_benchmark.py
@@ -0,0 +1,30 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry import benchmark
+from telemetry.timeline import tracing_category_filter
+from telemetry.web_perf import timeline_based_measurement
+
+from benchmarks import simple_story_set
+from benchmarks import v8_metric
+
+
+class MessageLoopBenchmark(benchmark.Benchmark):
+
+  def CreateStorySet(self, options):
+    return simple_story_set.SimpleStorySet()
+
+  def CreateTimelineBasedMeasurementOptions(self):
+    cat_filter = tracing_category_filter.CreateNoOverheadFilter()
+    # blink.console category is required to make sure that Chrome can output
+    # interaction records in its tracing data.
+    cat_filter.AddIncludedCategory('blink.console')
+    cat_filter.AddIncludedCategory('v8')
+    options = timeline_based_measurement.Options(overhead_level=cat_filter)
+    options.SetTimelineBasedMetrics(
+        [v8_metric.MessageLoopLatencyMetric()])
+    return options
+
+  @classmethod
+  def Name(cls):
+    return 'v8_latency.simple_story'
diff --git a/tools/telemetry/examples/benchmarks/v8_metric.py b/tools/telemetry/examples/benchmarks/v8_metric.py
new file mode 100644
index 0000000..91efdad
--- /dev/null
+++ b/tools/telemetry/examples/benchmarks/v8_metric.py
@@ -0,0 +1,42 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.value import improvement_direction
+from telemetry.value import scalar
+from telemetry.web_perf.metrics import timeline_based_metric
+
+def _IsMessageLoopEvent(event):
+  return event.name.startswith('v8')
+
+
+class _AverageMessageLoopLatency(scalar.ScalarValue):
+  def __init__(self, value, page, tir_label, none_value_reason=None):
+    super(_AverageMessageLoopLatency, self).__init__(
+      page=page, name='avg_v8_events_latency', value=value,
+      tir_label=tir_label,
+      units='ms', improvement_direction=improvement_direction.DOWN,
+      description=('Average wall-time latency of message loop events during '
+                   'any of the interaction records\' time ranges'),
+      none_value_reason=none_value_reason)
+
+
+class MessageLoopLatencyMetric(timeline_based_metric.TimelineBasedMetric):
+
+  def AddResults(self, model, renderer_thread, interactions, results):
+    v8_events = []
+    for event in model.IterAllEvents(event_predicate=_IsMessageLoopEvent):
+      if timeline_based_metric.IsEventInInteractions(event, interactions):
+        v8_events.append(event)
+
+    if v8_events:
+      avg = (
+          sum(e.duration for e in v8_events)/len(v8_events))
+      results.AddValue(_AverageMessageLoopLatency(
+          value=avg, page=results.current_page,
+          tir_label=interactions[0].label))
+    else:
+      results.AddValue(_AverageMessageLoopLatency(
+          None, page=results.current_page,
+          tir_label=interactions[0].label,
+          none_value_reason='No v8 events found.'))
diff --git a/tools/telemetry/examples/run_benchmark b/tools/telemetry/examples/run_benchmark
new file mode 100755
index 0000000..6b2d3761
--- /dev/null
+++ b/tools/telemetry/examples/run_benchmark
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+from telemetry import benchmark_runner
+
+def main():
+  top_level_dir = os.path.dirname(__file__)
+  config = benchmark_runner.ProjectConfig(
+      top_level_dir=top_level_dir,
+      benchmark_dirs=[os.path.join(top_level_dir, 'benchmarks')])
+  return benchmark_runner.main(config)
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/tools/telemetry/telemetry/core/android_action_runner.py b/tools/telemetry/telemetry/core/android_action_runner.py
index c4c8e303..882dcb1 100644
--- a/tools/telemetry/telemetry/core/android_action_runner.py
+++ b/tools/telemetry/telemetry/core/android_action_runner.py
@@ -116,19 +116,6 @@
     """
     self._platform_backend.device.RunShellCommand('input roll %s %s' % (dx, dy))
 
-  def EnsureScreenOn(self):
-    """If device screen is off, turn screen on.
-    If the screen is already on, return immediately.
-
-    Raises:
-      Timeout: If the screen is off and device fails to turn screen on.
-    """
-    if self._platform_backend.IsScreenOn():
-      return
-
-    self._ToggleScreenOn()
-    util.WaitFor(self._platform_backend.IsScreenOn, 5)
-
   def TurnScreenOn(self):
     """If device screen is off, turn screen on.
     If the screen is already on, log a warning and return immediately.
@@ -136,13 +123,8 @@
     Raises:
       Timeout: If the screen is off and device fails to turn screen on.
     """
-    if not self._platform_backend.IsScreenOn():
-      self._ToggleScreenOn()
-    else:
-      logging.warning('Screen on when expected off.')
-      return
-
-    util.WaitFor(self._platform_backend.IsScreenOn, 5)
+    self._platform_backend.device.SetScreen(True)
+    util.WaitFor(self._platform_backend.device.IsScreenOn, 5)
 
   def TurnScreenOff(self):
     """If device screen is on, turn screen off.
@@ -152,14 +134,9 @@
       Timeout: If the screen is on and device fails to turn screen off.
     """
     def is_screen_off():
-      return not self._platform_backend.IsScreenOn()
+      return not self._platform_backend.device.IsScreenOn()
 
-    if self._platform_backend.IsScreenOn():
-      self._ToggleScreenOn()
-    else:
-      logging.warning('Screen off when expected on.')
-      return
-
+    self._platform_backend.device.SetScreen(False)
     util.WaitFor(is_screen_off, 5)
 
   def UnlockScreen(self):
@@ -179,6 +156,3 @@
       return
 
     util.WaitFor(is_screen_unlocked, 5)
-
-  def _ToggleScreenOn(self):
-    self._platform_backend.device.RunShellCommand('input keyevent 26')
diff --git a/tools/telemetry/telemetry/decorators.py b/tools/telemetry/telemetry/decorators.py
index 8865408..abcfa9f 100644
--- a/tools/telemetry/telemetry/decorators.py
+++ b/tools/telemetry/telemetry/decorators.py
@@ -99,8 +99,6 @@
 def Disabled(*args):
   """Decorator for disabling tests/benchmarks.
 
-  May be used without args to unconditionally disable:
-    @Disabled  # Unconditionally disabled.
 
   If args are given, the test will be disabled if ANY of the args match the
   browser type, OS name or OS version:
@@ -108,19 +106,17 @@
     @Disabled('win')           # Disabled on Windows.
     @Disabled('win', 'linux')  # Disabled on both Windows and Linux.
     @Disabled('mavericks')     # Disabled on Mac Mavericks (10.9) only.
+    @Disabled('all')  # Unconditionally disabled.
   """
   def _Disabled(func):
-    if not isinstance(func, types.FunctionType):
-      func._disabled_strings = disabled_strings
-      return func
-    @functools.wraps(func)
-    def wrapper(*args, **kwargs):
-      func(*args, **kwargs)
-    wrapper._disabled_strings = disabled_strings
-    return wrapper
-  if len(args) == 1 and callable(args[0]):
-    disabled_strings = []
-    return _Disabled(args[0])
+    if not hasattr(func, '_disabled_strings'):
+      func._disabled_strings = set()
+    func._disabled_strings.update(disabled_strings)
+    return func
+  assert args, (
+      "@Disabled(...) requires arguments. Use @Disabled('all') if you want to "
+      'unconditionally disable the test.')
+  assert not callable(args[0]), 'Please use @Disabled(..).'
   disabled_strings = list(args)
   for disabled_string in disabled_strings:
     # TODO(tonyg): Validate that these strings are recognized.
@@ -139,15 +135,12 @@
     @Enabled('mavericks')     # Enabled only on Mac Mavericks (10.9).
   """
   def _Enabled(func):
-    if not isinstance(func, types.FunctionType):
-      func._enabled_strings = enabled_strings
-      return func
-    @functools.wraps(func)
-    def wrapper(*args, **kwargs):
-      func(*args, **kwargs)
-    wrapper._enabled_strings = enabled_strings
-    return wrapper
-  assert args and not callable(args[0]), '@Enabled requires arguments'
+    if not hasattr(func, '_enabled_strings'):
+      func._enabled_strings = set()
+    func._enabled_strings.update(enabled_strings)
+    return func
+  assert args, '@Enabled(..) requires arguments'
+  assert not callable(args[0]), 'Please use @Enabled(..).'
   enabled_strings = list(args)
   for enabled_string in enabled_strings:
     # TODO(tonyg): Validate that these strings are recognized.
@@ -180,6 +173,7 @@
   return _Isolated
 
 
+# TODO(nednguyen): Remove this and have call site just use ShouldSkip directly.
 def IsEnabled(test, possible_browser):
   """Returns True iff |test| is enabled given the |possible_browser|.
 
@@ -220,14 +214,14 @@
   running = 'You are running %r.' % platform_attributes
 
   if hasattr(test, '_disabled_strings'):
-    if not test._disabled_strings:
+    if 'all' in test._disabled_strings:
       return (True, '%s it is unconditionally disabled.' % skip)
     if set(test._disabled_strings) & set(platform_attributes):
       return (True, '%s it is disabled for %s. %s' %
                       (skip, ' and '.join(test._disabled_strings), running))
 
   if hasattr(test, '_enabled_strings'):
-    if not test._enabled_strings:
+    if 'all' in test._enabled_strings:
       return False, None  # No arguments to @Enabled means always enable.
     if not set(test._enabled_strings) & set(platform_attributes):
       return (True, '%s it is only enabled for %s. %s' %
diff --git a/tools/telemetry/telemetry/decorators_unittest.py b/tools/telemetry/telemetry/decorators_unittest.py
index 8109057e..84ca050 100644
--- a/tools/telemetry/telemetry/decorators_unittest.py
+++ b/tools/telemetry/telemetry/decorators_unittest.py
@@ -33,6 +33,95 @@
     self._disabled_strings = disabled_strings
 
 
+class TestDisableDecorators(unittest.TestCase):
+
+  def testDisabledStringOnFunction(self):
+    @decorators.Disabled('bar')
+    def Sum():
+      return 1 + 1
+    self.assertEquals({'bar'}, Sum._disabled_strings)
+
+    @decorators.Disabled('bar')
+    @decorators.Disabled('baz')
+    @decorators.Disabled('bart', 'baz')
+    def Product():
+      return 1 * 1
+    self.assertEquals({'bar', 'bart', 'baz'}, Product._disabled_strings)
+
+  def testDisabledStringOnClass(self):
+    @decorators.Disabled('windshield')
+    class Ford(object):
+      pass
+    self.assertEquals({'windshield'}, Ford._disabled_strings)
+
+    @decorators.Disabled('windows', 'Drive')
+    @decorators.Disabled('wheel')
+    @decorators.Disabled('windows')
+    class Honda(object):
+      pass
+    self.assertEquals({'wheel', 'Drive', 'windows'}, Honda._disabled_strings)
+
+  def testDisabledStringOnMethod(self):
+    class Ford(object):
+      @decorators.Disabled('windshield')
+      def Drive(self):
+        pass
+    self.assertEquals({'windshield'}, Ford().Drive._disabled_strings)
+
+    class Honda(object):
+      @decorators.Disabled('windows', 'Drive')
+      @decorators.Disabled('wheel')
+      @decorators.Disabled('windows')
+      def Drive(self):
+        pass
+    self.assertEquals({'wheel', 'Drive', 'windows'},
+                      Honda().Drive._disabled_strings)
+
+class TestEnableDecorators(unittest.TestCase):
+
+  def testEnabledStringOnFunction(self):
+    @decorators.Enabled('minus', 'power')
+    def Sum():
+      return 1 + 1
+    self.assertEquals({'minus', 'power'}, Sum._enabled_strings)
+
+    @decorators.Enabled('dot')
+    @decorators.Enabled('product')
+    @decorators.Enabled('product', 'dot')
+    def Product():
+      return 1 * 1
+    self.assertEquals({'dot', 'product'}, Product._enabled_strings)
+
+  def testEnabledStringOnClass(self):
+    @decorators.Enabled('windshield', 'light')
+    class Ford(object):
+      pass
+    self.assertEquals({'windshield', 'light'}, Ford._enabled_strings)
+
+    @decorators.Enabled('wheel', 'Drive')
+    @decorators.Enabled('wheel')
+    @decorators.Enabled('windows')
+    class Honda(object):
+      pass
+    self.assertEquals({'wheel', 'Drive', 'windows'}, Honda._enabled_strings)
+
+  def testEnabledStringOnMethod(self):
+    class Ford(object):
+      @decorators.Enabled('windshield')
+      def Drive(self):
+        pass
+    self.assertEquals({'windshield'}, Ford().Drive._enabled_strings)
+
+    class Honda(object):
+      @decorators.Enabled('windows', 'Drive')
+      @decorators.Enabled('wheel', 'Drive')
+      @decorators.Enabled('windows')
+      def Drive(self):
+        pass
+    self.assertEquals({'wheel', 'Drive', 'windows'},
+                      Honda().Drive._enabled_strings)
+
+
 class TestShouldSkip(unittest.TestCase):
   def testEnabledStrings(self):
     test = FakeTest()
@@ -84,6 +173,7 @@
     test.SetDisabledStrings(['another_os_name', 'another_os_version_name'])
     self.assertFalse(decorators.ShouldSkip(test, possible_browser)[0])
 
+
 class TestDeprecation(unittest.TestCase):
 
   @mock.patch('warnings.warn')
diff --git a/tools/telemetry/telemetry/internal/backends/chrome/cros_unittest.py b/tools/telemetry/telemetry/internal/backends/chrome/cros_unittest.py
index 7529fa06..607567f3 100644
--- a/tools/telemetry/telemetry/internal/backends/chrome/cros_unittest.py
+++ b/tools/telemetry/telemetry/internal/backends/chrome/cros_unittest.py
@@ -65,7 +65,7 @@
         pass
       util.WaitFor(lambda: not self._IsCryptohomeMounted(), 20)
 
-  @decorators.Disabled
+  @decorators.Disabled('all')
   def testGaiaLogin(self):
     """Tests gaia login. Credentials are expected to be found in a
     credentials.txt file, with a single line of format username:password."""
@@ -152,7 +152,7 @@
     util.WaitFor(lambda: not browser.oobe_exists, 10)
     self.assertFalse(self._IsScreenLocked(browser))
 
-  @decorators.Disabled
+  @decorators.Disabled('all')
   def testScreenLock(self):
     """Tests autotestPrivate.screenLock"""
     if self._is_guest:
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/inspector_network_unittest.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/inspector_network_unittest.py
index 752ee05..fc1c371 100644
--- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/inspector_network_unittest.py
+++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/inspector_network_unittest.py
@@ -65,7 +65,7 @@
 
   # Flaky on many platforms (at least Win, Linux, and Mac).
   # http://crbug.com/424706
-  @decorators.Disabled
+  @decorators.Disabled('all')
   def testCacheableHTTPResponse(self):
     # We know this page has one PNG image and its cacheable.
     events = self._NavigateAndGetHTTPResponseEvents('image_decoding.html')
diff --git a/tools/telemetry/telemetry/internal/backends/mandoline/desktop_mandoline_backend.py b/tools/telemetry/telemetry/internal/backends/mandoline/desktop_mandoline_backend.py
index f5df151..f5a571da 100644
--- a/tools/telemetry/telemetry/internal/backends/mandoline/desktop_mandoline_backend.py
+++ b/tools/telemetry/telemetry/internal/backends/mandoline/desktop_mandoline_backend.py
@@ -16,9 +16,9 @@
 
 class DesktopMandolineBackend(
     mandoline_browser_backend.MandolineBrowserBackend):
-  """The backend for controlling a locally-executed browser instance, on Linux
+  '''The backend for controlling a locally-executed browser instance, on Linux
   or Windows.
-  """
+  '''
   # It is OK to have abstract methods. pylint: disable=W0223
 
   def __init__(self, desktop_platform_backend, browser_options, executable,
@@ -34,7 +34,7 @@
     self._tmp_profile_dir = None
     if not self.browser_options.profile_dir:
       self._tmp_profile_dir = tempfile.mkdtemp()
-    logging.info("Using profile directory:'%s'." % self.profile_directory)
+    logging.info('Using profile directory: %s' % self.profile_directory)
 
     self._executable = executable
     if not self._executable:
@@ -47,7 +47,7 @@
     # check if the browser process is still alive.
     if not self.IsBrowserRunning():
       raise exceptions.ProcessGoneException(
-          "Return code: %d" % self._proc.returncode)
+          'Return code: %d' % self._proc.returncode)
     return super(DesktopMandolineBackend, self).HasBrowserFinishedLaunching()
 
   def GetBrowserStartupArgs(self):
@@ -113,7 +113,7 @@
         # This can happen in the case that loading the mandoline binary fails.
         # We print rather than using logging here, because that makes a
         # recursive call to this function.
-        print >> sys.stderr, "Can't get standard output with --show-stdout"
+        print >> sys.stderr, 'Can\'t get standard output with --show-stdout'
       return ''
     try:
       self._tmp_output_file.flush()
@@ -129,26 +129,21 @@
   def __del__(self):
     self.Close()
 
-  def _TryCooperativeShutdown(self):
-    if self.browser.platform.IsCooperativeShutdownSupported():
-      if self.browser.platform.CooperativelyShutdown(self._proc, "mandoline"):
-        try:
-          util.WaitFor(lambda: not self.IsBrowserRunning(), timeout=5)
-          logging.info('Successfully shut down browser cooperatively')
-        except exceptions.TimeoutException as e:
-          logging.warning('Failed to cooperatively shutdown. ' +
-                          'Proceeding to terminate: ' + str(e))
-
   def Close(self):
     super(DesktopMandolineBackend, self).Close()
 
-    if self.IsBrowserRunning():
-      self._TryCooperativeShutdown()
-
+    # Cooperative shutdown does not work with mandoline. Its HWNDs are owned by
+    # subprocesses of mandoline.exe, so its pid won't match pids of HWND owners.
     if self.IsBrowserRunning():
       self._proc.kill()
+      util.WaitFor(lambda: not self.IsBrowserRunning(), timeout=10)
+      if self.IsBrowserRunning():
+        logging.warning('Failed to kill the browser process cleanly.')
     self._proc = None
 
     if self._tmp_profile_dir and os.path.exists(self._tmp_profile_dir):
-      shutil.rmtree(self._tmp_profile_dir, ignore_errors=True)
+      try:
+        shutil.rmtree(self._tmp_profile_dir)
+      except Exception as e:
+        logging.warning('Leaking temp dir: %s\n%s' % (self._tmp_profile_dir, e))
       self._tmp_profile_dir = None
diff --git a/tools/telemetry/telemetry/internal/image_processing/video_unittest.py b/tools/telemetry/telemetry/internal/image_processing/video_unittest.py
index 6a2cd83c..7cbf4e6 100644
--- a/tools/telemetry/telemetry/internal/image_processing/video_unittest.py
+++ b/tools/telemetry/telemetry/internal/image_processing/video_unittest.py
@@ -15,7 +15,7 @@
 
 class VideoTest(unittest.TestCase):
 
-  @decorators.Disabled
+  @decorators.Disabled('all')
   def testFramesFromMp4(self):
     host_platform = platform.GetHostPlatform()
 
diff --git a/tools/telemetry/telemetry/internal/platform/android_platform_backend.py b/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
index 186968fd..d349b67 100644
--- a/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
+++ b/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
@@ -798,38 +798,9 @@
                                        stdout=subprocess.PIPE).communicate()[0])
     return ret
 
-  @staticmethod
-  def _IsScreenOn(input_methods):
-    """Parser method of IsScreenOn()
-
-    Args:
-      input_methods: Output from dumpsys input_methods
-
-    Returns:
-      boolean: True if screen is on, false if screen is off.
-
-    Raises:
-      ValueError: An unknown value is found for the screen state.
-      AndroidDeviceParsingError: Error in detecting screen state.
-    """
-    for line in input_methods:
-      if 'mScreenOn' in line or 'mInteractive' in line:
-        for pair in line.strip().split(' '):
-          key, value = pair.split('=', 1)
-          if key == 'mScreenOn' or key == 'mInteractive':
-            if value == 'true':
-              return True
-            elif value == 'false':
-              return False
-            else:
-              raise ValueError('Unknown value for %s: %s' % (key, value))
-    raise exceptions.AndroidDeviceParsingError(str(input_methods))
-
   def IsScreenOn(self):
     """Determines if device screen is on."""
-    input_methods = self._device.RunShellCommand(
-        'dumpsys input_method', check_return=True, large_output=True)
-    return self._IsScreenOn(input_methods)
+    return self._device.IsScreenOn()
 
   @staticmethod
   def _IsScreenLocked(input_methods):
diff --git a/tools/telemetry/telemetry/internal/platform/android_platform_backend_unittest.py b/tools/telemetry/telemetry/internal/platform/android_platform_backend_unittest.py
index 84edc5c..5fae513f 100644
--- a/tools/telemetry/telemetry/internal/platform/android_platform_backend_unittest.py
+++ b/tools/telemetry/telemetry/internal/platform/android_platform_backend_unittest.py
@@ -121,29 +121,6 @@
         android_device.AndroidDevice('success'), self._options)
     self.assertFalse(backend._IsScreenLocked(test_input))
 
-  def testIsScreenOnmScreenOnTrue(self):
-    test_input = ['a=b', 'mScreenOn=true']
-    backend = android_platform_backend.AndroidPlatformBackend(
-        android_device.AndroidDevice('success'), self._options)
-    self.assertTrue(backend._IsScreenOn(test_input))
-
-  def testIsScreenOnmScreenOnFalse(self):
-    test_input = ['a=b', 'mScreenOn=false']
-    backend = android_platform_backend.AndroidPlatformBackend(
-        android_device.AndroidDevice('success'), self._options)
-    self.assertFalse(backend._IsScreenOn(test_input))
-
-  def testIsScreenOnmInteractiveTrue(self):
-    test_input = ['a=b', 'mInteractive=true']
-    backend = android_platform_backend.AndroidPlatformBackend(
-        android_device.AndroidDevice('success'), self._options)
-    self.assertTrue(backend._IsScreenOn(test_input))
-
-  def testIsScreenOnmInteractiveFalse(self):
-    test_input = ['a=b', 'mInteractive=false']
-    backend = android_platform_backend.AndroidPlatformBackend(
-        android_device.AndroidDevice('success'), self._options)
-    self.assertFalse(backend._IsScreenOn(test_input))
 
 class AndroidPlatformBackendPsutilTest(unittest.TestCase):
 
diff --git a/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper_unittest.py b/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper_unittest.py
index 0db4e56..7e423232 100644
--- a/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper_unittest.py
+++ b/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper_unittest.py
@@ -201,7 +201,7 @@
 
   # Test fails: crbug.com/437081
   # @decorators.Enabled('android')
-  @decorators.Disabled
+  @decorators.Disabled('all')
   def testGetToolchainBinaryPath(self):
     with tempfile.NamedTemporaryFile() as libc:
       self._device.PullFile('/system/lib/libc.so', libc.name)
diff --git a/tools/telemetry/telemetry/internal/platform/profiler/vtune_profiler_unittest.py b/tools/telemetry/telemetry/internal/platform/profiler/vtune_profiler_unittest.py
index 8b35844c..4c1eee2b 100644
--- a/tools/telemetry/telemetry/internal/platform/profiler/vtune_profiler_unittest.py
+++ b/tools/telemetry/telemetry/internal/platform/profiler/vtune_profiler_unittest.py
@@ -99,7 +99,7 @@
   # This test is only meant to be run if VTune is installed locally. Please
   # run it locally if you are modifying related code, but it's disabled on the
   # bots because they don't have VTune. See crbug.com/437085
-  @decorators.Disabled
+  @decorators.Disabled('all')
   def testVTuneProfiler(self):
     mock_subprocess = MockSubprocess()
     real_subprocess = vtune_profiler.subprocess
diff --git a/tools/telemetry/telemetry/page/page_test_unittest.py b/tools/telemetry/telemetry/page/page_test_unittest.py
index df4fa2a9..80630c27 100644
--- a/tools/telemetry/telemetry/page/page_test_unittest.py
+++ b/tools/telemetry/telemetry/page/page_test_unittest.py
@@ -92,7 +92,7 @@
 
   # This test is disabled because it runs against live sites, and needs to be
   # fixed. crbug.com/179038
-  @decorators.Disabled
+  @decorators.Disabled('all')
   def testRecordAndReplay(self):
     test_archive = '/tmp/google.wpr'
     google_url = 'http://www.google.com/'
diff --git a/tools/telemetry/telemetry/testing/disabled_cases.py b/tools/telemetry/telemetry/testing/disabled_cases.py
index 0cace2ab..bb4641a 100644
--- a/tools/telemetry/telemetry/testing/disabled_cases.py
+++ b/tools/telemetry/telemetry/testing/disabled_cases.py
@@ -14,7 +14,7 @@
   def testAllEnabled(self):
     pass
 
-  @decorators.Disabled
+  @decorators.Disabled('all')
   def testAllDisabled(self):
     pass
 
diff --git a/tools/telemetry/telemetry/timeline/memory_dump_event.py b/tools/telemetry/telemetry/timeline/memory_dump_event.py
index 0ba32fe..218b687 100644
--- a/tools/telemetry/telemetry/timeline/memory_dump_event.py
+++ b/tools/telemetry/telemetry/timeline/memory_dump_event.py
@@ -163,9 +163,8 @@
     for allocator_name, size_values in allocators_dict.iteritems():
       name_parts = allocator_name.split('/')
       # we want to skip allocated_objects, since they are already counted by
-      # outer allocator names; but malloc is special, because the size of outer
-      # allocators is only inherited from its allocated_objects.
-      if name_parts[-1] == 'allocated_objects' and name_parts[0] != 'malloc':
+      # outer allocator names.
+      if name_parts[-1] == 'allocated_objects':
         continue
       allocator_name = name_parts[0]
       # For 'gpu/android_memtrack/*' we want to keep track of individual
diff --git a/tools/telemetry/telemetry/web_perf/metrics/timeline_based_metric.py b/tools/telemetry/telemetry/web_perf/metrics/timeline_based_metric.py
index 71f3f15..0ad00aa 100644
--- a/tools/telemetry/telemetry/web_perf/metrics/timeline_based_metric.py
+++ b/tools/telemetry/telemetry/web_perf/metrics/timeline_based_metric.py
@@ -67,6 +67,17 @@
     """
     raise NotImplementedError()
 
+  def AddWholeTraceResults(self, model, results):
+    """Computes and adds metrics corresponding to the entire trace.
+
+    Override this method to compute results that correspond to the whole trace.
+
+    Args:
+      model: An instance of telemetry.timeline.model.TimelineModel.
+      results: An instance of page.PageTestResults.
+    """
+    pass
+
   def VerifyNonOverlappedRecords(self, interaction_records):
     """This raises exceptions if interaction_records contain overlapped ranges.
     """
diff --git a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
index 5be3dea..664a8d8 100644
--- a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
+++ b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
@@ -271,13 +271,19 @@
           'This could be caused by console.time() & console.timeEnd() execution'
           ' failure or the tracing category specified doesn\'t include '
           'blink.console categories.')
+
+    all_metrics = self._tbm_options.GetTimelineBasedMetrics()
+
     for renderer_thread, interaction_records in (
         threads_to_records_map.iteritems()):
       meta_metrics = _TimelineBasedMetrics(
-          model, renderer_thread, interaction_records,
-          self._results_wrapper, self._tbm_options.GetTimelineBasedMetrics())
+          model, renderer_thread, interaction_records, self._results_wrapper,
+          all_metrics)
       meta_metrics.AddResults(results)
 
+    for metric in all_metrics:
+      metric.AddWholeTraceResults(model, results)
+
   def DidRunStory(self, platform):
     """Clean up after running the story."""
     if platform.tracing_controller.is_tracing_running:
diff --git a/tools/telemetry/telemetry/web_perf/timeline_based_measurement_unittest.py b/tools/telemetry/telemetry/web_perf/timeline_based_measurement_unittest.py
index a2d46cd..fcfe103a 100644
--- a/tools/telemetry/telemetry/web_perf/timeline_based_measurement_unittest.py
+++ b/tools/telemetry/telemetry/web_perf/timeline_based_measurement_unittest.py
@@ -40,6 +40,17 @@
         improvement_direction=improvement_direction.DOWN))
 
 
+class FakeStartupMetric(timeline_based_metric.TimelineBasedMetric):
+
+  def AddResults(self, model, renderer_thread, interaction_records, results):
+    pass
+
+  def AddWholeTraceResults(self, model, results):
+    results.AddValue(scalar.ScalarValue(
+        results.current_page, 'FakeStartupMetric', 'ms', 3,
+        improvement_direction=improvement_direction.DOWN))
+
+
 class TimelineBasedMetricTestData(object):
 
   def __init__(self, options):
@@ -93,11 +104,16 @@
     self._results.WillRunPage(self._story_set.stories[0])
 
   def AddResults(self):
+    all_metrics = self._tbm_options.GetTimelineBasedMetrics()
+
     for thread, records in self._threads_to_records_map.iteritems():
       metric = tbm_module._TimelineBasedMetrics(  # pylint: disable=W0212
-          self._model, thread, records, self._results_wrapper,
-          self._tbm_options.GetTimelineBasedMetrics())
+          self._model, thread, records, self._results_wrapper, all_metrics)
       metric.AddResults(self._results)
+
+    for metric in all_metrics:
+      metric.AddWholeTraceResults(self._model, self._results)
+
     self._results.DidRunPage(self._story_set.stories[0])
 
 
@@ -107,7 +123,7 @@
     self.actual_get_all_tbm_metrics = tbm_module._GetAllTimelineBasedMetrics
     self._options = tbm_module.Options()
     self._options.SetTimelineBasedMetrics(
-        (FakeSmoothMetric(), FakeLoadingMetric()))
+        (FakeSmoothMetric(), FakeLoadingMetric(), FakeStartupMetric()))
 
   def tearDown(self):
     tbm_module._GetAllTimelineBasedMetrics = self.actual_get_all_tbm_metrics
@@ -154,6 +170,8 @@
         'LogicalName1', 'FakeSmoothMetric')))
     self.assertEquals(1, len(d.results.FindAllPageSpecificValuesFromIRNamed(
         'LogicalName2', 'FakeLoadingMetric')))
+    self.assertEquals(1, len(d.results.FindAllPageSpecificValuesNamed(
+        'FakeStartupMetric')))
 
   def testDuplicateInteractionsInDifferentThreads(self):
     d = TimelineBasedMetricTestData(self._options)
@@ -171,7 +189,6 @@
                      marker='Interaction.LogicalName/repeatable')
     self.assertRaises(tbm_module.InvalidInteractions, d.FinalizeImport)
 
-
   def testDuplicateUnrepeatableInteractionsInSameThread(self):
     d = TimelineBasedMetricTestData(self._options)
     d.AddInteraction(d.renderer_thread, ts=10, duration=5,
diff --git a/ui/gfx/text_elider.cc b/ui/gfx/text_elider.cc
index 654b1aa..cac4fa06 100644
--- a/ui/gfx/text_elider.cc
+++ b/ui/gfx/text_elider.cc
@@ -39,7 +39,7 @@
 
 namespace {
 
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID) && !defined(USE_AURA) || defined(OS_IOS)
 // The returned string will have at least one character besides the ellipsis
 // on either side of '@'; if that's impossible, a single ellipsis is returned.
 // If possible, only the username is elided. Otherwise, the domain is elided
@@ -194,21 +194,7 @@
                          const FontList& font_list,
                          float available_pixel_width,
                          ElideBehavior behavior) {
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-  DCHECK_NE(behavior, FADE_TAIL);
-  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
-  render_text->SetCursorEnabled(false);
-  // Do not bother accurately sizing strings over 5000 characters here, for
-  // performance purposes. This matches the behavior of Canvas::SizeStringFloat.
-  render_text->set_truncate_length(5000);
-  render_text->SetFontList(font_list);
-  available_pixel_width = std::ceil(available_pixel_width);
-  render_text->SetDisplayRect(
-      gfx::ToEnclosingRect(gfx::RectF(gfx::SizeF(available_pixel_width, 1))));
-  render_text->SetElideBehavior(behavior);
-  render_text->SetText(text);
-  return render_text->GetDisplayText();
-#else
+#if defined(OS_ANDROID) && !defined(USE_AURA) || defined(OS_IOS)
   DCHECK_NE(behavior, FADE_TAIL);
   if (text.empty() || behavior == FADE_TAIL || behavior == NO_ELIDE ||
       GetStringWidthF(text, font_list) <= available_pixel_width) {
@@ -252,6 +238,21 @@
   }
 
   return cut;
+#else
+  DCHECK_NE(behavior, FADE_TAIL);
+  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
+  render_text->SetCursorEnabled(false);
+  // TODO(bshe): 5000 is out dated. We should remove it. See crbug.com/551660.
+  // Do not bother accurately sizing strings over 5000 characters here, for
+  // performance purposes. This matches the behavior of Canvas::SizeStringFloat.
+  render_text->set_truncate_length(5000);
+  render_text->SetFontList(font_list);
+  available_pixel_width = std::ceil(available_pixel_width);
+  render_text->SetDisplayRect(
+      gfx::ToEnclosingRect(gfx::RectF(gfx::SizeF(available_pixel_width, 1))));
+  render_text->SetElideBehavior(behavior);
+  render_text->SetText(text);
+  return render_text->GetDisplayText();
 #endif
 }
 
diff --git a/ui/views/animation/ink_drop_animation.cc b/ui/views/animation/ink_drop_animation.cc
index 4826f78a..6fbc648 100644
--- a/ui/views/animation/ink_drop_animation.cc
+++ b/ui/views/animation/ink_drop_animation.cc
@@ -9,16 +9,15 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkPaint.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/compositor/callback_layer_animation_observer.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animation_sequence.h"
-#include "ui/compositor/paint_recorder.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/transform_util.h"
 #include "ui/views/animation/ink_drop_animation_observer.h"
+#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
 #include "ui/views/view.h"
 
 namespace {
@@ -123,116 +122,6 @@
 
 namespace views {
 
-// Base ui::LayerDelegate stub that can be extended to paint shapes of a
-// specific color.
-class BasePaintedLayerDelegate : public ui::LayerDelegate {
- public:
-  ~BasePaintedLayerDelegate() override;
-
-  SkColor color() const { return color_; }
-
-  // ui::LayerDelegate:
-  void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
-  void OnDeviceScaleFactorChanged(float device_scale_factor) override;
-  base::Closure PrepareForLayerBoundsChange() override;
-
- protected:
-  explicit BasePaintedLayerDelegate(SkColor color);
-
- private:
-  // The color to paint.
-  SkColor color_;
-
-  DISALLOW_COPY_AND_ASSIGN(BasePaintedLayerDelegate);
-};
-
-BasePaintedLayerDelegate::BasePaintedLayerDelegate(SkColor color)
-    : color_(color) {}
-
-BasePaintedLayerDelegate::~BasePaintedLayerDelegate() {}
-
-void BasePaintedLayerDelegate::OnDelegatedFrameDamage(
-    const gfx::Rect& damage_rect_in_dip) {}
-
-void BasePaintedLayerDelegate::OnDeviceScaleFactorChanged(
-    float device_scale_factor) {}
-
-base::Closure BasePaintedLayerDelegate::PrepareForLayerBoundsChange() {
-  return base::Closure();
-}
-
-// A BasePaintedLayerDelegate that paints a circle of a specified color and
-// radius.
-class CircleLayerDelegate : public BasePaintedLayerDelegate {
- public:
-  CircleLayerDelegate(SkColor color, int radius);
-  ~CircleLayerDelegate() override;
-
-  int radius() const { return radius_; }
-
-  // ui::LayerDelegate:
-  void OnPaintLayer(const ui::PaintContext& context) override;
-
- private:
-  // The radius of the circle.
-  int radius_;
-
-  DISALLOW_COPY_AND_ASSIGN(CircleLayerDelegate);
-};
-
-CircleLayerDelegate::CircleLayerDelegate(SkColor color, int radius)
-    : BasePaintedLayerDelegate(color), radius_(radius) {}
-
-CircleLayerDelegate::~CircleLayerDelegate() {}
-
-void CircleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
-  SkPaint paint;
-  paint.setColor(color());
-  paint.setFlags(SkPaint::kAntiAlias_Flag);
-  paint.setStyle(SkPaint::kFill_Style);
-
-  ui::PaintRecorder recorder(context, gfx::Size(radius_, radius_));
-  gfx::Canvas* canvas = recorder.canvas();
-
-  gfx::Point center_point = gfx::Point(radius_, radius_);
-  canvas->DrawCircle(center_point, radius_, paint);
-}
-
-// A BasePaintedLayerDelegate that paints a rectangle of a specified color and
-// size.
-class RectangleLayerDelegate : public BasePaintedLayerDelegate {
- public:
-  RectangleLayerDelegate(SkColor color, gfx::Size size);
-  ~RectangleLayerDelegate() override;
-
-  const gfx::Size& size() const { return size_; }
-
-  // ui::LayerDelegate:
-  void OnPaintLayer(const ui::PaintContext& context) override;
-
- private:
-  // The size of the rectangle.
-  gfx::Size size_;
-
-  DISALLOW_COPY_AND_ASSIGN(RectangleLayerDelegate);
-};
-
-RectangleLayerDelegate::RectangleLayerDelegate(SkColor color, gfx::Size size)
-    : BasePaintedLayerDelegate(color), size_(size) {}
-
-RectangleLayerDelegate::~RectangleLayerDelegate() {}
-
-void RectangleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
-  SkPaint paint;
-  paint.setColor(color());
-  paint.setFlags(SkPaint::kAntiAlias_Flag);
-  paint.setStyle(SkPaint::kFill_Style);
-
-  ui::PaintRecorder recorder(context, size_);
-  gfx::Canvas* canvas = recorder.canvas();
-  canvas->DrawRect(gfx::Rect(size_), paint);
-}
-
 InkDropAnimation::InkDropAnimation(const gfx::Size& large_size,
                                    int large_corner_radius,
                                    const gfx::Size& small_size,
@@ -441,19 +330,19 @@
   const float circle_target_y_offset = size.height() / 2.0f - corner_radius;
 
   (*transforms_out)[TOP_LEFT_CIRCLE] = CalculateCircleTransform(
-      painted_layers_[TOP_LEFT_CIRCLE]->bounds().CenterPoint(), circle_scale,
+      ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
       -circle_target_x_offset, -circle_target_y_offset);
 
   (*transforms_out)[TOP_RIGHT_CIRCLE] = CalculateCircleTransform(
-      painted_layers_[TOP_RIGHT_CIRCLE]->bounds().CenterPoint(), circle_scale,
+      ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
       circle_target_x_offset, -circle_target_y_offset);
 
   (*transforms_out)[BOTTOM_RIGHT_CIRCLE] = CalculateCircleTransform(
-      painted_layers_[BOTTOM_RIGHT_CIRCLE]->bounds().CenterPoint(),
-      circle_scale, circle_target_x_offset, circle_target_y_offset);
+      ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
+      circle_target_x_offset, circle_target_y_offset);
 
   (*transforms_out)[BOTTOM_LEFT_CIRCLE] = CalculateCircleTransform(
-      painted_layers_[BOTTOM_LEFT_CIRCLE]->bounds().CenterPoint(), circle_scale,
+      ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
       -circle_target_x_offset, circle_target_y_offset);
 
   const float rect_delegate_width =
@@ -462,13 +351,13 @@
       static_cast<float>(rect_layer_delegate_->size().height());
 
   (*transforms_out)[HORIZONTAL_RECT] = CalculateRectTransform(
-      painted_layers_[HORIZONTAL_RECT]->bounds().CenterPoint(),
+      ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()),
       std::max(kMinimumRectScale, size.width() / rect_delegate_width),
       std::max(kMinimumRectScale,
                (size.height() - 2.0f * corner_radius) / rect_delegate_height));
 
   (*transforms_out)[VERTICAL_RECT] = CalculateRectTransform(
-      painted_layers_[VERTICAL_RECT]->bounds().CenterPoint(),
+      ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()),
       std::max(kMinimumRectScale,
                (size.width() - 2.0f * corner_radius) / rect_delegate_width),
       std::max(kMinimumRectScale, size.height() / rect_delegate_height));
diff --git a/ui/views/animation/ink_drop_painted_layer_delegates.cc b/ui/views/animation/ink_drop_painted_layer_delegates.cc
new file mode 100644
index 0000000..bdb7946
--- /dev/null
+++ b/ui/views/animation/ink_drop_painted_layer_delegates.cc
@@ -0,0 +1,85 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
+
+#include "third_party/skia/include/core/SkPaint.h"
+#include "ui/compositor/paint_recorder.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_conversions.h"
+
+namespace views {
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// BasePaintedLayerDelegate
+//
+
+BasePaintedLayerDelegate::BasePaintedLayerDelegate(SkColor color)
+    : color_(color) {}
+
+BasePaintedLayerDelegate::~BasePaintedLayerDelegate() {}
+
+void BasePaintedLayerDelegate::OnDelegatedFrameDamage(
+    const gfx::Rect& damage_rect_in_dip) {}
+
+void BasePaintedLayerDelegate::OnDeviceScaleFactorChanged(
+    float device_scale_factor) {}
+
+base::Closure BasePaintedLayerDelegate::PrepareForLayerBoundsChange() {
+  return base::Closure();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// CircleLayerDelegate
+//
+
+CircleLayerDelegate::CircleLayerDelegate(SkColor color, int radius)
+    : BasePaintedLayerDelegate(color), radius_(radius) {}
+
+CircleLayerDelegate::~CircleLayerDelegate() {}
+
+gfx::PointF CircleLayerDelegate::GetCenterPoint() const {
+  return gfx::PointF(radius_, radius_);
+}
+
+void CircleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
+  SkPaint paint;
+  paint.setColor(color());
+  paint.setFlags(SkPaint::kAntiAlias_Flag);
+  paint.setStyle(SkPaint::kFill_Style);
+
+  ui::PaintRecorder recorder(context, gfx::Size(radius_, radius_));
+  gfx::Canvas* canvas = recorder.canvas();
+
+  canvas->DrawCircle(ToRoundedPoint(GetCenterPoint()), radius_, paint);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// RectangleLayerDelegate
+//
+
+RectangleLayerDelegate::RectangleLayerDelegate(SkColor color, gfx::Size size)
+    : BasePaintedLayerDelegate(color), size_(size) {}
+
+RectangleLayerDelegate::~RectangleLayerDelegate() {}
+
+gfx::PointF RectangleLayerDelegate::GetCenterPoint() const {
+  return gfx::PointF(size_.width() / 2.0f, size_.height() / 2.0f);
+}
+
+void RectangleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
+  SkPaint paint;
+  paint.setColor(color());
+  paint.setFlags(SkPaint::kAntiAlias_Flag);
+  paint.setStyle(SkPaint::kFill_Style);
+
+  ui::PaintRecorder recorder(context, size_);
+  gfx::Canvas* canvas = recorder.canvas();
+  canvas->DrawRect(gfx::Rect(size_), paint);
+}
+
+}  // namespace views
diff --git a/ui/views/animation/ink_drop_painted_layer_delegates.h b/ui/views/animation/ink_drop_painted_layer_delegates.h
new file mode 100644
index 0000000..feb2921
--- /dev/null
+++ b/ui/views/animation/ink_drop_painted_layer_delegates.h
@@ -0,0 +1,86 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INK_DROP_PAINTED_LAYER_DELEGATES_H_
+#define UI_VIEWS_ANIMATION_INK_DROP_PAINTED_LAYER_DELEGATES_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/compositor/layer_delegate.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace views {
+
+// Base ui::LayerDelegate stub that can be extended to paint shapes of a
+// specific color.
+class BasePaintedLayerDelegate : public ui::LayerDelegate {
+ public:
+  ~BasePaintedLayerDelegate() override;
+
+  SkColor color() const { return color_; }
+
+  // Returns the center point of the painted shape.
+  virtual gfx::PointF GetCenterPoint() const = 0;
+
+  // ui::LayerDelegate:
+  void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
+  void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+  base::Closure PrepareForLayerBoundsChange() override;
+
+ protected:
+  explicit BasePaintedLayerDelegate(SkColor color);
+
+ private:
+  // The color to paint.
+  SkColor color_;
+
+  DISALLOW_COPY_AND_ASSIGN(BasePaintedLayerDelegate);
+};
+
+// A BasePaintedLayerDelegate that paints a circle of a specified color and
+// radius.
+class CircleLayerDelegate : public BasePaintedLayerDelegate {
+ public:
+  CircleLayerDelegate(SkColor color, int radius);
+  ~CircleLayerDelegate() override;
+
+  int radius() const { return radius_; }
+
+  // BasePaintedLayerDelegate:
+  gfx::PointF GetCenterPoint() const override;
+  void OnPaintLayer(const ui::PaintContext& context) override;
+
+ private:
+  // The radius of the circle.
+  int radius_;
+
+  DISALLOW_COPY_AND_ASSIGN(CircleLayerDelegate);
+};
+
+// A BasePaintedLayerDelegate that paints a rectangle of a specified color and
+// size.
+class RectangleLayerDelegate : public BasePaintedLayerDelegate {
+ public:
+  RectangleLayerDelegate(SkColor color, gfx::Size size);
+  ~RectangleLayerDelegate() override;
+
+  const gfx::Size& size() const { return size_; }
+
+  // BasePaintedLayerDelegate:
+  gfx::PointF GetCenterPoint() const override;
+  void OnPaintLayer(const ui::PaintContext& context) override;
+
+ private:
+  // The size of the rectangle.
+  gfx::Size size_;
+
+  DISALLOW_COPY_AND_ASSIGN(RectangleLayerDelegate);
+};
+
+}  // namespace views
+
+#endif  // UI_VIEWS_ANIMATION_INK_DROP_PAINTED_LAYER_DELEGATES_H_
diff --git a/ui/views/mus/native_widget_mus.cc b/ui/views/mus/native_widget_mus.cc
index 717a8be..ccc90d2 100644
--- a/ui/views/mus/native_widget_mus.cc
+++ b/ui/views/mus/native_widget_mus.cc
@@ -4,6 +4,7 @@
 
 #include "ui/views/mus/native_widget_mus.h"
 
+#include "components/mus/public/cpp/property_type_converters.h"
 #include "components/mus/public/cpp/window.h"
 #include "mojo/converters/geometry/geometry_type_converters.h"
 #include "ui/aura/client/default_capture_client.h"
@@ -122,6 +123,18 @@
   DISALLOW_COPY_AND_ASSIGN(ClientSideNonClientFrameView);
 };
 
+mus::mojom::ResizeBehavior ResizeBehaviorFromDelegate(
+    WidgetDelegate* delegate) {
+  int32_t behavior = mus::mojom::RESIZE_BEHAVIOR_NONE;
+  if (delegate->CanResize())
+    behavior |= mus::mojom::RESIZE_BEHAVIOR_CAN_RESIZE;
+  if (delegate->CanMaximize())
+    behavior |= mus::mojom::RESIZE_BEHAVIOR_CAN_MAXIMIZE;
+  if (delegate->CanMinimize())
+    behavior |= mus::mojom::RESIZE_BEHAVIOR_CAN_MINIMIZE;
+  return static_cast<mus::mojom::ResizeBehavior>(behavior);
+}
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -148,20 +161,16 @@
   window_manager_client_area_insets = new WindowManagerClientAreaInsets(insets);
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetMus, private:
-
-void NativeWidgetMus::UpdateClientAreaInWindowManager() {
-  NonClientView* non_client_view =
-      native_widget_delegate_->AsWidget()->non_client_view();
-  if (!non_client_view || !non_client_view->client_view())
+// static
+void NativeWidgetMus::ConfigurePropertiesForNewWindow(
+    const Widget::InitParams& init_params,
+    std::map<std::string, std::vector<uint8_t>>* properties) {
+  if (!Widget::RequiresNonClientView(init_params.type))
     return;
 
-  const gfx::Rect client_area_rect(non_client_view->client_view()->bounds());
-  window_->SetClientArea(gfx::Insets(
-      client_area_rect.y(), client_area_rect.x(),
-      non_client_view->bounds().height() - client_area_rect.bottom(),
-      non_client_view->bounds().width() - client_area_rect.right()));
+  (*properties)[mus::mojom::WindowManager::kResizeBehavior_Property] =
+      mojo::TypeConverter<const std::vector<uint8_t>, int32_t>::Convert(
+          ResizeBehaviorFromDelegate(init_params.delegate));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -536,7 +545,8 @@
 }
 
 void NativeWidgetMus::OnSizeConstraintsChanged() {
-  // NOTIMPLEMENTED();
+  window_->SetResizeBehavior(
+      ResizeBehaviorFromDelegate(GetWidget()->widget_delegate()));
 }
 
 void NativeWidgetMus::RepostNativeEvent(gfx::NativeEvent native_event) {
@@ -670,4 +680,20 @@
   native_widget_delegate_->OnGestureEvent(event);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetMus, private:
+
+void NativeWidgetMus::UpdateClientAreaInWindowManager() {
+  NonClientView* non_client_view =
+      native_widget_delegate_->AsWidget()->non_client_view();
+  if (!non_client_view || !non_client_view->client_view())
+    return;
+
+  const gfx::Rect client_area_rect(non_client_view->client_view()->bounds());
+  window_->SetClientArea(gfx::Insets(
+      client_area_rect.y(), client_area_rect.x(),
+      non_client_view->bounds().height() - client_area_rect.bottom(),
+      non_client_view->bounds().width() - client_area_rect.right()));
+}
+
 }  // namespace views
diff --git a/ui/views/mus/native_widget_mus.h b/ui/views/mus/native_widget_mus.h
index fa270cb..bedbba5 100644
--- a/ui/views/mus/native_widget_mus.h
+++ b/ui/views/mus/native_widget_mus.h
@@ -5,6 +5,9 @@
 #ifndef UI_VIEWS_MUS_NATIVE_WIDGET_MUS_H_
 #define UI_VIEWS_MUS_NATIVE_WIDGET_MUS_H_
 
+#include <map>
+#include <string>
+
 #include "base/memory/scoped_ptr.h"
 #include "components/mus/public/interfaces/window_manager.mojom.h"
 #include "ui/aura/window_delegate.h"
@@ -58,16 +61,17 @@
   static void SetWindowManagerClientAreaInsets(
       const WindowManagerClientAreaInsets& insets);
 
+  // Configures the set of properties supplied to the window manager when
+  // creating a new Window for a Widget.
+  static void ConfigurePropertiesForNewWindow(
+      const Widget::InitParams& init_params,
+      std::map<std::string, std::vector<uint8_t>>* properties);
+
   mus::Window* window() { return window_; }
 
  protected:
   // internal::NativeWidgetPrivate:
   NonClientFrameView* CreateNonClientFrameView() override;
-
- private:
-  void UpdateClientAreaInWindowManager();
-
-  // internal::NativeWidgetPrivate:
   void InitNativeWidget(const Widget::InitParams& params) override;
   bool ShouldUseNativeFrame() const override;
   bool ShouldWindowContentsBeTransparent() const override;
@@ -178,6 +182,9 @@
   void OnScrollEvent(ui::ScrollEvent* event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
 
+ private:
+  void UpdateClientAreaInWindowManager();
+
   mus::Window* window_;
 
   mojo::Shell* shell_;
diff --git a/ui/views/mus/window_manager_connection.cc b/ui/views/mus/window_manager_connection.cc
index 006a8b3..d18d5d52 100644
--- a/ui/views/mus/window_manager_connection.cc
+++ b/ui/views/mus/window_manager_connection.cc
@@ -140,11 +140,12 @@
     mus::WindowTreeConnection* connection) {}
 
 NativeWidget* WindowManagerConnection::CreateNativeWidget(
+    const Widget::InitParams& init_params,
     internal::NativeWidgetDelegate* delegate) {
-  return new NativeWidgetMus(
-      delegate, app_->shell(),
-      NewWindow(std::map<std::string, std::vector<uint8_t>>()),
-      mus::mojom::SURFACE_TYPE_DEFAULT);
+  std::map<std::string, std::vector<uint8_t>> properties;
+  NativeWidgetMus::ConfigurePropertiesForNewWindow(init_params, &properties);
+  return new NativeWidgetMus(delegate, app_->shell(), NewWindow(properties),
+                             mus::mojom::SURFACE_TYPE_DEFAULT);
 }
 
 }  // namespace views
diff --git a/ui/views/mus/window_manager_connection.h b/ui/views/mus/window_manager_connection.h
index cb64c8ee..38a90d08 100644
--- a/ui/views/mus/window_manager_connection.h
+++ b/ui/views/mus/window_manager_connection.h
@@ -8,6 +8,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "components/mus/public/cpp/window_tree_delegate.h"
 #include "components/mus/public/interfaces/window_manager.mojom.h"
+#include "ui/views/widget/widget.h"
 
 namespace mojo {
 class ApplicationImpl;
@@ -49,7 +50,8 @@
   void OnEmbed(mus::Window* root) override;
   void OnConnectionLost(mus::WindowTreeConnection* connection) override;
 
-  NativeWidget* CreateNativeWidget(internal::NativeWidgetDelegate* delegate);
+  NativeWidget* CreateNativeWidget(const Widget::InitParams& init_params,
+                                   internal::NativeWidgetDelegate* delegate);
 
   mojo::ApplicationImpl* app_;
   mus::mojom::WindowManagerPtr window_manager_;
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index 152488d..e678ff9 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -24,6 +24,8 @@
       'animation/ink_drop_animation_observer.cc',
       'animation/ink_drop_animation_observer.h',
       'animation/ink_drop_host.h',
+      'animation/ink_drop_painted_layer_delegates.cc',
+      'animation/ink_drop_painted_layer_delegates.h',
       'animation/ink_drop_state.cc',
       'animation/ink_drop_state.h',
       'animation/scroll_animator.cc',
diff --git a/ui/views/views_delegate.h b/ui/views/views_delegate.h
index f805d28..16ecca0 100644
--- a/ui/views/views_delegate.h
+++ b/ui/views/views_delegate.h
@@ -65,7 +65,8 @@
 class VIEWS_EXPORT ViewsDelegate {
  public:
   using NativeWidgetFactory =
-      base::Callback<NativeWidget*(internal::NativeWidgetDelegate*)>;
+      base::Callback<NativeWidget*(const Widget::InitParams&,
+                                   internal::NativeWidgetDelegate*)>;
 #if defined(OS_WIN)
   enum AppbarAutohideEdge {
     EDGE_TOP    = 1 << 0,
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index 6c0168d4..c3c0252a 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -56,14 +56,15 @@
 // Create a native widget implementation.
 // First, use the supplied one if non-NULL.
 // Finally, make a default one.
-NativeWidget* CreateNativeWidget(NativeWidget* native_widget,
+NativeWidget* CreateNativeWidget(const Widget::InitParams& params,
                                  internal::NativeWidgetDelegate* delegate) {
-  if (native_widget)
-    return native_widget;
+  if (params.native_widget)
+    return params.native_widget;
 
   ViewsDelegate* views_delegate = ViewsDelegate::GetInstance();
   if (views_delegate && !views_delegate->native_widget_factory().is_null()) {
-    native_widget = views_delegate->native_widget_factory().Run(delegate);
+    NativeWidget* native_widget =
+        views_delegate->native_widget_factory().Run(params, delegate);
     if (native_widget)
       return native_widget;
   }
@@ -356,8 +357,7 @@
   widget_delegate_->set_can_activate(can_activate);
 
   ownership_ = params.ownership;
-  native_widget_ = CreateNativeWidget(params.native_widget, this)->
-                   AsNativeWidgetPrivate();
+  native_widget_ = CreateNativeWidget(params, this)->AsNativeWidgetPrivate();
   root_view_.reset(CreateRootView());
   default_theme_provider_.reset(new ui::DefaultThemeProvider);
   if (params.type == InitParams::TYPE_MENU) {
diff --git a/ui/webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.html b/ui/webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.html
deleted file mode 100644
index 4096e9c..0000000
--- a/ui/webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
-<link rel="import" href="chrome://resources/polymer/paper-dropdown-menu/paper-dropdown-menu.html">
-<link rel="import" href="chrome://resources/polymer/paper-dropdown/paper-dropdown.html">
-<link rel="import" href="chrome://resources/html/assert.html">
-
-<polymer-element name="cr-dropdown-menu">
-  <template>
-    <link rel="stylesheet" href="cr_dropdown_menu.css">
-    <paper-dropdown-menu flex label="{{label}}" disabled="{{disabled}}"
-        opened="{{opened}}">
-      <paper-dropdown class="dropdown">
-        <content></content>
-      </paper-dropdown>
-    </paper-dropdown-menu>
-  </template>
-  <script src="cr_dropdown_menu.js"></script>
-</polymer-element>
diff --git a/ui/webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.js b/ui/webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.js
deleted file mode 100644
index 9f3342a..0000000
--- a/ui/webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.js
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview
- * `cr-dropdown-menu` is a Chrome-specific wrapper around paper-dropdown-menu.
- * It includes a paper-dropdown so its content should just be a core-menu and
- * items.
- *
- * Example:
- *   <cr-dropdown-menu>
- *     <core-menu>
- *       <paper-item>Chrome</paper-item>
- *       <paper-item>Firefox</paper-item>
- *       <paper-item>IE</paper-item>
- *       <paper-item>Opera</paper-item>
- *     </core-menu>
- *   </cr-dropdown-menu>
- *
- * @group Chrome Elements
- * @element cr-dropdown-menu
- */
-
-Polymer('cr-dropdown-menu', {
-  publish: {
-    /**
-     * True if the menu is open.
-     *
-     * @attribute opened
-     * @type boolean
-     * @default false
-     */
-    opened: false,
-
-    /**
-     * A label for the control. The label is displayed if no item is selected.
-     *
-     * @attribute label
-     * @type string
-     * @default '<Dropdown Menu Label>'
-     */
-    label: '<Dropdown Menu Label>',
-
-    /**
-     * True if the menu is disabled.
-     *
-     * @attribute disabled
-     * @type boolean
-     * @default false
-     */
-    disabled: {value: false, reflect: true},
-  },
-
-  /** @override */
-  domReady: function() {
-    assert(
-        this.querySelector('.menu'),
-        'cr-dropdown-menu must have a menu child with class="menu".');
-  },
-});
diff --git a/ui/webui/resources/cr_elements/cr_dropdown_menu/demo.html b/ui/webui/resources/cr_elements/cr_dropdown_menu/demo.html
deleted file mode 100644
index c00f516e..0000000
--- a/ui/webui/resources/cr_elements/cr_dropdown_menu/demo.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<html>
-<head>
-  <link href="chrome://resources/polymer/core-menu/core-menu.html" rel="import">
-  <link href="chrome://resources/polymer/paper-item/paper-item.html" rel="import">
-  <link href="cr_dropdown_menu.html" rel="import">
-</head>
-<body unresolved>
-  <cr-dropdown-menu>
-    <core-menu class="menu">
-      <paper-item>Chrome</paper-item>
-      <paper-item>IE</paper-item>
-      <paper-item>Firefox</paper-item>
-    </core-menu>
-  </cr-dropdown-menu>
-  <h2>Disabled:</h2>
-  <cr-dropdown-menu disabled>
-    <core-menu class="menu">
-      <paper-item>Chrome</paper-item>
-      <paper-item>IE</paper-item>
-      <paper-item>Firefox</paper-item>
-    </core-menu>
-  </cr-dropdown-menu>
-</body>
-</html>
diff --git a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
index 798a6f73..26b36702 100644
--- a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
+++ b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
@@ -3,6 +3,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
 
 <dom-module id="cr-expand-button">
+  <link rel="import" type="css" href="chrome://resources/cr_elements/shared.css">
   <link rel="import" type="css" href="cr_expand_button.css">
   <template>
     <content></content>
diff --git a/ui/webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.css b/ui/webui/resources/cr_elements/shared.css
similarity index 78%
rename from ui/webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.css
rename to ui/webui/resources/cr_elements/shared.css
index f867d044..52a48e4 100644
--- a/ui/webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.css
+++ b/ui/webui/resources/cr_elements/shared.css
@@ -2,10 +2,6 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
-:host {
-  display: inline-flex;
-}
-
 :host([disabled]) {
-  opacity: .33;
+  pointer-events: none;
 }
diff --git a/ui/webui/resources/cr_elements_resources.grdp b/ui/webui/resources/cr_elements_resources.grdp
index 25c1a6f..74434b8c 100644
--- a/ui/webui/resources/cr_elements_resources.grdp
+++ b/ui/webui/resources/cr_elements_resources.grdp
@@ -126,4 +126,7 @@
   <structure name="IDR_CR_ELEMENTS_CR_SEARCH_FIELD_JS"
              file="../../webui/resources/cr_elements/cr_search_field/cr_search_field.js"
              type="chrome_html" />
+  <structure name="IDR_CR_ELEMENTS_SHARED_CSS"
+             file="../../webui/resources/cr_elements/shared.css"
+             type="chrome_html" />
 </grit-part>