diff --git a/DEPS b/DEPS
index 54249c5..1f7e9024 100644
--- a/DEPS
+++ b/DEPS
@@ -36,7 +36,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'c90bc40fdd7f0e8908df81766891e5c62fe77932',
+  'skia_revision': 'f119796f95f336d5b29f06f369b15b48a6a0df45',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
diff --git a/android_webview/tools/cts_config/expected_failure_on_bot.json b/android_webview/tools/cts_config/expected_failure_on_bot.json
index 45a8625..1969d47 100644
--- a/android_webview/tools/cts_config/expected_failure_on_bot.json
+++ b/android_webview/tools/cts_config/expected_failure_on_bot.json
@@ -3,10 +3,6 @@
     {
       "name": "testPageScroll",
       "_bug_id": "crbug.com/534643"
-    },
-    {
-      "name": "testFindNext",
-      "_bug_id": "crbug.com/618089"
     }
   ]
 }
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py
index f283c5b..0a01525 100644
--- a/build/android/pylib/gtest/gtest_test_instance.py
+++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -90,8 +90,6 @@
 _RE_TEST_STATUS = re.compile(
     r'\[ +((?:RUN)|(?:FAILED)|(?:OK)|(?:CRASHED)) +\]'
     r' ?([^ ]+)?(?: \((\d+) ms\))?$')
-_RE_TEST_RUN_STATUS = re.compile(
-    r'\[ +(PASSED|RUNNER_FAILED|CRASHED) \] ?[^ ]+')
 # Crash detection constants.
 _RE_TEST_ERROR = re.compile(r'FAILURES!!! Tests run: \d+,'
                                     r' Failures: \d+, Errors: 1')
@@ -139,6 +137,8 @@
   Returns:
     A list of base_test_result.BaseTestResults.
   """
+  duration = 0
+  fallback_result_type = None
   log = []
   result_type = None
   results = []
@@ -147,8 +147,9 @@
   def handle_possibly_unknown_test():
     if test_name is not None:
       results.append(base_test_result.BaseTestResult(
-          test_name, base_test_result.ResultType.UNKNOWN, 0,
-          log=('\n'.join(log) if log else '')))
+          test_name,
+          fallback_result_type or base_test_result.ResultType.UNKNOWN,
+          duration, log=('\n'.join(log) if log else '')))
 
   for l in output:
     logging.info(l)
@@ -156,13 +157,16 @@
     if matcher:
       if matcher.group(1) == 'RUN':
         handle_possibly_unknown_test()
+        duration = 0
+        fallback_result_type = None
         log = []
+        result_type = None
       elif matcher.group(1) == 'OK':
         result_type = base_test_result.ResultType.PASS
       elif matcher.group(1) == 'FAILED':
         result_type = base_test_result.ResultType.FAIL
       elif matcher.group(1) == 'CRASHED':
-        result_type = base_test_result.ResultType.CRASH
+        fallback_result_type = base_test_result.ResultType.CRASH
       # Be aware that test name and status might not appear on same line.
       test_name = matcher.group(2) if matcher.group(2) else test_name
       duration = int(matcher.group(3)) if matcher.group(3) else 0
@@ -182,8 +186,6 @@
       results.append(base_test_result.BaseTestResult(
           test_name, result_type, duration,
           log=('\n'.join(log) if log else '')))
-      log = None
-      result_type = None
       test_name = None
 
   handle_possibly_unknown_test()
diff --git a/build/android/pylib/gtest/gtest_test_instance_test.py b/build/android/pylib/gtest/gtest_test_instance_test.py
index 910ac40..02e29bb 100755
--- a/build/android/pylib/gtest/gtest_test_instance_test.py
+++ b/build/android/pylib/gtest/gtest_test_instance_test.py
@@ -152,6 +152,19 @@
     self.assertEquals(1, actual[1].GetDuration())
     self.assertEquals(base_test_result.ResultType.PASS, actual[1].GetType())
 
+  def testParseGTestOutput_deathTestCrashOk(self):
+    raw_output = [
+      '[ RUN      ] FooTest.Bar',
+      '[ CRASHED      ]',
+      '[       OK ] FooTest.Bar (1 ms)',
+    ]
+    actual = gtest_test_instance.ParseGTestOutput(raw_output)
+    self.assertEquals(1, len(actual))
+
+    self.assertEquals('FooTest.Bar', actual[0].GetName())
+    self.assertEquals(1, actual[0].GetDuration())
+    self.assertEquals(base_test_result.ResultType.PASS, actual[0].GetType())
+
 
 if __name__ == '__main__':
   unittest.main(verbosity=2)
diff --git a/build/config/mac/gen_plist.py b/build/config/mac/gen_plist.py
index e3d4f4af..00041795 100644
--- a/build/config/mac/gen_plist.py
+++ b/build/config/mac/gen_plist.py
@@ -18,7 +18,7 @@
 # while IDENT_RE matches all characters that are not valid in an "identifier"
 # value (used when applying the modifier).
 SUBST_RE = re.compile(r'\$\{(?P<id>[^}]*?)(?P<modifier>:[^}]*)?\}')
-IDENT_RE = re.compile(r'[/\s]')
+IDENT_RE = re.compile(r'[_/\s]')
 
 
 class ArgumentParser(argparse.ArgumentParser):
@@ -73,13 +73,13 @@
       return None
     # Some values need to be identifier and thus the variables references may
     # contains :modifier attributes to indicate how they should be converted
-    # to identifiers ("identifier" replaces all invalid characters by '-' and
-    # "rfc1034identifier" replaces them by "_" to make valid URI too).
+    # to identifiers ("identifier" replaces all invalid characters by '_' and
+    # "rfc1034identifier" replaces them by "-" to make valid URI too).
     modifier = match.group('modifier')
-    if modifier == 'identifier':
-      interpolated = IDENT_RE.sub('-', substitutions[variable])
-    elif modifier == 'rfc1034identifier':
+    if modifier == ':identifier':
       interpolated = IDENT_RE.sub('_', substitutions[variable])
+    elif modifier == ':rfc1034identifier':
+      interpolated = IDENT_RE.sub('-', substitutions[variable])
     else:
       interpolated = substitutions[variable]
     result = result[:match.start()] + interpolated + result[match.end():]
diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py
index d1aa1aac..35b913b 100755
--- a/build/linux/sysroot_scripts/install-sysroot.py
+++ b/build/linux/sysroot_scripts/install-sysroot.py
@@ -3,18 +3,19 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-"""Install Debian Wheezy sysroots for building chromium.
+"""Install Debian sysroots for building chromium.
 """
 
 # The sysroot is needed to ensure that binaries will run on Debian Wheezy,
-# the oldest supported linux distribution.  This script can be run manually but
-# is more often run as part of gclient hooks. When run from hooks this script
-# in a no-op on non-linux platforms.
+# the oldest supported linux distribution. For ARM64 linux, we have Debian
+# Jessie sysroot as Jessie is the first version with ARM64 support. This script
+# can be run manually but is more often run as part of gclient hooks. When run
+# from hooks this script is a no-op on non-linux platforms.
 
 # The sysroot image could be constructed from scratch based on the current
-# state or Debian Wheezy but for consistency we currently use a pre-built root
-# image. The image will normally need to be rebuilt every time chrome's build
-# dependencies are changed.
+# state or Debian Wheezy/Jessie but for consistency we currently use a
+# pre-built root image. The image will normally need to be rebuilt every time
+# chrome's build dependencies are changed.
 
 import hashlib
 import platform
@@ -164,6 +165,7 @@
   # TODO(thestig) Consider putting this else where to avoid having to recreate
   # it on every build.
   linux_dir = os.path.dirname(SCRIPT_DIR)
+  debian_release = 'Wheezy'
   if target_arch == 'amd64':
     sysroot = os.path.join(linux_dir, SYSROOT_DIR_AMD64)
     tarball_filename = TARBALL_AMD64
@@ -175,6 +177,7 @@
     tarball_sha1sum = TARBALL_ARM_SHA1SUM
     revision = REVISION_ARM
   elif target_arch == 'arm64':
+    debian_release = 'Jessie'
     sysroot = os.path.join(linux_dir, SYSROOT_DIR_ARM64)
     tarball_filename = TARBALL_ARM64
     tarball_sha1sum = TARBALL_ARM64_SHA1SUM
@@ -198,11 +201,12 @@
   if os.path.exists(stamp):
     with open(stamp) as s:
       if s.read() == url:
-        print 'Debian Wheezy %s root image already up to date: %s' % \
-            (target_arch, sysroot)
+        print 'Debian %s %s root image already up to date: %s' % \
+            (debian_release, target_arch, sysroot)
         return
 
-  print 'Installing Debian Wheezy %s root image: %s' % (target_arch, sysroot)
+  print 'Installing Debian %s %s root image: %s' % \
+      (debian_release, target_arch, sysroot)
   if os.path.isdir(sysroot):
     shutil.rmtree(sysroot)
   os.mkdir(sysroot)
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc
index d175058..92abb20a 100644
--- a/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -436,8 +436,8 @@
     filters.Append(FilterOperation::CreateBlurFilter(5.0f));
     filter->SetBackgroundFilters(filters);
 
-#if defined(OS_WIN)
-    // Windows has 3.065% pixels off by at most 2: crbug.com/225027
+    // Allow some fuzziness so that this doesn't fail when Skia makes minor
+    // changes to blur or rectangle rendering.
     float percentage_pixels_large_error = 3.1f;
     float percentage_pixels_small_error = 0.0f;
     float average_error_allowed_in_bad_pixels = 2.f;
@@ -448,7 +448,6 @@
         percentage_pixels_large_error, percentage_pixels_small_error,
         average_error_allowed_in_bad_pixels, large_error_allowed,
         small_error_allowed));
-#endif
 
     RunPixelTest(test_type, background, image_name);
   }
diff --git a/chrome/android/java/res/layout/autofill_editor_base_buttons.xml b/chrome/android/java/res/layout/autofill_editor_base_buttons.xml
index fe127a8..32670cb 100644
--- a/chrome/android/java/res/layout/autofill_editor_base_buttons.xml
+++ b/chrome/android/java/res/layout/autofill_editor_base_buttons.xml
@@ -9,19 +9,18 @@
 
     <Space style="@style/ButtonBarTopSpacerLight" />
 
-    <!-- CANCEL and SAVE buttons.
-         paddingEnd is already handled by the ScrollView parent.     
-    -->
+    <!-- CANCEL and DONE buttons. -->
     <org.chromium.chrome.browser.widget.DualControlLayout
         android:id="@+id/button_bar"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingStart="@dimen/payments_section_large_spacing"
+        android:paddingStart="@dimen/pref_autofill_field_horizontal_padding"
+        android:paddingEnd="@dimen/pref_autofill_field_horizontal_padding"
         android:paddingTop="@dimen/payments_section_large_spacing"
         android:paddingBottom="@dimen/payments_section_large_spacing"
         android:background="@android:color/white"
         app:stackedMargin="@dimen/infobar_margin_between_stacked_buttons"
-        app:primaryButtonText="@string/save"
+        app:primaryButtonText="@string/done"
         app:secondaryButtonText="@string/cancel" />
 
 </merge>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/new_tab_page_layout.xml b/chrome/android/java/res/layout/new_tab_page_layout.xml
index b8dfd5ae..89d1f21 100644
--- a/chrome/android/java/res/layout/new_tab_page_layout.xml
+++ b/chrome/android/java/res/layout/new_tab_page_layout.xml
@@ -14,9 +14,9 @@
     android:paddingTop="@dimen/toolbar_height_no_shadow"
     android:visibility="gone" >
 
-    <!-- Spacer. Note: this must have layout_weight="1" and the other spacers must have
-         layout_weight="0". The NewTabPageLayout will redistribute the extra space between
-         them. -->
+    <!-- Top spacer. Note: the top spacer must have layout_weight="1" and the middle and bottom
+         spacers must have layout_weight="0". The NewTabPageLayout will redistribute the extra space
+         between them. -->
     <View
         android:id="@+id/ntp_top_spacer"
         android:layout_width="0dp"
@@ -70,7 +70,7 @@
             android:src="@drawable/btn_mic" />
     </LinearLayout>
 
-    <!-- Spacer -->
+    <!-- Middle spacer -->
     <View
         android:id="@+id/ntp_middle_spacer"
         android:layout_width="0dp"
@@ -99,7 +99,7 @@
         android:inflatedId="@+id/most_visited_placeholder"
         android:layout="@layout/most_visited_placeholder" />
 
-    <!-- Spacer -->
+    <!-- Bottom spacer -->
     <View
         android:id="@+id/ntp_bottom_spacer"
         android:layout_width="0dp"
@@ -107,6 +107,7 @@
         android:layout_weight="0"
         android:visibility="invisible" />
 
+    <!--  Logo spacer -->
     <View
         android:id="@+id/no_search_logo_spacer"
         android:layout_width="match_parent"
@@ -114,6 +115,7 @@
         android:layout_weight="1"
         android:visibility="gone" />
 
+    <!--  Scroll spacer -->
     <View
         android:id="@+id/ntp_scroll_spacer"
         android:layout_width="match_parent"
diff --git a/chrome/android/java/res/layout/payment_request_editor.xml b/chrome/android/java/res/layout/payment_request_editor.xml
index 419a37b..2c1ae15 100644
--- a/chrome/android/java/res/layout/payment_request_editor.xml
+++ b/chrome/android/java/res/layout/payment_request_editor.xml
@@ -4,48 +4,48 @@
      found in the LICENSE file. -->
 
 <!-- PaymentRequestUI editor dialog. -->
-<LinearLayout
+<RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
-    android:orientation="vertical" >
+    xmlns:chrome="http://schemas.android.com/apk/res-auto" >
 
-    <!-- Toolbar and shadow. -->
+    <!-- Toolbar -->
     <org.chromium.chrome.browser.payments.ui.EditorDialogToolbar
         android:id="@+id/action_bar"
         android:layout_width="match_parent"
         android:layout_height="?attr/actionBarSize"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentEnd="true"
         android:background="@color/dark_action_bar_color" />
-    <org.chromium.chrome.browser.widget.FadingShadowView
-        android:id="@+id/shadow"
-        android:layout_width="match_parent"
-        android:layout_height="10dp" />
     
     <!-- All the page content in scrollable form. -->
     <org.chromium.chrome.browser.payments.ui.FadingEdgeScrollView
         android:id="@+id/scroll_view"
         android:layout_height="0dp"
         android:layout_width="match_parent"
-        android:layout_weight="1" >
+        android:layout_below="@id/action_bar"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentEnd="true" >
 
         <LinearLayout
             android:id="@+id/contents"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:paddingTop="@dimen/payments_section_large_spacing"
             android:paddingStart="@dimen/pref_autofill_content_spacing"
             android:paddingEnd="@dimen/pref_autofill_content_spacing"
             android:orientation="vertical" />
 
     </org.chromium.chrome.browser.payments.ui.FadingEdgeScrollView>
 
-    <!-- CANCEL and DONE buttons. -->
-    <org.chromium.chrome.browser.widget.DualControlLayout
-        android:id="@+id/button_bar"
+    <!-- Shadow overlaps the FadingEdgeScrollView. -->
+    <org.chromium.chrome.browser.widget.FadingShadowView
+        android:id="@+id/shadow"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:padding="@dimen/payments_section_large_spacing"
-        android:background="@android:color/white"
-        chrome:stackedMargin="@dimen/infobar_margin_between_stacked_buttons"
-        chrome:primaryButtonText="@string/done"
-        chrome:secondaryButtonText="@string/cancel" />
+        android:layout_height="10dp"
+        android:layout_below="@id/action_bar"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentEnd="true" />
 
-</LinearLayout>
+</RelativeLayout>
diff --git a/chrome/android/java/res/layout/payment_request_editor_footer.xml b/chrome/android/java/res/layout/payment_request_editor_footer.xml
index 84741e60..24ad020 100644
--- a/chrome/android/java/res/layout/payment_request_editor_footer.xml
+++ b/chrome/android/java/res/layout/payment_request_editor_footer.xml
@@ -3,12 +3,19 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<TextView
+<LinearLayout
         xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:layout_marginBottom="16dp"
-        android:textColor="@color/descriptive_text_color"
-        android:textSize="12sp"
-        android:text="@string/payments_required_field_message" />
\ No newline at end of file
+        android:orientation="vertical" >
+
+    <TextView    
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:layout_marginBottom="16dp"
+            android:textColor="@color/descriptive_text_color"
+            android:textSize="12sp"
+            android:text="@string/payments_required_field_message" />
+
+    <include layout="@layout/autofill_editor_base_buttons" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index f4d35a24..00fbc885 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -659,6 +659,7 @@
             }
             return true;
         } else if (id == R.id.info_menu_id) {
+            if (getTabModelSelector().getCurrentTab() == null) return false;
             WebsiteSettingsPopup.show(
                     this, getTabModelSelector().getCurrentTab(),
                     getToolbarManager().getContentPublisher(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
index f74873f..a4e1f4f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -61,10 +61,9 @@
         mBottomSpacerIdealHeight = Math.round(density * BOTTOM_SPACER_HEIGHT_DP);
         mTotalSpacerIdealHeight = Math.round(density * TOTAL_SPACER_HEIGHT_DP);
         mMostVisitedLayoutBleed = res.getDimensionPixelSize(R.dimen.most_visited_layout_bleed);
-
-        mPeekingCardHeight = getResources()
-                .getDimensionPixelSize(R.dimen.snippets_padding_and_peeking_card_height);
-        mTabStripHeight = getResources().getDimensionPixelSize(R.dimen.tab_strip_height);
+        mPeekingCardHeight =
+                res.getDimensionPixelSize(R.dimen.snippets_padding_and_peeking_card_height);
+        mTabStripHeight = res.getDimensionPixelSize(R.dimen.tab_strip_height);
     }
 
     @Override
@@ -102,6 +101,8 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // Remove the scroll spacer from the layout so the weighted children can be measured
+        // correctly.
         mScrollCompensationSpacer.setVisibility(View.GONE);
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
@@ -110,8 +111,11 @@
             // to see all of it. Extra spacing should be added at the bottom so the user can scroll
             // until Most Visited is at the top.
 
-            // All the spacers have height 0 since they use weights to set height.
+            // The top, middle, and bottom spacers should have a measured height of 0 at this point
+            // since they use weights to set height, and there was no extra space.
             assert mTopSpacer.getMeasuredHeight() == 0;
+            assert mMiddleSpacer.getMeasuredHeight() == 0;
+            assert mBottomSpacer.getMeasuredHeight() == 0;
 
             final int topOfMostVisited = calculateTopOfMostVisited();
             final int belowTheFoldHeight = getMeasuredHeight() - mParentViewportHeight;
@@ -124,15 +128,20 @@
                     mScrollCompensationSpacer.getLayoutParams().height -= mPeekingCardHeight;
                 }
 
+                // Include the scroll spacer in the layout and call super.onMeasure again so it is
+                // measured.
                 mScrollCompensationSpacer.setVisibility(View.INVISIBLE);
                 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
             }
         } else {
-            // This layout is smaller than it's parent viewport, redistribute the extra space.
+            // This layout is smaller than or equal to its parent viewport. Redistribute any
+            // weighted space.
             if (mCardsUiEnabled) {
-                getLayoutParams().height = Math.max(getMeasuredHeight(),
+                // Call super.onMeasure with mode EXACTLY and the target height to allow the top
+                // spacer (which has a weight of 1) to grow and take up the remaining space.
+                int targetHeight = Math.max(getMeasuredHeight(),
                         mParentViewportHeight - mPeekingCardHeight - mTabStripHeight);
-                // Call onMeasure to update mTopScaper's height.
+                heightMeasureSpec = MeasureSpec.makeMeasureSpec(targetHeight, MeasureSpec.EXACTLY);
                 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
             }
             distributeExtraSpace(mTopSpacer.getMeasuredHeight());
@@ -141,9 +150,10 @@
         // Make the search box and logo as wide as the most visited items.
         if (mMostVisitedLayout.getVisibility() != GONE) {
             final int width = mMostVisitedLayout.getMeasuredWidth() - mMostVisitedLayoutBleed;
-            setMeasure(mSearchBoxView, width + mSearchboxViewShadowWidth,
+            measureExactly(mSearchBoxView, width + mSearchboxViewShadowWidth,
                     mSearchBoxView.getMeasuredHeight());
-            setMeasure(mSearchProviderLogoView, width, mSearchProviderLogoView.getMeasuredHeight());
+            measureExactly(
+                    mSearchProviderLogoView, width, mSearchProviderLogoView.getMeasuredHeight());
         }
     }
 
@@ -197,7 +207,8 @@
     }
 
     /**
-     * Distribute extra vertical space between the three spacer views.
+     * Distribute extra vertical space between the three spacer views. Doing this here allows for
+     * more sophisticated constraints than in xml.
      * @param extraHeight The amount of extra space, in pixels.
      */
     private void distributeExtraSpace(int extraHeight) {
@@ -220,17 +231,16 @@
             bottomSpacerHeight = mBottomSpacerIdealHeight + extraHeight / 2;
         }
 
-        setMeasure(mTopSpacer, 0, topSpacerHeight);
-        setMeasure(mMiddleSpacer, 0, middleSpacerHeight);
-        setMeasure(mBottomSpacer, 0, bottomSpacerHeight);
+        measureExactly(mTopSpacer, 0, topSpacerHeight);
+        measureExactly(mMiddleSpacer, 0, middleSpacerHeight);
+        measureExactly(mBottomSpacer, 0, bottomSpacerHeight);
     }
 
-
     /**
-     * Convenience method to call |measure| on the given View with MeasureSpecs converted from the
+     * Convenience method to call measure() on the given View with MeasureSpecs converted from the
      * given dimensions (in pixels) with MeasureSpec.EXACTLY.
      */
-    private void setMeasure(View view, int widthPx, int heightPx) {
+    private static void measureExactly(View view, int widthPx, int heightPx) {
         view.measure(MeasureSpec.makeMeasureSpec(widthPx, MeasureSpec.EXACTLY),
                 MeasureSpec.makeMeasureSpec(heightPx, MeasureSpec.EXACTLY));
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorView.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorView.java
index 9b21004..710f836 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorView.java
@@ -62,7 +62,7 @@
     private final int mHalfRowMargin;
     private final List<EditorTextField> mEditorTextFields;
 
-    private ViewGroup mLayout;
+    private View mLayout;
     private EditorModel mEditorModel;
     private Button mDoneButton;
     private ViewGroup mDataView;
@@ -152,8 +152,6 @@
                 R.color.toolbar_shadow_color), FadingShadow.POSITION_TOP);
 
         // The top shadow is handled by the toolbar, so hide the one used in the field editor.
-        // TODO(dfalcantara): Make the toolbar's shadow cover the field editor instead of pushing
-        //                    it down.  Maybe use a RelativeLayout with overlapping views?
         FadingEdgeScrollView scrollView =
                 (FadingEdgeScrollView) mLayout.findViewById(R.id.scroll_view);
         scrollView.setShadowVisibility(false, true);
@@ -312,16 +310,15 @@
         setOnDismissListener(this);
         mEditorModel = editorModel;
 
-        mLayout = (LinearLayout) LayoutInflater.from(mContext).inflate(
-                R.layout.payment_request_editor, null);
+        mLayout = LayoutInflater.from(mContext).inflate(R.layout.payment_request_editor, null);
         setContentView(mLayout);
 
         mFooter = LayoutInflater.from(mContext).inflate(
                 R.layout.payment_request_editor_footer, null, false);
 
         prepareToolbar();
-        prepareButtons();
         prepareEditor();
+        prepareButtons();
         show();
 
         // Immediately focus the first invalid field to make it faster to edit.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
index c16c2cf..35bf3cd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -506,6 +506,8 @@
             // in JavaScript.
             dismissRunnable.run();
         } else {
+            mIsProcessingPayClicked = false;
+
             // Animate the bottom sheet going away.
             new DisappearingAnimator(false);
 
@@ -712,7 +714,8 @@
 
     /** @return Whether or not the dialog can be closed via the X close button. */
     private boolean isAcceptingCloseButton() {
-        return mSheetAnimator == null && mSectionAnimator == null && mIsInitialLayoutComplete;
+        return mSheetAnimator == null && mSectionAnimator == null && mIsInitialLayoutComplete
+                && !mIsProcessingPayClicked;
     }
 
     /** @return Whether or not the dialog is accepting user input. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheController.java b/chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheController.java
index 4ee943e..d7cfa9c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheController.java
@@ -105,17 +105,23 @@
     /** Receiver that will be notified when conditions become wrong for precaching. */
     private final BroadcastReceiver mDeviceStateReceiver = new BroadcastReceiver() {
         @Override
-        public void onReceive(Context context, Intent intent) {
-            Log.v(TAG, "conditions changed: precaching(%s), powered(%s), unmetered(%s)",
-                    isPrecaching(), mDeviceState.isPowerConnected(context),
-                    mDeviceState.isUnmeteredNetworkAvailable(context));
-            if (isPrecaching() && (!mDeviceState.isPowerConnected(context)
-                    || !mDeviceState.isUnmeteredNetworkAvailable(context))) {
-                recordFailureReasons(context);
-                cancelPrecaching(!mDeviceState.isPowerConnected(context)
-                        ? PrecacheUMA.Event.PRECACHE_CANCEL_NO_POWER
-                        : PrecacheUMA.Event.PRECACHE_CANCEL_NO_UNMETERED_NETWORK);
-            }
+        public void onReceive(final Context context, Intent intent) {
+            runOnInstanceThread(new Runnable() {
+                @Override
+                public void run() {
+                    Log.v(TAG, "conditions changed: precaching(%s), powered(%s), unmetered(%s)",
+                            isPrecaching(), mDeviceState.isPowerConnected(context),
+                            mDeviceState.isUnmeteredNetworkAvailable(context));
+                    if (isPrecaching()
+                            && (!mDeviceState.isPowerConnected(context)
+                                       || !mDeviceState.isUnmeteredNetworkAvailable(context))) {
+                        recordFailureReasons(context);
+                        cancelPrecaching(!mDeviceState.isPowerConnected(context)
+                                ? PrecacheUMA.Event.PRECACHE_CANCEL_NO_POWER
+                                : PrecacheUMA.Event.PRECACHE_CANCEL_NO_UNMETERED_NETWORK);
+                    }
+                }
+            });
         }
     };
 
@@ -276,12 +282,7 @@
             cancelPrecacheCompletionTask(appContext);
         }
         if (cancelRequired) {
-            sInstance.runOnInstanceThread(new Runnable() {
-                @Override
-                public void run() {
-                    sInstance.cancelPrecaching(PrecacheUMA.Event.PRECACHE_CANCEL_DISABLED_PREF);
-                }
-            });
+            sInstance.cancelPrecaching(PrecacheUMA.Event.PRECACHE_CANCEL_DISABLED_PREF);
         }
     }
 
@@ -413,13 +414,20 @@
      * Cancels the current precache session.
      * @param event the failure reason.
      */
-    private void cancelPrecaching(int event) {
-        Log.v(TAG, "canceling precache session");
-        if (setIsPrecaching(false)) {
-            mPrecacheLauncher.cancel();
-            shutdownPrecaching(true);
-        }
-        PrecacheUMA.record(event);
+    private void cancelPrecaching(final int event) {
+        // cancelPrecaching() could be called from PrecacheManager::Shutdown(), precache GCM task,
+        // etc., where it could be a different thread.
+        runOnInstanceThread(new Runnable() {
+            @Override
+            public void run() {
+                Log.v(TAG, "canceling precache session");
+                if (setIsPrecaching(false)) {
+                    mPrecacheLauncher.cancel();
+                    shutdownPrecaching(true);
+                }
+                PrecacheUMA.record(event);
+            }
+        });
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
index 174da7e4..535de6534 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -1813,7 +1813,16 @@
         mTabSwitcherButtonDrawableLight.updateForTabCount(numberOfTabs, isIncognito());
         mTabSwitcherButtonDrawable.updateForTabCount(numberOfTabs, isIncognito());
 
-        boolean useTabStackDrawableLight = isIncognito();
+        int themeColor;
+        if (getToolbarDataProvider() != null) {
+            themeColor = getToolbarDataProvider().getPrimaryColor();
+        } else {
+            themeColor = getToolbarColorForVisualState(
+                    isIncognito() ? VisualState.INCOGNITO : VisualState.NORMAL);
+        }
+
+        boolean useTabStackDrawableLight = isIncognito()
+                || ColorUtils.shouldUseLightForegroundOnBackground(themeColor);
         if (mTabSwitcherAnimationTabStackDrawable == null
                 || mIsOverlayTabStackDrawableLight != useTabStackDrawableLight) {
             mTabSwitcherAnimationTabStackDrawable =
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index f8af92a0..e1ac0da 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -159,7 +159,6 @@
 #include "content/public/common/content_descriptors.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/mojo_shell_connection.h"
 #include "content/public/common/sandbox_type.h"
 #include "content/public/common/url_utils.h"
 #include "content/public/common/web_preferences.h"
@@ -2850,8 +2849,8 @@
 #if defined(OS_CHROMEOS)
 #if defined(MOJO_SHELL_CLIENT)
   if (chrome::IsRunningInMash()) {
-    content::MojoShellConnection::GetForProcess()->AddConnectionFilter(
-        base::MakeUnique<chromeos::ChromeInterfaceFactory>());
+    content::MojoShellConnection::GetForProcess()->MergeService(
+        base::WrapUnique(new chromeos::ChromeInterfaceFactory));
   }
 #endif  // MOJO_SHELL_CLIENT
 #endif  // OS_CHROMEOS
diff --git a/chrome/browser/chromeos/arc/arc_auth_service_unittest.cc b/chrome/browser/chromeos/arc/arc_auth_service_unittest.cc
index 7aa97f3..352899f 100644
--- a/chrome/browser/chromeos/arc/arc_auth_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_auth_service_unittest.cc
@@ -74,8 +74,7 @@
     // Check initial conditions.
     EXPECT_EQ(bridge_service_.get(), ArcBridgeService::Get());
     EXPECT_FALSE(ArcBridgeService::Get()->available());
-    EXPECT_EQ(ArcBridgeService::State::STOPPED,
-              ArcBridgeService::Get()->state());
+    EXPECT_TRUE(ArcBridgeService::Get()->stopped());
 
     const AccountId account_id(
         AccountId::FromUserEmailGaiaId("user@gmail.com", "1234567890"));
@@ -178,7 +177,7 @@
 }
 
 TEST_F(ArcAuthServiceTest, BaseWorkflow) {
-  ASSERT_EQ(ArcBridgeService::State::STOPPED, bridge_service()->state());
+  ASSERT_FALSE(bridge_service()->ready());
   ASSERT_EQ(ArcAuthService::State::NOT_INITIALIZED, auth_service()->state());
   ASSERT_EQ(std::string(), auth_service()->GetAndResetAuthCode());
 
@@ -195,14 +194,14 @@
   auth_service()->SetAuthCodeAndStartArc(kTestAuthCode);
 
   ASSERT_EQ(ArcAuthService::State::ACTIVE, auth_service()->state());
-  ASSERT_EQ(ArcBridgeService::State::READY, bridge_service()->state());
+  ASSERT_TRUE(bridge_service()->ready());
   // Auth code valid only for one call.
   ASSERT_EQ(kTestAuthCode, auth_service()->GetAndResetAuthCode());
   ASSERT_EQ(std::string(), auth_service()->GetAndResetAuthCode());
 
   auth_service()->Shutdown();
   ASSERT_EQ(ArcAuthService::State::NOT_INITIALIZED, auth_service()->state());
-  ASSERT_EQ(ArcBridgeService::State::STOPPED, bridge_service()->state());
+  ASSERT_FALSE(bridge_service()->ready());
   ASSERT_EQ(std::string(), auth_service()->GetAndResetAuthCode());
 
   // Send profile and don't provide a code.
@@ -278,27 +277,27 @@
   EXPECT_EQ(ArcAuthService::State::FETCHING_CODE, auth_service()->state());
   auth_service()->SetAuthCodeAndStartArc(kTestAuthCode);
   EXPECT_EQ(ArcAuthService::State::ACTIVE, auth_service()->state());
-  EXPECT_EQ(ArcBridgeService::State::READY, bridge_service()->state());
+  EXPECT_TRUE(bridge_service()->ready());
   EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn));
   auth_service()->OnSignInComplete();
   EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn));
   EXPECT_EQ(ArcAuthService::State::ACTIVE, auth_service()->state());
-  EXPECT_EQ(ArcBridgeService::State::READY, bridge_service()->state());
+  EXPECT_TRUE(bridge_service()->ready());
 
   // Second start, no fetching code is expected.
   auth_service()->Shutdown();
   EXPECT_EQ(ArcAuthService::State::NOT_INITIALIZED, auth_service()->state());
-  EXPECT_EQ(ArcBridgeService::State::STOPPED, bridge_service()->state());
+  EXPECT_FALSE(bridge_service()->ready());
   auth_service()->OnPrimaryUserProfilePrepared(profile());
   EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn));
   EXPECT_EQ(ArcAuthService::State::ACTIVE, auth_service()->state());
-  EXPECT_EQ(ArcBridgeService::State::READY, bridge_service()->state());
+  EXPECT_TRUE(bridge_service()->ready());
 
   // Report failure.
   auth_service()->OnSignInFailed(mojom::ArcSignInFailureReason::NETWORK_ERROR);
   EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn));
   EXPECT_EQ(ArcAuthService::State::STOPPED, auth_service()->state());
-  EXPECT_EQ(ArcBridgeService::State::STOPPED, bridge_service()->state());
+  EXPECT_FALSE(bridge_service()->ready());
 
   // Correctly stop service.
   auth_service()->Shutdown();
diff --git a/chrome/browser/chromeos/chrome_interface_factory.cc b/chrome/browser/chromeos/chrome_interface_factory.cc
index 3e29eec..a4b334d 100644
--- a/chrome/browser/chromeos/chrome_interface_factory.cc
+++ b/chrome/browser/chromeos/chrome_interface_factory.cc
@@ -4,13 +4,6 @@
 
 #include "chrome/browser/chromeos/chrome_interface_factory.h"
 
-#include <memory>
-
-#include "ash/sysui/public/interfaces/wallpaper.mojom.h"
-#include "base/lazy_instance.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/app_list/app_list_presenter_service.h"
@@ -18,16 +11,7 @@
 #include "chrome/browser/ui/ash/keyboard_ui_service.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
-#include "content/public/common/mojo_shell_connection.h"
-#include "mash/public/interfaces/launchable.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/shell/public/cpp/connection.h"
-#include "ui/app_list/presenter/app_list_presenter.mojom.h"
-#include "ui/keyboard/keyboard.mojom.h"
-
-namespace chromeos {
-
-namespace {
 
 class ChromeLaunchable : public mash::mojom::Launchable {
  public:
@@ -73,92 +57,49 @@
   DISALLOW_COPY_AND_ASSIGN(ChromeLaunchable);
 };
 
-class FactoryImpl {
- public:
-  FactoryImpl() {}
-  ~FactoryImpl() {}
+namespace chromeos {
 
-  template <typename Interface>
-  static void AddFactory(
-      shell::Connection* connection,
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-    connection->AddInterface<Interface>(
-        base::Bind(&FactoryImpl::CallMainThreadFactory<Interface>),
-        task_runner);
-  }
-
- private:
-  static FactoryImpl* Get() {
-    if (!factory_.Get())
-      factory_.Get().reset(new FactoryImpl);
-    return factory_.Get().get();
-  }
-
-  template <typename Interface>
-  static void CallMainThreadFactory(mojo::InterfaceRequest<Interface> request) {
-    Get()->BindRequest(std::move(request));
-  }
-
-  void BindRequest(keyboard::mojom::KeyboardRequest request) {
-    if (!keyboard_ui_service_)
-      keyboard_ui_service_.reset(new KeyboardUIService);
-    keyboard_bindings_.AddBinding(keyboard_ui_service_.get(),
-                                  std::move(request));
-  }
-
-  void BindRequest(mash::mojom::LaunchableRequest request) {
-    if (!launchable_)
-      launchable_.reset(new ChromeLaunchable);
-    launchable_->ProcessRequest(std::move(request));
-  }
-
-  void BindRequest(ash::sysui::mojom::WallpaperManagerRequest request) {
-    if (!wallpaper_manager_)
-      wallpaper_manager_.reset(new ChromeWallpaperManager);
-    wallpaper_manager_->ProcessRequest(std::move(request));
-  }
-
-  void BindRequest(app_list::mojom::AppListPresenterRequest request) {
-    if (!app_list_presenter_service_)
-      app_list_presenter_service_.reset(new AppListPresenterService);
-    app_list_presenter_bindings_.AddBinding(app_list_presenter_service_.get(),
-                                            std::move(request));
-  }
-
-  static base::LazyInstance<std::unique_ptr<FactoryImpl>>::Leaky factory_;
-
-  std::unique_ptr<KeyboardUIService> keyboard_ui_service_;
-  mojo::BindingSet<keyboard::mojom::Keyboard> keyboard_bindings_;
-  std::unique_ptr<ChromeLaunchable> launchable_;
-  std::unique_ptr<ChromeWallpaperManager> wallpaper_manager_;
-  std::unique_ptr<AppListPresenterService> app_list_presenter_service_;
-  mojo::BindingSet<app_list::mojom::AppListPresenter>
-      app_list_presenter_bindings_;
-
-  DISALLOW_COPY_AND_ASSIGN(FactoryImpl);
-};
-
-base::LazyInstance<std::unique_ptr<FactoryImpl>>::Leaky FactoryImpl::factory_ =
-    LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
-
-ChromeInterfaceFactory::ChromeInterfaceFactory()
-    : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
-
+ChromeInterfaceFactory::ChromeInterfaceFactory() {}
 ChromeInterfaceFactory::~ChromeInterfaceFactory() {}
 
-bool ChromeInterfaceFactory::OnConnect(shell::Connection* connection,
-                                       shell::Connector* connector) {
-  FactoryImpl::AddFactory<keyboard::mojom::Keyboard>(
-      connection, main_thread_task_runner_);
-  FactoryImpl::AddFactory<mash::mojom::Launchable>(
-      connection, main_thread_task_runner_);
-  FactoryImpl::AddFactory<ash::sysui::mojom::WallpaperManager>(
-      connection, main_thread_task_runner_);
-  FactoryImpl::AddFactory<app_list::mojom::AppListPresenter>(
-      connection, main_thread_task_runner_);
+bool ChromeInterfaceFactory::OnConnect(shell::Connection* connection) {
+  connection->AddInterface<keyboard::mojom::Keyboard>(this);
+  connection->AddInterface<mash::mojom::Launchable>(this);
+  connection->AddInterface<ash::sysui::mojom::WallpaperManager>(this);
+  connection->AddInterface<app_list::mojom::AppListPresenter>(this);
   return true;
 }
 
+void ChromeInterfaceFactory::Create(
+    shell::Connection* connection,
+    mojo::InterfaceRequest<keyboard::mojom::Keyboard> request) {
+  if (!keyboard_ui_service_)
+    keyboard_ui_service_.reset(new KeyboardUIService);
+  keyboard_bindings_.AddBinding(keyboard_ui_service_.get(), std::move(request));
+}
+
+void ChromeInterfaceFactory::Create(shell::Connection* connection,
+                                    mash::mojom::LaunchableRequest request) {
+  if (!launchable_)
+    launchable_.reset(new ChromeLaunchable);
+  launchable_->ProcessRequest(std::move(request));
+}
+
+void ChromeInterfaceFactory::Create(
+    shell::Connection* connection,
+    ash::sysui::mojom::WallpaperManagerRequest request) {
+  if (!wallpaper_manager_)
+    wallpaper_manager_.reset(new ChromeWallpaperManager);
+  wallpaper_manager_->ProcessRequest(std::move(request));
+}
+
+void ChromeInterfaceFactory::Create(
+    shell::Connection* connection,
+    mojo::InterfaceRequest<app_list::mojom::AppListPresenter> request) {
+  if (!app_list_presenter_service_)
+    app_list_presenter_service_.reset(new AppListPresenterService);
+  app_list_presenter_bindings_.AddBinding(app_list_presenter_service_.get(),
+                                          std::move(request));
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/chrome_interface_factory.h b/chrome/browser/chromeos/chrome_interface_factory.h
index 3538bbc0..d8afb09f 100644
--- a/chrome/browser/chromeos/chrome_interface_factory.h
+++ b/chrome/browser/chromeos/chrome_interface_factory.h
@@ -5,25 +5,62 @@
 #ifndef CHROME_BROWSER_CHROMEOS_CHROME_INTERFACE_FACTORY_H_
 #define CHROME_BROWSER_CHROMEOS_CHROME_INTERFACE_FACTORY_H_
 
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "content/public/common/connection_filter.h"
+#include "ash/sysui/public/interfaces/wallpaper.mojom.h"
+#include "content/public/common/mojo_shell_connection.h"
+#include "mash/public/interfaces/launchable.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/shell/public/cpp/interface_factory.h"
+#include "services/shell/public/cpp/service.h"
+#include "ui/app_list/presenter/app_list_presenter.mojom.h"
+#include "ui/keyboard/keyboard.mojom.h"
+
+class AppListPresenterService;
+class ChromeLaunchable;
+class ChromeWallpaperManager;
+class KeyboardUIService;
 
 namespace chromeos {
 
 // InterfaceFactory for creating all services provided by chrome.
-class ChromeInterfaceFactory : public content::ConnectionFilter {
+class ChromeInterfaceFactory
+    : public shell::Service,
+      public shell::InterfaceFactory<keyboard::mojom::Keyboard>,
+      public shell::InterfaceFactory<mash::mojom::Launchable>,
+      public shell::InterfaceFactory<ash::sysui::mojom::WallpaperManager>,
+      public shell::InterfaceFactory<app_list::mojom::AppListPresenter> {
  public:
   ChromeInterfaceFactory();
   ~ChromeInterfaceFactory() override;
 
  private:
-  // content::ConnectionFilter:
-  bool OnConnect(shell::Connection* connection,
-                 shell::Connector* connector) override;
+  // shell::Service:
+  bool OnConnect(shell::Connection* connection) override;
 
-  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+  // shell::InterfaceFactory<keyboard::Keyboard>:
+  void Create(
+      shell::Connection* connection,
+      mojo::InterfaceRequest<keyboard::mojom::Keyboard> request) override;
+
+  // mojo::InterfaceFactory<mash::mojom::Launchable>
+  void Create(shell::Connection* connection,
+              mash::mojom::LaunchableRequest request) override;
+
+  // mojo::InterfaceFactory<ash::sysui::mojom::WallpaperManager>
+  void Create(shell::Connection* connection,
+              ash::sysui::mojom::WallpaperManagerRequest request) override;
+
+  // mojo::InterfaceFactory<app_list::AppListPresenter>:
+  void Create(shell::Connection* connection,
+              mojo::InterfaceRequest<app_list::mojom::AppListPresenter> request)
+      override;
+
+  std::unique_ptr<KeyboardUIService> keyboard_ui_service_;
+  mojo::BindingSet<keyboard::mojom::Keyboard> keyboard_bindings_;
+  std::unique_ptr<ChromeLaunchable> launchable_;
+  std::unique_ptr<ChromeWallpaperManager> wallpaper_manager_;
+  std::unique_ptr<AppListPresenterService> app_list_presenter_service_;
+  mojo::BindingSet<app_list::mojom::AppListPresenter>
+      app_list_presenter_bindings_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeInterfaceFactory);
 };
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 1725076..f4d108818 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -3950,7 +3950,7 @@
       = arc::ArcBridgeService::Get();
 
   // ARC is switched off by default.
-  EXPECT_EQ(arc::ArcBridgeService::State::STOPPED, arc_bridge_service->state());
+  EXPECT_TRUE(arc_bridge_service->stopped());
   EXPECT_FALSE(pref->GetBoolean(prefs::kArcEnabled));
 
   // Enable ARC.
@@ -3960,7 +3960,7 @@
                base::WrapUnique(new base::FundamentalValue(true)), nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_TRUE(pref->GetBoolean(prefs::kArcEnabled));
-  EXPECT_EQ(arc::ArcBridgeService::State::READY, arc_bridge_service->state());
+  EXPECT_TRUE(arc_bridge_service->ready());
 
   // Disable ARC.
   policies.Set(key::kArcEnabled, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
@@ -3968,7 +3968,7 @@
                base::WrapUnique(new base::FundamentalValue(false)), nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_FALSE(pref->GetBoolean(prefs::kArcEnabled));
-  EXPECT_EQ(arc::ArcBridgeService::State::STOPPED, arc_bridge_service->state());
+  EXPECT_TRUE(arc_bridge_service->stopped());
 
   TearDownTest();
 }
diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
index 47eca0f..f9923d4a 100644
--- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
+++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
@@ -5,12 +5,14 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test_utils.h"
@@ -18,6 +20,7 @@
 #include "content/public/test/text_input_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "ui/base/ime/composition_underline.h"
 #include "ui/base/ime/text_input_client.h"
 #include "ui/base/ime/text_input_mode.h"
 #include "ui/base/ime/text_input_type.h"
@@ -206,6 +209,32 @@
   DISALLOW_COPY_AND_ASSIGN(ViewSelectionBoundsChangedObserver);
 };
 
+// This class observes the |expected_view| for the first change in its
+// composition range information.
+class ViewCompositionRangeChangedObserver
+    : public TextInputManagerObserverBase {
+ public:
+  ViewCompositionRangeChangedObserver(
+      content::WebContents* web_contents,
+      content::RenderWidgetHostView* expected_view)
+      : TextInputManagerObserverBase(web_contents),
+        expected_view_(expected_view) {
+    tester()->SetOnImeCompositionRangeChangedCallback(
+        base::Bind(&ViewCompositionRangeChangedObserver::VerifyChange,
+                   base::Unretained(this)));
+  }
+
+ private:
+  void VerifyChange() {
+    if (expected_view_ == tester()->GetUpdatedView())
+      OnSuccess();
+  }
+
+  const content::RenderWidgetHostView* const expected_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(ViewCompositionRangeChangedObserver);
+};
+
 }  // namespace
 
 // Main class for all TextInputState and IME related tests.
@@ -484,7 +513,7 @@
 // receives the corresponding update on the change in selection bounds on the
 // browser side.
 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
-                       TrackSelectionBoundsForChildFrames) {
+                       TrackSelectionBoundsForAllFrames) {
   CreateIframePage("a(b,c(a,b),d)");
   std::vector<content::RenderFrameHost*> frames{
       GetFrame(IndexVector{}),     GetFrame(IndexVector{0}),
@@ -515,6 +544,44 @@
     send_tab_insert_text_wait_for_bounds_change(view);
 }
 
+// This test creates a page with multiple child frames and adds an <input> to
+// each frame. Then, sequentially, each <input> is focused by sending a tab key.
+// Then, after |TextInputState.type| for a view is changed to text, the test
+// sends a set composition IPC to the active widget and waits until the widget
+// updates its composition range.
+IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
+                       TrackCompositionRangeForAllFrames) {
+  // TODO(ekaramd): After IME methods are implemented for WebFrameWidgetImpl,
+  // change the page so that it contains child frames as well
+  // (crbug.com/626746).
+  CreateIframePage("a()");
+  std::vector<content::RenderFrameHost*> frames{GetFrame(IndexVector{})};
+  std::vector<content::RenderWidgetHostView*> views;
+  for (auto frame : frames)
+    views.push_back(frame->GetView());
+  for (size_t i = 0; i < frames.size(); ++i)
+    AddInputFieldToFrame(frames[i], "text", "", true);
+
+  content::WebContents* web_contents = active_contents();
+
+  auto send_tab_set_composition_wait_for_bounds_change =
+      [&web_contents](content::RenderWidgetHostView* view) {
+        ViewTextInputTypeObserver type_observer(web_contents, view,
+                                                ui::TEXT_INPUT_TYPE_TEXT);
+        SimulateKeyPress(web_contents, ui::DomKey::TAB, ui::DomCode::TAB,
+                         ui::VKEY_TAB, false, false, false, false);
+        type_observer.Wait();
+        ViewCompositionRangeChangedObserver range_observer(web_contents, view);
+        content::SetCompositionForRenderWidgetHost(
+            view->GetRenderWidgetHost(), base::ASCIIToUTF16("text"),
+            {ui::CompositionUnderline()}, gfx::Range::InvalidRange(), 0, 0);
+        range_observer.Wait();
+      };
+
+  for (auto view : views)
+    send_tab_set_composition_wait_for_bounds_change(view);
+}
+
 // TODO(ekaramad): The following tests are specifically written for Aura and are
 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus
 // (crbug.com/602723).
diff --git a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html
index ee16710f..8da11aa 100644
--- a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html
+++ b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html
@@ -102,13 +102,13 @@
 
       #pin-input {
         -webkit-text-security: disc;
+        background-color: white;
         border: 0;
         font-size: 18px;
         height: 64px;
         left: 20px;
         padding: 28px 3px 12px 3px;
         position: relative;
-        text-align: center;
         width: 180px;
       }
 
@@ -170,6 +170,7 @@
             <inner-text>$i18n{pinKeyboard7}</inner-text>
           </paper-button>
           <paper-button class="digit-button center-button" on-tap="onNumberTap_"
+                        value="8">
             <inner-text>$i18n{pinKeyboard8}</inner-text>
           </paper-button>
           <paper-button class="digit-button" on-tap="onNumberTap_" value="9">
diff --git a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
index de93c08d..f9f5873 100644
--- a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
+++ b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
@@ -48,6 +48,22 @@
     }
   },
 
+  /**
+   * Gets the container holding the password field.
+   * @type {!HTMLInputElement}
+   */
+  get inputElement() {
+    return this.$$('#pin-input');
+  },
+
+  /**
+   * Gets the submit button.
+   * @type {!HTMLElement}
+   */
+  get submitButton() {
+    return this.$$('.submit-button');
+  },
+
   /** Transfers focus to the input element. */
   focus: function() {
     this.$$('#pin-input').focus();
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html
index 607fde2..04cdcb15 100644
--- a/chrome/browser/resources/settings/device_page/display.html
+++ b/chrome/browser/resources/settings/device_page/display.html
@@ -39,6 +39,7 @@
 
      .info-text {
        color: var(--paper-grey-500);
+       margin-top: 5px;
      }
 
      .settings-box > paper-button:first-child {
@@ -82,16 +83,17 @@
       </div>
       <div class="settings-box embedded">
         <div class="start textarea">$i18n{displayOrientation}</div>
-        <paper-dropdown-menu>
+        <paper-dropdown-menu no-label-float>
           <paper-listbox class="dropdown-content"
               selected="[[selectedDisplay.rotation]]"
               attr-for-selected="value"
               on-iron-activate="onSetOrientation_">
-            <paper-item value="0">$i18n{displayOrientationStandard}
-            </paper-item>
-            <paper-item value="90">90</paper-item>
-            <paper-item value="180">180</paper-item>
-            <paper-item value="270">270</paper-item>
+            <div class="dropdown-item" value="0">
+              $i18n{displayOrientationStandard}
+            </div>
+            <div class="dropdown-item" value="90">90</div>
+            <div class="dropdown-item" value="180">180</div>
+            <div class="dropdown-item" value="270">270</div>
           </paper-listbox>
         </paper-dropdown-menu>
       </div>
diff --git a/chrome/browser/resources/settings/device_page/display_layout.html b/chrome/browser/resources/settings/device_page/display_layout.html
index acbe3dc0..fda6b74 100644
--- a/chrome/browser/resources/settings/device_page/display_layout.html
+++ b/chrome/browser/resources/settings/device_page/display_layout.html
@@ -16,6 +16,8 @@
         position: relative;
         width: 100%;
       }
+      /* Note: the size of the border / box shadow affects the style generated
+         in getDivStyle_ and getMirrorDivStyle_ */
       .display {
         align-items: center;
         background: var(--paper-grey-200);
@@ -30,6 +32,10 @@
         border: var(--google-blue-500) solid 2px;
         box-shadow: none;
       }
+      .display.mirror {
+        border: var(--google-blue-500) solid 1px;
+        box-shadow: none;
+      }
       .highlight-left {
         border-left: var(--google-blue-700) solid 1px;
       }
@@ -45,7 +51,13 @@
     </style>
     <div id="displayArea" on-iron-resize="calculateVisualScale_">
       <template is="dom-repeat" items="[[displays]]">
-        <div id="_[[item.id]]" class="display" draggable="true"
+        <div id="_mirror_[[item.id]]" class="display mirror"
+            hidden$="[[!mirroring]]"
+            style$="[[getMirrorDivStyle_(item.id, item.bounds, visualScale)]]"
+        </div>
+      </template>
+      <template is="dom-repeat" items="[[displays]]">
+        <div id="_[[item.id]]" class="display" draggable="[[dragEnabled]]"
             style$="[[getDivStyle_(item.id, item.bounds, visualScale)]]"
             selected$="[[isSelected_(item, selectedDisplay)]]"
             on-tap="onSelectDisplayTap_">
diff --git a/chrome/browser/resources/settings/device_page/display_layout.js b/chrome/browser/resources/settings/device_page/display_layout.js
index c37f9cb..eb1931f 100644
--- a/chrome/browser/resources/settings/device_page/display_layout.js
+++ b/chrome/browser/resources/settings/device_page/display_layout.js
@@ -28,12 +28,6 @@
      */
     displays: Array,
 
-    /**
-     * Whether or not mirroring is enabled.
-     * @type {boolean}
-     */
-    mirroring: false,
-
     /** @type {!chrome.system.display.DisplayUnitInfo|undefined} */
     selectedDisplay: Object,
 
@@ -48,19 +42,6 @@
   visualOffset_: {left: 0, top: 0},
 
   /** @override */
-  attached: function() {
-    // TODO(stevenjb): Remove retry once fixed:
-    // https://github.com/Polymer/polymer/issues/3629
-    var self = this;
-    var retry = 100;  // ms
-    function tryCalcVisualScale() {
-      if (!self.calculateVisualScale_())
-        setTimeout(tryCalcVisualScale, retry);
-    }
-    tryCalcVisualScale();
-  },
-
-  /** @override */
   detached: function() { this.initializeDrag(false); },
 
   /**
@@ -73,11 +54,15 @@
     this.displays = displays;
     this.layouts = layouts;
 
-    this.mirroring = displays.length > 0 && !!displays[0].mirroringSourceId;
-
     this.initializeDisplayLayout(displays, layouts);
 
-    this.calculateVisualScale_();
+    var self = this;
+    var retry = 100;  // ms
+    function tryCalcVisualScale() {
+      if (!self.calculateVisualScale_())
+        setTimeout(tryCalcVisualScale, retry);
+    }
+    tryCalcVisualScale();
 
     this.initializeDrag(
         !this.mirroring, this.$.displayArea, this.onDrag_.bind(this));
@@ -150,24 +135,39 @@
    * @param {string} id
    * @param {!chrome.system.display.Bounds} displayBounds
    * @param {number} visualScale
+   * @param {boolean=} opt_mirrored
    * @return {string} The style string for the div.
    * @private
    */
-  getDivStyle_: function(id, displayBounds, visualScale) {
+  getDivStyle_: function(id, displayBounds, visualScale, opt_mirrored) {
     // This matches the size of the box-shadow or border in CSS.
-    /** @const {number} */ var BORDER = 2;
-    var bounds = this.getCalculatedDisplayBounds(id);
+    /** @const {number} */ var BORDER = opt_mirrored ? 1 : 2;
+    /** @const {number} */ var OFFSET = opt_mirrored ? -4 : 0;
+    var bounds = this.getCalculatedDisplayBounds(id, true /* notest */);
+    if (!bounds)
+      return '';
     var height = Math.round(bounds.height * this.visualScale) - BORDER * 2;
     var width = Math.round(bounds.width * this.visualScale) - BORDER * 2;
-    var left =
+    var left = OFFSET +
         Math.round(this.visualOffset_.left + (bounds.left * this.visualScale));
-    var top =
+    var top = OFFSET +
         Math.round(this.visualOffset_.top + (bounds.top * this.visualScale));
     return `height: ${height}px; width: ${width}px;` +
         ` left: ${left}px; top: ${top}px`;
   },
 
   /**
+   * @param {string} id
+   * @param {!chrome.system.display.Bounds} displayBounds
+   * @param {number} visualScale
+   * @return {string} The style string for the mirror div.
+   * @private
+   */
+  getMirrorDivStyle_: function(id, displayBounds, visualScale) {
+    return this.getDivStyle_(id, displayBounds, visualScale, true);
+  },
+
+  /**
    * @param {!chrome.system.display.DisplayUnitInfo} display
    * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
    * @return {boolean}
diff --git a/chrome/browser/resources/settings/device_page/drag_behavior.js b/chrome/browser/resources/settings/device_page/drag_behavior.js
index 91d9c50..0d92c6d 100644
--- a/chrome/browser/resources/settings/device_page/drag_behavior.js
+++ b/chrome/browser/resources/settings/device_page/drag_behavior.js
@@ -17,15 +17,17 @@
 
 /** @polymerBehavior */
 var DragBehavior = {
+  properties: {
+    /** Whether or not drag is enabled (e.g. not mirrored). */
+    dragEnabled: Boolean,
+  },
+
   /**
    * The id of the element being dragged, or empty if not dragging.
    * @private {string}
    */
   dragId_: '',
 
-  /** @private {boolean} */
-  enabled_: false,
-
   /** @private {!HTMLDivElement|undefined} */
   container_: undefined,
 
@@ -62,62 +64,69 @@
    * @param {!function(string, ?DragPosition):void=} opt_callback
    */
   initializeDrag: function(enabled, opt_container, opt_callback) {
-    this.enabled_ = enabled;
+    this.dragEnabled = enabled;
     if (!enabled) {
-      if (this.container) {
-        this.container.removeEventListener('mousdown', this.mouseDownListener_);
-        this.mouseDownListener_ = null;
-        this.container.removeEventListener(
-            'mousemove', this.mouseMoveListener_);
-        this.mouseMoveListener_ = null;
-        this.container.removeEventListener(
-            'touchstart', this.touchStartListener_);
-        this.touchStartListener_ = null;
-        this.container.removeEventListener(
-            'touchmove', this.touchMoveListener_);
-        this.touchMoveListener_ = null;
-        this.container.removeEventListener('touchend', this.endDragListener_);
-      }
-      if (this.mouseUpListener_)
-        window.removeEventListener('mouseup', this.endDragListener_);
-      this.endDragListener_ = null;
+      this.removeListeners_();
       return;
     }
 
     if (opt_container !== undefined)
       this.container_ = opt_container;
-    var container = this.container_;
-    assert(container);
 
-    this.mouseDownListener_ = this.onMouseDown_.bind(this);
-    container.addEventListener('mousedown', this.mouseDownListener_, true);
-
-    this.mouseMoveListener_ = this.onMouseMove_.bind(this);
-    container.addEventListener('mousemove', this.mouseMoveListener_, true);
-
-    this.touchStartListener_ = this.onTouchStart_.bind(this);
-    container.addEventListener('touchstart', this.touchStartListener_, true);
-
-    this.touchMoveListener_ = this.onTouchMove_.bind(this);
-    container.addEventListener('touchmove', this.touchMoveListener_, true);
-
-    this.endDragListener_ = this.endDrag_.bind(this);
-    window.addEventListener('mouseup', this.endDragListener_, true);
-    container.addEventListener('touchend', this.endDragListener_, true);
+    this.addListeners_();
 
     if (opt_callback !== undefined)
       this.callback_ = opt_callback;
   },
 
+  /** @private */
+  addListeners_() {
+    let container = this.container_;
+    if (!container || this.mouseDownListener_)
+      return;
+    this.mouseDownListener_ = this.onMouseDown_.bind(this);
+    container.addEventListener('mousedown', this.mouseDownListener_);
+
+    this.mouseMoveListener_ = this.onMouseMove_.bind(this);
+    container.addEventListener('mousemove', this.mouseMoveListener_);
+
+    this.touchStartListener_ = this.onTouchStart_.bind(this);
+    container.addEventListener('touchstart', this.touchStartListener_);
+
+    this.touchMoveListener_ = this.onTouchMove_.bind(this);
+    container.addEventListener('touchmove', this.touchMoveListener_);
+
+    this.endDragListener_ = this.endDrag_.bind(this);
+    window.addEventListener('mouseup', this.endDragListener_);
+    container.addEventListener('touchend', this.endDragListener_);
+  },
+
+  /** @private */
+  removeListeners_() {
+    let container = this.container_;
+    if (!container || !this.mouseDownListener_)
+      return;
+    container.removeEventListener('mousedown', this.mouseDownListener_);
+    this.mouseDownListener_ = null;
+    container.removeEventListener('mousemove', this.mouseMoveListener_);
+    this.mouseMoveListener_ = null;
+    container.removeEventListener('touchstart', this.touchStartListener_);
+    this.touchStartListener_ = null;
+    container.removeEventListener('touchmove', this.touchMoveListener_);
+    this.touchMoveListener_ = null;
+    container.removeEventListener('touchend', this.endDragListener_);
+    if (this.endDragListener_)
+      window.removeEventListener('mouseup', this.endDragListener_);
+    this.endDragListener_ = null;
+  },
+
   /**
    * @param {Event} e The mouse down event.
    * @return {boolean}
    * @private
    */
   onMouseDown_: function(e) {
-    if (e.button != 0)
-      return true;
-    if (!e.target.getAttribute('draggable'))
+    if (e.button != 0 || !e.target.getAttribute('draggable'))
       return true;
     e.preventDefault();
     var target = assertInstanceof(e.target, HTMLElement);
@@ -181,6 +190,7 @@
    * @private
    */
   startDrag_: function(target, eventLocation) {
+    assert(this.dragEnabled);
     this.dragId_ = target.id;
     this.dragStartLocation_ = eventLocation;
     return false;
@@ -192,6 +202,7 @@
    * @private
    */
   endDrag_: function(e) {
+    assert(this.dragEnabled);
     if (this.dragId_ && this.callback_)
       this.callback_(this.dragId_, null);
     this.dragId_ = '';
@@ -206,6 +217,7 @@
    * @private
    */
   processDrag_: function(e, eventLocation) {
+    assert(this.dragEnabled);
     if (!this.dragId_)
       return true;
     if (this.callback_) {
diff --git a/chrome/browser/resources/settings/device_page/layout_behavior.js b/chrome/browser/resources/settings/device_page/layout_behavior.js
index 51ba51bd..33e2162 100644
--- a/chrome/browser/resources/settings/device_page/layout_behavior.js
+++ b/chrome/browser/resources/settings/device_page/layout_behavior.js
@@ -15,6 +15,12 @@
      * @type {!Array<!chrome.system.display.DisplayLayout>}
      */
     layouts: Array,
+
+    /**
+     * Whether or not mirroring is enabled.
+     * @type {boolean}
+     */
+    mirroring: false,
   },
 
   /** @private {!Map<string, chrome.system.display.Bounds>} */
@@ -49,6 +55,8 @@
     this.dragLayoutId = '';
     this.dragParentId_ = '';
 
+    this.mirroring = displays.length > 0 && !!displays[0].mirroringSourceId;
+
     this.displayBoundsMap_.clear();
     for (let display of displays)
       this.displayBoundsMap_.set(display.id, display.bounds);
@@ -182,11 +190,12 @@
 
   /**
    * @param {string} displayId
+   * @param {boolean=} opt_notest Set to true if bounds may not be set.
    * @return {!chrome.system.display.Bounds} bounds
    */
-  getCalculatedDisplayBounds: function(displayId) {
+  getCalculatedDisplayBounds: function(displayId, opt_notest) {
     var bounds = this.calculatedBoundsMap_.get(displayId);
-    assert(bounds);
+    assert(opt_notest || bounds);
     return bounds;
   },
 
@@ -308,7 +317,7 @@
   calculateBounds_: function(id, width, height) {
     var left, top;
     var layout = this.displayLayoutMap_.get(id);
-    if (!layout || !layout.parentId) {
+    if (this.mirroring || !layout || !layout.parentId) {
       left = -width / 2;
       top = -height / 2;
     } else {
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js b/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js
index 5456283..b70692a6 100644
--- a/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js
+++ b/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js
@@ -131,7 +131,7 @@
 
     /** @override */
     manageExtension: function(extensionId) {
-      window.location = 'chrome://extensions?id=' + extensionId;
+      window.open('chrome://extensions?id=' + extensionId);
     },
   };
 
diff --git a/chrome/browser/resources/settings/settings.js b/chrome/browser/resources/settings/settings.js
index 8de0323..17ef39b 100644
--- a/chrome/browser/resources/settings/settings.js
+++ b/chrome/browser/resources/settings/settings.js
@@ -2,6 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+cr.exportPath('settings');
+assert(!settings.defaultResourceLoaded,
+       'settings.js run twice. You probably have an invalid import.');
+/** Global defined when the main Settings script runs. */
+settings.defaultResourceLoaded = true;
+
 /**
  * @fileoverview
  * 'cr-settings' is the main MD-Settings element, combining the UI and models.
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index bcbc88c..fa58150 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -235,7 +235,8 @@
   DCHECK(bridge_service);
 
   bridge_service->AddObserver(this);
-  OnStateChanged(bridge_service->state());
+  if (!bridge_service->ready())
+    OnBridgeStopped();
 }
 
 ArcAppListPrefs::~ArcAppListPrefs() {
@@ -562,9 +563,8 @@
     RemoveAllApps();
 }
 
-void ArcAppListPrefs::OnStateChanged(arc::ArcBridgeService::State state) {
-  if (state != arc::ArcBridgeService::State::READY)
-    DisableAllApps();
+void ArcAppListPrefs::OnBridgeStopped() {
+  DisableAllApps();
 }
 
 void ArcAppListPrefs::OnAppInstanceReady() {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
index 0357525..173843c5 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -206,7 +206,7 @@
   ArcAppListPrefs(const base::FilePath& base_path, PrefService* prefs);
 
   // arc::ArcBridgeService::Observer:
-  void OnStateChanged(arc::ArcBridgeService::State state) override;
+  void OnBridgeStopped() override;
   void OnAppInstanceReady() override;
   void OnAppInstanceClosed() override;
 
diff --git a/chrome/browser/ui/app_list/arc/arc_app_test.cc b/chrome/browser/ui/app_list/arc/arc_app_test.cc
index 7ef0ed9..a32626c6 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_test.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_test.cc
@@ -118,8 +118,7 @@
   // Check initial conditions.
   EXPECT_EQ(bridge_service_.get(), arc::ArcBridgeService::Get());
   EXPECT_TRUE(!arc::ArcBridgeService::Get()->available());
-  EXPECT_EQ(arc::ArcBridgeService::State::STOPPED,
-            arc::ArcBridgeService::Get()->state());
+  EXPECT_FALSE(arc::ArcBridgeService::Get()->ready());
 
   // At this point we should have ArcAppListPrefs as observer of service.
   EXPECT_TRUE(bridge_service_->HasObserver(arc_app_list_pref_));
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
index ecdc856..cf5a14a7 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
@@ -6,6 +6,7 @@
 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/common/wm/window_state.h"
 #include "ash/common/wm_shell.h"
+#include "ash/display/display_manager.h"
 #include "ash/display/screen_orientation_controller_chromeos.h"
 #include "ash/shelf/shelf_delegate.h"
 #include "ash/shelf/shelf_util.h"
@@ -28,6 +29,7 @@
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/env.h"
 #include "ui/base/base_window.h"
+#include "ui/display/display.h"
 #include "ui/views/widget/widget.h"
 
 namespace {
@@ -38,8 +40,29 @@
   NON_ACTIVE,   // Fullscreen was not activated for an app.
 };
 
+arc::mojom::OrientationLock GetCurrentOrientation() {
+  if (!display::Display::HasInternalDisplay())
+    return arc::mojom::OrientationLock::NONE;
+  display::Display internal_display =
+      ash::Shell::GetInstance()->display_manager()->GetDisplayForId(
+          display::Display::InternalDisplayId());
+
+  // ChromeOS currently assumes that the internal panel is always
+  // landscape (ROTATE_0 == landscape).
+  switch (internal_display.rotation()) {
+    case display::Display::ROTATE_0:
+    case display::Display::ROTATE_180:
+      return arc::mojom::OrientationLock::LANDSCAPE;
+    case display::Display::ROTATE_90:
+    case display::Display::ROTATE_270:
+      return arc::mojom::OrientationLock::PORTRAIT;
+  }
+  return arc::mojom::OrientationLock::NONE;
+}
+
 blink::WebScreenOrientationLockType BlinkOrientationLockFromMojom(
     arc::mojom::OrientationLock orientation_lock) {
+  DCHECK_NE(arc::mojom::OrientationLock::CURRENT, orientation_lock);
   if (orientation_lock == arc::mojom::OrientationLock::PORTRAIT) {
     return blink::WebScreenOrientationLockPortrait;
   } else if (orientation_lock == arc::mojom::OrientationLock::LANDSCAPE) {
@@ -572,6 +595,13 @@
       return;
     orientation_lock = app_info->orientation_lock;
   }
+
+  if (orientation_lock == arc::mojom::OrientationLock::CURRENT) {
+    // Resolve the orientation when it first resolved.
+    orientation_lock = GetCurrentOrientation();
+    app_window->set_requested_orientation_lock(orientation_lock);
+  }
+
   shell->screen_orientation_controller()->LockOrientationForWindow(
       window, BlinkOrientationLockFromMojom(orientation_lock));
 }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
index c39afdf9..458e78b 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
@@ -3466,8 +3466,86 @@
                    "AppList, Chrome");
 }
 
-TEST_F(ChromeLauncherControllerImplTest, ArcOrientationLock) {
-  DCHECK(display::Display::HasInternalDisplay());
+namespace {
+
+class ChromeLauncherControllerOrientationTest
+    : public ChromeLauncherControllerImplTest {
+ public:
+  ChromeLauncherControllerOrientationTest() {}
+  ~ChromeLauncherControllerOrientationTest() override {}
+
+ protected:
+  void InitApps() {
+    appinfo_none_ =
+        CreateAppInfo("None", "None", "com.example.app", OrientationLock::NONE);
+    appinfo_landscape_ =
+        CreateAppInfo("Landscape", "Landscape", "com.example.app",
+                      OrientationLock::LANDSCAPE);
+    appinfo_portrait_ = CreateAppInfo("Portrait", "Portrait", "com.example.app",
+                                      OrientationLock::PORTRAIT);
+    appinfo_current_ = CreateAppInfo(
+        "LockCurrent", "current", "com.example.app", OrientationLock::CURRENT);
+
+    AddArcAppAndShortcut(appinfo_none_);
+    AddArcAppAndShortcut(appinfo_landscape_);
+    AddArcAppAndShortcut(appinfo_portrait_);
+    AddArcAppAndShortcut(appinfo_current_);
+
+    ash::ScreenOrientationController* controller =
+        ash::Shell::GetInstance()->screen_orientation_controller();
+
+    // Creating a window with NONE orientation will not lock the screen.
+    window_none_ = CreateArcWindow(window_app_id_none_);
+    NotifyOnTaskCreated(appinfo_none_, task_id_none_);
+    EXPECT_FALSE(controller->rotation_locked());
+    EXPECT_EQ(display::Display::ROTATE_0,
+              display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+
+    // Create a arc window with PORTRAIT orientation locks the screen to 90.
+    window_portrait_ = CreateArcWindow(window_app_id_portrait_);
+    NotifyOnTaskCreated(appinfo_portrait_, task_id_portrait_);
+    EXPECT_TRUE(controller->rotation_locked());
+    EXPECT_EQ(display::Display::ROTATE_90,
+              display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+
+    // Create a arc window with LANDSCAPE orientation locks the screen to 0.
+    window_landscape_ = CreateArcWindow(window_app_id_landscape_);
+    NotifyOnTaskCreated(appinfo_landscape_, task_id_landscape_);
+    EXPECT_TRUE(controller->rotation_locked());
+    EXPECT_EQ(display::Display::ROTATE_0,
+              display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+  }
+
+  int32_t task_id_none_ = 1;
+  int32_t task_id_landscape_ = 2;
+  int32_t task_id_portrait_ = 3;
+  int32_t task_id_current_ = 4;
+
+  // This needs to be kept on the instance because window's property has
+  // refeference to this.
+  std::string window_app_id_none_ = {"org.chromium.arc.1"};
+  std::string window_app_id_landscape_ = {"org.chromium.arc.2"};
+  std::string window_app_id_portrait_ = {"org.chromium.arc.3"};
+  std::string window_app_id_current_ = {"org.chromium.arc.4"};
+
+  arc::mojom::AppInfo appinfo_none_;
+  arc::mojom::AppInfo appinfo_landscape_;
+  arc::mojom::AppInfo appinfo_portrait_;
+  arc::mojom::AppInfo appinfo_current_;
+
+  views::Widget* window_none_ = nullptr;
+  views::Widget* window_landscape_ = nullptr;
+  views::Widget* window_portrait_ = nullptr;
+  views::Widget* window_current_ = nullptr;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerOrientationTest);
+};
+
+}  // namespace
+
+TEST_F(ChromeLauncherControllerOrientationTest, ArcOrientationLock) {
+  ASSERT_TRUE(display::Display::HasInternalDisplay());
 
   extension_service_->AddExtension(arc_support_host_.get());
   arc_test_.SetUp(profile());
@@ -3476,59 +3554,19 @@
 
   InitLauncherController();
   arc::ArcAuthService::SetShelfDelegateForTesting(launcher_controller_.get());
-  arc::mojom::AppInfo appinfo_none =
-      CreateAppInfo("None", "None", "com.example.app", OrientationLock::NONE);
-  arc::mojom::AppInfo appinfo_landscape = CreateAppInfo(
-      "Landscape", "Landscape", "com.example.app", OrientationLock::LANDSCAPE);
-  arc::mojom::AppInfo appinfo_portrait = CreateAppInfo(
-      "Portrait", "Portrait", "com.example.app", OrientationLock::PORTRAIT);
 
-  const std::string app_id_none = AddArcAppAndShortcut(appinfo_none);
-  const std::string app_id_landscape = AddArcAppAndShortcut(appinfo_landscape);
-  const std::string app_id_portrait = AddArcAppAndShortcut(appinfo_portrait);
-
-  int32_t task_id_none = 1;
-  int32_t task_id_landscape = 2;
-  int32_t task_id_portrait = 3;
-
-  // This needs to be kept on stack because window's property has
-  // refeference to this.
-  std::string window_app_id_none("org.chromium.arc.1");
-  std::string window_app_id_landscape("org.chromium.arc.2");
-  std::string window_app_id_portrait("org.chromium.arc.3");
-
+  InitApps();
   ash::ScreenOrientationController* controller =
       ash::Shell::GetInstance()->screen_orientation_controller();
 
-  // Creating a window with NONE orientation will not lock the screen.
-  views::Widget* window_none = CreateArcWindow(window_app_id_none);
-  NotifyOnTaskCreated(appinfo_none, task_id_none);
-  EXPECT_FALSE(controller->rotation_locked());
-  EXPECT_EQ(display::Display::ROTATE_0,
-            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
-
-  // Create a arc window with PORTRAIT orientation locks the screen to 90.
-  views::Widget* window_portrait = CreateArcWindow(window_app_id_portrait);
-  NotifyOnTaskCreated(appinfo_portrait, task_id_portrait);
-  EXPECT_TRUE(controller->rotation_locked());
-  EXPECT_EQ(display::Display::ROTATE_90,
-            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
-
-  // Create a arc window with LANDSCAPE orientation locks the screen to 0.
-  views::Widget* window_landscape = CreateArcWindow(window_app_id_landscape);
-  NotifyOnTaskCreated(appinfo_landscape, task_id_landscape);
-  EXPECT_TRUE(controller->rotation_locked());
-  EXPECT_EQ(display::Display::ROTATE_0,
-            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
-
   // Activating a window with NON orientation unlocks the screen.
-  window_none->Activate();
+  window_none_->Activate();
   EXPECT_FALSE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_0,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
 
   // Activating a window with PORTRAIT orientation locks the screen to 90.
-  window_portrait->Activate();
+  window_portrait_->Activate();
   EXPECT_TRUE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_90,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
@@ -3545,38 +3583,38 @@
   EXPECT_EQ(display::Display::ROTATE_90,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
 
-  window_portrait->Activate();
+  window_portrait_->Activate();
   EXPECT_TRUE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_90,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
 
-  window_landscape->Activate();
+  window_landscape_->Activate();
   EXPECT_TRUE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_0,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
 
   // OnTaskOrientationLockRequested can overwrite the current lock.
-  NotifyOnTaskOrientationLockRequested(task_id_landscape,
+  NotifyOnTaskOrientationLockRequested(task_id_landscape_,
                                        OrientationLock::NONE);
   EXPECT_FALSE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_0,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
 
-  NotifyOnTaskOrientationLockRequested(task_id_landscape,
+  NotifyOnTaskOrientationLockRequested(task_id_landscape_,
                                        OrientationLock::PORTRAIT);
   EXPECT_TRUE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_90,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
 
   // Non active window won't change the lock.
-  NotifyOnTaskOrientationLockRequested(task_id_none,
+  NotifyOnTaskOrientationLockRequested(task_id_none_,
                                        OrientationLock::LANDSCAPE);
   EXPECT_TRUE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_90,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
 
   // But activating it will change the locked orinetation.
-  window_none->Activate();
+  window_none_->Activate();
   EXPECT_TRUE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_0,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
@@ -3587,7 +3625,8 @@
   EXPECT_EQ(display::Display::ROTATE_0,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
 
-  NotifyOnTaskOrientationLockRequested(task_id_none, OrientationLock::PORTRAIT);
+  NotifyOnTaskOrientationLockRequested(task_id_none_,
+                                       OrientationLock::PORTRAIT);
   EXPECT_FALSE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_0,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
@@ -3598,4 +3637,71 @@
   EXPECT_TRUE(controller->rotation_locked());
   EXPECT_EQ(display::Display::ROTATE_90,
             display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+
+  // Manually unlock first.
+  NotifyOnTaskOrientationLockRequested(task_id_none_, OrientationLock::NONE);
+  EXPECT_FALSE(controller->rotation_locked());
+}
+
+TEST_F(ChromeLauncherControllerOrientationTest, CurrentWithLandscapeDisplay) {
+  ASSERT_TRUE(display::Display::HasInternalDisplay());
+
+  extension_service_->AddExtension(arc_support_host_.get());
+  arc_test_.SetUp(profile());
+  EnableArc(true);
+  EnableTabletMode(true);
+
+  InitLauncherController();
+  arc::ArcAuthService::SetShelfDelegateForTesting(launcher_controller_.get());
+
+  InitApps();
+  ash::ScreenOrientationController* controller =
+      ash::Shell::GetInstance()->screen_orientation_controller();
+
+  // Start with portrait.
+  window_portrait_->Activate();
+
+  // Create a arc window to lock the CURRENT orientation.
+  views::Widget* window_current = CreateArcWindow(window_app_id_current_);
+  NotifyOnTaskCreated(appinfo_current_, task_id_current_);
+  EXPECT_TRUE(controller->rotation_locked());
+  EXPECT_EQ(display::Display::ROTATE_90,
+            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+
+  // Re-activating changes the orientation to previously locked orientation.
+  window_landscape_->Activate();
+  EXPECT_TRUE(controller->rotation_locked());
+  EXPECT_EQ(display::Display::ROTATE_0,
+            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+  window_current->Activate();
+  EXPECT_TRUE(controller->rotation_locked());
+  EXPECT_EQ(display::Display::ROTATE_90,
+            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+
+  // Exitting and re-entering tablet mode re-locks the orientation.
+  EnableTabletMode(false);
+  EXPECT_FALSE(controller->rotation_locked());
+  EXPECT_EQ(display::Display::ROTATE_0,
+            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+
+  EnableTabletMode(true);
+  EXPECT_TRUE(window_current->IsActive());
+  EXPECT_TRUE(controller->rotation_locked());
+  EXPECT_EQ(display::Display::ROTATE_90,
+            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+
+  // Manually unlock, and lock again at landscape.
+  NotifyOnTaskOrientationLockRequested(task_id_current_, OrientationLock::NONE);
+  window_landscape_->Activate();
+  EXPECT_TRUE(controller->rotation_locked());
+  window_current->Activate();
+  EXPECT_FALSE(controller->rotation_locked());
+  EXPECT_EQ(display::Display::ROTATE_0,
+            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
+
+  NotifyOnTaskOrientationLockRequested(task_id_current_,
+                                       OrientationLock::CURRENT);
+  EXPECT_TRUE(controller->rotation_locked());
+  EXPECT_EQ(display::Display::ROTATE_0,
+            display::Screen::GetScreen()->GetPrimaryDisplay().rotation());
 }
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index cbae94c..7ea8a87 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -1565,7 +1565,7 @@
   current_profile_name->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   NonInteractiveContainer* profile_name_container =
       new NonInteractiveContainer();
-  int name_container_v_spacing = views::kRelatedControlSmallVerticalSpacing;
+  int name_container_v_spacing = views::kRelatedControlVerticalSpacing;
   if (!avatar_item.signed_in || switches::IsEnableAccountConsistency())
     name_container_v_spacing += views::kRelatedControlVerticalSpacing;
   profile_name_container->SetLayoutManager(new views::BoxLayout(
@@ -1801,15 +1801,17 @@
 
 views::View* ProfileChooserView::CreateSupervisedUserDisclaimerView() {
   views::View* view = new views::View();
+  int horizontal_margin = switches::IsMaterialDesignUserMenu() ?
+      kMaterialMenuEdgeMargin : views::kButtonHEdgeMarginNew;
   views::GridLayout* layout = CreateSingleColumnLayout(
-      view, GetFixedMenuWidth() - 2 * views::kButtonHEdgeMarginNew);
+      view, GetFixedMenuWidth() - 2 * horizontal_margin);
   if (switches::IsMaterialDesignUserMenu()) {
-    layout->SetInsets(0, kMaterialMenuEdgeMargin, kMaterialMenuEdgeMargin,
-                      kMaterialMenuEdgeMargin);
+    layout->SetInsets(0, horizontal_margin,
+                      kMaterialMenuEdgeMargin, horizontal_margin);
   } else {
     layout->SetInsets(
-        views::kRelatedControlVerticalSpacing, views::kButtonHEdgeMarginNew,
-        views::kRelatedControlVerticalSpacing, views::kButtonHEdgeMarginNew);
+        views::kRelatedControlVerticalSpacing, horizontal_margin,
+        views::kRelatedControlVerticalSpacing, horizontal_margin);
   }
 
   views::Label* disclaimer = new views::Label(
diff --git a/chrome/installer/gcapi_mac/gcapi.mm b/chrome/installer/gcapi_mac/gcapi.mm
index c95c2ab..798a539 100644
--- a/chrome/installer/gcapi_mac/gcapi.mm
+++ b/chrome/installer/gcapi_mac/gcapi.mm
@@ -58,8 +58,8 @@
   // 10.2.
   int mac_os_x_minor_version = darwin_major_version - 4;
 
-  // Chrome is known to work on 10.9 - 10.11.
-  return mac_os_x_minor_version >= 9 && mac_os_x_minor_version <= 11;
+  // Chrome is known to work on 10.9 - 10.12.
+  return mac_os_x_minor_version >= 9 && mac_os_x_minor_version <= 12;
 }
 
 // Returns the pid/gid of the logged-in user, even if getuid() claims that the
diff --git a/chrome/test/base/mash_browser_tests_main.cc b/chrome/test/base/mash_browser_tests_main.cc
index 47d736f..e23e754 100644
--- a/chrome/test/base/mash_browser_tests_main.cc
+++ b/chrome/test/base/mash_browser_tests_main.cc
@@ -10,7 +10,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/process/launch.h"
 #include "base/sys_info.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "chrome/test/base/chrome_test_launcher.h"
 #include "chrome/test/base/chrome_test_suite.h"
 #include "chrome/test/base/mojo_test_connector.h"
@@ -109,9 +108,7 @@
     MashTestLauncherDelegate* delegate) {
   std::unique_ptr<content::MojoShellConnection> connection(
       content::MojoShellConnection::Create(
-          delegate->GetMojoTestConnectorForSingleProcess()->Init(),
-          base::ThreadTaskRunnerHandle::Get()));
-  connection->Start();
+          delegate->GetMojoTestConnectorForSingleProcess()->Init()));
   ConnectToDefaultApps(connection->GetConnector());
   return connection;
 }
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index dfaf07e..ba961b80 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -67,6 +67,9 @@
 _VERSION_SPECIFIC_FILTER['HEAD'] = [
     # https://code.google.com/p/chromedriver/issues/detail?id=992
     'ChromeDownloadDirTest.testDownloadDirectoryOverridesExistingPreferences',
+    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1431
+    'ChromeDriverTest.testAutoReporting',
+    'ChromeDriverTest.testConsoleLogSources',
 ]
 
 _OS_SPECIFIC_FILTER = {}
diff --git a/chrome/utility/safe_browsing/mac/hfs.cc b/chrome/utility/safe_browsing/mac/hfs.cc
index f984636..9a27223 100644
--- a/chrome/utility/safe_browsing/mac/hfs.cc
+++ b/chrome/utility/safe_browsing/mac/hfs.cc
@@ -369,7 +369,10 @@
 
     // Read the entire extent now, to avoid excessive seeking and re-reading.
     if (!read_current_extent_) {
-      hfs_->SeekToBlock(extent->startBlock);
+      if (!hfs_->SeekToBlock(extent->startBlock)) {
+        DLOG(ERROR) << "Failed to seek to block " << extent->startBlock;
+        return false;
+      }
       current_extent_data_.resize(extent_size.ValueOrDie());
       if (!hfs_->stream()->ReadExact(&current_extent_data_[0],
                                      extent_size.ValueOrDie())) {
diff --git a/chrome/utility/safe_browsing/mac/udif.cc b/chrome/utility/safe_browsing/mac/udif.cc
index 90fde88..d3cadf8 100644
--- a/chrome/utility/safe_browsing/mac/udif.cc
+++ b/chrome/utility/safe_browsing/mac/udif.cc
@@ -181,29 +181,62 @@
 // endian, the data for both the block and the chunk.
 class UDIFBlock {
  public:
-  explicit UDIFBlock(const UDIFBlockData* block_data) : block(*block_data) {
-    ConvertBigEndian(&block);
-    for (uint32_t i = 0; i < block.chunk_count; ++i) {
-      chunks.push_back(block_data->chunks[i]);
-      ConvertBigEndian(&chunks[i]);
+  UDIFBlock() : block_() {}
+
+  bool ParseBlockData(const UDIFBlockData* block_data, uint16_t sector_size) {
+    block_ = *block_data;
+    ConvertBigEndian(&block_);
+
+    // Make sure the number of sectors doesn't overflow.
+    auto block_size = base::CheckedNumeric<size_t>(sector_count()) *
+                      sector_size;
+    if (!block_size.IsValid()) {
+      DLOG(ERROR) << "UDIF block size overflows";
+      return false;
     }
+
+    // Make sure that the chunk data isn't larger than the block reports.
+    base::CheckedNumeric<size_t> chunk_sectors(0);
+    for (uint32_t i = 0; i < block_.chunk_count; ++i) {
+      chunks_.push_back(block_data->chunks[i]);
+      UDIFBlockChunk* chunk = &chunks_[i];
+      ConvertBigEndian(chunk);
+
+      chunk_sectors += chunk->sector_count;
+      if (!chunk_sectors.IsValid() ||
+          chunk_sectors.ValueOrDie() > sector_count()) {
+        DLOG(ERROR) << "Total chunk sectors larger than reported block sectors";
+        return false;
+      }
+
+      auto chunk_end_offset =
+          base::CheckedNumeric<size_t>(chunk->compressed_offset) +
+          chunk->compressed_length;
+      if (!chunk_end_offset.IsValid() ||
+          chunk->compressed_length > block_size.ValueOrDie()) {
+        DLOG(ERROR) << "UDIF chunk data length " << i << " overflows";
+        return false;
+      }
+    }
+
+    return true;
   }
 
-  uint32_t signature() const { return block.signature; }
-  uint32_t version() const { return block.version; }
-  uint64_t start_sector() const { return block.start_sector; }
-  uint64_t sector_count() const { return block.sector_count; }
-  uint64_t chunk_count() const { return chunks.size(); }
+  uint32_t signature() const { return block_.signature; }
+  uint32_t version() const { return block_.version; }
+  uint64_t start_sector() const { return block_.start_sector; }
+  uint64_t sector_count() const { return block_.sector_count; }
+  uint64_t chunk_count() const { return chunks_.size(); }
 
   const UDIFBlockChunk* chunk(uint32_t i) const {
     if (i >= chunk_count())
       return nullptr;
-    return &chunks[i];
+    return &chunks_[i];
   }
 
  private:
-  UDIFBlockData block;
-  std::vector<UDIFBlockChunk> chunks;
+  UDIFBlockData block_;
+  std::vector<UDIFBlockChunk> chunks_;
 
   DISALLOW_COPY_AND_ASSIGN(UDIFBlock);
 };
@@ -348,7 +381,8 @@
 
 bool UDIFParser::ParseBlkx() {
   UDIFResourceFile trailer;
-  if (stream_->Seek(-sizeof(trailer), SEEK_END) == -1)
+  off_t trailer_start = stream_->Seek(-sizeof(trailer), SEEK_END);
+  if (trailer_start == -1)
     return false;
 
   if (!stream_->ReadType(&trailer)) {
@@ -367,6 +401,14 @@
     return false;
   }
 
+  auto plist_end = base::CheckedNumeric<size_t>(trailer.plist_offset) +
+                   trailer.plist_length;
+  if (!plist_end.IsValid() ||
+      plist_end.ValueOrDie() > base::checked_cast<size_t>(trailer_start)) {
+    DLOG(ERROR) << "blkx plist extends past UDIF trailer";
+    return false;
+  }
+
   std::vector<uint8_t> plist_bytes(trailer.plist_length, 0);
 
   if (stream_->Seek(trailer.plist_offset, SEEK_SET) == -1)
@@ -434,9 +476,13 @@
     }
 
     // Copy the block table out of the plist.
-    auto block_data =
-        reinterpret_cast<const UDIFBlockData*>(CFDataGetBytePtr(data));
-    std::unique_ptr<UDIFBlock> block(new UDIFBlock(block_data));
+    std::unique_ptr<UDIFBlock> block(new UDIFBlock());
+    if (!block->ParseBlockData(
+            reinterpret_cast<const UDIFBlockData*>(CFDataGetBytePtr(data)),
+            block_size_)) {
+      DLOG(ERROR) << "Failed to parse UDIF block data";
+      return false;
+    }
 
     if (block->signature() != UDIFBlockData::kSignature) {
       DLOG(ERROR) << "Skipping block " << i << " because its signature does not"
@@ -480,14 +526,6 @@
   return true;
 }
 
-bool UDIFParser::ReadBlockChunk(const UDIFBlockChunk* chunk,
-                                std::vector<uint8_t>* decompressed_data) {
-  UDIFBlockChunkReadStream chunk_read_stream(stream_, block_size_, chunk);
-  decompressed_data->resize(chunk_read_stream.length_in_bytes());
-  return chunk_read_stream.ReadExact(&(*decompressed_data)[0],
-                                     decompressed_data->size());
-}
-
 namespace {
 
 UDIFPartitionReadStream::UDIFPartitionReadStream(
diff --git a/chrome/utility/safe_browsing/mac/udif.h b/chrome/utility/safe_browsing/mac/udif.h
index 3b1a29d..023a8729 100644
--- a/chrome/utility/safe_browsing/mac/udif.h
+++ b/chrome/utility/safe_browsing/mac/udif.h
@@ -76,11 +76,6 @@
   // Parses the blkx plist trailer structure.
   bool ParseBlkx();
 
-  // Reads the data pointed to by the block |chunk|, decompressing it as
-  // necessary, into the out-buffer |decompressed_data|.
-  bool ReadBlockChunk(const UDIFBlockChunk* chunk,
-                      std::vector<uint8_t>* decompressed_data);
-
   ReadStream* const stream_;  // The stream backing the UDIF image. Weak.
   std::vector<std::string> partition_names_;  // The names of all partitions.
   ScopedVector<const UDIFBlock> blocks_;  // All blocks in the UDIF image.
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc
index 1544f84..ed543fa6 100644
--- a/chromecast/renderer/cast_content_renderer_client.cc
+++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -96,18 +96,9 @@
     blink::WebFrameWidget* web_frame_widget = render_view->GetWebFrameWidget();
     web_frame_widget->setBaseBackgroundColor(kColorBlack);
 
-    // The following settings express consistent behaviors across Cast
-    // embedders, though Android has enabled by default for mobile browsers.
-    webview->settings()->setShrinksViewportContentToFit(false);
+    // Settings for ATV (Android defaults are not what we want):
     webview->settings()->setMediaControlsOverlayPlayButtonEnabled(false);
 
-    // Scale 1 ensures window.innerHeight/Width match application resolution.
-    // PageScaleOverride is the 'user agent' value which overrides page
-    // settings (from meta viewport tag) - thus preventing inconsistency
-    // between Android and non-Android cast_shell.
-    webview->setDefaultPageScaleLimits(1.f, 1.f);
-    webview->setInitialPageScaleOverride(1.f);
-
     // Disable application cache as Chromecast doesn't support off-line
     // application running.
     webview->settings()->setOfflineWebApplicationCacheEnabled(false);
diff --git a/components/arc/arc_bridge_service.cc b/components/arc/arc_bridge_service.cc
index 179cde9..bc864faf 100644
--- a/components/arc/arc_bridge_service.cc
+++ b/components/arc/arc_bridge_service.cc
@@ -576,11 +576,9 @@
 
 void ArcBridgeService::SetState(State state) {
   DCHECK(CalledOnValidThread());
-  // DCHECK on enum classes not supported.
-  DCHECK(state_ != state);
+  DCHECK_NE(state_, state);
   state_ = state;
   VLOG(2) << "State: " << static_cast<uint32_t>(state_);
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnStateChanged(state_));
   if (state_ == State::READY)
     FOR_EACH_OBSERVER(Observer, observer_list(), OnBridgeReady());
   else if (state == State::STOPPED)
@@ -589,7 +587,7 @@
 
 void ArcBridgeService::SetAvailable(bool available) {
   DCHECK(CalledOnValidThread());
-  DCHECK(available_ != available);
+  DCHECK_NE(available_, available);
   available_ = available;
   FOR_EACH_OBSERVER(Observer, observer_list(), OnAvailableChanged(available_));
 }
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h
index 3d719694..bcd5b09 100644
--- a/components/arc/arc_bridge_service.h
+++ b/components/arc/arc_bridge_service.h
@@ -22,53 +22,17 @@
 namespace arc {
 
 class ArcBridgeBootstrap;
+class ArcBridgeTest;
 
 // The Chrome-side service that handles ARC instances and ARC bridge creation.
 // This service handles the lifetime of ARC instances and sets up the
 // communication channel (the ARC bridge) used to send and receive messages.
 class ArcBridgeService : public mojom::ArcBridgeHost {
  public:
-  // The possible states of the bridge.  In the normal flow, the state changes
-  // in the following sequence:
-  //
-  // STOPPED
-  //   PrerequisitesChanged() ->
-  // CONNECTING
-  //   OnConnectionEstablished() ->
-  // READY
-  //
-  // The ArcBridgeBootstrap state machine can be thought of being substates of
-  // ArcBridgeService's CONNECTING state.
-  //
-  // *
-  //   StopInstance() ->
-  // STOPPING
-  //   OnStopped() ->
-  // STOPPED
-  enum class State {
-    // ARC is not currently running.
-    STOPPED,
-
-    // The request to connect has been sent.
-    CONNECTING,
-
-    // The instance has started, and the bridge is fully established.
-    CONNECTED,
-
-    // The ARC instance has finished initializing and is now ready for user
-    // interaction.
-    READY,
-
-    // The ARC instance has started shutting down.
-    STOPPING,
-  };
-
   // Notifies life cycle events of ArcBridgeService.
   class Observer {
    public:
     // Called whenever the state of the bridge has changed.
-    // TODO(lchavez): Rename to OnStateChangedForTest
-    virtual void OnStateChanged(State state) {}
     virtual void OnBridgeReady() {}
     virtual void OnBridgeStopped() {}
 
@@ -283,15 +247,57 @@
   void OnWindowManagerInstanceReady(
       mojom::WindowManagerInstancePtr window_manager_ptr) override;
 
-  // Gets the current state of the bridge service.
-  State state() const { return state_; }
-
   // Gets if ARC is available in this system.
   bool available() const { return available_; }
 
+  // Gets if ARC is currently running.
+  bool ready() const { return state() == State::READY; }
+
+  // Gets if ARC is currently stopped. This is not exactly !ready() since there
+  // are transient states between ready() and stopped().
+  bool stopped() const { return state() == State::STOPPED; }
+
  protected:
+  // The possible states of the bridge.  In the normal flow, the state changes
+  // in the following sequence:
+  //
+  // STOPPED
+  //   PrerequisitesChanged() ->
+  // CONNECTING
+  //   OnConnectionEstablished() ->
+  // READY
+  //
+  // The ArcBridgeBootstrap state machine can be thought of being substates of
+  // ArcBridgeService's CONNECTING state.
+  //
+  // *
+  //   StopInstance() ->
+  // STOPPING
+  //   OnStopped() ->
+  // STOPPED
+  enum class State {
+    // ARC is not currently running.
+    STOPPED,
+
+    // The request to connect has been sent.
+    CONNECTING,
+
+    // The instance has started, and the bridge is fully established.
+    CONNECTED,
+
+    // The ARC instance has finished initializing and is now ready for user
+    // interaction.
+    READY,
+
+    // The ARC instance has started shutting down.
+    STOPPING,
+  };
+
   ArcBridgeService();
 
+  // Gets the current state of the bridge service.
+  State state() const { return state_; }
+
   // Changes the current state and notifies all observers.
   void SetState(State state);
 
diff --git a/components/arc/arc_bridge_service_unittest.cc b/components/arc/arc_bridge_service_unittest.cc
index 598e54b..52ad15fc 100644
--- a/components/arc/arc_bridge_service_unittest.cc
+++ b/components/arc/arc_bridge_service_unittest.cc
@@ -20,25 +20,23 @@
 
 namespace {
 
+class DummyObserver : public ArcBridgeService::Observer {};
+
+}  // namespace
+
 class ArcBridgeTest : public testing::Test, public ArcBridgeService::Observer {
  public:
   ArcBridgeTest() : ready_(false) {}
   ~ArcBridgeTest() override {}
 
-  void OnStateChanged(ArcBridgeService::State state) override {
-    state_ = state;
-    switch (state) {
-      case ArcBridgeService::State::READY:
-        ready_ = true;
-        break;
+  void OnBridgeReady() override {
+    state_ = ArcBridgeService::State::READY;
+    ready_ = true;
+  }
 
-      case ArcBridgeService::State::STOPPED:
-        message_loop_.PostTask(FROM_HERE, message_loop_.QuitWhenIdleClosure());
-        break;
-
-      default:
-        break;
-    }
+  void OnBridgeStopped() override {
+    state_ = ArcBridgeService::State::STOPPED;
+    message_loop_.PostTask(FROM_HERE, message_loop_.QuitWhenIdleClosure());
   }
 
   bool ready() const { return ready_; }
@@ -77,10 +75,6 @@
   DISALLOW_COPY_AND_ASSIGN(ArcBridgeTest);
 };
 
-class DummyObserver : public ArcBridgeService::Observer {};
-
-}  // namespace
-
 // Exercises the basic functionality of the ARC Bridge Service.  A message from
 // within the instance should cause the observer to be notified.
 TEST_F(ArcBridgeTest, Basic) {
diff --git a/components/arc/common/app.mojom b/components/arc/common/app.mojom
index d3d3039..1110e41b 100644
--- a/components/arc/common/app.mojom
+++ b/components/arc/common/app.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Next MinVersion: 12
+// Next MinVersion: 13
 
 module arc.mojom;
 
@@ -15,6 +15,7 @@
   NONE = 0,
   PORTRAIT = 1,
   LANDSCAPE = 2,
+  CURRENT = 3,
 };
 
 // Describes ARC app.
@@ -24,7 +25,7 @@
   string activity;
   [MinVersion=2] bool sticky;  // true if the app cannot be uninstalled
   [MinVersion=7] bool notifications_enabled;
-  [MinVersion=11] OrientationLock orientation_lock;
+  [MinVersion=12] OrientationLock orientation_lock;
 };
 
 // Describes ARC package.
@@ -107,7 +108,7 @@
   [MinVersion=9] OnInstallShortcut@11(ShortcutInfo shortcut);
 
   // Notifies that task requested orientation lock.
-  [MinVersion=11] OnTaskOrientationLockRequested@12(int32 task_id,
+  [MinVersion=12] OnTaskOrientationLockRequested@12(int32 task_id,
                                                     OrientationLock lock);
 };
 
diff --git a/components/arc/user_data/arc_user_data_service.cc b/components/arc/user_data/arc_user_data_service.cc
index f946de5..e37f8782 100644
--- a/components/arc/user_data/arc_user_data_service.cc
+++ b/components/arc/user_data/arc_user_data_service.cc
@@ -47,7 +47,7 @@
 
 void ArcUserDataService::ClearIfDisabled() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (arc_bridge_service()->state() != ArcBridgeService::State::STOPPED) {
+  if (!arc_bridge_service()->stopped()) {
     LOG(ERROR) << "ARC instance not stopped, user data can't be cleared";
     return;
   }
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp
index c90af58..5ead8eb 100644
--- a/components/autofill_strings.grdp
+++ b/components/autofill_strings.grdp
@@ -21,7 +21,7 @@
     Automatic credit card filling is disabled because this form does not use a secure connection.
   </message>
   <message name="IDS_AUTOFILL_CREDIT_CARD_SIGNIN_PROMO" desc="Promo text shown alongside credit card suggestions to get people to sign in.">
-    Sign in to Chrome to use cards you saved to your Google Account.
+    To use cards you saved to your Google Account, sign in to Chrome.
   </message>
   <if expr="_google_chrome">
     <message name="IDS_AUTOFILL_DELETE_AUTOCOMPLETE_SUGGESTION_CONFIRMATION_BODY" desc="Text in a dialog to confirm that the user wants to delete an autocomplete form history suggestion.">
diff --git a/components/devtools_discovery/devtools_discovery_manager.cc b/components/devtools_discovery/devtools_discovery_manager.cc
index 3233085a..7953b6c 100644
--- a/components/devtools_discovery/devtools_discovery_manager.cc
+++ b/components/devtools_discovery/devtools_discovery_manager.cc
@@ -67,15 +67,15 @@
     base::DictionaryValue* command_dict) {
   int id;
   std::string method;
-  std::string initial_url;
+  std::string url;
   const base::DictionaryValue* params_dict = nullptr;
   if (command_dict->GetInteger("id", &id) &&
       command_dict->GetString("method", &method) &&
-      method == "Browser.newPage" &&
+      method == "Browser.createTarget" &&
       command_dict->GetDictionary("params", &params_dict) &&
-      params_dict->GetString("initialUrl", &initial_url)) {
+      params_dict->GetString("url", &url)) {
     std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor> descriptor =
-        CreateNew(GURL(initial_url));
+        CreateNew(GURL(url));
     if (!descriptor)
       return nullptr;
     std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
diff --git a/components/precache/content/precache_manager.cc b/components/precache/content/precache_manager.cc
index 9a81fbb..2f896f3e 100644
--- a/components/precache/content/precache_manager.cc
+++ b/components/precache/content/precache_manager.cc
@@ -197,12 +197,12 @@
   if (precache_fetcher_) {
     std::unique_ptr<PrecacheUnfinishedWork> unfinished_work =
         precache_fetcher_->CancelPrecaching();
-    BrowserThread::PostTask(
-        BrowserThread::DB,
-        FROM_HERE,
-        base::Bind(&PrecacheDatabase::SaveUnfinishedWork,
-                   precache_database_->GetWeakPtr(),
-                   base::Passed(&unfinished_work)));
+    if (unfinished_work) {
+      BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+                              base::Bind(&PrecacheDatabase::SaveUnfinishedWork,
+                                         precache_database_->GetWeakPtr(),
+                                         base::Passed(&unfinished_work)));
+    }
     // Destroying the |precache_fetcher_| will cancel any fetch in progress.
     precache_fetcher_.reset();
   }
diff --git a/components/precache/core/precache_fetcher.cc b/components/precache/core/precache_fetcher.cc
index dc0d3a2..a5cf650 100644
--- a/components/precache/core/precache_fetcher.cc
+++ b/components/precache/core/precache_fetcher.cc
@@ -359,6 +359,10 @@
 }
 
 std::unique_ptr<PrecacheUnfinishedWork> PrecacheFetcher::CancelPrecaching() {
+  // This could get called multiple times, and it should be handled gracefully.
+  if (!unfinished_work_)
+    return nullptr;
+
   unfinished_work_->clear_manifest();
   unfinished_work_->clear_resource();
   for (const auto& manifest : manifest_urls_to_fetch_)
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index 729df89..3a8d0a4b 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -152,9 +152,7 @@
       std::unique_ptr<shell::Connection> connection,
       shell::mojom::ServiceRequest request)
       : root_connection_(std::move(connection)),
-        shell_connection_(MojoShellConnection::Create(
-            std::move(request),
-            BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))) {}
+        shell_connection_(MojoShellConnection::Create(std::move(request))) {}
   ~BrowserContextShellConnectionHolder() override {}
 
   MojoShellConnection* shell_connection() { return shell_connection_.get(); }
@@ -435,7 +433,6 @@
     browser_context->SetUserData(kMojoShellConnection, connection_holder);
 
     MojoShellConnection* connection = connection_holder->shell_connection();
-    connection->Start();
 
     // New embedded service factories should be added to |connection| here.
 
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 910422da..80c84a73 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -278,8 +278,8 @@
 void WaitForMojoShellInitialize() {
   // TODO(rockot): Remove this. http://crbug.com/594852.
   base::RunLoop wait_loop;
-  MojoShellConnection::GetForProcess()->SetInitializeHandler(
-      wait_loop.QuitClosure());
+  MojoShellConnection::GetForProcess()->GetShellConnection()->
+      set_initialize_handler(wait_loop.QuitClosure());
   wait_loop.Run();
 }
 #endif  // defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
diff --git a/content/browser/devtools/protocol/browser_handler.cc b/content/browser/devtools/protocol/browser_handler.cc
index 83fd95f..be31b84c 100644
--- a/content/browser/devtools/protocol/browser_handler.cc
+++ b/content/browser/devtools/protocol/browser_handler.cc
@@ -56,7 +56,7 @@
   return Response::ServerError("Not supported");
 }
 
-Response BrowserHandler::CreateTarget(const std::string& initial_url,
+Response BrowserHandler::CreateTarget(const std::string& url,
                                       const int* width,
                                       const int* height,
                                       const std::string* context_id,
diff --git a/content/browser/devtools/protocol/browser_handler.h b/content/browser/devtools/protocol/browser_handler.h
index 3cf34de7..ee14bfd 100644
--- a/content/browser/devtools/protocol/browser_handler.h
+++ b/content/browser/devtools/protocol/browser_handler.h
@@ -37,7 +37,7 @@
   Response CreateBrowserContext(std::string* out_context_id);
   Response DisposeBrowserContext(const std::string& context_id,
                                  bool* out_success);
-  Response CreateTarget(const std::string& initial_url,
+  Response CreateTarget(const std::string& url,
                         const int* width,
                         const int* height,
                         const std::string* context_id,
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index e6e8357..858070b 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -587,13 +587,13 @@
   dialog_manager.Handle();
 }
 
-IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserNewPage) {
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateTarget) {
   NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
   Attach();
   EXPECT_EQ(1u, shell()->windows().size());
   std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
-  params->SetString("initialUrl", "about:blank");
-  SendCommand("Browser.newPage", std::move(params), true);
+  params->SetString("url", "about:blank");
+  SendCommand("Browser.createTarget", std::move(params), true);
   EXPECT_EQ(2u, shell()->windows().size());
 }
 
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index bc4ba82c..f776f54 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -4685,6 +4685,94 @@
   EXPECT_EQ(0U, root->child_count());
 }
 
+// Ensure that we do not corrupt a NavigationEntry's PageState if two forward
+// navigations compete in different frames, and the main frame entry contains an
+// iframe of its own.  See https://crbug.com/623319.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+                       PageStateWithIframeAfterForwardInCompetingFrames) {
+  // Navigate to a page with an iframe.
+  GURL url_a(embedded_test_server()->GetURL(
+      "/navigation_controller/page_with_data_iframe.html"));
+  GURL data_url("data:text/html,Subframe");
+  EXPECT_TRUE(NavigateToURL(shell(), url_a));
+
+  NavigationController& controller = shell()->web_contents()->GetController();
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  EXPECT_EQ(url_a, root->current_url());
+  EXPECT_EQ(data_url, root->child_at(0)->current_url());
+
+  // Navigate the iframe to a first real page.
+  GURL frame_url_a1 = embedded_test_server()->GetURL(
+      "/navigation_controller/simple_page_1.html");
+  NavigateFrameToURL(root->child_at(0), frame_url_a1);
+
+  // Navigate the iframe to a second real page.
+  GURL frame_url_a2 = embedded_test_server()->GetURL(
+      "/navigation_controller/simple_page_2.html");
+  NavigateFrameToURL(root->child_at(0), frame_url_a2);
+  EXPECT_EQ(3, controller.GetEntryCount());
+  EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
+  EXPECT_EQ(url_a, root->current_url());
+  EXPECT_EQ(frame_url_a2, root->child_at(0)->current_url());
+
+  // Go back to the middle entry.
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+
+  // Replace the entry with a cross-site top-level page with an iframe.  By
+  // doing a replacement, the main frame pages before and after have the same
+  // item sequence number, and thus going between them only requires loads in
+  // the subframe.
+  GURL url_b(embedded_test_server()->GetURL(
+      "b.com", "/navigation_controller/page_with_data_iframe.html"));
+  std::string replace_script = "location.replace('" + url_b.spec() + "')";
+  TestNavigationObserver replace_observer(shell()->web_contents());
+  EXPECT_TRUE(ExecuteScript(shell()->web_contents(), replace_script));
+  replace_observer.Wait();
+  EXPECT_EQ(3, controller.GetEntryCount());
+  EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+  EXPECT_EQ(url_b, root->current_url());
+  EXPECT_EQ(data_url, root->child_at(0)->current_url());
+
+  // Go back to the original page.
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+  // Navigate forward twice using script.  This will race, but in either outcome
+  // we want to ensure that the subframes target entry index 1 and not 2.  In
+  // https://crbug.com/623319, the subframes targeted the wrong entry, leading
+  // to a URL spoof and renderer kill.
+  EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+                            "history.forward(); history.forward();"));
+  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+  EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+  EXPECT_EQ(url_b, root->current_url());
+  EXPECT_EQ(data_url, root->child_at(0)->current_url());
+  NavigationEntry* entry = controller.GetLastCommittedEntry();
+  EXPECT_EQ(url_b, entry->GetURL());
+  ExplodedPageState exploded_state;
+  EXPECT_TRUE(
+      DecodePageState(entry->GetPageState().ToEncodedData(), &exploded_state));
+  EXPECT_EQ(url_b, GURL(exploded_state.top.url_string.string()));
+
+  // Go back and then forward to see if the PageState loads correctly.
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  controller.GoForward();
+  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+  // We should be on url_b, and the renderer process shouldn't be killed.
+  ASSERT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+  EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+  EXPECT_EQ(url_b, shell()->web_contents()->GetVisibleURL());
+  EXPECT_EQ(url_b, root->current_url());
+  EXPECT_EQ(data_url, root->child_at(0)->current_url());
+}
+
 // Ensure that forward navigations in cloned tabs can commit if they redirect to
 // a different site than before.  This causes the navigation's item sequence
 // number to change, meaning that we can't use it for determining whether the
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 9be164e..67dfe7d 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
@@ -233,12 +233,6 @@
   NOTREACHED();
 }
 
-void RenderWidgetHostViewChildFrame::ImeCompositionRangeChanged(
-    const gfx::Range& range,
-    const std::vector<gfx::Rect>& character_bounds) {
-  // TODO(kenrb): Fix OOPIF Ime.
-}
-
 void RenderWidgetHostViewChildFrame::UpdateCursor(const WebCursor& cursor) {
   if (frame_connector_)
     frame_connector_->UpdateCursor(cursor);
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h
index eef16d0..dc9bd12 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.h
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -96,9 +96,6 @@
   void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
   void UpdateCursor(const WebCursor& cursor) override;
   void SetIsLoading(bool is_loading) override;
-  void ImeCompositionRangeChanged(
-      const gfx::Range& range,
-      const std::vector<gfx::Rect>& character_bounds) override;
   void RenderProcessGone(base::TerminationStatus status,
                          int error_code) override;
   void Destroy() override;
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index ff47de9..8c3a201 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -565,9 +565,10 @@
 
   DCHECK(!mojo_child_connection_);
   mojo_child_connection_.reset(new MojoChildConnection(
-      kGpuMojoApplicationName, "", child_token_,
-      MojoShellContext::GetConnectorForIOThread(),
-      BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+      kGpuMojoApplicationName,
+      "",
+      child_token_,
+      MojoShellContext::GetConnectorForIOThread()));
 
   gpu::GpuPreferences gpu_preferences = GetGpuPreferencesFromCommandLine();
   if (in_process_) {
@@ -938,11 +939,11 @@
 }
 
 shell::InterfaceRegistry* GpuProcessHost::GetInterfaceRegistry() {
-  return mojo_child_connection_->GetInterfaceRegistry();
+  return mojo_child_connection_->connection()->GetInterfaceRegistry();
 }
 
 shell::InterfaceProvider* GpuProcessHost::GetRemoteInterfaces() {
-  return mojo_child_connection_->GetRemoteInterfaces();
+  return mojo_child_connection_->connection()->GetRemoteInterfaces();
 }
 
 GpuProcessHost::GpuProcessKind GpuProcessHost::kind() {
diff --git a/content/browser/mojo/mojo_child_connection.cc b/content/browser/mojo/mojo_child_connection.cc
index 1fe0c2e..cb7ea985 100644
--- a/content/browser/mojo/mojo_child_connection.cc
+++ b/content/browser/mojo/mojo_child_connection.cc
@@ -7,7 +7,6 @@
 #include <stdint.h>
 #include <utility>
 
-#include "base/macros.h"
 #include "content/public/common/mojo_shell_connection.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "mojo/public/cpp/system/message_pipe.h"
@@ -17,163 +16,43 @@
 
 namespace content {
 
-namespace {
-
-void CallBinderOnTaskRunner(
-    const shell::InterfaceRegistry::Binder& binder,
-    scoped_refptr<base::SequencedTaskRunner> task_runner,
-    const mojo::String& interface_name,
-    mojo::ScopedMessagePipeHandle request_handle) {
-  task_runner->PostTask(
-      FROM_HERE,
-      base::Bind(binder, interface_name, base::Passed(&request_handle)));
-}
-
-}  // namespace
-
-class MojoChildConnection::IOThreadContext
-    : public base::RefCountedThreadSafe<IOThreadContext> {
- public:
-  IOThreadContext() {}
-
-  void Initialize(const std::string& application_name,
-                  const std::string& instance_id,
-                  shell::Connector* connector,
-                  mojo::ScopedMessagePipeHandle service_pipe,
-                  scoped_refptr<base::SequencedTaskRunner> io_task_runner,
-                  const shell::InterfaceRegistry::Binder& default_binder) {
-    DCHECK(!io_task_runner_);
-    io_task_runner_ = io_task_runner;
-    std::unique_ptr<shell::Connector> io_thread_connector;
-    if (connector)
-      io_thread_connector = connector->Clone();
-    io_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&IOThreadContext::InitializeOnIOThread, this,
-                   application_name, instance_id,
-                   base::Passed(&io_thread_connector),
-                   base::Passed(&service_pipe),
-                   base::Bind(&CallBinderOnTaskRunner, default_binder,
-                              base::ThreadTaskRunnerHandle::Get())));
-  }
-
-  void ShutDown() {
-    if (!io_task_runner_)
-      return;
-    bool posted = io_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&IOThreadContext::ShutDownOnIOThread, this));
-    DCHECK(posted);
-  }
-
-  void GetRemoteInterfaceOnIOThread(
-      const mojo::String& interface_name,
-      mojo::ScopedMessagePipeHandle request_handle) {
-    if (connection_) {
-      connection_->GetRemoteInterfaces()->GetInterface(
-          interface_name, std::move(request_handle));
-    }
-  }
-
-  void SetProcessHandle(base::ProcessHandle handle) {
-    DCHECK(io_task_runner_);
-    io_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&IOThreadContext::SetProcessHandleOnIOThread, this, handle));
-  }
-
- private:
-  friend class base::RefCountedThreadSafe<IOThreadContext>;
-
-  virtual ~IOThreadContext() {}
-
-  void InitializeOnIOThread(
-      const std::string& application_name,
-      const std::string& instance_id,
-      std::unique_ptr<shell::Connector> connector,
-      mojo::ScopedMessagePipeHandle service_pipe,
-      const shell::InterfaceRegistry::Binder& default_binder) {
-    shell::mojom::ServicePtr service;
-    service.Bind(mojo::InterfacePtrInfo<shell::mojom::Service>(
-        std::move(service_pipe), 0u));
-    shell::mojom::PIDReceiverRequest pid_receiver_request =
-        mojo::GetProxy(&pid_receiver_);
-
-    shell::Identity target(application_name, shell::mojom::kInheritUserID,
-                           instance_id);
-    shell::Connector::ConnectParams params(target);
-    params.set_client_process_connection(std::move(service),
-                                         std::move(pid_receiver_request));
-
-    // In some unit testing scenarios a null connector is passed.
-    if (!connector)
-      return;
-
-    connection_ = connector->Connect(&params);
-    connection_->GetInterfaceRegistry()->set_default_binder(default_binder);
-  }
-
-  void ShutDownOnIOThread() {
-    connection_.reset();
-    pid_receiver_.reset();
-  }
-
-  void SetProcessHandleOnIOThread(base::ProcessHandle handle) {
-    DCHECK(pid_receiver_.is_bound());
-    pid_receiver_->SetPID(base::GetProcId(handle));
-    pid_receiver_.reset();
-  }
-
-  scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
-  std::unique_ptr<shell::Connection> connection_;
-  shell::mojom::PIDReceiverPtr pid_receiver_;
-
-  DISALLOW_COPY_AND_ASSIGN(IOThreadContext);
-};
-
-MojoChildConnection::MojoChildConnection(
-    const std::string& application_name,
-    const std::string& instance_id,
-    const std::string& child_token,
-    shell::Connector* connector,
-    scoped_refptr<base::SequencedTaskRunner> io_task_runner)
-    : context_(new IOThreadContext),
-      service_token_(mojo::edk::GenerateRandomToken()),
-      interface_registry_(nullptr),
-      weak_factory_(this) {
+MojoChildConnection::MojoChildConnection(const std::string& application_name,
+                                         const std::string& instance_id,
+                                         const std::string& child_token,
+                                         shell::Connector* connector)
+    : service_token_(mojo::edk::GenerateRandomToken()) {
   mojo::ScopedMessagePipeHandle service_pipe =
       mojo::edk::CreateParentMessagePipe(service_token_, child_token);
 
-  context_ = new IOThreadContext;
-  context_->Initialize(
-      application_name, instance_id, connector, std::move(service_pipe),
-      io_task_runner,
-      base::Bind(&MojoChildConnection::GetInterface,
-                 weak_factory_.GetWeakPtr()));
-  remote_interfaces_.Forward(
-      base::Bind(&CallBinderOnTaskRunner,
-                 base::Bind(&IOThreadContext::GetRemoteInterfaceOnIOThread,
-                            context_), io_task_runner));
+  shell::mojom::ServicePtr service;
+  service.Bind(mojo::InterfacePtrInfo<shell::mojom::Service>(
+      std::move(service_pipe), 0u));
+  shell::mojom::PIDReceiverRequest pid_receiver_request =
+      GetProxy(&pid_receiver_);
 
+  shell::Identity target(application_name, shell::mojom::kInheritUserID,
+                         instance_id);
+  shell::Connector::ConnectParams params(target);
+  params.set_client_process_connection(std::move(service),
+                                       std::move(pid_receiver_request));
+
+  // In some unit testing scenarios a null connector is passed.
+  if (!connector)
+    return;
+
+  connection_ = connector->Connect(&params);
 #if defined(OS_ANDROID)
-  service_registry_android_ =
-      ServiceRegistryAndroid::Create(&interface_registry_, &remote_interfaces_);
+  service_registry_android_ = ServiceRegistryAndroid::Create(
+      connection_->GetInterfaceRegistry(), connection_->GetRemoteInterfaces());
 #endif
 }
 
-MojoChildConnection::~MojoChildConnection() {
-  context_->ShutDown();
-}
+MojoChildConnection::~MojoChildConnection() {}
 
 void MojoChildConnection::SetProcessHandle(base::ProcessHandle handle) {
-  context_->SetProcessHandle(handle);
-}
-
-void MojoChildConnection::GetInterface(
-    const mojo::String& interface_name,
-    mojo::ScopedMessagePipeHandle request_handle) {
-  static_cast<shell::mojom::InterfaceProvider*>(&interface_registry_)
-      ->GetInterface(interface_name, std::move(request_handle));
+  DCHECK(pid_receiver_.is_bound());
+  pid_receiver_->SetPID(base::GetProcId(handle));
+  pid_receiver_.reset();
 }
 
 }  // namespace content
diff --git a/content/browser/mojo/mojo_child_connection.h b/content/browser/mojo/mojo_child_connection.h
index c51f67e4..9ed83da 100644
--- a/content/browser/mojo/mojo_child_connection.h
+++ b/content/browser/mojo/mojo_child_connection.h
@@ -9,12 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
 #include "base/process/process_handle.h"
-#include "base/sequenced_task_runner.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/interfaces/connector.mojom.h"
 
 #if defined(OS_ANDROID)
@@ -40,16 +35,11 @@
   MojoChildConnection(const std::string& application_name,
                       const std::string& instance_id,
                       const std::string& child_token,
-                      shell::Connector* connector,
-                      scoped_refptr<base::SequencedTaskRunner> io_task_runner);
+                      shell::Connector* connector);
   ~MojoChildConnection();
 
-  shell::InterfaceRegistry* GetInterfaceRegistry() {
-    return &interface_registry_;
-  }
-
-  shell::InterfaceProvider* GetRemoteInterfaces() {
-    return &remote_interfaces_;
+  shell::Connection* connection() const {
+    return connection_.get();
   }
 
   // A token which must be passed to the child process via
@@ -69,24 +59,13 @@
 #endif
 
  private:
-  class IOThreadContext;
-
-  void GetInterface(const mojo::String& interface_name,
-                    mojo::ScopedMessagePipeHandle request_handle);
-
-  scoped_refptr<IOThreadContext> context_;
-
   const std::string service_token_;
-
-  shell::InterfaceRegistry interface_registry_;
-  shell::InterfaceProvider remote_interfaces_;
-
+  std::unique_ptr<shell::Connection> connection_;
+  shell::mojom::PIDReceiverPtr pid_receiver_;
 #if defined(OS_ANDROID)
   std::unique_ptr<ServiceRegistryAndroid> service_registry_android_;
 #endif
 
-  base::WeakPtrFactory<MojoChildConnection> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(MojoChildConnection);
 };
 
diff --git a/content/browser/mojo/mojo_shell_context.cc b/content/browser/mojo/mojo_shell_context.cc
index 37b9e70..24e21ca 100644
--- a/content/browser/mojo/mojo_shell_context.cc
+++ b/content/browser/mojo/mojo_shell_context.cc
@@ -49,10 +49,20 @@
 
 namespace {
 
-base::LazyInstance<std::unique_ptr<shell::Connector>>::Leaky
-    g_io_thread_connector = LAZY_INSTANCE_INITIALIZER;
+using ConnectorPtr = base::ThreadLocalPointer<shell::Connector>;
 
-void DestroyConnectorOnIOThread() { g_io_thread_connector.Get().reset(); }
+base::LazyInstance<ConnectorPtr>::Leaky io_connector_tls_ptr =
+    LAZY_INSTANCE_INITIALIZER;
+
+void SetConnectorOnIOThread(std::unique_ptr<shell::Connector> connector) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  io_connector_tls_ptr.Pointer()->Set(connector.release());
+}
+
+void DestroyConnectorOnIOThread() {
+  delete MojoShellContext::GetConnectorForIOThread();
+  io_connector_tls_ptr.Pointer()->Set(nullptr);
+}
 
 void StartUtilityProcessOnIOThread(
     mojo::InterfaceRequest<mojom::ProcessControl> request,
@@ -262,9 +272,14 @@
     request =
         service_manager_->StartEmbedderService(kBrowserMojoApplicationName);
   }
-  MojoShellConnection::SetForProcess(MojoShellConnection::Create(
-      std::move(request),
-      BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+  MojoShellConnection::SetForProcess(
+      MojoShellConnection::Create(std::move(request)));
+
+  std::unique_ptr<shell::Connector> io_connector =
+      MojoShellConnection::GetForProcess()->GetConnector()->Clone();
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&SetConnectorOnIOThread, base::Passed(&io_connector)));
 
   ContentBrowserClient::StaticMojoApplicationMap apps;
   GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps);
@@ -273,13 +288,6 @@
                                                              entry.second);
   }
 
-  // This is safe to assign directly from any thread, because MojoShellContext
-  // must be constructed before anyone can call GetConnectorForIOThread().
-  g_io_thread_connector.Get() =
-      MojoShellConnection::GetForProcess()->GetConnector()->Clone();
-
-  MojoShellConnection::GetForProcess()->Start();
-
   ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps;
   GetContentClient()
       ->browser()
@@ -332,7 +340,7 @@
 // static
 shell::Connector* MojoShellContext::GetConnectorForIOThread() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  return g_io_thread_connector.Get().get();
+  return io_connector_tls_ptr.Pointer()->Get();
 }
 
 void MojoShellContext::ConnectToApplicationOnOwnThread(
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index c4b72a3..de830f4 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -169,8 +169,6 @@
 #include "mojo/edk/embedder/embedder.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "ppapi/shared_impl/ppapi_switches.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/runner/common/switches.h"
 #include "storage/browser/fileapi/sandbox_file_system_backend.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -602,8 +600,6 @@
 #endif  // defined(OS_MACOSX)
 #endif  // USE_ATTACHMENT_BROKER
 
-  scoped_refptr<base::SequencedTaskRunner> io_task_runner =
-      BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
   shell::Connector* connector =
       BrowserContext::GetShellConnectorFor(browser_context_);
   // Some embedders may not initialize Mojo or the shell connector for a browser
@@ -616,14 +612,15 @@
     if (!MojoShellConnection::GetForProcess()) {
       shell::mojom::ServiceRequest request = mojo::GetProxy(&test_service_);
       MojoShellConnection::SetForProcess(MojoShellConnection::Create(
-          std::move(request), io_task_runner));
+          std::move(request)));
     }
     connector = MojoShellConnection::GetForProcess()->GetConnector();
   }
   mojo_child_connection_.reset(new MojoChildConnection(
       kRendererMojoApplicationName,
-      base::StringPrintf("%d_%d", id_, instance_id_++), child_token_, connector,
-      io_task_runner));
+      base::StringPrintf("%d_%d", id_, instance_id_++),
+      child_token_,
+      connector));
 }
 
 // static
@@ -763,7 +760,8 @@
     in_process_renderer_.reset(
         g_renderer_main_thread_factory(InProcessChildThreadParams(
             channel_id,
-            BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+            BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
+                ->task_runner(),
             mojo_channel_token_,
             mojo_child_connection_->service_token())));
 
@@ -1123,11 +1121,16 @@
 }
 
 shell::InterfaceRegistry* RenderProcessHostImpl::GetInterfaceRegistry() {
-  return mojo_child_connection_->GetInterfaceRegistry();
+  return GetChildConnection()->GetInterfaceRegistry();
 }
 
 shell::InterfaceProvider* RenderProcessHostImpl::GetRemoteInterfaces() {
-  return mojo_child_connection_->GetRemoteInterfaces();
+  return GetChildConnection()->GetRemoteInterfaces();
+}
+
+shell::Connection* RenderProcessHostImpl::GetChildConnection() {
+  DCHECK(mojo_child_connection_);
+  return mojo_child_connection_->connection();
 }
 
 std::unique_ptr<base::SharedPersistentMemoryAllocator>
@@ -2431,8 +2434,9 @@
     connector = MojoShellConnection::GetForProcess()->GetConnector();
   mojo_child_connection_.reset(new MojoChildConnection(
       kRendererMojoApplicationName,
-      base::StringPrintf("%d_%d", id_, instance_id_++), child_token_, connector,
-      BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+      base::StringPrintf("%d_%d", id_, instance_id_++),
+      child_token_,
+      connector));
 
   within_process_died_observer_ = true;
   NotificationService::current()->Notify(
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 5a07a6c..3c754893 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -157,6 +157,7 @@
   void NotifyTimezoneChange(const std::string& timezone) override;
   shell::InterfaceRegistry* GetInterfaceRegistry() override;
   shell::InterfaceProvider* GetRemoteInterfaces() override;
+  shell::Connection* GetChildConnection() override;
   std::unique_ptr<base::SharedPersistentMemoryAllocator> TakeMetricsAllocator()
       override;
   const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
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 7940896..94f1d0d 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -976,12 +976,6 @@
   UpdateCursorIfOverSelf();
 }
 
-void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
-    const gfx::Range& range,
-    const std::vector<gfx::Rect>& character_bounds) {
-  composition_character_bounds_ = character_bounds;
-}
-
 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
                                                  int error_code) {
   UpdateCursorIfOverSelf();
@@ -1533,9 +1527,15 @@
     uint32_t index,
     gfx::Rect* rect) const {
   DCHECK(rect);
-  if (index >= composition_character_bounds_.size())
+
+  if (!text_input_manager_ || !text_input_manager_->GetActiveWidget())
     return false;
-  *rect = ConvertRectToScreen(composition_character_bounds_[index]);
+
+  const std::vector<gfx::Rect>* composition_character_bounds =
+      text_input_manager_->GetCompositionCharacterBounds();
+  if (index >= composition_character_bounds->size())
+    return false;
+  *rect = ConvertRectToScreen(composition_character_bounds->at(index));
   return true;
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index b71e90c..6c06169 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -142,9 +142,6 @@
   void Focus() override;
   void UpdateCursor(const WebCursor& cursor) override;
   void SetIsLoading(bool is_loading) override;
-  void ImeCompositionRangeChanged(
-      const gfx::Range& range,
-      const std::vector<gfx::Rect>& character_bounds) override;
   void RenderProcessGone(base::TerminationStatus status,
                          int error_code) override;
   void Destroy() override;
@@ -586,8 +583,6 @@
   // object.
   ui::MotionEventAura pointer_state_;
 
-  // The current composition character bounds.
-  std::vector<gfx::Rect> composition_character_bounds_;
 
   // Indicates if there is onging composition text.
   bool has_composition_text_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 30defc8..47c1db5 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -4300,4 +4300,26 @@
   }
 }
 
+// This test activates child frames in a specific sequence and changes their
+// composition range. Then it verifies that the ui::TextInputClient returns the
+// correct character bound at the given indices.
+TEST_F(InputMethodStateAuraTest, GetCompositionCharacterBounds) {
+  gfx::Rect bound;
+  // Initially, there should be no bounds.
+  EXPECT_FALSE(text_input_client()->GetCompositionCharacterBounds(0, &bound));
+  for (auto index : active_view_sequence_) {
+    ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT);
+    // Simulate an IPC to set character bounds for the view.
+    views_[index]->ImeCompositionRangeChanged(gfx::Range(),
+                                              {gfx::Rect(1, 2, 3, 4 + index)});
+
+    // No bounds at index 1.
+    EXPECT_FALSE(text_input_client()->GetCompositionCharacterBounds(1, &bound));
+
+    // Valid bound at index 0.
+    EXPECT_TRUE(text_input_client()->GetCompositionCharacterBounds(0, &bound));
+    EXPECT_EQ(4 + (int)index, bound.height());
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 41724ea..ab346c0 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -424,6 +424,18 @@
 #endif
 }
 
+void RenderWidgetHostViewBase::ImeCompositionRangeChanged(
+    const gfx::Range& range,
+    const std::vector<gfx::Rect>& character_bounds) {
+// TODO(ekaramad): Use TextInputManager code paths for IME on other platforms.
+#if defined(USE_AURA)
+  if (GetTextInputManager()) {
+    GetTextInputManager()->ImeCompositionRangeChanged(this, range,
+                                                      character_bounds);
+  }
+#endif
+}
+
 TextInputManager* RenderWidgetHostViewBase::GetTextInputManager() {
   if (text_input_manager_)
     return text_input_manager_;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 756a7d8..185d11a6 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -272,6 +272,11 @@
   virtual void SelectionBoundsChanged(
       const ViewHostMsg_SelectionBounds_Params& params);
 
+  // Updates the range of the marked text in an IME composition.
+  virtual void ImeCompositionRangeChanged(
+      const gfx::Range& range,
+      const std::vector<gfx::Rect>& character_bounds);
+
   //----------------------------------------------------------------------------
   // The following static methods are implemented by each platform.
 
@@ -382,11 +387,6 @@
   virtual void LockCompositingSurface() = 0;
   virtual void UnlockCompositingSurface() = 0;
 
-  // Updates the range of the marked text in an IME composition.
-  virtual void ImeCompositionRangeChanged(
-      const gfx::Range& range,
-      const std::vector<gfx::Rect>& character_bounds) = 0;
-
   // Add and remove observers for lifetime event notifications. The order in
   // which notifications are sent to observers is undefined. Clients must be
   // sure to remove the observer before they go away.
diff --git a/content/browser/renderer_host/render_widget_host_view_mus.cc b/content/browser/renderer_host/render_widget_host_view_mus.cc
index 1befbca3..3932681 100644
--- a/content/browser/renderer_host/render_widget_host_view_mus.cc
+++ b/content/browser/renderer_host/render_widget_host_view_mus.cc
@@ -43,7 +43,7 @@
   // Connect to the renderer, pass it a WindowTreeClient interface request
   // and embed that client inside our mus window.
   mojom::RenderWidgetWindowTreeClientFactoryPtr factory;
-  host_->GetProcess()->GetRemoteInterfaces()->GetInterface(&factory);
+  host_->GetProcess()->GetChildConnection()->GetInterface(&factory);
 
   ui::mojom::WindowTreeClientPtr window_tree_client;
   factory->CreateWindowTreeClientForRenderWidget(
diff --git a/content/browser/renderer_host/text_input_manager.cc b/content/browser/renderer_host/text_input_manager.cc
index 3029d93..eed2012 100644
--- a/content/browser/renderer_host/text_input_manager.cc
+++ b/content/browser/renderer_host/text_input_manager.cc
@@ -7,6 +7,7 @@
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "content/common/view_messages.h"
+#include "ui/gfx/geometry/rect.h"
 
 namespace content {
 
@@ -45,16 +46,16 @@
     Unregister(view);
 }
 
-const TextInputState* TextInputManager::GetTextInputState() {
-  return !!active_view_ ? &text_input_state_map_[active_view_] : nullptr;
-}
-
 RenderWidgetHostImpl* TextInputManager::GetActiveWidget() const {
   return !!active_view_ ? static_cast<RenderWidgetHostImpl*>(
                               active_view_->GetRenderWidgetHost())
                         : nullptr;
 }
 
+const TextInputState* TextInputManager::GetTextInputState() {
+  return !!active_view_ ? &text_input_state_map_[active_view_] : nullptr;
+}
+
 gfx::Rect TextInputManager::GetSelectionBoundsRect() {
   if (!active_view_)
     return gfx::Rect();
@@ -64,6 +65,13 @@
       selection_region_map_[active_view_].focus);
 }
 
+const std::vector<gfx::Rect>*
+TextInputManager::GetCompositionCharacterBounds() {
+  return !!active_view_
+             ? &composition_range_info_map_[active_view_].character_bounds
+             : nullptr;
+}
+
 void TextInputManager::UpdateTextInputState(
     RenderWidgetHostViewBase* view,
     const TextInputState& text_input_state) {
@@ -148,6 +156,24 @@
 #endif
 }
 
+void TextInputManager::ImeCompositionRangeChanged(
+    RenderWidgetHostViewBase* view,
+    const gfx::Range& range,
+    const std::vector<gfx::Rect>& character_bounds) {
+  DCHECK(IsRegistered(view));
+  composition_range_info_map_[view].character_bounds.clear();
+
+  // The values for the bounds should be converted to root view's coordinates
+  // before being stored.
+  for (auto rect : character_bounds) {
+    composition_range_info_map_[view].character_bounds.emplace_back(gfx::Rect(
+        view->TransformPointToRootCoordSpace(rect.origin()), rect.size()));
+  }
+
+  FOR_EACH_OBSERVER(Observer, observer_list_,
+                    OnImeCompositionRangeChanged(this, view));
+}
+
 void TextInputManager::Register(RenderWidgetHostViewBase* view) {
   DCHECK(!IsRegistered(view));
 
@@ -200,4 +226,11 @@
 TextInputManager::SelectionRegion::SelectionRegion(
     const SelectionRegion& other) = default;
 
+TextInputManager::CompositionRangeInfo::CompositionRangeInfo() {}
+
+TextInputManager::CompositionRangeInfo::CompositionRangeInfo(
+    const CompositionRangeInfo& other) = default;
+
+TextInputManager::CompositionRangeInfo::~CompositionRangeInfo() {}
+
 }  // namespace content
\ No newline at end of file
diff --git a/content/browser/renderer_host/text_input_manager.h b/content/browser/renderer_host/text_input_manager.h
index f240a1b..bef6e81 100644
--- a/content/browser/renderer_host/text_input_manager.h
+++ b/content/browser/renderer_host/text_input_manager.h
@@ -16,7 +16,12 @@
 
 struct ViewHostMsg_SelectionBounds_Params;
 
+namespace gfx {
+class Range;
+}
+
 namespace content {
+
 class RenderWidgetHostImpl;
 class RenderWidgetHostView;
 class RenderWidgetHostViewBase;
@@ -45,31 +50,40 @@
     virtual void OnImeCancelComposition(
         TextInputManager* text_input_manager,
         RenderWidgetHostViewBase* updated_view) {}
-    // Called when the selection bounds for the |updated_view| has changed.
+    // Called when |updated_view| has changed its SelectionRegion.
     virtual void OnSelectionBoundsChanged(
         TextInputManager* text_input_manager,
         RenderWidgetHostViewBase* updated_view) {}
+    // Called when |updated_view| has changed its CompositionRangeInfo.
+    virtual void OnImeCompositionRangeChanged(
+        TextInputManager* text_input_manager,
+        RenderWidgetHostViewBase* updated_view) {}
   };
 
   TextInputManager();
   ~TextInputManager();
 
-  // ---------------------------------------------------------------------------
-  // The following methods can be used to obtain information about IME-related
-  // state for the active RenderWidget.
-
   // Returns the currently active widget, i.e., the RWH which is associated with
   // |active_view_|.
   RenderWidgetHostImpl* GetActiveWidget() const;
 
-  // Returns the TextInputState corresponding to |active_view_|.
-  // Users of this method should not hold on to the pointer as it might become
-  // dangling if the TextInputManager or |active_view_| might go away.
+  // ---------------------------------------------------------------------------
+  // The following methods can be used to obtain information about IME-related
+  // state for the active RenderWidgetHost. If the active widget is nullptr, the
+  // methods below will return nullptr as well.
+  // Users of these methods should not hold on to the pointers as they become
+  // dangling if the TextInputManager or |active_view_| are destroyed.
+
+  // Returns the currently stored TextInputState. An state of nullptr can be
+  // interpreted as a ui::TextInputType of ui::TEXT_INPUT_TYPE_NONE.
   const TextInputState* GetTextInputState();
 
-  // Returns the rect between selection bounds for the |active_view_|.
+  // Returns the rect between selection bounds.
   gfx::Rect GetSelectionBoundsRect();
 
+  // Returns a vector of rects representing the character bounds.
+  const std::vector<gfx::Rect>* GetCompositionCharacterBounds();
+
   // ---------------------------------------------------------------------------
   // The following methods are called by RWHVs on the tab to update their IME-
   // related state.
@@ -88,6 +102,12 @@
   void SelectionBoundsChanged(RenderWidgetHostViewBase* view,
                               const ViewHostMsg_SelectionBounds_Params& params);
 
+  // Called when the composition range and/or character bounds have changed.
+  void ImeCompositionRangeChanged(
+      RenderWidgetHostViewBase* view,
+      const gfx::Range& range,
+      const std::vector<gfx::Rect>& character_bounds);
+
   // Registers the given |view| for tracking its TextInputState. This is called
   // by any view which has updates in its TextInputState (whether tab's RWHV or
   // that of a child frame). The |view| must unregister itself before being
@@ -128,6 +148,15 @@
     gfx::SelectionBound focus;
   };
 
+  // Ccomposition range information.
+  struct CompositionRangeInfo {
+    CompositionRangeInfo();
+    CompositionRangeInfo(const CompositionRangeInfo& other);
+    ~CompositionRangeInfo();
+
+    std::vector<gfx::Rect> character_bounds;
+  };
+
   // This class is used to create maps which hold specific IME state for a
   // view.
   template <class Value>
@@ -146,6 +175,7 @@
 
   // Text selection bounds information for registered views.
   ViewMap<SelectionRegion> selection_region_map_;
+  ViewMap<CompositionRangeInfo> composition_range_info_map_;
 
   base::ObserverList<Observer> observer_list_;
 
@@ -153,4 +183,4 @@
 };
 }
 
-#endif  // CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__
\ No newline at end of file
+#endif  // CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc
index ddab806..e4b8228 100644
--- a/content/browser/utility_process_host_impl.cc
+++ b/content/browser/utility_process_host_impl.cc
@@ -172,10 +172,9 @@
                                                  child_token_));
   mojo_child_connection_.reset(new MojoChildConnection(
       kUtilityMojoApplicationName,
-      base::StringPrintf("%d_0", process_->GetData().id), child_token_,
-      MojoShellContext::GetConnectorForIOThread(),
-      BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
-          ->task_runner()));
+      base::StringPrintf("%d_0", process_->GetData().id),
+      child_token_,
+      MojoShellContext::GetConnectorForIOThread()));
 }
 
 UtilityProcessHostImpl::~UtilityProcessHostImpl() {
@@ -240,11 +239,11 @@
 }
 
 shell::InterfaceRegistry* UtilityProcessHostImpl::GetInterfaceRegistry() {
-  return mojo_child_connection_->GetInterfaceRegistry();
+  return mojo_child_connection_->connection()->GetInterfaceRegistry();
 }
 
 shell::InterfaceProvider* UtilityProcessHostImpl::GetRemoteInterfaces() {
-  return mojo_child_connection_->GetRemoteInterfaces();
+  return mojo_child_connection_->connection()->GetRemoteInterfaces();
 }
 
 void UtilityProcessHostImpl::SetName(const base::string16& name) {
diff --git a/content/child/background_sync/background_sync_provider.cc b/content/child/background_sync/background_sync_provider.cc
index b10a33c..517a6b61 100644
--- a/content/child/background_sync/background_sync_provider.cc
+++ b/content/child/background_sync/background_sync_provider.cc
@@ -16,7 +16,6 @@
 #include "content/child/background_sync/background_sync_type_converters.h"
 #include "content/child/child_thread_impl.h"
 #include "content/child/service_worker/web_service_worker_registration_impl.h"
-#include "services/shell/public/cpp/interface_provider.h"
 #include "third_party/WebKit/public/platform/modules/background_sync/WebSyncError.h"
 #include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h"
 
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index d388d333..3bac8ae 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -68,8 +68,6 @@
 #include "mojo/edk/embedder/named_platform_channel_pair.h"
 #include "mojo/edk/embedder/platform_channel_pair.h"
 #include "mojo/edk/embedder/scoped_ipc_support.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/runner/common/client_util.h"
 
 #if defined(OS_POSIX)
@@ -333,18 +331,14 @@
 
 ChildThreadImpl::ChildThreadImpl()
     : router_(this),
-      channel_connected_factory_(
-          new base::WeakPtrFactory<ChildThreadImpl>(this)),
-      weak_factory_(this) {
+      channel_connected_factory_(this) {
   Init(Options::Builder().Build());
 }
 
 ChildThreadImpl::ChildThreadImpl(const Options& options)
     : router_(this),
       browser_process_io_runner_(options.browser_process_io_runner),
-      channel_connected_factory_(
-          new base::WeakPtrFactory<ChildThreadImpl>(this)),
-      weak_factory_(this) {
+      channel_connected_factory_(this) {
   Init(options);
 }
 
@@ -419,18 +413,8 @@
         mojo::edk::CreateChildMessagePipe(mojo_application_token);
     DCHECK(handle.is_valid());
     mojo_shell_connection_ = MojoShellConnection::Create(
-        mojo::MakeRequest<shell::mojom::Service>(std::move(handle)),
-        GetIOTaskRunner());
-
-    // TODO(rockot): Remove this once all child-to-browser interface connections
-    // are made via a Connector rather than directly through an
-    // InterfaceProvider, and all exposed interfaces are exposed via a
-    // ConnectionFilter.
-    mojo_shell_connection_->SetupInterfaceRequestProxies(
-        GetInterfaceRegistry(), GetRemoteInterfaces());
-
-    AddConnectionFilters(mojo_shell_connection_.get());
-    mojo_shell_connection_->Start();
+        mojo::MakeRequest<shell::mojom::Service>(std::move(handle)));
+    mojo_shell_connection_->MergeService(this);
   }
 
   sync_message_filter_ = channel_->CreateSyncMessageFilter();
@@ -515,7 +499,7 @@
 
   message_loop_->task_runner()->PostDelayedTask(
       FROM_HERE, base::Bind(&ChildThreadImpl::EnsureConnected,
-                            channel_connected_factory_->GetWeakPtr()),
+                            channel_connected_factory_.GetWeakPtr()),
       base::TimeDelta::FromSeconds(connection_timeout));
 
 #if defined(OS_ANDROID)
@@ -533,6 +517,9 @@
 }
 
 ChildThreadImpl::~ChildThreadImpl() {
+  if (MojoShellConnection::GetForProcess())
+    MojoShellConnection::DestroyForProcess();
+
 #ifdef IPC_MESSAGE_LOG_ENABLED
   IPC::Logging::GetInstance()->SetIPCSender(NULL);
 #endif
@@ -569,7 +556,7 @@
 }
 
 void ChildThreadImpl::OnChannelConnected(int32_t peer_pid) {
-  channel_connected_factory_.reset();
+  channel_connected_factory_.InvalidateWeakPtrs();
 }
 
 void ChildThreadImpl::OnChannelError() {
@@ -621,6 +608,14 @@
   return remote_interfaces_.get();
 }
 
+shell::InterfaceRegistry* ChildThreadImpl::GetInterfaceRegistryForConnection() {
+  return GetInterfaceRegistry();
+}
+
+shell::InterfaceProvider* ChildThreadImpl::GetInterfaceProviderForConnection() {
+  return GetRemoteInterfaces();
+}
+
 IPC::MessageRouter* ChildThreadImpl::GetRouter() {
   DCHECK(message_loop_->task_runner()->BelongsToCurrentThread());
   return &router_;
@@ -696,8 +691,6 @@
   return router_.OnMessageReceived(msg);
 }
 
-void ChildThreadImpl::AddConnectionFilters(MojoShellConnection* connection) {}
-
 bool ChildThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
   return false;
 }
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h
index e4447c9e..3680890 100644
--- a/content/child/child_thread_impl.h
+++ b/content/child/child_thread_impl.h
@@ -23,6 +23,7 @@
 #include "ipc/ipc_message.h"  // For IPC_MESSAGE_LOG_ENABLED.
 #include "ipc/ipc_platform_file.h"
 #include "ipc/message_router.h"
+#include "services/shell/public/cpp/service.h"
 
 namespace base {
 class MessageLoop;
@@ -67,7 +68,8 @@
 // The main thread of a child process derives from this class.
 class CONTENT_EXPORT ChildThreadImpl
     : public IPC::Listener,
-      virtual public ChildThread {
+      virtual public ChildThread,
+      public NON_EXPORTED_BASE(shell::Service){
  public:
   struct CONTENT_EXPORT Options;
 
@@ -99,6 +101,10 @@
   shell::InterfaceRegistry* GetInterfaceRegistry() override;
   shell::InterfaceProvider* GetRemoteInterfaces() override;
 
+  // shell::Service:
+  shell::InterfaceRegistry* GetInterfaceRegistryForConnection() override;
+  shell::InterfaceProvider* GetInterfaceProviderForConnection() override;
+
   IPC::SyncChannel* channel() { return channel_.get(); }
 
   IPC::MessageRouter* GetRouter();
@@ -203,10 +209,6 @@
   // Called when the process refcount is 0.
   void OnProcessFinalRelease();
 
-  // Implemented by subclasses to attach ConnectionFilters to the thread's
-  // shell connection.
-  virtual void AddConnectionFilters(MojoShellConnection* connection);
-
   virtual bool OnControlMessageReceived(const IPC::Message& msg);
   virtual void OnProcessBackgrounded(bool backgrounded);
   virtual void OnProcessPurgeAndSuspend();
@@ -251,9 +253,9 @@
   void EnsureConnected();
 
   std::unique_ptr<mojo::edk::ScopedIPCSupport> mojo_ipc_support_;
+  std::unique_ptr<MojoShellConnection> mojo_shell_connection_;
   std::unique_ptr<shell::InterfaceRegistry> interface_registry_;
   std::unique_ptr<shell::InterfaceProvider> remote_interfaces_;
-  std::unique_ptr<MojoShellConnection> mojo_shell_connection_;
 
   std::string channel_name_;
   std::unique_ptr<IPC::SyncChannel> channel_;
@@ -307,10 +309,7 @@
 
   scoped_refptr<base::SequencedTaskRunner> browser_process_io_runner_;
 
-  std::unique_ptr<base::WeakPtrFactory<ChildThreadImpl>>
-      channel_connected_factory_;
-
-  base::WeakPtrFactory<ChildThreadImpl> weak_factory_;
+  base::WeakPtrFactory<ChildThreadImpl> channel_connected_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ChildThreadImpl);
 };
diff --git a/content/common/content_switches_internal.cc b/content/common/content_switches_internal.cc
index 2c385d5..fa7ab4b 100644
--- a/content/common/content_switches_internal.cc
+++ b/content/common/content_switches_internal.cc
@@ -20,7 +20,7 @@
 namespace {
 
 bool IsUseZoomForDSFEnabledByDefault() {
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_WIN)
   return true;
 #else
   return false;
diff --git a/content/common/mojo/mojo_shell_connection_impl.cc b/content/common/mojo/mojo_shell_connection_impl.cc
index ee7ff97..5311ba6c 100644
--- a/content/common/mojo/mojo_shell_connection_impl.cc
+++ b/content/common/mojo/mojo_shell_connection_impl.cc
@@ -4,327 +4,63 @@
 
 #include "content/common/mojo/mojo_shell_connection_impl.h"
 
-#include <queue>
-#include <utility>
-#include <vector>
-
 #include "base/bind.h"
-#include "base/callback_helpers.h"
 #include "base/lazy_instance.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/threading/thread_checker.h"
+#include "base/threading/thread_local.h"
 #include "content/common/mojo/embedded_application_runner.h"
-#include "content/public/common/connection_filter.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "mojo/public/cpp/system/message_pipe.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/shell/public/cpp/service_context.h"
-#include "services/shell/public/interfaces/service_factory.mojom.h"
 #include "services/shell/runner/common/client_util.h"
 
 namespace content {
 namespace {
 
-base::LazyInstance<std::unique_ptr<MojoShellConnection>>::Leaky
-    g_connection_for_process = LAZY_INSTANCE_INITIALIZER;
+using MojoShellConnectionPtr =
+    base::ThreadLocalPointer<MojoShellConnection>;
+
+// Env is thread local so that aura may be used on multiple threads.
+base::LazyInstance<MojoShellConnectionPtr>::Leaky lazy_tls_ptr =
+    LAZY_INSTANCE_INITIALIZER;
 
 MojoShellConnection::Factory* mojo_shell_connection_factory = nullptr;
 
 }  // namespace
 
-// A ref-counted object which owns the IO thread state of a
-// MojoShellConnectionImpl. This includes Service and ServiceFactory
-// bindings.
-class MojoShellConnectionImpl::IOThreadContext
-    : public base::RefCountedThreadSafe<IOThreadContext>,
-      public shell::Service,
-      public shell::InterfaceFactory<shell::mojom::ServiceFactory>,
-      public shell::mojom::ServiceFactory {
- public:
-  using InitializeCallback = base::Callback<void(const shell::Identity&)>;
-  using ServiceFactoryCallback =
-      base::Callback<void(shell::mojom::ServiceRequest, const mojo::String&)>;
-
-  IOThreadContext(shell::mojom::ServiceRequest service_request,
-                  scoped_refptr<base::SequencedTaskRunner> io_task_runner,
-                  std::unique_ptr<shell::Connector> io_thread_connector,
-                  shell::mojom::ConnectorRequest connector_request)
-      : pending_service_request_(std::move(service_request)),
-        io_task_runner_(io_task_runner),
-        io_thread_connector_(std::move(io_thread_connector)),
-        pending_connector_request_(std::move(connector_request)) {
-    // This will be reattached by any of the IO thread functions on first call.
-    io_thread_checker_.DetachFromThread();
-  }
-
-  // Safe to call from any thread.
-  void Start(const InitializeCallback& initialize_callback,
-             const ServiceFactoryCallback& create_service_callback,
-             const base::Closure& stop_callback) {
-    DCHECK(!started_);
-
-    started_ = true;
-    callback_task_runner_ = base::ThreadTaskRunnerHandle::Get();
-    initialize_handler_ = initialize_callback;
-    create_service_callback_ = create_service_callback;
-    stop_callback_ = stop_callback;
-    io_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&IOThreadContext::StartOnIOThread, this));
-  }
-
-  // Safe to call from whichever thread called Start() (or may have called
-  // Start()). Must be called before IO thread shutdown.
-  void ShutDown() {
-    if (!started_)
-      return;
-
-    bool posted = io_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&IOThreadContext::ShutDownOnIOThread, this));
-    DCHECK(posted);
-  }
-
-  // Safe to call any time before Start() is called.
-  void AddConnectionFilter(std::unique_ptr<ConnectionFilter> filter) {
-    DCHECK(!started_);
-    connection_filters_.emplace_back(std::move(filter));
-  }
-
-  // Safe to call any time before Start() is called.
-  void SetDefaultBinderForBrowserConnection(
-      const shell::InterfaceRegistry::Binder& binder) {
-    DCHECK(!started_);
-    default_browser_binder_ = base::Bind(
-        &IOThreadContext::CallBinderOnTaskRunner,
-        base::ThreadTaskRunnerHandle::Get(), binder);
-  }
-
-  // Safe to call any time after Start() is called.
-  void GetRemoteInterface(const mojo::String& interface_name,
-                          mojo::ScopedMessagePipeHandle request_handle) {
-    DCHECK(started_);
-    io_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&IOThreadContext::GetRemoteInterfaceOnIOThread, this,
-                   interface_name, base::Passed(&request_handle)));
-  }
-
- private:
-  friend class base::RefCountedThreadSafe<IOThreadContext>;
-
-  ~IOThreadContext() override {}
-
-  void StartOnIOThread() {
-    // Should bind |io_thread_checker_| to the context's thread.
-    DCHECK(io_thread_checker_.CalledOnValidThread());
-    service_context_.reset(new shell::ServiceContext(
-        this, std::move(pending_service_request_),
-        std::move(io_thread_connector_),
-        std::move(pending_connector_request_)));
-  }
-
-  void ShutDownOnIOThread() {
-    DCHECK(io_thread_checker_.CalledOnValidThread());
-    service_context_.reset();
-    factory_bindings_.CloseAllBindings();
-  }
-
-  void GetRemoteInterfaceOnIOThread(
-      const mojo::String& interface_name,
-      mojo::ScopedMessagePipeHandle request_handle) {
-    DCHECK(io_thread_checker_.CalledOnValidThread());
-    if (browser_connection_) {
-      browser_connection_->GetRemoteInterfaces()->GetInterface(
-          interface_name, std::move(request_handle));
-    } else {
-      pending_remote_interface_requests_.emplace(interface_name,
-                                                 std::move(request_handle));
-    }
-  }
-
-  void OnBrowserConnectionLost() {
-    DCHECK(io_thread_checker_.CalledOnValidThread());
-    browser_connection_ = nullptr;
-  }
-
-  /////////////////////////////////////////////////////////////////////////////
-  // shell::Service implementation
-
-  void OnStart(shell::Connector* connector,
-               const shell::Identity& identity,
-               uint32_t id) override {
-    DCHECK(io_thread_checker_.CalledOnValidThread());
-    DCHECK(!initialize_handler_.is_null());
-
-    InitializeCallback handler = base::ResetAndReturn(&initialize_handler_);
-    callback_task_runner_->PostTask(FROM_HERE, base::Bind(handler, identity));
-  }
-
-  bool OnConnect(shell::Connection* connection) override {
-    DCHECK(io_thread_checker_.CalledOnValidThread());
-    std::string remote_app = connection->GetRemoteIdentity().name();
-    if (remote_app == "mojo:shell") {
-      // Only expose the SCF interface to the shell.
-      connection->AddInterface<shell::mojom::ServiceFactory>(this);
-      return true;
-    }
-
-    bool accept = false;
-    for (auto& filter : connection_filters_) {
-      accept = accept ||
-        filter->OnConnect(connection, service_context_->connector());
-    }
-
-    // Capture the browser connection if possible.
-    if (remote_app == "exe:content_browser" && !browser_connection_) {
-      browser_connection_ = connection;
-      connection->GetInterfaceRegistry()->set_default_binder(
-          default_browser_binder_);
-      connection->SetConnectionLostClosure(
-          base::Bind(&IOThreadContext::OnBrowserConnectionLost, this));
-      shell::InterfaceProvider* remote_interfaces =
-          connection->GetRemoteInterfaces();
-
-      // Flush any pending outgoing interface requests.
-      while (!pending_remote_interface_requests_.empty()) {
-        auto& request = pending_remote_interface_requests_.front();
-        remote_interfaces->GetInterface(
-            request.first, std::move(request.second));
-        pending_remote_interface_requests_.pop();
-      }
-      return true;
-    }
-
-    // If no filters were interested, reject the connection.
-    return accept;
-  }
-
-  bool OnStop() override {
-    callback_task_runner_->PostTask(FROM_HERE, stop_callback_);
-    return true;
-  }
-
-  /////////////////////////////////////////////////////////////////////////////
-  // shell::InterfaceFactory<shell::mojom::ServiceFactory> implementation
-
-  void Create(shell::Connection* connection,
-              shell::mojom::ServiceFactoryRequest request) override {
-    DCHECK(io_thread_checker_.CalledOnValidThread());
-    factory_bindings_.AddBinding(this, std::move(request));
-  }
-
-  /////////////////////////////////////////////////////////////////////////////
-  // shell::mojom::ServiceFactory implementation
-
-  void CreateService(shell::mojom::ServiceRequest request,
-                     const mojo::String& name) override {
-    DCHECK(io_thread_checker_.CalledOnValidThread());
-    callback_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(create_service_callback_, base::Passed(&request), name));
-  }
-
-  static void CallBinderOnTaskRunner(
-      scoped_refptr<base::SequencedTaskRunner> task_runner,
-      const shell::InterfaceRegistry::Binder& binder,
-      const mojo::String& interface_name,
-      mojo::ScopedMessagePipeHandle request_handle) {
-    task_runner->PostTask(FROM_HERE, base::Bind(binder, interface_name,
-                                                base::Passed(&request_handle)));
-  }
-
-  base::ThreadChecker io_thread_checker_;
-  bool started_ = false;
-
-  // Temporary state established on construction and consumed on the IO thread
-  // once the connection is started.
-  shell::mojom::ServiceRequest pending_service_request_;
-  scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
-  std::unique_ptr<shell::Connector> io_thread_connector_;
-  shell::mojom::ConnectorRequest pending_connector_request_;
-
-  // TaskRunner on which to run our owner's callbacks, i.e. the ones passed to
-  // Start().
-  scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
-
-  // Callback to run once Service::OnStart is invoked.
-  InitializeCallback initialize_handler_;
-
-  // Callback to run when a new Service request is received.
-  ServiceFactoryCallback create_service_callback_;
-
-  // Callback to run if the service is stopped by the service manager.
-  base::Closure stop_callback_;
-
-  // The incoming Connection from the browser process. This is captured the
-  // first time the browser connects to this Service and persists until shutdown
-  // or a connection error is detected. This connection is used to fulfill
-  // remote interface requests from legacy code which does not use
-  // shell::Connector.
-  //
-  // TODO(rockot): Remove this once all child-to-browser interface connections
-  // are made via a Connector rather than directly through an InterfaceProvider
-  // and all interfaces exposed to the browser are exposed via a
-  // ConnectionFilter.
-  shell::Connection* browser_connection_ = nullptr;
-
-  // A queue of remote interface requests destined for the browser, which will
-  // remain pending until an incoming connection is accepted from the browser.
-  //
-  // TODO(rockot): Remove this once all child-to-browser interface connections
-  // are made via a Connector rather than directly through an InterfaceProvider.
-  std::queue<std::pair<mojo::String, mojo::ScopedMessagePipeHandle>>
-      pending_remote_interface_requests_;
-
-  // Default binder callback used for the browser connection's
-  // InterfaceRegistry.
-  //
-  // TODO(rockot): Remove this once all interfaces exposed to the browser are
-  // exposed via a ConnectionFilter.
-  shell::InterfaceRegistry::Binder default_browser_binder_;
-
-  std::unique_ptr<shell::ServiceContext> service_context_;
-  mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_;
-  std::vector<std::unique_ptr<ConnectionFilter>> connection_filters_;
-
-  DISALLOW_COPY_AND_ASSIGN(IOThreadContext);
-};
-
 ////////////////////////////////////////////////////////////////////////////////
 // MojoShellConnection, public:
 
 // static
 void MojoShellConnection::SetForProcess(
     std::unique_ptr<MojoShellConnection> connection) {
-  DCHECK(!g_connection_for_process.Get());
-  g_connection_for_process.Get() = std::move(connection);
+  DCHECK(!lazy_tls_ptr.Pointer()->Get());
+  lazy_tls_ptr.Pointer()->Set(connection.release());
 }
 
 // static
 MojoShellConnection* MojoShellConnection::GetForProcess() {
-  return g_connection_for_process.Get().get();
+  return lazy_tls_ptr.Pointer()->Get();
 }
 
 // static
 void MojoShellConnection::DestroyForProcess() {
   // This joins the shell controller thread.
-  g_connection_for_process.Get().reset();
+  delete GetForProcess();
+  lazy_tls_ptr.Pointer()->Set(nullptr);
 }
 
 // static
 void MojoShellConnection::SetFactoryForTest(Factory* factory) {
-  DCHECK(!g_connection_for_process.Get());
+  DCHECK(!lazy_tls_ptr.Pointer()->Get());
   mojo_shell_connection_factory = factory;
 }
 
 // static
 std::unique_ptr<MojoShellConnection> MojoShellConnection::Create(
-    shell::mojom::ServiceRequest request,
-    scoped_refptr<base::SequencedTaskRunner> io_task_runner) {
+    shell::mojom::ServiceRequest request) {
   if (mojo_shell_connection_factory)
     return mojo_shell_connection_factory->Run();
-  return base::MakeUnique<MojoShellConnectionImpl>(
-      std::move(request), io_task_runner);
+  return base::WrapUnique(new MojoShellConnectionImpl(std::move(request)));
 }
 
 MojoShellConnection::~MojoShellConnection() {}
@@ -333,72 +69,115 @@
 // MojoShellConnectionImpl, public:
 
 MojoShellConnectionImpl::MojoShellConnectionImpl(
-    shell::mojom::ServiceRequest request,
-    scoped_refptr<base::SequencedTaskRunner> io_task_runner)
-    : weak_factory_(this) {
-  shell::mojom::ConnectorRequest connector_request;
-  connector_ = shell::Connector::Create(&connector_request);
+    shell::mojom::ServiceRequest request)
+    : shell_connection_(new shell::ServiceContext(this, std::move(request))) {}
 
-  std::unique_ptr<shell::Connector> io_thread_connector = connector_->Clone();
-  context_ = new IOThreadContext(
-      std::move(request), io_task_runner, std::move(io_thread_connector),
-      std::move(connector_request));
+MojoShellConnectionImpl::~MojoShellConnectionImpl() {}
+
+////////////////////////////////////////////////////////////////////////////////
+// MojoShellConnectionImpl, shell::Service implementation:
+
+void MojoShellConnectionImpl::OnStart(shell::Connector* connector,
+                                      const shell::Identity& identity,
+                                      uint32_t id) {
+  for (auto& client : embedded_services_)
+    client->OnStart(connector, identity, id);
 }
 
-MojoShellConnectionImpl::~MojoShellConnectionImpl() {
-  context_->ShutDown();
+bool MojoShellConnectionImpl::OnConnect(shell::Connection* connection) {
+  std::string remote_app = connection->GetRemoteIdentity().name();
+  if (remote_app == "mojo:shell") {
+    // Only expose the SCF interface to the shell.
+    connection->AddInterface<shell::mojom::ServiceFactory>(this);
+    return true;
+  }
+
+  bool accept = false;
+  for (auto& client : embedded_services_)
+    accept |= client->OnConnect(connection);
+
+  // Reject all other connections to this application.
+  return accept;
+}
+
+shell::InterfaceRegistry*
+MojoShellConnectionImpl::GetInterfaceRegistryForConnection() {
+  // TODO(beng): This is really horrible since obviously subject to issues
+  // of ordering, but is no more horrible than this API is in general.
+  shell::InterfaceRegistry* registry = nullptr;
+  for (auto& client : embedded_services_) {
+    registry = client->GetInterfaceRegistryForConnection();
+    if (registry)
+      return registry;
+  }
+  return nullptr;
+}
+
+shell::InterfaceProvider*
+MojoShellConnectionImpl::GetInterfaceProviderForConnection() {
+  // TODO(beng): This is really horrible since obviously subject to issues
+  // of ordering, but is no more horrible than this API is in general.
+  shell::InterfaceProvider* provider = nullptr;
+  for (auto& client : embedded_services_) {
+    provider = client->GetInterfaceProviderForConnection();
+    if (provider)
+      return provider;
+  }
+  return nullptr;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MojoShellConnectionImpl,
+//     shell::InterfaceFactory<shell::mojom::ServiceFactory> implementation:
+
+void MojoShellConnectionImpl::Create(
+    shell::Connection* connection,
+    shell::mojom::ServiceFactoryRequest request) {
+  factory_bindings_.AddBinding(this, std::move(request));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MojoShellConnectionImpl, shell::mojom::ServiceFactory implementation:
+
+void MojoShellConnectionImpl::CreateService(
+    shell::mojom::ServiceRequest request,
+    const mojo::String& name) {
+  auto it = request_handlers_.find(name);
+  if (it != request_handlers_.end())
+    it->second.Run(std::move(request));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // MojoShellConnectionImpl, MojoShellConnection implementation:
 
-void MojoShellConnectionImpl::Start() {
-  context_->Start(
-      base::Bind(&MojoShellConnectionImpl::OnContextInitialized,
-                 weak_factory_.GetWeakPtr()),
-      base::Bind(&MojoShellConnectionImpl::CreateService,
-                 weak_factory_.GetWeakPtr()),
-      base::Bind(&MojoShellConnectionImpl::OnConnectionLost,
-                 weak_factory_.GetWeakPtr()));
-}
-
-void MojoShellConnectionImpl::SetInitializeHandler(
-    const base::Closure& handler) {
-  DCHECK(initialize_handler_.is_null());
-  initialize_handler_ = handler;
+shell::ServiceContext* MojoShellConnectionImpl::GetShellConnection() {
+  return shell_connection_.get();
 }
 
 shell::Connector* MojoShellConnectionImpl::GetConnector() {
-  return connector_.get();
+  DCHECK(shell_connection_);
+  return shell_connection_->connector();
 }
 
 const shell::Identity& MojoShellConnectionImpl::GetIdentity() const {
-  return identity_;
+  DCHECK(shell_connection_);
+  return shell_connection_->identity();
 }
 
 void MojoShellConnectionImpl::SetConnectionLostClosure(
     const base::Closure& closure) {
-  connection_lost_handler_ = closure;
+  shell_connection_->SetConnectionLostClosure(closure);
 }
 
-void MojoShellConnectionImpl::SetupInterfaceRequestProxies(
-    shell::InterfaceRegistry* registry,
-    shell::InterfaceProvider* provider) {
-  // It's safe to bind |registry| as a raw pointer because the caller must
-  // guarantee that it outlives |this|, and |this| is bound as a weak ptr here.
-  context_->SetDefaultBinderForBrowserConnection(
-      base::Bind(&MojoShellConnectionImpl::GetInterface,
-                 weak_factory_.GetWeakPtr(), registry));
-
-  // Forward all remote interface requests on |provider| to our IO-thread
-  // context. This will ensure they're forwarded to the provider on the
-  // incoming browser connection.
-  provider->Forward(base::Bind(&IOThreadContext::GetRemoteInterface, context_));
+void MojoShellConnectionImpl::MergeService(
+    std::unique_ptr<shell::Service> service) {
+  embedded_services_.push_back(service.get());
+  owned_services_.push_back(std::move(service));
 }
 
-void MojoShellConnectionImpl::AddConnectionFilter(
-    std::unique_ptr<ConnectionFilter> filter) {
-  context_->AddConnectionFilter(std::move(filter));
+void MojoShellConnectionImpl::MergeService(
+    shell::Service* service) {
+  embedded_services_.push_back(service);
 }
 
 void MojoShellConnectionImpl::AddEmbeddedService(
@@ -420,31 +199,4 @@
   DCHECK(result.second);
 }
 
-void MojoShellConnectionImpl::CreateService(
-    shell::mojom::ServiceRequest request,
-    const mojo::String& name) {
-  auto it = request_handlers_.find(name);
-  if (it != request_handlers_.end())
-    it->second.Run(std::move(request));
-}
-
-void MojoShellConnectionImpl::OnContextInitialized(
-    const shell::Identity& identity) {
-  identity_ = identity;
-  if (!initialize_handler_.is_null())
-    base::ResetAndReturn(&initialize_handler_).Run();
-}
-
-void MojoShellConnectionImpl::OnConnectionLost() {
-  if (!connection_lost_handler_.is_null())
-    connection_lost_handler_.Run();
-}
-
-void MojoShellConnectionImpl::GetInterface(
-    shell::mojom::InterfaceProvider* provider,
-    const mojo::String& interface_name,
-    mojo::ScopedMessagePipeHandle request_handle) {
-  provider->GetInterface(interface_name, std::move(request_handle));
-}
-
 }  // namespace content
diff --git a/content/common/mojo/mojo_shell_connection_impl.h b/content/common/mojo/mojo_shell_connection_impl.h
index c262c9e..6a6882413 100644
--- a/content/common/mojo/mojo_shell_connection_impl.h
+++ b/content/common/mojo/mojo_shell_connection_impl.h
@@ -6,73 +6,68 @@
 #define CONTENT_COMMON_MOJO_SHELL_CONNECTION_IMPL_H_
 
 #include <memory>
+#include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
 #include "content/public/common/mojo_shell_connection.h"
-#include "mojo/public/cpp/bindings/string.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/system/message_pipe.h"
-#include "services/shell/public/cpp/identity.h"
-#include "services/shell/public/interfaces/service.mojom.h"
-
-namespace shell {
-class Connector;
-}
+#include "services/shell/public/cpp/service.h"
+#include "services/shell/public/cpp/service_context.h"
+#include "services/shell/public/interfaces/service_factory.mojom.h"
 
 namespace content {
 
 class EmbeddedApplicationRunner;
 
-class MojoShellConnectionImpl : public MojoShellConnection {
+class MojoShellConnectionImpl
+    : public MojoShellConnection,
+      public shell::Service,
+      public shell::InterfaceFactory<shell::mojom::ServiceFactory>,
+      public shell::mojom::ServiceFactory {
+
  public:
-  explicit MojoShellConnectionImpl(
-      shell::mojom::ServiceRequest request,
-      scoped_refptr<base::SequencedTaskRunner> io_task_runner);
+  explicit MojoShellConnectionImpl(shell::mojom::ServiceRequest request);
   ~MojoShellConnectionImpl() override;
 
  private:
-  class IOThreadContext;
-
   // MojoShellConnection:
-  void Start() override;
-  void SetInitializeHandler(const base::Closure& handler) override;
+  shell::ServiceContext* GetShellConnection() override;
   shell::Connector* GetConnector() override;
   const shell::Identity& GetIdentity() const override;
   void SetConnectionLostClosure(const base::Closure& closure) override;
-  void SetupInterfaceRequestProxies(
-      shell::InterfaceRegistry* registry,
-      shell::InterfaceProvider* provider) override;
-  void AddConnectionFilter(std::unique_ptr<ConnectionFilter> filter) override;
+  void MergeService(std::unique_ptr<shell::Service> service) override;
+  void MergeService(shell::Service* service) override;
   void AddEmbeddedService(const std::string& name,
                           const MojoApplicationInfo& info) override;
   void AddServiceRequestHandler(
       const std::string& name,
       const ServiceRequestHandler& handler) override;
 
-  void OnContextInitialized(const shell::Identity& identity);
-  void OnConnectionLost();
+  // shell::Service:
+  void OnStart(shell::Connector* connector,
+               const shell::Identity& identity,
+               uint32_t id) override;
+  bool OnConnect(shell::Connection* connection) override;
+  shell::InterfaceRegistry* GetInterfaceRegistryForConnection() override;
+  shell::InterfaceProvider* GetInterfaceProviderForConnection() override;
+
+  // shell::InterfaceFactory<shell::mojom::ServiceFactory>:
+  void Create(shell::Connection* connection,
+              shell::mojom::ServiceFactoryRequest request) override;
+
+  // shell::mojom::ServiceFactory:
   void CreateService(shell::mojom::ServiceRequest request,
-                     const mojo::String& name);
-  void GetInterface(shell::mojom::InterfaceProvider* provider,
-                    const mojo::String& interface_name,
-                    mojo::ScopedMessagePipeHandle request_handle);
+                         const mojo::String& name) override;
 
-  shell::Identity identity_;
-
-  std::unique_ptr<shell::Connector> connector_;
-  scoped_refptr<IOThreadContext> context_;
-
-  base::Closure initialize_handler_;
-  base::Closure connection_lost_handler_;
-
+  std::unique_ptr<shell::ServiceContext> shell_connection_;
+  mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_;
+  std::vector<shell::Service*> embedded_services_;
+  std::vector<std::unique_ptr<shell::Service>> owned_services_;
   std::unordered_map<std::string, std::unique_ptr<EmbeddedApplicationRunner>>
       embedded_apps_;
   std::unordered_map<std::string, ServiceRequestHandler> request_handlers_;
 
-  base::WeakPtrFactory<MojoShellConnectionImpl> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(MojoShellConnectionImpl);
 };
 
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 914b7fa..10cc09f7 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -114,7 +114,6 @@
       'public/common/common_param_traits.h',
       'public/common/common_param_traits_macros.h',
       'public/common/console_message_level.h',
-      'public/common/connection_filter.h',
       'public/common/content_client.cc',
       'public/common/content_client.h',
       'public/common/content_constants.cc',
diff --git a/content/gpu/BUILD.gn b/content/gpu/BUILD.gn
index 5b0f6b6..16c4aea 100644
--- a/content/gpu/BUILD.gn
+++ b/content/gpu/BUILD.gn
@@ -57,7 +57,6 @@
     "//ipc",
     "//media/gpu",
     "//media/gpu/ipc/service",
-    "//services/shell/public/cpp",
     "//services/shell/public/interfaces",
     "//skia",
     "//ui/events/ipc",
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index 2c36e17d..af207ab 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -22,7 +22,6 @@
 #include "content/gpu/gpu_watchdog_thread.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/mojo_shell_connection.h"
 #include "content/public/gpu/content_gpu_client.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
@@ -37,7 +36,6 @@
 #include "media/gpu/ipc/service/gpu_video_decode_accelerator.h"
 #include "media/gpu/ipc/service/gpu_video_encode_accelerator.h"
 #include "media/gpu/ipc/service/media_service.h"
-#include "services/shell/public/cpp/interface_registry.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/gl/gpu_switching_manager.h"
@@ -223,18 +221,6 @@
   // Only set once per process instance.
   process_control_.reset(new GpuProcessControlImpl());
 
-  GetInterfaceRegistry()->AddInterface(base::Bind(
-      &GpuChildThread::BindProcessControlRequest, base::Unretained(this)));
-
-  if (GetContentClient()->gpu()) {  // NULL in tests.
-    GetContentClient()->gpu()->ExposeInterfacesToBrowser(
-        GetInterfaceRegistry());
-  }
-
-  // We don't want to process any incoming interface requests until
-  // OnInitialize() is invoked.
-  GetInterfaceRegistry()->PauseBinding();
-
   if (GetContentClient()->gpu())  // NULL in tests.
     GetContentClient()->gpu()->Initialize(this);
 }
@@ -304,6 +290,37 @@
   return false;
 }
 
+bool GpuChildThread::OnConnect(shell::Connection* connection) {
+  // Use of base::Unretained(this) is safe here because |service_registry()|
+  // will be destroyed before GpuChildThread is destructed.
+  connection->GetInterfaceRegistry()->AddInterface(base::Bind(
+      &GpuChildThread::BindProcessControlRequest, base::Unretained(this)));
+
+  if (GetContentClient()->gpu()) {  // NULL in tests.
+    GetContentClient()->gpu()->ExposeInterfacesToBrowser(
+        connection->GetInterfaceRegistry());
+  }
+
+  // We don't want to process any incoming interface requests until
+  // OnInitialize().
+  if (!gpu_channel_manager_) {
+    connection->GetInterfaceRegistry()->PauseBinding();
+    resume_interface_bindings_callback_ = base::Bind(
+        &shell::InterfaceRegistry::ResumeBinding,
+        connection->GetInterfaceRegistry()->GetWeakPtr());
+  }
+
+  return true;
+}
+
+shell::InterfaceRegistry* GpuChildThread::GetInterfaceRegistryForConnection() {
+  return nullptr;
+}
+
+shell::InterfaceProvider* GpuChildThread::GetInterfaceProviderForConnection() {
+  return nullptr;
+}
+
 void GpuChildThread::SetActiveURL(const GURL& url) {
   GetContentClient()->SetActiveURL(url);
 }
@@ -347,7 +364,8 @@
 }
 
 void GpuChildThread::OnInitialize(const gpu::GpuPreferences& gpu_preferences) {
-  GetInterfaceRegistry()->ResumeBinding();
+  if (!resume_interface_bindings_callback_.is_null())
+    base::ResetAndReturn(&resume_interface_bindings_callback_).Run();
 
   gpu_preferences_ = gpu_preferences;
 
@@ -566,7 +584,7 @@
 }
 
 void GpuChildThread::BindProcessControlRequest(
-    mojom::ProcessControlRequest request) {
+    mojo::InterfaceRequest<mojom::ProcessControl> request) {
   DVLOG(1) << "GPU: Binding ProcessControl request";
   DCHECK(process_control_);
   process_control_bindings_.AddBinding(process_control_.get(),
diff --git a/content/gpu/gpu_child_thread.h b/content/gpu/gpu_child_thread.h
index 7eb8c462..f51bba1 100644
--- a/content/gpu/gpu_child_thread.h
+++ b/content/gpu/gpu_child_thread.h
@@ -28,6 +28,7 @@
 #include "gpu/ipc/service/gpu_config.h"
 #include "gpu/ipc/service/x_util.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
 #include "ui/gfx/native_widget_types.h"
 
 namespace gpu {
@@ -86,6 +87,9 @@
   bool Send(IPC::Message* msg) override;
   bool OnControlMessageReceived(const IPC::Message& msg) override;
   bool OnMessageReceived(const IPC::Message& msg) override;
+  bool OnConnect(shell::Connection* connection) override;
+  shell::InterfaceRegistry* GetInterfaceRegistryForConnection() override;
+  shell::InterfaceProvider* GetInterfaceProviderForConnection() override;
 
   // gpu::GpuChannelManagerDelegate:
   void SetActiveURL(const GURL& url) override;
@@ -134,7 +138,8 @@
 #endif
   void OnLoseAllContexts();
 
-  void BindProcessControlRequest(mojom::ProcessControlRequest request);
+  void BindProcessControlRequest(
+      mojo::InterfaceRequest<mojom::ProcessControl> request);
 
   gpu::GpuPreferences gpu_preferences_;
 
@@ -174,6 +179,8 @@
   // Bindings to the mojom::ProcessControl impl.
   mojo::BindingSet<mojom::ProcessControl> process_control_bindings_;
 
+  base::Closure resume_interface_bindings_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(GpuChildThread);
 };
 
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h
index e1ddb079..8526ef7e 100644
--- a/content/public/browser/render_process_host.h
+++ b/content/public/browser/render_process_host.h
@@ -270,6 +270,9 @@
   // interfaces exposed to it from the renderer.
   virtual shell::InterfaceProvider* GetRemoteInterfaces() = 0;
 
+  // Returns the shell connection for this process.
+  virtual shell::Connection* GetChildConnection() = 0;
+
   // Extracts any persistent-memory-allocator used for renderer metrics.
   // Ownership is passed to the caller. To support sharing of histogram data
   // between the Renderer and the Browser, the allocator is created when the
diff --git a/content/public/child/child_thread.h b/content/public/child/child_thread.h
index 2a3c8d8..d3ad0ce 100644
--- a/content/public/child/child_thread.h
+++ b/content/public/child/child_thread.h
@@ -5,7 +5,6 @@
 #ifndef CONTENT_PUBLIC_CHILD_CHILD_THREAD_H_
 #define CONTENT_PUBLIC_CHILD_CHILD_THREAD_H_
 
-#include <memory>
 #include <string>
 
 #include "base/logging.h"
@@ -28,8 +27,7 @@
 
 namespace content {
 
-class ConnectionFilter;
-class MojoShellConnection;
+  class MojoShellConnection;
 
 // An abstract base class that contains logic shared between most child
 // processes of the embedder.
diff --git a/content/public/common/connection_filter.h b/content/public/common/connection_filter.h
deleted file mode 100644
index be8da3f..0000000
--- a/content/public/common/connection_filter.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 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_COMMON_CONNECTION_FILTER_H_
-#define CONTENT_PUBLIC_COMMON_CONNECTION_FILTER_H_
-
-#include "content/common/content_export.h"
-
-namespace shell {
-class Connection;
-class Connector;
-}
-
-namespace content {
-
-// A ConnectionFilter may be used to conditionally expose interfaces on inbound
-// connections accepted by MojoShellConnection. ConnectionFilters are used
-// exclusively on the IO thread. See MojoShellConnection::AddConnectionFilter
-// for details.
-class CONTENT_EXPORT ConnectionFilter {
- public:
-  virtual ~ConnectionFilter() {}
-
-  // Called for every new connection accepted. Implementations may add
-  // interfaces to |connection|, in which case they should return |true|.
-  // |connector| is a corresponding outgoing Connector that may be used by any
-  // interfaces added to the connection. Note that references to |connector|
-  // must not be retained, but an owned copy may be obtained by calling
-  // |connector->Clone()|.
-  //
-  // If a ConnectionFilter is not interested in an incoming connection, it
-  // should return |false|.
-  virtual bool OnConnect(shell::Connection* connection,
-                         shell::Connector* connector) = 0;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_PUBLIC_COMMON_CONNECTION_FILTER_H_
diff --git a/content/public/common/mojo_shell_connection.h b/content/public/common/mojo_shell_connection.h
index 577f128..7014034 100644
--- a/content/public/common/mojo_shell_connection.h
+++ b/content/public/common/mojo_shell_connection.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/callback_forward.h"
-#include "base/sequenced_task_runner.h"
 #include "content/common/content_export.h"
 #include "content/public/common/mojo_application_info.h"
 #include "services/shell/public/cpp/identity.h"
@@ -17,14 +16,11 @@
 namespace shell {
 class Connection;
 class Connector;
-class InterfaceProvider;
-class InterfaceRegistry;
+class ServiceContext;
 }
 
 namespace content {
 
-class ConnectionFilter;
-
 // Encapsulates a connection to a //services/shell.
 // Access a global instance on the thread the ServiceContext was bound by
 // calling Holder::Get().
@@ -59,21 +55,13 @@
   // called before the MojoShellConnection has been created.
   static void SetFactoryForTest(Factory* factory);
 
-  // Creates a MojoShellConnection from |request|. The connection binds
-  // its interfaces and accept new connections on |io_task_runner| only. Note
-  // that no incoming connections are accepted until Start() is called.
+  // Creates a MojoShellConnection from |request|.
   static std::unique_ptr<MojoShellConnection> Create(
-      shell::mojom::ServiceRequest request,
-      scoped_refptr<base::SequencedTaskRunner> io_task_runner);
+      shell::mojom::ServiceRequest request);
 
-  // Begins accepting incoming connections. Connection filters MUST be added
-  // before calling this in order to avoid races. See AddConnectionFilter()
-  // below.
-  virtual void Start() = 0;
-
-  // Sets a closure to be invoked once the connection receives an Initialize()
-  // request from the shell.
-  virtual void SetInitializeHandler(const base::Closure& handler) = 0;
+  // Returns the bound shell::ServiceContext object.
+  // TODO(rockot): remove.
+  virtual shell::ServiceContext* GetShellConnection() = 0;
 
   // Returns the shell::Connector received via this connection's Service
   // implementation. Use this to initiate connections as this object's Identity.
@@ -88,31 +76,12 @@
   // run immediately before returning from this function.
   virtual void SetConnectionLostClosure(const base::Closure& closure) = 0;
 
-  // Provides an InterfaceRegistry to forward incoming interface requests to
-  // on the MojoShellConnection's own thread if they aren't bound by the
-  // connection's internal InterfaceRegistry on the IO thread.
-  //
-  // Also configures |interface_provider| to forward all of its outgoing
-  // interface requests to the connection's internal remote interface provider.
-  //
-  // Note that neither |interface_registry| or |interface_provider| is owned
-  // and both MUST outlive the MojoShellConnection.
-  //
-  // TODO(rockot): Remove this. It's a temporary solution to avoid porting all
-  // relevant code to ConnectionFilters at once.
-  virtual void SetupInterfaceRequestProxies(
-      shell::InterfaceRegistry* registry,
-      shell::InterfaceProvider* provider) = 0;
-
-  // Allows the caller to filter inbound connections and/or expose interfaces
-  // on them. |filter| may be created on any thread, but will be used and
-  // destroyed exclusively on the IO thread (the thread corresponding to
-  // |io_task_runner| passed to Create() above.)
-  //
-  // Connection filters MUST be added before calling Start() in order to avoid
-  // races.
-  virtual void AddConnectionFilter(
-      std::unique_ptr<ConnectionFilter> filter) = 0;
+  // Allows the caller to expose interfaces to the caller using the identity of
+  // this object's Service. As distinct from MergeService() and
+  // AddServiceRequestHandler() which specify unique identities for the
+  // registered services.
+  virtual void MergeService(std::unique_ptr<shell::Service> service) = 0;
+  virtual void MergeService(shell::Service* service) = 0;
 
   // Adds an embedded service to this connection's ServiceFactory.
   // |info| provides details on how to construct new instances of the
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc
index 5924b51..a75a3f9 100644
--- a/content/public/test/mock_render_process_host.cc
+++ b/content/public/test/mock_render_process_host.cc
@@ -269,6 +269,10 @@
   return remote_interfaces_.get();
 }
 
+shell::Connection* MockRenderProcessHost::GetChildConnection() {
+  return nullptr;
+}
+
 std::unique_ptr<base::SharedPersistentMemoryAllocator>
 MockRenderProcessHost::TakeMetricsAllocator() {
   return nullptr;
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h
index 770377d..38030657 100644
--- a/content/public/test/mock_render_process_host.h
+++ b/content/public/test/mock_render_process_host.h
@@ -96,6 +96,7 @@
   void NotifyTimezoneChange(const std::string& zone_id) override;
   shell::InterfaceRegistry* GetInterfaceRegistry() override;
   shell::InterfaceProvider* GetRemoteInterfaces() override;
+  shell::Connection* GetChildConnection() override;
   std::unique_ptr<base::SharedPersistentMemoryAllocator> TakeMetricsAllocator()
       override;
   const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
diff --git a/content/public/test/text_input_test_utils.cc b/content/public/test/text_input_test_utils.cc
index 594c4be..bc13104e 100644
--- a/content/public/test/text_input_test_utils.cc
+++ b/content/public/test/text_input_test_utils.cc
@@ -18,6 +18,8 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/test/test_utils.h"
+#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
+#include "ui/base/ime/composition_underline.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/base/ime/input_method_observer.h"
 
@@ -58,6 +60,11 @@
     on_selection_bounds_changed_callback_ = callback;
   }
 
+  void set_on_ime_composition_range_changed_callback(
+      const base::Closure& callback) {
+    on_ime_composition_range_changed_callback_ = callback;
+  }
+
   const RenderWidgetHostView* GetUpdatedView() const { return updated_view_; }
 
   bool text_input_state_changed() const { return text_input_state_changed_; }
@@ -84,6 +91,14 @@
       on_selection_bounds_changed_callback_.Run();
   }
 
+  void OnImeCompositionRangeChanged(
+      TextInputManager* text_input_manager,
+      RenderWidgetHostViewBase* updated_view) override {
+    updated_view_ = updated_view;
+    if (!on_ime_composition_range_changed_callback_.is_null())
+      on_ime_composition_range_changed_callback_.Run();
+  }
+
   // WebContentsObserver implementation.
   void WebContentsDestroyed() override { text_input_manager_ = nullptr; }
 
@@ -93,6 +108,7 @@
   bool text_input_state_changed_;
   base::Closure update_text_input_state_callback_;
   base::Closure on_selection_bounds_changed_callback_;
+  base::Closure on_ime_composition_range_changed_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(InternalObserver);
 };
@@ -216,6 +232,25 @@
   return true;
 }
 
+void SetCompositionForRenderWidgetHost(
+    RenderWidgetHost* render_widget_host,
+    const base::string16& text,
+    const std::vector<ui::CompositionUnderline>& underlines,
+    const gfx::Range& replacement_range,
+    int selection_start,
+    int selection_end) {
+  std::vector<blink::WebCompositionUnderline> web_underlines;
+  for (auto underline : underlines) {
+    web_underlines.emplace_back(blink::WebCompositionUnderline(
+        underline.start_offset, underline.end_offset, underline.color,
+        underline.thick, underline.background_color));
+  }
+
+  static_cast<RenderWidgetHostImpl*>(render_widget_host)
+      ->ImeSetComposition(text, web_underlines, replacement_range,
+                          selection_start, selection_end);
+}
+
 size_t GetRegisteredViewsCountFromTextInputManager(WebContents* web_contents) {
   std::unordered_set<RenderWidgetHostView*> views;
   TextInputManager* manager =
@@ -244,6 +279,11 @@
   observer_->set_on_selection_bounds_changed_callback(callback);
 }
 
+void TextInputManagerTester::SetOnImeCompositionRangeChangedCallback(
+    const base::Closure& callback) {
+  observer_->set_on_ime_composition_range_changed_callback(callback);
+}
+
 bool TextInputManagerTester::GetTextInputType(ui::TextInputType* type) {
   DCHECK(observer_->text_input_manager());
   const TextInputState* state =
@@ -351,4 +391,4 @@
   return observer;
 }
 
-}  // namespace content
\ No newline at end of file
+}  // namespace content
diff --git a/content/public/test/text_input_test_utils.h b/content/public/test/text_input_test_utils.h
index f87e9fe..97b1da1 100644
--- a/content/public/test/text_input_test_utils.h
+++ b/content/public/test/text_input_test_utils.h
@@ -6,13 +6,24 @@
 #define CONTENT_PUBLIC_TEST_TEXT_INPUT_TEST_UTILS_H_
 
 #include <string>
+#include <vector>
 
 #include "base/callback.h"
+#include "base/strings/string16.h"
 #include "ui/base/ime/text_input_mode.h"
 #include "ui/base/ime/text_input_type.h"
 
+namespace gfx {
+class Range;
+}
+
+namespace ui {
+struct CompositionUnderline;
+}
+
 namespace content {
 
+class RenderWidgetHost;
 class RenderWidgetHostView;
 class RenderWidgetHostViewBase;
 class WebContents;
@@ -38,6 +49,16 @@
 // given WebContents.
 RenderWidgetHostView* GetActiveViewFromWebContents(WebContents* web_contents);
 
+// This method will send an InputMsg_ImeSetComposition IPC with the provided
+// parameters to the |render_widget_host|.
+void SetCompositionForRenderWidgetHost(
+    RenderWidgetHost* render_widget_host,
+    const base::string16& text,
+    const std::vector<ui::CompositionUnderline>& underlines,
+    const gfx::Range& replacement_range,
+    int selection_start,
+    int selection_end);
+
 // This class provides the necessary API for accessing the state of and also
 // observing the TextInputManager for WebContents.
 class TextInputManagerTester {
@@ -53,6 +74,10 @@
   // on the TextInputManager which is being observed.
   void SetOnSelectionBoundsChangedCallback(const base::Closure& callback);
 
+  // Sets a callback which is invoked when a RWHV calls
+  // ImeCompositionRangeChanged on the TextInputManager that is being observed.
+  void SetOnImeCompositionRangeChangedCallback(const base::Closure& callback);
+
   // Returns true if there is a focused <input> and populates |type| with
   // |TextInputState.type| of the TextInputManager.
   bool GetTextInputType(ui::TextInputType* type);
diff --git a/content/renderer/history_controller.cc b/content/renderer/history_controller.cc
index 5f0f28b..14ced356 100644
--- a/content/renderer/history_controller.cc
+++ b/content/renderer/history_controller.cc
@@ -201,7 +201,8 @@
         // a different frame.  For main frames, it is not safe to leave the
         // current_entry_ in place, which may have a cross-site page and will be
         // included in the PageState for this commit.  Replace it with a new
-        // HistoryEntry corresponding to the commit.
+        // HistoryEntry corresponding to the commit, and clear any stale
+        // NavigationParams which might point to the wrong entry.
         //
         // This will lack any subframe history items that were in the original
         // provisional entry, but we don't know what those were after discarding
@@ -214,8 +215,10 @@
         // main frame case.  Since this bug is not present in the new
         // FrameNavigationEntry-based navigation path (https://crbug.com/236848)
         // we'll wait for that to fix the subframe case.
-        if (frame->IsMainFrame())
+        if (frame->IsMainFrame()) {
           current_entry_.reset(new HistoryEntry(item));
+          navigation_params_.reset();
+        }
 
         return;
       }
@@ -251,6 +254,13 @@
 
       if (HistoryEntry::HistoryNode* node =
               current_entry_->GetHistoryNodeForFrame(frame)) {
+        // Clear the children and any NavigationParams if this commit isn't for
+        // the same item.  Otherwise we might have stale data from a race.
+        if (node->item().itemSequenceNumber() != item.itemSequenceNumber()) {
+          node->RemoveChildren();
+          navigation_params_.reset();
+        }
+
         node->set_item(item);
       }
       break;
diff --git a/content/renderer/history_controller.h b/content/renderer/history_controller.h
index ff205967..ac52241 100644
--- a/content/renderer/history_controller.h
+++ b/content/renderer/history_controller.h
@@ -153,11 +153,15 @@
   // A HistoryEntry representing the page that is being loaded, or an empty
   // scoped_ptr if no page is being loaded.
   std::unique_ptr<HistoryEntry> provisional_entry_;
-  // The NavigationParams corresponding to the last load that was initiated by
-  // |GoToEntry|. This is kept around so that it can be passed into existing
-  // frames modified during a history navigation in GoToEntry(), and can be
+
+  // The NavigationParams corresponding to the last back/forward load that was
+  // initiated by |GoToEntry|. This is kept around so that it can be passed into
+  // existing frames affected by a history navigation in GoToEntry(), and can be
   // passed into frames created after the commit that resulted from the
   // navigation in GetItemForNewChildFrame().
+  //
+  // This is reset in UpdateForCommit if we see a commit from a different
+  // navigation, to avoid using stale parameters.
   std::unique_ptr<NavigationParams> navigation_params_;
 
   DISALLOW_COPY_AND_ASSIGN(HistoryController);
diff --git a/content/renderer/media/webmediaplayer_ms_compositor.cc b/content/renderer/media/webmediaplayer_ms_compositor.cc
index e337e64..7f95ba1 100644
--- a/content/renderer/media/webmediaplayer_ms_compositor.cc
+++ b/content/renderer/media/webmediaplayer_ms_compositor.cc
@@ -24,6 +24,7 @@
 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
 #include "third_party/libyuv/include/libyuv/convert.h"
+#include "third_party/libyuv/include/libyuv/planar_functions.h"
 #include "third_party/libyuv/include/libyuv/video_common.h"
 
 namespace content {
diff --git a/content/renderer/mus/render_widget_window_tree_client_factory.cc b/content/renderer/mus/render_widget_window_tree_client_factory.cc
index a068781..ef56edd 100644
--- a/content/renderer/mus/render_widget_window_tree_client_factory.cc
+++ b/content/renderer/mus/render_widget_window_tree_client_factory.cc
@@ -9,14 +9,11 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "content/common/render_widget_window_tree_client_factory.mojom.h"
-#include "content/public/common/connection_filter.h"
 #include "content/public/common/mojo_shell_connection.h"
 #include "content/renderer/mus/render_widget_mus_connection.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/shell/public/cpp/connection.h"
 #include "services/shell/public/cpp/interface_factory.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/ui/public/interfaces/window_tree.mojom.h"
@@ -26,34 +23,23 @@
 
 namespace {
 
-void BindMusConnectionOnMainThread(
-    uint32_t routing_id,
-    ui::mojom::WindowTreeClientRequest request) {
-  RenderWidgetMusConnection* connection =
-      RenderWidgetMusConnection::GetOrCreate(routing_id);
-  connection->Bind(std::move(request));
-}
-
 // This object's lifetime is managed by MojoShellConnection because it's a
 // registered with it.
 class RenderWidgetWindowTreeClientFactoryImpl
-    : public ConnectionFilter,
+    : public shell::Service,
       public shell::InterfaceFactory<
           mojom::RenderWidgetWindowTreeClientFactory>,
       public mojom::RenderWidgetWindowTreeClientFactory {
  public:
   RenderWidgetWindowTreeClientFactoryImpl() {
     DCHECK(MojoShellConnection::GetForProcess());
-
-    main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
   }
 
   ~RenderWidgetWindowTreeClientFactoryImpl() override {}
 
  private:
-  // ConnectionFilter implementation:
-  bool OnConnect(shell::Connection* connection,
-                 shell::Connector* connector) override {
+  // shell::Service implementation:
+  bool OnConnect(shell::Connection* connection) override {
     connection->AddInterface<mojom::RenderWidgetWindowTreeClientFactory>(this);
     return true;
   }
@@ -68,13 +54,12 @@
   // mojom::RenderWidgetWindowTreeClientFactory implementation.
   void CreateWindowTreeClientForRenderWidget(
       uint32_t routing_id,
-      ui::mojom::WindowTreeClientRequest request) override {
-    main_thread_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&BindMusConnectionOnMainThread, routing_id,
-                              base::Passed(&request)));
+      mojo::InterfaceRequest<ui::mojom::WindowTreeClient> request) override {
+    RenderWidgetMusConnection* connection =
+        RenderWidgetMusConnection::GetOrCreate(routing_id);
+    connection->Bind(std::move(request));
   }
 
-  scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
   mojo::BindingSet<mojom::RenderWidgetWindowTreeClientFactory> bindings_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetWindowTreeClientFactoryImpl);
@@ -82,10 +67,9 @@
 
 }  // namespace
 
-void CreateRenderWidgetWindowTreeClientFactory(
-    MojoShellConnection* connection) {
-  connection->AddConnectionFilter(
-      base::MakeUnique<RenderWidgetWindowTreeClientFactoryImpl>());
+void CreateRenderWidgetWindowTreeClientFactory() {
+  MojoShellConnection::GetForProcess()->MergeService(
+      base::WrapUnique(new RenderWidgetWindowTreeClientFactoryImpl));
 }
 
 }  // namespace content
diff --git a/content/renderer/mus/render_widget_window_tree_client_factory.h b/content/renderer/mus/render_widget_window_tree_client_factory.h
index f32e30fa8..f3b3b73 100644
--- a/content/renderer/mus/render_widget_window_tree_client_factory.h
+++ b/content/renderer/mus/render_widget_window_tree_client_factory.h
@@ -7,9 +7,7 @@
 
 namespace content {
 
-class MojoShellConnection;
-
-void CreateRenderWidgetWindowTreeClientFactory(MojoShellConnection* connection);
+void CreateRenderWidgetWindowTreeClientFactory();
 
 }  // namespace content
 
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index ef0fc885..660b52b 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -142,8 +142,6 @@
 #include "net/base/port_util.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/base/url_util.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
 #include "skia/ext/event_tracer_impl.h"
 #include "skia/ext/skia_memory_dump_provider.h"
 #include "third_party/WebKit/public/platform/WebImageGenerator.h"
@@ -851,6 +849,15 @@
   GetInterfaceRegistry()->AddInterface(base::Bind(CreateFrameFactory));
   GetInterfaceRegistry()->AddInterface(base::Bind(CreateEmbeddedWorkerSetup));
 
+#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
+  // We may not have a MojoShellConnection object in tests that directly
+  // instantiate a RenderThreadImpl.
+  if (MojoShellConnection::GetForProcess() &&
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kUseMusInRenderer))
+    CreateRenderWidgetWindowTreeClientFactory();
+#endif
+
   GetRemoteInterfaces()->GetInterface(
       mojo::GetProxy(&storage_partition_service_));
 
@@ -987,15 +994,6 @@
   lazy_tls.Pointer()->Set(nullptr);
 }
 
-void RenderThreadImpl::AddConnectionFilters(MojoShellConnection* connection) {
-#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kUseMusInRenderer)) {
-    CreateRenderWidgetWindowTreeClientFactory(connection);
-  }
-#endif
-}
-
 bool RenderThreadImpl::Send(IPC::Message* msg) {
   // There are cases where we want to pump asynchronous messages while waiting
   // synchronously for the replies to the message to be sent here. However, this
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 19fb8087..9a3795f 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -166,9 +166,6 @@
   // changed.
   static void NotifyTimezoneChange();
 
-  // ChildThreadImpl implementation:
-  void AddConnectionFilters(MojoShellConnection* connection) override;
-
   // RenderThread implementation:
   bool Send(IPC::Message* msg) override;
   IPC::SyncChannel* GetChannel() override;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 2fb3aac..7990efe5 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -84,7 +84,6 @@
 #include "media/blink/webcontentdecryptionmodule_impl.h"
 #include "media/filters/stream_parser_factory.h"
 #include "mojo/common/common_type_converters.h"
-#include "services/shell/public/cpp/interface_provider.h"
 #include "storage/common/database/database_identifier.h"
 #include "storage/common/quota/quota_types.h"
 #include "third_party/WebKit/public/platform/BlameContext.h"
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 30d6abd6..7988b852 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -43,8 +43,6 @@
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_macros.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
 #include "third_party/WebKit/public/platform/URLConversion.h"
 #include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index c0d3c92..aac19a8 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -653,8 +653,6 @@
     # AMD
     self.Flaky('conformance/more/functions/uniformi.html',
                ['linux', 'amd'], bug=550989)
-    self.Fail('conformance/textures/misc/tex-image-webgl.html',
-              ['linux', 'amd'], bug=626742)
 
     # AMD Radeon 6450
     self.Fail('conformance/extensions/angle-instanced-arrays.html',
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h
index b467c0e..a21fc48f 100644
--- a/content/test/test_render_view_host.h
+++ b/content/test/test_render_view_host.h
@@ -101,9 +101,6 @@
   void SetIsLoading(bool is_loading) override {}
   void UpdateCursor(const WebCursor& cursor) override {}
   void ImeCancelComposition() override {}
-  void ImeCompositionRangeChanged(
-      const gfx::Range& range,
-      const std::vector<gfx::Rect>& character_bounds) override {}
   void RenderProcessGone(base::TerminationStatus status,
                          int error_code) override;
   void Destroy() override;
diff --git a/docs/clang_tidy.md b/docs/clang_tidy.md
new file mode 100644
index 0000000..9265e0cbf
--- /dev/null
+++ b/docs/clang_tidy.md
@@ -0,0 +1,108 @@
+# Clang Tidy
+
+[TOC]
+
+## Danger, Will Robinson!
+
+Support for `clang-tidy` in Chromium is very experimental, and is somewhat
+painful to use. We are exploring making it easier and integrating with existing
+tools, but aren't there yet. If you don't want to wait and enjoy tinkering,
+forge ahead. Otherwise, feel free to turn back now.
+
+## Introduction
+
+[clang-tidy](http://clang.llvm.org/extra/clang-tidy/) is a clang-based C++
+“linter” tool. Its purpose is to provide an extensible framework for diagnosing
+and fixing typical programming errors, like style violations, interface misuse,
+or bugs that can be deduced via static analysis.
+
+## Setting Up
+
+In addition to a full Chromium checkout, you need the clang-tidy binary. We
+recommend checking llvm's clang source and building the clang-tidy binary
+directly. Instructions for getting started with clang are available from
+[llvm](http://clang.llvm.org/get_started.html). You'll need to get llvm,
+clang, and the extra clang tools (you won't need Compiler-RT or libcxx).
+If you don't have it, you'll also need to install cmake as a part of this
+process.
+
+Instead of building with `"Unix Makefiles"`, generate build files for Ninja with
+```
+cmake -GNinja ../llvm
+```
+
+Then, instead of using `make`, use ninja to build the clang-tidy binary with
+```
+ninja clang-tidy
+```
+
+This binary will be at (build)/bin/clang-tidy.
+
+If you intend to use the `fix` feature of clang-tidy, you'll also need to build
+the `clang-apply-replacements` binary.
+```
+ninja clang-apply-replacements
+```
+
+## Running clang-tidy
+
+Running clang-tidy is (hopefully) simple.
+1.  Build chrome normally.\*
+```
+ninja -C out/Release chrome
+```
+2.  Generate the compilation database
+```
+ninja -C out/Release -t compdb objcxx cxx > compile_commands.json
+```
+3.  Enter the build directory.
+```
+cd out/Release
+```
+4.  Run clang-tidy.
+```
+<PATH_TO_LLVM_SRC>/tools/clang/tools/extra/clang-tidy/tools/run-clang-tidy.py \
+    -p ../.. \# Set the root project directory, where compile_commands.json is.
+    # Set the clang-tidy binary path, if it's not in your $PATH.
+    -clang-tidy-binary <PATH_TO_LLVM_BUILD>/bin/clang-tidy \
+    # Set the clang-apply-replacements binary path, if it's not in your $PATH
+    # and you are using the `fix` behavior of clang-tidy.
+    -clang-apply-replacements-binary \
+        <PATH_TO_LLVM_BUILD>/bin/clang-apply-replacements \
+    # The checks to employ in the build. Use `-*` to omit default checks.
+    -checks=<CHECKS> \
+    -header-filter=<FILTER> \# Optional, limit results to only certain files.
+    -fix \# Optional, used if you want to have clang-tidy auto-fix errors.
+    chrome/browser # The path to the files you want to check.
+
+Copy-Paste Friendly (though you'll still need to stub in the variables):
+<PATH_TO_LLVM_SRC>/tools/clang/tools/extra/clang-tidy/tools/run-clang-tidy.py \
+    -p ../.. \
+    -clang-tidy-binary <PATH_TO_LLVM_BUILD>/bin/clang-tidy \
+    -clang-apply-replacements-binary \
+        <PATH_TO_LLVM_BUILD>/bin/clang-apply-replacements \
+    -checks=<CHECKS> \
+    -header-filter=<FILTER> \
+    -fix \
+    chrome/browser
+```
+
+\*It's not clear which, if any, `gn` flags may cause issues for `clang-tidy`.
+I've had no problems building a component release build, both with and without
+goma. if you run into issues, let us know!
+
+## Troubleshooting
+
+If you see errors like
+```
+src/build/linux/debian_wheezy_amd64-sysroot/usr/include/wchar.h:40:11: error: 'stdarg.h' file not found [clang-diagnostic-error]
+```
+
+then you should also build the `clang-headers` target in your llvm checkout.
+This is fixed by http://reviews.llvm.org/D22046, so if your llvm checkout is
+up-to-date, this shouldn't be needed.
+
+## Questions
+
+Questions? Reach out to rdevlin.cronin@chromium.org or thakis@chromium.org.
+Discoveries? Update the doc!
diff --git a/extensions/browser/extension_icon_image.cc b/extensions/browser/extension_icon_image.cc
index fc0bc0d..94e6489 100644
--- a/extensions/browser/extension_icon_image.cc
+++ b/extensions/browser/extension_icon_image.cc
@@ -43,13 +43,13 @@
 namespace {
 
 extensions::ExtensionResource GetExtensionIconResource(
-    const extensions::Extension* extension,
+    const extensions::Extension& extension,
     const ExtensionIconSet& icons,
     int size,
     ExtensionIconSet::MatchType match_type) {
   const std::string& path = icons.Get(size, match_type);
   return path.empty() ? extensions::ExtensionResource()
-                      : extension->GetResource(path);
+                      : extension.GetResource(path);
 }
 
 class BlankImageSource : public gfx::CanvasImageSource {
@@ -180,15 +180,15 @@
   extensions::ExtensionResource resource;
 
   // Find extension resource for non bundled component extensions.
-  resource = GetExtensionIconResource(extension_,
-                                      icon_set_,
-                                      resource_size_in_pixel,
-                                      ExtensionIconSet::MATCH_BIGGER);
+  resource =
+      GetExtensionIconResource(*extension_, icon_set_, resource_size_in_pixel,
+                               ExtensionIconSet::MATCH_BIGGER);
 
   // If resource is not found by now, try matching smaller one.
   if (resource.empty()) {
-    resource = GetExtensionIconResource(extension_, icon_set_,
-        resource_size_in_pixel, ExtensionIconSet::MATCH_SMALLER);
+    resource =
+        GetExtensionIconResource(*extension_, icon_set_, resource_size_in_pixel,
+                                 ExtensionIconSet::MATCH_SMALLER);
   }
 
   // If there is no resource found, return default icon.
@@ -204,10 +204,9 @@
 
   extensions::ImageLoader* loader =
       extensions::ImageLoader::Get(browser_context_);
-  loader->LoadImagesAsync(extension_, info_list,
+  loader->LoadImagesAsync(extension_.get(), info_list,
                           base::Bind(&IconImage::OnImageLoaded,
-                                     weak_ptr_factory_.GetWeakPtr(),
-                                     scale));
+                                     weak_ptr_factory_.GetWeakPtr(), scale));
 
   return gfx::ImageSkiaRep();
 }
@@ -258,8 +257,8 @@
 
   const Extension* extension = content::Details<const Extension>(details).ptr();
 
-  if (extension_ == extension)
-    extension_ = NULL;
+  if (extension_.get() == extension)
+    extension_ = nullptr;
 }
 
 }  // namespace extensions
diff --git a/extensions/browser/extension_icon_image.h b/extensions/browser/extension_icon_image.h
index 75a4c2d..e3e29a3 100644
--- a/extensions/browser/extension_icon_image.h
+++ b/extensions/browser/extension_icon_image.h
@@ -101,8 +101,8 @@
                const content::NotificationDetails& details) override;
 
   content::BrowserContext* browser_context_;
-  const Extension* extension_;
-  const ExtensionIconSet& icon_set_;
+  scoped_refptr<const Extension> extension_;
+  ExtensionIconSet icon_set_;
   const int resource_size_in_dip_;
 
   base::ObserverList<Observer> observers_;
diff --git a/headless/lib/headless_devtools_client_browsertest.cc b/headless/lib/headless_devtools_client_browsertest.cc
index daceba5d..65e8145 100644
--- a/headless/lib/headless_devtools_client_browsertest.cc
+++ b/headless/lib/headless_devtools_client_browsertest.cc
@@ -183,7 +183,7 @@
 
     devtools_client_->GetBrowser()->GetExperimental()->CreateTarget(
         browser::CreateTargetParams::Builder()
-            .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec())
+            .SetUrl(embedded_test_server()->GetURL("/hello.html").spec())
             .SetWidth(1)
             .SetHeight(1)
             .Build(),
@@ -229,7 +229,7 @@
 
     devtools_client_->GetBrowser()->GetExperimental()->CreateTarget(
         browser::CreateTargetParams::Builder()
-            .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec())
+            .SetUrl(embedded_test_server()->GetURL("/hello.html").spec())
             .SetBrowserContextId(context_id_)
             .Build(),
         base::Bind(
@@ -323,7 +323,7 @@
 
     devtools_client_->GetBrowser()->GetExperimental()->CreateTarget(
         browser::CreateTargetParams::Builder()
-            .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec())
+            .SetUrl(embedded_test_server()->GetURL("/hello.html").spec())
             .SetBrowserContextId(context_id_one_)
             .Build(),
         base::Bind(&BrowserDomainCreateTwoContexts::OnCreateTargetOneResult,
@@ -331,7 +331,7 @@
 
     devtools_client_->GetBrowser()->GetExperimental()->CreateTarget(
         browser::CreateTargetParams::Builder()
-            .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec())
+            .SetUrl(embedded_test_server()->GetURL("/hello.html").spec())
             .SetBrowserContextId(context_id_two_)
             .Build(),
         base::Bind(&BrowserDomainCreateTwoContexts::OnCreateTargetTwoResult,
diff --git a/media/base/mac/avfoundation_glue.h b/media/base/mac/avfoundation_glue.h
index a5b4304..fb76958ae 100644
--- a/media/base/mac/avfoundation_glue.h
+++ b/media/base/mac/avfoundation_glue.h
@@ -2,12 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// AVFoundation API is only introduced in Mac OS X > 10.6, and there is only one
-// build of Chromium, so the (potential) linking with AVFoundation has to happen
-// in runtime. For this to be clean, an AVFoundationGlue class is defined to try
-// and load these AVFoundation system libraries. If it succeeds, subsequent
-// clients can use AVFoundation via the rest of the classes declared in this
-// file.
+// TODO(mcasas): Remove this whole glue, https://crbug.com/579648. This glue was
+// introduced to support Mac OS X <= 10.6 where AVFoundation was not available,
+// and had to happen in runtime.
 
 #ifndef MEDIA_BASE_MAC_AVFOUNDATION_GLUE_H_
 #define MEDIA_BASE_MAC_AVFOUNDATION_GLUE_H_
@@ -51,6 +48,7 @@
 
   static Class AVCaptureSessionClass();
   static Class AVCaptureVideoDataOutputClass();
+  static Class AVCaptureStillImageOutputClass();
 #endif  // defined(__OBJC__)
 
  private:
@@ -95,6 +93,9 @@
 
 MEDIA_EXPORT
 @interface CrAVCaptureOutput : NSObject  // Originally from AVCaptureOutput.h.
+
+- (NSArray*)connections;
+
 @end
 
 // Originally AVCaptureSession and coming from AVCaptureSession.h.
@@ -104,6 +105,7 @@
 - (void)release;
 - (void)addInput:(CrAVCaptureInput*)input;
 - (void)removeInput:(CrAVCaptureInput*)input;
+- (NSArray*)outputs;
 - (void)addOutput:(CrAVCaptureOutput*)output;
 - (void)removeOutput:(CrAVCaptureOutput*)output;
 - (BOOL)isRunning;
@@ -156,6 +158,17 @@
 
 @end
 
+// Originally AVCaptureStillImageOutput and coming from AVCaptureOutput.h.
+MEDIA_EXPORT
+@interface CrAVCaptureStillImageOutput : CrAVCaptureOutput
+
+typedef void (^CompletionHandler)(CoreMediaGlue::CMSampleBufferRef, NSError*);
+- (void)
+captureStillImageAsynchronouslyFromConnection:(CrAVCaptureConnection*)connection
+                            completionHandler:(CompletionHandler)handler;
+
+@end
+
 // Class to provide access to class methods of AVCaptureDevice.
 MEDIA_EXPORT
 @interface AVCaptureDeviceGlue : NSObject
diff --git a/media/base/mac/avfoundation_glue.mm b/media/base/mac/avfoundation_glue.mm
index 56f51aa..4bd6d72 100644
--- a/media/base/mac/avfoundation_glue.mm
+++ b/media/base/mac/avfoundation_glue.mm
@@ -167,6 +167,10 @@
   return [AVFoundationBundle() classNamed:@"AVCaptureVideoDataOutput"];
 }
 
+Class AVFoundationGlue::AVCaptureStillImageOutputClass() {
+  return [AVFoundationBundle() classNamed:@"AVCaptureStillImageOutput"];
+}
+
 @implementation AVCaptureDeviceGlue
 
 + (NSArray*)devices {
diff --git a/media/base/mac/coremedia_glue.h b/media/base/mac/coremedia_glue.h
index 9f69f96f..093427cd 100644
--- a/media/base/mac/coremedia_glue.h
+++ b/media/base/mac/coremedia_glue.h
@@ -52,6 +52,7 @@
     kCMPixelFormat_422YpCbCr8_yuvs = 'yuvs',
   };
   enum {
+    kCMVideoCodecType_JPEG = 'jpeg',
     kCMVideoCodecType_JPEG_OpenDML = 'dmb1',
     kCMVideoCodecType_H264 = 'avc1',
   };
diff --git a/media/blink/webmediaplayer_cast_android.cc b/media/blink/webmediaplayer_cast_android.cc
index 8f073b95..5ad9565 100644
--- a/media/blink/webmediaplayer_cast_android.cc
+++ b/media/blink/webmediaplayer_cast_android.cc
@@ -18,8 +18,6 @@
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkTypeface.h"
-#include "third_party/skia/include/gpu/GrContext.h"
-#include "third_party/skia/include/gpu/SkGrPixelRef.h"
 
 using gpu::gles2::GLES2Interface;
 
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.h b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
index 8198bcd..69082e7a 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.h
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
@@ -21,8 +21,9 @@
 @class CrAVCaptureDevice;
 @class CrAVCaptureSession;
 @class CrAVCaptureVideoDataOutput;
+@class CrAVCaptureStillImageOutput;
 
-// Class used by VideoCaptureDeviceMac (VCDM) for video capture using
+// Class used by VideoCaptureDeviceMac (VCDM) for video and image capture using
 // AVFoundation API. This class lives inside the thread created by its owner
 // VCDM.
 //
@@ -62,7 +63,7 @@
   int frameHeight_;
   float frameRate_;
 
-  base::Lock lock_;  // Protects concurrent setting and using of frameReceiver_.
+  base::Lock lock_;  // Protects concurrent setting and using |frameReceiver_|.
   media::VideoCaptureDeviceMac* frameReceiver_;  // weak.
 
   base::scoped_nsobject<CrAVCaptureSession> captureSession_;
@@ -74,6 +75,9 @@
   CrAVCaptureDeviceInput* captureDeviceInput_;
   base::scoped_nsobject<CrAVCaptureVideoDataOutput> captureVideoDataOutput_;
 
+  // An AVDataOutput specialized for taking pictures out of |captureSession_|.
+  base::scoped_nsobject<CrAVCaptureStillImageOutput> stillImageOutput_;
+
   base::ThreadChecker main_thread_checker_;
 }
 
@@ -114,6 +118,10 @@
 // Stops video capturing and stops listening to notifications.
 - (void)stopCapture;
 
+// Takes a photo. This method should only be called between -startCapture and
+// -stopCapture.
+- (void)takePhoto;
+
 @end
 
 #endif  // MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
index 0f89a031..c47ff9c4 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -95,8 +95,6 @@
   }
 }
 
-}  // anonymous namespace
-
 // This function translates Mac Core Video pixel formats to Chromium pixel
 // formats.
 media::VideoPixelFormat FourCCToChromiumPixelFormat(FourCharCode code) {
@@ -112,6 +110,26 @@
   }
 }
 
+// Extracts |base_address| and |length| out of a SampleBuffer.
+void ExtractBaseAddressAndLength(
+    char** base_address,
+    size_t* length,
+    CoreMediaGlue::CMSampleBufferRef sample_buffer) {
+  CoreMediaGlue::CMBlockBufferRef block_buffer =
+      CoreMediaGlue::CMSampleBufferGetDataBuffer(sample_buffer);
+  DCHECK(block_buffer);
+
+  size_t length_at_offset;
+  const OSStatus status = CoreMediaGlue::CMBlockBufferGetDataPointer(
+      block_buffer, 0, &length_at_offset, length, base_address);
+  DCHECK_EQ(noErr, status);
+  // Expect the (M)JPEG data to be available as a contiguous reference, i.e.
+  // not covered by multiple memory blocks.
+  DCHECK_EQ(length_at_offset, *length);
+}
+
+}  // anonymous namespace
+
 @implementation VideoCaptureDeviceAVFoundation
 
 #pragma mark Class methods
@@ -217,6 +235,8 @@
       // No need to release |captureDeviceInput_|, is owned by the session.
       captureDeviceInput_ = nil;
     }
+    if (stillImageOutput_)
+      [captureSession_ removeOutput:stillImageOutput_];
     return YES;
   }
 
@@ -261,6 +281,13 @@
                         queue:dispatch_get_global_queue(
                                   DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
   [captureSession_ addOutput:captureVideoDataOutput_];
+
+  // Create and plug the still image capture output. This should happen in
+  // advance of the actual picture to allow for the 3A to stabilize.
+  stillImageOutput_.reset(
+      [[AVFoundationGlue::AVCaptureStillImageOutputClass() alloc] init]);
+  [captureSession_ addOutput:stillImageOutput_];
+
   return YES;
 }
 
@@ -359,6 +386,48 @@
   [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
+- (void)takePhoto {
+  DCHECK(main_thread_checker_.CalledOnValidThread());
+  DCHECK([captureSession_ isRunning]);
+
+  DCHECK_EQ(1u, [[stillImageOutput_ connections] count]);
+  CrAVCaptureConnection* const connection =
+      [[stillImageOutput_ connections] firstObject];
+  if (!connection) {
+    base::AutoLock lock(lock_);
+    frameReceiver_->OnPhotoError();
+    return;
+  }
+
+  const auto handler = ^(CoreMediaGlue::CMSampleBufferRef sampleBuffer,
+                         NSError* error) {
+    base::AutoLock lock(lock_);
+    if (!frameReceiver_)
+      return;
+    if (error != nil) {
+      frameReceiver_->OnPhotoError();
+      return;
+    }
+
+    // Recommended compressed pixel format is JPEG, we don't expect surprises.
+    // TODO(mcasas): Consider using [1] for merging EXIF output information:
+    // [1] +(NSData*)jpegStillImageNSDataRepresentation:jpegSampleBuffer;
+    DCHECK_EQ(
+        CoreMediaGlue::kCMVideoCodecType_JPEG,
+        CoreMediaGlue::CMFormatDescriptionGetMediaSubType(
+            CoreMediaGlue::CMSampleBufferGetFormatDescription(sampleBuffer)));
+
+    char* baseAddress = 0;
+    size_t length = 0;
+    ExtractBaseAddressAndLength(&baseAddress, &length, sampleBuffer);
+    frameReceiver_->OnPhotoTaken(reinterpret_cast<uint8_t*>(baseAddress),
+                                 length, "image/jpeg");
+  };
+
+  [stillImageOutput_ captureStillImageAsynchronouslyFromConnection:connection
+                                                 completionHandler:handler];
+}
+
 #pragma mark Private methods
 
 // |captureOutput| is called by the capture device to deliver a new frame.
@@ -381,17 +450,7 @@
   size_t frameSize = 0;
   CVImageBufferRef videoFrame = nil;
   if (fourcc == CoreMediaGlue::kCMVideoCodecType_JPEG_OpenDML) {
-    // If MJPEG, use block buffer instead of pixel buffer.
-    CoreMediaGlue::CMBlockBufferRef blockBuffer =
-        CoreMediaGlue::CMSampleBufferGetDataBuffer(sampleBuffer);
-    if (blockBuffer) {
-      size_t lengthAtOffset;
-      CoreMediaGlue::CMBlockBufferGetDataPointer(
-          blockBuffer, 0, &lengthAtOffset, &frameSize, &baseAddress);
-      // Expect the MJPEG data to be available as a contiguous reference, i.e.
-      // not covered by multiple memory blocks.
-      CHECK_EQ(lengthAtOffset, frameSize);
-    }
+    ExtractBaseAddressAndLength(&baseAddress, &frameSize, sampleBuffer);
   } else {
     videoFrame = CoreMediaGlue::CMSampleBufferGetImageBuffer(sampleBuffer);
     // Lock the frame and calculate frame size.
diff --git a/media/capture/video/mac/video_capture_device_mac.h b/media/capture/video/mac/video_capture_device_mac.h
index 88b986b..7eff128 100644
--- a/media/capture/video/mac/video_capture_device_mac.h
+++ b/media/capture/video/mac/video_capture_device_mac.h
@@ -62,10 +62,12 @@
       const VideoCaptureParams& params,
       std::unique_ptr<VideoCaptureDevice::Client> client) override;
   void StopAndDeAllocate() override;
+  void TakePhoto(TakePhotoCallback callback) override;
 
   bool Init(VideoCaptureDevice::Name::CaptureApiType capture_api_type);
 
-  // Called to deliver captured video frames.
+  // Called to deliver captured video frames.  It's safe to call this method
+  // from any thread, including those controlled by AVFoundation.
   void ReceiveFrame(const uint8_t* video_frame,
                     int video_frame_length,
                     const VideoCaptureFormat& frame_format,
@@ -73,6 +75,13 @@
                     int aspect_denominator,
                     base::TimeDelta timestamp);
 
+  // Callbacks with the result of a still image capture, or in case of error,
+  // respectively. It's safe to call these methods from any thread.
+  void OnPhotoTaken(const uint8_t* image_data,
+                    size_t image_length,
+                    const std::string& mime_type);
+  void OnPhotoError();
+
   // Forwarder to VideoCaptureDevice::Client::OnError().
   void ReceiveError(const tracked_objects::Location& from_here,
                     const std::string& reason);
@@ -99,6 +108,9 @@
 
   base::scoped_nsobject<VideoCaptureDeviceAVFoundation> capture_device_;
 
+  // To hold on to the TakePhotoCallback while the picture is being taken.
+  std::unique_ptr<TakePhotoCallback> photo_callback_;
+
   // Used with Bind and PostTask to ensure that methods aren't called after the
   // VideoCaptureDeviceMac is destroyed.
   // NOTE: Weak pointers must be invalidated before all other member variables.
diff --git a/media/capture/video/mac/video_capture_device_mac.mm b/media/capture/video/mac/video_capture_device_mac.mm
index f032280..6ae6b8c 100644
--- a/media/capture/video/mac/video_capture_device_mac.mm
+++ b/media/capture/video/mac/video_capture_device_mac.mm
@@ -389,6 +389,17 @@
   state_ = kIdle;
 }
 
+void VideoCaptureDeviceMac::TakePhoto(TakePhotoCallback callback) {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  DCHECK(state_ == kCapturing) << state_;
+
+  if (photo_callback_)  // Only one picture can be in flight at a time.
+    return;
+
+  photo_callback_.reset(new TakePhotoCallback(std::move(callback)));
+  [capture_device_ takePhoto];
+}
+
 bool VideoCaptureDeviceMac::Init(
     VideoCaptureDevice::Name::CaptureApiType capture_api_type) {
   DCHECK(task_runner_->BelongsToCurrentThread());
@@ -413,8 +424,6 @@
                                          int aspect_numerator,
                                          int aspect_denominator,
                                          base::TimeDelta timestamp) {
-  // This method is safe to call from a device capture thread, i.e. any thread
-  // controlled by AVFoundation.
   if (capture_format_.frame_size != frame_format.frame_size) {
     ReceiveError(FROM_HERE,
                  "Captured resolution " + frame_format.frame_size.ToString() +
@@ -426,6 +435,26 @@
                                   0, base::TimeTicks::Now(), timestamp);
 }
 
+void VideoCaptureDeviceMac::OnPhotoTaken(const uint8_t* image_data,
+                                         size_t image_length,
+                                         const std::string& mime_type) {
+  DCHECK(photo_callback_);
+  if (!image_data || !image_length) {
+    OnPhotoError();
+    return;
+  }
+
+  photo_callback_->Run(mojo::String::From(mime_type),
+                       mojo::Array<uint8_t>(std::vector<uint8_t>(
+                           image_data, image_data + image_length)));
+  photo_callback_.reset();
+}
+
+void VideoCaptureDeviceMac::OnPhotoError() {
+  DLOG(ERROR) << __FUNCTION__ << " error taking picture";
+  photo_callback_.reset();
+}
+
 void VideoCaptureDeviceMac::ReceiveError(
     const tracked_objects::Location& from_here,
     const std::string& reason) {
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index 0ea3fb9..e71fb71 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "media/base/bind_to_current_loop.h"
 #include "media/base/video_capture_types.h"
 #include "media/capture/video/video_capture_device_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -45,9 +46,11 @@
 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize
 // We will always get YUYV from the Mac AVFoundation implementations.
 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg
+#define MAYBE_TakePhoto TakePhoto
 #elif defined(OS_WIN)
 #define MAYBE_AllocateBadSize AllocateBadSize
 #define MAYBE_CaptureMjpeg CaptureMjpeg
+#define MAYBE_TakePhoto DISABLED_TakePhoto
 #elif defined(OS_ANDROID)
 // TODO(wjia): enable those tests on Android.
 // On Android, native camera (JAVA) delivers frames on UI thread which is the
@@ -57,6 +60,7 @@
 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning
 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning
 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg
+#define MAYBE_TakePhoto DISABLED_TakePhoto
 #elif defined(OS_LINUX)
 // AllocateBadSize will hang when a real camera is attached and if more than one
 // test is trying to use the camera (even across processes). Do NOT renable
@@ -64,9 +68,11 @@
 // http://crbug.com/94134 http://crbug.com/137260 http://crbug.com/417824
 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize
 #define MAYBE_CaptureMjpeg CaptureMjpeg
+#define MAYBE_TakePhoto DISABLED_TakePhoto
 #else
 #define MAYBE_AllocateBadSize AllocateBadSize
 #define MAYBE_CaptureMjpeg CaptureMjpeg
+#define MAYBE_TakePhoto DISABLED_TakePhoto
 #endif
 
 using ::testing::_;
@@ -136,6 +142,30 @@
   base::Callback<void(const VideoCaptureFormat&)> frame_cb_;
 };
 
+class MockImageCaptureClient : public base::RefCounted<MockImageCaptureClient> {
+ public:
+  // GMock doesn't support move-only arguments, so we use this forward method.
+  void DoOnPhotoTaken(mojo::String mime_type, mojo::Array<uint8_t> data) {
+    EXPECT_STREQ("image/jpeg", mime_type.storage().c_str());
+    ASSERT_GT(data.size(), 4u);
+    // Check some bytes that univocally identify |data| as a JPEG File.
+    // https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#File_format_structure
+    EXPECT_EQ(0xFF, data[0]);  // First SOI byte
+    EXPECT_EQ(0xD8, data[1]);  // Second SOI byte
+    EXPECT_EQ(0xFF, data[2]);  // First JFIF-APP0 byte
+    EXPECT_EQ(0xE0, data[3]);  // Second JFIF-APP0 byte
+    OnCorrectPhotoTaken();
+  }
+  MOCK_METHOD0(OnCorrectPhotoTaken, void(void));
+  MOCK_METHOD1(
+      OnTakePhotoFailure,
+      void(const base::Callback<void(mojo::String, mojo::Array<uint8_t>)>&));
+
+ private:
+  friend class base::RefCounted<MockImageCaptureClient>;
+  virtual ~MockImageCaptureClient() {}
+};
+
 class DeviceEnumerationListener
     : public base::RefCounted<DeviceEnumerationListener> {
  public:
@@ -163,10 +193,10 @@
         video_capture_client_(new MockVideoCaptureClient(
             base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured,
                        base::Unretained(this)))),
+        device_enumeration_listener_(new DeviceEnumerationListener()),
+        image_capture_client_(new MockImageCaptureClient()),
         video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory(
-            base::ThreadTaskRunnerHandle::Get())) {
-    device_enumeration_listener_ = new DeviceEnumerationListener();
-  }
+            base::ThreadTaskRunnerHandle::Get())) {}
 
   void SetUp() override {
 #if defined(OS_ANDROID)
@@ -255,12 +285,14 @@
   base::win::ScopedCOMInitializer initialize_com_;
 #endif
   std::unique_ptr<VideoCaptureDevice::Names> names_;
-  std::unique_ptr<base::MessageLoop> loop_;
+  const std::unique_ptr<base::MessageLoop> loop_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::unique_ptr<MockVideoCaptureClient> video_capture_client_;
-  scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_;
+  const scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_;
+  const scoped_refptr<MockImageCaptureClient> image_capture_client_;
   VideoCaptureFormat last_format_;
-  std::unique_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_;
+  const std::unique_ptr<VideoCaptureDeviceFactory>
+      video_capture_device_factory_;
 };
 
 // Cause hangs on Windows Debug. http://crbug.com/417824
@@ -325,8 +357,7 @@
   VideoCaptureParams capture_params;
   capture_params.requested_format.frame_size.SetSize(width, height);
   capture_params.requested_format.frame_rate = 30.0f;
-  capture_params.requested_format.pixel_format =
-      PIXEL_FORMAT_I420;
+  capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
   device->AllocateAndStart(capture_params, std::move(video_capture_client_));
   // Get captured video frames.
   WaitForCapturedFrame();
@@ -361,8 +392,7 @@
   VideoCaptureParams capture_params;
   capture_params.requested_format.frame_size.SetSize(637, 472);
   capture_params.requested_format.frame_rate = 35;
-  capture_params.requested_format.pixel_format =
-      PIXEL_FORMAT_I420;
+  capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
   device->AllocateAndStart(capture_params, std::move(video_capture_client_));
   WaitForCapturedFrame();
   device->StopAndDeAllocate();
@@ -484,10 +514,42 @@
   // GetDeviceSupportedFormats().
   std::unique_ptr<VideoCaptureDevice::Name> name =
       GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MAX);
-  // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else
-  // to test here
+  // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else to test here
   // since we cannot forecast the hardware capabilities.
   ASSERT_FALSE(name);
 }
 
+// Start the camera and take a photo.
+TEST_F(VideoCaptureDeviceTest, MAYBE_TakePhoto) {
+  names_ = EnumerateDevices();
+  if (names_->empty()) {
+    VLOG(1) << "No camera available. Exiting test.";
+    return;
+  }
+  std::unique_ptr<VideoCaptureDevice> device(
+      video_capture_device_factory_->Create(names_->front()));
+  ASSERT_TRUE(device);
+
+  EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0);
+
+  VideoCaptureParams capture_params;
+  capture_params.requested_format.frame_size.SetSize(640, 480);
+  capture_params.requested_format.frame_rate = 30;
+  capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
+  device->AllocateAndStart(capture_params, std::move(video_capture_client_));
+  WaitForCapturedFrame();
+
+  VideoCaptureDevice::TakePhotoCallback scoped_callback(
+      base::Bind(&MockImageCaptureClient::DoOnPhotoTaken,
+                 image_capture_client_),
+      media::BindToCurrentLoop(base::Bind(
+          &MockImageCaptureClient::OnTakePhotoFailure, image_capture_client_)));
+
+  EXPECT_CALL(*image_capture_client_.get(), OnCorrectPhotoTaken()).Times(1);
+  device->TakePhoto(std::move(scoped_callback));
+  WaitForCapturedFrame();
+
+  device->StopAndDeAllocate();
+}
+
 };  // namespace media
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc
index 2ff9393..75d3fb8a 100644
--- a/media/filters/vpx_video_decoder.cc
+++ b/media/filters/vpx_video_decoder.cc
@@ -44,6 +44,7 @@
 }
 
 #include "third_party/libyuv/include/libyuv/convert.h"
+#include "third_party/libyuv/include/libyuv/planar_functions.h"
 
 namespace media {
 
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 501575ec..e44fff26 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -318,6 +318,16 @@
                                        least_unacked, true);
   }
 
+  std::unique_ptr<QuicEncryptedPacket> ConstructClientAckPacket(
+      QuicPacketNumber packet_number,
+      QuicPacketNumber largest_received,
+      QuicPacketNumber ack_least_unacked,
+      QuicPacketNumber stop_least_unacked) {
+    return client_maker_.MakeAckPacket(packet_number, largest_received,
+                                       ack_least_unacked, stop_least_unacked,
+                                       true);
+  }
+
   std::unique_ptr<QuicEncryptedPacket> ConstructClientAckAndRstPacket(
       QuicPacketNumber num,
       QuicStreamId stream_id,
@@ -330,24 +340,6 @@
         stop_least_unacked, true);
   }
 
-  std::unique_ptr<QuicEncryptedPacket> ConstructClientAckPacket(
-      QuicPacketNumber largest_received,
-      QuicPacketNumber least_unacked,
-      QuicTestPacketMaker* maker) {
-    return client_maker_.MakeAckPacket(2, largest_received, least_unacked,
-                                       least_unacked, true);
-  }
-
-  std::unique_ptr<QuicEncryptedPacket> ConstructClientAckPacket(
-      QuicPacketNumber packet_number,
-      QuicPacketNumber largest_received,
-      QuicPacketNumber ack_least_unacked,
-      QuicPacketNumber stop_least_unacked) {
-    return client_maker_.MakeAckPacket(packet_number, largest_received,
-                                       ack_least_unacked, stop_least_unacked,
-                                       true);
-  }
-
   std::unique_ptr<QuicEncryptedPacket>
   ConstructClientAckAndConnectionClosePacket(
       QuicPacketNumber packet_number,
@@ -458,36 +450,10 @@
       QuicStreamId stream_id,
       bool should_include_version,
       bool fin,
-      SpdyHeaderBlock headers,
-      QuicStreamOffset* offset,
-      QuicTestPacketMaker* maker) {
-    SpdyPriority priority =
-        ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
-    return client_maker_.MakeRequestHeadersPacketWithOffsetTracking(
-        packet_number, stream_id, should_include_version, fin, priority,
-        std::move(headers), offset);
-  }
-
-  std::unique_ptr<QuicEncryptedPacket> ConstructClientRequestHeadersPacket(
-      QuicPacketNumber packet_number,
-      QuicStreamId stream_id,
-      bool should_include_version,
-      bool fin,
       SpdyHeaderBlock headers) {
-    return ConstructClientRequestHeadersPacket(
-        packet_number, stream_id, should_include_version, fin,
-        std::move(headers), nullptr, &client_maker_);
-  }
-  std::unique_ptr<QuicEncryptedPacket> ConstructClientRequestHeadersPacket(
-      QuicPacketNumber packet_number,
-      QuicStreamId stream_id,
-      bool should_include_version,
-      bool fin,
-      SpdyHeaderBlock headers,
-      QuicTestPacketMaker* maker) {
-    return ConstructClientRequestHeadersPacket(
-        packet_number, stream_id, should_include_version, fin,
-        std::move(headers), nullptr, maker);
+    return ConstructClientRequestHeadersPacket(packet_number, stream_id,
+                                               should_include_version, fin,
+                                               std::move(headers), nullptr);
   }
 
   std::unique_ptr<QuicEncryptedPacket> ConstructServerPushPromisePacket(
@@ -509,21 +475,9 @@
       bool should_include_version,
       bool fin,
       SpdyHeaderBlock headers) {
-    return ConstructServerResponseHeadersPacket(
-        packet_number, stream_id, should_include_version, fin,
-        std::move(headers), nullptr, &server_maker_);
-  }
-
-  std::unique_ptr<QuicEncryptedPacket> ConstructServerResponseHeadersPacket(
-      QuicPacketNumber packet_number,
-      QuicStreamId stream_id,
-      bool should_include_version,
-      bool fin,
-      SpdyHeaderBlock headers,
-      QuicTestPacketMaker* maker) {
-    return ConstructServerResponseHeadersPacket(
-        packet_number, stream_id, should_include_version, fin,
-        std::move(headers), nullptr, maker);
+    return ConstructServerResponseHeadersPacket(packet_number, stream_id,
+                                                should_include_version, fin,
+                                                std::move(headers), nullptr);
   }
 
   std::unique_ptr<QuicEncryptedPacket> ConstructServerResponseHeadersPacket(
@@ -538,19 +492,6 @@
         std::move(headers), offset);
   }
 
-  std::unique_ptr<QuicEncryptedPacket> ConstructServerResponseHeadersPacket(
-      QuicPacketNumber packet_number,
-      QuicStreamId stream_id,
-      bool should_include_version,
-      bool fin,
-      SpdyHeaderBlock headers,
-      QuicStreamOffset* offset,
-      QuicTestPacketMaker* maker) {
-    return server_maker_.MakeResponseHeadersPacketWithOffsetTracking(
-        packet_number, stream_id, should_include_version, fin,
-        std::move(headers), offset);
-  }
-
   void CreateSession() {
     params_.enable_quic = true;
     params_.quic_clock = clock_;
@@ -1408,10 +1349,10 @@
   mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
       3, kClientDataStreamId2, false, true,
       GetRequestHeaders("GET", "https", "/", &client_maker2),
-      &request_header_offset, &client_maker2));
+      &request_header_offset));
   mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
       3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"),
-      &response_header_offset, &server_maker2));
+      &response_header_offset));
   mock_quic_data.AddRead(ConstructServerDataPacket(4, kClientDataStreamId2,
                                                    false, true, 0, "hello!"));
   mock_quic_data.AddWrite(
@@ -1516,7 +1457,7 @@
   mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
       3, kClientDataStreamId2, false, true,
       GetRequestHeaders("GET", "https", "/", &client_maker),
-      &request_header_offset, &client_maker));
+      &request_header_offset));
   mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
       3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"),
       &response_header_offset));
diff --git a/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java b/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java
index 3f518a6f..4cbd35ed 100644
--- a/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java
+++ b/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java
@@ -570,6 +570,9 @@
             }
 
             if (!mInputStrategy.isIndirectInputMode()) {
+                if (!mapScreenPointToImage(x, y)) {
+                    return false;
+                }
                 moveCursorToScreenPoint(x, y);
             }
 
@@ -592,6 +595,9 @@
             }
 
             if (!mInputStrategy.isIndirectInputMode()) {
+                if (!mapScreenPointToImage(x, y)) {
+                    return;
+                }
                 moveCursorToScreenPoint(x, y);
             }
 
@@ -619,5 +625,22 @@
                     return InputStub.BUTTON_UNDEFINED;
             }
         }
+
+        /** Verifies the given point maps to a valid location within the desktop image. */
+        private boolean mapScreenPointToImage(float screenX, float screenY) {
+            float[] mappedPoints = {screenX, screenY};
+            int imageWidth;
+            int imageHeight;
+            Matrix screenToImage = new Matrix();
+            synchronized (mRenderData) {
+                mRenderData.transform.invert(screenToImage);
+                imageWidth = mRenderData.imageWidth;
+                imageHeight = mRenderData.imageHeight;
+            }
+            screenToImage.mapPoints(mappedPoints);
+
+            return (mappedPoints[0] >= 0 && mappedPoints[0] <= imageWidth)
+                    && (mappedPoints[1] >= 0 && mappedPoints[1] <= imageHeight);
+        }
     }
 }
diff --git a/remoting/codec/video_decoder_vpx.cc b/remoting/codec/video_decoder_vpx.cc
index 2d59cc6c..07b4dca 100644
--- a/remoting/codec/video_decoder_vpx.cc
+++ b/remoting/codec/video_decoder_vpx.cc
@@ -12,6 +12,7 @@
 #include "remoting/base/util.h"
 #include "remoting/proto/video.pb.h"
 #include "third_party/libyuv/include/libyuv/convert_argb.h"
+#include "third_party/libyuv/include/libyuv/convert_from.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
diff --git a/services/navigation/BUILD.gn b/services/navigation/BUILD.gn
index d719ed4..4d84fa5 100644
--- a/services/navigation/BUILD.gn
+++ b/services/navigation/BUILD.gn
@@ -58,17 +58,12 @@
     "view_impl.h",
   ]
 
-  public_deps = [
+  deps = [
     "//base",
-    "//content/public/common",
-    "//mojo/public/cpp/bindings",
+    "//content/public/browser",
     "//services/navigation/public/interfaces",
     "//services/shell/public/cpp",
     "//services/ui/public/cpp",
-  ]
-
-  deps = [
-    "//content/public/browser",
     "//skia",
     "//ui/gfx/geometry/mojo",
     "//ui/views",
diff --git a/services/navigation/content_client/content_browser_client.cc b/services/navigation/content_client/content_browser_client.cc
index 744a4f3..c59aead 100644
--- a/services/navigation/content_client/content_browser_client.cc
+++ b/services/navigation/content_client/content_browser_client.cc
@@ -36,8 +36,8 @@
 
 void ContentBrowserClient::RegisterInProcessMojoApplications(
     StaticMojoApplicationMap* apps) {
-  content::MojoShellConnection::GetForProcess()->AddConnectionFilter(
-      base::MakeUnique<Navigation>());
+  content::MojoShellConnection::GetForProcess()->MergeService(
+      base::WrapUnique(new Navigation));
 }
 
 }  // namespace navigation
diff --git a/services/navigation/navigation.cc b/services/navigation/navigation.cc
index 3a86644..91e46ce 100644
--- a/services/navigation/navigation.cc
+++ b/services/navigation/navigation.cc
@@ -6,37 +6,24 @@
 
 #include "base/bind.h"
 #include "base/message_loop/message_loop.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "services/navigation/view_impl.h"
-#include "services/shell/public/cpp/connector.h"
 
 namespace navigation {
 
-namespace {
-
-void CreateViewOnViewTaskRunner(
-    std::unique_ptr<shell::Connector> connector,
-    const std::string& client_user_id,
-    mojom::ViewClientPtr client,
-    mojom::ViewRequest request,
-    std::unique_ptr<shell::ServiceContextRef> context_ref) {
-  // Owns itself.
-  new ViewImpl(std::move(connector), client_user_id, std::move(client),
-               std::move(request), std::move(context_ref));
-}
-
-}  // namespace
-
 Navigation::Navigation()
-    : view_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      ref_factory_(base::MessageLoop::QuitWhenIdleClosure()) {
+    : ref_factory_(base::MessageLoop::QuitWhenIdleClosure()) {
   bindings_.set_connection_error_handler(
       base::Bind(&Navigation::ViewFactoryLost, base::Unretained(this)));
 }
 Navigation::~Navigation() {}
 
-bool Navigation::OnConnect(shell::Connection* connection,
-                           shell::Connector* connector) {
+void Navigation::OnStart(shell::Connector* connector,
+                         const shell::Identity& identity,
+                         uint32_t instance_id) {
+  connector_ = connector;
+}
+
+bool Navigation::OnConnect(shell::Connection* connection) {
   std::string remote_user_id = connection->GetRemoteIdentity().user_id();
   if (!client_user_id_.empty() && client_user_id_ != remote_user_id) {
     LOG(ERROR) << "Must have a separate Navigation service instance for "
@@ -57,14 +44,8 @@
 
 void Navigation::CreateView(mojom::ViewClientPtr client,
                             mojom::ViewRequest request) {
-  std::unique_ptr<shell::Connector> new_connector = connector_->Clone();
-  std::unique_ptr<shell::ServiceContextRef> context_ref =
-      ref_factory_.CreateRef();
-  view_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&CreateViewOnViewTaskRunner, base::Passed(&new_connector),
-                 client_user_id_, base::Passed(&client), base::Passed(&request),
-                 base::Passed(&context_ref)));
+  new ViewImpl(connector_, client_user_id_, std::move(client),
+               std::move(request), ref_factory_.CreateRef());
 }
 
 void Navigation::ViewFactoryLost() {
diff --git a/services/navigation/navigation.h b/services/navigation/navigation.h
index ded2c7db..3a731dd6 100644
--- a/services/navigation/navigation.h
+++ b/services/navigation/navigation.h
@@ -5,9 +5,6 @@
 #ifndef SERVICES_NAVIGATION_NAVIGATION_H_
 #define SERVICES_NAVIGATION_NAVIGATION_H_
 
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "content/public/common/connection_filter.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/navigation/public/interfaces/view.mojom.h"
 #include "services/shell/public/cpp/interface_factory.h"
@@ -20,7 +17,7 @@
 
 namespace navigation {
 
-class Navigation : public content::ConnectionFilter,
+class Navigation : public shell::Service,
                    public shell::InterfaceFactory<mojom::ViewFactory>,
                    public mojom::ViewFactory {
  public:
@@ -28,9 +25,11 @@
   ~Navigation() override;
 
  private:
-  // content::ConnectionFilter:
-  bool OnConnect(shell::Connection* connection,
-                 shell::Connector* connector) override;
+  // shell::Service:
+  void OnStart(shell::Connector* connector,
+               const shell::Identity& identity,
+               uint32_t instance_id) override;
+  bool OnConnect(shell::Connection* connection) override;
 
   // shell::InterfaceFactory<mojom::ViewFactory>:
   void Create(shell::Connection* connection,
@@ -42,8 +41,6 @@
 
   void ViewFactoryLost();
 
-  scoped_refptr<base::SequencedTaskRunner> view_task_runner_;
-
   shell::Connector* connector_ = nullptr;
   std::string client_user_id_;
 
diff --git a/services/navigation/view_impl.cc b/services/navigation/view_impl.cc
index 9a85fec0..6bb54cf85 100644
--- a/services/navigation/view_impl.cc
+++ b/services/navigation/view_impl.cc
@@ -15,7 +15,6 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
-#include "services/shell/public/cpp/connector.h"
 #include "services/ui/public/cpp/window_tree_client.h"
 #include "ui/views/controls/webview/webview.h"
 #include "ui/views/mus/native_widget_mus.h"
@@ -57,12 +56,12 @@
 
 }  // namespace
 
-ViewImpl::ViewImpl(std::unique_ptr<shell::Connector> connector,
+ViewImpl::ViewImpl(shell::Connector* connector,
                    const std::string& client_user_id,
                    mojom::ViewClientPtr client,
                    mojom::ViewRequest request,
                    std::unique_ptr<shell::ServiceContextRef> ref)
-    : connector_(std::move(connector)),
+    : connector_(connector),
       binding_(this, std::move(request)),
       client_(std::move(client)),
       ref_(std::move(ref)),
@@ -149,9 +148,8 @@
   const std::string new_user_id =
       content::BrowserContext::GetShellUserIdFor(
           new_contents->GetBrowserContext());
-  ViewImpl* impl = new ViewImpl(
-      connector_->Clone(), new_user_id, std::move(client),
-      std::move(view_request), ref_->Clone());
+  ViewImpl* impl = new ViewImpl(connector_, new_user_id, std::move(client),
+                                std::move(view_request), ref_->Clone());
   // TODO(beng): This is a bit crappy. should be able to create the ViewImpl
   //             with |new_contents| instead.
   impl->web_view_->SetWebContents(new_contents);
@@ -274,7 +272,7 @@
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.delegate = this;
   params.native_widget = new views::NativeWidgetMus(
-      widget_.get(), connector_.get(), root, ui::mojom::SurfaceType::DEFAULT);
+      widget_.get(), connector_, root, ui::mojom::SurfaceType::DEFAULT);
   widget_->Init(params);
   widget_->Show();
 }
diff --git a/services/navigation/view_impl.h b/services/navigation/view_impl.h
index ad9b7edc..427afa1 100644
--- a/services/navigation/view_impl.h
+++ b/services/navigation/view_impl.h
@@ -5,8 +5,6 @@
 #ifndef SERVICES_NAVIGATION_VIEW_IMPL_H_
 #define SERVICES_NAVIGATION_VIEW_IMPL_H_
 
-#include <memory>
-
 #include "base/macros.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -34,7 +32,7 @@
                  public ui::WindowTreeClientDelegate,
                  public views::WidgetDelegate {
  public:
-  ViewImpl(std::unique_ptr<shell::Connector> connector,
+  ViewImpl(shell::Connector* connector,
            const std::string& client_user_id,
            mojom::ViewClientPtr client,
            mojom::ViewRequest request,
@@ -89,7 +87,7 @@
   views::Widget* GetWidget() override;
   const views::Widget* GetWidget() const override;
 
-  std::unique_ptr<shell::Connector> connector_;
+  shell::Connector* connector_;
   mojo::StrongBinding<mojom::View> binding_;
   mojom::ViewClientPtr client_;
   std::unique_ptr<shell::ServiceContextRef> ref_;
diff --git a/services/shell/public/cpp/connection.h b/services/shell/public/cpp/connection.h
index 1c78c7a1..eb49c2c8 100644
--- a/services/shell/public/cpp/connection.h
+++ b/services/shell/public/cpp/connection.h
@@ -37,7 +37,8 @@
 // interface_registry.h for more information.
 //
 // A Connection returned via Shell::ConnectToApplication() is owned by the
-// caller. A Connection received via OnConnect is owned by the ServiceContext.
+// caller.
+// An Connection received via OnConnect is owned by the ServiceContext.
 // To close a connection, call CloseConnection which will destroy this object.
 class Connection {
  public:
diff --git a/services/shell/public/cpp/connector.h b/services/shell/public/cpp/connector.h
index dfc440b..2f26e4c 100644
--- a/services/shell/public/cpp/connector.h
+++ b/services/shell/public/cpp/connector.h
@@ -72,10 +72,6 @@
     DISALLOW_COPY_AND_ASSIGN(ConnectParams);
   };
 
-  // Creates a new Connector instance and fills in |*request| with a request
-  // for the other end the Connector's interface.
-  static std::unique_ptr<Connector> Create(mojom::ConnectorRequest* request);
-
   // Requests a new connection to an application. Returns a pointer to the
   // connection if the connection is permitted by this application's delegate,
   // or nullptr otherwise. Caller takes ownership.
diff --git a/services/shell/public/cpp/interface_provider.h b/services/shell/public/cpp/interface_provider.h
index 865ab8b..fe6930e 100644
--- a/services/shell/public/cpp/interface_provider.h
+++ b/services/shell/public/cpp/interface_provider.h
@@ -18,8 +18,6 @@
 // Connection.
 class InterfaceProvider {
  public:
-  using ForwardCallback = base::Callback<void(const mojo::String&,
-                                              mojo::ScopedMessagePipeHandle)>;
   class TestApi {
    public:
     explicit TestApi(InterfaceProvider* provider) : provider_(provider) {}
@@ -43,17 +41,8 @@
   InterfaceProvider();
   ~InterfaceProvider();
 
-  // Binds this InterfaceProvider to an actual mojom::InterfaceProvider pipe.
-  // It is an error to call this on a forwarding InterfaceProvider, i.e. this
-  // call is exclusive to Forward().
   void Bind(mojom::InterfaceProviderPtr interface_provider);
 
-  // Sets this InterfaceProvider to forward all GetInterface() requests to
-  // |callback|. It is an error to call this on a bound InterfaceProvider, i.e.
-  // this call is exclusive to Bind(). In addition, and unlike Bind(), this MUST
-  // be called before any calls to GetInterface() are made.
-  void Forward(const ForwardCallback& callback);
-
   // Returns a raw pointer to the remote InterfaceProvider.
   mojom::InterfaceProvider* get() { return interface_provider_.get(); }
 
@@ -94,10 +83,6 @@
   mojom::InterfaceProviderPtr interface_provider_;
   mojom::InterfaceProviderRequest pending_request_;
 
-  // A callback to receive all GetInterface() requests in lieu of the
-  // InterfaceProvider pipe.
-  ForwardCallback forward_callback_;
-
   base::WeakPtrFactory<InterfaceProvider> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(InterfaceProvider);
diff --git a/services/shell/public/cpp/interface_registry.h b/services/shell/public/cpp/interface_registry.h
index 0c6624e..98f85550 100644
--- a/services/shell/public/cpp/interface_registry.h
+++ b/services/shell/public/cpp/interface_registry.h
@@ -6,10 +6,7 @@
 #define SERVICES_SHELL_PUBLIC_CPP_INTERFACE_REGISTRY_H_
 
 #include <memory>
-#include <queue>
-#include <utility>
 
-#include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/shell/public/cpp/lib/callback_binder.h"
@@ -43,9 +40,6 @@
 //
 class InterfaceRegistry : public mojom::InterfaceProvider {
  public:
-  using Binder = base::Callback<void(const mojo::String&,
-                                     mojo::ScopedMessagePipeHandle)>;
-
   class TestApi {
    public:
     explicit TestApi(InterfaceRegistry* registry) : registry_(registry) {}
@@ -70,10 +64,6 @@
   explicit InterfaceRegistry(Connection* connection);
   ~InterfaceRegistry() override;
 
-  // Sets a default handler for incoming interface requests which are allowed by
-  // capability filters but have no registered handler in this registry.
-  void set_default_binder(const Binder& binder) { default_binder_ = binder; }
-
   void Bind(mojom::InterfaceProviderRequest local_interfaces_request);
 
   base::WeakPtr<InterfaceRegistry> GetWeakPtr();
@@ -142,15 +132,6 @@
 
   NameToInterfaceBinderMap name_to_binder_;
 
-  Binder default_binder_;
-
-  bool is_paused_ = false;
-
-  // Pending interface requests which can accumulate if GetInterface() is called
-  // while binding is paused.
-  std::queue<std::pair<mojo::String, mojo::ScopedMessagePipeHandle>>
-      pending_interface_requests_;
-
   base::WeakPtrFactory<InterfaceRegistry> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(InterfaceRegistry);
diff --git a/services/shell/public/cpp/lib/connector_impl.cc b/services/shell/public/cpp/lib/connector_impl.cc
index 84af886..73c6723e 100644
--- a/services/shell/public/cpp/lib/connector_impl.cc
+++ b/services/shell/public/cpp/lib/connector_impl.cc
@@ -19,12 +19,11 @@
 Connector::ConnectParams::~ConnectParams() {}
 
 ConnectorImpl::ConnectorImpl(mojom::ConnectorPtrInfo unbound_state)
-    : unbound_state_(std::move(unbound_state)) {
-  thread_checker_.DetachFromThread();
-}
+    : unbound_state_(std::move(unbound_state)) {}
 
 ConnectorImpl::ConnectorImpl(mojom::ConnectorPtr connector)
     : connector_(std::move(connector)) {
+  thread_checker_.reset(new base::ThreadChecker);
   connector_.set_connection_error_handler(
       base::Bind(&ConnectorImpl::OnConnectionError, base::Unretained(this)));
 }
@@ -32,7 +31,7 @@
 ConnectorImpl::~ConnectorImpl() {}
 
 void ConnectorImpl::OnConnectionError() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(thread_checker_->CalledOnValidThread());
   connector_.reset();
 }
 
@@ -42,12 +41,23 @@
 }
 
 std::unique_ptr<Connection> ConnectorImpl::Connect(ConnectParams* params) {
-  if (!BindIfNecessary())
-    return nullptr;
+  // Bind this object to the current thread the first time it is used to
+  // connect.
+  if (!connector_.is_bound()) {
+    if (!unbound_state_.is_valid()) {
+      // It's possible to get here when the link to the shell has been severed
+      // (and so the connector pipe has been closed) but the app has chosen not
+      // to quit.
+      return nullptr;
+    }
+    connector_.Bind(std::move(unbound_state_));
+    connector_.set_connection_error_handler(
+        base::Bind(&ConnectorImpl::OnConnectionError, base::Unretained(this)));
+    thread_checker_.reset(new base::ThreadChecker);
+  }
+  DCHECK(thread_checker_->CalledOnValidThread());
 
-  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(params);
-
   // We allow all interfaces on outgoing connections since we are presumably in
   // a position to know who we're talking to.
   CapabilityRequest request;
@@ -102,41 +112,9 @@
 }
 
 std::unique_ptr<Connector> ConnectorImpl::Clone() {
-  if (!BindIfNecessary())
-    return nullptr;
-
   mojom::ConnectorPtr connector;
-  mojom::ConnectorRequest request = GetProxy(&connector);
-  connector_->Clone(std::move(request));
-  return base::MakeUnique<ConnectorImpl>(connector.PassInterface());
-}
-
-bool ConnectorImpl::BindIfNecessary() {
-  // Bind this object to the current thread the first time it is used to
-  // connect.
-  if (!connector_.is_bound()) {
-    if (!unbound_state_.is_valid()) {
-      // It's possible to get here when the link to the shell has been severed
-      // (and so the connector pipe has been closed) but the app has chosen not
-      // to quit.
-      return false;
-    }
-
-    // Bind the ThreadChecker to this thread.
-    DCHECK(thread_checker_.CalledOnValidThread());
-
-    connector_.Bind(std::move(unbound_state_));
-    connector_.set_connection_error_handler(
-        base::Bind(&ConnectorImpl::OnConnectionError, base::Unretained(this)));
-  }
-
-  return true;
-}
-
-std::unique_ptr<Connector> Connector::Create(mojom::ConnectorRequest* request) {
-  mojom::ConnectorPtr proxy;
-  *request = mojo::GetProxy(&proxy);
-  return base::MakeUnique<ConnectorImpl>(proxy.PassInterface());
+  connector_->Clone(GetProxy(&connector));
+  return base::WrapUnique(new ConnectorImpl(connector.PassInterface()));
 }
 
 }  // namespace shell
diff --git a/services/shell/public/cpp/lib/connector_impl.h b/services/shell/public/cpp/lib/connector_impl.h
index 003e3fd..9ab5bebe 100644
--- a/services/shell/public/cpp/lib/connector_impl.h
+++ b/services/shell/public/cpp/lib/connector_impl.h
@@ -28,12 +28,10 @@
   std::unique_ptr<Connection> Connect(ConnectParams* params) override;
   std::unique_ptr<Connector> Clone() override;
 
-  bool BindIfNecessary();
-
   mojom::ConnectorPtrInfo unbound_state_;
   mojom::ConnectorPtr connector_;
 
-  base::ThreadChecker thread_checker_;
+  std::unique_ptr<base::ThreadChecker> thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(ConnectorImpl);
 };
diff --git a/services/shell/public/cpp/lib/interface_provider.cc b/services/shell/public/cpp/lib/interface_provider.cc
index 0934ee15..209d356 100644
--- a/services/shell/public/cpp/lib/interface_provider.cc
+++ b/services/shell/public/cpp/lib/interface_provider.cc
@@ -4,32 +4,19 @@
 
 #include "services/shell/public/cpp/interface_provider.h"
 
-#include "base/macros.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
 namespace shell {
 
 InterfaceProvider::InterfaceProvider() : weak_factory_(this) {
   pending_request_ = GetProxy(&interface_provider_);
 }
-
 InterfaceProvider::~InterfaceProvider() {}
 
 void InterfaceProvider::Bind(mojom::InterfaceProviderPtr interface_provider) {
   DCHECK(pending_request_.is_pending());
-  DCHECK(forward_callback_.is_null());
   mojo::FuseInterface(std::move(pending_request_),
                       interface_provider.PassInterface());
 }
 
-void InterfaceProvider::Forward(const ForwardCallback& callback) {
-  DCHECK(pending_request_.is_pending());
-  DCHECK(forward_callback_.is_null());
-  interface_provider_.reset();
-  pending_request_.PassMessagePipe().reset();
-  forward_callback_ = callback;
-}
-
 void InterfaceProvider::SetConnectionLostClosure(
     const base::Closure& connection_lost_closure) {
   interface_provider_.set_connection_error_handler(connection_lost_closure);
@@ -48,14 +35,7 @@
     it->second.Run(std::move(request_handle));
     return;
   }
-
-  if (!forward_callback_.is_null()) {
-    DCHECK(!interface_provider_.is_bound());
-    forward_callback_.Run(name, std::move(request_handle));
-  } else {
-    DCHECK(interface_provider_.is_bound());
-    interface_provider_->GetInterface(name, std::move(request_handle));
-  }
+  interface_provider_->GetInterface(name, std::move(request_handle));
 }
 
 void InterfaceProvider::ClearBinders() {
diff --git a/services/shell/public/cpp/lib/interface_registry.cc b/services/shell/public/cpp/lib/interface_registry.cc
index b585eae..ebfaddd 100644
--- a/services/shell/public/cpp/lib/interface_registry.cc
+++ b/services/shell/public/cpp/lib/interface_registry.cc
@@ -39,29 +39,20 @@
 }
 
 void InterfaceRegistry::PauseBinding() {
-  DCHECK(!is_paused_);
-  is_paused_ = true;
+  DCHECK(!pending_request_.is_pending());
+  DCHECK(binding_.is_bound());
+  pending_request_ = binding_.Unbind();
 }
 
 void InterfaceRegistry::ResumeBinding() {
-  DCHECK(is_paused_);
-  is_paused_ = false;
-
-  while (!pending_interface_requests_.empty()) {
-    auto& request = pending_interface_requests_.front();
-    GetInterface(request.first, std::move(request.second));
-    pending_interface_requests_.pop();
-  }
+  DCHECK(pending_request_.is_pending());
+  DCHECK(!binding_.is_bound());
+  binding_.Bind(std::move(pending_request_));
 }
 
 // mojom::InterfaceProvider:
 void InterfaceRegistry::GetInterface(const mojo::String& interface_name,
                                      mojo::ScopedMessagePipeHandle handle) {
-  if (is_paused_) {
-    pending_interface_requests_.emplace(interface_name, std::move(handle));
-    return;
-  }
-
   auto iter = name_to_binder_.find(interface_name);
   if (iter != name_to_binder_.end()) {
     iter->second->BindInterface(connection_, interface_name, std::move(handle));
@@ -70,8 +61,6 @@
                << "interface: " << interface_name << " connection_name:"
                << connection_->GetConnectionName() << " remote_name:"
                << connection_->GetRemoteIdentity().name();
-  } else if (!default_binder_.is_null()) {
-    default_binder_.Run(interface_name, std::move(handle));
   }
 }
 
diff --git a/services/shell/public/cpp/lib/service_context.cc b/services/shell/public/cpp/lib/service_context.cc
index 1a9cd42..e5458dd 100644
--- a/services/shell/public/cpp/lib/service_context.cc
+++ b/services/shell/public/cpp/lib/service_context.cc
@@ -10,6 +10,7 @@
 #include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/shell/public/cpp/capabilities.h"
+#include "services/shell/public/cpp/connector.h"
 #include "services/shell/public/cpp/lib/connection_impl.h"
 #include "services/shell/public/cpp/lib/connector_impl.h"
 #include "services/shell/public/cpp/service.h"
@@ -19,24 +20,29 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ServiceContext, public:
 
-ServiceContext::ServiceContext(shell::Service* service,
-                               mojom::ServiceRequest request,
-                               std::unique_ptr<Connector> connector,
-                               mojom::ConnectorRequest connector_request)
-    : pending_connector_request_(std::move(connector_request)),
-      service_(service),
-      binding_(this, std::move(request)),
-      connector_(std::move(connector)) {
-  DCHECK(binding_.is_bound());
-  if (!connector_) {
-    connector_ = Connector::Create(&pending_connector_request_);
-  } else {
-    DCHECK(pending_connector_request_.is_pending());
-  }
+ServiceContext::ServiceContext(shell::Service* client,
+                               mojom::ServiceRequest request)
+    : client_(client), binding_(this) {
+  mojom::ConnectorPtr connector;
+  pending_connector_request_ = GetProxy(&connector);
+  connector_.reset(new ConnectorImpl(std::move(connector)));
+
+  DCHECK(request.is_pending());
+  binding_.Bind(std::move(request));
 }
 
 ServiceContext::~ServiceContext() {}
 
+void ServiceContext::set_initialize_handler(const base::Closure& callback) {
+  initialize_handler_ = callback;
+}
+
+void ServiceContext::SetAppTestConnectorForTesting(
+    mojom::ConnectorPtr connector) {
+  pending_connector_request_ = nullptr;
+  connector_.reset(new ConnectorImpl(std::move(connector)));
+}
+
 void ServiceContext::SetConnectionLostClosure(const base::Closure& closure) {
   connection_lost_closure_ = closure;
   if (should_run_connection_lost_closure_ &&
@@ -60,7 +66,7 @@
   binding_.set_connection_error_handler(
       base::Bind(&ServiceContext::OnConnectionError, base::Unretained(this)));
 
-  service_->OnStart(connector_.get(), identity_, id);
+  client_->OnStart(connector_.get(), identity_, id);
 }
 
 void ServiceContext::OnConnect(
@@ -75,16 +81,29 @@
                                    allowed_capabilities.To<CapabilityRequest>(),
                                    Connection::State::CONNECTED));
 
-  std::unique_ptr<InterfaceRegistry> exposed_interfaces(
-      new InterfaceRegistry(registry.get()));
-  exposed_interfaces->Bind(std::move(local_interfaces));
-  registry->SetExposedInterfaces(std::move(exposed_interfaces));
+  InterfaceRegistry* exposed_interfaces =
+      client_->GetInterfaceRegistryForConnection();
+  if (exposed_interfaces) {
+    exposed_interfaces->Bind(std::move(local_interfaces));
+    registry->set_exposed_interfaces(exposed_interfaces);
+  } else {
+    std::unique_ptr<InterfaceRegistry> interfaces(
+        new InterfaceRegistry(registry.get()));
+    interfaces->Bind(std::move(local_interfaces));
+    registry->SetExposedInterfaces(std::move(interfaces));
+  }
+  shell::InterfaceProvider* remote_interface_provider =
+    client_->GetInterfaceProviderForConnection();
+  if (remote_interface_provider) {
+    remote_interface_provider->Bind(std::move(remote_interfaces));
+    registry->set_remote_interfaces(remote_interface_provider);
+  } else {
+    std::unique_ptr<InterfaceProvider> interfaces(new InterfaceProvider);
+    interfaces->Bind(std::move(remote_interfaces));
+    registry->SetRemoteInterfaces(std::move(interfaces));
+  }
 
-  std::unique_ptr<InterfaceProvider> interfaces(new InterfaceProvider);
-  interfaces->Bind(std::move(remote_interfaces));
-  registry->SetRemoteInterfaces(std::move(interfaces));
-
-  if (!service_->OnConnect(registry.get()))
+  if (!client_->OnConnect(registry.get()))
     return;
 
   // TODO(beng): it appears we never prune this list. We should, when the
@@ -99,7 +118,7 @@
   // Note that the Service doesn't technically have to quit now, it may live
   // on to service existing connections. All existing Connectors however are
   // invalid.
-  should_run_connection_lost_closure_ = service_->OnStop();
+  should_run_connection_lost_closure_ = client_->OnStop();
   if (should_run_connection_lost_closure_ &&
       !connection_lost_closure_.is_null())
     connection_lost_closure_.Run();
diff --git a/services/shell/public/cpp/service_context.h b/services/shell/public/cpp/service_context.h
index 504efd0f..2cad395 100644
--- a/services/shell/public/cpp/service_context.h
+++ b/services/shell/public/cpp/service_context.h
@@ -11,15 +11,17 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/memory/scoped_vector.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/core.h"
-#include "services/shell/public/cpp/connector.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/shell/public/interfaces/connector.mojom.h"
 #include "services/shell/public/interfaces/service.mojom.h"
 
 namespace shell {
 
+class Connector;
+
 // Encapsulates a connection to the Service Manager in two parts:
 // - a bound InterfacePtr to mojom::Connector, the primary mechanism
 //   by which the instantiating service connects to other services,
@@ -43,20 +45,22 @@
  public:
   // Creates a new ServiceContext bound to |request|. This connection may be
   // used immediately to make outgoing connections via connector().  Does not
-  // take ownership of |service|, which must remain valid for the lifetime of
-  // ServiceContext. If either |connector| or |connector_request| is non-null
-  // both must be non-null. If both are null, the connection will create its own
-  // Connector and request to pass to the Service Manager on initialization.
-  ServiceContext(shell::Service* service,
-                 mojom::ServiceRequest request,
-                 std::unique_ptr<Connector> connector = nullptr,
-                 mojom::ConnectorRequest connector_request = nullptr);
+  // take ownership of |client|, which must remain valid for the lifetime of
+  // ServiceContext.
+  ServiceContext(shell::Service* client,
+                 mojom::ServiceRequest request);
 
   ~ServiceContext() override;
 
   Connector* connector() { return connector_.get(); }
   const Identity& identity() { return identity_; }
 
+  // TODO(rockot): Remove this. http://crbug.com/594852.
+  void set_initialize_handler(const base::Closure& callback);
+
+  // TODO(rockot): Remove this once we get rid of app tests.
+  void SetAppTestConnectorForTesting(mojom::ConnectorPtr connector);
+
   // Specify a function to be called when the connection to the shell is lost.
   // Note that if connection has already been lost, then |closure| is called
   // immediately.
@@ -81,13 +85,13 @@
 
   // We track the lifetime of incoming connection registries as it more
   // convenient for the client.
-  std::vector<std::unique_ptr<Connection>> incoming_connections_;
+  ScopedVector<Connection> incoming_connections_;
 
   // A pending Connector request which will eventually be passed to the Service
   // Manager.
   mojom::ConnectorRequest pending_connector_request_;
 
-  shell::Service* service_;
+  shell::Service* client_;
   mojo::Binding<mojom::Service> binding_;
   std::unique_ptr<Connector> connector_;
   shell::Identity identity_;
diff --git a/testing/android/native_test/native_test_launcher.cc b/testing/android/native_test/native_test_launcher.cc
index 3b5ee83..aadf06a 100644
--- a/testing/android/native_test/native_test_launcher.cc
+++ b/testing/android/native_test/native_test_launcher.cc
@@ -50,7 +50,7 @@
 // This function runs in a compromised context. It should not allocate memory.
 void SignalHandler(int sig, siginfo_t* info, void* reserved) {
   // Output the crash marker.
-  write(STDOUT_FILENO, kCrashedMarker, sizeof(kCrashedMarker));
+  write(STDOUT_FILENO, kCrashedMarker, sizeof(kCrashedMarker) - 1);
   g_old_sa[sig].sa_sigaction(sig, info, reserved);
 }
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 471589c..8e76b1d9 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -195,13 +195,34 @@
 # TODO(oshima): Mac Android are currently not supported.
 crbug.com/567837 [ Mac Android ] virtual/scalefactor200withzoom/fast/hidpi/static [ Skip ]
 
-# TODO(oshima): Debug build generates slightly different image for these tests due to different background color.
-#crbug.com/593567 [ Debug ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ Skip ]
-crbug.com/593567 [ Debug ] virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ Skip ]
-crbug.com/593567 virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance.html [ Skip ]
-crbug.com/593567 [ Debug ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ Skip ]
-crbug.com/593567 [ Debug ] virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance.html [ Skip ]
-crbug.com/593567 [ Debug ] virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance.html [ Skip ]
+crbug.com/613414 [ Win ] fast/hidpi/broken-image-icon-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] svg/custom/masking-clipping-hidpi.svg [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] css3/filters/effect-reference-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/hidpi/device-scale-factor-paint.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/hidpi/focus-rings.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] css3/filters/effect-reference-hidpi-hw.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/hidpi/resize-corner-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/hidpi/broken-image-with-size-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] virtual/gpu/fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/sub-pixel/shadows-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] compositing/tiled-layers-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] svg/as-image/image-respects-deviceScaleFactor.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/hidpi/clip-text-in-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/backgrounds/gradient-background-leakage-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/hidpi/gradient-with-scaled-ancestor.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] editing/spelling/grammar-markers-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] editing/spelling/inline-spelling-markers-hidpi.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] editing/spelling/inline-spelling-markers-hidpi-composited.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] fast/hidpi/image-srcset-intrinsic-size-zero.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] svg/filters/filter-source-position.svg [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance.html [ NeedsRebaseline ]
+crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance.html [ NeedsRebaseline ]
 
 # Mac does not support fractional scale factor.
 crbug.com/567837 [ Mac ] virtual/scalefactor150/fast/hidpi/static [ Skip ]
@@ -1312,6 +1333,8 @@
 crbug.com/624019 [ Mac ] bluetooth/notifications/stop-twice.html [ Skip ]
 crbug.com/624019 [ Mac ] bluetooth/notifications/stop-without-starting.html [ Skip ]
 
+crbug.com/626992 paint/invalidation/outline-containing-image-in-non-standard-mode.html [ NeedsRebaseline ]
+
 crbug.com/487344 compositing/video/video-controls-layer-creation.html [ Failure ]
 crbug.com/487344 fast/hidpi/video-controls-in-hidpi.html [ Failure ]
 crbug.com/487344 fast/layers/video-layer.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/element-animate-iterable-keyframes.html b/third_party/WebKit/LayoutTests/animations/element-animate-iterable-keyframes.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/web-animations-api/element-animate-iterable-keyframes.html
rename to third_party/WebKit/LayoutTests/animations/element-animate-iterable-keyframes.html
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/align-absolute-child.html b/third_party/WebKit/LayoutTests/css3/flexbox/align-absolute-child.html
index 345ce2c..cbbc97eb 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/align-absolute-child.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/align-absolute-child.html
@@ -59,7 +59,6 @@
 }
 </style>
 
-<script src="../../resources/js-test.js"></script>
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
 <script src="../../resources/check-layout-th.js"></script>
@@ -145,8 +144,11 @@
 var afterPosition = absolute.getBoundingClientRect();
 
 // Positioned element should not change position when the height of it's parent flexbox is changed.
-for (key in beforePosition)
-    shouldBe('beforePosition[key]', 'afterPosition[key]');
+for (key in beforePosition) {
+    test(function() {
+        assert_equals(beforePosition[key], afterPosition[key]);
+    }, 'position of ' + key);
+}
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button-expected.txt
deleted file mode 100644
index 6c19de14..0000000
--- a/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button-expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-Check if box-orient is working in <button>. See https://bugs.webkit.org/show_bug.cgi?id=25406
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS gebi('default').clientHeight is referenceHorizontalHeight
-PASS gebi('horizontal').clientHeight is referenceHorizontalHeight
-PASS gebi('vertical').clientHeight is referenceVerticalHeight
-PASS gebi('toHorizontal').clientHeight is referenceHorizontalHeight
-PASS gebi('toVertical').clientHeight is referenceVerticalHeight
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button.html b/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button.html
index e580d8c..16771c9 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button.html
@@ -19,10 +19,12 @@
   display: flex;
 }
 </style>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 </head>
 <body>
-<p id="description"></p>
+<p id="description">Check if box-orient is working in &lt;button&gt;. See https://bugs.webkit.org/show_bug.cgi?id=25406</p>
+<div id="log"></p>
 <div id="main">
 <p>
 reference of horizontal button:<br>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get-expected.txt
deleted file mode 100644
index a0d1b61..0000000
--- a/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get-expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Test that setting and getting display: flex and inline-flex works as expected
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Test getting |display| set through CSS
-PASS getComputedStyle(flexboxElement, '').getPropertyValue('display') is 'flex'
-PASS getComputedStyle(inlineFlexboxElement, '').getPropertyValue('display') is 'inline-flex'
-
-Test getting and setting display through JS
-PASS getComputedStyle(element, '').getPropertyValue('display') is 'block'
-PASS getComputedStyle(element, '').getPropertyValue('display') is 'flex'
-PASS getComputedStyle(element, '').getPropertyValue('display') is 'block'
-PASS getComputedStyle(element, '').getPropertyValue('display') is 'inline-flex'
-PASS getComputedStyle(element, '').getPropertyValue('display') is 'flex'
-PASS getComputedStyle(element, '').getPropertyValue('display') is 'inline-flex'
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get.html b/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get.html
index 0daa782..69f47f4a 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get.html
@@ -2,37 +2,41 @@
 <html>
 <head>
 <link href="resources/flexbox.css" rel="stylesheet">
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 </head>
 <body>
+<p>Test that setting and getting display: flex and inline-flex works as expected</p>
+<div id="log"></div>
 <div class="flexbox" id="flexbox"></div>
 <div class="inline-flexbox" id="flexboxInline"></div>
 <script>
-description('Test that setting and getting display: flex and inline-flex works as expected');
 
-debug("Test getting |display| set through CSS");
+test(function() {
 var flexboxElement = document.getElementById("flexbox");
-shouldBe("getComputedStyle(flexboxElement, '').getPropertyValue('display')", "'flex'");
+assert_equals(getComputedStyle(flexboxElement, '').getPropertyValue('display'), 'flex');
 var inlineFlexboxElement = document.getElementById("flexboxInline");
-shouldBe("getComputedStyle(inlineFlexboxElement, '').getPropertyValue('display')", "'inline-flex'");
+assert_equals(getComputedStyle(inlineFlexboxElement, '').getPropertyValue('display'), 'inline-flex');
+}, "Test getting |display| set through CSS");
 
-debug("");
-debug("Test getting and setting display through JS");
+test(function() {
 var element = document.createElement("div");
 document.body.appendChild(element);
-shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'block'");
+assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'block');
 element.style.display = "flex";
-shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'flex'");
+assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'flex');
 
 element = document.createElement("div");
 document.body.appendChild(element);
-shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'block'");
+assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'block');
 element.style.display = "inline-flex";
-shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'inline-flex'");
+assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'inline-flex');
 element.style.display = "-webkit-flex";
-shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'flex'");
+assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'flex');
 element.style.display = "-webkit-inline-flex";
-shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'inline-flex'");
+assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'inline-flex');
+
+}, "Test getting and setting display through JS");
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial-expected.txt
deleted file mode 100644
index 14e54ea1..0000000
--- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Tests that 'initial' is handled correctly for the flex-flow shorthand.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS window.getComputedStyle(test1).flexDirection is "row"
-PASS window.getComputedStyle(test2).flexDirection is "row"
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial.html
index 35c5978..87f9b10 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial.html
@@ -13,15 +13,19 @@
   flex-direction: initial;
 }
 </style>
+<p>Tests that 'initial' is handled correctly for the flex-flow shorthand.</p>
+<div id="log"></div>
 <span id="test1"></span>
 <span id="test2"></span>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <script>
-description("Tests that 'initial' is handled correctly for the flex-flow shorthand.");
 value1 = window.getComputedStyle(test1).flexDirection;
 value2 = window.getComputedStyle(test2).flexDirection;
-shouldBeEqualToString('window.getComputedStyle(test1).flexDirection', 'row');
-shouldBeEqualToString('window.getComputedStyle(test2).flexDirection', 'row');
+test(function() {
+assert_equals(window.getComputedStyle(test1).flexDirection, "row");
+assert_equals(window.getComputedStyle(test2).flexDirection, "row");
+}, "initial value is correct");
 if (window.testRunner)
    testRunner.dumpAsText();
 </script>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flexitem-no-margin-collapsing.html b/third_party/WebKit/LayoutTests/css3/flexbox/flexitem-no-margin-collapsing.html
index 71ee9200..d21f5db 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/flexitem-no-margin-collapsing.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flexitem-no-margin-collapsing.html
@@ -13,7 +13,6 @@
     background-color: blue;
 }
 </style>
-<script src="../../resources/js-test.js"></script>
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
 <script src="../../resources/check-layout-th.js"></script>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash-expected.txt
index 4e8436fe..8b13789 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash-expected.txt
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash-expected.txt
@@ -1,9 +1 @@
-This test passes if it does not crash.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
 
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash.html b/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash.html
index 68be93b4..433e808 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash.html
@@ -1,8 +1,9 @@
 <!DOCTYPE html>
 <html style="display: inline-flex;">
-<script src="../../resources/js-test.js"></script>
 <script>
-description('This test passes if it does not crash.');
+if (window.testRunner)
+    testRunner.dumpAsText();
 </script>
+<title>This test passes if it does not crash.</title>
 <frameset></frameset>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/min-size-auto.html b/third_party/WebKit/LayoutTests/css3/flexbox/min-size-auto.html
index a9c25860..0959549 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/min-size-auto.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/min-size-auto.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <link href="resources/flexbox.css" rel="stylesheet">
 
-<script src="../../resources/js-test.js"></script>
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
 <script src="../../resources/check-layout-th.js"></script>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos-expected.txt
deleted file mode 100644
index 83a9959..0000000
--- a/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-PASS successfullyParsed is true
-
-TEST COMPLETE
-PASS document.querySelector('.overflow-auto').scrollTop is 50
-
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos.html b/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos.html
index 117db77..19ab2df 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos.html
@@ -1,7 +1,8 @@
 <!DOCTYPE html>
 <html>
 <head>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <style>
 div.flexbox {
     display: flex;
@@ -21,12 +22,13 @@
     function runTest() {
         document.querySelector('.overflow-auto').scrollTop = 50;
         document.querySelector('#sidebar').innerHTML = '';
-        shouldBe("document.querySelector('.overflow-auto').scrollTop", "50");
+        assert_equals(document.querySelector('.overflow-auto').scrollTop, 50);
     }
 </script>
 
 </head>
-<body onload="runTest()">
+<body onload="test(runTest, 'Scroll position is correct')">
+<div id=log></div>
 <div class="container flexbox">
     <div class="flex overflow-auto flexbox">
         <div style="height: 400px"></div>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/resources/box-orient-button.js b/third_party/WebKit/LayoutTests/css3/flexbox/resources/box-orient-button.js
index 84f135f..1e4a5eb 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/resources/box-orient-button.js
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/resources/box-orient-button.js
@@ -1,4 +1,3 @@
-description("Check if box-orient is working in &lt;button&gt;. See https://bugs.webkit.org/show_bug.cgi?id=25406");
 
 function setFlexDirection(element, flexDirection) {
     element.style.webkitFlexDirection = flexDirection;
@@ -14,12 +13,8 @@
 
 var referenceHorizontalHeight = gebi("reference_horizontal").clientHeight;
 var referenceVerticalHeight = gebi("reference_vertical").clientHeight;
-shouldBe("gebi('default').clientHeight", "referenceHorizontalHeight");
-shouldBe("gebi('horizontal').clientHeight", "referenceHorizontalHeight");
-shouldBe("gebi('vertical').clientHeight", "referenceVerticalHeight");
-shouldBe("gebi('toHorizontal').clientHeight", "referenceHorizontalHeight");
-shouldBe("gebi('toVertical').clientHeight", "referenceVerticalHeight");
-
-// If we are in DRT, we don't need meaningless messages.
-if (window.testRunner)
-    document.getElementById("main").innerHTML = "";
+test(function() { assert_equals(gebi('default').clientHeight, referenceHorizontalHeight); }, "default height");
+test(function() { assert_equals(gebi('horizontal').clientHeight, referenceHorizontalHeight); }, "horizontal height");
+test(function() { assert_equals(gebi('vertical').clientHeight, referenceVerticalHeight); }, "vertical height");
+test(function() { assert_equals(gebi('toHorizontal').clientHeight, referenceHorizontalHeight); }, "toHorizontal height");
+test(function() { assert_equals(gebi('toVertical').clientHeight, referenceVerticalHeight); }, "toVertical height");
diff --git a/third_party/WebKit/LayoutTests/fullscreen/full-screen-will-change.html b/third_party/WebKit/LayoutTests/fullscreen/full-screen-will-change.html
index 38e68b6..9186be1 100644
--- a/third_party/WebKit/LayoutTests/fullscreen/full-screen-will-change.html
+++ b/third_party/WebKit/LayoutTests/fullscreen/full-screen-will-change.html
@@ -1,26 +1,7 @@
 <!DOCTYPE html>
 <html>
 <style>
-    #bad {
-        position: fixed;
-        top: 0px;
-        left: 0px;
-        background-color: red;
-        width: 100%;
-        height: 100%;
-    }
-
-    #fixed-container {
-        position: fixed;
-        top: 0px;
-        left: 0px;
-        z-index: 0;
-    }
-
-    #fullscreenme {
-        height: 400px;
-        width: 400px;
-        border: 0px;
+    #container {
         will-change: transform;
     }
 </style>
@@ -51,10 +32,8 @@
     window.addEventListener("load", doTest, false);
 </script>
 <body>
-    <!-- when full screening the iframe, bad should not be visible -->
-    <div id="fixed-container">
+    <div id="container">
         <iframe id="fullscreenme" src="resources/green.html"></iframe>
     </div>
-    <div id="bad"></div>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-multiple-attach.html b/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-multiple-attach.html
index 6cc7bdc6..971198a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-multiple-attach.html
+++ b/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-multiple-attach.html
@@ -108,6 +108,25 @@
                   test.done();
               });
           }, 'Test that MediaSource can reattach if closed first');
+
+          mediasource_test(function(test, mediaElement, mediaSource) {
+              assert_equals(mediaSource.readyState, 'open', 'Source open');
+              // Generate two different unique URLs for MediaSource
+              var url1 = URL.createObjectURL(mediaSource);
+              var url2 = URL.createObjectURL(mediaSource);
+              assert_not_equals(url1, url2, 'URLs not unique');
+              // Revoke the first url
+              URL.revokeObjectURL(url1);
+              // And use the second, non-revoked URL to reopen the media source
+              test.expectEvent(mediaSource, 'sourceopen', 'Source reopened');
+              mediaElement.src = url2;
+              assert_equals(mediaSource.readyState, 'closed', 'Source closed');
+              test.waitForExpectedEvents(function()
+              {
+                  assert_equals(mediaSource.readyState, 'open', 'Source opened');
+                  test.done();
+              });
+          }, 'Generate multiple unique URLs via URL.createObjectURL and revoke an URL');
         </script>
     </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation-expected.txt
deleted file mode 100644
index 4675af2..0000000
--- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests that we don't crash when detaching on pause from instrumentation call.
-Paused on the innerHTML assignment: modifyHTML@:7
-
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation.html
deleted file mode 100644
index 47c38d7..0000000
--- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<html>
-<head>
-<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script>
-<script>
-
-function modifyHTML()
-{
-    document.getElementById("divUnderTest").innerHTML = "innerHTML";
-}
-
-function test()
-{
-    InspectorTest.sendCommand("Debugger.enable", {});
-    InspectorTest.sendCommand("DOM.enable", {});
-    InspectorTest.sendCommand("DOMDebugger.enable", {});
-    InspectorTest.sendCommand("DOMDebugger.setInstrumentationBreakpoint", {"eventName":"setInnerHTML"});
-    InspectorTest.sendCommand("Runtime.evaluate", { "expression": "modifyHTML()" });
-    InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedOne;
-
-    function handleDebuggerPausedOne(messageObject)
-    {
-        var callFrame = messageObject.params.callFrames[0];
-        InspectorTest.log("Paused on the innerHTML assignment: " + callFrame.functionName + "@:" + callFrame.location.lineNumber);
-        InspectorTest.completeTest();
-    }
-}
-</script>
-</head>
-<body onLoad="runTest();">
-<div id="divUnderTest"></div>
-Tests that we don't crash when detaching on pause from instrumentation call.
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal-expected.txt
index d88e126..9bb1912f 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal-expected.txt
@@ -4,8 +4,25 @@
 Object {a: 1, b: 2}
 {a:1}
 Object {a: 1}
-{var a = 1; eval("{a :1, b:2 }");}
-VM:1 Uncaught SyntaxError: Unexpected identifier
+{var a = 1; eval("{ a:1, b:2 }");}
+    VM:1 Uncaught SyntaxError: Unexpected token :(…)
+(anonymous function) @ VM:1
 { for (var i = 0; i < 5; ++i); }
-VM:1 Uncaught SyntaxError: Unexpected token var
+undefined
+{ a: 4 }),({ b: 7 }
+VM:1 Uncaught SyntaxError: Unexpected token )
+{ let a = 4; a; }
+4
+{ let a = 4; }; { let b = 5; };
+undefined
+{ a: 4 } + { a: 5 }
+"[object Object][object Object]"
+{ a: 4 }, { a: 5 }
+Object {a: 5}
+var foo = 4;
+undefined
+{ a: foo++ }
+Object {a: 4}
+foo;
+5
 
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal.html b/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal.html
index afa3fd3..ac1c2e5 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal.html
@@ -5,7 +5,22 @@
 <script>
 function test()
 {
-    var commands = ["{a:1, b:2}", "{a:1}", "{var a = 1; eval(\"{a :1, b:2 }\");}", "{ for (var i = 0; i < 5; ++i); }"];
+    var commands = [
+        "{a:1, b:2}",
+        "{a:1}",
+        "{var a = 1; eval(\"{ a:1, b:2 }\");}",
+        "{ for (var i = 0; i < 5; ++i); }",
+        "{ a: 4 }),({ b: 7 }",
+        "{ let a = 4; a; }",
+        "{ let a = 4; }; { let b = 5; };",
+        "{ a: 4 } + { a: 5 }",
+        "{ a: 4 }, { a: 5 }",
+
+        // Test that detection doesn't incur side effects.
+        "var foo = 4;",
+        "{ a: foo++ }",
+        "foo;"
+    ];
     var current = -1;
     loopOverCommands();
     function loopOverCommands()
diff --git a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt
index ba9cfe33..d56aeaa 100644
--- a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt
+++ b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt
@@ -2,8 +2,6 @@
 CONSOLE ERROR: line 71: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture.
 CONSOLE WARNING: line 71: Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture.
 CONSOLE ERROR: line 71: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture.
-CONSOLE WARNING: IntersectionObserver.observe(target): target element is not a descendant of root.
-CONSOLE WARNING: IntersectionObserver.observe(target): target element is not a descendant of root.
 CONSOLE WARNING: line 71: Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture.
 CONSOLE ERROR: line 71: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture.
 CONSOLE WARNING: line 71: Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture.
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.html
new file mode 100644
index 0000000..b82cd951
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.html
@@ -0,0 +1,3 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- Almost Standards mode -->
+<span id="target" style="outline: 2px solid green"><img style="width: 200px; height: 50px"></span>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt
new file mode 100644
index 0000000..28ceb64
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt
@@ -0,0 +1,47 @@
+{
+  "name": "Content Root Layer",
+  "bounds": [800, 600],
+  "children": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutInline SPAN id='target'",
+          "rect": [6, 6, 204, 58],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutImage IMG",
+          "rect": [8, 8, 200, 50],
+          "reason": "forced by layout"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutInline SPAN id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutImage IMG",
+      "reason": "forced by layout"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode.html
new file mode 100644
index 0000000..f2e17f2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- Almost Standards mode -->
+<script src="../../fast/repaint/resources/text-based-repaint.js"></script>
+<script>
+function repaintTest() {
+  target.style.outlineColor = "green";
+}
+onload = runRepaintAndPixelTest;
+</script>
+<body style="height: 0">
+  <span id="target" style="outline: 2px solid red"><img style="width: 200px; height: 50px"></span>
+</body>
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png
deleted file mode 100644
index dc0df09..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/image-object-in-canvas-expected.png
deleted file mode 100644
index 7ed279a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/image-object-in-canvas-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png
new file mode 100644
index 0000000..a1ae22d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes-expected.txt
new file mode 100644
index 0000000..cb3ff3a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+FAIL Custom iterator with basic keyframes. effect.getKeyframes is not a function
+FAIL easing and offset are ignored on iterable objects. effect.getKeyframes is not a function
+FAIL Custom iterator with multiple properties specified. effect.getKeyframes is not a function
+FAIL Custom iterator with offset specified. effect.getKeyframes is not a function
+PASS Custom iterator with non object keyframe should throw. 
+FAIL Custom iterator with value list in keyframe should give bizarre string representation of list. effect.getKeyframes is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes.html
new file mode 100644
index 0000000..1cd20ff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>Test that KeyframeEffect can take iterable objects as keyframes</title>
+<link rel='help' href='https://w3c.github.io/web-animations/#processing-a-keyframes-argument'>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<body></body>
+<script>
+function assertAnimationEffect({keyframes, expect}) {
+  var effect = new KeyframeEffect(null, keyframes);
+  var frames = effect.getKeyframes();
+  for (let i = 0; i < expect.length; i++) {
+    assert_equals(frames[i].computedOffset, expect[i].at);
+    for (var property in expect[i].is)
+      assert_equals(frames[i][property], expect[i].is[property], 
+	  `${property} is ${expect[i].is[property]} at ${expect[i].at}`);
+  }
+  return frames;
+}
+
+function createIterable(iterations) {
+  return {
+    [Symbol.iterator]() {
+      var i = 0;
+      return {next: () => iterations[i++]};
+    },
+  };
+}
+
+test(() => {
+  assertAnimationEffect({
+    keyframes: createIterable([
+      {done: false, value: {left: '100px'}},
+      {done: false, value: {left: '300px'}},
+      {done: false, value: {left: '200px'}},
+      {done: true},
+    ]),
+    expect: [
+      {at: 0, is: {left: '100px'}},
+      {at: 0.5, is: {left: '300px'}},
+      {at: 1, is: {left: '200px'}},
+    ],
+  });
+}, 'Custom iterator with basic keyframes.');
+
+test(() => {
+  var keyframes = createIterable([
+    {done: false, value: {left: '100px'}},
+    {done: false, value: {left: '300px'}},
+    {done: false, value: {left: '200px'}},
+    {done: true},
+  ]);
+  keyframes.easing = 'ease-in-out';
+  keyframes.offset = '0.1';
+  let frames = assertAnimationEffect({
+    keyframes,
+    expect: [
+      {at: 0, is: {left: '100px'}},
+      {at: 0.5, is: {left: '300px'}},
+      {at: 1, is: {left: '200px'}},
+    ],
+  });
+  assert_equals(frames[0].easing, 'linear');
+  assert_equals(frames[0].offset, null);
+}, 'easing and offset are ignored on iterable objects.');
+
+test(() => {
+  assertAnimationEffect({
+    keyframes: createIterable([
+      {done: false, value: {left: '100px', top: '200px'}},
+      {done: false, value: {left: '300px'}},
+      {done: false, value: {left: '200px', top: '100px'}},
+      {done: true},
+    ]),
+    expect: [
+      {at: 0, is: {left: '100px', top: '200px'}},
+      {at: 0.5, is: {left: '300px'}},
+      {at: 1, is: {left: '200px', top: '100px'}},
+    ],
+  });
+}, 'Custom iterator with multiple properties specified.');
+
+test(() => {
+  assertAnimationEffect({
+    keyframes: createIterable([
+      {done: false, value: {left: '100px'}},
+      {done: false, value: {left: '250px', offset: 0.75}},
+      {done: false, value: {left: '200px'}},
+      {done: true},
+    ]),
+    expect: [
+      {at: 0, is: {left: '100px'}},
+      {at: 0.75, is: {left: '250px'}},
+      {at: 1, is: {left: '200px'}},
+    ],
+  });
+}, 'Custom iterator with offset specified.');
+
+test(() => {
+  assert_throws({name: 'TypeError'}, () => {
+    assertAnimationEffect({
+      keyframes: createIterable([
+        {done: false, value: {left: '100px'}},
+        {done: false, value: 1234},
+        {done: false, value: {left: '200px'}},
+        {done: true},
+      ]),
+      expect: [],
+    });
+  });
+}, 'Custom iterator with non object keyframe should throw.');
+
+test(() => {
+  assertAnimationEffect({
+    keyframes: createIterable([
+      {done: false, value: {left: ['100px', '200px']}},
+      {done: true},
+    ]),
+    expect: [{at: 1, is: {left: "100px,200px"}}],
+  });
+}, 'Custom iterator with value list in keyframe should give bizarre string representation of list.');
+</script>
diff --git a/third_party/WebKit/PRESUBMIT.py b/third_party/WebKit/PRESUBMIT.py
index b6d2afc1..5f060cc 100644
--- a/third_party/WebKit/PRESUBMIT.py
+++ b/third_party/WebKit/PRESUBMIT.py
@@ -206,8 +206,8 @@
             'instead, as these can be more easily upstreamed to Web Platform '
             'Tests for cross-vendor compatibility testing. If you\'re not '
             'already familiar with this framework, a tutorial is available at '
-            'https://darobin.github.io/test-harness-tutorial/docs/using-testharness.html.'
-            'with the new framework.\n\n%s' % '\n'.join(errors))]
+            'https://darobin.github.io/test-harness-tutorial/docs/using-testharness.html'
+            '\n\n%s' % '\n'.join(errors))]
     return []
 
 def _CheckForFailInFile(input_api, f):
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp b/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
index 7230fd4..2c1739f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
@@ -125,8 +125,12 @@
     }
     const DOMWrapperWorld& currentWorld = DOMWrapperWorld::world(m_context);
     RELEASE_ASSERT(currentWorld.worldId() == DOMWrapperWorld::world(contextForWrapper).worldId());
-    if (currentWorld.isMainWorld()) {
-        RELEASE_ASSERT(BindingSecurity::shouldAllowAccessToFrame(isolate, currentDOMWindow(isolate), frame, DoNotReportSecurityError));
+    if (currentWorld.isMainWorld() && !BindingSecurity::shouldAllowAccessToFrame(isolate, currentDOMWindow(isolate), frame, DoNotReportSecurityError)) {
+        // TODO(jochen): Add the interface name here once this is generalized.
+        ExceptionState exceptionState(ExceptionState::ConstructionContext, nullptr, contextForWrapper->Global(), isolate);
+        exceptionState.throwSecurityError(String(), String());
+        exceptionState.throwIfNeeded();
+        return;
     }
 }
 
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi
index 1dbdbf37..aec61cf8 100644
--- a/third_party/WebKit/Source/core/core.gypi
+++ b/third_party/WebKit/Source/core/core.gypi
@@ -2845,8 +2845,6 @@
         'webcore_html_files': [
             'html/AutoplayExperimentHelper.cpp',
             'html/AutoplayExperimentHelper.h',
-            'html/AutoplayUmaHelper.cpp',
-            'html/AutoplayUmaHelper.h',
             'html/ClassList.cpp',
             'html/ClassList.h',
             'html/CrossOriginAttribute.cpp',
diff --git a/third_party/WebKit/Source/core/css/fullscreen.css b/third_party/WebKit/Source/core/css/fullscreen.css
index 1ff986e2..f6a773a7 100644
--- a/third_party/WebKit/Source/core/css/fullscreen.css
+++ b/third_party/WebKit/Source/core/css/fullscreen.css
@@ -19,7 +19,7 @@
     -webkit-box-reflect: none !important;
     -webkit-perspective: none !important;
     -webkit-transform-style: flat !important;
-    will-change: none !important;
+    will-change: auto !important;
 }
 
 video:-webkit-full-screen, audio:-webkit-full-screen {
diff --git a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp
deleted file mode 100644
index e9be0cc..0000000
--- a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2016 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 "core/html/AutoplayUmaHelper.h"
-
-#include "core/dom/ElementVisibilityObserver.h"
-#include "core/events/Event.h"
-#include "core/html/HTMLMediaElement.h"
-#include "platform/Histogram.h"
-
-namespace blink {
-
-namespace {
-
-void recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(bool visible)
-{
-    DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, ("Media.Video.Autoplay.Muted.PlayMethod.BecomesVisible"));
-    histogram.count(visible);
-}
-
-} // namespace
-
-AutoplayUmaHelper* AutoplayUmaHelper::create(HTMLMediaElement* element)
-{
-    return new AutoplayUmaHelper(element);
-}
-
-AutoplayUmaHelper::AutoplayUmaHelper(HTMLMediaElement* element)
-    : EventListener(CPPEventListenerType)
-    , m_source(AutoplaySource::NumberOfSources)
-    , m_element(element)
-    , m_videoMutedPlayMethodVisibilityObserver(nullptr) { }
-
-AutoplayUmaHelper::~AutoplayUmaHelper() = default;
-
-bool AutoplayUmaHelper::operator==(const EventListener& other) const
-{
-    return this == &other;
-}
-
-void AutoplayUmaHelper::onAutoplayInitiated(AutoplaySource source)
-{
-    DEFINE_STATIC_LOCAL(EnumerationHistogram, videoHistogram, ("Media.Video.Autoplay", static_cast<int>(AutoplaySource::NumberOfSources)));
-    DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, ("Media.Video.Autoplay.Muted", static_cast<int>(AutoplaySource::NumberOfSources)));
-    DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, ("Media.Audio.Autoplay", static_cast<int>(AutoplaySource::NumberOfSources)));
-
-    m_source = source;
-
-    if (m_element->isHTMLVideoElement()) {
-        videoHistogram.count(static_cast<int>(m_source));
-        if (m_element->muted())
-            mutedVideoHistogram.count(static_cast<int>(m_source));
-    } else {
-        audioHistogram.count(static_cast<int>(m_source));
-    }
-
-    if (m_source == AutoplaySource::Method && m_element->isHTMLVideoElement() && m_element->muted())
-        m_element->addEventListener(EventTypeNames::playing, this, false);
-}
-
-void AutoplayUmaHelper::onElementDestroyed()
-{
-    if (m_videoMutedPlayMethodVisibilityObserver) {
-        recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(false);
-        m_videoMutedPlayMethodVisibilityObserver->stop();
-        m_videoMutedPlayMethodVisibilityObserver = nullptr;
-    }
-}
-
-void AutoplayUmaHelper::recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus status)
-{
-    DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayUnmuteHistogram, ("Media.Video.Autoplay.Muted.UnmuteAction", static_cast<int>(AutoplayUnmuteActionStatus::NumberOfStatus)));
-
-    autoplayUnmuteHistogram.count(static_cast<int>(status));
-}
-
-void AutoplayUmaHelper::onVisibilityChangedForVideoMutedPlayMethod(bool isVisible)
-{
-    if (!isVisible)
-        return;
-
-    recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(true);
-    m_videoMutedPlayMethodVisibilityObserver->stop();
-    m_videoMutedPlayMethodVisibilityObserver = nullptr;
-}
-
-void AutoplayUmaHelper::handleEvent(ExecutionContext* executionContext, Event* event)
-{
-    DCHECK(event->type() == EventTypeNames::playing);
-    handlePlayingEvent();
-}
-
-void AutoplayUmaHelper::handlePlayingEvent()
-{
-    if (m_source == AutoplaySource::Method && m_element->isHTMLVideoElement() && m_element->muted()) {
-        if (!m_videoMutedPlayMethodVisibilityObserver) {
-            m_videoMutedPlayMethodVisibilityObserver = new ElementVisibilityObserver(m_element, WTF::bind(&AutoplayUmaHelper::onVisibilityChangedForVideoMutedPlayMethod, wrapPersistent(this)));
-            m_videoMutedPlayMethodVisibilityObserver->start();
-        }
-    }
-    m_element->removeEventListener(EventTypeNames::playing, this, false);
-}
-
-DEFINE_TRACE(AutoplayUmaHelper)
-{
-    EventListener::trace(visitor);
-    visitor->trace(m_element);
-    visitor->trace(m_videoMutedPlayMethodVisibilityObserver);
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h
deleted file mode 100644
index 913b74e..0000000
--- a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2016 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 AutoplayUmaHelper_h
-#define AutoplayUmaHelper_h
-
-#include "core/events/EventListener.h"
-#include "platform/heap/Handle.h"
-
-namespace blink {
-
-// These values are used for histograms. Do not reorder.
-enum class AutoplaySource {
-    // Autoplay comes from HTMLMediaElement `autoplay` attribute.
-    Attribute = 0,
-    // Autoplay comes from `play()` method.
-    Method = 1,
-    // This enum value must be last.
-    NumberOfSources = 2,
-};
-
-// These values are used for histograms. Do not reorder.
-enum class AutoplayUnmuteActionStatus {
-    Failure = 0,
-    Success = 1,
-    NumberOfStatus = 2,
-};
-
-class ElementVisibilityObserver;
-class HTMLMediaElement;
-
-class AutoplayUmaHelper final : public EventListener {
-public:
-    static AutoplayUmaHelper* create(HTMLMediaElement*);
-
-    ~AutoplayUmaHelper();
-
-    bool operator==(const EventListener&) const override;
-
-    void onAutoplayInitiated(AutoplaySource);
-    void onElementDestroyed();
-
-    void recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus);
-
-    void onVisibilityChangedForVideoMutedPlayMethod(bool isVisible);
-
-    DECLARE_VIRTUAL_TRACE();
-
-private:
-    explicit AutoplayUmaHelper(HTMLMediaElement*);
-
-    void handleEvent(ExecutionContext*, Event*) override;
-
-    void handlePlayingEvent();
-
-    // The autoplay source. Use AutoplaySource::NumberOfSources for invalid source.
-    AutoplaySource m_source;
-    // The media element this UMA helper is attached to. |m_element| owns |this|.
-    WeakMember<HTMLMediaElement> m_element;
-    // The observer is used to observe whether a muted video autoplaying by play() method become visible at some point.
-    Member<ElementVisibilityObserver> m_videoMutedPlayMethodVisibilityObserver;
-};
-
-} // namespace blink
-
-#endif // AutoplayUmaHelper_h
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index 07dba32..5a63b92 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -44,7 +44,6 @@
 #include "core/frame/Settings.h"
 #include "core/frame/UseCounter.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
-#include "core/html/AutoplayUmaHelper.h"
 #include "core/html/HTMLMediaSource.h"
 #include "core/html/HTMLSourceElement.h"
 #include "core/html/HTMLTrackElement.h"
@@ -281,6 +280,16 @@
     return String();
 }
 
+// These values are used for histograms. Do not reorder.
+enum AutoplaySource {
+    // Autoplay comes from HTMLMediaElement `autoplay` attribute.
+    AutoplaySourceAttribute = 0,
+    // Autoplay comes from `play()` method.
+    AutoplaySourceMethod = 1,
+    // This enum value must be last.
+    NumberOfAutoplaySources = 2,
+};
+
 } // anonymous namespace
 
 class HTMLMediaElement::AutoplayHelperClientImpl :
@@ -438,7 +447,6 @@
     , m_audioSourceNode(nullptr)
     , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this))
     , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient.get()))
-    , m_autoplayUmaHelper(AutoplayUmaHelper::create(this))
     , m_remotePlaybackClient(nullptr)
     , m_autoplayVisibilityObserver(nullptr)
 {
@@ -482,8 +490,6 @@
     // See Document::isDelayingLoadEvent().
     // Also see http://crbug.com/275223 for more details.
     clearMediaPlayerAndAudioSourceProviderClientWithoutLocking();
-
-    m_autoplayUmaHelper->onElementDestroyed();
 }
 
 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument)
@@ -1620,7 +1626,7 @@
 
         // Check for autoplay, and record metrics about it if needed.
         if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) {
-            m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute);
+            recordAutoplaySourceMetric(AutoplaySourceAttribute);
 
             // If the autoplay experiment says that it's okay to play now,
             // then don't require a user gesture.
@@ -2075,7 +2081,7 @@
     m_autoplayHelper->playMethodCalled();
 
     if (!UserGestureIndicator::processingUserGesture()) {
-        m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Method);
+        recordAutoplaySourceMetric(AutoplaySourceMethod);
         if (isGestureNeededForPlayback()) {
             // If playback is deferred, then don't start playback but don't
             // fail yet either.
@@ -2300,9 +2306,9 @@
     if (wasAutoplayingMuted) {
         if (isGestureNeededForPlayback()) {
             pause();
-            m_autoplayUmaHelper->recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus::Failure);
+            recordAutoplayUnmuteStatus(AutoplayUnmuteActionFailure);
         } else {
-            m_autoplayUmaHelper->recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus::Success);
+            recordAutoplayUnmuteStatus(AutoplayUnmuteActionSuccess);
         }
     }
 }
@@ -3660,7 +3666,6 @@
     visitor->trace(m_audioSourceProvider);
     visitor->trace(m_autoplayHelperClient);
     visitor->trace(m_autoplayHelper);
-    visitor->trace(m_autoplayUmaHelper);
     visitor->trace(m_srcObject);
     visitor->trace(m_autoplayVisibilityObserver);
     visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::clearWeakMembers>(this);
@@ -3881,6 +3886,28 @@
     return histogram;
 }
 
+void HTMLMediaElement::recordAutoplaySourceMetric(int source)
+{
+    DEFINE_STATIC_LOCAL(EnumerationHistogram, videoHistogram, ("Media.Video.Autoplay", NumberOfAutoplaySources));
+    DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, ("Media.Video.Autoplay.Muted", NumberOfAutoplaySources));
+    DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, ("Media.Audio.Autoplay", NumberOfAutoplaySources));
+
+    if (isHTMLVideoElement()) {
+        videoHistogram.count(source);
+        if (muted())
+            mutedVideoHistogram.count(source);
+    } else {
+        audioHistogram.count(source);
+    }
+}
+
+void HTMLMediaElement::recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus status)
+{
+    DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayUnmuteHistogram, ("Media.Video.Autoplay.Muted.UnmuteAction", AutoplayUnmuteActionMax));
+
+    autoplayUnmuteHistogram.count(status);
+}
+
 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible)
 {
     if (!isVisible)
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
index f488f66..9863e39 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -46,7 +46,6 @@
 
 class AudioSourceProviderClient;
 class AudioTrackList;
-class AutoplayUmaHelper;
 class ContentType;
 class CueTimeline;
 class ElementVisibilityObserver;
@@ -299,6 +298,13 @@
     void recordAutoplayMetric(AutoplayMetrics);
 
 private:
+    // These values are used for histograms. Do not reorder.
+    enum AutoplayUnmuteActionStatus {
+        AutoplayUnmuteActionFailure = 0,
+        AutoplayUnmuteActionSuccess = 1,
+        AutoplayUnmuteActionMax
+    };
+
     void resetMediaPlayerAndMediaSource();
 
     bool alwaysCreateUserAgentShadowRoot() const final { return true; }
@@ -493,6 +499,9 @@
 
     EnumerationHistogram& showControlsHistogram() const;
 
+    void recordAutoplaySourceMetric(int source);
+    void recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus);
+
     void onVisibilityChangedForAutoplay(bool isVisible);
 
     UnthrottledTimer<HTMLMediaElement> m_loadTimer;
@@ -669,7 +678,6 @@
 
     Member<AutoplayExperimentHelper::Client> m_autoplayHelperClient;
     Member<AutoplayExperimentHelper> m_autoplayHelper;
-    Member<AutoplayUmaHelper> m_autoplayUmaHelper;
 
     WebRemotePlaybackClient* m_remotePlaybackClient;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
index b62b61d..b660dce 100644
--- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
@@ -517,24 +517,11 @@
 
 bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
 {
-    // Allow other plugins to win over QuickTime because if the user has
-    // installed a plugin that can handle TIFF (which QuickTime can also
-    // handle) they probably intended to override QT.
-    if (document().frame()->page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) {
-        const PluginData* pluginData = document().frame()->pluginData();
-        String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String();
-        if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", TextCaseInsensitive)) {
-            useFallback = false;
-            return true;
-        }
-    }
-
     ObjectContentType objectType = document().frame()->loader().client()->getObjectContentType(url, mimeType, shouldPreferPlugInsForImages());
     // If an object's content can't be handled and it has no fallback, let
     // it be handled as a plugin to show the broken plugin icon.
     useFallback = objectType == ObjectContentNone && hasFallback;
     return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin;
-
 }
 
 void HTMLPlugInElement::dispatchErrorEvent()
diff --git a/third_party/WebKit/Source/core/html/OWNERS b/third_party/WebKit/Source/core/html/OWNERS
index ab32e99..c877bae 100644
--- a/third_party/WebKit/Source/core/html/OWNERS
+++ b/third_party/WebKit/Source/core/html/OWNERS
@@ -1,4 +1,3 @@
 per-file Autoplay*=mlamouri@chromium.org
-per-file AutoplayUmaHelper=zqzhang@chromium.org
 per-file Media*=mlamouri@chromium.org
 per-file HTMLMedia*=mlamouri@chromium.org
diff --git a/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py b/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py
index eaf7a60..188ed26 100755
--- a/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py
+++ b/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py
@@ -102,72 +102,6 @@
 public:
     InstrumentingAgents();
     DECLARE_TRACE();
-
-    template <class T>
-    class AgentsList {
-        DISALLOW_NEW();
-    private:
-        using AgentsVector = HeapVector<Member<T>>;
-        using InnerIterator = typename AgentsVector::iterator;
-
-    public:
-        class Iterator {
-            STACK_ALLOCATED();
-        public:
-            Iterator operator++(int) { InnerIterator value = m_value; ++*this; return Iterator(value, m_list); }
-            Iterator& operator++() { if (!isEnd()) ++m_value; return *this; }
-            bool operator==(const Iterator& other) const { return (isEnd() && other.isEnd()) || m_value == other.m_value; }
-            bool operator!=(const Iterator& other) const { return !(*this == other); }
-            T* operator*() { return *m_value; }
-            T* operator->() { return *m_value; }
-
-        private:
-            friend class AgentsList;
-            Iterator(InnerIterator value, AgentsList* list) : m_value(value), m_list(list), m_version(m_list->m_version) { }
-            bool isEnd() const { return m_list->m_version != m_version || m_value == m_list->m_vector.end(); }
-
-            InnerIterator m_value;
-            Member<AgentsList> m_list;
-            int m_version;
-        };
-
-        Iterator begin() { return Iterator(m_vector.begin(), this); }
-        Iterator end() { return Iterator(m_vector.end(), this); }
-
-        DEFINE_INLINE_TRACE()
-        {
-            visitor->trace(m_vector);
-        }
-
-    private:
-        friend class InstrumentingAgents;
-        friend class Iterator;
-
-        AgentsList() : m_version(0) { }
-
-        bool isEmpty() const { return m_vector.isEmpty(); }
-
-        void add(T* value)
-        {
-            if (m_vector.contains(value))
-                return;
-            ++m_version;
-            m_vector.append(value);
-        }
-
-        void remove(T* value)
-        {
-            size_t index = m_vector.find(value);
-            if (index == WTF::kNotFound)
-                return;
-            ++m_version;
-            m_vector.remove(index);
-        }
-
-        AgentsVector m_vector;
-        int m_version;
-    };
-
 ${accessor_list}
 
 private:
@@ -181,7 +115,7 @@
 
 template_instrumenting_agent_accessor = string.Template("""
     bool has${class_name}s() const { return ${has_member_name}; }
-    AgentsList<${class_name}>& ${getter_name}s() { return ${member_name}; }
+    const HeapHashSet<Member<${class_name}>>& ${getter_name}s() const { return ${member_name}; }
     void add${class_name}(${class_name}* agent);
     void remove${class_name}(${class_name}* agent);""")
 
@@ -189,7 +123,7 @@
 void InstrumentingAgents::add${class_name}(${class_name}* agent)
 {
     ${member_name}.add(agent);
-    ${has_member_name} = !${member_name}.isEmpty();
+    ${has_member_name} = true;
 }
 
 void InstrumentingAgents::remove${class_name}(${class_name}* agent)
@@ -455,7 +389,7 @@
             getter_name=getter_name,
             member_name=member_name,
             has_member_name=has_member_name))
-        member_list.append("    AgentsList<%s> %s;" % (class_name, member_name))
+        member_list.append("    HeapHashSet<Member<%s>> %s;" % (class_name, member_name))
         member_list.append("    bool %s;" % has_member_name)
         init_list.append("%s(false)" % has_member_name)
         trace_list.append("visitor->trace(%s);" % member_name)
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json
index 7de6c22a..f4a2de9 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.json
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -4230,7 +4230,7 @@
                 "name": "createTarget",
                 "description": "Creates a new page.",
                 "parameters": [
-                    { "name": "initialUrl", "type": "string", "description": "The initial URL the page will be navigated to." },
+                    { "name": "url", "type": "string", "description": "The initial URL the page will be navigated to." },
                     { "name": "width", "type": "integer", "description": "Window width (headless chrome only).", "optional": true },
                     { "name": "height", "type": "integer", "description": "Window height (headless chrome only).", "optional": true },
                     { "name": "browserContextId", "$ref": "BrowserContextID", "description": "The browser context to create the page in (headless chrome only).", "optional": true }
diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.cpp b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
index fefc372..5d11e8f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutInline.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
@@ -1062,9 +1062,15 @@
     LayoutUnit outlineOutset(style()->outlineOutsetExtent());
     if (outlineOutset) {
         Vector<LayoutRect> rects;
-        // We have already included outline extents of line boxes in linesVisualOverflowBoundingBox(),
-        // so the following just add outline rects for children and continuations.
-        addOutlineRectsForChildrenAndContinuations(rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow());
+        if (document().inNoQuirksMode()) {
+            // We have already included outline extents of line boxes in linesVisualOverflowBoundingBox(),
+            // so the following just add outline rects for children and continuations.
+            addOutlineRectsForChildrenAndContinuations(rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow());
+        } else {
+            // In non-standard mode, because the difference in LayoutBlock::minLineHeightForReplacedObject(),
+            // linesVisualOverflowBoundingBox() may not cover outline rects of lines containing replaced objects.
+            addOutlineRects(rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow());
+        }
         if (!rects.isEmpty()) {
             LayoutRect outlineRect = unionRectEvenIfEmpty(rects);
             outlineRect.inflate(outlineOutset);
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp
index c6cae63..14efaeeb 100644
--- a/third_party/WebKit/Source/core/page/DragController.cpp
+++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -584,7 +584,7 @@
         return DragOperationCopy;
     if (srcOpMask == DragOperationNone)
         return DragOperationNone;
-    if (srcOpMask & DragOperationMove || srcOpMask & DragOperationGeneric)
+    if (srcOpMask & DragOperationMove)
         return DragOperationMove;
     if (srcOpMask & DragOperationCopy)
         return DragOperationCopy;
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi
index 97666e3..f4a0c08 100644
--- a/third_party/WebKit/Source/devtools/devtools.gypi
+++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -432,7 +432,6 @@
         ],
         'devtools_devices_js_files': [
             'front_end/devices/devicesView.css',
-            'front_end/devices/DevicesDialog.js',
             'front_end/devices/DevicesView.js',
         ],
         'devtools_diff_js_files': [
diff --git a/third_party/WebKit/Source/devtools/front_end/Runtime.js b/third_party/WebKit/Source/devtools/front_end/Runtime.js
index a1e681f..e79325f 100644
--- a/third_party/WebKit/Source/devtools/front_end/Runtime.js
+++ b/third_party/WebKit/Source/devtools/front_end/Runtime.js
@@ -455,6 +455,16 @@
     Runtime._originalAssert.call(Runtime._console, value, message + " " + new Error().stack);
 }
 
+Runtime._platform = "";
+
+/**
+ * @param {string} platform
+ */
+Runtime.setPlatform = function(platform)
+{
+    Runtime._platform = platform;
+}
+
 Runtime.prototype = {
     useTestBase: function()
     {
@@ -563,11 +573,12 @@
     /**
      * @param {*} type
      * @param {?Object=} context
+     * @param {boolean=} sortByTitle
      * @return {!Array.<!Runtime.Extension>}
      */
-    extensions: function(type, context)
+    extensions: function(type, context, sortByTitle)
     {
-        return this._extensions.filter(filter).sort(orderComparator);
+        return this._extensions.filter(filter).sort(sortByTitle ? titleComparator : orderComparator);
 
         /**
          * @param {!Runtime.Extension} extension
@@ -593,6 +604,18 @@
             var order2 = extension2.descriptor()["order"] || 0;
             return order1 - order2;
         }
+
+        /**
+         * @param {!Runtime.Extension} extension1
+         * @param {!Runtime.Extension} extension2
+         * @return {number}
+         */
+        function titleComparator(extension1, extension2)
+        {
+            var title1 = extension1.title() || "";
+            var title2 = extension2.title() || "";
+            return title1.localeCompare(title2);
+        }
     },
 
     /**
@@ -978,13 +1001,12 @@
     },
 
     /**
-     * @param {string} platform
      * @return {string}
      */
-    title: function(platform)
+    title: function()
     {
         // FIXME: should be WebInspector.UIString() but runtime is not l10n aware yet.
-        return this._descriptor["title-" + platform] || this._descriptor["title"];
+        return this._descriptor["title-" + Runtime._platform] || this._descriptor["title"];
     }
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
index 16653bc5d..6db738a 100644
--- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
+++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
@@ -758,29 +758,3 @@
         return new WebInspector.AnimationTimeline.StepTimingFunction(parseInt(match[1], 10), match[2]);
     return null;
 }
-
-/**
- * @constructor
- * @implements {WebInspector.ToolbarItem.Provider}
- */
-WebInspector.AnimationTimeline.ButtonProvider = function()
-{
-    this._button = new WebInspector.ToolbarButton(WebInspector.UIString("Animations"), "animation-toolbar-item");
-    this._button.addEventListener("click", this._clicked, this);
-}
-
-WebInspector.AnimationTimeline.ButtonProvider.prototype = {
-    _clicked: function()
-    {
-        WebInspector.inspectorView.showViewInDrawer("animations");
-    },
-
-    /**
-     * @override
-     * @return {!WebInspector.ToolbarItem}
-     */
-    item: function()
-    {
-        return this._button;
-    }
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/module.json b/third_party/WebKit/Source/devtools/front_end/animation/module.json
index 236b476..0e03f47 100644
--- a/third_party/WebKit/Source/devtools/front_end/animation/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/animation/module.json
@@ -1,12 +1,6 @@
 {
     "extensions": [
         {
-            "type": "@WebInspector.ToolbarItem.Provider",
-            "className": "WebInspector.AnimationTimeline.ButtonProvider",
-            "order": 2,
-            "location": "styles-sidebarpane-toolbar"
-        },
-        {
             "type": "drawer-view",
             "name": "animations",
             "title": "Animations",
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
index a299b322..2e2a94bc 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
@@ -645,7 +645,7 @@
  */
 WebInspector.DOMPresentationUtils.GenericDecorator = function(extension)
 {
-    this._title = WebInspector.UIString(extension.title(WebInspector.platform()));
+    this._title = WebInspector.UIString(extension.title());
     this._color = extension.descriptor()["color"];
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/devices/DevicesDialog.js b/third_party/WebKit/Source/devtools/front_end/devices/DevicesDialog.js
deleted file mode 100644
index 05fdade..0000000
--- a/third_party/WebKit/Source/devtools/front_end/devices/DevicesDialog.js
+++ /dev/null
@@ -1,44 +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.
-
-/**
- * @constructor
- */
-WebInspector.DevicesDialog = function()
-{
-}
-
-/**
- * @constructor
- * @implements {WebInspector.ActionDelegate}
- */
-WebInspector.DevicesDialog.ActionDelegate = function()
-{
-    /** @type {?WebInspector.DevicesView} */
-    this._view = null;
-}
-
-WebInspector.DevicesDialog.ActionDelegate.prototype = {
-    /**
-     * @override
-     * @param {!WebInspector.Context} context
-     * @param {string} actionId
-     * @return {boolean}
-     */
-    handleAction: function(context, actionId)
-    {
-        if (actionId === "devices.dialog.show") {
-            if (!this._view)
-                this._view = new WebInspector.DevicesView();
-
-            var dialog = new WebInspector.Dialog();
-            dialog.addCloseButton();
-            this._view.show(dialog.element);
-            dialog.setMaxSize(new Size(700, 500));
-            dialog.show();
-            return true;
-        }
-        return false;
-    }
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/devices/devicesView.css b/third_party/WebKit/Source/devtools/front_end/devices/devicesView.css
index e9930d6e..19cf476 100644
--- a/third_party/WebKit/Source/devtools/front_end/devices/devicesView.css
+++ b/third_party/WebKit/Source/devtools/front_end/devices/devicesView.css
@@ -85,6 +85,14 @@
     white-space: pre;
 }
 
+.discovery-view {
+    overflow: auto;
+}
+
+.discovery-view > * {
+    flex: none;
+}
+
 .usb-checkbox {
     padding-bottom: 8px;
     margin-top: 20px;
@@ -113,7 +121,7 @@
 .port-forwarding-list {
     margin: 10px 0 0 25px;
     max-width: 500px;
-    flex: 0 1 auto;
+    flex: none;
 }
 
 .port-forwarding-list-empty {
@@ -206,7 +214,7 @@
     flex: auto;
     overflow: auto;
     padding-right: 10px;
-    margin-top: 20px;
+    margin-top: 30px;
 }
 
 .device-browser-list > div {
@@ -273,7 +281,7 @@
 }
 
 .device-page-url {
-    margin: 3px 0;
+    margin: 3px 100px 3px 0;
 }
 
 .device-page-url a {
diff --git a/third_party/WebKit/Source/devtools/front_end/devices/module.json b/third_party/WebKit/Source/devtools/front_end/devices/module.json
index 42a7695b..f253327 100644
--- a/third_party/WebKit/Source/devtools/front_end/devices/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/devices/module.json
@@ -1,23 +1,18 @@
 {
     "extensions": [
         {
-            "type": "@WebInspector.ActionDelegate",
-            "category": "Mobile",
-            "actionId": "devices.dialog.show",
-            "className": "WebInspector.DevicesDialog.ActionDelegate",
-            "title": "Inspect devices\u2026"
-        },
-        {
-            "type": "context-menu-item",
-            "location": "mainMenu/tools/open",
+            "type": "drawer-view",
+            "name": "remote-devices",
+            "title": "Remote devices",
+            "persistence": "closeable",
             "order": 50,
-            "actionId": "devices.dialog.show"
+            "className": "WebInspector.DevicesView",
+            "tags": "usb, android, mobile"
         }
     ],
     "dependencies": ["platform", "ui", "host", "components"],
     "scripts": [
-        "DevicesView.js",
-        "DevicesDialog.js"
+        "DevicesView.js"
     ],
     "resources": [
         "devicesView.css"
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
index 1d15b64..b187427d 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
@@ -4,24 +4,24 @@
 
 /**
  * @constructor
- * @extends {WebInspector.ElementsPanel.BaseToolbarPaneWidget}
- * @param {!WebInspector.ToolbarItem} toolbarItem
+ * @extends {WebInspector.Widget}
  */
-WebInspector.ClassesPaneWidget = function(toolbarItem)
+WebInspector.ClassesPaneWidget = function()
 {
-    WebInspector.ElementsPanel.BaseToolbarPaneWidget.call(this, toolbarItem);
+    WebInspector.Widget.call(this);
     this.element.className = "styles-element-classes-pane";
     var container = this.element.createChild("div", "title-container");
-    var input = container.createChild("input", "new-class-input monospace");
-    input.placeholder = WebInspector.UIString("Add new class");
-    input.addEventListener("keydown", this._onKeyDown.bind(this), false);
-    this.setDefaultFocusedElement(input);
+    this._input = container.createChild("input", "new-class-input monospace");
+    this._input.placeholder = WebInspector.UIString("Add new class");
+    this._input.addEventListener("keydown", this._onKeyDown.bind(this), false);
+    this.setDefaultFocusedElement(this._input);
     this._classesContainer = this.element.createChild("div", "source-code");
     this._classesContainer.classList.add("styles-element-classes-container");
 
     WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.DOMMutated, this._onDOMMutated, this);
     /** @type {!Set<!WebInspector.DOMNode>} */
     this._mutatingNodes = new Set();
+    WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._update, this);
 }
 
 WebInspector.ClassesPaneWidget._classesSymbol = Symbol("WebInspector.ClassesPaneWidget._classesSymbol");
@@ -55,7 +55,7 @@
             this._toggleClass(node, className, true);
         }
         this._installNodeClasses(node);
-        this.update();
+        this._update();
         event.consume(true);
     },
 
@@ -68,19 +68,31 @@
         if (this._mutatingNodes.has(node))
             return;
         delete node[WebInspector.ClassesPaneWidget._classesSymbol];
-        this.update();
+        this._update();
     },
 
     /**
      * @override
-     * @return {!Promise.<?>}
      */
-    doUpdate: function()
+    wasShown: function()
     {
-        this._classesContainer.removeChildren();
+        this._update();
+    },
+
+    _update: function()
+    {
+        if (!this.isShowing())
+            return;
+
         var node = WebInspector.context.flavor(WebInspector.DOMNode);
+        if (node)
+            node = node.enclosingElementOrSelf();
+
+        this._classesContainer.removeChildren();
+        this._input.disabled = !node;
+
         if (!node)
-            return Promise.resolve();
+            return;
 
         var classes = this._nodeClasses(node);
         var keys = classes.keysArray();
@@ -92,7 +104,6 @@
             label.checkboxElement.addEventListener("click", this._onClick.bind(this, className), false);
             this._classesContainer.appendChild(label);
         }
-        return Promise.resolve();
     },
 
     /**
@@ -168,16 +179,7 @@
         }
     },
 
-    /**
-     * @override
-     * @param {?WebInspector.DOMNode} newNode
-     */
-    onNodeChanged: function(newNode)
-    {
-        this.update();
-    },
-
-    __proto__: WebInspector.ElementsPanel.BaseToolbarPaneWidget.prototype
+    __proto__: WebInspector.Widget.prototype
 }
 
 /**
@@ -190,15 +192,13 @@
     this._button.setText(".cls");
     this._button.element.classList.add("monospace");
     this._button.addEventListener("click", this._clicked, this);
-    this._view = new WebInspector.ClassesPaneWidget(this.item());
-    WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._nodeChanged, this);
-    this._nodeChanged();
+    this._view = new WebInspector.ClassesPaneWidget();
 }
 
 WebInspector.ClassesPaneWidget.ButtonProvider.prototype = {
     _clicked: function()
     {
-        WebInspector.ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null);
+        WebInspector.ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null, this._button);
     },
 
     /**
@@ -208,14 +208,5 @@
     item: function()
     {
         return this._button;
-    },
-
-    _nodeChanged: function()
-    {
-        var node = WebInspector.context.flavor(WebInspector.DOMNode);
-        var enabled = !!node;
-        this._button.setEnabled(enabled);
-        if (!enabled && this._button.toggled())
-            WebInspector.ElementsPanel.instance().showToolbarPane(null);
     }
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js
index 17da5ab..b008343bf 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js
@@ -4,12 +4,11 @@
 
 /**
  * @constructor
- * @extends {WebInspector.ElementsPanel.BaseToolbarPaneWidget}
- * @param {!WebInspector.ToolbarItem} toolbarItem
+ * @extends {WebInspector.Widget}
  */
-WebInspector.ElementStatePaneWidget = function(toolbarItem)
+WebInspector.ElementStatePaneWidget = function()
 {
-    WebInspector.ElementsPanel.BaseToolbarPaneWidget.call(this, toolbarItem);
+    WebInspector.Widget.call(this);
     this.element.className = "styles-element-state-pane";
     this.element.createChild("div").createTextChild(WebInspector.UIString("Force element state"));
     var table = createElementWithClass("table", "source-code");
@@ -53,6 +52,7 @@
     tr.appendChild(createCheckbox.call(null, "visited"));
 
     this.element.appendChild(table);
+    WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._update, this);
 }
 
 WebInspector.ElementStatePaneWidget.prototype = {
@@ -66,40 +66,33 @@
 
         if (this._target) {
             var cssModel = WebInspector.CSSModel.fromTarget(this._target);
-            cssModel.removeEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._pseudoStateForced, this)
+            cssModel.removeEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._update, this)
         }
         this._target = target;
         if (target) {
             var cssModel = WebInspector.CSSModel.fromTarget(target);
-            cssModel.addEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._pseudoStateForced, this)
+            cssModel.addEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._update, this)
         }
     },
 
     /**
-     * @param {!WebInspector.Event} event
+     * @override
      */
-    _pseudoStateForced: function(event)
+    wasShown: function()
     {
-        this.update();
+        this._update();
     },
 
-    /**
-     * @override
-     * @param {?WebInspector.DOMNode} newNode
-     */
-    onNodeChanged: function(newNode)
+    _update: function()
     {
-        this._updateTarget(newNode ? newNode.target() : null);
-        this.update();
-    },
+        if (!this.isShowing())
+            return;
 
-    /**
-     * @override
-     * @return {!Promise.<?>}
-     */
-    doUpdate: function()
-    {
         var node = WebInspector.context.flavor(WebInspector.DOMNode);
+        if (node)
+            node = node.enclosingElementOrSelf();
+
+        this._updateTarget(node ? node.target() : null);
         if (node) {
             var nodePseudoState = WebInspector.CSSModel.fromNode(node).pseudoState(node);
             for (var input of this._inputs) {
@@ -112,10 +105,9 @@
                 input.checked = false;
             }
         }
-        return Promise.resolve();
     },
 
-    __proto__: WebInspector.ElementsPanel.BaseToolbarPaneWidget.prototype
+    __proto__: WebInspector.Widget.prototype
 }
 
 /**
@@ -127,15 +119,13 @@
     this._button = new WebInspector.ToolbarToggle(WebInspector.UIString("Toggle Element State"), "", WebInspector.UIString(":hov"));
     this._button.addEventListener("click", this._clicked, this);
     this._button.element.classList.add("monospace");
-    this._view = new WebInspector.ElementStatePaneWidget(this.item());
-    WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._nodeChanged, this);
-    this._nodeChanged();
+    this._view = new WebInspector.ElementStatePaneWidget();
 }
 
 WebInspector.ElementStatePaneWidget.ButtonProvider.prototype = {
     _clicked: function()
     {
-        WebInspector.ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null);
+        WebInspector.ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null, this._button);
     },
 
     /**
@@ -145,13 +135,5 @@
     item: function()
     {
         return this._button;
-    },
-
-    _nodeChanged: function()
-    {
-        var enabled = !!WebInspector.context.flavor(WebInspector.DOMNode);
-        this._button.setEnabled(enabled);
-        if (!enabled && this._button.toggled())
-            WebInspector.ElementsPanel.instance().showToolbarPane(null);
     }
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
index 5da3bbe..bc5f4de 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -134,13 +134,21 @@
 
     /**
      * @param {?WebInspector.Widget} widget
+     * @param {!WebInspector.ToolbarToggle=} toggle
      */
-    showToolbarPane: function(widget)
+    showToolbarPane: function(widget, toggle)
     {
+        if (this._pendingWidgetToggle)
+            this._pendingWidgetToggle.setToggled(false);
+        this._pendingWidgetToggle = toggle;
+
         if (this._animatedToolbarPane !== undefined)
             this._pendingWidget = widget;
         else
             this._startToolbarPaneAnimation(widget);
+
+        if (widget && toggle)
+            toggle.setToggled(true);
     },
 
     /**
@@ -291,7 +299,6 @@
             width -= this._splitWidget.sidebarSize();
         for (var i = 0; i < this._treeOutlines.length; ++i) {
             this._treeOutlines[i].setVisibleWidth(width);
-            this._treeOutlines[i].updateSelection();
         }
         this._breadcrumbs.updateSizes();
     },
@@ -329,7 +336,6 @@
 
         for (var i = 0; i < this._treeOutlines.length; ++i) {
             var treeOutline = this._treeOutlines[i];
-            treeOutline.updateSelection();
             treeOutline.setVisible(true);
 
             if (!treeOutline.rootDOMNode)
@@ -551,14 +557,6 @@
         this._contentElement.classList.toggle("elements-wrap", event.data);
         for (var i = 0; i < this._treeOutlines.length; ++i)
             this._treeOutlines[i].setWordWrap(/** @type {boolean} */ (event.data));
-
-        var selectedNode = this.selectedDOMNode();
-        if (!selectedNode)
-            return;
-
-        var treeElement = this._treeElementForNode(selectedNode);
-        if (treeElement)
-            treeElement.updateSelection(); // Recalculate selection highlight dimensions.
     },
 
     switchToAndFocus: function(node)
@@ -1244,55 +1242,3 @@
         return { color: "orange", title: WebInspector.UIString("Element state: %s", ":" + WebInspector.CSSModel.fromNode(node).pseudoState(node).join(", :")) };
     }
 }
-
-/**
- * @constructor
- * @extends {WebInspector.ThrottledWidget}
- * @param {!WebInspector.ToolbarItem} toolbarItem
- */
-WebInspector.ElementsPanel.BaseToolbarPaneWidget = function(toolbarItem)
-{
-    WebInspector.ThrottledWidget.call(this);
-    this._toolbarItem = toolbarItem;
-    WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._nodeChanged, this);
-}
-
-WebInspector.ElementsPanel.BaseToolbarPaneWidget.prototype = {
-    _nodeChanged: function()
-    {
-        if (!this.isShowing())
-            return;
-
-        var elementNode = WebInspector.SharedSidebarModel.elementNode(WebInspector.context.flavor(WebInspector.DOMNode));
-        this.onNodeChanged(elementNode);
-    },
-
-    /**
-     * @param {?WebInspector.DOMNode} newNode
-     * @protected
-     */
-    onNodeChanged: function(newNode)
-    {
-    },
-
-    /**
-     * @override
-     */
-    willHide: function()
-    {
-        this._toolbarItem.setToggled(false);
-        WebInspector.ThrottledWidget.prototype.willHide.call(this);
-    },
-
-    /**
-     * @override
-     */
-    wasShown: function()
-    {
-        this._toolbarItem.setToggled(true);
-        this._nodeChanged();
-        WebInspector.ThrottledWidget.prototype.wasShown.call(this);
-    },
-
-    __proto__: WebInspector.ThrottledWidget.prototype
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
index 39b1dca5..bf14bffc 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
@@ -229,7 +229,7 @@
 
         if (this.listItemElement) {
             if (x) {
-                this.updateSelection();
+                this._createSelection();
                 this.listItemElement.classList.add("hovered");
             } else {
                 this.listItemElement.classList.remove("hovered");
@@ -253,7 +253,7 @@
         this._expandedChildrenLimit = expandedChildrenLimit;
     },
 
-    updateSelection: function()
+    _createSelection: function()
     {
         var listItemElement = this.listItemElement;
         if (!listItemElement)
@@ -290,7 +290,7 @@
     onattach: function()
     {
         if (this._hovered) {
-            this.updateSelection();
+            this._createSelection();
             this.listItemElement.classList.add("hovered");
         }
 
@@ -337,7 +337,6 @@
             return;
 
         this.updateTitle();
-        this.treeOutline.updateSelection();
     },
 
     oncollapse: function()
@@ -346,7 +345,6 @@
             return;
 
         this.updateTitle();
-        this.treeOutline.updateSelection();
     },
 
     /**
@@ -373,7 +371,7 @@
         this.treeOutline.selectDOMNode(this._node, selectedByUser);
         if (selectedByUser)
             this._node.highlight();
-        this.updateSelection();
+        this._createSelection();
         this.treeOutline.suppressRevealAndSelect = false;
         return true;
     },
@@ -454,8 +452,6 @@
             tag.appendChild(node);
             tag.createTextChild(">");
         }
-
-        this.updateSelection();
     },
 
     /**
@@ -810,8 +806,6 @@
         this.listItemElement.classList.add("editing-as-html");
         this.treeOutline.element.addEventListener("mousedown", consume, false);
 
-        this.updateSelection();
-
         /**
          * @param {!Element} element
          * @param {string} newValue
@@ -847,7 +841,6 @@
             }
 
             this.treeOutline.element.removeEventListener("mousedown", consume, false);
-            this.updateSelection();
             this.treeOutline.focus();
         }
 
@@ -1079,7 +1072,7 @@
 
         delete this.selectionElement;
         if (this.selected)
-            this.updateSelection();
+            this._createSelection();
         this._preventFollowingLinksOnDoubleClick();
         this._highlightSearchResults();
     },
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
index 8f653af..4b56b65 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -439,14 +439,6 @@
             this._revealAndSelectNode(selectedNode, true);
     },
 
-    updateSelection: function()
-    {
-        if (!this.selectedTreeElement)
-            return;
-        var element = this.selectedTreeElement;
-        element.updateSelection();
-    },
-
     _selectedNodeChanged: function()
     {
         this.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedDOMNode);
@@ -743,7 +735,6 @@
             node = node.parentNode;
         }
 
-        treeElement.updateSelection();
         treeElement.listItemElement.classList.add("elements-drag-over");
         this._dragOverTreeElement = treeElement;
         event.preventDefault();
@@ -822,7 +813,6 @@
     _clearDragOverTreeElementMarker: function()
     {
         if (this._dragOverTreeElement) {
-            this._dragOverTreeElement.updateSelection();
             this._dragOverTreeElement.listItemElement.classList.remove("elements-drag-over");
             delete this._dragOverTreeElement;
         }
@@ -1243,7 +1233,6 @@
             this._element.classList.remove("hidden");
             if (originalScrollTop)
                 treeOutlineContainerElement.scrollTop = originalScrollTop;
-            this.updateSelection();
         }
 
         this._updateRecords.clear();
@@ -1750,10 +1739,6 @@
         this.listItemElement.classList.toggle("hovered", x);
     },
 
-    updateSelection: function()
-    {
-    },
-
     /**
      * @return {number}
      */
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js b/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js
index bcf26d33..1eb7e82 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js
@@ -13,20 +13,6 @@
     WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._onNodeChanged, this);
 }
 
-/**
- * @param {?WebInspector.DOMNode} node
- * @return {?WebInspector.DOMNode}
- */
-WebInspector.SharedSidebarModel.elementNode = function(node)
-{
-    if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode)
-        node = node.parentNode;
-
-    if (node && node.nodeType() !== Node.ELEMENT_NODE)
-        node = null;
-    return node;
-}
-
 WebInspector.SharedSidebarModel.Events = {
     ComputedStyleChanged: "ComputedStyleChanged"
 }
@@ -94,7 +80,7 @@
      */
     _elementNode: function()
     {
-        return WebInspector.SharedSidebarModel.elementNode(this.node());
+        return this.node() ? this.node().enclosingElementOrSelf() : null;
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
index a2f9a35..4304ea08 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -206,7 +206,7 @@
     setNode: function(node)
     {
         this._stylesPopoverHelper.hide();
-        node = WebInspector.SharedSidebarModel.elementNode(node);
+        node = node ? node.enclosingElementOrSelf() : null;
 
         this._resetCache();
         WebInspector.ElementsSidebarPane.prototype.setNode.call(this, node);
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/module.json b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
index 45c8602..b1381de5 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
@@ -100,12 +100,6 @@
             "className": "WebInspector.SensorsView.ShowActionDelegate"
         },
         {
-            "type": "context-menu-item",
-            "location": "mainMenu/tools/open",
-            "order": 100,
-            "actionId": "emulation.show-sensors"
-        },
-        {
             "type": "drawer-view",
             "name": "sensors",
             "title": "Sensors",
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index 8c8748bf..1e7cf982 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -57,6 +57,7 @@
 
         if (InspectorFrontendHost.isUnderTest())
             self.runtime.useTestBase();
+        Runtime.setPlatform(WebInspector.platform());
         InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this));
     },
 
@@ -883,6 +884,13 @@
 
         contextMenu.appendAction("main.toggle-drawer", WebInspector.inspectorView.drawerVisible() ? WebInspector.UIString("Hide console") : WebInspector.UIString("Show console"));
         contextMenu.appendItemsAtLocation("mainMenu");
+        var moreTools = contextMenu.namedSubMenu("mainMenuMoreTools");
+        var extensions = self.runtime.extensions("drawer-view", undefined, true);
+        for (var extension of extensions) {
+            var descriptor = extension.descriptor();
+            moreTools.appendItem(extension.title(), WebInspector.inspectorView.showViewInDrawer.bind(WebInspector.inspectorView, descriptor["name"]));
+        }
+
         contextMenu.show();
     }
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js b/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js
index 83ffccc..05914662 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js
@@ -166,25 +166,3 @@
         WebInspector.RenderingOptionsView._instanceObject = new WebInspector.RenderingOptionsView();
     return WebInspector.RenderingOptionsView._instanceObject;
 }
-
-/**
- * @constructor
- * @implements {WebInspector.ActionDelegate}
- */
-WebInspector.RenderingOptionsView.ShowActionDelegate = function()
-{
-}
-
-WebInspector.RenderingOptionsView.ShowActionDelegate.prototype = {
-    /**
-     * @override
-     * @param {!WebInspector.Context} context
-     * @param {string} actionId
-     * @return {boolean}
-     */
-    handleAction: function(context, actionId)
-    {
-        WebInspector.inspectorView.showViewInDrawer("rendering");
-        return true;
-    }
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/main/module.json b/third_party/WebKit/Source/devtools/front_end/main/module.json
index 9c4c309..cb9cd42 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/main/module.json
@@ -178,12 +178,6 @@
             ]
         },
         {
-            "type": "@WebInspector.ActionDelegate",
-            "actionId": "main.show-rendering-options",
-            "title": "Rendering settings",
-            "className": "WebInspector.RenderingOptionsView.ShowActionDelegate"
-        },
-        {
             "type": "@WebInspector.ToolbarItem.Provider",
             "separator": true,
             "location": "main-toolbar-left",
@@ -321,16 +315,10 @@
             "type": "context-menu-item",
             "location": "mainMenu/navigate",
             "title": "More tools",
-            "subMenuId": "mainMenu/tools",
+            "subMenuId": "mainMenuMoreTools",
             "order": 80
         },
         {
-            "type": "context-menu-item",
-            "location": "mainMenu/tools/open",
-            "order": 80,
-            "actionId": "main.show-rendering-options"
-        },
-        {
             "type": "drawer-view",
             "name": "rendering",
             "title": "Rendering",
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js
index 36ebc177..ba8ae54c 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js
@@ -244,25 +244,3 @@
         ]
     }
 ]
-
-/**
- * @constructor
- * @implements {WebInspector.ActionDelegate}
- */
-WebInspector.NetworkConfigView.ShowActionDelegate = function()
-{
-}
-
-WebInspector.NetworkConfigView.ShowActionDelegate.prototype = {
-    /**
-     * @override
-     * @param {!WebInspector.Context} context
-     * @param {string} actionId
-     * @return {boolean}
-     */
-    handleAction: function(context, actionId)
-    {
-        WebInspector.inspectorView.showViewInDrawer("network.config");
-        return true;
-    }
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/network/module.json b/third_party/WebKit/Source/devtools/front_end/network/module.json
index 63f5ac7..45e11269 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/network/module.json
@@ -68,18 +68,6 @@
             "experiment": "requestBlocking"
         },
         {
-            "type": "@WebInspector.ActionDelegate",
-            "actionId": "network.show-config",
-            "title": "Network conditions",
-            "className": "WebInspector.NetworkConfigView.ShowActionDelegate"
-        },
-        {
-            "type": "context-menu-item",
-            "location": "mainMenu/tools/open",
-            "order": 60,
-            "actionId": "network.show-config"
-        },
-        {
             "type": "drawer-view",
             "name": "network.config",
             "title": "Network conditions",
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/module.json b/third_party/WebKit/Source/devtools/front_end/screencast/module.json
index 64f46d99..e2d451f 100644
--- a/third_party/WebKit/Source/devtools/front_end/screencast/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/screencast/module.json
@@ -14,7 +14,7 @@
         {
             "type": "context-menu-item",
             "condition": "remoteFrontend",
-            "location": "mainMenu/tools",
+            "location": "mainMenu",
             "order": 10,
             "actionId": "components.request-app-banner"
         }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
index 44f865d7..03e46ff 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
@@ -213,10 +213,35 @@
             target.consoleModel.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, {result: result, wasThrown: wasThrown, text: requestedText, commandMessage: commandMessage, exceptionDetails: exceptionDetails});
         }
     }
-    if (/^\s*\{/.test(text) && /\}\s*$/.test(text))
-        text = "(" + text + ")";
-    executionContext.evaluate(text, "console", !!useCommandLineAPI, false, false, true, true, printResult);
 
+    /**
+     * @param {string} code
+     * @suppress {uselessCode}
+     * @return {boolean}
+     */
+    function looksLikeAnObjectLiteral(code)
+    {
+        // Only parenthesize what appears to be an object literal.
+        if (!(/^\s*\{/.test(code) && /\}\s*$/.test(code)))
+            return false;
+
+        try {
+            // Check if the code can be interpreted as an expression.
+            Function("return " + code + ";");
+
+            // No syntax error! Does it work parenthesized?
+            Function("(" + code + ")");
+
+            return true;
+        } catch (e) {
+            return false;
+        }
+    }
+
+    if (looksLikeAnObjectLiteral(text))
+        text = "(" + text + ")";
+
+    executionContext.evaluate(text, "console", !!useCommandLineAPI, false, false, true, true, printResult);
     WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.ConsoleEvaluated);
 }
 
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 bfa5d48..01b031b 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
@@ -961,6 +961,20 @@
         this._agent.setInspectedNode(node.id);
     },
 
+    /**
+     *  @return {?WebInspector.DOMNode}
+     */
+    enclosingElementOrSelf: function()
+    {
+        var node = this;
+        if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode)
+            node = node.parentNode;
+
+        if (node && node.nodeType() !== Node.ELEMENT_NODE)
+            node = null;
+        return node;
+    },
+
     __proto__: WebInspector.SDKObject.prototype
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
index 38aa0d4..e4a5580b 100644
--- a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
+++ b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
@@ -204,7 +204,7 @@
         var sectionName = descriptor["category"];
         var settingName = descriptor["settingName"];
         var setting = WebInspector.moduleSetting(settingName);
-        var uiTitle = WebInspector.UIString(extension.title(WebInspector.platform()));
+        var uiTitle = WebInspector.UIString(extension.title());
 
         var sectionElement = this._sectionElement(sectionName);
         var settingControl;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ActionRegistry.js b/third_party/WebKit/Source/devtools/front_end/ui/ActionRegistry.js
index e21053c..afc737b 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/ActionRegistry.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/ActionRegistry.js
@@ -170,7 +170,7 @@
      */
     title: function()
     {
-        var title = this._extension.title(WebInspector.platform());
+        var title = this._extension.title();
         var options = this._extension.descriptor()["options"];
         if (options) {
             for (var pair of options) {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js b/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js
index b46e31b..c48d5c87 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js
@@ -171,11 +171,14 @@
     /**
      * @param {string} label
      * @param {boolean=} disabled
+     * @param {string=} subMenuId
      * @return {!WebInspector.ContextSubMenuItem}
      */
-    appendSubMenuItem: function(label, disabled)
+    appendSubMenuItem: function(label, disabled, subMenuId)
     {
         var item = new WebInspector.ContextSubMenuItem(this._contextMenu, label, disabled);
+        if (subMenuId)
+            this._contextMenu._namedSubMenus.set(subMenuId, item);
         this._pushItem(item);
         return item;
     },
@@ -246,7 +249,7 @@
         {
             var subMenuId = extension.descriptor()["subMenuId"];
             if (subMenuId) {
-                var subMenuItem = menu.appendSubMenuItem(extension.title(WebInspector.platform()));
+                var subMenuItem = menu.appendSubMenuItem(extension.title(), false, subMenuId);
                 subMenuItem.appendItemsAtLocation(subMenuId);
             } else {
                 menu.appendAction(extension.descriptor()["actionId"]);
@@ -309,6 +312,8 @@
     this._y = y === undefined ? event.y : y;
     this._handlers = {};
     this._id = 0;
+    /** @type {!Map<string, !WebInspector.ContextSubMenuItem>} */
+    this._namedSubMenus = new Map();
 }
 
 WebInspector.ContextMenu.initialize = function()
@@ -483,6 +488,15 @@
         this._pendingTargets.push(target);
     },
 
+    /**
+     * @param {string} name
+     * @return {?WebInspector.ContextSubMenuItem}
+     */
+    namedSubMenu: function(name)
+    {
+        return this._namedSubMenus.get(name) || null;
+    },
+
     __proto__: WebInspector.ContextSubMenuItem.prototype
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js
index c20310c..d4aaba3 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js
@@ -391,7 +391,8 @@
     {
         if (this._subMenu)
             this._subMenu._discardSubMenus();
-        this.element.remove();
+        if (this.element)
+            this.element.remove();
         if (this._parentMenu)
             delete this._parentMenu._subMenu;
     }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
index 9f3fb088..5ab0706 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
@@ -1273,11 +1273,7 @@
             this._extensions.set(id, extensions[i]);
             if (this._isPermanentTab(id))
                 this._appendTab(extensions[i]);
-        }
-
-        for (var i = 0; i < extensions.length; i++) {
-            var id = extensions[i].descriptor()["name"];
-            if (this._isCloseableTab(id) && this._closeableTabSetting.get()[id])
+            else if (this._isCloseableTab(id) && this._closeableTabSetting.get()[id])
                 this._appendTab(extensions[i]);
         }
     },
@@ -1313,13 +1309,10 @@
      */
     _appendTabsToMenu: function(contextMenu)
     {
-        for (var id of this._extensions.keysArray().filter(this._isPermanentTab.bind(this))) {
-            var title = WebInspector.UIString(this._extensions.get(id).title(WebInspector.platform()));
-            contextMenu.appendItem(title, this.showTab.bind(this, id));
-        }
-        for (var id of this._extensions.keysArray().filter(this._isCloseableTab.bind(this))) {
-            var title = WebInspector.UIString(this._extensions.get(id).title(WebInspector.platform()));
-            contextMenu.appendItem(title, this.showTab.bind(this, id));
+        var extensions = self.runtime.extensions(this._extensionPoint, undefined, true);
+        for (var extension of extensions) {
+            var title = WebInspector.UIString(extension.title());
+            contextMenu.appendItem(title, this.showTab.bind(this, extension.descriptor()["name"]));
         }
     },
 
@@ -1330,7 +1323,7 @@
     {
         var descriptor = extension.descriptor();
         var id = descriptor["name"];
-        var title = WebInspector.UIString(extension.title(WebInspector.platform()));
+        var title = WebInspector.UIString(extension.title());
         var closeable = descriptor["persistence"] === "closeable" || descriptor["persistence"] === "temporary";
         this._tabbedPane.appendTab(id, title, this._views.get(id) || new WebInspector.Widget(), undefined, false, closeable);
     },
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js
index 76bac863..39788fa5 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js
@@ -307,7 +307,7 @@
 {
     var panelName = extension.descriptor()["name"];
     var tags = extension.descriptor()["tags"] || "";
-    return WebInspector.CommandMenu.createCommand(WebInspector.UIString("Panel"), tags, WebInspector.UIString("Show %s", extension.title(WebInspector.platform())), "", executeHandler, availableHandler);
+    return WebInspector.CommandMenu.createCommand(WebInspector.UIString("Panel"), tags, WebInspector.UIString("Show %s", extension.title()), "", executeHandler, availableHandler);
 
     /**
      * @return {boolean}
@@ -332,7 +332,7 @@
     var drawerId = extension.descriptor()["name"];
     var executeHandler = WebInspector.inspectorView.showViewInDrawer.bind(WebInspector.inspectorView, drawerId);
     var tags = extension.descriptor()["tags"] || "";
-    return WebInspector.CommandMenu.createCommand(WebInspector.UIString("Drawer"), tags, WebInspector.UIString("Show %s", extension.title(WebInspector.platform())), "", executeHandler);
+    return WebInspector.CommandMenu.createCommand(WebInspector.UIString("Drawer"), tags, WebInspector.UIString("Show %s", extension.title()), "", executeHandler);
 }
 
 /** @type {!WebInspector.CommandMenu} */
diff --git a/third_party/WebKit/Source/modules/OWNERS b/third_party/WebKit/Source/modules/OWNERS
index 72f11c26..6244e25 100644
--- a/third_party/WebKit/Source/modules/OWNERS
+++ b/third_party/WebKit/Source/modules/OWNERS
@@ -1,3 +1,4 @@
+esprehn@chromium.org
 haraken@chromium.org
 mkwst@chromium.org
 mlamouri@chromium.org
diff --git a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp
index 16149c1..ba29649 100644
--- a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp
+++ b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp
@@ -106,7 +106,7 @@
     , m_sourceBuffers(SourceBufferList::create(getExecutionContext(), m_asyncEventQueue.get()))
     , m_activeSourceBuffers(SourceBufferList::create(getExecutionContext(), m_asyncEventQueue.get()))
     , m_liveSeekableRange(TimeRanges::create())
-    , m_isAddedToRegistry(false)
+    , m_addedToRegistryCounter(0)
 {
     MSLOG << __FUNCTION__ << " this=" << this;
 }
@@ -302,14 +302,15 @@
 
 void MediaSource::addedToRegistry()
 {
-    DCHECK(!m_isAddedToRegistry);
-    m_isAddedToRegistry = true;
+    ++m_addedToRegistryCounter;
+    // Ensure there's no counter overflow.
+    CHECK_GT(m_addedToRegistryCounter, 0);
 }
 
 void MediaSource::removedFromRegistry()
 {
-    DCHECK(m_isAddedToRegistry);
-    m_isAddedToRegistry = false;
+    DCHECK_GT(m_addedToRegistryCounter, 0);
+    --m_addedToRegistryCounter;
 }
 
 double MediaSource::duration() const
@@ -648,7 +649,7 @@
 {
     return m_attachedElement || m_webMediaSource
         || m_asyncEventQueue->hasPendingEvents()
-        || m_isAddedToRegistry;
+        || m_addedToRegistryCounter > 0;
 }
 
 void MediaSource::stop()
diff --git a/third_party/WebKit/Source/modules/mediasource/MediaSource.h b/third_party/WebKit/Source/modules/mediasource/MediaSource.h
index a82b36bec..e6abbb5 100644
--- a/third_party/WebKit/Source/modules/mediasource/MediaSource.h
+++ b/third_party/WebKit/Source/modules/mediasource/MediaSource.h
@@ -145,7 +145,7 @@
 
     Member<TimeRanges> m_liveSeekableRange;
 
-    bool m_isAddedToRegistry;
+    int m_addedToRegistryCounter;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index ebed1a6..382461c7 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -6152,7 +6152,7 @@
     std::unique_ptr<WebGraphicsContext3DProvider> contextProvider = wrapUnique(Platform::current()->createOffscreenGraphicsContext3DProvider(
         attributes, canvas()->document().topDocument().url(), 0, &glInfo));
     RefPtr<DrawingBuffer> buffer;
-    if (contextProvider->bindToCurrentThread()) {
+    if (contextProvider && contextProvider->bindToCurrentThread()) {
         // Construct a new drawing buffer with the new GL context.
         buffer = createDrawingBuffer(std::move(contextProvider));
         // If DrawingBuffer::create() fails to allocate a fbo, |drawingBuffer| is set to null.
diff --git a/third_party/WebKit/Source/platform/inspector_protocol/String16STL.h b/third_party/WebKit/Source/platform/inspector_protocol/String16STL.h
index 7b185a2..e86c405 100644
--- a/third_party/WebKit/Source/platform/inspector_protocol/String16STL.h
+++ b/third_party/WebKit/Source/platform/inspector_protocol/String16STL.h
@@ -243,6 +243,17 @@
 };
 } // namespace WTF
 
+
+namespace std {
+template<> struct hash<String16> {
+    std::size_t operator()(const String16& string) const
+    {
+        return string.hash();
+    }
+};
+
+} // namespace std
+
 using String = WTF::String;
 
 #endif // !defined(String16STL_h)
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InspectedContext.h b/third_party/WebKit/Source/platform/v8_inspector/InspectedContext.h
index 16a2326..ecff5e4 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/InspectedContext.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/InspectedContext.h
@@ -6,6 +6,7 @@
 #define InspectedContext_h
 
 #include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/Platform.h"
 #include "platform/inspector_protocol/String16.h"
 #include <v8.h>
 
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
index e4c9083..d59b983a 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
@@ -17,7 +17,7 @@
 
 namespace {
 
-String messageSourceValue(MessageSource source)
+String16 messageSourceValue(MessageSource source)
 {
     switch (source) {
     case XMLMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Xml;
@@ -35,7 +35,7 @@
 }
 
 
-String messageTypeValue(MessageType type)
+String16 messageTypeValue(MessageType type)
 {
     switch (type) {
     case LogMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Log;
@@ -54,7 +54,7 @@
     return protocol::Console::ConsoleMessage::TypeEnum::Log;
 }
 
-String messageLevelValue(MessageLevel level)
+String16 messageLevelValue(MessageLevel level)
 {
     switch (level) {
     case DebugMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum::Debug;
@@ -141,8 +141,10 @@
 
     bool append(v8::Local<v8::Array> array)
     {
-        if (m_visitedArrays.contains(array))
-            return true;
+        for (const auto& it : m_visitedArrays) {
+            if (it == array)
+                return true;
+        }
         uint32_t length = array->Length();
         if (length > m_arrayLimit)
             return false;
@@ -151,7 +153,7 @@
 
         bool result = true;
         m_arrayLimit -= length;
-        m_visitedArrays.append(array);
+        m_visitedArrays.push_back(array);
         for (uint32_t i = 0; i < length; ++i) {
             if (i)
                 m_builder.append(',');
@@ -160,7 +162,7 @@
                 break;
             }
         }
-        m_visitedArrays.removeLast();
+        m_visitedArrays.pop_back();
         return result;
     }
 
@@ -191,7 +193,7 @@
     uint32_t m_arrayLimit;
     v8::Isolate* m_isolate;
     String16Builder m_builder;
-    Vector<v8::Local<v8::Array>> m_visitedArrays;
+    std::vector<v8::Local<v8::Array>> m_visitedArrays;
     v8::TryCatch m_tryCatch;
 };
 
@@ -244,7 +246,7 @@
     result->setLine(static_cast<int>(m_lineNumber));
     result->setColumn(static_cast<int>(m_columnNumber));
     if (m_scriptId)
-        result->setScriptId(String::number(m_scriptId));
+        result->setScriptId(String16::number(m_scriptId));
     result->setUrl(m_url);
     if (m_source == NetworkMessageSource && !m_requestIdentifier.isEmpty())
         result->setNetworkRequestId(m_requestIdentifier);
@@ -303,7 +305,7 @@
         if (m_columnNumber)
             details->setColumnNumber(static_cast<int>(m_columnNumber) - 1);
         if (m_scriptId)
-            details->setScriptId(String::number(m_scriptId));
+            details->setScriptId(String16::number(m_scriptId));
         if (m_stackTrace)
             details->setStack(m_stackTrace->buildInspectorObject());
 
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
index 23ed3fa4..1bc5962 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
@@ -21,6 +21,8 @@
 #include "platform/v8_inspector/public/V8DebuggerClient.h"
 #include "platform/v8_inspector/public/V8ToProtocolValue.h"
 
+#include <algorithm>
+
 using blink::protocol::Array;
 using blink::protocol::Maybe;
 using blink::protocol::Debugger::BreakpointId;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerScript.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerScript.cpp
index cc1b251..487fa25 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerScript.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerScript.cpp
@@ -5,6 +5,7 @@
 #include "platform/v8_inspector/V8DebuggerScript.h"
 
 #include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/Platform.h"
 #include "platform/v8_inspector/V8StringUtil.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h
index f32d0e5..dff99a2 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h
@@ -13,6 +13,8 @@
 
 namespace blink {
 
+class V8StackTrace;
+
 class PLATFORM_EXPORT V8DebuggerClient {
 public:
     virtual ~V8DebuggerClient() { }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.cpp b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.cpp
index fadab16d..f118dca 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.cpp
@@ -13,6 +13,7 @@
 namespace blink {
 
 V8Inspector::V8Inspector(v8::Isolate* isolate, v8::Local<v8::Context> context)
+    : m_context(context)
 {
     m_debugger = V8Debugger::create(isolate, this);
     m_debugger->contextCreated(V8ContextInfo(context, 1, true, "",
@@ -55,18 +56,9 @@
         m_session->dispatchProtocolMessage(message);
 }
 
-int V8Inspector::ensureDefaultContextInGroup(int contextGroupId)
+v8::Local<v8::Context> V8Inspector::ensureDefaultContextInGroup(int)
 {
-    return 1;
-}
-
-void V8Inspector::muteConsole()
-{
-}
-
-void V8Inspector::unmuteConsole()
-{
-
+    return m_context;
 }
 
 bool V8Inspector::isExecutionAllowed()
@@ -74,4 +66,9 @@
     return true;
 }
 
+bool V8Inspector::canExecuteScripts()
+{
+    return true;
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h
index 38bbc88..3f689ae 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h
@@ -42,36 +42,39 @@
     void unmuteWarningsAndDeprecations() override { }
     double currentTimeMS() override { return 0; };
 
-    void muteConsole() override;
-    void unmuteConsole() override;
     bool isExecutionAllowed() override;
-    int ensureDefaultContextInGroup(int contextGroupId) override;
+    v8::Local<v8::Context> ensureDefaultContextInGroup(int contextGroupId) override;
     void beginUserGesture() override { }
     void endUserGesture() override { }
     bool isInspectableHeapObject(v8::Local<v8::Object>) override { return true; }
     void consoleTime(const String16& title) override { }
     void consoleTimeEnd(const String16& title) override { }
     void consoleTimeStamp(const String16& title) override { }
+    void messageAddedToConsole(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, V8StackTrace*) override { }
     v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*, v8::Local<v8::Context>) override
     {
         return v8::MaybeLocal<v8::Value>();
     }
-    void reportMessageToConsole(v8::Local<v8::Context>, MessageType, MessageLevel, const String16& message, const v8::FunctionCallbackInfo<v8::Value>* arguments, unsigned skipArgumentCount) override { }
     void installAdditionalCommandLineAPI(v8::Local<v8::Context>, v8::Local<v8::Object>) override { }
-
-    // V8InspectorSessionClient
-    void startInstrumenting() override { }
-    void stopInstrumenting() override { }
-    void resumeStartup() override { }
-    bool canExecuteScripts() override { return true; }
-    void profilingStarted() override { }
-    void profilingStopped() override { }
+    void enableAsyncInstrumentation() override { }
+    void disableAsyncInstrumentation() override { }
     void startRepeatingTimer(double, TimerCallback, void* data) override { }
     void cancelTimer(void* data) override { }
 
+    // V8InspectorSessionClient
+    void runtimeEnabled() override { };
+    void runtimeDisabled() override { };
+    void resumeStartup() override { };
+    bool canExecuteScripts() override;
+    void profilingStarted() override { };
+    void profilingStopped() override { };
+    void consoleEnabled() override { };
+    void consoleCleared() override { };
+
     std::unique_ptr<V8Debugger> m_debugger;
     std::unique_ptr<V8InspectorSession> m_session;
     String16 m_state;
+    v8::Local<v8::Context> m_context;
 };
 
 }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp b/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp
index f6b39a7f..4433b04 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp
+++ b/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp
@@ -150,6 +150,8 @@
         '<(SHARED_INTERMEDIATE_DIR)/blink',
       ],
       'sources': [
+        '<(blink_platform_output_dir)/v8_inspector/protocol/Console.cpp',
+        '<(blink_platform_output_dir)/v8_inspector/protocol/Console.h',
         '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.cpp',
         '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.h',
         '<(blink_platform_output_dir)/v8_inspector/protocol/HeapProfiler.cpp',
@@ -194,6 +196,10 @@
         'RemoteObjectId.h',
         'V8Console.cpp',
         'V8Console.h',
+        'V8ConsoleAgentImpl.cpp',
+        'V8ConsoleAgentImpl.h',
+        'V8ConsoleMessage.cpp',
+        'V8ConsoleMessage.h',
         'V8DebuggerAgentImpl.cpp',
         'V8DebuggerAgentImpl.h',
         'V8DebuggerImpl.cpp',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py
index 77424eec..de91521 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py
@@ -285,18 +285,18 @@
 
     def __init__(self, options=None):
         super(AbstractParallelRebaselineCommand, self).__init__(options=options)
-        self._builder_data = {}
 
+    @memoized
     def builder_data(self):
-        if not self._builder_data:
-            for builder_name in self._release_builders():
-                builder = self._tool.buildbot.builder_with_name(builder_name)
-                builder_results = builder.latest_layout_test_results()
-                if builder_results:
-                    self._builder_data[builder_name] = builder_results
-                else:
-                    raise Exception("No result for builder %s." % builder_name)
-        return self._builder_data
+        builder_to_results = {}
+        for builder_name in self._release_builders():
+            builder = self._tool.buildbot.builder_with_name(builder_name)
+            builder_results = builder.latest_layout_test_results()
+            if builder_results:
+                builder_to_results[builder_name] = builder_results
+            else:
+                raise Exception("No result for builder %s." % builder_name)
+        return builder_to_results
 
     # The release builders cycle much faster than the debug ones and cover all the platforms.
     def _release_builders(self):
@@ -346,7 +346,7 @@
                 builders_to_fallback_paths[builder] = fallback_path
         return builders_to_fallback_paths.keys()
 
-    def _rebaseline_commands(self, test_prefix_list, options):
+    def _rebaseline_commands(self, test_prefix_list, options, skip_checking_actual_results=False):
         path_to_webkit_patch = self._tool.path()
         cwd = self._tool.scm().checkout_root
         copy_baseline_commands = []
@@ -357,8 +357,13 @@
         for test_prefix in test_prefix_list:
             for test in port.tests([test_prefix]):
                 for builder in self._builders_to_fetch_from(test_prefix_list[test_prefix]):
-                    actual_failures_suffixes = self._suffixes_for_actual_failures(
-                        test, builder, test_prefix_list[test_prefix][builder])
+                    # TODO(qyearsley): Remove the parameter skip_checking_actual_results
+                    # and instead refactor the existing code so that this is not necessary.
+                    if skip_checking_actual_results:
+                        actual_failures_suffixes = test_prefix_list[test_prefix][builder]
+                    else:
+                        actual_failures_suffixes = self._suffixes_for_actual_failures(
+                            test, builder, test_prefix_list[test_prefix][builder])
                     if not actual_failures_suffixes:
                         # If we're not going to rebaseline the test because it's passing on this
                         # builder, we still want to remove the line from TestExpectations.
@@ -491,7 +496,7 @@
             self._tool.scm().add_list(files_to_add)
         return lines_to_remove
 
-    def _rebaseline(self, options, test_prefix_list):
+    def _rebaseline(self, options, test_prefix_list, skip_checking_actual_results=False):
         """Downloads new baselines in parallel, then updates expectations files
         and optimizes baselines.
 
@@ -507,13 +512,18 @@
                 "some/test.html" on both builder-1 and builder-2, and new text
                 baselines should be downloaded for "some/other.html" but only
                 from builder-1.
+            skip_checking_actual_results: If True, then the lists of suffixes
+                to rebaseline from |test_prefix_list| will be used directly;
+                if False, then the list of suffixes will filtered to include
+                suffixes with mismatches in actual results.
         """
         for test, builders_to_check in sorted(test_prefix_list.items()):
             _log.info("Rebaselining %s" % test)
             for builder, suffixes in sorted(builders_to_check.items()):
                 _log.debug("  %s: %s" % (builder, ",".join(suffixes)))
 
-        copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = self._rebaseline_commands(test_prefix_list, options)
+        copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = self._rebaseline_commands(
+            test_prefix_list, options, skip_checking_actual_results)
         lines_to_remove = {}
 
         self._run_in_parallel_and_update_scm(copy_baseline_commands)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
index 879285b..bd8cdf11 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
@@ -6,18 +6,15 @@
 
 This command interacts with the Rietveld API to get information about try jobs
 with layout test results.
-
-TODO(qyearsley): Finish this module. After getting a list of try bots:
-  - For each bot get the list of tests to rebaseline.
-  - Invoke webkit-patch rebaseline-test-internal to fetch the baselines.
 """
 
 import logging
 import optparse
 
 from webkitpy.common.net.rietveld import latest_try_jobs
-from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand
 from webkitpy.common.net.web import Web
+from webkitpy.layout_tests.models.test_expectations import BASELINE_SUFFIX_LIST
+from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand
 
 
 _log = logging.getLogger(__name__)
@@ -32,12 +29,65 @@
         super(RebaselineFromTryJobs, self).__init__(options=[
             optparse.make_option(
                 '--issue', type='int', default=None,
-                help="Rietveld issue number."),
+                help='Rietveld issue number.'),
+            optparse.make_option(
+                '--dry-run', action='store_true', default=False,
+                help='Dry run mode; list actions that would be performed but do not do anything.'),
+            self.no_optimize_option,
+            self.results_directory_option,
         ])
         self.web = Web()
 
+    def execute(self, options, args, tool):
+        if not options.issue:
+            # TODO(qyearsley): If no issue number is given, get the one for the current branch.
+            _log.info('No issue number provided.')
+            return
+
+        if args:
+            test_prefix_list = {}
+            try_jobs = latest_try_jobs(options.issue, self._try_bots(), self.web)
+            builders = [j.builder_name for j in try_jobs]
+            for t in args:
+                test_prefix_list[t] = {b: BASELINE_SUFFIX_LIST for b in builders}
+        else:
+            test_prefix_list = self._test_prefix_list(options.issue)
+        self._log_test_prefix_list(test_prefix_list)
+
+        if options.dry_run:
+            return
+        self._rebaseline(options, test_prefix_list, skip_checking_actual_results=True)
+
+    def _test_prefix_list(self, issue_number):
+        """Returns a collection of test, builder and file extensions to get new baselines for."""
+        builders_to_tests = self._builders_to_tests(issue_number)
+        result = {}
+        for builder, tests in builders_to_tests.iteritems():
+            for test in tests:
+                if test not in result:
+                    result[test] = {}
+                # TODO(qyearsley): Consider using TestExpectations.suffixes_for_test_result.
+                result[test][builder] = BASELINE_SUFFIX_LIST
+        return result
+
+    def _builders_to_tests(self, issue_number):
+        """Fetches a list of try bots, and for each, fetches tests with new baselines."""
+        _log.debug('Getting results for Rietveld issue %d.' % issue_number)
+        try_jobs = latest_try_jobs(issue_number, self._try_bots(), self.web)
+        if not try_jobs:
+            _log.debug('No try job results for builders in: %r.' % (self._try_bots(),))
+        builders_to_tests = {}
+        for job in try_jobs:
+            test_results = self._unexpected_mismatch_results(job)
+            builders_to_tests[job.builder_name] = sorted(r.test_name() for r in test_results)
+        return builders_to_tests
+
+    def _try_bots(self):
+        """Retuns a collection of try bot builders to fetch results for."""
+        return self._tool.builders.all_try_builder_names()
 
     def _unexpected_mismatch_results(self, try_job):
+        """Fetches a list of LayoutTestResult objects for unexpected results with new baselines."""
         results_url = self._results_url(try_job.builder_name, try_job.build_number)
         builder = self._tool.buildbot.builder_with_name(try_job.builder_name)
         layout_test_results = builder.fetch_layout_test_results(results_url)
@@ -46,28 +96,12 @@
             return []
         return layout_test_results.unexpected_mismatch_results()
 
-    def try_bots(self):
-        return self._tool.builders.all_try_builder_names()
-
-    def execute(self, options, args, tool):
-        if not options.issue:
-            # TODO(qyearsley): Later, the default behavior will be to run
-            # git cl issue to get the issue number, then get lists of tests
-            # to rebaseline and download new baselines.
-            _log.info('No issue number provided.')
+    @staticmethod
+    def _log_test_prefix_list(test_prefix_list):
+        """Logs the tests to download new baselines for."""
+        if not test_prefix_list:
+            _log.info('No tests to rebaseline.')
             return
-        _log.info('Getting results for Rietveld issue %d.' % options.issue)
-
-        jobs = latest_try_jobs(options.issue, self.try_bots(), self.web)
-
-        for job in jobs:
-            _log.info('  Builder: %s', job.builder_name)
-            _log.info('  Build: %s', job.build_number)
-            test_results = self._unexpected_mismatch_results(job)
-            if test_results:
-                for result in test_results:
-                    _log.info(
-                        '%s (actual: %s, expected: %s)', result.test_name(),
-                        result.actual_results(), result.expected_results())
-            else:
-                _log.info('No unexpected test results.')
+        _log.info('Tests to rebaseline:')
+        for test, builders in test_prefix_list.iteritems():
+            _log.info('  %s: %s', test, ', '.join(sorted(builders)))
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
index 68bd5817..30820fca 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
@@ -10,6 +10,7 @@
 from webkitpy.tool.commands.rebaseline_from_try_jobs import RebaselineFromTryJobs
 from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
 from webkitpy.tool.mock_tool import MockOptions
+from webkitpy.layout_tests.builder_list import BuilderList
 
 
 class RebaselineFromTryJobsTest(BaseTestCase):
@@ -27,6 +28,10 @@
                         'builder': 'MOCK Try Win',
                         'buildnumber': 5000,
                     },
+                    {
+                        'builder': 'MOCK Mac Try',
+                        'buildnumber': 4000,
+                    },
                 ],
             }),
         })
@@ -47,17 +52,19 @@
         oc = OutputCapture()
         try:
             oc.capture_output()
-            self.command.execute(MockOptions(issue=11112222), [], self.tool)
+            options = MockOptions(issue=11112222, dry_run=False, optimize=True, verbose=False)
+            self.command.execute(options, [], self.tool)
         finally:
             _, _, logs = oc.restore_output()
         self.assertEqual(
             logs,
-            ('Getting results for Rietveld issue 11112222.\n'
-             '  Builder: MOCK Try Win\n'
-             '  Build: 5000\n'
-             'fast/dom/prototype-inheritance.html (actual: TEXT, expected: PASS)\n'
-             'fast/dom/prototype-taco.html (actual: PASS TEXT, expected: PASS)\n'
-             'svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html (actual: IMAGE, expected: PASS)\n'))
+            ('Tests to rebaseline:\n'
+             '  svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html: MOCK Try Win\n'
+             '  fast/dom/prototype-inheritance.html: MOCK Try Win\n'
+             '  fast/dom/prototype-taco.html: MOCK Try Win\n'
+             'Rebaselining fast/dom/prototype-inheritance.html\n'
+             'Rebaselining fast/dom/prototype-taco.html\n'
+             'Rebaselining svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html\n'))
 
     def test_execute_with_no_issue_number(self):
         oc = OutputCapture()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
index ec999679..2a9632b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
@@ -52,6 +52,7 @@
         # we can make the default port also a "test" port.
         self.original_port_factory_get = self.tool.port_factory.get
         test_port = self.tool.port_factory.get('test')
+        self._builder_data = {}
 
         def get_test_port(port_name=None, options=None, **kwargs):
             if not port_name:
@@ -96,8 +97,14 @@
                 }
             }
         })
-        for builder in ['MOCK Win7', 'MOCK Win7 (dbg)', 'MOCK Mac10.11']:
-            self.command._builder_data[builder] = data
+
+        def builder_data():
+            self._builder_data = {}
+            for builder in ['MOCK Win7', 'MOCK Win7 (dbg)', 'MOCK Mac10.11']:
+                self._builder_data[builder] = data
+            return self._builder_data
+
+        self.command.builder_data = builder_data
 
 class TestCopyExistingBaselinesInternal(BaseTestCase):
     command_constructor = CopyExistingBaselinesInternal
@@ -337,7 +344,7 @@
         self._setup_mock_builder_data()
 
         def builder_data():
-            self.command._builder_data['MOCK Win7'] = LayoutTestResults({
+            self._builder_data['MOCK Win7'] = LayoutTestResults({
                 "tests": {
                     "userscripts": {
                         "first-test.html": {
@@ -347,7 +354,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -602,7 +609,7 @@
         self.tool.executive = MockExecutive2()
 
         def builder_data():
-            self.command._builder_data['MOCK Mac10.11'] = self.command._builder_data['MOCK Mac10.10'] = LayoutTestResults({
+            self._builder_data['MOCK Mac10.11'] = self._builder_data['MOCK Mac10.10'] = LayoutTestResults({
                 "tests": {
                     "userscripts": {
                         "another-test.html": {
@@ -616,7 +623,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -659,7 +666,7 @@
         self.tool.executive = MockExecutive2()
 
         def builder_data():
-            self.command._builder_data['MOCK Mac10.10'] = self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({
+            self._builder_data['MOCK Mac10.10'] = self._builder_data['MOCK Mac10.11'] = LayoutTestResults({
                 "tests": {
                     "userscripts": {
                         "reftest-text.html": {
@@ -677,7 +684,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -745,7 +752,7 @@
         test_port = self.tool.port_factory.get('test')
 
         def builder_data():
-            self.command._builder_data['MOCK Mac10.10'] = self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({
+            self._builder_data['MOCK Mac10.10'] = self._builder_data['MOCK Mac10.11'] = LayoutTestResults({
                 "tests": {
                     "fast": {
                         "dom": {
@@ -758,7 +765,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -785,7 +792,7 @@
 
     def test_rebaseline_missing(self):
         def builder_data():
-            self.command._builder_data['MOCK Mac10.10'] = LayoutTestResults({
+            self._builder_data['MOCK Mac10.10'] = LayoutTestResults({
                 "tests": {
                     "fast": {
                         "dom": {
@@ -812,7 +819,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -1049,11 +1056,9 @@
 
         test_port = self.tool.port_factory.get('test')
 
-        original_builder_data = self.command.builder_data
         def builder_data():
-            original_builder_data()
             # Have prototype-chocolate only fail on "MOCK Mac10.11".
-            self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({
+            self._builder_data['MOCK Mac10.11'] = LayoutTestResults({
                 "tests": {
                     "fast": {
                         "dom": {
@@ -1075,7 +1080,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -1109,31 +1114,22 @@
 
         self.assertEqual(self.tool.executive.calls, [
             [
-                ['python', 'echo', 'copy-existing-baselines-internal', '--suffixes', 'txt,png',
-                 '--builder', 'MOCK Mac10.10', '--test', 'fast/dom/prototype-chocolate.html'],
                 ['python', 'echo', 'copy-existing-baselines-internal', '--suffixes', 'png',
                  '--builder', 'MOCK Mac10.11', '--test', 'fast/dom/prototype-strawberry.html'],
                 ['python', 'echo', 'copy-existing-baselines-internal', '--suffixes', 'txt',
-                 '--builder', 'MOCK Mac10.10', '--test', 'fast/dom/prototype-taco.html'],
-                ['python', 'echo', 'copy-existing-baselines-internal', '--suffixes', 'txt',
                  '--builder', 'MOCK Mac10.11', '--test', 'fast/dom/prototype-taco.html'],
             ],
             [
-                ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'txt,png',
-                 '--builder', 'MOCK Mac10.10', '--test', 'fast/dom/prototype-chocolate.html'],
-                ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'png', '--builder',
-                 'MOCK Mac10.11', '--test', 'fast/dom/prototype-strawberry.html'],
-                ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'txt',
-                 '--builder', 'MOCK Mac10.10', '--test', 'fast/dom/prototype-taco.html'],
+                ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'png',
+                 '--builder', 'MOCK Mac10.11', '--test', 'fast/dom/prototype-strawberry.html'],
                 ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'txt',
                  '--builder', 'MOCK Mac10.11', '--test', 'fast/dom/prototype-taco.html'],
             ],
             [
                 ['python', 'echo', 'optimize-baselines', '--no-modify-scm',
-                 '--suffixes', 'txt,png', 'fast/dom/prototype-chocolate.html'],
-                ['python', 'echo', 'optimize-baselines', '--no-modify-scm',
                  '--suffixes', 'png', 'fast/dom/prototype-strawberry.html'],
-                ['python', 'echo', 'optimize-baselines', '--no-modify-scm', '--suffixes', 'txt', 'fast/dom/prototype-taco.html'],
+                ['python', 'echo', 'optimize-baselines', '--no-modify-scm',
+                 '--suffixes', 'txt', 'fast/dom/prototype-taco.html'],
             ],
             ['git', 'cl', 'upload', '-f'],
             ['git', 'pull'],
@@ -1162,8 +1158,8 @@
         original_builder_data = self.command.builder_data
         def builder_data():
             original_builder_data()
-            # have prototype-chocolate only fail on "MOCK Mac10.10".
-            self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({
+            # Have prototype-chocolate only fail on "MOCK Mac10.11".
+            self._builder_data['MOCK Mac10.11'] = LayoutTestResults({
                 "tests": {
                     "fast": {
                         "dom": {
@@ -1176,7 +1172,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -1219,7 +1215,7 @@
         test_port = self.tool.port_factory.get('test')
 
         def builder_data():
-            self.command._builder_data['MOCK Mac10.10'] = self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({
+            self._builder_data['MOCK Mac10.10'] = self._builder_data['MOCK Mac10.11'] = LayoutTestResults({
                 "tests": {
                     "fast": {
                         "dom": {
@@ -1232,7 +1228,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -1273,7 +1269,7 @@
         test_port = self.tool.port_factory.get('test')
 
         def builder_data():
-            self.command._builder_data['MOCK Win'] = LayoutTestResults({
+            self._builder_data['MOCK Win'] = LayoutTestResults({
                 "tests": {
                     "fast": {
                         "dom": {
@@ -1286,7 +1282,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -1329,7 +1325,7 @@
         test_port = self.tool.port_factory.get('test')
 
         def builder_data():
-            self.command._builder_data['MOCK Win'] = LayoutTestResults({
+            self._builder_data['MOCK Win'] = LayoutTestResults({
                 "tests": {
                     "fast": {
                         "dom": {
@@ -1342,7 +1338,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
@@ -1386,7 +1382,7 @@
         test_port = self.tool.port_factory.get('test')
 
         def builder_data():
-            self.command._builder_data['MOCK Mac10.10'] = self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({
+            self._builder_data['MOCK Mac10.10'] = self._builder_data['MOCK Mac10.11'] = LayoutTestResults({
                 "tests": {
                     "fast": {
                         "dom": {
@@ -1399,7 +1395,7 @@
                     }
                 }
             })
-            return self.command._builder_data
+            return self._builder_data
 
         self.command.builder_data = builder_data
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
index db9fda2..03a437f 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
@@ -191,9 +191,23 @@
         else:
             self.print_('## Done: no changes to import.')
 
-    def is_manual_test(self, fs, dirname, basename):  # Callback for FileSystem.files_under; not all arguments used - pylint: disable=unused-argument
-        # We are importing manual pointer event tests and we are automating them.
-        return ("pointerevents" not in dirname) and (basename.endswith('-manual.html') or basename.endswith('-manual.htm'))
+    def is_manual_test(self, fs, dirname, basename):
+        """Returns True if the file should be removed because it's a manual test.
+
+        Tests with "-manual" in the name are not considered manual tests
+        if there is a corresponding JS automation file.
+        """
+        basename_without_extension, _ = basename.rsplit('.', 1)
+        if not basename_without_extension.endswith('-manual'):
+            return False
+        dir_from_wpt = fs.relpath(dirname, self.path_from_webkit_base('LayoutTests', 'imported', 'wpt'))
+        automation_dir = self.path_from_webkit_base('LayoutTests', 'imported', 'wpt_automation', dir_from_wpt)
+        # TODO(qyearsley): Update this when all *-input.js are renamed to *-automation.js.
+        if fs.isfile(fs.join(automation_dir, '%s-input.js' % basename_without_extension)):
+            return False
+        if fs.isfile(fs.join(automation_dir, '%s-automation.js' % basename_without_extension)):
+            return False
+        return True
 
     def is_baseline(self, fs, dirname, basename):  # Callback for FileSystem.files_under; not all arguments used - pylint: disable=unused-argument
         return basename.endswith('-expected.txt')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
index 50da6a5b..5789130 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
@@ -6,6 +6,7 @@
 
 from webkitpy.w3c.deps_updater import DepsUpdater
 from webkitpy.common.host_mock import MockHost
+from webkitpy.common.system.filesystem_mock import MockFileSystem
 
 
 class DepsUpdaterTest(unittest.TestCase):
@@ -41,3 +42,29 @@
                 'chromeos_daisy'
             ])
         })
+
+    def test_is_manual_test_regular_test(self):
+        updater = DepsUpdater(MockHost())
+        fs = MockFileSystem()
+        dirname = '/mock-checkout/third_party/WebKit/LayoutTests/imported/wpt/a'
+        self.assertFalse(updater.is_manual_test(fs, dirname, 'test.html'))
+        self.assertFalse(updater.is_manual_test(fs, dirname, 'manual-foo.htm'))
+        self.assertFalse(updater.is_manual_test(fs, dirname, 'script.js'))
+
+    def test_is_manual_test_no_automation_file(self):
+        updater = DepsUpdater(MockHost())
+        fs = MockFileSystem()
+        dirname = '/mock-checkout/third_party/WebKit/LayoutTests/imported/wpt/a'
+        self.assertTrue(updater.is_manual_test(fs, dirname, 'test-manual.html'))
+        self.assertTrue(updater.is_manual_test(fs, dirname, 'test-manual.htm'))
+        self.assertTrue(updater.is_manual_test(fs, dirname, 'test-manual.xht'))
+
+    def test_is_manual_test_with_corresponding_automation_file(self):
+        updater = DepsUpdater(MockHost())
+        imported_dir = '/mock-checkout/third_party/WebKit/LayoutTests/imported/'
+        fs = MockFileSystem(files={
+            imported_dir + 'wpt_automation/a/x-manual-input.js': '',
+            imported_dir + 'wpt_automation/a/y-manual-automation.js': '',
+        })
+        self.assertFalse(updater.is_manual_test(fs, imported_dir + 'wpt/a', 'y-manual.html'))
+        self.assertFalse(updater.is_manual_test(fs, imported_dir + 'wpt/a', 'x-manual.html'))
diff --git a/tools/bisect-builds.py b/tools/bisect-builds.py
index f080e18f..e89ce104 100755
--- a/tools/bisect-builds.py
+++ b/tools/bisect-builds.py
@@ -894,7 +894,7 @@
     m = blink_re.search(url.read())
     url.close()
     if m:
-      return m.group(1)]
+      return m.group(1)
 
   url = urllib.urlopen(DEPS_FILE % GetGitHashFromSVNRevision(rev))
   if url.getcode() == 200:
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py
index cc4415b..fb958605 100755
--- a/tools/clang/scripts/package.py
+++ b/tools/clang/scripts/package.py
@@ -288,6 +288,17 @@
               filter=PrintTarProgress)
     MaybeUpload(args, golddir, platform)
 
+  # Zip up llvm-objdump for sanitizer coverage.
+  objdumpdir = 'llvmobjdump-' + stamp
+  shutil.rmtree(objdumpdir, ignore_errors=True)
+  os.makedirs(os.path.join(objdumpdir, 'bin'))
+  shutil.copy(os.path.join(LLVM_RELEASE_DIR, 'bin', 'llvm-objdump' + exe_ext),
+              os.path.join(objdumpdir, 'bin'))
+  with tarfile.open(objdumpdir + '.tgz', 'w:gz') as tar:
+    tar.add(os.path.join(objdumpdir, 'bin'), arcname='bin',
+            filter=PrintTarProgress)
+  MaybeUpload(args, objdumpdir, platform)
+
   # FIXME: Warn if the file already exists on the server.
 
 
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc
index 90642d4..7fe64fd 100644
--- a/tools/gn/target_generator.cc
+++ b/tools/gn/target_generator.cc
@@ -305,7 +305,7 @@
     if (!outputs.required_types().empty()) {
       *err_ = Err(*value, "Source expansions not allowed here.",
           "The outputs of this target used source {{expansions}} but this "
-          "targe type\ndoesn't support them. Just express the outputs "
+          "target type\ndoesn't support them. Just express the outputs "
           "literally.");
       return false;
     }
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 84a0cdd..78e185b6 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -22700,20 +22700,6 @@
   <summary>Records the autoplay source of muted videos.</summary>
 </histogram>
 
-<histogram name="Media.Video.Autoplay.Muted.PlayMethod.BecomesVisible"
-    enum="Boolean">
-  <owner>avayvod@chromium.org</owner>
-  <owner>mlamouri@chromium.org</owner>
-  <owner>zqzhang@chromium.org</owner>
-  <summary>
-    Records muted video started playing with play() become visible at some
-    point. The UMA for false is not complete since it is recorded in a
-    destructor which is garbage-collected. Please subtract
-    Media.Video.Autoplay.Muted &quot;play() method&quot; count with the true
-    count of this histogram to obtain the real false count.
-  </summary>
-</histogram>
-
 <histogram name="Media.Video.Autoplay.Muted.UnmuteAction" enum="BooleanSuccess">
   <owner>avayvod@chromium.org</owner>
   <owner>mlamouri@chromium.org</owner>
diff --git a/tools/perf/page_sets/tough_scheduling_cases/raf_touch_animation.html b/tools/perf/page_sets/tough_scheduling_cases/raf_touch_animation.html
index c2757f2..2e199d6 100644
--- a/tools/perf/page_sets/tough_scheduling_cases/raf_touch_animation.html
+++ b/tools/perf/page_sets/tough_scheduling_cases/raf_touch_animation.html
@@ -59,12 +59,13 @@
 
     function startExperiment() {
       g_status = document.getElementById('status');
-      window.addEventListener('touchstart', onTouchStart);
-      window.addEventListener('touchmove', onTouchMove);
+      // Pass 'passive' false in to prevent any intervention.
+      window.addEventListener('touchstart', onTouchStart, {passive: false});
+      window.addEventListener('touchmove', onTouchMove, {passive: false});
       window.addEventListener('touchend', onTouchEnd);
       window.addEventListener('touchleave', onTouchEnd);
       window.addEventListener('touchcancel', onTouchEnd);
-      window.addEventListener('wheel', onMouseWheel);
+      window.addEventListener('wheel', onMouseWheel, {passive: false});
       window.requestAnimationFrame(onAnimationFrame);
     }
 
diff --git a/tools/perf/page_sets/tough_scheduling_cases/touch_handler_scrolling.html b/tools/perf/page_sets/tough_scheduling_cases/touch_handler_scrolling.html
index c49833b..1a0552d 100644
--- a/tools/perf/page_sets/tough_scheduling_cases/touch_handler_scrolling.html
+++ b/tools/perf/page_sets/tough_scheduling_cases/touch_handler_scrolling.html
@@ -38,12 +38,13 @@
     }
 
     function startExperiment() {
-      window.addEventListener('touchstart', onTouchStart);
-      window.addEventListener('touchmove', onTouchMove);
+      // Pass 'passive' false in to prevent any intervention.
+      window.addEventListener('touchstart', onTouchStart, {passive: false});
+      window.addEventListener('touchmove', onTouchMove, {passive: false});
       window.addEventListener('touchend', onTouchEnd);
       window.addEventListener('touchleave', onTouchEnd);
       window.addEventListener('touchcancel', onTouchEnd);
-      window.addEventListener('wheel', onMouseWheel);
+      window.addEventListener('wheel', onMouseWheel, {passive: false});
     }
 
     window.addEventListener('load', startExperiment);
diff --git a/tools/resources/list_resources_removed_by_repack.py b/tools/resources/list_resources_removed_by_repack.py
index a009ead..db3b4abc 100755
--- a/tools/resources/list_resources_removed_by_repack.py
+++ b/tools/resources/list_resources_removed_by_repack.py
@@ -54,18 +54,21 @@
     sys.stderr.write('Cannot find gen dir %s' % generated_output_dir)
     return 1
 
-  if build_type == 'chromium':
-    excluded_header = 'google_chrome_strings.h'
-  else:
-    excluded_header = 'chromium_strings.h'
+  product = 'chromium' if build_type == 'chromium' else 'google_chrome'
+  suffix = product + '_strings.h'
+  excluded_headers = set([s % suffix for s in (
+      '%s',
+      'components_%s',
+      'settings_%s'
+  )])
+
   data_files = []
   for root, dirs, files in os.walk(generated_output_dir):
     if os.path.basename(root) != 'grit':
       continue
 
-    header_files = [header for header in files if header.endswith('.h')]
-    if excluded_header in header_files:
-      header_files.remove(excluded_header)
+    header_files = set([header for header in files if header.endswith('.h')])
+    header_files -= excluded_headers
     data_files.extend([os.path.join(root, header) for header in header_files])
 
   resource_id_to_name_file_map = {}
diff --git a/ui/login/account_picker/user_pod_row.js b/ui/login/account_picker/user_pod_row.js
index 48a7073ad1..912c21b 100644
--- a/ui/login/account_picker/user_pod_row.js
+++ b/ui/login/account_picker/user_pod_row.js
@@ -748,11 +748,6 @@
       this.passwordElement.addEventListener('keypress',
           this.handlePasswordKeyPress_.bind(this));
 
-      if (this.pinKeyboard) {
-        this.pinKeyboard.addEventListener('submit',
-            this.handlePinSubmitted_.bind(this));
-      }
-
       this.imageElement.addEventListener('load',
           this.parentNode.handlePodImageLoad.bind(this.parentNode, this));
 
@@ -773,16 +768,6 @@
     },
 
     /**
-     * Handles the user hitting 'submit' on the PIN keyboard.
-     * @param {Event} e Submit event object.
-     * @private
-     */
-    handlePinSubmitted_: function(e) {
-      var pin = e.detail.pin;
-      chrome.send('authenticateUser', [this.user.username, pin]);
-    },
-
-    /**
      * Handles keypress event (i.e. any textual input) on password input.
      * @param {Event} e Keypress Event object.
      * @private
@@ -1188,6 +1173,8 @@
      */
     get mainInput() {
       if (this.isAuthTypePassword) {
+        if (this.pinContainer.classList.contains('pin-enabled'))
+          return this.pinKeyboard.inputElement;
         return this.passwordElement;
       } else if (this.isAuthTypeOnlineSignIn) {
         return this;
@@ -1354,11 +1341,11 @@
         this.classList.toggle('signing-in', true);
         chrome.send('attemptUnlock', [this.user.username]);
       } else if (this.isAuthTypePassword) {
-        if (!this.passwordElement.value)
+        var password = this.passwordElement.value || this.pinKeyboard.value;
+        if (!password)
           return false;
         Oobe.disableSigninUI();
-        chrome.send('authenticateUser',
-                    [this.user.username, this.passwordElement.value]);
+        chrome.send('authenticateUser', [this.user.username, password]);
       } else {
         console.error('Activating user pod with invalid authentication type: ' +
             this.authType);
@@ -1420,6 +1407,7 @@
      */
     reset: function(takeFocus) {
       this.passwordElement.value = '';
+      this.pinKeyboard.value = '';
       this.classList.toggle('signing-in', false);
       if (takeFocus) {
         if (!this.multiProfilesPolicyApplied)
@@ -1817,6 +1805,11 @@
           // Note that this.userClickAuthAllowed_ is set in mouse down event
           // handler.
           this.parentNode.setActivatedPod(this);
+        } else if (this.pinKeyboard.submitButton &&
+                   e.target == this.pinKeyboard.submitButton) {
+          // Sets the pod as activated if the submit button is clicked so that
+          // it simulates what the enter button does for the password/pin.
+          this.parentNode.setActivatedPod(this);
         }
 
         if (this.multiProfilesPolicyApplied)
@@ -3413,6 +3406,7 @@
           if (this.focusedPod_) {
             var targetTag = e.target.tagName;
             if (e.target == this.focusedPod_.passwordElement ||
+                e.target == this.focusedPod_.pinKeyboard.inputElement ||
                 (targetTag != 'INPUT' &&
                  targetTag != 'BUTTON' &&
                  targetTag != 'A')) {
diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc
index 876c6c2..b990372 100644
--- a/ui/views/bubble/tray_bubble_view.cc
+++ b/ui/views/bubble/tray_bubble_view.cc
@@ -200,6 +200,7 @@
     : layer_(ui::LAYER_TEXTURED),
       corner_radius_(corner_radius) {
   layer_.set_delegate(this);
+  layer_.SetFillsBoundsOpaquely(false);
 }
 
 TrayBubbleContentMask::~TrayBubbleContentMask() {