diff --git a/DEPS b/DEPS
index cf0edba..3aa588a8 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'b3ab49fff913807d151e289dc44b3fb91201997d',
+  'v8_revision': '661a53a29a09544439cb49076cd9411f2c052e61',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -88,7 +88,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling NaCl
   # and whatever else without interference from each other.
-  'nacl_revision': '9f8fdd668b305511b605ee229533639c29a5222b',
+  'nacl_revision': '01d3ae00d277726b8aaee572120a5ba2a31d511e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype-android
   # and whatever else without interference from each other.
@@ -228,7 +228,7 @@
     Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'b554cd674f91f0a060236ff662b1fef28ec1f93f', # commit position 15882
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '9ce24c7963d329a9222f2e093f9b4ab2ea77d469', # commit position 15894
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
index 4d62167..7128bf9 100644
--- a/base/numerics/safe_conversions.h
+++ b/base/numerics/safe_conversions.h
@@ -51,8 +51,7 @@
 // for the destination type.
 template <typename Dst, typename Src>
 constexpr bool IsValueInRangeForNumericType(Src value) {
-  return internal::DstRangeRelationToSrcRange<Dst>(value) ==
-         internal::RANGE_VALID;
+  return internal::DstRangeRelationToSrcRange<Dst>(value).IsValid();
 }
 
 // Forces a crash, like a CHECK(false). Used for numeric boundary errors.
diff --git a/build/config/gcc/BUILD.gn b/build/config/gcc/BUILD.gn
index 422ec0e..bf97f712 100644
--- a/build/config/gcc/BUILD.gn
+++ b/build/config/gcc/BUILD.gn
@@ -7,6 +7,17 @@
 import("//build/config/sysroot.gni")
 import("//build/toolchain/toolchain.gni")
 
+declare_args() {
+  # When non empty, overrides the target rpath value. This allows a user to
+  # make a Chromium build where binaries and shared libraries are meant to be
+  # installed into separate directories, like /usr/bin/chromium and
+  # /usr/lib/chromium for instance. It is useful when a build system that
+  # generates a whole target root filesystem (like Yocto) is used on top of gn,
+  # especially when cross-compiling.
+  # Note: this gn arg is similar to gyp target_rpath generator flag.
+  gcc_target_rpath = ""
+}
+
 # This config causes functions not to be automatically exported from shared
 # libraries. By default, all symbols are exported but this means there are
 # lots of exports that slow everything down. In general we explicitly mark
@@ -61,11 +72,18 @@
     } else {
       rpath_link = "."
     }
-    ldflags = [
-      # Want to pass "\$". GN will re-escape as required for ninja.
-      "-Wl,-rpath=\$ORIGIN/${rpath_link}",
-      "-Wl,-rpath-link=${rpath_link}",
-    ]
+    if (current_toolchain != default_toolchain || gcc_target_rpath == "") {
+      ldflags = [
+        # Want to pass "\$". GN will re-escape as required for ninja.
+        "-Wl,-rpath=\$ORIGIN/${rpath_link}",
+        "-Wl,-rpath-link=${rpath_link}",
+      ]
+    } else {
+      ldflags = [
+        "-Wl,-rpath=${gcc_target_rpath}",
+        "-Wl,-rpath-link=${rpath_link}",
+      ]
+    }
   }
 }
 
diff --git a/build/nocompile.gni b/build/nocompile.gni
index 1b292d7..d425b79 100644
--- a/build/nocompile.gni
+++ b/build/nocompile.gni
@@ -58,11 +58,12 @@
 import("//testing/test.gni")
 
 declare_args() {
-  # TODO(crbug.com/105388): Disabled until http://crbug.com/105388 is resolved.
-  enable_nocompile_tests = false
+  # TODO(crbug.com/105388): make sure no-compile test is not flaky.
+  enable_nocompile_tests = is_linux && is_clang
 }
 
 if (enable_nocompile_tests) {
+  import("//build/config/sysroot.gni")
   template("nocompile_test") {
     nocompile_target = target_name + "_run_nocompile"
 
@@ -75,11 +76,15 @@
       outputs = [
         result_path,
       ]
+      sysroot_args = ""
+      if (sysroot != "") {
+        sysroot_args = " --sysroot " + rebase_path(sysroot, root_build_dir)
+      }
       args = [
         "4",  # number of compilers to invoke in parallel.
         "{{source}}",
         "-Wall -Werror -Wfatal-errors " + "-I" +
-            rebase_path("//", root_build_dir),
+            rebase_path("//", root_build_dir) + sysroot_args,
         "{{output}}",
       ]
     }
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index 4c091ed6..211f43b4 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -431,6 +431,45 @@
   }
 }
 
+mac_toolchain("clang_x86") {
+  toolchain_args = {
+    current_cpu = "x86"
+    current_os = "mac"
+  }
+}
+
+mac_toolchain("clang_x86_v8_arm") {
+  toolchain_args = {
+    current_cpu = "x86"
+    v8_current_cpu = "arm"
+    current_os = "mac"
+  }
+}
+
+mac_toolchain("clang_x86_v8_mipsel") {
+  toolchain_args = {
+    current_cpu = "x86"
+    v8_current_cpu = "mipsel"
+    current_os = "mac"
+  }
+}
+
+mac_toolchain("clang_x64_v8_arm64") {
+  toolchain_args = {
+    current_cpu = "x64"
+    v8_current_cpu = "arm64"
+    current_os = "mac"
+  }
+}
+
+mac_toolchain("clang_x64_v8_mips64el") {
+  toolchain_args = {
+    current_cpu = "x64"
+    v8_current_cpu = "mips64el"
+    current_os = "mac"
+  }
+}
+
 if (is_ios) {
   mac_toolchain("ios_clang_arm") {
     toolchain_args = {
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 9bab239..24307313 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -13940,7 +13940,7 @@
       </message>
       <message name="IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE" desc="Text for the checkbox on the window picker dialog, when checked, audio will be shared, otherwise just video sharing">
         Share audio
-      </message>      
+      </message>
       <message name="IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_SCREEN" desc="Text for the button on the window picker dialog, clicking which takes one to full screen sharing">
         Your Entire Screen
       </message>
@@ -15143,6 +15143,12 @@
     </if>
 
     <if expr="is_android">
+      <message name="IDS_FLAGS_CONTENT_SUGGESTIONS_CATEGORY_RANKER_NAME" desc="Name for the flag to choose a category ranker for content suggestions, e.g. on the New Tab page." translateable="false">
+        Content suggestions category ranker (e.g. on NTP)
+      </message>
+      <message name="IDS_FLAGS_CONTENT_SUGGESTIONS_CATEGORY_RANKER_DESCRIPTION" desc="Description for the flag to choose a category ranker for content suggestions, e.g. on the New Tab page." translateable="false">
+        Set category ranker to order sections of content suggestions (e.g. on the NTP).
+      </message>
       <message name="IDS_FLAGS_ENABLE_NTP_SNIPPETS_NAME" desc="Name for the flag to enable snippets on the New Tab page." translateable="false">
         Show content snippets on the New Tab page
       </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 131341c..30102a3 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3215,10 +3215,10 @@
       "android/rlz/revenue_stats.h",
       "android/safe_browsing/safe_browsing_api_handler_bridge.cc",
       "android/safe_browsing/safe_browsing_api_handler_bridge.h",
-      "android/search_geolocation_disclosure_infobar_delegate.cc",
-      "android/search_geolocation_disclosure_infobar_delegate.h",
-      "android/search_geolocation_disclosure_tab_helper.cc",
-      "android/search_geolocation_disclosure_tab_helper.h",
+      "android/search_geolocation/search_geolocation_disclosure_infobar_delegate.cc",
+      "android/search_geolocation/search_geolocation_disclosure_infobar_delegate.h",
+      "android/search_geolocation/search_geolocation_disclosure_tab_helper.cc",
+      "android/search_geolocation/search_geolocation_disclosure_tab_helper.h",
       "android/seccomp_support_detector.cc",
       "android/seccomp_support_detector.h",
       "android/service_tab_launcher.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index dada3f3..a9babd3d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -510,6 +510,31 @@
 #endif  // OS_ANDROID
 
 #if defined(OS_ANDROID)
+const FeatureEntry::FeatureParam
+    kContentSuggestionsCategoryRankerFeatureVariationConstant[] = {
+        {ntp_snippets::kCategoryRankerParameter,
+         ntp_snippets::kCategoryRankerConstantRanker},
+};
+
+const FeatureEntry::FeatureParam
+    kContentSuggestionsCategoryRankerFeatureVariationClickBased[] = {
+        {ntp_snippets::kCategoryRankerParameter,
+         ntp_snippets::kCategoryRankerClickBasedRanker},
+};
+
+const FeatureEntry::FeatureVariation
+    kContentSuggestionsCategoryRankerFeatureVariations[] = {
+        {"(constant)",
+         kContentSuggestionsCategoryRankerFeatureVariationConstant,
+         arraysize(kContentSuggestionsCategoryRankerFeatureVariationConstant),
+         nullptr},
+        {"(click based)",
+         kContentSuggestionsCategoryRankerFeatureVariationClickBased,
+         arraysize(kContentSuggestionsCategoryRankerFeatureVariationClickBased),
+         nullptr}};
+#endif  // OS_ANDROID
+
+#if defined(OS_ANDROID)
 const FeatureEntry::FeatureParam kNTPSnippetsFeatureVariationOnlyPersonal[] = {
     {"fetching_personalization", "personal"},
 };
@@ -1839,6 +1864,13 @@
      SINGLE_VALUE_TYPE(extensions::switches::kDisableTabForDesktopShare)},
 #endif  // ENABLE_EXTENSIONS
 #if defined(OS_ANDROID)
+    {"content-suggestions-category-ranker",
+     IDS_FLAGS_CONTENT_SUGGESTIONS_CATEGORY_RANKER_NAME,
+     IDS_FLAGS_CONTENT_SUGGESTIONS_CATEGORY_RANKER_DESCRIPTION, kOsAndroid,
+     FEATURE_WITH_VARIATIONS_VALUE_TYPE(
+         ntp_snippets::kCategoryRanker,
+         kContentSuggestionsCategoryRankerFeatureVariations,
+         ntp_snippets::kStudyName)},
     {"enable-ntp-snippets", IDS_FLAGS_ENABLE_NTP_SNIPPETS_NAME,
      IDS_FLAGS_ENABLE_NTP_SNIPPETS_DESCRIPTION, kOsAndroid,
      FEATURE_WITH_VARIATIONS_VALUE_TYPE(
@@ -2075,8 +2107,8 @@
 #endif
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
     {"print-pdf-as-image", IDS_FLAGS_PRINT_PDF_AS_IMAGE_NAME,
-      IDS_FLAGS_PRINT_PDF_AS_IMAGE_DESCRIPTION, kOsDesktop,
-      FEATURE_VALUE_TYPE(features::kPrintPdfAsImage)},
+     IDS_FLAGS_PRINT_PDF_AS_IMAGE_DESCRIPTION, kOsDesktop,
+     FEATURE_VALUE_TYPE(features::kPrintPdfAsImage)},
     {"print-scaling", IDS_FLAGS_PRINT_SCALING_NAME,
      IDS_FLAGS_PRINT_SCALING_DESCRIPTION, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kPrintScaling)},
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index d090ae74..bc68782 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -89,7 +89,7 @@
 #include "chrome/browser/android/recently_closed_tabs_bridge.h"
 #include "chrome/browser/android/rlz/revenue_stats.h"
 #include "chrome/browser/android/safe_browsing/safe_browsing_api_handler_bridge.h"
-#include "chrome/browser/android/search_geolocation_disclosure_tab_helper.h"
+#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h"
 #include "chrome/browser/android/service_tab_launcher.h"
 #include "chrome/browser/android/sessions/session_tab_helper_android.h"
 #include "chrome/browser/android/shortcut_helper.h"
diff --git a/chrome/browser/android/preferences/browser_prefs_android.cc b/chrome/browser/android/preferences/browser_prefs_android.cc
index faa83e0..e7810190 100644
--- a/chrome/browser/android/preferences/browser_prefs_android.cc
+++ b/chrome/browser/android/preferences/browser_prefs_android.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/android/preferences/browser_prefs_android.h"
 
 #include "blimp/client/public/blimp_client_context.h"
-#include "chrome/browser/android/search_geolocation_disclosure_tab_helper.h"
+#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h"
 #include "chrome/browser/notifications/notification_platform_bridge_android.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_registry_simple.h"
diff --git a/chrome/browser/android/search_geolocation/OWNERS b/chrome/browser/android/search_geolocation/OWNERS
new file mode 100644
index 0000000..f3f66a3
--- /dev/null
+++ b/chrome/browser/android/search_geolocation/OWNERS
@@ -0,0 +1,2 @@
+benwells@chromium.org
+dfalcantara@chromium.org
diff --git a/chrome/browser/android/search_geolocation_disclosure_infobar_delegate.cc b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.cc
similarity index 97%
rename from chrome/browser/android/search_geolocation_disclosure_infobar_delegate.cc
rename to chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.cc
index 8f031c4..577f9c3 100644
--- a/chrome/browser/android/search_geolocation_disclosure_infobar_delegate.cc
+++ b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/android/search_geolocation_disclosure_infobar_delegate.h"
+#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.h"
 
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/chrome/browser/android/search_geolocation_disclosure_infobar_delegate.h b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.h
similarity index 88%
rename from chrome/browser/android/search_geolocation_disclosure_infobar_delegate.h
rename to chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.h
index e3a9cb06..61a998be 100644
--- a/chrome/browser/android/search_geolocation_disclosure_infobar_delegate.h
+++ b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_DISCLOSURE_INFOBAR_DELEGATE_H_
-#define CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_DISCLOSURE_INFOBAR_DELEGATE_H_
+#ifndef CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_SEARCH_GEOLOCATION_DISCLOSURE_INFOBAR_DELEGATE_H_
+#define CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_SEARCH_GEOLOCATION_DISCLOSURE_INFOBAR_DELEGATE_H_
 
 #include <stddef.h>
 
@@ -86,4 +86,4 @@
   DISALLOW_COPY_AND_ASSIGN(SearchGeolocationDisclosureInfoBarDelegate);
 };
 
-#endif  // CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_DISCLOSURE_INFOBAR_DELEGATE_H_
+#endif  // CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_SEARCH_GEOLOCATION_DISCLOSURE_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/android/search_geolocation_disclosure_tab_helper.cc b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.cc
similarity index 97%
rename from chrome/browser/android/search_geolocation_disclosure_tab_helper.cc
rename to chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.cc
index 5bfdc99..e92959d 100644
--- a/chrome/browser/android/search_geolocation_disclosure_tab_helper.cc
+++ b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/android/search_geolocation_disclosure_tab_helper.h"
+#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h"
 
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
@@ -11,7 +11,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
-#include "chrome/browser/android/search_geolocation_disclosure_infobar_delegate.h"
+#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.h"
 #include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
diff --git a/chrome/browser/android/search_geolocation_disclosure_tab_helper.h b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h
similarity index 85%
rename from chrome/browser/android/search_geolocation_disclosure_tab_helper.h
rename to chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h
index 1eac8be..5d5e2f2 100644
--- a/chrome/browser/android/search_geolocation_disclosure_tab_helper.h
+++ b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_DISCLOSURE_TAB_HELPER_H_
-#define CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_DISCLOSURE_TAB_HELPER_H_
+#ifndef CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_SEARCH_GEOLOCATION_DISCLOSURE_TAB_HELPER_H_
+#define CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_SEARCH_GEOLOCATION_DISCLOSURE_TAB_HELPER_H_
 
 #include <jni.h>
 
@@ -55,4 +55,4 @@
   DISALLOW_COPY_AND_ASSIGN(SearchGeolocationDisclosureTabHelper);
 };
 
-#endif  // CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_DISCLOSURE_TAB_HELPER_H_
+#endif  // CHROME_BROWSER_ANDROID_SEARCH_GEOLOCATION_SEARCH_GEOLOCATION_DISCLOSURE_TAB_HELPER_H_
diff --git a/chrome/browser/geolocation/geolocation_permission_context.cc b/chrome/browser/geolocation/geolocation_permission_context.cc
index 57751751..4e282fcb 100644
--- a/chrome/browser/geolocation/geolocation_permission_context.cc
+++ b/chrome/browser/geolocation/geolocation_permission_context.cc
@@ -15,7 +15,7 @@
 #include "device/geolocation/geolocation_provider.h"
 
 #if defined(OS_ANDROID)
-#include "chrome/browser/android/search_geolocation_disclosure_infobar_delegate.h"
+#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.h"
 #endif
 
 GeolocationPermissionContext::GeolocationPermissionContext(Profile* profile)
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index d065de4..84882db 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -29,7 +29,7 @@
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h"
-#include "components/ntp_snippets/category_rankers/constant_category_ranker.h"
+#include "components/ntp_snippets/category_rankers/category_ranker.h"
 #include "components/ntp_snippets/content_suggestions_service.h"
 #include "components/ntp_snippets/features.h"
 #include "components/ntp_snippets/ntp_snippets_constants.h"
@@ -76,6 +76,7 @@
 using history::HistoryService;
 using image_fetcher::ImageFetcherImpl;
 using ntp_snippets::BookmarkSuggestionsProvider;
+using ntp_snippets::CategoryRanker;
 using ntp_snippets::ContentSuggestionsService;
 using ntp_snippets::ForeignSessionsSuggestionsProvider;
 using ntp_snippets::NTPSnippetsFetcher;
@@ -252,8 +253,8 @@
   HistoryService* history_service = HistoryServiceFactory::GetForProfile(
       profile, ServiceAccessType::EXPLICIT_ACCESS);
   PrefService* pref_service = profile->GetPrefs();
-  auto category_ranker =
-      base::MakeUnique<ntp_snippets::ConstantCategoryRanker>();
+  std::unique_ptr<CategoryRanker> category_ranker =
+      ntp_snippets::BuildSelectedCategoryRanker(pref_service);
   auto* service =
       new ContentSuggestionsService(state, signin_manager, history_service,
                                     pref_service, std::move(category_ranker));
diff --git a/chrome/browser/ui/android/infobars/search_geolocation_disclosure_infobar.cc b/chrome/browser/ui/android/infobars/search_geolocation_disclosure_infobar.cc
index f5da11e..76145f5 100644
--- a/chrome/browser/ui/android/infobars/search_geolocation_disclosure_infobar.cc
+++ b/chrome/browser/ui/android/infobars/search_geolocation_disclosure_infobar.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/android/infobars/search_geolocation_disclosure_infobar.h"
 
 #include "base/android/jni_string.h"
-#include "chrome/browser/android/search_geolocation_disclosure_infobar_delegate.h"
+#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.h"
 #include "jni/SearchGeolocationDisclosureInfoBar_jni.h"
 
 using base::android::JavaParamRef;
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 0ef2975..4caf0f5 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -69,7 +69,7 @@
 #include "chrome/browser/android/data_usage/data_use_tab_helper.h"
 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h"
 #include "chrome/browser/android/offline_pages/recent_tab_helper.h"
-#include "chrome/browser/android/search_geolocation_disclosure_tab_helper.h"
+#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h"
 #include "chrome/browser/android/voice_search_tab_helper.h"
 #include "chrome/browser/android/webapps/single_tab_mode_tab_helper.h"
 #include "chrome/browser/ui/android/context_menu_helper.h"
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index c20c3b2..d696e90 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-9145.0.0
\ No newline at end of file
+9149.0.0
\ No newline at end of file
diff --git a/components/ntp_snippets/category_rankers/click_based_category_ranker.cc b/components/ntp_snippets/category_rankers/click_based_category_ranker.cc
index 6dbab54b5..5b7ca83 100644
--- a/components/ntp_snippets/category_rankers/click_based_category_ranker.cc
+++ b/components/ntp_snippets/category_rankers/click_based_category_ranker.cc
@@ -86,9 +86,33 @@
 }
 
 void ClickBasedCategoryRanker::ClearHistory(base::Time begin, base::Time end) {
-  // TODO(crbug.com/675953): Preserve remote categories with 0 counts instead of
-  // removing them.
+  // The categories added through |AppendCategoryIfNecessary| cannot be
+  // completely removed, since no one is required to reregister them. Instead
+  // they are preserved in the default order (sorted by id).
+  std::vector<RankedCategory> old_categories = ordered_categories_;
   RestoreDefaultOrder();
+
+  std::vector<Category> added_categories;
+  for (const RankedCategory& old_category : old_categories) {
+    auto it =
+        std::find_if(ordered_categories_.begin(), ordered_categories_.end(),
+                     [old_category](const RankedCategory& other) {
+                       return other.category == old_category.category;
+                     });
+    if (it == ordered_categories_.end()) {
+      added_categories.push_back(old_category.category);
+    }
+  }
+
+  // Sort added categories by id to make their order history independent.
+  std::sort(added_categories.begin(), added_categories.end(),
+            Category::CompareByID());
+
+  for (Category added_category : added_categories) {
+    ordered_categories_.push_back(RankedCategory(added_category, /*clicks=*/0));
+  }
+
+  StoreOrderToPrefs(ordered_categories_);
 }
 
 void ClickBasedCategoryRanker::AppendCategoryIfNecessary(Category category) {
diff --git a/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc b/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc
index 8295a6e3..0f14faa 100644
--- a/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc
+++ b/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc
@@ -339,4 +339,43 @@
   EXPECT_FALSE(CompareCategories(first, second));
 }
 
+TEST_F(ClickBasedCategoryRankerTest, ShouldRestoreDefaultOrderOnClearHistory) {
+  std::vector<KnownCategories> default_order =
+      ConstantCategoryRanker::GetKnownCategoriesDefaultOrder();
+  Category first = Category::FromKnownCategory(default_order[0]);
+  Category second = Category::FromKnownCategory(default_order[1]);
+
+  ASSERT_TRUE(CompareCategories(first, second));
+
+  // Change the order.
+  while (CompareCategories(first, second)) {
+    NotifyOnSuggestionOpened(
+        /*times=*/ClickBasedCategoryRanker::GetPassingMargin(), second);
+  }
+
+  ASSERT_FALSE(CompareCategories(first, second));
+
+  // The user clears history.
+  ranker()->ClearHistory(/*begin=*/base::Time(),
+                         /*end=*/base::Time::Max());
+
+  // The default order must be restored.
+  EXPECT_TRUE(CompareCategories(first, second));
+}
+
+TEST_F(ClickBasedCategoryRankerTest,
+       ShouldPreserveRemoteCategoriesOnClearHistory) {
+  Category first = AddUnusedRemoteCategory();
+  Category second = AddUnusedRemoteCategory();
+
+  ASSERT_TRUE(CompareCategories(first, second));
+
+  // The user clears history.
+  ranker()->ClearHistory(/*begin=*/base::Time(),
+                         /*end=*/base::Time::Max());
+
+  // The order does not matter, but the ranker should not die.
+  CompareCategories(first, second);
+}
+
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/content_suggestions_service.cc b/components/ntp_snippets/content_suggestions_service.cc
index 6469882..712589a8 100644
--- a/components/ntp_snippets/content_suggestions_service.cc
+++ b/components/ntp_snippets/content_suggestions_service.cc
@@ -130,6 +130,7 @@
   for (const auto& provider : providers_) {
     provider->ClearHistory(begin, end, filter);
   }
+  category_ranker_->ClearHistory(begin, end);
 }
 
 void ContentSuggestionsService::ClearAllCachedSuggestions() {
diff --git a/components/ntp_snippets/features.cc b/components/ntp_snippets/features.cc
index 03cfbc3..c3c7fc8 100644
--- a/components/ntp_snippets/features.cc
+++ b/components/ntp_snippets/features.cc
@@ -4,6 +4,8 @@
 
 #include "components/ntp_snippets/features.h"
 
+#include "components/ntp_snippets/category_rankers/click_based_category_ranker.h"
+#include "components/ntp_snippets/category_rankers/constant_category_ranker.h"
 #include "components/variations/variations_associated_data.h"
 
 namespace ntp_snippets {
@@ -44,4 +46,47 @@
 const base::Feature kPreferAmpUrlsFeature{"NTPPreferAmpUrls",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
+const base::Feature kCategoryRanker{"ContentSuggestionsCategoryRanker",
+                                    base::FEATURE_ENABLED_BY_DEFAULT};
+
+const char kCategoryRankerParameter[] = "category_ranker";
+const char kCategoryRankerConstantRanker[] = "constant";
+const char kCategoryRankerClickBasedRanker[] = "click_based";
+
+CategoryRankerChoice GetSelectedCategoryRanker() {
+  std::string category_ranker_value =
+      variations::GetVariationParamValueByFeature(kCategoryRanker,
+                                                  kCategoryRankerParameter);
+
+  if (category_ranker_value.empty()) {
+    // Default, Enabled or Disabled.
+    return CategoryRankerChoice::CONSTANT;
+  }
+  if (category_ranker_value == kCategoryRankerConstantRanker) {
+    return CategoryRankerChoice::CONSTANT;
+  }
+  if (category_ranker_value == kCategoryRankerClickBasedRanker) {
+    return CategoryRankerChoice::CLICK_BASED;
+  }
+
+  NOTREACHED() << "The " << kCategoryRankerParameter << " parameter value is '"
+               << category_ranker_value << "'";
+  return CategoryRankerChoice::CONSTANT;
+}
+
+std::unique_ptr<CategoryRanker> BuildSelectedCategoryRanker(
+    PrefService* pref_service) {
+  CategoryRankerChoice choice = ntp_snippets::GetSelectedCategoryRanker();
+  switch (choice) {
+    case CategoryRankerChoice::CONSTANT:
+      return base::MakeUnique<ConstantCategoryRanker>();
+    case CategoryRankerChoice::CLICK_BASED:
+      return base::MakeUnique<ClickBasedCategoryRanker>(pref_service);
+    default:
+      NOTREACHED() << "The category ranker choice value is "
+                   << static_cast<int>(choice);
+  }
+  return nullptr;
+}
+
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/features.h b/components/ntp_snippets/features.h
index d4cf6a0..8991367 100644
--- a/components/ntp_snippets/features.h
+++ b/components/ntp_snippets/features.h
@@ -5,9 +5,12 @@
 #ifndef COMPONENTS_NTP_SNIPPETS_FEATURES_H_
 #define COMPONENTS_NTP_SNIPPETS_FEATURES_H_
 
+#include <memory>
 #include <string>
 
 #include "base/feature_list.h"
+#include "components/ntp_snippets/category_rankers/category_ranker.h"
+#include "components/prefs/pref_service.h"
 
 namespace ntp_snippets {
 
@@ -41,6 +44,27 @@
 // Feature to prefer AMP URLs over regular URLs when available.
 extern const base::Feature kPreferAmpUrlsFeature;
 
+// Feature to choose a category ranker.
+extern const base::Feature kCategoryRanker;
+
+// Parameter for a kCategoryRanker feature flag.
+extern const char kCategoryRankerParameter[];
+// Possible values of the parameter above.
+extern const char kCategoryRankerConstantRanker[];
+extern const char kCategoryRankerClickBasedRanker[];
+
+enum class CategoryRankerChoice {
+  CONSTANT,
+  CLICK_BASED,
+};
+
+// Returns which CategoryRanker to use according to kCategoryRanker feature.
+CategoryRankerChoice GetSelectedCategoryRanker();
+
+// Builds a CategoryRanker according to kCategoryRanker feature.
+std::unique_ptr<CategoryRanker> BuildSelectedCategoryRanker(
+    PrefService* pref_service);
+
 }  // namespace ntp_snippets
 
 #endif  // COMPONENTS_NTP_SNIPPETS_FEATURES_H_
diff --git a/content/browser/resources/media/peer_connection_update_table.js b/content/browser/resources/media/peer_connection_update_table.js
index f5e58b5b..f3475a8 100644
--- a/content/browser/resources/media/peer_connection_update_table.js
+++ b/content/browser/resources/media/peer_connection_update_table.js
@@ -84,18 +84,60 @@
       var time = new Date(parseFloat(update.time));
       row.innerHTML = '<td>' + time.toLocaleString() + '</td>';
 
+      // map internal event names to spec event names.
+      var type = {
+        onRenegotiationNeeded: 'negotiationneeded',
+        signalingStateChange: 'signalingstatechange',
+        iceGatheringStateChange: 'icegatheringstatechange',
+        iceConnectionStateChange: 'iceconnectionstatechange',
+        onIceCandidate: 'icecandidate',
+        stop: 'close'
+      }[update.type] || update.type;
+
       if (update.value.length == 0) {
-        row.innerHTML += '<td>' + update.type + '</td>';
+        row.innerHTML += '<td>' + type + '</td>';
         return;
       }
 
-      row.innerHTML += '<td><details><summary>' + update.type +
+      row.innerHTML += '<td><details><summary>' + type +
           '</summary></details></td>';
 
       var valueContainer = document.createElement('pre');
       var details = row.cells[1].childNodes[0];
       details.appendChild(valueContainer);
-      valueContainer.textContent = update.value;
+
+      var value = update.value;
+      // map internal names and values to names and events from the
+      // specification. This is a display change which shall not
+      // change the JSON dump.
+      if (update.type === 'iceConnectionStateChange') {
+        value = {
+          ICEConnectionStateNew: 'new',
+          ICEConnectionStateChecking: 'checking',
+          ICEConnectionStateConnected: 'connected',
+          ICEConnectionStateCompleted: 'completed',
+          ICEConnectionStateFailed: 'failed',
+          ICEConnectionStateDisconnected: 'disconnected',
+          ICEConnectionStateClosed: 'closed',
+        }[value] || value;
+      } else if (update.type === 'iceGatheringStateChange') {
+        value = {
+          ICEGatheringStateNew: 'new',
+          ICEGatheringStateGathering: 'gathering',
+          ICEGatheringStateComplete: 'complete',
+        }[value] || value;
+      } else if (update.type === 'signalingStateChange') {
+        value = {
+          SignalingStateStable: 'stable',
+          SignalingStateHaveLocalOffer: 'have-local-offer',
+          SignalingStateHaveRemoteOffer: 'have-remote-offer',
+          SignalingStateHaveLocalPrAnswer: 'have-local-pranswer',
+          SignalingStateHaveRemotePrAnswer: 'have-remote-pranswer',
+          SignalingStateClosed: 'closed',
+        }[value] || value;
+      }
+
+      valueContainer.textContent = value;
     },
 
     /**
diff --git a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc
index 232edcbd..5249011 100644
--- a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc
+++ b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc
@@ -19,6 +19,7 @@
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h"
 #include "components/ntp_snippets/category_rankers/category_ranker.h"
+#include "components/ntp_snippets/category_rankers/click_based_category_ranker.h"
 #include "components/ntp_snippets/category_rankers/constant_category_ranker.h"
 #include "components/ntp_snippets/content_suggestions_service.h"
 #include "components/ntp_snippets/features.h"
@@ -126,7 +127,7 @@
       ios::HistoryServiceFactory::GetForBrowserState(
           chrome_browser_state, ServiceAccessType::EXPLICIT_ACCESS);
   std::unique_ptr<ntp_snippets::CategoryRanker> category_ranker =
-      base::MakeUnique<ntp_snippets::ConstantCategoryRanker>();
+      ntp_snippets::BuildSelectedCategoryRanker(prefs);
   std::unique_ptr<ContentSuggestionsService> service =
       base::MakeUnique<ContentSuggestionsService>(state, signin_manager,
                                                   history_service, prefs,
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f814331..2f85ae9 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -190,6 +190,8 @@
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-height-004.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-height-005.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-height-006.htm [ Skip ]
+crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-height-007.htm [ Skip ]
+crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-height-008.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-height-009.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-height-010.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-height-011.htm [ Skip ]
@@ -200,6 +202,7 @@
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-max-height-004.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-max-height-005.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-max-height-006.htm [ Skip ]
+crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-max-height-008.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-max-height-009.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-max-height-010.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-max-height-011.htm [ Skip ]
@@ -770,7 +773,6 @@
 crbug.com/248938 virtual/threaded/animations/change-one-anim.html [ Failure Pass ]
 crbug.com/326139 crbug.com/390125 media/video-frame-accurate-seek.html [ Failure Pass ]
 crbug.com/248938 virtual/threaded/transitions/cancel-transition.html [ Pass Failure ]
-crbug.com/248938 virtual/threaded/transitions/extra-transition.html [ Pass Failure ]
 crbug.com/248938 [ Linux ] virtual/threaded/transitions/equivalent-background-image-no-transition.html [ Pass Timeout ]
 crbug.com/248938 [ Linux ] virtual/threaded/transitions/move-after-transition.html [ Pass Timeout ]
 crbug.com/248938 virtual/threaded/transitions/start-transform-transition.html [ Pass Failure ]
@@ -785,7 +787,6 @@
 crbug.com/638693 virtual/threaded/animations/display-inline-style-adjust.html [ Pass Crash Failure ]
 crbug.com/421283 fast/html/marquee-scrollamount.html [ Pass Failure ]
 crbug.com/248938 virtual/threaded/transitions/transition-end-event-rendering.html [ Pass Timeout ]
-crbug.com/248938 [ Linux ] virtual/threaded/transitions/unprefixed-perspective-origin.html [ Pass Timeout ]
 crbug.com/248938 [ Mac ] virtual/threaded/transitions/interrupted-all-transition.html [ Pass Failure ]
 
 crbug.com/659123 [ Mac ] fast/css/text-overflow-ellipsis-button.html [ Pass Failure ]
@@ -1642,6 +1643,18 @@
 crbug.com/538717 [ Win Mac Linux ] virtual/mojo-loading/http/tests/permissions/chromium/test-request-multiple-sharedworker.html [ Failure Pass Timeout ]
 
 crbug.com/543369 [ Linux ] fast/forms/select-popup/popup-menu-appearance-tall.html [ Failure ]
+crbug.com/564506 [ Linux Win ] fast/forms/select-popup/popup-menu-appearance-styled.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] fast/forms/select-popup/popup-menu-appearance-zoom.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] fast/forms/select-popup/popup-menu-appearance-zoom090.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] fast/forms/select-popup/popup-menu-appearance-zoom110.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] http/tests/webfont/popup-menu-load-webfont-after-open.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] virtual/mojo-loading/http/tests/webfont/popup-menu-load-webfont-after-open.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] virtual/scalefactor150/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] virtual/scalefactor200/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ]
+crbug.com/564506 [ Linux Win ] virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ NeedsRebaseline ]
 
 crbug.com/546215 [ Android ] fast/inline-block/overflow-clip.html [ Failure ]
 
diff --git a/third_party/WebKit/LayoutTests/css3/calc/calc-overflow.html b/third_party/WebKit/LayoutTests/css3/calc/calc-overflow.html
new file mode 100644
index 0000000..21bc4bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/calc/calc-overflow.html
@@ -0,0 +1,17 @@
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<body></body>
+<script>
+function undefinedBehaviourTest(input, expected, type) {
+  test(() => {
+    var target = document.createElement('div');
+    document.body.appendChild(target);
+    target.style.lineHeight = input;
+    assert_equals(getComputedStyle(target).lineHeight, expected);
+    target.remove();
+  }, 'Do not invoke undefined behaviour when using calc()s with large ' + type + ' values');
+}
+
+undefinedBehaviourTest('calc(1e400px * 1e400)', '3.35544e+07px', 'pixel');
+undefinedBehaviourTest('calc(1e400% * 1e400)', '3.43597e+08px', 'percentage');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/background-serialize.html b/third_party/WebKit/LayoutTests/fast/css/background-serialize.html
index 98525293..40b8cf0 100644
--- a/third_party/WebKit/LayoutTests/fast/css/background-serialize.html
+++ b/third_party/WebKit/LayoutTests/fast/css/background-serialize.html
@@ -12,7 +12,7 @@
 assert_equals(getStyle('.test { background: none; background-color: black;}'), '.test { background: none black; }');
 assert_equals(getStyle('.test { background: none; background-color: initial !important;}'), '.test { background-image: none; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial !important; }');
 assert_equals(getStyle('.test { background: initial; }'), '.test { background: initial; }');
-assert_equals(getStyle('.test { background: initial; background-color: black; }'), '.test { background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: black; }');
+assert_equals(getStyle('.test { background: initial; background-color: black; }'), '.test { background: black; }');
 assert_equals(getStyle('.test { background: inherit; }'), '.test { background: inherit; }');
 assert_equals(getStyle('.test { background: inherit; background-color: black; }'), '.test { background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: black; }');
 assert_equals(getStyle('.test { background: unset; background-color: black; }'), '.test { background-image: unset; background-position: unset; background-size: unset; background-repeat: unset; background-attachment: unset; background-origin: unset; background-clip: unset; background-color: black; }');
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom090.html b/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom090.html
index d91e6274..c80a85b 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom090.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom090.html
@@ -9,9 +9,6 @@
 </head>
 <body style="zoom:0.9;">
 <p>The bottom border of the popup should be visible in 90% zoom level.</p>
-<!-- TOOD(tkent): The pixel result on Linux has unexepcted scroll bar.  We
-  -- should understand the cause.  The scrollbar doesn't appear on content_shell
-  -- and chrome.  So, it's not a serious issue. -->
 <select id="menu">
   <option>foo</option>
   <option selected>bar</option>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom110-expected.png b/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom110-expected.png
new file mode 100644
index 0000000..8aaafac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom110-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom110-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom110-expected.txt
new file mode 100644
index 0000000..06404daa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom110-expected.txt
@@ -0,0 +1,7 @@
+There is no whitespace at the bottom of the popup in 110% zoom level.
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom110.html b/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom110.html
new file mode 100644
index 0000000..866eaf63
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/select-popup/popup-menu-appearance-zoom110.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+window.enablePixelTesting = true;
+</script>
+<script src="../../../resources/js-test.js"></script>
+<script src="../resources/picker-common.js"></script>
+</head>
+<body style="zoom:1.1;">
+<p>There is no whitespace at the bottom of the popup in 110% zoom level.</p>
+<!-- TOOD(tkent): The pixel result on Linux has unexepcted scroll bar.  We
+  -- should understand the cause.  The scrollbar doesn't appear on content_shell
+  -- and chrome.  So, it's not a serious issue. -->
+<select id="menu" style="font-size: 12px; font-family: 'Segoe UI', Tahoma, -webkit-sans-serif; width: 145.455px;">
+<option>25%</option>
+<option>33%</option>
+<option>50%</option>
+<option>67%</option>
+<option>75%</option>
+<option>90%</option>
+<option>100%</option>
+<option>110%</option>
+<option>125%</option>
+<option>150%</option>
+<option>175%</option>
+<option>200%</option>
+<option>250%</option>
+<option>300%</option>
+<option>400%</option>
+<option>500%</option>
+</select>
+<p id="description" style="opacity: 0"></p>
+<div id="console" style="opacity: 0"></div>
+<script>
+openPicker(menu, finishJSTest, function () {
+    testFailed('picker didn\'t open')
+    finishJSTest();
+});
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/masking/parsing-mask-expected.txt b/third_party/WebKit/LayoutTests/fast/masking/parsing-mask-expected.txt
index f372473..31a03d67 100644
--- a/third_party/WebKit/LayoutTests/fast/masking/parsing-mask-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/masking/parsing-mask-expected.txt
@@ -53,7 +53,7 @@
 PASS innerStyle("-webkit-mask", "no-repeat") is "no-repeat"
 PASS innerStyle("-webkit-mask", "repeat space") is "repeat space"
 PASS innerStyle("-webkit-mask", "repeat round") is "repeat round"
-PASS innerStyle("-webkit-mask", "repeat no-repeat") is "repeat no-repeat"
+PASS innerStyle("-webkit-mask", "repeat no-repeat") is "repeat-x"
 PASS innerStyle("-webkit-mask", "repeat space, repeat-x") is "repeat space, repeat-x"
 PASS innerStyle("-webkit-mask", "repeat none") is "none repeat"
 PASS innerStyle("-webkit-mask", "none repeat") is "none repeat"
diff --git a/third_party/WebKit/LayoutTests/fast/masking/parsing-mask.html b/third_party/WebKit/LayoutTests/fast/masking/parsing-mask.html
index 4511888c..c865a51 100644
--- a/third_party/WebKit/LayoutTests/fast/masking/parsing-mask.html
+++ b/third_party/WebKit/LayoutTests/fast/masking/parsing-mask.html
@@ -100,7 +100,7 @@
 testInner("-webkit-mask", "no-repeat", "no-repeat");
 testInner("-webkit-mask", "repeat space", "repeat space");
 testInner("-webkit-mask", "repeat round", "repeat round");
-testInner("-webkit-mask", "repeat no-repeat", "repeat no-repeat");
+testInner("-webkit-mask", "repeat no-repeat", "repeat-x");
 testInner("-webkit-mask", "repeat space, repeat-x", "repeat space, repeat-x");
 testInner("-webkit-mask", "repeat none", "none repeat");
 testInner("-webkit-mask", "none repeat", "none repeat");
diff --git a/third_party/WebKit/LayoutTests/media/mediasession/mediasessionmetadata.html b/third_party/WebKit/LayoutTests/media/mediasession/mediasessionmetadata.html
index bfa59ba5..a94f531 100644
--- a/third_party/WebKit/LayoutTests/media/mediasession/mediasessionmetadata.html
+++ b/third_party/WebKit/LayoutTests/media/mediasession/mediasessionmetadata.html
@@ -8,24 +8,16 @@
     var metadata = new MediaMetadata({});
     assert_not_equals(metadata, null);
 
-    var exception = false;
-    try {
-      metadata = new MediaMetadata("foobar");
-    } catch (e) {
-      exception = true;
-    }
-    assert_true(exception);
-
-    exception = false;
-    try {
-      metadata = new MediaMetadata(42);
-    } catch (e) {
-      exception = true;
-    }
-    assert_true(exception);
+    assert_throws(new TypeError(), _ => new MediaMetadata('foobar'));
+    assert_throws(new TypeError(), _ => new MediaMetadata(42));
   }, 'Test that MediaMetadata is constructed using a dictionary');
 
   test(function() {
+    var metadata = new MediaMetadata();
+    assert_not_equals(metadata, null);
+  }, "Test that MediaMetadata constructor can take no parameter");
+
+  test(function() {
     var metadata = new MediaMetadata({
         title: 'foo', album: 'bar', artist: 'plop',
         artwork: [ { src: 'src1', sizes: 'sizes1', type: 'type1'},
@@ -51,7 +43,15 @@
     assert_equals(metadata.artist, '');
     assert_equals(metadata.album, '');
     assert_equals(0, metadata.artwork.length);
-  }, 'Test the default values for MediaMetadata');
+  }, 'Test the default values for MediaMetadata with empty init dictionary');
+
+  test(function() {
+    var metadata = new MediaMetadata();
+    assert_equals(metadata.title, '');
+    assert_equals(metadata.artist, '');
+    assert_equals(metadata.album, '');
+    assert_equals(0, metadata.artwork.length);
+  }, 'Test the default values for MediaMetadata with no init dictionary');
 
   test(function() {
     var metadata = new MediaMetadata({ randomValueThatWillNotBeAdded: '... hopefully ;)' });
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select-popup/popup-menu-appearance-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select-popup/popup-menu-appearance-zoom-expected.png
index 44feffd..549fc666 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select-popup/popup-menu-appearance-zoom-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select-popup/popup-menu-appearance-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select-popup/popup-menu-appearance-zoom090-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select-popup/popup-menu-appearance-zoom090-expected.png
index 1a7d80e..5c8632a6 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select-popup/popup-menu-appearance-zoom090-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select-popup/popup-menu-appearance-zoom090-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/transitions/extra-transition-expected.txt b/third_party/WebKit/LayoutTests/transitions/extra-transition-expected.txt
deleted file mode 100644
index c649371..0000000
--- a/third_party/WebKit/LayoutTests/transitions/extra-transition-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Spaces lets you group your application windows and banish clutter completely. Leopard gives you a space for everything and makes it easy to switch between your spaces. Start by simply clicking the Spaces icon in the Dock.
-transform="matrix(1, 0, 0, 1, 100, 0)" as expected: PASS
-
diff --git a/third_party/WebKit/LayoutTests/transitions/extra-transition.html b/third_party/WebKit/LayoutTests/transitions/extra-transition.html
index ca850e0..0ef3ed2 100644
--- a/third_party/WebKit/LayoutTests/transitions/extra-transition.html
+++ b/third_party/WebKit/LayoutTests/transitions/extra-transition.html
@@ -1,106 +1,50 @@
 <!DOCTYPE html>
 <html>
 <head>
+  <meta charset="utf-8">
+  <script src="../resources/testharness.js"></script>
+  <script src="../resources/testharnessreport.js"></script>
   <style>
-  body {
-      background: url('resources/Aurora.jpg');
-      -webkit-background-size: 100% 100%;
-      font-family: "Lucida Grande";
-      height: 800px;
+  div > #picture {
+      transition-property: transform;
+      transition-duration: 50ms;
+      transition-timing-function: ease-in;
+      transform: scale(2);
   }
 
-  #features {
-      position: relative;
-      width: 400px;
-      list-style: none;
+  div.enabled > #picture {
+      transition-timing-function: ease-out;
+      transform: scale(3);
   }
 
-  #features > li > .picture {
-      -webkit-transition-property: transform;
-      -webkit-transition-duration: 500ms;
-      -webkit-transition-timing-function: ease-in;
-      transform: rotate(-5deg);
-      opacity: 0.2;
-      border: 5px solid white;
-      background-color: gray;
-      position: absolute;
-      left: 20%;
-      width: 380px;
-      height: 180px;
-      top: 30px;
+  div > #description {
+      transition-property: transform;
+      transition-duration: 90ms;
+      transition-timing-function: ease-in;
   }
 
-  #features > li.enabled > .picture {
-      -webkit-transition-timing-function: ease-out;
-      transform:rotate(10deg);
-  }
-
-  #features > li > .description {
-      -webkit-transition-property: transform;
-      -webkit-transition-duration: 560ms;
-      -webkit-transition-timing-function: ease-in;
-      line-height: 1.4em;
-      position: absolute;
-      background-color: black;
-      color: white;
-      margin: 10px;
-      padding: 10px;
-      border: 3px solid white;
-      -webkit-border-radius: 9px;
-      font-size: 16px;
-      left: 20%;
-      top: 330px;
-      width: 350px;
-  }
-
-  #features > li.enabled > .description {
-      transform:translate3d(100px,0,0);
+  div.enabled > #description {
+      transform: translate3d(100px,0,0);
   }
   </style>
-  <script>
-  if (window.testRunner) {
-    testRunner.waitUntilDone();
-    testRunner.dumpAsText();
-  }
-
-  function init()
-  {
-      document.getElementById("item").className = "enabled";
-      setTimeout(check, 1000);
-  }
-  
-  function log(s)
-  {
-    var results = document.getElementById('results');
-    results.innerHTML += s + '<br>';
-  }
-
-  function check()
-  {
-      var transform = window.getComputedStyle(document.getElementById('description')).transform;
-      if (transform == "matrix(1, 0, 0, 1, 100, 0)")
-          log('transform="'+transform+'" as expected: PASS');
-        else
-        log('transform="'+transform+'", expected "matrix(1, 0, 0, 1, 100, 0)": FAIL');
-
-      if (window.testRunner)
-        testRunner.notifyDone();
-  }
-  </script>
 </head>
-<body onload="init()">
+<body>
 
-<ul id="features">
-<li id="item">
-    <div class="picture"></div>
-  <div id="description" class="description">
-    <b>Spaces</b> lets you group your application windows and banish
-    clutter completely. Leopard gives you a space for everything and
-    makes it easy to switch between your spaces. Start by simply
-    clicking the Spaces icon in the Dock.
-  </div>
-</li>
-</ul>
-<div id="results"></div>
+<div id="item">
+  <div id="picture"></div>
+  <div id="description"></div>
+</div>
+<script>
+  'use strict';
+  async_test(t => {
+    description.addEventListener('transitionend', t.step_func_done(() => {
+      assert_equals(getComputedStyle(picture).transform, 'matrix(3, 0, 0, 3, 0, 0)');
+      assert_equals(getComputedStyle(description).transform, 'matrix(1, 0, 0, 1, 100, 0)');
+    }));
+
+    document.body.offsetHeight; // Force style recalc
+    item.className = 'enabled';
+  });
+</script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/transitions/unprefixed-perspective-origin.html b/third_party/WebKit/LayoutTests/transitions/unprefixed-perspective-origin.html
index cc12035f..bf2d928 100644
--- a/third_party/WebKit/LayoutTests/transitions/unprefixed-perspective-origin.html
+++ b/third_party/WebKit/LayoutTests/transitions/unprefixed-perspective-origin.html
@@ -5,6 +5,8 @@
 <div class="target">-webkit-perspective-origin-x 10ms</div><br>
 <div class="target">-webkit-perspective-origin-y 10ms</div><br>
 <script>
+'use strict';
+var remaining = 0;
 if (window.testRunner) {
   testRunner.dumpAsText();
   testRunner.waitUntilDone();
@@ -14,11 +16,9 @@
   var result = document.createElement('div');
   result.textContent = 'fired transitionend with propertyName: ' + e.propertyName;
   e.target.appendChild(result);
-  if (window.testRunner) {
-    // All events should be fired by next frame.
-    requestAnimationFrame(function() {
-      testRunner.notifyDone();
-    });
+  --remaining;
+  if (remaining === 0 && window.testRunner) {
+    testRunner.notifyDone();
   }
 });
 
@@ -30,6 +30,7 @@
     targets[i].style.webkitPerspectiveOriginX = '10px';
     targets[i].style.webkitPerspectiveOriginY = '10px';
     targets[i].style.perspectiveOrigin = '10px 10px';
+    ++remaining;
   }
 };
 </script>
diff --git a/third_party/WebKit/Source/core/css/CSSCalculationValue.cpp b/third_party/WebKit/Source/core/css/CSSCalculationValue.cpp
index 71464e4f..fc1115d 100644
--- a/third_party/WebKit/Source/core/css/CSSCalculationValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSCalculationValue.cpp
@@ -185,19 +185,22 @@
       float multiplier) const override {
     switch (m_category) {
       case CalcLength:
-        value.pixels +=
-            m_value->computeLength<float>(conversionData) * multiplier;
+        value.pixels = clampTo<float>(
+            value.pixels +
+            m_value->computeLength<double>(conversionData) * multiplier);
         break;
       case CalcPercent:
         ASSERT(m_value->isPercentage());
-        value.percent += m_value->getDoubleValue() * multiplier;
+        value.percent = clampTo<float>(value.percent +
+                                       m_value->getDoubleValue() * multiplier);
         break;
       case CalcNumber:
         // TODO(alancutter): Stop treating numbers like pixels unconditionally
         // in calcs to be able to accomodate border-image-width
         // https://drafts.csswg.org/css-backgrounds-3/#the-border-image-width
-        value.pixels +=
-            m_value->getDoubleValue() * conversionData.zoom() * multiplier;
+        value.pixels = clampTo<float>(value.pixels +
+                                      m_value->getDoubleValue() *
+                                          conversionData.zoom() * multiplier);
         break;
       default:
         ASSERT_NOT_REACHED();
@@ -396,14 +399,14 @@
                 CSSPrimitiveValue::canonicalUnitTypeForCategory(
                     leftUnitCategory);
             if (canonicalType != CSSPrimitiveValue::UnitType::Unknown) {
-              double leftValue =
+              double leftValue = clampTo<double>(
                   leftSide->doubleValue() *
                   CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(
-                      leftType);
-              double rightValue =
+                      leftType));
+              double rightValue = clampTo<double>(
                   rightSide->doubleValue() *
                   CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(
-                      rightType);
+                      rightType));
               return CSSCalcPrimitiveValue::create(
                   evaluateOperator(leftValue, rightValue, op), canonicalType,
                   isInteger);
@@ -623,14 +626,14 @@
                                  CalcOperator op) {
     switch (op) {
       case CalcAdd:
-        return leftValue + rightValue;
+        return clampTo<double>(leftValue + rightValue);
       case CalcSubtract:
-        return leftValue - rightValue;
+        return clampTo<double>(leftValue - rightValue);
       case CalcMultiply:
-        return leftValue * rightValue;
+        return clampTo<double>(leftValue * rightValue);
       case CalcDivide:
         if (rightValue)
-          return leftValue / rightValue;
+          return clampTo<double>(leftValue / rightValue);
         return std::numeric_limits<double>::quiet_NaN();
     }
     return 0;
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
index c16a818..3693f7e 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
+++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
@@ -153,15 +153,6 @@
   return value.value();
 }
 
-bool StylePropertySerializer::StylePropertySetForSerializer::isPropertyImplicit(
-    CSSPropertyID propertyID) const {
-  int index = findPropertyIndex(propertyID);
-  if (index == -1)
-    return false;
-  StylePropertySerializer::PropertyValueForSerializer value = propertyAt(index);
-  return value.isImplicit();
-}
-
 StylePropertySerializer::StylePropertySerializer(
     const StylePropertySet& properties)
     : m_propertySet(properties) {}
@@ -319,6 +310,7 @@
 // special-casing
 static bool allowInitialInShorthand(CSSPropertyID propertyID) {
   switch (propertyID) {
+    case CSSPropertyBackground:
     case CSSPropertyBorder:
     case CSSPropertyBorderTop:
     case CSSPropertyBorderRight:
@@ -333,11 +325,12 @@
     case CSSPropertyGridRow:
     case CSSPropertyGridArea:
     case CSSPropertyGridGap:
+    case CSSPropertyListStyle:
     case CSSPropertyMotion:
     case CSSPropertyOffset:
-    case CSSPropertyWebkitMarginCollapse:
-    case CSSPropertyListStyle:
     case CSSPropertyTextDecoration:
+    case CSSPropertyWebkitMarginCollapse:
+    case CSSPropertyWebkitMask:
     case CSSPropertyWebkitTextEmphasis:
     case CSSPropertyWebkitTextStroke:
       return true;
@@ -346,12 +339,6 @@
   }
 }
 
-// TODO(timloh): This should go away eventually, see crbug.com/471917
-static bool allowImplicitInitialInShorthand(CSSPropertyID propertyID) {
-  return propertyID == CSSPropertyBackground ||
-         propertyID == CSSPropertyWebkitMask;
-}
-
 String StylePropertySerializer::commonShorthandChecks(
     const StylePropertyShorthand& shorthand) const {
   int longhandCount = shorthand.length();
@@ -396,15 +383,8 @@
   }
 
   bool allowInitial = allowInitialInShorthand(shorthand.id());
-  bool allowImplicitInitial =
-      allowInitial || allowImplicitInitialInShorthand(shorthand.id());
   for (int i = 0; i < longhandCount; i++) {
     const CSSValue& value = *longhands[i];
-    if (value.isImplicitInitialValue()) {
-      if (allowImplicitInitial)
-        continue;
-      return emptyString();
-    }
     if (!allowInitial && value.isInitialValue())
       return emptyString();
     if (value.isInheritedValue() || value.isUnsetValue() ||
@@ -713,6 +693,8 @@
   // If the below loop succeeds, there should always be at minimum 1 layer.
   size_t numLayers = 1U;
 
+  // TODO(timloh): Shouldn't we fail if the lists are differently sized, with
+  // the exception of background-color?
   for (size_t i = 0; i < size; i++) {
     values[i] = m_propertySet.getPropertyCSSValue(shorthand.properties()[i]);
     if (values[i]->isBaseValueList()) {
@@ -723,9 +705,7 @@
 
   StringBuilder result;
 
-  // Now stitch the properties together. Implicit initial values are flagged as
-  // such and
-  // can safely be omitted.
+  // Now stitch the properties together.
   for (size_t layer = 0; layer < numLayers; layer++) {
     StringBuilder layerResult;
     bool useRepeatXShorthand = false;
@@ -756,10 +736,8 @@
         continue;
 
       // Special case for background-repeat.
-      if ((propertyIndex < size - 1 &&
-           m_propertySet.isPropertyImplicit(property)) &&
-          (property == CSSPropertyBackgroundRepeatX ||
-           property == CSSPropertyWebkitMaskRepeatX)) {
+      if (property == CSSPropertyBackgroundRepeatX ||
+          property == CSSPropertyWebkitMaskRepeatX) {
         DCHECK(shorthand.properties()[propertyIndex + 1] ==
                    CSSPropertyBackgroundRepeatY ||
                shorthand.properties()[propertyIndex + 1] ==
@@ -791,8 +769,7 @@
         }
       }
 
-      if (!(value->isInitialValue() &&
-            toCSSInitialValue(value)->isImplicit())) {
+      if (!value->isInitialValue()) {
         if (property == CSSPropertyBackgroundSize ||
             property == CSSPropertyWebkitMaskSize) {
           if (foundPositionYCSSProperty || foundPositionXCSSProperty)
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.h b/third_party/WebKit/Source/core/css/StylePropertySerializer.h
index 9c130dd..d4ecf27 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySerializer.h
+++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.h
@@ -83,7 +83,6 @@
         : m_value(property.value()),
           m_id(property.id()),
           m_isImportant(property.isImportant()),
-          m_isImplicit(property.isImplicit()),
           m_isInherited(property.isInherited()) {}
 
     // TODO(sashab): Make this take a const CSSValue&.
@@ -93,13 +92,11 @@
         : m_value(value),
           m_id(id),
           m_isImportant(isImportant),
-          m_isImplicit(value->isImplicitInitialValue()),
           m_isInherited(value->isInheritedValue()) {}
 
     CSSPropertyID id() const { return m_id; }
     const CSSValue* value() const { return m_value; }
     bool isImportant() const { return m_isImportant; }
-    bool isImplicit() const { return m_isImplicit; }
     bool isInherited() const { return m_isInherited; }
     bool isValid() const { return m_value; }
 
@@ -107,7 +104,6 @@
     Member<const CSSValue> m_value;
     CSSPropertyID m_id;
     bool m_isImportant;
-    bool m_isImplicit;
     bool m_isInherited;
   };
 
@@ -125,7 +121,6 @@
     bool shouldProcessPropertyAt(unsigned index) const;
     int findPropertyIndex(CSSPropertyID) const;
     const CSSValue* getPropertyCSSValue(CSSPropertyID) const;
-    bool isPropertyImplicit(CSSPropertyID) const;
 
     DECLARE_TRACE();
 
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
index 3aa55be..e551eee 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
@@ -850,8 +850,10 @@
               100.0,
           Fixed);
     }
-    if (primitiveValue.isNumber())
-      return Length(primitiveValue.getDoubleValue() * 100.0, Percent);
+    if (primitiveValue.isNumber()) {
+      return Length(clampTo<float>(primitiveValue.getDoubleValue() * 100.0),
+                    Percent);
+    }
     if (primitiveValue.isCalculated()) {
       Length zoomedLength = Length(primitiveValue.cssCalcValue()->toCalcValue(
           lineHeightToLengthConversionData(state)));
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp
index 75b31a8..d23ba61 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp
@@ -159,7 +159,7 @@
   }
 
   if (token.type() == HTMLToken::EndTag ||
-      (token.selfClosing() && token.type() == HTMLToken::StartTag &&
+      (token.type() == HTMLToken::StartTag && token.selfClosing() &&
        inForeignContent())) {
     const String& tagName = token.data();
     if ((m_namespaceStack.back() == SVG &&
diff --git a/third_party/WebKit/Source/core/layout/BUILD.gn b/third_party/WebKit/Source/core/layout/BUILD.gn
index 2bfda5c..978bd2c 100644
--- a/third_party/WebKit/Source/core/layout/BUILD.gn
+++ b/third_party/WebKit/Source/core/layout/BUILD.gn
@@ -322,6 +322,8 @@
     "ng/ng_line_builder.cc",
     "ng/ng_line_builder.h",
     "ng/ng_macros.h",
+    "ng/ng_out_of_flow_layout_part.cc",
+    "ng/ng_out_of_flow_layout_part.h",
     "ng/ng_physical_fragment.cc",
     "ng/ng_physical_fragment.h",
     "ng/ng_physical_fragment_base.cc",
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
index a0be580..8a359b3 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -12,6 +12,7 @@
 #include "core/layout/ng/ng_fragment.h"
 #include "core/layout/ng/ng_layout_opportunity_iterator.h"
 #include "core/layout/ng/ng_length_utils.h"
+#include "core/layout/ng/ng_out_of_flow_layout_part.h"
 #include "core/layout/ng/ng_units.h"
 #include "core/style/ComputedStyle.h"
 #include "platform/LengthFunctions.h"
@@ -292,15 +293,13 @@
     }
     case kStatePrepareForChildLayout: {
       if (current_child_) {
-        // TODO(atotic): uncomment this code when implementing oof layout.
-        // This code cannot be turned on because it prevents layout of
-        // oof children, and non-layedout objects trigger  a DCHECK.
-        // EPosition position = current_child_->Style()->position();
-        // if ((position == AbsolutePosition || position == FixedPosition)) {
-        //   builder_->AddOutOfFlowCandidateChild(current_child_,
-        //   GetChildSpaceOffset());
-        // }
-        // else
+        EPosition position = current_child_->Style()->position();
+        if ((position == AbsolutePosition || position == FixedPosition)) {
+          builder_->AddOutOfFlowChildCandidate(current_child_,
+                                               GetChildSpaceOffset());
+          current_child_ = current_child_->NextSibling();
+          return kNotFinished;
+        }
         space_for_current_child_ = CreateConstraintSpaceForCurrentChild();
         *algorithm_out = NGLayoutInputNode::AlgorithmForInputNode(
             current_child_, space_for_current_child_);
@@ -308,7 +307,21 @@
         return kChildAlgorithmRequired;
       }
 
-      layout_state_ = kStateFinalize;
+      // Prepare for kStateOutOfFlowLayout
+      content_size_ += border_and_padding_.block_end;
+
+      // Recompute the block-axis size now that we know our content size.
+      LayoutUnit block_size = ComputeBlockSizeForFragment(
+          ConstraintSpace(), Style(), content_size_);
+      builder_->SetBlockSize(block_size);
+
+      // Out of flow setup.
+      out_of_flow_layout_ = new NGOutOfFlowLayoutPart(style_, builder_->Size());
+      builder_->GetAndClearOutOfFlowDescendantCandidates(
+          &out_of_flow_candidates_, &out_of_flow_candidate_positions_);
+      out_of_flow_candidate_positions_index_ = 0;
+      current_child_ = nullptr;
+      layout_state_ = kStateOutOfFlowLayout;
       return kNotFinished;
     }
     case kStateChildLayout: {
@@ -326,15 +339,12 @@
       layout_state_ = kStatePrepareForChildLayout;
       return kNotFinished;
     }
+    case kStateOutOfFlowLayout:
+      if (LayoutOutOfFlowChild())
+        layout_state_ = kStateFinalize;
+      return kNotFinished;
     case kStateFinalize: {
-      content_size_ += border_and_padding_.block_end;
-
-      // Recompute the block-axis size now that we know our content size.
-      LayoutUnit block_size = ComputeBlockSizeForFragment(
-          ConstraintSpace(), Style(), content_size_);
-
-      builder_->SetBlockSize(block_size)
-          .SetInlineOverflow(max_inline_size_)
+      builder_->SetInlineOverflow(max_inline_size_)
           .SetBlockOverflow(content_size_);
       *fragment_out = builder_->ToFragment();
       layout_state_ = kStateInit;
@@ -363,6 +373,34 @@
   builder_->AddChild(fragment, fragment_offset);
 }
 
+bool NGBlockLayoutAlgorithm::LayoutOutOfFlowChild() {
+  if (!current_child_) {
+    if (out_of_flow_candidates_.isEmpty()) {
+      out_of_flow_layout_ = nullptr;
+      out_of_flow_candidate_positions_.clear();
+      return true;
+    }
+    current_child_ = out_of_flow_candidates_.first();
+    out_of_flow_candidates_.removeFirst();
+    NGStaticPosition position = out_of_flow_candidate_positions_
+        [out_of_flow_candidate_positions_index_++];
+
+    if (!out_of_flow_layout_->StartLayout(current_child_, position)) {
+      builder_->AddOutOfFlowDescendant(current_child_, position);
+      current_child_ = nullptr;
+      return false;
+    }
+  }
+  NGFragmentBase* fragment;
+  NGLogicalOffset offset;
+  if (out_of_flow_layout_->Layout(&fragment, &offset) == kNewFragment) {
+    // TODO(atotic) Need to adjust size of overflow rect per spec.
+    builder_->AddChild(fragment, offset);
+    current_child_ = nullptr;
+  }
+  return false;
+}
+
 NGBoxStrut NGBlockLayoutAlgorithm::CollapseMargins(
     const NGBoxStrut& margins,
     const NGFragment& fragment) {
@@ -523,6 +561,8 @@
   visitor->trace(space_for_current_child_);
   visitor->trace(current_child_);
   visitor->trace(current_minmax_child_);
+  visitor->trace(out_of_flow_layout_);
+  visitor->trace(out_of_flow_candidates_);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
index 9ea2ca16..4a0545a 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
@@ -19,6 +19,7 @@
 class NGConstraintSpaceBuilder;
 class NGFragment;
 class NGFragmentBuilder;
+class NGOutOfFlowLayoutPart;
 class NGPhysicalFragmentBase;
 
 // A class for general block layout (e.g. a <div> with no special style).
@@ -47,6 +48,7 @@
   // Creates a new constraint space for the current child.
   NGConstraintSpace* CreateConstraintSpaceForCurrentChild() const;
   void FinishCurrentChildLayout(NGFragmentBase* fragment);
+  bool LayoutOutOfFlowChild();
 
   // Computes collapsed margins for 2 adjoining blocks and updates the resultant
   // fragment's MarginStrut if needed.
@@ -103,6 +105,7 @@
     kStateInit,
     kStatePrepareForChildLayout,
     kStateChildLayout,
+    kStateOutOfFlowLayout,
     kStateFinalize
   };
   LayoutState layout_state_;
@@ -120,6 +123,11 @@
   Member<NGBlockNode> current_minmax_child_;
   MinAndMaxContentSizes pending_minmax_sizes_;
 
+  Member<NGOutOfFlowLayoutPart> out_of_flow_layout_;
+  HeapLinkedHashSet<WeakMember<NGBlockNode>> out_of_flow_candidates_;
+  Vector<NGStaticPosition> out_of_flow_candidate_positions_;
+  size_t out_of_flow_candidate_positions_index_;
+
   NGBoxStrut border_and_padding_;
   LayoutUnit content_size_;
   LayoutUnit max_inline_size_;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
index a1cdca3..6fbb34b 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
@@ -43,8 +43,6 @@
                          NGFragmentBase** out) {
   DCHECK(!minmax_algorithm_)
       << "Can't interleave Layout and ComputeMinAndMaxContentSizes";
-  if (layout_box_ && layout_box_->isOutOfFlowPositioned())
-    layout_box_->containingBlock()->insertPositionedObject(layout_box_);
   // We can either use the new layout code to do the layout and then copy the
   // resulting size to the LayoutObject, or use the old layout code and
   // synthesize a fragment.
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
index 4421a432..89f547c0 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
@@ -48,8 +48,9 @@
   return *this;
 }
 
-NGFragmentBuilder& NGFragmentBuilder::AddChild(NGFragmentBase* child,
-                                               NGLogicalOffset child_offset) {
+NGFragmentBuilder& NGFragmentBuilder::AddChild(
+    NGFragmentBase* child,
+    const NGLogicalOffset& child_offset) {
   DCHECK_EQ(type_, NGPhysicalFragmentBase::kFragmentBox)
       << "Only box fragments can have children";
   children_.append(child->PhysicalFragment());
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
index 93935aad..c871f6df 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
@@ -27,11 +27,12 @@
 
   NGFragmentBuilder& SetInlineSize(LayoutUnit);
   NGFragmentBuilder& SetBlockSize(LayoutUnit);
+  NGLogicalSize Size() const { return size_; }
 
   NGFragmentBuilder& SetInlineOverflow(LayoutUnit);
   NGFragmentBuilder& SetBlockOverflow(LayoutUnit);
 
-  NGFragmentBuilder& AddChild(NGFragmentBase*, NGLogicalOffset);
+  NGFragmentBuilder& AddChild(NGFragmentBase*, const NGLogicalOffset&);
 
   // Builder has non-trivial out-of-flow descendant methods.
   // These methods are building blocks for implementation of
@@ -55,11 +56,17 @@
   //
   // builder->SetInlineSize/SetBlockSize
   // builder->GetAndClearOutOfFlowDescendantCandidates(oof_candidates)
+  // NGOutOfFlowLayoutPart out_of_flow_layout(container_style,
+  //                                          builder->Size());
   // while (oof_candidates.size() > 0)
   // {
   //   candidate = oof_candidates.shift()
-  //   if (CanPosition(candidate))
-  //     fragment = candidate->Layout();
+  //   if (out_of_flow_layout.StartLayout(candidate))
+  //     NGFragmentBase* fragment;
+  //     NGLogicalOffset* fragment_offset;
+  //     while (out_of_flow_layout.Layout(&fragment, &fragment_offset) ==
+  //         kNotFinished)
+  //          ;
   //     builder->AddChild(fragment);
   //     builder->GetAndClearOutOfFlowDescendantCandidates(child_oof_candidates)
   //     oof_candidates.prepend(child_oof_candidates)
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
new file mode 100644
index 0000000..ec503ba
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -0,0 +1,169 @@
+// 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/layout/ng/ng_out_of_flow_layout_part.h"
+
+#include "core/layout/ng/ng_absolute_utils.h"
+#include "core/layout/ng/ng_block_node.h"
+#include "core/layout/ng/ng_constraint_space_builder.h"
+#include "core/layout/ng/ng_fragment_base.h"
+#include "core/layout/ng/ng_length_utils.h"
+#include "core/style/ComputedStyle.h"
+
+namespace blink {
+
+NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
+    PassRefPtr<const ComputedStyle> container_style,
+    NGLogicalSize container_size) {
+  contains_fixed_ = container_style->canContainFixedPositionObjects();
+  contains_absolute_ =
+      container_style->canContainAbsolutePositionObjects() || contains_fixed_;
+  // Initialize ConstraintSpace
+  NGLogicalSize space_size = container_size;
+  NGBoxStrut borders = ComputeBorders(*container_style);
+  space_size.block_size -= borders.BlockSum();
+  space_size.inline_size -= borders.InlineSum();
+  parent_offset_ = NGLogicalOffset{borders.inline_start, borders.block_start};
+  parent_physical_offset_ = parent_offset_.ConvertToPhysical(
+      FromPlatformWritingMode(container_style->getWritingMode()),
+      container_style->direction(),
+      container_size.ConvertToPhysical(
+          FromPlatformWritingMode(container_style->getWritingMode())),
+      NGPhysicalSize());
+  NGConstraintSpaceBuilder space_builder(
+      FromPlatformWritingMode(container_style->getWritingMode()));
+  space_builder.SetAvailableSize(space_size);
+  space_builder.SetIsNewFormattingContext(true);
+  space_builder.SetTextDirection(container_style->direction());
+  parent_space_ = space_builder.ToConstraintSpace();
+}
+
+bool NGOutOfFlowLayoutPart::StartLayout(
+    NGBlockNode* node,
+    const NGStaticPosition& static_position) {
+  EPosition position = node->Style()->position();
+  if ((contains_absolute_ && position == AbsolutePosition) ||
+      (contains_fixed_ && position == FixedPosition)) {
+    node_ = node;
+    static_position_ = static_position;
+    // Adjust static_position origin. static_position coordinate origin is
+    //  border_box, absolute position coordinate origin is padding box.
+    static_position_.offset -= parent_physical_offset_;
+    node_fragment_ = nullptr;
+    node_position_ = NGAbsolutePhysicalPosition();
+    inline_estimate_.reset();
+    block_estimate_.reset();
+    state_ = kComputeInlineEstimate;
+    return true;
+  }
+  return false;
+}
+
+NGLayoutStatus NGOutOfFlowLayoutPart::Layout(NGFragmentBase** fragment,
+                                             NGLogicalOffset* offset) {
+  DCHECK(node_);
+  switch (state_) {
+    case kComputeInlineEstimate:
+      if (ComputeInlineSizeEstimate())
+        state_ = kPartialPosition;
+      break;
+    case kPartialPosition:
+      node_position_ = ComputePartialAbsoluteWithChildInlineSize(
+          *parent_space_, *node_->Style(), static_position_, inline_estimate_);
+      state_ = kComputeBlockEstimate;
+      break;
+    case kComputeBlockEstimate:
+      if (ComputeBlockSizeEstimate())
+        state_ = kFullPosition;
+      break;
+    case kFullPosition:
+      ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node_->Style(),
+                                            static_position_, block_estimate_,
+                                            &node_position_);
+      state_ = kGenerateFragment;
+      break;
+    case kGenerateFragment:
+      block_estimate_ =
+          node_position_.size.ConvertToLogical(parent_space_->WritingMode())
+              .block_size;
+      if (!ComputeNodeFragment())
+        return kNotFinished;
+      state_ = kDone;
+      break;
+    case kDone:
+      *fragment = node_fragment_;
+      // Compute offset
+      NGBoxStrut inset = node_position_.inset.ConvertToLogical(
+          parent_space_->WritingMode(), parent_space_->Direction());
+      offset->inline_offset = inset.inline_start + parent_offset_.inline_offset;
+      offset->block_offset = inset.block_start + parent_offset_.block_offset;
+      return kNewFragment;
+  }
+  return kNotFinished;
+}
+
+bool NGOutOfFlowLayoutPart::ComputeInlineSizeEstimate() {
+  if (AbsoluteNeedsChildInlineSize(*node_->Style())) {
+    MinAndMaxContentSizes size;
+    if (node_->ComputeMinAndMaxContentSizes(&size)) {
+      inline_estimate_ =
+          size.ShrinkToFit(parent_space_->AvailableSize().inline_size);
+      return true;
+    }
+    return false;
+  }
+  return true;
+}
+
+bool NGOutOfFlowLayoutPart::ComputeBlockSizeEstimate() {
+  if (AbsoluteNeedsChildBlockSize(*node_->Style())) {
+    if (ComputeNodeFragment()) {
+      block_estimate_ = node_fragment_->BlockSize();
+      return true;
+    }
+    return false;
+  }
+  return true;
+}
+
+bool NGOutOfFlowLayoutPart::ComputeNodeFragment() {
+  if (node_fragment_)
+    return true;
+  if (!node_space_) {
+    NGConstraintSpaceBuilder builder(parent_space_->WritingMode());
+    LayoutUnit inline_width =
+        node_position_.size.ConvertToLogical(parent_space_->WritingMode())
+            .inline_size;
+    // Node fragment is computed in one of these two scenarios:
+    // 1. To estimate block size
+    //    In this case, available block_size is parent's size.
+    // 2. To compute final block fragment, when block size is known.
+
+    NGLogicalSize available_size =
+        NGLogicalSize(inline_width, parent_space_->AvailableSize().block_size);
+    if (block_estimate_)
+      available_size.block_size = *block_estimate_;
+    builder.SetAvailableSize(available_size);
+    builder.SetPercentageResolutionSize(available_size);
+    if (block_estimate_)
+      builder.SetIsFixedSizeBlock(true);
+    builder.SetIsFixedSizeInline(true);
+    builder.SetIsNewFormattingContext(true);
+    node_space_ = builder.ToConstraintSpace();
+  }
+  NGFragmentBase* fragment;
+  if (node_->Layout(node_space_, &fragment)) {
+    node_fragment_ = fragment;
+    return true;
+  }
+  return false;
+}
+
+DEFINE_TRACE(NGOutOfFlowLayoutPart) {
+  visitor->trace(node_);
+  visitor->trace(parent_space_);
+  visitor->trace(node_fragment_);
+  visitor->trace(node_space_);
+}
+}
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.h b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.h
new file mode 100644
index 0000000..a4c66b8
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.h
@@ -0,0 +1,72 @@
+// 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 NGOutOfFlowLayoutPart_h
+#define NGOutOfFlowLayoutPart_h
+
+#include "core/CoreExport.h"
+
+#include "core/layout/ng/ng_units.h"
+#include "core/layout/ng/ng_constraint_space.h"
+#include "core/layout/ng/ng_absolute_utils.h"
+#include "core/layout/ng/ng_layout_algorithm.h"
+#include "platform/heap/Handle.h"
+#include "wtf/Optional.h"
+
+namespace blink {
+
+class ComputedStyle;
+class NGBlockNode;
+class NGFragmentBase;
+class NGConstraintSpace;
+
+// Helper class for positioning of out-of-flow blocks.
+// It should be used together with NGFragmentBuilder.
+// See NGFragmentBuilder::AddOutOfFlowChildCandidate documentation
+// for example of using these classes together.
+class CORE_EXPORT NGOutOfFlowLayoutPart
+    : public GarbageCollectedFinalized<NGOutOfFlowLayoutPart> {
+ public:
+  NGOutOfFlowLayoutPart(PassRefPtr<const ComputedStyle>, NGLogicalSize);
+
+  // If false, this fragment should be passed up the tree for layout by
+  // an ancestor.
+  bool StartLayout(NGBlockNode*, const NGStaticPosition&);
+  NGLayoutStatus Layout(NGFragmentBase**, NGLogicalOffset*);
+
+  DECLARE_TRACE();
+
+ private:
+  bool ComputeInlineSizeEstimate();
+  bool ComputeBlockSizeEstimate();
+  bool ComputeNodeFragment();
+
+  bool contains_fixed_;
+  bool contains_absolute_;
+
+  enum State {
+    kComputeInlineEstimate,
+    kPartialPosition,
+    kComputeBlockEstimate,
+    kFullPosition,
+    kGenerateFragment,
+    kDone
+  };
+  State state_;
+
+  NGStaticPosition static_position_;
+  NGLogicalOffset parent_offset_;
+  NGPhysicalOffset parent_physical_offset_;
+  Member<NGConstraintSpace> parent_space_;
+  Member<NGBlockNode> node_;
+  Member<NGConstraintSpace> node_space_;
+  Member<NGFragmentBase> node_fragment_;
+  NGAbsolutePhysicalPosition node_position_;
+  Optional<LayoutUnit> inline_estimate_;
+  Optional<LayoutUnit> block_estimate_;
+};
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_units.cc b/third_party/WebKit/Source/core/layout/ng/ng_units.cc
index 1a4eec73..fc94812 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_units.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_units.cc
@@ -147,6 +147,16 @@
   return *this;
 }
 
+NGPhysicalOffset NGPhysicalOffset::operator-(
+    const NGPhysicalOffset& other) const {
+  return NGPhysicalOffset{this->left - other.left, this->top - other.top};
+}
+
+NGPhysicalOffset& NGPhysicalOffset::operator-=(const NGPhysicalOffset& other) {
+  *this = *this - other;
+  return *this;
+}
+
 bool NGBoxStrut::IsEmpty() const {
   return *this == NGBoxStrut();
 }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_units.h b/third_party/WebKit/Source/core/layout/ng/ng_units.h
index 6c768d7..63bd0b37 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_units.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_units.h
@@ -105,6 +105,8 @@
 
   NGPhysicalOffset operator+(const NGPhysicalOffset& other) const;
   NGPhysicalOffset& operator+=(const NGPhysicalOffset& other);
+  NGPhysicalOffset operator-(const NGPhysicalOffset& other) const;
+  NGPhysicalOffset& operator-=(const NGPhysicalOffset& other);
 };
 
 struct NGPhysicalSize {
@@ -310,7 +312,6 @@
   static NGStaticPosition Create(NGWritingMode,
                                  TextDirection,
                                  NGPhysicalOffset);
-
   // Left/Right/TopPosition functions map static position to
   // left/right/top edge wrt container space.
   // The function arguments are required to solve the equation:
diff --git a/third_party/WebKit/Source/core/page/PagePopupClient.h b/third_party/WebKit/Source/core/page/PagePopupClient.h
index 3be400c..b4765e1 100644
--- a/third_party/WebKit/Source/core/page/PagePopupClient.h
+++ b/third_party/WebKit/Source/core/page/PagePopupClient.h
@@ -58,7 +58,7 @@
   virtual Element& ownerElement() = 0;
   // Returns effective zoom factor of ownerElement, or the page zoom factor if
   // the effective zoom factor is not available.
-  float zoomFactor();
+  virtual float zoomFactor();
   // Returns a Locale object associated to the client.
   virtual Locale& locale() = 0;
 
diff --git a/third_party/WebKit/Source/modules/mediasession/MediaMetadata.idl b/third_party/WebKit/Source/modules/mediasession/MediaMetadata.idl
index 996a9b4..0955ea4 100644
--- a/third_party/WebKit/Source/modules/mediasession/MediaMetadata.idl
+++ b/third_party/WebKit/Source/modules/mediasession/MediaMetadata.idl
@@ -6,7 +6,7 @@
 
 [
     ConstructorCallWith=ExecutionContext,
-    Constructor(MediaMetadataInit metadata),
+    Constructor(optional MediaMetadataInit metadata),
     RuntimeEnabled=MediaSession,
 ] interface MediaMetadata {
     attribute DOMString title;
diff --git a/third_party/WebKit/Source/web/PopupMenuImpl.cpp b/third_party/WebKit/Source/web/PopupMenuImpl.cpp
index a6a856dd..c7c38399 100644
--- a/third_party/WebKit/Source/web/PopupMenuImpl.cpp
+++ b/third_party/WebKit/Source/web/PopupMenuImpl.cpp
@@ -177,7 +177,7 @@
     addProperty("textTransform",
                 String(textTransformToString(baseStyle().textTransform())),
                 m_buffer);
-    addProperty("fontSize", baseFont().specifiedSize(), m_buffer);
+    addProperty("fontSize", baseFont().computedPixelSize(), m_buffer);
     addProperty("fontStyle", String(fontStyleToString(baseFont().style())),
                 m_buffer);
     addProperty("fontVariant",
@@ -292,14 +292,14 @@
   PagePopupClient::addString("],\n", data);
 
   addProperty("anchorRectInScreen", anchorRectInScreen, data);
-  float zoom = zoomFactor();
   float scaleFactor = m_chromeClient->windowToViewportScalar(1.f);
-  addProperty("zoomFactor", zoom / scaleFactor, data);
+  addProperty("zoomFactor", 1, data);
+  addProperty("scaleFactor", scaleFactor, data);
   bool isRTL = !ownerStyle->isLeftToRightDirection();
   addProperty("isRTL", isRTL, data);
   addProperty("paddingStart",
-              isRTL ? ownerElement.clientPaddingRight().toDouble() / zoom
-                    : ownerElement.clientPaddingLeft().toDouble() / zoom,
+              isRTL ? ownerElement.clientPaddingRight().toDouble()
+                    : ownerElement.clientPaddingLeft().toDouble(),
               data);
   PagePopupClient::addString("};\n", data);
   data->append(Platform::current()->loadResource("pickerCommon.js"));
@@ -340,8 +340,7 @@
   if (baseFont.computedPixelSize() != fontDescription.computedPixelSize()) {
     // We don't use FontDescription::specifiedSize() because this element
     // might have its own zoom level.
-    addProperty("fontSize", fontDescription.computedSize() / zoomFactor(),
-                data);
+    addProperty("fontSize", fontDescription.computedPixelSize(), data);
   }
   // Our UA stylesheet has font-weight:normal for OPTION.
   if (FontWeightNormal != fontDescription.weight())
diff --git a/third_party/WebKit/Source/web/PopupMenuImpl.h b/third_party/WebKit/Source/web/PopupMenuImpl.h
index 7e30b2c2..f5ee422 100644
--- a/third_party/WebKit/Source/web/PopupMenuImpl.h
+++ b/third_party/WebKit/Source/web/PopupMenuImpl.h
@@ -50,6 +50,7 @@
   void setValue(const String&) override;
   void closePopup() override;
   Element& ownerElement() override;
+  float zoomFactor() override { return 1.0; }
   Locale& locale() override;
   void didClosePopup() override;
 
diff --git a/third_party/WebKit/Source/web/resources/listPicker.js b/third_party/WebKit/Source/web/resources/listPicker.js
index 575523f..0563a4c 100644
--- a/third_party/WebKit/Source/web/resources/listPicker.js
+++ b/third_party/WebKit/Source/web/resources/listPicker.js
@@ -218,11 +218,11 @@
 
 ListPicker.prototype._fixWindowSize = function() {
     this._selectElement.style.height = "";
-    var zoom = this._config.zoomFactor;
-    var maxHeight = this._selectElement.offsetHeight * zoom;
-    var noScrollHeight = (this._calculateScrollHeight() + ListPicker.ListboxSelectBorder * 2) * zoom;
-    var scrollbarWidth = getScrollbarWidth() * zoom;
-    var elementOffsetWidth = this._selectElement.offsetWidth * zoom;
+    var scale = this._config.scaleFactor;
+    var maxHeight = this._selectElement.offsetHeight;
+    var noScrollHeight = (this._calculateScrollHeight() + ListPicker.ListboxSelectBorder * 2);
+    var scrollbarWidth = getScrollbarWidth();
+    var elementOffsetWidth = this._selectElement.offsetWidth;
     var desiredWindowHeight = noScrollHeight;
     var desiredWindowWidth = elementOffsetWidth;
     // If we already have a vertical scrollbar, subtract it out, it will get re-added below.
@@ -236,22 +236,24 @@
         desiredWindowWidth += scrollbarWidth;
         expectingScrollbar = true;
     }
-    desiredWindowWidth = Math.max(this._config.anchorRectInScreen.width, desiredWindowWidth);
-    var windowRect = adjustWindowRect(desiredWindowWidth, desiredWindowHeight, elementOffsetWidth, 0);
+    // Screen coordinate for anchorRectInScreen and windowRect is DIP.
+    desiredWindowWidth = Math.max(this._config.anchorRectInScreen.width * scale, desiredWindowWidth);
+    var windowRect = adjustWindowRect(desiredWindowWidth / scale, desiredWindowHeight / scale, elementOffsetWidth / scale, 0);
     // If the available screen space is smaller than maxHeight, we will get an unexpected scrollbar.
-    if (!expectingScrollbar && windowRect.height < noScrollHeight) {
-        desiredWindowWidth = windowRect.width + scrollbarWidth;
-        windowRect = adjustWindowRect(desiredWindowWidth, windowRect.height, windowRect.width, windowRect.height);
+    if (!expectingScrollbar && windowRect.height < noScrollHeight / scale) {
+        desiredWindowWidth = windowRect.width * scale + scrollbarWidth;
+        windowRect = adjustWindowRect(desiredWindowWidth / scale, windowRect.height, windowRect.width, windowRect.height);
     }
-    this._selectElement.style.width = (windowRect.width / zoom) + "px";
-    this._selectElement.style.height = (windowRect.height / zoom) + "px";
-    this._element.style.height = (windowRect.height / zoom) + "px";
+    this._selectElement.style.width = (windowRect.width * scale) + "px";
+    this._selectElement.style.height = (windowRect.height * scale) + "px";
+    this._element.style.height = (windowRect.height * scale) + "px";
     setWindowRect(windowRect);
 };
 
 ListPicker.prototype._calculateScrollHeight = function() {
     // Element.scrollHeight returns an integer value but this calculate the
     // actual fractional value.
+    // TODO(tkent): This can be too large? crbug.com/579863
     var top = Infinity;
     var bottom = -Infinity;
     for (var i = 0; i < this._selectElement.children.length; i++) {
diff --git a/third_party/WebKit/Source/web/resources/pickerCommon.js b/third_party/WebKit/Source/web/resources/pickerCommon.js
index 1a2d2da8..a4f1673 100644
--- a/third_party/WebKit/Source/web/resources/pickerCommon.js
+++ b/third_party/WebKit/Source/web/resources/pickerCommon.js
@@ -99,11 +99,11 @@
 }
 
 /**
- * @param {!number} width in physical pixel
- * @param {!number} height in physical pixel
- * @param {?number} minWidth in physical pixel
- * @param {?number} minHeight in physical pixel
- * @return {!Rectangle} Adjusted rectangle with physical pixels
+ * @param {!number} width in DIP
+ * @param {!number} height in DIP
+ * @param {?number} minWidth in DIP
+ * @param {?number} minHeight in DIP
+ * @return {!Rectangle} Adjusted rectangle in DIP
  */
 function adjustWindowRect(width, height, minWidth, minHeight) {
     if (typeof minWidth !== "number")
@@ -126,7 +126,7 @@
 }
 
 /**
- * Arguments are physical pixels.
+ * Arguments are DIPs.
  */
 function _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeight) {
     var availableSpaceAbove = anchorRect.y - availRect.y;
@@ -146,7 +146,7 @@
 }
 
 /**
- * Arguments are physical pixels.
+ * Arguments are DIPs.
  */
 function _adjustWindowRectHorizontally(windowRect, availRect, anchorRect, minWidth) {
     windowRect.width = Math.min(windowRect.width, availRect.width);
@@ -160,7 +160,7 @@
 }
 
 /**
- * @param {!Rectangle} rect Window position and size with physical pixels.
+ * @param {!Rectangle} rect Window position and size in DIP.
  */
 function setWindowRect(rect) {
     if (window.frameElement) {
diff --git a/tools/gn/target.cc b/tools/gn/target.cc
index 44305128..759d7bf 100644
--- a/tools/gn/target.cc
+++ b/tools/gn/target.cc
@@ -352,8 +352,10 @@
   // private deps. This step re-exports them as public configs for targets that
   // depend on this one.
   for (const auto& dep : public_deps_) {
-    public_configs_.Append(dep.ptr->public_configs().begin(),
-                           dep.ptr->public_configs().end());
+    if (dep.ptr->toolchain() == toolchain()) {
+      public_configs_.Append(dep.ptr->public_configs().begin(),
+                             dep.ptr->public_configs().end());
+    }
   }
 
   // Copy our own libs and lib_dirs to the final set. This will be from our
@@ -502,10 +504,17 @@
 }
 
 void Target::PullDependentTargetConfigs() {
-  for (const auto& pair : GetDeps(DEPS_LINKED))
-    MergeAllDependentConfigsFrom(pair.ptr, &configs_, &all_dependent_configs_);
-  for (const auto& pair : GetDeps(DEPS_LINKED))
-    MergePublicConfigsFrom(pair.ptr, &configs_);
+  for (const auto& pair : GetDeps(DEPS_LINKED)) {
+    if (pair.ptr->toolchain() == toolchain()) {
+      MergeAllDependentConfigsFrom(pair.ptr, &configs_,
+                                   &all_dependent_configs_);
+    }
+  }
+  for (const auto& pair : GetDeps(DEPS_LINKED)) {
+    if (pair.ptr->toolchain() == toolchain()) {
+      MergePublicConfigsFrom(pair.ptr, &configs_);
+    }
+  }
 }
 
 void Target::PullDependentTargetLibsFrom(const Target* dep, bool is_public) {
diff --git a/tools/gn/target_unittest.cc b/tools/gn/target_unittest.cc
index 9bfeed5..9ddcf37 100644
--- a/tools/gn/target_unittest.cc
+++ b/tools/gn/target_unittest.cc
@@ -137,6 +137,61 @@
   EXPECT_EQ(&all, a_fwd.all_dependent_configs()[0].ptr);
 }
 
+// Tests that dependent configs don't propagate between toolchains.
+TEST(Target, NoDependentConfigsBetweenToolchains) {
+  TestWithScope setup;
+  Err err;
+
+  // Create another toolchain.
+  Toolchain other_toolchain(setup.settings(),
+                            Label(SourceDir("//other/"), "toolchain"));
+  TestWithScope::SetupToolchain(&other_toolchain);
+
+  // Set up a dependency chain of |a| -> |b| -> |c| where |a| has a different
+  // toolchain.
+  Target a(setup.settings(),
+           Label(SourceDir("//foo/"), "a", other_toolchain.label().dir(),
+                 other_toolchain.label().name()));
+  a.set_output_type(Target::EXECUTABLE);
+  EXPECT_TRUE(a.SetToolchain(&other_toolchain, &err));
+  TestTarget b(setup, "//foo:b", Target::EXECUTABLE);
+  TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
+  a.private_deps().push_back(LabelTargetPair(&b));
+  b.private_deps().push_back(LabelTargetPair(&c));
+
+  // All dependent config.
+  Config all_dependent(setup.settings(), Label(SourceDir("//foo/"), "all"));
+  ASSERT_TRUE(all_dependent.OnResolved(&err));
+  c.all_dependent_configs().push_back(LabelConfigPair(&all_dependent));
+
+  // Public config.
+  Config public_config(setup.settings(), Label(SourceDir("//foo/"), "public"));
+  ASSERT_TRUE(public_config.OnResolved(&err));
+  c.public_configs().push_back(LabelConfigPair(&public_config));
+
+  // Another public config.
+  Config public_config2(setup.settings(),
+                        Label(SourceDir("//foo/"), "public2"));
+  ASSERT_TRUE(public_config2.OnResolved(&err));
+  b.public_configs().push_back(LabelConfigPair(&public_config2));
+
+  ASSERT_TRUE(c.OnResolved(&err));
+  ASSERT_TRUE(b.OnResolved(&err));
+  ASSERT_TRUE(a.OnResolved(&err));
+
+  // B should have gotten the configs from C.
+  ASSERT_EQ(3u, b.configs().size());
+  EXPECT_EQ(&public_config2, b.configs()[0].ptr);
+  EXPECT_EQ(&all_dependent, b.configs()[1].ptr);
+  EXPECT_EQ(&public_config, b.configs()[2].ptr);
+  ASSERT_EQ(1u, b.all_dependent_configs().size());
+  EXPECT_EQ(&all_dependent, b.all_dependent_configs()[0].ptr);
+
+  // A should not have gotten any configs from B or C.
+  ASSERT_EQ(0u, a.configs().size());
+  ASSERT_EQ(0u, a.all_dependent_configs().size());
+}
+
 TEST(Target, InheritLibs) {
   TestWithScope setup;
   Err err;
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e82732c..5bdaaff 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -93703,6 +93703,7 @@
   <int value="-1832575380" label="show-saved-copy"/>
   <int value="-1832221649" label="disable-out-of-process-pac"/>
   <int value="-1821058653" label="enable-delay-agnostic-aec"/>
+  <int value="-1812579951" label="ContentSuggestionsCategoryRanker:enabled"/>
   <int value="-1811394154" label="disable-webrtc-hw-vp8-encoding"/>
   <int value="-1804485171" label="disable-fullscreen-tab-detaching"/>
   <int value="-1802502753" label="enable-manual-password-generation:enabled"/>
@@ -94209,6 +94210,7 @@
   <int value="550387510" label="NTPAssetDownloadSuggestions:disabled"/>
   <int value="567368307" label="enable-experimental-canvas-features"/>
   <int value="581118445" label="enable-eol-notification"/>
+  <int value="581355159" label="ContentSuggestionsCategoryRanker:disabled"/>
   <int value="584541349" label="ContextualSearchSingleActions:disabled"/>
   <int value="592050831" label="disable-slimming-paint"/>
   <int value="593707592" label="disable-network-portal-notification"/>