diff --git a/DEPS b/DEPS
index d4d1a3cd..a8214dc 100644
--- a/DEPS
+++ b/DEPS
@@ -83,7 +83,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': '5dfbb74d761f1ab521314314367577909e0772f3',
+  'v8_revision': '7e54dc48cb6432621765919312e98f13ca77d810',
   # 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.
@@ -91,7 +91,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'da91c9a6d86c9ecd21c6ac724cf9576d7ee310d2',
+  'angle_revision': '3e520b6f43998a54b088507ce2dd4f88597251fa',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -103,7 +103,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '9f72c45cbcd159f7b811589be1e896c9781e8394',
+  'pdfium_revision': '026717cb667cf0c7215cf55daf794d69752fc900',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -770,15 +770,39 @@
     ],
   },
   {
-    # Downloads the current stable linux sysroot to build/linux/ if needed.
-    # This sysroot updates at about the same rate that the chrome build deps
-    # change. This script is a no-op except for linux users who are doing
-    # official chrome builds or cross compiling.
-    'name': 'sysroot',
+    'name': 'sysroot_arm',
     'pattern': '.',
-    'condition': 'checkout_linux',
+    'condition': 'checkout_linux and checkout_arm',
     'action': ['python', 'src/build/linux/sysroot_scripts/install-sysroot.py',
-               '--running-as-hook'],
+               '--arch=arm'],
+  },
+  {
+    'name': 'sysroot_arm64',
+    'pattern': '.',
+    'condition': 'checkout_linux and checkout_arm64',
+    'action': ['python', 'src/build/linux/sysroot_scripts/install-sysroot.py',
+               '--arch=arm64'],
+  },
+  {
+    'name': 'sysroot_x86',
+    'pattern': '.',
+    'condition': 'checkout_linux and (checkout_x86 or checkout_x64)',
+    'action': ['python', 'src/build/linux/sysroot_scripts/install-sysroot.py',
+               '--arch=x86'],
+  },
+  {
+    'name': 'sysroot_mips',
+    'pattern': '.',
+    'condition': 'checkout_linux and checkout_mips',
+    'action': ['python', 'src/build/linux/sysroot_scripts/install-sysroot.py',
+               '--arch=mips'],
+  },
+  {
+    'name': 'sysroot_x64',
+    'pattern': '.',
+    'condition': 'checkout_linux and checkout_x64',
+    'action': ['python', 'src/build/linux/sysroot_scripts/install-sysroot.py',
+               '--arch=x64'],
   },
   {
     # Case-insensitivity for the Win SDK. Must run before win_toolchain below.
diff --git a/ash/public/cpp/vector_icons/vector_icons.cc.template b/ash/public/cpp/vector_icons/vector_icons.cc.template
index 49936d3..9a4a6d4 100644
--- a/ash/public/cpp/vector_icons/vector_icons.cc.template
+++ b/ash/public/cpp/vector_icons/vector_icons.cc.template
@@ -10,11 +10,11 @@
 #include "base/logging.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
+// Some of the icons in this target are passed over Mojo and thus rely on having
+// a unique ID, so make sure there's a prefix that won't be reused elsewhere.
+#define VECTOR_ICON_ID_PREFIX "ash_public::"
 
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
 
 namespace ash {
 
diff --git a/ash/resources/vector_icons/vector_icons.cc.template b/ash/resources/vector_icons/vector_icons.cc.template
index e48137d..7dfe504 100644
--- a/ash/resources/vector_icons/vector_icons.cc.template
+++ b/ash/resources/vector_icons/vector_icons.cc.template
@@ -10,11 +10,7 @@
 #include "base/logging.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
 
 namespace ash {
 
diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc
index 3479490..6bb263b 100644
--- a/ash/system/web_notification/web_notification_tray.cc
+++ b/ash/system/web_notification/web_notification_tray.cc
@@ -53,7 +53,7 @@
 constexpr int kMaximumSmallIconCount = 3;
 
 constexpr int kTrayItemInnerIconSize = 16;
-;
+
 constexpr gfx::Size kTrayItemOuterSize(26, 26);
 constexpr int kTrayMainAxisInset = 3;
 constexpr int kTrayCrossAxisInset = 0;
diff --git a/base/android/java/src/org/chromium/base/BuildInfo.java b/base/android/java/src/org/chromium/base/BuildInfo.java
index 6b6cfa8..d60b50e 100644
--- a/base/android/java/src/org/chromium/base/BuildInfo.java
+++ b/base/android/java/src/org/chromium/base/BuildInfo.java
@@ -102,6 +102,10 @@
         return msg;
     }
 
+    public static String getPackageVersionCode() {
+        return getAll()[9];
+    }
+
     public static String getPackageVersionName() {
         return getAll()[10];
     }
diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py
index 2a7918bb..0bf1752 100755
--- a/build/linux/sysroot_scripts/install-sysroot.py
+++ b/build/linux/sysroot_scripts/install-sysroot.py
@@ -31,7 +31,6 @@
 
 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
 sys.path.append(os.path.dirname(os.path.dirname(SCRIPT_DIR)))
-import detect_host_arch
 import gyp_chromium
 import gyp_environment
 
@@ -41,6 +40,12 @@
 
 VALID_ARCHS = ('arm', 'arm64', 'i386', 'amd64', 'mips', 'mips64el')
 
+ARCH_TRANSLATIONS = {
+    'x64': 'amd64',
+    'x86': 'i386',
+    'mipsel': 'mips',
+    'mips64': 'mips64el',
+}
 
 class Error(Exception):
   pass
@@ -58,109 +63,25 @@
   return sha1.hexdigest()
 
 
-def DetectHostArch():
-  # Figure out host arch using build/detect_host_arch.py and
-  # set target_arch to host arch
-  detected_host_arch = detect_host_arch.HostArch()
-  if detected_host_arch == 'x64':
-    return 'amd64'
-  if detected_host_arch == 'ia32':
-    return 'i386'
-  if detected_host_arch == 'arm':
-    return 'arm'
-  if detected_host_arch == 'arm64':
-    return 'arm64'
-  if detected_host_arch == 'mips':
-    return 'mips'
-  if detected_host_arch == 'mips64':
-    return 'mips64el'
-  if detected_host_arch == 'ppc':
-    return 'ppc'
-  if detected_host_arch == 's390':
-    return 's390'
-
-  raise Error('Unrecognized host arch: %s' % detected_host_arch)
-
-
-def DetectTargetArch():
-  """Attempt for determine target architecture.
-
-  This works by looking for target_arch in GYP_DEFINES.
-  """
-  # TODO(agrieve): Make this script not depend on GYP_DEFINES so that it works
-  #     with GN as well.
-  gyp_environment.SetEnvironment()
-  supplemental_includes = gyp_chromium.GetSupplementalFiles()
-  gyp_defines = gyp_chromium.GetGypVars(supplemental_includes)
-  target_arch = gyp_defines.get('target_arch')
-  if target_arch == 'x64':
-    return 'amd64'
-  if target_arch == 'ia32':
-    return 'i386'
-  if target_arch == 'arm':
-    return 'arm'
-  if target_arch == 'arm64':
-    return 'arm64'
-  if target_arch == 'mipsel':
-    return 'mips'
-  if target_arch == 'mips64el':
-    return 'mips64el'
-
-  return None
-
-
-def InstallDefaultSysroots(host_arch):
-  """Install the default set of sysroot images.
-
-  This includes at least the sysroot for host architecture, and the 32-bit
-  sysroot for building the v8 snapshot image.  It can also include the cross
-  compile sysroot for ARM/MIPS if cross compiling environment can be detected.
-
-  Another reason we're installing this by default is so that developers can
-  compile and run on our supported platforms without having to worry about
-  flipping things back and forth and whether the sysroots have been downloaded
-  or not.
-  """
-  InstallDefaultSysrootForArch(host_arch)
-
-  if host_arch == 'amd64':
-    InstallDefaultSysrootForArch('i386')
-
-  # If we can detect a non-standard target_arch such as ARM or MIPS,
-  # then install the sysroot too.  Don't attempt to install arm64
-  # since this is currently and android-only architecture.
-  target_arch = DetectTargetArch()
-  if target_arch and target_arch not in (host_arch, 'i386'):
-    InstallDefaultSysrootForArch(target_arch)
-
-
 def main(args):
   parser = optparse.OptionParser('usage: %prog [OPTIONS]', description=__doc__)
-  parser.add_option('--running-as-hook', action='store_true',
-                    default=False, help='Used when running from gclient hooks.'
-                                        ' Installs default sysroot images.')
-  parser.add_option('--arch', type='choice', choices=VALID_ARCHS,
+  parser.add_option('--arch',
                     help='Sysroot architecture: %s' % ', '.join(VALID_ARCHS))
   parser.add_option('--all', action='store_true',
                     help='Install all sysroot images (useful when updating the'
                          ' images)')
   options, _ = parser.parse_args(args)
-  if options.running_as_hook and not sys.platform.startswith('linux'):
+  if not sys.platform.startswith('linux'):
     return 0
 
-  if options.running_as_hook:
-    host_arch = DetectHostArch()
-    # PPC/s390 don't use sysroot, see http://crbug.com/646169
-    if host_arch in ['ppc','s390']:
-      return 0
-    InstallDefaultSysroots(host_arch)
-  elif options.arch:
-    InstallDefaultSysrootForArch(options.arch)
+  if options.arch:
+    InstallDefaultSysrootForArch(
+        ARCH_TRANSLATIONS.get(options.arch, options.arch))
   elif options.all:
     for arch in VALID_ARCHS:
       InstallDefaultSysrootForArch(arch)
   else:
-    print 'You much specify either --arch, --all or --running-as-hook'
+    print 'You much specify either --arch or --all'
     return 1
 
   return 0
diff --git a/build/linux/sysroot_scripts/sysroot-creator.sh b/build/linux/sysroot_scripts/sysroot-creator.sh
index d041578..5a8c583d 100644
--- a/build/linux/sysroot_scripts/sysroot-creator.sh
+++ b/build/linux/sysroot_scripts/sysroot-creator.sh
@@ -51,13 +51,13 @@
 readonly HAS_ARCH_MIPS=${HAS_ARCH_MIPS:=0}
 readonly HAS_ARCH_MIPS64EL=${HAS_ARCH_MIPS64EL:=0}
 
-readonly REQUIRED_TOOLS="curl gunzip"
+readonly REQUIRED_TOOLS="curl xzcat"
 
 ######################################################################
 # Package Config
 ######################################################################
 
-readonly PACKAGES_EXT=gz
+readonly PACKAGES_EXT=xz
 readonly RELEASE_FILE="Release"
 readonly RELEASE_FILE_GPG="Release.gpg"
 
@@ -187,11 +187,11 @@
   tar -I "xz -9 -T0" -cf ${TARBALL} -C ${INSTALL_ROOT} .
 }
 
-ExtractPackageGz() {
+ExtractPackageXz() {
   local src_file="$1"
   local dst_file="$2"
   local repo="$3"
-  gunzip -c "${src_file}" | egrep '^(Package:|Filename:|SHA256:) ' |
+  xzcat "${src_file}" | egrep '^(Package:|Filename:|SHA256:) ' |
     sed "s|Filename: |Filename: ${repo}|" > "${dst_file}"
 }
 
@@ -210,7 +210,7 @@
 
   DownloadOrCopy "${package_list_arch}" "${package_list}"
   VerifyPackageListing "${package_file_arch}" "${package_list}" ${repo} ${dist}
-  ExtractPackageGz "${package_list}" "${TMP_PACKAGE_LIST}" ${repo}
+  ExtractPackageXz "${package_list}" "${TMP_PACKAGE_LIST}" ${repo}
 }
 
 GeneratePackageListCommon() {
@@ -716,7 +716,7 @@
 #
 # VerifyPackageListing
 #
-#     Verifies the downloaded Packages.bz2 file has the right checksums.
+#     Verifies the downloaded Packages.xz file has the right checksums.
 #
 VerifyPackageListing() {
   local file_path="$1"
diff --git a/chrome/VERSION b/chrome/VERSION
index 27cd8cc..462c3875 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=66
 MINOR=0
-BUILD=3344
+BUILD=3345
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java
index 674a48b..5bfee3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java
@@ -10,6 +10,7 @@
 import android.util.Log;
 
 import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.BuildConfig;
 import org.chromium.base.BuildInfo;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.StrictModeContext;
@@ -128,9 +129,12 @@
         addPairedString(GMS_CORE_VERSION, allInfo[BuildInfo.GMS_CORE_VERSION_INDEX]);
         addPairedString(INSTALLER_PACKAGE_NAME, allInfo[BuildInfo.INSTALLER_PACKAGE_NAME_INDEX]);
         addPairedString(ABI_NAME, allInfo[BuildInfo.ABI_NAME_INDEX]);
-        addPairedString(PACKAGE, BuildInfo.getPackageName());
         addPairedString(EXCEPTION_INFO, Log.getStackTraceString(javaException));
         addPairedString(EARLY_JAVA_EXCEPTION, "true");
+        addPairedString(PACKAGE,
+                BuildConfig.FIREBASE_APP_ID + " v" + BuildInfo.getPackageVersionCode() + " ("
+                        + BuildInfo.getPackageVersionName() + ")");
+
         addString(mBoundary);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
index 110af94..dd8c01b1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
@@ -11,6 +11,7 @@
 import android.net.Uri;
 import android.os.SystemClock;
 import android.provider.Browser;
+import android.support.annotation.IntDef;
 import android.text.TextUtils;
 import android.util.Pair;
 import android.webkit.WebView;
@@ -64,6 +65,14 @@
     @VisibleForTesting
     static final String EXTRA_MARKET_REFERRER = "market_referrer";
 
+    // These values are persisted in histograms. Please do not renumber. Append only.
+    @IntDef({AIA_INTENT_FALLBACK_USED, AIA_INTENT_SERP, AIA_INTENT_OTHER, AIA_INTENT_BOUNDARY})
+    public @interface AiaIntent {}
+    private static final int AIA_INTENT_FALLBACK_USED = 0;
+    private static final int AIA_INTENT_SERP = 1;
+    private static final int AIA_INTENT_OTHER = 2;
+    private static final int AIA_INTENT_BOUNDARY = 3;
+
     private final ExternalNavigationDelegate mDelegate;
 
     /**
@@ -136,6 +145,12 @@
                 && (params.getRedirectHandler() == null
                         // For instance, if this is a chained fallback URL, we ignore it.
                         || !params.getRedirectHandler().shouldNotOverrideUrlLoading())) {
+            if (InstantAppsHandler.isIntentToInstantApp(intent)) {
+                RecordHistogram.recordEnumeratedHistogram(
+                        "Android.InstantApps.DirectInstantAppsIntent", AIA_INTENT_FALLBACK_USED,
+                        AIA_INTENT_BOUNDARY);
+            }
+
             return clobberCurrentTabWithFallbackUrl(browserFallbackUrl, params);
         }
         return result;
@@ -478,11 +493,15 @@
         boolean shouldProxyForInstantApps = isDirectInstantAppsIntent
                 && mDelegate.isSerpReferrer(params.getTab());
         if (shouldProxyForInstantApps) {
+            RecordHistogram.recordEnumeratedHistogram("Android.InstantApps.DirectInstantAppsIntent",
+                    AIA_INTENT_SERP, AIA_INTENT_BOUNDARY);
             intent.putExtra(InstantAppsHandler.IS_GOOGLE_SEARCH_REFERRER, true);
         } else if (isDirectInstantAppsIntent) {
             // For security reasons, we disable all intent:// URLs to Instant Apps that are
             // not coming from SERP.
             if (DEBUG) Log.i(TAG, "NO_OVERRIDE: Intent URL to an Instant App");
+            RecordHistogram.recordEnumeratedHistogram("Android.InstantApps.DirectInstantAppsIntent",
+                    AIA_INTENT_OTHER, AIA_INTENT_BOUNDARY);
             return OverrideUrlLoadingResult.NO_OVERRIDE;
         } else {
             // Make sure this extra is not sent unless we've done the verification.
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index ee969e7..1b5c0d1b 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6403,11 +6403,6 @@
           Open PDF in Preview
           </message>
         </if>
-        <if expr="is_win">
-          <message name="IDS_PRINT_PREVIEW_FRIENDLY_WIN_NETWORK_PRINTER_NAME" desc="Friendly name for a printer with a given name on a given server. This uses the same format as the Windows print dialog.">
-            <ph name="PRINTER_NAME">$1<ex>HP LaserJet</ex></ph> on <ph name="SERVER_NAME">$2<ex>printserver</ex></ph>
-          </message>
-        </if>
       </if>
 
       <!-- Load State -->
diff --git a/chrome/app/vector_icons/vector_icons.cc.template b/chrome/app/vector_icons/vector_icons.cc.template
index 99cc4a75..3b1e5ab3 100644
--- a/chrome/app/vector_icons/vector_icons.cc.template
+++ b/chrome/app/vector_icons/vector_icons.cc.template
@@ -11,11 +11,7 @@
 #include "ui/gfx/animation/tween.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
 
 using namespace gfx;
 
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 4da2041..eb4cd1c36b 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -348,16 +348,9 @@
   // an eligible controller is detected later.
   SetControllerDetectedPref(false);
 
-  // Show Material Design unless explicitly disabled or for an untested UX,
-  // or when resuming an OOBE that had it disabled or unset. We use an if/else
-  // here to try and not set state when it is the default value so it can
-  // change and affect the OOBE again.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kDisableMdOobe))
-    SetShowMdOobe(false);
-  else if ((screen_pref.empty() ||
-            GetLocalState()->HasPrefPath(prefs::kOobeMdMode)) ||
-           GetLocalState()->GetBoolean(prefs::kOobeMdMode))
+  if ((screen_pref.empty() ||
+       GetLocalState()->HasPrefPath(prefs::kOobeMdMode)) ||
+      GetLocalState()->GetBoolean(prefs::kOobeMdMode))
     SetShowMdOobe(true);
 
   // TODO(drcrash): Remove this after testing (http://crbug.com/647411).
@@ -581,7 +574,23 @@
 }
 
 void WizardController::ShowSyncConsentScreen() {
+#if defined(GOOGLE_CHROME_BUILD)
+  const user_manager::UserManager* user_manager =
+      user_manager::UserManager::Get();
+  // Skip for non-regular users.
+  if (user_manager->IsLoggedInAsPublicAccount() ||
+      (user_manager->IsCurrentUserNonCryptohomeDataEphemeral() &&
+       user_manager->GetActiveUser()->GetType() !=
+           user_manager::USER_TYPE_REGULAR)) {
+    ShowArcTermsOfServiceScreen();
+    return;
+  }
+  VLOG(1) << "Showing Sync Consent screen.";
+  UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_SYNC_CONSENT);
+  SetCurrentScreen(GetScreen(OobeScreen::SCREEN_SYNC_CONSENT));
+#else
   ShowArcTermsOfServiceScreen();
+#endif
 }
 
 void WizardController::ShowArcTermsOfServiceScreen() {
@@ -875,9 +884,7 @@
 }
 
 void WizardController::OnTermsOfServiceAccepted() {
-  // If the user accepts the Terms of Service, advance to the PlayStore terms
-  // of serice.
-  ShowArcTermsOfServiceScreen();
+  ShowSyncConsentScreen();
 }
 
 void WizardController::OnArcTermsOfServiceSkipped() {
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.cc b/chrome/browser/chromeos/smb_client/smb_file_system.cc
index 3cccd09..b700579db 100644
--- a/chrome/browser/chromeos/smb_client/smb_file_system.cc
+++ b/chrome/browser/chromeos/smb_client/smb_file_system.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/smb_client/smb_file_system.h"
 
+#include <algorithm>
+
 #include "base/memory/ptr_util.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/strings/string_number_conversions.h"
@@ -23,6 +25,14 @@
 // bogus so it falls back to the generic icon.
 constexpr char kUnknownImageDataUri[] = "data:image/png;base64,X";
 
+// Initial number of entries to send during read directory. This number is
+// smaller than kReadDirectoryMaxBatchSize since we want the initial page to
+// load as quickly as possible.
+constexpr uint32_t kReadDirectoryInitialBatchSize = 64;
+
+// Maximum number of entries to send at a time for read directory,
+constexpr uint32_t kReadDirectoryMaxBatchSize = 2048;
+
 using file_system_provider::ProvidedFileSystemInterface;
 
 bool RequestedIsDirectory(
@@ -421,11 +431,22 @@
     const storage::AsyncFileUtil::ReadDirectoryCallback& callback,
     smbprovider::ErrorType error,
     const smbprovider::DirectoryEntryListProto& entries) const {
+  uint32_t batch_size = kReadDirectoryInitialBatchSize;
   storage::AsyncFileUtil::EntryList entry_list;
+
+  // Loop through the entries and send when the desired batch size is hit.
   for (const smbprovider::DirectoryEntryProto& entry : entries.entries()) {
     entry_list.emplace_back(entry.name(), MapEntryType(entry.is_directory()));
+
+    if (entry_list.size() == batch_size) {
+      callback.Run(base::File::FILE_OK, entry_list, true /* has_more */);
+      entry_list.clear();
+
+      // Double the batch size until it gets to the maximum size.
+      batch_size = std::min(batch_size * 2, kReadDirectoryMaxBatchSize);
+    }
   }
-  // TODO(allenvic): Implement has_more (crbug.com/796246).
+
   callback.Run(TranslateError(error), entry_list, false /* has_more */);
 }
 
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc
index f9fc924..5fda1fa 100644
--- a/chrome/browser/devtools/devtools_window.cc
+++ b/chrome/browser/devtools/devtools_window.cc
@@ -84,8 +84,14 @@
 
 static const char kKeyUpEventName[] = "keyup";
 static const char kKeyDownEventName[] = "keydown";
+static const char kDefaultFrontendURL[] =
+    "chrome-devtools://devtools/bundled/devtools_app.html";
 static const char kNodeFrontendURL[] =
     "chrome-devtools://devtools/bundled/node_app.html";
+static const char kWorkerFrontendURL[] =
+    "chrome-devtools://devtools/bundled/worker_app.html";
+static const char kJSFrontendURL[] =
+    "chrome-devtools://devtools/bundled/js_app.html";
 
 bool FindInspectedBrowserAndTabIndex(
     WebContents* inspected_web_contents, Browser** browser, int* tab) {
@@ -538,14 +544,8 @@
                    type == DevToolsAgentHost::kTypeSharedWorker;
 
   if (!agent_host->GetFrontendURL().empty()) {
-    FrontendType frontend_type = kFrontendRemote;
-    if (is_worker) {
-      frontend_type = kFrontendWorker;
-    } else if (type == "node") {
-      frontend_type = kFrontendV8;
-    }
     DevToolsWindow::OpenExternalFrontend(profile, agent_host->GetFrontendURL(),
-                                         agent_host, frontend_type);
+                                         agent_host);
     return;
   }
 
@@ -607,19 +607,32 @@
 void DevToolsWindow::OpenExternalFrontend(
     Profile* profile,
     const std::string& frontend_url,
-    const scoped_refptr<content::DevToolsAgentHost>& agent_host,
-    FrontendType frontend_type) {
+    const scoped_refptr<content::DevToolsAgentHost>& agent_host) {
   DevToolsWindow* window = FindDevToolsWindow(agent_host.get());
-  if (!window) {
+  if (window) {
+    window->ScheduleShow(DevToolsToggleAction::Show());
+    return;
+  }
+
+  std::string type = agent_host->GetType();
+  if (type == "node") {
+    // Direct node targets will always open using ToT front-end.
+    window = Create(profile, nullptr, kFrontendV8, std::string(), false,
+                    std::string(), std::string(), agent_host->IsAttached());
+  } else {
+    bool is_worker = type == DevToolsAgentHost::kTypeServiceWorker ||
+                     type == DevToolsAgentHost::kTypeSharedWorker;
+
+    FrontendType frontend_type =
+        is_worker ? kFrontendRemoteWorker : kFrontendRemote;
     window = Create(profile, nullptr, frontend_type,
                     DevToolsUI::GetProxyURL(frontend_url).spec(), false,
                     std::string(), std::string(), agent_host->IsAttached());
-    if (!window)
-      return;
-    window->bindings_->AttachTo(agent_host);
-    window->close_on_detach_ = false;
   }
-
+  if (!window)
+    return;
+  window->bindings_->AttachTo(agent_host);
+  window->close_on_detach_ = false;
   window->ScheduleShow(DevToolsToggleAction::Show());
 }
 
@@ -990,38 +1003,43 @@
                                     bool can_dock,
                                     const std::string& panel,
                                     bool has_other_clients) {
-  std::string url = frontend_url;
-  if (url.empty()) {
-    url = frontend_type == kFrontendNode ? kNodeFrontendURL
-                                         : chrome::kChromeUIDevToolsURL;
-  }
-
-  std::string url_string(url +
-                         ((url.find("?") == std::string::npos) ? "?" : "&"));
+  std::string url;
+  std::string remote_base =
+      "?remoteBase=" + DevToolsUI::GetRemoteBaseURL().spec();
+  // remoteFrontend is here for backwards compatibility only.
+  std::string remote_frontend =
+      frontend_url + ((frontend_url.find("?") == std::string::npos)
+                          ? "?remoteFrontend=true"
+                          : "&remoteFrontend=true");
   switch (frontend_type) {
-    case kFrontendRemote:
-      url_string += "&remoteFrontend=true";
+    case kFrontendDefault:
+      url = kDefaultFrontendURL + remote_base;
+      if (can_dock)
+        url += "&can_dock=true";
+      if (panel.size())
+        url += "&panel=" + panel;
       break;
     case kFrontendWorker:
-      url_string += "&isSharedWorker=true";
+      url = kWorkerFrontendURL + remote_base;
       break;
     case kFrontendV8:
-      url_string += "&v8only=true";
+      url = kJSFrontendURL + remote_base;
       break;
-    case kFrontendDefault:
-    default:
+    case kFrontendNode:
+      url = kNodeFrontendURL + remote_base;
+      break;
+    case kFrontendRemote:
+      url = remote_frontend;
+      break;
+    case kFrontendRemoteWorker:
+      // isSharedWorker is here for backwards compatibility only.
+      url = remote_frontend + "&isSharedWorker=true";
       break;
   }
 
-  if (frontend_url.empty())
-    url_string += "&remoteBase=" + DevToolsUI::GetRemoteBaseURL().spec();
-  if (can_dock)
-    url_string += "&can_dock=true";
-  if (panel.size())
-    url_string += "&panel=" + panel;
   if (has_other_clients)
-    url_string += "&hasOtherClients=true";
-  return DevToolsUIBindings::SanitizeFrontendURL(GURL(url_string));
+    url += "&hasOtherClients=true";
+  return DevToolsUIBindings::SanitizeFrontendURL(GURL(url));
 }
 
 // static
diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h
index 9aca0915..0f008302 100644
--- a/chrome/browser/devtools/devtools_window.h
+++ b/chrome/browser/devtools/devtools_window.h
@@ -241,10 +241,11 @@
 
   enum FrontendType {
     kFrontendDefault,
-    kFrontendRemote,
     kFrontendWorker,
     kFrontendV8,
-    kFrontendNode
+    kFrontendNode,
+    kFrontendRemote,
+    kFrontendRemoteWorker,
   };
 
   DevToolsWindow(FrontendType frontend_type,
@@ -258,8 +259,7 @@
   static void OpenExternalFrontend(
       Profile* profile,
       const std::string& frontend_uri,
-      const scoped_refptr<content::DevToolsAgentHost>& agent_host,
-      FrontendType frontend_type);
+      const scoped_refptr<content::DevToolsAgentHost>& agent_host);
 
   static DevToolsWindow* Create(Profile* profile,
                                 content::WebContents* inspected_web_contents,
diff --git a/chrome/browser/extensions/api/dial/dial_apitest.cc b/chrome/browser/extensions/api/dial/dial_apitest.cc
index 67049da..1a8413a 100644
--- a/chrome/browser/extensions/api/dial/dial_apitest.cc
+++ b/chrome/browser/extensions/api/dial/dial_apitest.cc
@@ -9,6 +9,8 @@
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/media/router/discovery/dial/dial_registry.h"
+#include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h"
+#include "chrome/browser/media/router/test/noop_dual_media_sink_service.h"
 #include "extensions/common/switches.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
@@ -33,6 +35,13 @@
         extensions::switches::kWhitelistedExtensionID,
         "ddchlicdkolnonkihahngkmmmjnjlkkf");
   }
+
+  void SetUp() override {
+    // Stub out DualMediaSinkService so it does not interfere with the test.
+    media_router::DualMediaSinkService::SetInstanceForTest(
+        new media_router::NoopDualMediaSinkService());
+    ExtensionApiTest::SetUp();
+  }
 };
 
 }  // namespace
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn
index e0054252..e1d59c72 100644
--- a/chrome/browser/media/router/BUILD.gn
+++ b/chrome/browser/media/router/BUILD.gn
@@ -131,6 +131,8 @@
       "test/mock_dns_sd_registry.h",
       "test/mock_mojo_media_router.cc",
       "test/mock_mojo_media_router.h",
+      "test/noop_dual_media_sink_service.cc",
+      "test/noop_dual_media_sink_service.h",
     ]
   }
 }
diff --git a/chrome/browser/media/router/media_router_factory_unittest.cc b/chrome/browser/media/router/media_router_factory_unittest.cc
index d4fff27..6618745 100644
--- a/chrome/browser/media/router/media_router_factory_unittest.cc
+++ b/chrome/browser/media/router/media_router_factory_unittest.cc
@@ -14,20 +14,16 @@
 
 namespace media_router {
 
-namespace {
-
-std::unique_ptr<KeyedService> CreateMockMediaRouter(
-    content::BrowserContext* context) {
-  return base::WrapUnique(new MockMediaRouter);
-}
-
-}  // namespace
-
 class MediaRouterFactoryTest : public testing::Test {
  protected:
   MediaRouterFactoryTest() {}
   ~MediaRouterFactoryTest() override {}
 
+  void SetUp() override {
+    MediaRouterFactory::GetInstance()->SetTestingFactory(
+        profile(), &MockMediaRouter::Create);
+  }
+
   Profile* profile() { return &profile_; }
 
  private:
@@ -53,9 +49,6 @@
 }
 
 TEST_F(MediaRouterFactoryTest, IncognitoBrowserContextShutdown) {
-  MediaRouterFactory::GetInstance()->SetTestingFactory(profile(),
-                                                       &CreateMockMediaRouter);
-
   // Creates an incognito profile.
   profile()->GetOffTheRecordProfile();
   MockMediaRouter* router = static_cast<MockMediaRouter*>(
diff --git a/chrome/browser/media/router/mojo/media_router_desktop.cc b/chrome/browser/media/router/mojo/media_router_desktop.cc
index 806ee4c..6ab67097 100644
--- a/chrome/browser/media/router/mojo/media_router_desktop.cc
+++ b/chrome/browser/media/router/mojo/media_router_desktop.cc
@@ -42,8 +42,7 @@
   // media source.
   UpdateMediaSinks(MediaSourceForDesktop().id());
 
-  if (media_sink_service_)
-    media_sink_service_->OnUserGesture();
+  media_sink_service_->OnUserGesture();
 
 #if defined(OS_WIN)
   EnsureMdnsDiscoveryEnabled();
@@ -65,7 +64,7 @@
 
 MediaRouterDesktop::MediaRouterDesktop(content::BrowserContext* context)
     : MediaRouterMojoImpl(context),
-      media_sink_service_(nullptr),
+      media_sink_service_(DualMediaSinkService::GetInstance()),
       weak_factory_(this) {
   InitializeMediaRouteProviders();
 #if defined(OS_WIN)
@@ -150,9 +149,6 @@
 void MediaRouterDesktop::ProvideSinksToExtension() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DVLOG(1) << "ProvideSinksToExtension";
-  if (!media_sink_service_)
-    media_sink_service_ = DualMediaSinkService::GetInstance();
-
   // If calling |ProvideSinksToExtension| for the first time, add a callback to
   // be notified of sink updates.
   if (!media_sink_service_subscription_) {
@@ -208,8 +204,7 @@
 #if defined(OS_WIN)
 void MediaRouterDesktop::EnsureMdnsDiscoveryEnabled() {
   if (media_router::CastDiscoveryEnabled()) {
-    if (media_sink_service_)
-      media_sink_service_->StartMdnsDiscovery();
+    media_sink_service_->StartMdnsDiscovery();
   } else {
     media_route_providers_[MediaRouteProviderId::EXTENSION]
         ->EnableMdnsDiscovery();
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc
index 4aaadf2..18a177fa 100644
--- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc
+++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc
@@ -653,11 +653,6 @@
   return weak_factory_.GetWeakPtr();
 }
 
-void PresentationServiceDelegateImpl::SetMediaRouterForTest(
-    MediaRouter* router) {
-  router_ = router;
-}
-
 bool PresentationServiceDelegateImpl::HasScreenAvailabilityListenerForTest(
     int render_process_id,
     int render_frame_id,
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h
index 66bd93e4..dfaead3 100644
--- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h
+++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h
@@ -151,7 +151,6 @@
 
   base::WeakPtr<PresentationServiceDelegateImpl> GetWeakPtr();
 
-  void SetMediaRouterForTest(MediaRouter* router);
   bool HasScreenAvailabilityListenerForTest(
       int render_process_id,
       int render_frame_id,
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc b/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc
index 995a268..e3fe7d5 100644
--- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc
+++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/test/mock_callback.h"
 #include "build/build_config.h"
+#include "chrome/browser/media/router/media_router_factory.h"
 #include "chrome/browser/media/router/presentation/local_presentation_manager.h"
 #include "chrome/browser/media/router/presentation/local_presentation_manager_factory.h"
 #include "chrome/browser/media/router/test/mock_media_router.h"
@@ -117,7 +118,8 @@
     : public ChromeRenderViewHostTestHarness {
  public:
   PresentationServiceDelegateImplTest()
-      : delegate_impl_(nullptr),
+      : router_(nullptr),
+        delegate_impl_(nullptr),
         presentation_url1_(kPresentationUrl1),
         presentation_url2_(kPresentationUrl2),
         presentation_urls_({presentation_url1_}),
@@ -131,10 +133,12 @@
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
     content::WebContents* wc = GetWebContents();
+    router_ = static_cast<MockMediaRouter*>(
+        MediaRouterFactory::GetInstance()->SetTestingFactoryAndUse(
+            web_contents()->GetBrowserContext(), &MockMediaRouter::Create));
     ASSERT_TRUE(wc);
     PresentationServiceDelegateImpl::CreateForWebContents(wc);
     delegate_impl_ = PresentationServiceDelegateImpl::FromWebContents(wc);
-    delegate_impl_->SetMediaRouterForTest(&router_);
     SetMainFrame();
     presentation_request_ = std::make_unique<content::PresentationRequest>(
         RenderFrameHostId(main_frame_process_id_, main_frame_routing_id_),
@@ -203,8 +207,8 @@
             profile()));
   }
 
+  MockMediaRouter* router_;
   PresentationServiceDelegateImpl* delegate_impl_;
-  MockMediaRouter router_;
   const GURL presentation_url1_;
   const GURL presentation_url2_;
   std::vector<GURL> presentation_urls_;
@@ -263,7 +267,7 @@
   // result, the observer added with have an empty GURL as origin.
   int render_frame_id2 = 2;
 
-  EXPECT_CALL(router_, RegisterMediaSinksObserver(_))
+  EXPECT_CALL(*router_, RegisterMediaSinksObserver(_))
       .Times(2)
       .WillRepeatedly(Return(true));
   EXPECT_TRUE(delegate_impl_->AddScreenAvailabilityListener(
@@ -277,7 +281,7 @@
       main_frame_process_id_, render_frame_id2, source2_.id()))
       << "Mapping not found for " << source2_.ToString();
 
-  EXPECT_CALL(router_, UnregisterMediaSinksObserver(_)).Times(2);
+  EXPECT_CALL(*router_, UnregisterMediaSinksObserver(_)).Times(2);
   delegate_impl_->RemoveScreenAvailabilityListener(
       main_frame_process_id_, main_frame_routing_id_, &listener1_);
   delegate_impl_->RemoveScreenAvailabilityListener(
@@ -289,9 +293,9 @@
 }
 
 TEST_F(PresentationServiceDelegateImplTest, AddMultipleListenersToFrame) {
-  ON_CALL(router_, RegisterMediaSinksObserver(_)).WillByDefault(Return(true));
+  ON_CALL(*router_, RegisterMediaSinksObserver(_)).WillByDefault(Return(true));
 
-  EXPECT_CALL(router_, RegisterMediaSinksObserver(_)).Times(2);
+  EXPECT_CALL(*router_, RegisterMediaSinksObserver(_)).Times(2);
   EXPECT_TRUE(delegate_impl_->AddScreenAvailabilityListener(
       main_frame_process_id_, main_frame_routing_id_, &listener1_));
   EXPECT_TRUE(delegate_impl_->AddScreenAvailabilityListener(
@@ -303,7 +307,7 @@
       main_frame_process_id_, main_frame_routing_id_, source2_.id()))
       << "Mapping not found for " << source2_.ToString();
 
-  EXPECT_CALL(router_, UnregisterMediaSinksObserver(_)).Times(2);
+  EXPECT_CALL(*router_, UnregisterMediaSinksObserver(_)).Times(2);
   delegate_impl_->RemoveScreenAvailabilityListener(
       main_frame_process_id_, main_frame_routing_id_, &listener1_);
   delegate_impl_->RemoveScreenAvailabilityListener(
@@ -315,7 +319,7 @@
 }
 
 TEST_F(PresentationServiceDelegateImplTest, AddSameListenerTwice) {
-  EXPECT_CALL(router_, RegisterMediaSinksObserver(_)).WillOnce(Return(true));
+  EXPECT_CALL(*router_, RegisterMediaSinksObserver(_)).WillOnce(Return(true));
   EXPECT_TRUE(delegate_impl_->AddScreenAvailabilityListener(
       main_frame_process_id_, main_frame_routing_id_, &listener1_));
   EXPECT_FALSE(delegate_impl_->AddScreenAvailabilityListener(
@@ -323,7 +327,7 @@
   EXPECT_TRUE(delegate_impl_->HasScreenAvailabilityListenerForTest(
       main_frame_process_id_, main_frame_routing_id_, source1_.id()));
 
-  EXPECT_CALL(router_, UnregisterMediaSinksObserver(_)).Times(1);
+  EXPECT_CALL(*router_, UnregisterMediaSinksObserver(_)).Times(1);
   delegate_impl_->RemoveScreenAvailabilityListener(
       main_frame_process_id_, main_frame_routing_id_, &listener1_);
   EXPECT_FALSE(delegate_impl_->HasScreenAvailabilityListenerForTest(
@@ -337,7 +341,7 @@
                   blink::mojom::ScreenAvailability::SOURCE_NOT_SUPPORTED));
   EXPECT_FALSE(delegate_impl_->AddScreenAvailabilityListener(
       main_frame_process_id_, main_frame_routing_id_, &listener));
-  EXPECT_CALL(router_, RegisterMediaSinksObserver(_)).Times(0);
+  EXPECT_CALL(*router_, RegisterMediaSinksObserver(_)).Times(0);
 }
 
 TEST_F(PresentationServiceDelegateImplTest, SetDefaultPresentationUrl) {
@@ -422,7 +426,7 @@
 
   // Set up a PresentationConnection so we can listen to it.
   std::vector<MediaRouteResponseCallback> route_response_callbacks;
-  EXPECT_CALL(router_, JoinRouteInternal(_, _, _, _, _, _, false))
+  EXPECT_CALL(*router_, JoinRouteInternal(_, _, _, _, _, _, false))
       .WillOnce(WithArgs<4>(
           Invoke([&route_response_callbacks](
                      std::vector<MediaRouteResponseCallback>& callbacks) {
@@ -458,21 +462,21 @@
       mock_callback;
   auto callback = mock_callback.Get();
   content::PresentationInfo connection(presentation_url1_, kPresentationId);
-  EXPECT_CALL(router_, OnAddPresentationConnectionStateChangedCallbackInvoked(
-                           Equals(callback)));
+  EXPECT_CALL(*router_, OnAddPresentationConnectionStateChangedCallbackInvoked(
+                            Equals(callback)));
   delegate_impl_->ListenForConnectionStateChange(
       main_frame_process_id_, main_frame_routing_id_, connection, callback);
 }
 
 TEST_F(PresentationServiceDelegateImplTest, Reset) {
-  EXPECT_CALL(router_, RegisterMediaSinksObserver(_))
+  EXPECT_CALL(*router_, RegisterMediaSinksObserver(_))
       .WillRepeatedly(Return(true));
 
   EXPECT_TRUE(delegate_impl_->AddScreenAvailabilityListener(
       main_frame_process_id_, main_frame_routing_id_, &listener1_));
   EXPECT_TRUE(delegate_impl_->HasScreenAvailabilityListenerForTest(
       main_frame_process_id_, main_frame_routing_id_, source1_.id()));
-  EXPECT_CALL(router_, UnregisterMediaSinksObserver(_)).Times(1);
+  EXPECT_CALL(*router_, UnregisterMediaSinksObserver(_)).Times(1);
   delegate_impl_->Reset(main_frame_process_id_, main_frame_routing_id_);
   EXPECT_FALSE(delegate_impl_->HasScreenAvailabilityListenerForTest(
       main_frame_process_id_, main_frame_routing_id_, source1_.id()));
@@ -481,7 +485,6 @@
 TEST_F(PresentationServiceDelegateImplTest, DelegateObservers) {
   std::unique_ptr<PresentationServiceDelegateImpl> manager(
       new PresentationServiceDelegateImpl(GetWebContents()));
-  manager->SetMediaRouterForTest(&router_);
 
   StrictMock<MockDelegateObserver> delegate_observer1;
   StrictMock<MockDelegateObserver> delegate_observer2;
@@ -497,7 +500,7 @@
 }
 
 TEST_F(PresentationServiceDelegateImplTest, SinksObserverCantRegister) {
-  EXPECT_CALL(router_, RegisterMediaSinksObserver(_)).WillOnce(Return(false));
+  EXPECT_CALL(*router_, RegisterMediaSinksObserver(_)).WillOnce(Return(false));
   EXPECT_CALL(listener1_, OnScreenAvailabilityChanged(
                               blink::mojom::ScreenAvailability::DISABLED));
   EXPECT_FALSE(delegate_impl_->AddScreenAvailabilityListener(
@@ -528,7 +531,7 @@
   EXPECT_CALL(mock_local_manager,
               UnregisterLocalPresentationController(kPresentationId, rfh_id))
       .Times(1);
-  EXPECT_CALL(router_, DetachRoute(_)).Times(0);
+  EXPECT_CALL(*router_, DetachRoute(_)).Times(0);
 
   delegate_impl_->CloseConnection(main_frame_process_id_,
                                   main_frame_routing_id_, kPresentationId);
@@ -590,7 +593,7 @@
 
   EXPECT_CALL(mock_local_manager,
               UnregisterLocalPresentationController(kPresentationId, rfh_id));
-  EXPECT_CALL(router_, DetachRoute(_)).Times(0);
+  EXPECT_CALL(*router_, DetachRoute(_)).Times(0);
   delegate_impl_->Reset(main_frame_process_id_, main_frame_routing_id_);
 }
 
@@ -616,13 +619,13 @@
       &mock_proxy, mojo::MakeRequest(&connection_ptr));
 
   content::PresentationConnectionRequest connection_request;
-  EXPECT_CALL(router_, RegisterRouteMessageObserver(_));
+  EXPECT_CALL(*router_, RegisterRouteMessageObserver(_));
   delegate_impl_->ConnectToPresentation(
       main_frame_process_id_, main_frame_routing_id_, presentation_info,
       std::move(connection_ptr), std::move(connection_request));
 
-  EXPECT_CALL(router_, UnregisterRouteMessageObserver(_));
-  EXPECT_CALL(router_, DetachRoute("route_id")).Times(1);
+  EXPECT_CALL(*router_, UnregisterRouteMessageObserver(_));
+  EXPECT_CALL(*router_, DetachRoute("route_id")).Times(1);
   delegate_impl_->Reset(main_frame_process_id_, main_frame_routing_id_);
 }
 
@@ -649,7 +652,7 @@
 
   // Auto-join requests should be rejected.
   EXPECT_CALL(mock_create_connection_callbacks, OnCreateConnectionError(_));
-  EXPECT_CALL(router_, JoinRouteInternal(_, kPresentationId, _, _, _, _, _))
+  EXPECT_CALL(*router_, JoinRouteInternal(_, kPresentationId, _, _, _, _, _))
       .Times(0);
   delegate_impl_->ReconnectPresentation(
       *presentation_request_, kPresentationId,
@@ -668,7 +671,7 @@
   }
 
   // Auto-join requests should now go through.
-  EXPECT_CALL(router_, JoinRouteInternal(_, kPresentationId, _, _, _, _, _))
+  EXPECT_CALL(*router_, JoinRouteInternal(_, kPresentationId, _, _, _, _, _))
       .Times(1);
   delegate_impl_->ReconnectPresentation(
       *presentation_request_, kPresentationId,
@@ -709,7 +712,7 @@
 
   // Auto-join requests should be rejected.
   EXPECT_CALL(mock_create_connection_callbacks, OnCreateConnectionError(_));
-  EXPECT_CALL(router_, JoinRouteInternal(_, kPresentationId, _, _, _, _, _))
+  EXPECT_CALL(*router_, JoinRouteInternal(_, kPresentationId, _, _, _, _, _))
       .Times(0);
   delegate_impl_->ReconnectPresentation(
       *presentation_request_, kPresentationId,
@@ -728,7 +731,7 @@
   }
 
   // Auto-join requests should now go through.
-  EXPECT_CALL(router_, JoinRouteInternal(_, kPresentationId, _, _, _, _, _))
+  EXPECT_CALL(*router_, JoinRouteInternal(_, kPresentationId, _, _, _, _, _))
       .Times(1);
   delegate_impl_->ReconnectPresentation(
       *presentation_request_, kPresentationId,
diff --git a/chrome/browser/media/router/providers/cast/dual_media_sink_service.cc b/chrome/browser/media/router/providers/cast/dual_media_sink_service.cc
index 30d22d2e..2b8352d6 100644
--- a/chrome/browser/media/router/providers/cast/dual_media_sink_service.cc
+++ b/chrome/browser/media/router/providers/cast/dual_media_sink_service.cc
@@ -14,13 +14,24 @@
 
 namespace media_router {
 
+DualMediaSinkService* DualMediaSinkService::instance_for_test_ = nullptr;
+
 // static
 DualMediaSinkService* DualMediaSinkService::GetInstance() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (instance_for_test_)
+    return instance_for_test_;
+
   static DualMediaSinkService* instance = new DualMediaSinkService();
   return instance;
 }
 
+// static
+void DualMediaSinkService::SetInstanceForTest(
+    DualMediaSinkService* instance_for_test) {
+  instance_for_test_ = instance_for_test;
+}
+
 DualMediaSinkService::Subscription
 DualMediaSinkService::AddSinksDiscoveredCallback(
     const OnSinksDiscoveredProviderCallback& callback) {
diff --git a/chrome/browser/media/router/providers/cast/dual_media_sink_service.h b/chrome/browser/media/router/providers/cast/dual_media_sink_service.h
index a957e36..362c01b 100644
--- a/chrome/browser/media/router/providers/cast/dual_media_sink_service.h
+++ b/chrome/browser/media/router/providers/cast/dual_media_sink_service.h
@@ -43,6 +43,7 @@
 
   // Returns the lazily-created leaky singleton instance.
   static DualMediaSinkService* GetInstance();
+  static void SetInstanceForTest(DualMediaSinkService* instance_for_test);
 
   // Returns the current list of sinks, keyed by provider name.
   const base::flat_map<std::string, std::vector<MediaSinkInternal>>&
@@ -56,13 +57,20 @@
   Subscription AddSinksDiscoveredCallback(
       const OnSinksDiscoveredProviderCallback& callback);
 
-  void OnUserGesture();
+  virtual void OnUserGesture();
 
   // Starts mDNS discovery on |cast_media_sink_service_| if it is not already
   // started.
-  void StartMdnsDiscovery();
-  void RegisterMediaSinksObserver(MediaSinksObserver* observer);
-  void UnregisterMediaSinksObserver(MediaSinksObserver* observer);
+  virtual void StartMdnsDiscovery();
+  virtual void RegisterMediaSinksObserver(MediaSinksObserver* observer);
+  virtual void UnregisterMediaSinksObserver(MediaSinksObserver* observer);
+
+ protected:
+  // Used by tests.
+  DualMediaSinkService(
+      std::unique_ptr<CastMediaSinkService> cast_media_sink_service,
+      std::unique_ptr<DialMediaSinkService> dial_media_sink_service);
+  virtual ~DualMediaSinkService();
 
  private:
   friend class DualMediaSinkServiceTest;
@@ -74,15 +82,10 @@
 
   friend struct std::default_delete<DualMediaSinkService>;
 
+  static DualMediaSinkService* instance_for_test_;
+
   DualMediaSinkService();
 
-  // Used by tests.
-  DualMediaSinkService(
-      std::unique_ptr<CastMediaSinkService> cast_media_sink_service,
-      std::unique_ptr<DialMediaSinkService> dial_media_sink_service);
-
-  ~DualMediaSinkService();
-
   void OnSinksDiscovered(const std::string& provider_name,
                          std::vector<MediaSinkInternal> sinks);
 
diff --git a/chrome/browser/media/router/test/noop_dual_media_sink_service.cc b/chrome/browser/media/router/test/noop_dual_media_sink_service.cc
new file mode 100644
index 0000000..d4dcd61
--- /dev/null
+++ b/chrome/browser/media/router/test/noop_dual_media_sink_service.cc
@@ -0,0 +1,17 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/router/test/noop_dual_media_sink_service.h"
+
+#include "chrome/browser/media/router/discovery/dial/dial_media_sink_service.h"
+#include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h"
+
+namespace media_router {
+
+NoopDualMediaSinkService::NoopDualMediaSinkService()
+    : DualMediaSinkService(std::unique_ptr<CastMediaSinkService>(nullptr),
+                           std::unique_ptr<DialMediaSinkService>(nullptr)) {}
+NoopDualMediaSinkService::~NoopDualMediaSinkService() = default;
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/test/noop_dual_media_sink_service.h b/chrome/browser/media/router/test/noop_dual_media_sink_service.h
new file mode 100644
index 0000000..d8f30d4
--- /dev/null
+++ b/chrome/browser/media/router/test/noop_dual_media_sink_service.h
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_ROUTER_TEST_NOOP_DUAL_MEDIA_SINK_SERVICE_H_
+#define CHROME_BROWSER_MEDIA_ROUTER_TEST_NOOP_DUAL_MEDIA_SINK_SERVICE_H_
+
+#include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h"
+
+namespace media_router {
+
+class NoopDualMediaSinkService : public DualMediaSinkService {
+ public:
+  NoopDualMediaSinkService();
+  ~NoopDualMediaSinkService() override;
+
+  // DualMediaSinkService
+  void OnUserGesture() override {}
+  void StartMdnsDiscovery() override {}
+  void RegisterMediaSinksObserver(MediaSinksObserver* observer) override {}
+  void UnregisterMediaSinksObserver(MediaSinksObserver* observer) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NoopDualMediaSinkService);
+};
+
+}  // namespace media_router
+
+#endif  // CHROME_BROWSER_MEDIA_ROUTER_TEST_NOOP_DUAL_MEDIA_SINK_SERVICE_H_
diff --git a/chrome/browser/resources/cryptotoken/gnubby-u2f.js b/chrome/browser/resources/cryptotoken/gnubby-u2f.js
index d0335ec9..4d219de 100644
--- a/chrome/browser/resources/cryptotoken/gnubby-u2f.js
+++ b/chrome/browser/resources/cryptotoken/gnubby-u2f.js
@@ -151,8 +151,8 @@
       cb(-GnubbyDevice.OK, v1.buffer);
       return;
     }
-    if (rc == 0x6700) {
-      // Wrong length. Try with non-ISO 7816-4-conforming layout defined in
+    if (rc) {
+      // Error. Try with non-ISO 7816-4-conforming layout defined in
       // earlier U2F drafts.
       apdu = new Uint8Array(
           [0x00, Gnubby.U2F_VERSION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
index e1c4626..84c7fa3 100644
--- a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
+++ b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
@@ -9,6 +9,8 @@
 #include "chrome/browser/extensions/browser_action_test_util.h"
 #include "chrome/browser/extensions/extension_action_test_util.h"
 #include "chrome/browser/extensions/load_error_reporter.h"
+#include "chrome/browser/media/router/media_router_factory.h"
+#include "chrome/browser/media/router/test/mock_media_router.h"
 #include "chrome/browser/signin/fake_signin_manager_builder.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h"
@@ -63,6 +65,11 @@
     BrowserWithTestWindowTest::TearDown();
   }
 
+  TestingProfile::TestingFactories GetTestingFactories() override {
+    return {{media_router::MediaRouterFactory::GetInstance(),
+             &media_router::MockMediaRouter::Create}};
+  }
+
  protected:
   // These constants are used to inject the state of the Media Router action
   // that would be inferred in the production code.
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
index fc499de4..3d74af7b 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
@@ -18,6 +18,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "chrome/browser/local_discovery/test_service_discovery_client.h"
+#include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h"
+#include "chrome/browser/media/router/test/noop_dual_media_sink_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -355,6 +357,16 @@
   ~LocalDiscoveryUITest() override {
   }
 
+  void SetUp() override {
+    // We need to stub out DualMediaSinkService here, because the profile setup
+    // instantiates DualMediaSinkService, which in turn sets
+    // |g_service_discovery_client| with a real instance. This causes
+    // a DCHECK during TestServiceDiscoveryClient construction.
+    media_router::DualMediaSinkService::SetInstanceForTest(
+        new media_router::NoopDualMediaSinkService());
+    WebUIBrowserTest::SetUp();
+  }
+
   void SetUpOnMainThread() override {
     WebUIBrowserTest::SetUpOnMainThread();
 
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.cc b/chrome/browser/ui/webui/media_router/media_router_ui.cc
index e9a87a1c..dbef24b 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui.cc
@@ -343,11 +343,6 @@
   std::unique_ptr<content::WebUIDataSource> html_source(
       content::WebUIDataSource::Create(chrome::kChromeUIMediaRouterHost));
 
-  content::WebContents* wc = web_ui->GetWebContents();
-  DCHECK(wc);
-  content::BrowserContext* context = wc->GetBrowserContext();
-  router_ = MediaRouterFactory::GetApiForBrowserContext(context);
-
   AddLocalizedStrings(html_source.get());
   AddMediaRouterUIResources(html_source.get());
   // Ownership of |html_source| is transferred to the BrowserContext.
@@ -429,11 +424,13 @@
 
 void MediaRouterUI::InitCommon(content::WebContents* initiator) {
   DCHECK(initiator);
-  DCHECK(router_);
 
   TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("media_router", "UI", initiator,
                                       "MediaRouterUI::InitCommon", this);
 
+  router_ = GetMediaRouter();
+  DCHECK(router_);
+
   // Presentation requests from content must show the origin requesting
   // presentation: crbug.com/704964
   if (start_presentation_context_)
@@ -495,7 +492,6 @@
     MediaRouterWebUIMessageHandler* handler,
     std::unique_ptr<StartPresentationContext> context,
     std::unique_ptr<MediaRouterFileDialog> file_dialog) {
-  router_ = router;
   handler_ = handler;
   start_presentation_context_ = std::move(context);
   InitForTest(std::move(file_dialog));
@@ -593,6 +589,13 @@
   TRACE_EVENT_NESTABLE_ASYNC_END0("media_router", "UI", initiator_);
   ui_initialized_ = true;
 
+  // Workaround for MediaRouterElementsBrowserTest, in which MediaRouterUI is
+  // created without calling one of the |Init*()| methods.
+  // TODO(imcheng): We should be able to instantiate |issue_observer_| during
+  // InitCommon by storing an initial Issue in this class.
+  if (!router_)
+    router_ = GetMediaRouter();
+
   // Register for Issue updates.
   issues_observer_ =
       std::make_unique<UIIssuesObserver>(GetIssueManager(), this);
@@ -1125,4 +1128,8 @@
   handler_->UpdateSinks(GetEnabledSinks());
 }
 
+MediaRouter* MediaRouterUI::GetMediaRouter() {
+  return MediaRouterFactory::GetApiForBrowserContext(
+      web_ui()->GetWebContents()->GetBrowserContext());
+}
 }  // namespace media_router
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.h b/chrome/browser/ui/webui/media_router/media_router_ui.h
index 7bc9d0ee..e8abac5 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui.h
+++ b/chrome/browser/ui/webui/media_router/media_router_ui.h
@@ -403,6 +403,9 @@
   // Sends the current list of enabled sinks to |handler_|.
   void UpdateSinks();
 
+  // Overridden by tests.
+  virtual MediaRouter* GetMediaRouter();
+
   // Owned by the |web_ui| passed in the ctor, and guaranteed to be deleted
   // only after it has deleted |this|.
   MediaRouterWebUIMessageHandler* handler_ = nullptr;
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_service_factory_unittest.cc b/chrome/browser/ui/webui/media_router/media_router_ui_service_factory_unittest.cc
index c3d0cbd..3ee9f6d2 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_service_factory_unittest.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_service_factory_unittest.cc
@@ -4,6 +4,8 @@
 
 #include <memory>
 
+#include "chrome/browser/media/router/media_router_factory.h"
+#include "chrome/browser/media/router/test/mock_media_router.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h"
@@ -26,6 +28,8 @@
     // requires ToolbarActionsModel.
     builder.AddTestingFactory(ToolbarActionsModelFactory::GetInstance(),
                               BuildFakeToolBarActionsModel);
+    builder.AddTestingFactory(MediaRouterFactory::GetInstance(),
+                              MockMediaRouter::Create);
     profile_ = builder.Build();
   }
 
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
index 0d4e529..6a6e17ef 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
@@ -117,6 +117,19 @@
   content::PresentationError expected_error_;
 };
 
+class TestMediaRouterUI : public MediaRouterUI {
+ public:
+  TestMediaRouterUI(content::WebUI* web_ui, MediaRouter* router)
+      : MediaRouterUI(web_ui), router_(router) {}
+  ~TestMediaRouterUI() override = default;
+
+  MediaRouter* GetMediaRouter() override { return router_; }
+
+ private:
+  MediaRouter* router_;
+  DISALLOW_COPY_AND_ASSIGN(TestMediaRouterUI);
+};
+
 class MediaRouterUITest : public ChromeRenderViewHostTestHarness {
  public:
   MediaRouterUITest()
@@ -162,7 +175,8 @@
     web_ui_contents_.reset(
         WebContents::Create(WebContents::CreateParams(profile)));
     web_ui_.set_web_contents(web_ui_contents_.get());
-    media_router_ui_ = std::make_unique<MediaRouterUI>(&web_ui_);
+    media_router_ui_ =
+        std::make_unique<TestMediaRouterUI>(&web_ui_, &mock_router_);
     message_handler_ = std::make_unique<MockMediaRouterWebUIMessageHandler>(
         media_router_ui_.get());
 
@@ -213,7 +227,7 @@
   content::TestWebUI web_ui_;
   std::unique_ptr<WebContents> web_ui_contents_;
   std::unique_ptr<StartPresentationContext> start_presentation_context_;
-  std::unique_ptr<MediaRouterUI> media_router_ui_;
+  std::unique_ptr<TestMediaRouterUI> media_router_ui_;
   std::unique_ptr<MockMediaRouterWebUIMessageHandler> message_handler_;
   MockMediaRouterFileDialog* mock_file_dialog_ = nullptr;
   std::vector<MediaSinksObserver*> media_sinks_observers_;
@@ -787,7 +801,8 @@
   web_ui_contents_.reset(
       WebContents::Create(WebContents::CreateParams(profile())));
   web_ui_.set_web_contents(web_ui_contents_.get());
-  media_router_ui_ = std::make_unique<MediaRouterUI>(&web_ui_);
+  media_router_ui_ =
+      std::make_unique<TestMediaRouterUI>(&web_ui_, &mock_router_);
   message_handler_ = std::make_unique<MockMediaRouterWebUIMessageHandler>(
       media_router_ui_.get());
   message_handler_->SetWebUIForTest(&web_ui_);
@@ -797,26 +812,18 @@
         return true;
       }));
   EXPECT_CALL(mock_router_, RegisterMediaRoutesObserver(_)).Times(AnyNumber());
-  // For some reason we push two sets of cast modes to the dialog, even when
-  // initializing the dialog with a presentation request.  The WebUI can handle
-  // the forced mode that is not in the initial cast mode set, but is this a
-  // bug?
-  CastModeSet expected_modes({MediaCastMode::TAB_MIRROR,
-                              MediaCastMode::DESKTOP_MIRROR,
-                              MediaCastMode::LOCAL_FILE});
-  EXPECT_CALL(*message_handler_,
-              UpdateCastModes(
-                  expected_modes, "",
-                  base::Optional<MediaCastMode>(MediaCastMode::PRESENTATION)));
-  expected_modes.insert(MediaCastMode::PRESENTATION);
-  EXPECT_CALL(*message_handler_,
-              UpdateCastModes(
-                  expected_modes, "google.com",
-                  base::Optional<MediaCastMode>(MediaCastMode::PRESENTATION)));
-  media_router_ui_->UIInitialized();
+
+  CastModeSet expected_modes(
+      {MediaCastMode::TAB_MIRROR, MediaCastMode::DESKTOP_MIRROR,
+       MediaCastMode::LOCAL_FILE, MediaCastMode::PRESENTATION});
   media_router_ui_->InitForTest(
       &mock_router_, web_contents(), message_handler_.get(),
       std::move(start_presentation_context_), nullptr);
+  EXPECT_EQ(expected_modes, media_router_ui_->cast_modes());
+  EXPECT_EQ(base::Optional<MediaCastMode>(MediaCastMode::PRESENTATION),
+            media_router_ui_->forced_cast_mode());
+  EXPECT_EQ("google.com", media_router_ui_->GetPresentationRequestSourceName());
+
   // |media_router_ui_| takes ownership of |request_callbacks|.
   media_router_ui_.reset();
 }
diff --git a/chrome/browser/ui/webui/media_router/media_router_web_ui_test.cc b/chrome/browser/ui/webui/media_router/media_router_web_ui_test.cc
index 11ec23b..0b0a38e 100644
--- a/chrome/browser/ui/webui/media_router/media_router_web_ui_test.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_web_ui_test.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/webui/media_router/media_router_web_ui_test.h"
 
+#include "chrome/browser/media/router/media_router_factory.h"
+#include "chrome/browser/media/router/test/mock_media_router.h"
 #include "chrome/browser/ui/toolbar/mock_media_router_action_controller.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h"
@@ -45,14 +47,18 @@
 MediaRouterWebUITest::~MediaRouterWebUITest() {}
 
 TestingProfile::TestingFactories MediaRouterWebUITest::GetTestingFactories() {
+  TestingProfile::TestingFactories factories = {
+      {media_router::MediaRouterFactory::GetInstance(),
+       &media_router::MockMediaRouter::Create}};
   if (require_mock_ui_service_) {
-    return {
-        {media_router::MediaRouterUIServiceFactory::GetInstance(),
-         BuildMockMediaRouterUIService},
-        {ToolbarActionsModelFactory::GetInstance(), BuildToolbarActionsModel}};
+    factories.emplace_back(
+        media_router::MediaRouterUIServiceFactory::GetInstance(),
+        BuildMockMediaRouterUIService);
+    factories.emplace_back(ToolbarActionsModelFactory::GetInstance(),
+                           BuildToolbarActionsModel);
   }
 
-  return BrowserWithTestWindowTest::GetTestingFactories();
+  return factories;
 }
 
 BrowserWindow* MediaRouterWebUITest::CreateBrowserWindow() {
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index c84509e..750084e 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/extensions/extension_enable_flow.h"
@@ -608,6 +609,13 @@
   if (!extension)
     return;
 
+  if (extension->is_hosted_app() && extension->from_bookmark()) {
+    chrome::ShowSiteSettings(
+        chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()),
+        extensions::AppLaunchInfo::GetFullLaunchURL(extension));
+    return;
+  }
+
   UMA_HISTOGRAM_ENUMERATION("Apps.AppInfoDialog.Launches",
                             AppInfoLaunchSource::FROM_APPS_PAGE,
                             AppInfoLaunchSource::NUM_LAUNCH_SOURCES);
diff --git a/chrome/browser/ui/webui/print_preview/printer_capabilities.cc b/chrome/browser/ui/webui/print_preview/printer_capabilities.cc
index 20d6688..c696002 100644
--- a/chrome/browser/ui/webui/print_preview/printer_capabilities.cc
+++ b/chrome/browser/ui/webui/print_preview/printer_capabilities.cc
@@ -32,7 +32,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #endif
 
diff --git a/chrome/browser/vr/elements/vector_icon.cc b/chrome/browser/vr/elements/vector_icon.cc
index d40db097..9f42f24 100644
--- a/chrome/browser/vr/elements/vector_icon.cc
+++ b/chrome/browser/vr/elements/vector_icon.cc
@@ -24,6 +24,7 @@
 
   void SetIcon(const gfx::VectorIcon& icon) {
     SetAndDirty(&icon_no_1x_.path, icon.path);
+    SetAndDirty(&icon_no_1x_.path_size, icon.path_size);
   }
 
  private:
@@ -50,7 +51,7 @@
   }
 
   gfx::SizeF size_;
-  gfx::VectorIcon icon_no_1x_{nullptr, nullptr};
+  gfx::VectorIcon icon_no_1x_{};
   SkColor color_ = SK_ColorWHITE;
   DISALLOW_COPY_AND_ASSIGN(VectorIconTexture);
 };
@@ -89,7 +90,7 @@
   // 1x version if device scale factor isn't set. See crbug.com/749146. If all
   // icons end up being drawn via VectorIcon instances, this will not be
   // required (the 1x version is automatically elided by this class).
-  gfx::VectorIcon icon_no_1x{icon.path, nullptr};
+  gfx::VectorIcon icon_no_1x{icon.path, icon.path_size};
   PaintVectorIcon(canvas, icon_no_1x, size_px, color);
 }
 
diff --git a/chrome/browser/vr/vector_icons/vector_icons.cc.template b/chrome/browser/vr/vector_icons/vector_icons.cc.template
index 5969c4f..d3e6381 100644
--- a/chrome/browser/vr/vector_icons/vector_icons.cc.template
+++ b/chrome/browser/vr/vector_icons/vector_icons.cc.template
@@ -11,16 +11,12 @@
 #include "ui/gfx/animation/tween.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
-
-using namespace gfx;
+#include "components/vector_icons/cc_macros.h"
 
 namespace vr {
 
+using namespace gfx;
+
 TEMPLATE_PLACEHOLDER
 
 }  // namespace vr
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 2fa3fed5..49a5c4a 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -208,7 +208,7 @@
 #if defined(OS_ANDROID)
 // Enables downloads as a foreground service for all versions of Android.
 const base::Feature kDownloadsForeground{"DownloadsForeground",
-                                         base::FEATURE_DISABLED_BY_DEFAULT};
+                                         base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
 #if defined(OS_ANDROID)
diff --git a/chrome/test/data/vr/e2e_test_files/resources/webxr_boilerplate.js b/chrome/test/data/vr/e2e_test_files/resources/webxr_boilerplate.js
index 488eec0..baa0f1e 100644
--- a/chrome/test/data/vr/e2e_test_files/resources/webxr_boilerplate.js
+++ b/chrome/test/data/vr/e2e_test_files/resources/webxr_boilerplate.js
@@ -38,7 +38,7 @@
   session.addEventListener('end', onSessionEnded);
   // Initialize the WebGL context for use with XR if it hasn't been already
   if (!gl) {
-    glAttribs['compatibleXrDevice'] = session.device;
+    glAttribs['compatibleXRDevice'] = session.device;
 
     // Create an offscreen canvas and get its context
     let offscreenCanvas = document.createElement('canvas');
diff --git a/chromecast/media/cma/pipeline/BUILD.gn b/chromecast/media/cma/pipeline/BUILD.gn
index 8ddb1ac..906244f8 100644
--- a/chromecast/media/cma/pipeline/BUILD.gn
+++ b/chromecast/media/cma/pipeline/BUILD.gn
@@ -21,6 +21,10 @@
     "av_pipeline_client.h",
     "av_pipeline_impl.cc",
     "av_pipeline_impl.h",
+    "backend_decryptor.cc",
+    "backend_decryptor.h",
+    "cdm_decryptor.cc",
+    "cdm_decryptor.h",
     "decrypt_util.cc",
     "decrypt_util.h",
     "load_type.h",
@@ -30,6 +34,7 @@
     "media_pipeline_impl.h",
     "media_pipeline_observer.cc",
     "media_pipeline_observer.h",
+    "stream_decryptor.h",
     "video_pipeline_client.cc",
     "video_pipeline_client.h",
     "video_pipeline_impl.cc",
@@ -44,6 +49,7 @@
   deps = [
     ":cma_pipeline_features",
     "//base",
+    "//chromecast/base",
     "//chromecast/base/metrics:metrics",
     "//chromecast/media/base",
     "//chromecast/media/cdm",
diff --git a/chromecast/media/cma/pipeline/audio_pipeline_impl.cc b/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
index 38ec800b2..20aeb68 100644
--- a/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
@@ -12,7 +12,10 @@
 #include "chromecast/media/cma/base/cma_logging.h"
 #include "chromecast/media/cma/base/coded_frame_provider.h"
 #include "chromecast/media/cma/base/decoder_config_adapter.h"
+#include "chromecast/media/cma/pipeline/backend_decryptor.h"
+#include "chromecast/media/cma/pipeline/cdm_decryptor.h"
 #include "chromecast/public/media/decoder_config.h"
+#include "chromecast/public/media/media_capabilities_shlib.h"
 #include "media/base/audio_decoder_config.h"
 
 namespace chromecast {
@@ -20,6 +23,12 @@
 
 namespace {
 const size_t kMaxAudioFrameSize = 32 * 1024;
+
+bool ShouldUseSoftwareDecoder(const AudioConfig& config) {
+  // If the config isn't supported by the backend natively, we'll use software
+  // decoder to support it.
+  return !MediaCapabilitiesShlib::IsSupportedAudioConfig(config);
+}
 }
 
 AudioPipelineImpl::AudioPipelineImpl(
@@ -29,7 +38,7 @@
   DCHECK(audio_decoder_);
 }
 
-AudioPipelineImpl::~AudioPipelineImpl() {}
+AudioPipelineImpl::~AudioPipelineImpl() = default;
 
 ::media::PipelineStatus AudioPipelineImpl::Initialize(
     const ::media::AudioDecoderConfig& audio_config,
@@ -42,10 +51,9 @@
   }
 
   DCHECK(audio_config.IsValidConfig());
-  AudioConfig cast_audio_config =
+  audio_config_ =
       DecoderConfigAdapter::ToCastAudioConfig(kPrimary, audio_config);
-  encryption_scheme_ = cast_audio_config.encryption_scheme;
-  if (!audio_decoder_->SetConfig(cast_audio_config)) {
+  if (!audio_decoder_->SetConfig(audio_config_)) {
     return ::media::PIPELINE_ERROR_INITIALIZATION_FAILED;
   }
   set_state(kFlushed);
@@ -64,10 +72,8 @@
     CMALOG(kLogControl) << __FUNCTION__ << " id:" << id << " "
                         << audio_config.AsHumanReadableString();
 
-    AudioConfig cast_audio_config =
-        DecoderConfigAdapter::ToCastAudioConfig(id, audio_config);
-    encryption_scheme_ = cast_audio_config.encryption_scheme;
-    bool success = audio_decoder_->SetConfig(cast_audio_config);
+    audio_config_ = DecoderConfigAdapter::ToCastAudioConfig(id, audio_config);
+    bool success = audio_decoder_->SetConfig(audio_config_);
     if (!success && !client().playback_error_cb.is_null())
       client().playback_error_cb.Run(::media::PIPELINE_ERROR_DECODE);
   }
@@ -75,7 +81,19 @@
 
 const EncryptionScheme& AudioPipelineImpl::GetEncryptionScheme(
     StreamId id) const {
-  return encryption_scheme_;
+  return audio_config_.encryption_scheme;
+}
+
+std::unique_ptr<StreamDecryptor> AudioPipelineImpl::CreateDecryptor() {
+  // TODO(yucliu): Enable it on devices that support multiroom.
+  if (audio_config_.encryption_scheme.is_encrypted() &&
+      MediaPipelineBackend::CreateAudioDecryptor &&
+      ShouldUseSoftwareDecoder(audio_config_)) {
+    CMALOG(kLogControl) << __func__ << " Create backend decryptor for audio.";
+    return std::make_unique<BackendDecryptor>(audio_config_.encryption_scheme);
+  }
+
+  return std::make_unique<CdmDecryptor>();
 }
 
 void AudioPipelineImpl::UpdateStatistics() {
diff --git a/chromecast/media/cma/pipeline/audio_pipeline_impl.h b/chromecast/media/cma/pipeline/audio_pipeline_impl.h
index 87c3d01..1f9382b 100644
--- a/chromecast/media/cma/pipeline/audio_pipeline_impl.h
+++ b/chromecast/media/cma/pipeline/audio_pipeline_impl.h
@@ -45,9 +45,11 @@
                       const ::media::AudioDecoderConfig& audio_config,
                       const ::media::VideoDecoderConfig& video_config) override;
   const EncryptionScheme& GetEncryptionScheme(StreamId id) const override;
+  std::unique_ptr<StreamDecryptor> CreateDecryptor() override;
 
   MediaPipelineBackend::AudioDecoder* const audio_decoder_;
-  EncryptionScheme encryption_scheme_;
+
+  AudioConfig audio_config_;
 
   DISALLOW_COPY_AND_ASSIGN(AudioPipelineImpl);
 };
diff --git a/chromecast/media/cma/pipeline/av_pipeline_impl.cc b/chromecast/media/cma/pipeline/av_pipeline_impl.cc
index 4656309..a8da7de0 100644
--- a/chromecast/media/cma/pipeline/av_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/av_pipeline_impl.cc
@@ -45,7 +45,7 @@
       playable_buffered_time_(::media::kNoTimestamp),
       enable_feeding_(false),
       pending_read_(false),
-      cast_cdm_context_(NULL),
+      cast_cdm_context_(nullptr),
       player_tracker_callback_id_(kNoCallbackId),
       weak_factory_(this),
       decrypt_weak_factory_(this) {
@@ -140,6 +140,11 @@
   // in a double push.
   decrypt_weak_factory_.InvalidateWeakPtrs();
 
+  ready_buffers_ = {};
+
+  // Reset |decryptor_| to flush buffered frames in |decryptor_|.
+  decryptor_.reset();
+
   frame_provider_->Flush(base::Bind(&AvPipelineImpl::OnFlushDone, weak_this_));
 }
 
@@ -197,6 +202,13 @@
   if (audio_config.IsValidConfig() || video_config.IsValidConfig())
     OnUpdateConfig(buffer->stream_id(), audio_config, video_config);
 
+  if (!decryptor_) {
+    decryptor_ = CreateDecryptor();
+    DCHECK(decryptor_);
+    decryptor_->Init(base::BindRepeating(&AvPipelineImpl::OnBufferDecrypted,
+                                         decrypt_weak_factory_.GetWeakPtr()));
+  }
+
   pending_buffer_ = buffer;
   ProcessPendingBuffer();
 }
@@ -237,38 +249,34 @@
     }
 
     DCHECK_NE(decrypt_context->GetKeySystem(), KEY_SYSTEM_NONE);
-
-    // If we can get the clear content, decrypt the pending buffer
-    if (decrypt_context->CanDecryptToBuffer()) {
-      auto buffer = pending_buffer_;
-      pending_buffer_ = nullptr;
-      DecryptDecoderBuffer(buffer, decrypt_context.get(),
-                           base::Bind(&AvPipelineImpl::OnBufferDecrypted,
-                                      decrypt_weak_factory_.GetWeakPtr(),
-                                      base::Passed(&decrypt_context)));
-
-      return;
-    }
-
     pending_buffer_->set_decrypt_context(std::move(decrypt_context));
   }
 
-  PushPendingBuffer();
+  decryptor_->Decrypt(std::move(pending_buffer_));
 }
 
-void AvPipelineImpl::PushPendingBuffer() {
-  DCHECK(pending_buffer_);
+void AvPipelineImpl::PushAllReadyBuffers() {
+  DCHECK(!ready_buffers_.empty());
+
+  scoped_refptr<DecoderBufferBase> ready_buffer =
+      std::move(ready_buffers_.front());
+  ready_buffers_.pop();
+
+  PushReadyBuffer(std::move(ready_buffer));
+}
+
+void AvPipelineImpl::PushReadyBuffer(scoped_refptr<DecoderBufferBase> buffer) {
   DCHECK(!pushed_buffer_);
 
-  if (!pending_buffer_->end_of_stream() && buffering_state_.get()) {
+  if (!buffer->end_of_stream() && buffering_state_.get()) {
     base::TimeDelta timestamp =
-        base::TimeDelta::FromMicroseconds(pending_buffer_->timestamp());
+        base::TimeDelta::FromMicroseconds(buffer->timestamp());
     if (timestamp != ::media::kNoTimestamp)
       buffering_state_->SetMaxRenderingTime(timestamp);
   }
 
-  pushed_buffer_ = pending_buffer_;
-  pending_buffer_ = nullptr;
+  pushed_buffer_ = std::move(buffer);
+
   MediaPipelineBackend::BufferStatus status =
       decoder_->PushBuffer(pushed_buffer_.get());
 
@@ -276,32 +284,41 @@
     OnPushBufferComplete(status);
 }
 
-void AvPipelineImpl::OnBufferDecrypted(
-    std::unique_ptr<DecryptContextImpl> decrypt_context,
-    scoped_refptr<DecoderBufferBase> buffer,
-    bool success) {
+void AvPipelineImpl::OnBufferDecrypted(bool success,
+                                       StreamDecryptor::BufferQueue buffers) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
   if (!success) {
-    LOG(WARNING) << "Can't decrypt with decrypt_context";
-    buffer->set_decrypt_context(std::move(decrypt_context));
+    OnDecoderError();
+    return;
   }
 
-  if (!enable_feeding_)
+  // Decryptor needs more data.
+  if (buffers.empty()) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(&AvPipelineImpl::FetchBuffer, weak_this_));
     return;
+  }
 
-  pending_buffer_ = buffer;
-  PushPendingBuffer();
+  ready_buffers_ = std::move(buffers);
+  PushAllReadyBuffers();
 }
 
 void AvPipelineImpl::OnPushBufferComplete(BufferStatus status) {
   DCHECK(thread_checker_.CalledOnValidThread());
+
   pushed_buffer_ = nullptr;
   if (status == MediaPipelineBackend::kBufferFailed) {
     LOG(WARNING) << "AvPipelineImpl: PushFrame failed";
     OnDecoderError();
     return;
   }
+
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&AvPipelineImpl::FetchBuffer, weak_this_));
+      FROM_HERE,
+      ready_buffers_.empty()
+          ? base::BindOnce(&AvPipelineImpl::FetchBuffer, weak_this_)
+          : base::BindOnce(&AvPipelineImpl::PushAllReadyBuffers, weak_this_));
 }
 
 void AvPipelineImpl::OnEndOfStream() {
diff --git a/chromecast/media/cma/pipeline/av_pipeline_impl.h b/chromecast/media/cma/pipeline/av_pipeline_impl.h
index 3558694..d857f2cc 100644
--- a/chromecast/media/cma/pipeline/av_pipeline_impl.h
+++ b/chromecast/media/cma/pipeline/av_pipeline_impl.h
@@ -18,6 +18,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+#include "chromecast/media/cma/pipeline/stream_decryptor.h"
 #include "chromecast/public/media/media_pipeline_backend.h"
 #include "chromecast/public/media/stream_id.h"
 #include "media/base/pipeline_status.h"
@@ -34,7 +35,6 @@
 class BufferingState;
 class CodedFrameProvider;
 class DecoderBufferBase;
-class DecryptContextImpl;
 struct EncryptionScheme;
 
 class AvPipelineImpl : MediaPipelineBackend::Decoder::Delegate {
@@ -78,6 +78,9 @@
       const ::media::VideoDecoderConfig& video_config) = 0;
   virtual const EncryptionScheme& GetEncryptionScheme(StreamId id) const = 0;
 
+  // Create a decoder for decrypt and decode.
+  virtual std::unique_ptr<StreamDecryptor> CreateDecryptor() = 0;
+
   // Setting the frame provider must be done in the |kUninitialized| state.
   void SetCodedFrameProvider(std::unique_ptr<CodedFrameProvider> frame_provider,
                              size_t max_buffer_size,
@@ -98,6 +101,8 @@
                           uint32_t system_code) override;
   void OnVideoResolutionChanged(const Size& size) override;
 
+  void OnBufferDecrypted(bool success, StreamDecryptor::BufferQueue buffers);
+
   // Feed the pipeline, getting the frames from |frame_provider_|.
   void FetchBuffer();
 
@@ -108,16 +113,19 @@
 
   // Process a pending buffer.
   void ProcessPendingBuffer();
-  void PushPendingBuffer();
+  void DoPushBufferCompleteTask(MediaPipelineBackend::BufferStatus status);
+
+  // Pushes all the ready buffers to decoder.
+  void PushAllReadyBuffers();
+
+  // Pushes one ready buffer to decoder.
+  void PushReadyBuffer(scoped_refptr<DecoderBufferBase> buffer);
 
   // Callbacks:
   // - when BrowserCdm updated its state.
   // - when BrowserCdm has been destroyed.
   void OnCdmStateChanged();
   void OnCdmDestroyed();
-  void OnBufferDecrypted(std::unique_ptr<DecryptContextImpl> decrypt_context,
-                         scoped_refptr<DecoderBufferBase> buffer,
-                         bool success);
 
   // Callback invoked when a media buffer has been buffered by |frame_provider_|
   // which is a BufferingFrameProvider.
@@ -159,9 +167,12 @@
   // Indicate whether there is a pending buffer read.
   bool pending_read_;
 
-  // Pending buffer (not pushed to device yet)
+  // Pending buffer (not pushed to decryptor yet)
   scoped_refptr<DecoderBufferBase> pending_buffer_;
 
+  // Buffers which are ready to be pushed to decoder.
+  StreamDecryptor::BufferQueue ready_buffers_;
+
   // Buffer that has been pushed to the device but not processed yet.
   scoped_refptr<DecoderBufferBase> pushed_buffer_;
 
@@ -169,6 +180,11 @@
   CastCdmContext* cast_cdm_context_;
   int player_tracker_callback_id_;
 
+  // Decryptor to get clear buffers. All the buffers (clear or encrypted) will
+  // be pushed to |decryptor_| before being pushed to |decoder_|. |decryptor_|
+  // can do nothing if the media backend is able to handle encrypted buffer.
+  std::unique_ptr<StreamDecryptor> decryptor_;
+
   base::WeakPtr<AvPipelineImpl> weak_this_;
   base::WeakPtrFactory<AvPipelineImpl> weak_factory_;
   // Special weak factory used for asynchronous decryption. This allows us to
diff --git a/chromecast/media/cma/pipeline/backend_decryptor.cc b/chromecast/media/cma/pipeline/backend_decryptor.cc
new file mode 100644
index 0000000..2c786ab
--- /dev/null
+++ b/chromecast/media/cma/pipeline/backend_decryptor.cc
@@ -0,0 +1,95 @@
+// Copyright 2018 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 "chromecast/media/cma/pipeline/backend_decryptor.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "chromecast/base/task_runner_impl.h"
+#include "chromecast/media/cma/base/cma_logging.h"
+#include "chromecast/media/cma/pipeline/decrypt_util.h"
+
+namespace chromecast {
+namespace media {
+
+BackendDecryptor::BackendDecryptor(const EncryptionScheme& scheme)
+    : decrypt_success_(true),
+      wait_eos_(false),
+      task_runner_(new TaskRunnerImpl) {
+  DCHECK(MediaPipelineBackend::CreateAudioDecryptor);
+
+  task_runner_ = std::make_unique<TaskRunnerImpl>();
+  decryptor_ = base::WrapUnique(
+      MediaPipelineBackend::CreateAudioDecryptor(scheme, task_runner_.get()));
+
+  DCHECK(decryptor_);
+  decryptor_->SetDelegate(this);
+}
+
+BackendDecryptor::~BackendDecryptor() = default;
+
+void BackendDecryptor::Init(const DecryptCB& decrypt_cb) {
+  DCHECK(!decrypt_cb_);
+  decrypt_cb_ = decrypt_cb;
+}
+
+void BackendDecryptor::Decrypt(scoped_refptr<DecoderBufferBase> buffer) {
+  DCHECK(!wait_eos_);
+
+  // Push both clear and encrypted buffers to backend, so that |decryptor_|
+  // won't be blocked if there are not enough encrypted buffers. EOS buffer is
+  // also needed so that the last buffer can be flushed.
+  pending_buffers_.push(buffer);
+
+  if (buffer->end_of_stream())
+    wait_eos_ = true;
+
+  MediaPipelineBackend::BufferStatus status = decryptor_->PushBufferForDecrypt(
+      buffer.get(),
+      buffer->end_of_stream() ? nullptr : buffer->writable_data());
+
+  if (status != MediaPipelineBackend::kBufferPending)
+    OnPushBufferForDecryptComplete(status);
+}
+
+void BackendDecryptor::OnPushBufferForDecryptComplete(
+    MediaPipelineBackend::BufferStatus status) {
+  // If the pushed buffer is EOS, the callback should be called when all the
+  // buffers are decrypted.
+  if (wait_eos_)
+    return;
+
+  DCHECK(decrypt_cb_);
+  decrypt_cb_.Run(
+      decrypt_success_ && status == MediaPipelineBackend::kBufferSuccess,
+      std::move(ready_buffers_));
+}
+
+void BackendDecryptor::OnDecryptComplete(bool success) {
+  DCHECK(!pending_buffers_.empty());
+
+  // Cache the success value and return it in OnPushBufferForDecryptComplete.
+  decrypt_success_ &= success;
+
+  scoped_refptr<DecoderBufferBase> buffer = std::move(pending_buffers_.front());
+  pending_buffers_.pop();
+
+  ready_buffers_.push(buffer->end_of_stream() || !buffer->decrypt_config()
+                          ? buffer
+                          : base::MakeRefCounted<DecoderBufferClear>(buffer));
+
+  if (wait_eos_ && buffer->end_of_stream()) {
+    // Last frame, all the buffers should be decrypted.
+    DCHECK(pending_buffers_.empty());
+    DCHECK(decrypt_cb_);
+    CMALOG(kLogControl) << "Return all the ready buffers, size = "
+                        << ready_buffers_.size();
+    decrypt_cb_.Run(decrypt_success_, std::move(ready_buffers_));
+  }
+}
+
+}  // namespace media
+}  // namespace chromecast
diff --git a/chromecast/media/cma/pipeline/backend_decryptor.h b/chromecast/media/cma/pipeline/backend_decryptor.h
new file mode 100644
index 0000000..42b361ae
--- /dev/null
+++ b/chromecast/media/cma/pipeline/backend_decryptor.h
@@ -0,0 +1,60 @@
+// Copyright 2018 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 CHROMECAST_MEDIA_CMA_PIPELINE_BACKEND_DECRYPTOR_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_BACKEND_DECRYPTOR_H_
+
+#include <memory>
+#include <queue>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "chromecast/media/cma/base/decoder_buffer_base.h"
+#include "chromecast/media/cma/pipeline/stream_decryptor.h"
+#include "chromecast/public/media/media_pipeline_backend.h"
+
+namespace chromecast {
+class TaskRunnerImpl;
+
+namespace media {
+struct EncryptionScheme;
+
+class BackendDecryptor : public StreamDecryptor,
+                         MediaPipelineBackend::AudioDecryptor::Delegate {
+ public:
+  explicit BackendDecryptor(const EncryptionScheme& scheme);
+  ~BackendDecryptor() override;
+
+  // StreamDecryptor implementation:
+  void Init(const DecryptCB& decrypt_cb) override;
+  void Decrypt(scoped_refptr<DecoderBufferBase> buffer) override;
+
+ private:
+  // MediaPipelineBackend::AudioDecryptor::Delegate implementation:
+  void OnPushBufferForDecryptComplete(
+      MediaPipelineBackend::BufferStatus status) override;
+  void OnDecryptComplete(bool success) override;
+
+  // Pending buffers for decrypt.
+  BufferQueue pending_buffers_;
+
+  // Buffers that are ready to return to caller.
+  BufferQueue ready_buffers_;
+  bool decrypt_success_;
+  bool wait_eos_;
+
+  // |task_runner_| should have a longer life than |decryptor_|.
+  std::unique_ptr<TaskRunnerImpl> task_runner_;
+  std::unique_ptr<MediaPipelineBackend::AudioDecryptor> decryptor_;
+
+  DecryptCB decrypt_cb_;
+
+  DISALLOW_COPY_AND_ASSIGN(BackendDecryptor);
+};
+
+}  // namespace media
+}  // namespace chromecast
+
+#endif  // CHROMECAST_MEDIA_CMA_PIPELINE_BACKEND_DECRYPTOR_H_
diff --git a/chromecast/media/cma/pipeline/cdm_decryptor.cc b/chromecast/media/cma/pipeline/cdm_decryptor.cc
new file mode 100644
index 0000000..1a26323
--- /dev/null
+++ b/chromecast/media/cma/pipeline/cdm_decryptor.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 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 "chromecast/media/cma/pipeline/cdm_decryptor.h"
+
+#include "base/bind.h"
+#include "chromecast/media/base/decrypt_context_impl.h"
+#include "chromecast/media/cma/base/decoder_buffer_base.h"
+#include "chromecast/media/cma/pipeline/decrypt_util.h"
+
+namespace chromecast {
+namespace media {
+
+CdmDecryptor::CdmDecryptor() : weak_factory_(this) {
+  weak_this_ = weak_factory_.GetWeakPtr();
+}
+
+CdmDecryptor::~CdmDecryptor() = default;
+
+void CdmDecryptor::Init(const DecryptCB& decrypt_cb) {
+  DCHECK(!decrypt_cb_);
+  decrypt_cb_ = decrypt_cb;
+}
+
+void CdmDecryptor::Decrypt(scoped_refptr<DecoderBufferBase> buffer) {
+  if (buffer->end_of_stream() || !buffer->decrypt_config()) {
+    OnResult(std::move(buffer), true);
+    return;
+  }
+
+  DecryptContextImpl* decrypt_context =
+      static_cast<DecryptContextImpl*>(buffer->decrypt_context());
+  DCHECK(decrypt_context);
+
+  if (decrypt_context->CanDecryptToBuffer()) {
+    DecryptDecoderBuffer(std::move(buffer), decrypt_context,
+                         base::BindOnce(&CdmDecryptor::OnResult, weak_this_));
+    return;
+  }
+
+  // Media pipeline backend will handle decryption.
+  OnResult(std::move(buffer), true);
+}
+
+void CdmDecryptor::OnResult(scoped_refptr<DecoderBufferBase> buffer,
+                            bool success) {
+  BufferQueue ready_buffers;
+  ready_buffers.push(buffer);
+
+  DCHECK(decrypt_cb_);
+  decrypt_cb_.Run(success, std::move(ready_buffers));
+}
+
+}  // namespace media
+}  // namespace chromecast
diff --git a/chromecast/media/cma/pipeline/cdm_decryptor.h b/chromecast/media/cma/pipeline/cdm_decryptor.h
new file mode 100644
index 0000000..0de4c3d7
--- /dev/null
+++ b/chromecast/media/cma/pipeline/cdm_decryptor.h
@@ -0,0 +1,37 @@
+// Copyright 2018 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 CHROMECAST_MEDIA_CMA_PIPELINE_CDM_DECRYPTOR_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_CDM_DECRYPTOR_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chromecast/media/cma/pipeline/stream_decryptor.h"
+
+namespace chromecast {
+namespace media {
+
+// StreamDecryptor implemented with CDM decrypt APIs.
+class CdmDecryptor : public StreamDecryptor {
+ public:
+  CdmDecryptor();
+  ~CdmDecryptor() override;
+
+  // StreamDecryptor implementation:
+  void Init(const DecryptCB& decrypt_cb) override;
+  void Decrypt(scoped_refptr<DecoderBufferBase> buffer) override;
+
+ private:
+  void OnResult(scoped_refptr<DecoderBufferBase> buffer, bool success);
+
+  DecryptCB decrypt_cb_;
+
+  base::WeakPtr<CdmDecryptor> weak_this_;
+  base::WeakPtrFactory<CdmDecryptor> weak_factory_;
+  DISALLOW_COPY_AND_ASSIGN(CdmDecryptor);
+};
+
+}  // namespace media
+}  // namespace chromecast
+
+#endif  // CHROMECAST_MEDIA_CMA_PIPELINE_CDM_DECRYPTOR_H_
diff --git a/chromecast/media/cma/pipeline/decrypt_util.cc b/chromecast/media/cma/pipeline/decrypt_util.cc
index f05af67a..c72ed59 100644
--- a/chromecast/media/cma/pipeline/decrypt_util.cc
+++ b/chromecast/media/cma/pipeline/decrypt_util.cc
@@ -13,37 +13,20 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "chromecast/media/base/decrypt_context_impl.h"
-#include "chromecast/media/cma/base/decoder_buffer_base.h"
 #include "chromecast/public/media/cast_decrypt_config.h"
 #include "media/base/decoder_buffer.h"
 
 namespace chromecast {
 namespace media {
-
 namespace {
-
-class DecoderBufferClear : public DecoderBufferBase {
- public:
-  explicit DecoderBufferClear(scoped_refptr<DecoderBufferBase> buffer);
-
-  // DecoderBufferBase implementation.
-  StreamId stream_id() const override;
-  int64_t timestamp() const override;
-  void set_timestamp(base::TimeDelta timestamp) override;
-  const uint8_t* data() const override;
-  uint8_t* writable_data() const override;
-  size_t data_size() const override;
-  const CastDecryptConfig* decrypt_config() const override;
-  bool end_of_stream() const override;
-  scoped_refptr<::media::DecoderBuffer> ToMediaBuffer() const override;
-
- private:
-  ~DecoderBufferClear() override;
-
-  scoped_refptr<DecoderBufferBase> const buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(DecoderBufferClear);
-};
+void OnBufferDecrypted(scoped_refptr<DecoderBufferBase> buffer,
+                       BufferDecryptedCB buffer_decrypted_cb,
+                       bool success) {
+  scoped_refptr<DecoderBufferBase> out_buffer =
+      success ? base::MakeRefCounted<DecoderBufferClear>(buffer) : buffer;
+  std::move(buffer_decrypted_cb).Run(std::move(out_buffer), success);
+}
+}  // namespace
 
 DecoderBufferClear::DecoderBufferClear(scoped_refptr<DecoderBufferBase> buffer)
     : buffer_(buffer) {}
@@ -89,21 +72,12 @@
   return buffer_->ToMediaBuffer();
 }
 
-void OnBufferDecrypted(scoped_refptr<DecoderBufferBase> buffer,
-                       const BufferDecryptedCB& buffer_decrypted_cb,
-                       bool success) {
-  scoped_refptr<DecoderBufferBase> out_buffer =
-      success ? new DecoderBufferClear(buffer) : buffer;
-  buffer_decrypted_cb.Run(out_buffer, success);
-}
-}  // namespace
-
 void DecryptDecoderBuffer(scoped_refptr<DecoderBufferBase> buffer,
                           DecryptContextImpl* decrypt_ctxt,
-                          const BufferDecryptedCB& buffer_decrypted_cb) {
-  decrypt_ctxt->DecryptAsync(
-      buffer.get(), buffer->writable_data(), 0,
-      base::BindOnce(&OnBufferDecrypted, buffer, buffer_decrypted_cb));
+                          BufferDecryptedCB buffer_decrypted_cb) {
+  decrypt_ctxt->DecryptAsync(buffer.get(), buffer->writable_data(), 0,
+                             base::BindOnce(&OnBufferDecrypted, buffer,
+                                            std::move(buffer_decrypted_cb)));
 }
 
 }  // namespace media
diff --git a/chromecast/media/cma/pipeline/decrypt_util.h b/chromecast/media/cma/pipeline/decrypt_util.h
index ed9bdb6..76659fd 100644
--- a/chromecast/media/cma/pipeline/decrypt_util.h
+++ b/chromecast/media/cma/pipeline/decrypt_util.h
@@ -7,15 +7,39 @@
 
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
+#include "chromecast/media/cma/base/decoder_buffer_base.h"
 
 namespace chromecast {
 namespace media {
 
-class DecoderBufferBase;
+class CastDecryptConfig;
 class DecryptContextImpl;
 
+class DecoderBufferClear : public DecoderBufferBase {
+ public:
+  explicit DecoderBufferClear(scoped_refptr<DecoderBufferBase> buffer);
+
+  // DecoderBufferBase implementation.
+  StreamId stream_id() const override;
+  int64_t timestamp() const override;
+  void set_timestamp(base::TimeDelta timestamp) override;
+  const uint8_t* data() const override;
+  uint8_t* writable_data() const override;
+  size_t data_size() const override;
+  const CastDecryptConfig* decrypt_config() const override;
+  bool end_of_stream() const override;
+  scoped_refptr<::media::DecoderBuffer> ToMediaBuffer() const override;
+
+ private:
+  ~DecoderBufferClear() override;
+
+  const scoped_refptr<DecoderBufferBase> buffer_;
+
+  DISALLOW_COPY_AND_ASSIGN(DecoderBufferClear);
+};
+
 using BufferDecryptedCB =
-    base::Callback<void(scoped_refptr<DecoderBufferBase>, bool)>;
+    base::OnceCallback<void(scoped_refptr<DecoderBufferBase>, bool)>;
 
 // Create a new buffer which corresponds to the clear version of |buffer|.
 // Note: the memory area corresponding to the ES data of the new buffer
@@ -25,7 +49,7 @@
 // clear.
 void DecryptDecoderBuffer(scoped_refptr<DecoderBufferBase> buffer,
                           DecryptContextImpl* decrypt_ctxt,
-                          const BufferDecryptedCB& buffer_decrypted_cb);
+                          BufferDecryptedCB buffer_decrypted_cb);
 
 }  // namespace media
 }  // namespace chromecast
diff --git a/chromecast/media/cma/pipeline/stream_decryptor.h b/chromecast/media/cma/pipeline/stream_decryptor.h
new file mode 100644
index 0000000..8cb175d
--- /dev/null
+++ b/chromecast/media/cma/pipeline/stream_decryptor.h
@@ -0,0 +1,49 @@
+// Copyright 2018 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 CHROMECAST_MEDIA_CMA_PIPELINE_STREAM_DECRYPTOR_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_STREAM_DECRYPTOR_H_
+
+#include <queue>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+
+namespace chromecast {
+namespace media {
+class DecoderBufferBase;
+
+// Decryptor to get clear buffers in asynchronous way. All the buffers are
+// pushed into decryptor to keep the order of frames.
+class StreamDecryptor {
+ public:
+  using BufferQueue = std::queue<scoped_refptr<DecoderBufferBase>>;
+
+  // Callback for Decrypt. The first argument is true iff Decrypt was
+  // successful. The second argument contains all the buffers that are ready to
+  // be pushed to decoder by the time the callback is called.
+  // If BufferQueue is empty, it means decryptor can't return ready buffer right
+  // now but it can accept more data. The buffer will be returned together with
+  // other buffers in a later call to Decrypt. Some of the implementations
+  // expect more data to keep themselves running.
+  // Once Decrypt is called with EOS buffer, implementation should decrypt all
+  // the buffers and return them in one callback. In other words, the total
+  // number of output buffers should be the same as number of input buffers.
+  // Caller won't call Decrypt again once EOS is pushed.
+  using DecryptCB = base::RepeatingCallback<void(bool, BufferQueue)>;
+
+  virtual ~StreamDecryptor() = default;
+
+  virtual void Init(const DecryptCB& decrypt_cb) = 0;
+
+  // Decrypts |buffer| and returns the clear buffers in DecryptCB. Caller must
+  // not call Decrypt again until |decrypt_cb| is called. |decrypt_cb| will be
+  // called once for each call to Decrypt.
+  virtual void Decrypt(scoped_refptr<DecoderBufferBase> buffer) = 0;
+};
+
+}  // namespace media
+}  // namespace chromecast
+
+#endif  // CHROMECAST_MEDIA_CMA_PIPELINE_STREAM_DECRYPTOR_H_
diff --git a/chromecast/media/cma/pipeline/video_pipeline_impl.cc b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
index 518f7731..e3d51e0b 100644
--- a/chromecast/media/cma/pipeline/video_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
@@ -15,6 +15,7 @@
 #include "chromecast/media/cma/base/coded_frame_provider.h"
 #include "chromecast/media/cma/base/decoder_config_adapter.h"
 #include "chromecast/media/cma/pipeline/av_pipeline_impl.h"
+#include "chromecast/media/cma/pipeline/cdm_decryptor.h"
 #include "chromecast/public/graphics_types.h"
 #include "chromecast/public/media/decoder_config.h"
 #include "media/base/video_decoder_config.h"
@@ -126,6 +127,10 @@
   return encryption_schemes_[static_cast<int>(id)];
 }
 
+std::unique_ptr<StreamDecryptor> VideoPipelineImpl::CreateDecryptor() {
+  return std::make_unique<CdmDecryptor>();
+}
+
 void VideoPipelineImpl::UpdateStatistics() {
   if (client().statistics_cb.is_null())
     return;
diff --git a/chromecast/media/cma/pipeline/video_pipeline_impl.h b/chromecast/media/cma/pipeline/video_pipeline_impl.h
index 4ba130c..e2655479 100644
--- a/chromecast/media/cma/pipeline/video_pipeline_impl.h
+++ b/chromecast/media/cma/pipeline/video_pipeline_impl.h
@@ -45,6 +45,7 @@
                       const ::media::AudioDecoderConfig& audio_config,
                       const ::media::VideoDecoderConfig& video_config) override;
   const EncryptionScheme& GetEncryptionScheme(StreamId id) const override;
+  std::unique_ptr<StreamDecryptor> CreateDecryptor() override;
 
   MediaPipelineBackend::VideoDecoder* const video_decoder_;
   const VideoPipelineClient::NaturalSizeChangedCB natural_size_changed_cb_;
diff --git a/chromecast/public/media/media_pipeline_backend.h b/chromecast/public/media/media_pipeline_backend.h
index 3ca386f..f8d25811 100644
--- a/chromecast/public/media/media_pipeline_backend.h
+++ b/chromecast/public/media/media_pipeline_backend.h
@@ -9,9 +9,11 @@
 #include <string>
 
 #include "cast_key_status.h"
+#include "chromecast_export.h"
 #include "decoder_config.h"
 
 namespace chromecast {
+class TaskRunner;
 struct Size;
 
 namespace media {
@@ -183,6 +185,57 @@
     ~VideoDecoder() override {}
   };
 
+  // This is created/deleted on media thread. All the methods and delegate
+  // methods should be called on media thread.
+  class AudioDecryptor {
+   public:
+    using BufferStatus = MediaPipelineBackend::BufferStatus;
+
+    // Delegate methods must be called on media thread.
+    class Delegate {
+     public:
+      // Called to indicate decryptor can accept more buffers, after
+      // PushBufferForDecrypt returns |kBufferPending|.
+      virtual void OnPushBufferForDecryptComplete(BufferStatus status) = 0;
+
+      // Must be called for each pushed buffer (both clear and encrypted).
+      // Returns false if decryption fails, e.g. license policy violation.
+      virtual void OnDecryptComplete(bool success) = 0;
+
+     protected:
+      virtual ~Delegate() = default;
+    };
+
+    // Aborts all the pending operations once the object is deleted.
+    virtual ~AudioDecryptor() = default;
+
+    // Provides delegate for this decryptor. Called once before any other APIs.
+    virtual void SetDelegate(Delegate* delegate) = 0;
+
+    // Pushes a buffer of data for decrypting. Decrypted data will be put in
+    // |output|. Implementation MUST check the license policy before returning
+    // the clear buffer back.
+    //
+    // Similar to Decoder::PushBuffer, implementation can return
+    // |kBufferPending| to stop caller from pushing more buffers. See comments
+    // of Decoder::PushBuffer for more details on buffer pushing.
+    //
+    // Implementation must invoke Delegate::OnDecryptComplete once data is
+    // decrypted. Both encrypted and clear buffers will be pushed.
+    // Implementation should call the delegate methods in the same sequence as
+    // pushing buffer.
+    //
+    // Once EOS buffer is pushed, implementation should decrypt and return all
+    // the buffers.
+    //
+    // |buffer| and |output| are owned by caller. Caller must not destroy them
+    // until Delegate::OnDecryptComplete is called. |output| must be long
+    // enough to hold clear data. |output| may overlap with the memory carried
+    // by |buffer|. The size of decrypted data should be same as encrypted data.
+    virtual BufferStatus PushBufferForDecrypt(CastDecoderBuffer* buffer,
+                                              uint8_t* output) = 0;
+  };
+
   virtual ~MediaPipelineBackend() {}
 
   // Creates a new AudioDecoder attached to this pipeline.  MediaPipelineBackend
@@ -231,6 +284,17 @@
   // of 1.0 is assumed. Returns true if successful. Only called when in
   // the "playing" or "paused" states.
   virtual bool SetPlaybackRate(float rate) = 0;
+
+  // Creates a new AudioDecryptor for extracting clear audio buffers.  Caller
+  // owns the object. This will be called multiple times on media thread. When
+  // the object is deleted, the implementation should abort all the pending
+  // operations.
+  // This function is optional. The correct implementation must return a valid
+  // object. Platforms which support standard CDM decryption APIs do not need to
+  // implement this function.
+  CHROMECAST_EXPORT static AudioDecryptor* CreateAudioDecryptor(
+      const EncryptionScheme& scheme,
+      TaskRunner* task_runner) __attribute__((weak));
 };
 
 }  // namespace media
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 051923c8..e8efe0f 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -227,9 +227,6 @@
 // Disables material design Error screen.
 const char kDisableMdErrorScreen[] = "disable-md-error-screen";
 
-// Disables material design OOBE UI.
-const char kDisableMdOobe[] = "disable-md-oobe";
-
 // Disables mtp write support.
 const char kDisableMtpWriteSupport[] = "disable-mtp-write-support";
 
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index 4fccf580b..4485683 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -69,7 +69,6 @@
 CHROMEOS_EXPORT extern const char kDisableLoginAnimations[];
 CHROMEOS_EXPORT extern const char kDisableMachineCertRequest[];
 CHROMEOS_EXPORT extern const char kDisableMdErrorScreen[];
-CHROMEOS_EXPORT extern const char kDisableMdOobe[];
 CHROMEOS_EXPORT extern const char kDisableMtpWriteSupport[];
 CHROMEOS_EXPORT extern const char kDisableMultiDisplayLayout[];
 CHROMEOS_EXPORT extern const char kDisableNetworkPortalNotification[];
diff --git a/components/OWNERS b/components/OWNERS
index 39cf709..7a8738d 100644
--- a/components/OWNERS
+++ b/components/OWNERS
@@ -23,6 +23,7 @@
 per-file pdf_strings.grdp=raymes@chromium.org
 per-file physical_web_ui_strings.grdp=file://components/physical_web/OWNERS
 per-file policy_strings.grdp=file://components/policy/OWNERS
+per-file printing_strings.grdp=file://components/printing/OWNERS
 per-file security_interstitials_strings.grdp=file://components/security_interstitials/OWNERS
 per-file security_state_strings.grdp=file://components/security_state/OWNERS
 per-file ssl_errors_strings.grdp=file://components/ssl_errors/OWNERS
diff --git a/components/components_strings.grd b/components/components_strings.grd
index 370afcd..de57007 100644
--- a/components/components_strings.grd
+++ b/components/components_strings.grd
@@ -205,6 +205,7 @@
       <part file="pdf_strings.grdp" />
       <part file="physical_web_ui_strings.grdp" />
       <part file="policy_strings.grdp" />
+      <part file="printing_strings.grdp" />
       <part file="safe_browsing_strings.grdp" />
       <part file="security_interstitials_strings.grdp" />
       <part file="security_state_strings.grdp" />
diff --git a/components/omnibox/browser/vector_icons/vector_icons.cc.template b/components/omnibox/browser/vector_icons/vector_icons.cc.template
index d7b6f83..90e7d14d 100644
--- a/components/omnibox/browser/vector_icons/vector_icons.cc.template
+++ b/components/omnibox/browser/vector_icons/vector_icons.cc.template
@@ -10,11 +10,7 @@
 #include "base/logging.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
 
 namespace omnibox {
 
diff --git a/components/printing_strings.grdp b/components/printing_strings.grdp
new file mode 100644
index 0000000..a6692263
--- /dev/null
+++ b/components/printing_strings.grdp
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>

+<grit-part>

+  <if expr="enable_print_preview">

+    <if expr="is_win">

+      <message name="IDS_PRINT_PREVIEW_FRIENDLY_WIN_NETWORK_PRINTER_NAME" desc="Friendly name for a printer with a given name on a given server. This uses the same format as the Windows print dialog.">

+        <ph name="PRINTER_NAME">$1<ex>HP LaserJet</ex></ph> on <ph name="SERVER_NAME">$2<ex>printserver</ex></ph>

+      </message>

+    </if>

+  </if>

+</grit-part>

diff --git a/components/strings/BUILD.gn b/components/strings/BUILD.gn
index a299d38..1f0b61fc 100644
--- a/components/strings/BUILD.gn
+++ b/components/strings/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/locales.gni")
 import("//ppapi/features/features.gni")
+import("//printing/features/features.gni")
 import("//tools/grit/grit_rule.gni")
 
 if (is_android) {
@@ -67,7 +68,10 @@
 
 grit("components_strings") {
   source = "../components_strings.grd"
-  defines = [ "enable_plugins=$enable_plugins" ]
+  defines = [
+    "enable_plugins=$enable_plugins",
+    "enable_print_preview=$enable_print_preview",
+  ]
 
   outputs = [
     "grit/components_strings.h",
diff --git a/components/toolbar/vector_icons/vector_icons.cc.template b/components/toolbar/vector_icons/vector_icons.cc.template
index 6120c7c..dc4a46f0 100644
--- a/components/toolbar/vector_icons/vector_icons.cc.template
+++ b/components/toolbar/vector_icons/vector_icons.cc.template
@@ -10,11 +10,7 @@
 #include "base/logging.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
 
 namespace toolbar {
 
diff --git a/components/vector_icons/aggregate_vector_icons.py b/components/vector_icons/aggregate_vector_icons.py
index 87aa1be..c48a349 100644
--- a/components/vector_icons/aggregate_vector_icons.py
+++ b/components/vector_icons/aggregate_vector_icons.py
@@ -124,10 +124,13 @@
             CamelCase(icon_name, "Path1x"), vector_commands_1x))
 
       # Define the value of kFooBarIcon.
-      third_arg = "nullptr" if vector_commands_1x is None else CamelCase(
-                  icon_name, "Path1x")
-      output_cc.write("VECTOR_ICON_TEMPLATE({}, {}, {})\n".format(CamelCase(
-          icon_name, "Icon"), CamelCase(icon_name, "Path"), third_arg))
+      if vector_commands_1x is None:
+        output_cc.write("VECTOR_ICON_TEMPLATE({}, {})\n".format(CamelCase(
+            icon_name, "Icon"), CamelCase(icon_name, "Path")))
+      else:
+        output_cc.write("VECTOR_ICON_TEMPLATE2({}, {}, {})\n".format(CamelCase(
+            icon_name, "Icon"), CamelCase(icon_name, "Path"), CamelCase(
+                  icon_name, "Path1x")))
 
   output_cc.close()
 
diff --git a/components/vector_icons/cc_macros.h b/components/vector_icons/cc_macros.h
new file mode 100644
index 0000000..6ba0c245
--- /dev/null
+++ b/components/vector_icons/cc_macros.h
@@ -0,0 +1,36 @@
+// Copyright 2018 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 COMPONENTS_VECTOR_ICONS_CC_MACROS_H_
+#define COMPONENTS_VECTOR_ICONS_CC_MACROS_H_
+
+// This file holds macros that are common to each vector icon target's
+// vector_icons.cc.template file.
+
+// The prefix is used to help make sure the string IDs are unique. Typically,
+// matching the namespace of the icons should ensure that is the case. If the
+// vector_icons.cc.template file doesn't define a prefix, we'll go without one.
+#ifndef VECTOR_ICON_ID_PREFIX
+#define VECTOR_ICON_ID_PREFIX ""
+#endif
+
+#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
+  static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
+
+// The VectorIcon will be called kMyIcon, and the identifier for the icon might
+// be "my_namespace::kMyIconId".
+#define VECTOR_ICON_TEMPLATE(icon_name, path_name)                             \
+  const char icon_name##Id[] = VECTOR_ICON_ID_PREFIX #icon_name;               \
+  const gfx::VectorIcon icon_name = {path_name, arraysize(path_name), nullptr, \
+                                     0u, icon_name##Id};
+
+#define VECTOR_ICON_TEMPLATE2(icon_name, path_name, path_name_1x)           \
+  const char icon_name##Id[] = VECTOR_ICON_ID_PREFIX #icon_name;            \
+  const gfx::VectorIcon icon_name = {path_name, arraysize(path_name),       \
+                                     path_name_1x, arraysize(path_name_1x), \
+                                     icon_name##Id};
+
+#else  // !COMPONENTS_VECTOR_ICONS_CC_MACROS_H_
+#error This file should only be included once.
+#endif  // COMPONENTS_VECTOR_ICONS_CC_MACROS_H_
diff --git a/components/vector_icons/vector_icons.cc.template b/components/vector_icons/vector_icons.cc.template
index 4a965b1c..7cb1012 100644
--- a/components/vector_icons/vector_icons.cc.template
+++ b/components/vector_icons/vector_icons.cc.template
@@ -10,11 +10,7 @@
 #include "base/logging.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
 
 namespace vector_icons {
 
diff --git a/components/vector_icons/vector_icons.gni b/components/vector_icons/vector_icons.gni
index e1a3648..b8ba375 100644
--- a/components/vector_icons/vector_icons.gni
+++ b/components/vector_icons/vector_icons.gni
@@ -40,7 +40,9 @@
       "vector_icons.cc.template",
       "vector_icons.h.template",
     ]
-    inputs = rebase_path(templates + invoker.icons, ".", invoker.icon_directory)
+    inputs =
+        rebase_path(templates + invoker.icons, ".", invoker.icon_directory) +
+        [ "//components/vector_icons/aggregate_vector_icons.py" ]
 
     outputs = [
       output_cc,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index b3586cab..dd72608d 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1027,6 +1027,8 @@
     "loader/signed_exchange_consts.h",
     "loader/signed_exchange_handler.cc",
     "loader/signed_exchange_handler.h",
+    "loader/signed_exchange_header.cc",
+    "loader/signed_exchange_header.h",
     "loader/signed_exchange_header_parser.cc",
     "loader/signed_exchange_header_parser.h",
     "loader/signed_exchange_signature_verifier.cc",
diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc
index c394b83..9c55045 100644
--- a/content/browser/devtools/devtools_http_handler.cc
+++ b/content/browser/devtools/devtools_http_handler.cc
@@ -15,6 +15,7 @@
 #include "base/json/json_writer.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
@@ -77,8 +78,6 @@
 const int32_t kSendBufferSizeForDevTools = 256 * 1024 * 1024;  // 256Mb
 const int32_t kReceiveBufferSizeForDevTools = 100 * 1024 * 1024;  // 100Mb
 
-const char kFrontEndURL[] =
-    "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/inspector.html";
 }  // namespace
 
 // ServerWrapper -------------------------------------------------------------
@@ -455,15 +454,22 @@
 }
 
 std::string DevToolsHttpHandler::GetFrontendURLInternal(
+    scoped_refptr<DevToolsAgentHost> agent_host,
     const std::string& id,
     const std::string& host) {
-  return base::StringPrintf(
-      "%s%sws=%s%s%s",
-      frontend_url_.c_str(),
-      frontend_url_.find("?") == std::string::npos ? "?" : "&",
-      host.c_str(),
-      kPageUrlPrefix,
-      id.c_str());
+  std::string frontend_url;
+  if (delegate_->HasBundledFrontendResources()) {
+    frontend_url = "/devtools/inspector.html";
+  } else {
+    std::string type = agent_host->GetType();
+    bool is_worker = type == DevToolsAgentHost::kTypeServiceWorker ||
+                     type == DevToolsAgentHost::kTypeSharedWorker;
+    frontend_url = base::StringPrintf(
+        "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/%s.html",
+        GetWebKitRevision().c_str(), is_worker ? "worker_app" : "inspector");
+  }
+  return base::StringPrintf("%s?ws=%s%s%s", frontend_url.c_str(), host.c_str(),
+                            kPageUrlPrefix, id.c_str());
 }
 
 static bool ParseJsonPath(
@@ -750,11 +756,6 @@
                        output_directory, debug_frontend_dir, browser_guid_,
                        delegate_->HasBundledFrontendResources()));
   }
-  if (delegate_->HasBundledFrontendResources())
-    frontend_url_ = "/devtools/inspector.html";
-  else
-    frontend_url_ =
-        base::StringPrintf(kFrontEndURL, GetWebKitRevision().c_str());
 }
 
 void DevToolsHttpHandler::ServerStarted(
@@ -858,7 +859,8 @@
   dictionary->SetString(kTargetWebSocketDebuggerUrlField,
                         base::StringPrintf("ws://%s%s%s", host.c_str(),
                                            kPageUrlPrefix, id.c_str()));
-  std::string devtools_frontend_url = GetFrontendURLInternal(id, host);
+  std::string devtools_frontend_url =
+      GetFrontendURLInternal(agent_host, id, host);
   dictionary->SetString(kTargetDevtoolsFrontendUrlField, devtools_frontend_url);
 
   return dictionary;
diff --git a/content/browser/devtools/devtools_http_handler.h b/content/browser/devtools/devtools_http_handler.h
index f41e5c18..68260a28 100644
--- a/content/browser/devtools/devtools_http_handler.h
+++ b/content/browser/devtools/devtools_http_handler.h
@@ -96,8 +96,10 @@
   void DecompressAndSendJsonProtocol(int connection_id);
 
   // Returns the front end url without the host at the beginning.
-  std::string GetFrontendURLInternal(const std::string& target_id,
-                                     const std::string& host);
+  std::string GetFrontendURLInternal(
+      scoped_refptr<DevToolsAgentHost> agent_host,
+      const std::string& target_id,
+      const std::string& host);
 
   std::unique_ptr<base::DictionaryValue> SerializeDescriptor(
       scoped_refptr<DevToolsAgentHost> agent_host,
@@ -105,7 +107,6 @@
 
   // The thread used by the devtools handler to run server socket.
   std::unique_ptr<base::Thread> thread_;
-  std::string frontend_url_;
   std::string browser_guid_;
   std::unique_ptr<ServerWrapper> server_wrapper_;
   std::unique_ptr<net::IPEndPoint> server_ip_address_;
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index 59889c6..465ea2d 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -1782,26 +1782,28 @@
   TestDownloadHttpResponse::Parameters parameters;
 
   // As a control, let's try GetHash() on an uninterrupted download.
-  GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
-  GURL server_url = embedded_test_server()->GetURL(url.host(), url.path());
-  TestDownloadHttpResponse::StartServing(parameters, server_url);
+  GURL url1 = TestDownloadHttpResponse::GetNextURLForDownload();
+  GURL server_url1 = embedded_test_server()->GetURL(url1.host(), url1.path());
+  TestDownloadHttpResponse::StartServing(parameters, server_url1);
   DownloadItem* uninterrupted_download(
-      StartDownloadAndReturnItem(shell(), server_url));
+      StartDownloadAndReturnItem(shell(), server_url1));
   WaitForCompletion(uninterrupted_download);
   EXPECT_EQ(expected_hash, uninterrupted_download->GetHash());
 
   SetupErrorInjectionDownloads();
   // Now with interruptions.
+  GURL url2 = TestDownloadHttpResponse::GetNextURLForDownload();
+  GURL server_url2 = embedded_test_server()->GetURL(url2.host(), url2.path());
   parameters.inject_error_cb = inject_error_callback();
   parameters.injected_errors.push(100);
   parameters.injected_errors.push(211);
   parameters.injected_errors.push(337);
   parameters.injected_errors.push(400);
   parameters.injected_errors.push(512);
-  TestDownloadHttpResponse::StartServing(parameters, server_url);
+  TestDownloadHttpResponse::StartServing(parameters, server_url2);
 
   // Start and watch for interrupt.
-  DownloadItem* download(StartDownloadAndReturnItem(shell(), server_url));
+  DownloadItem* download(StartDownloadAndReturnItem(shell(), server_url2));
   WaitForInterrupt(download);
 
   download->Resume();
diff --git a/content/browser/loader/signed_exchange_header.cc b/content/browser/loader/signed_exchange_header.cc
new file mode 100644
index 0000000..20d724b
--- /dev/null
+++ b/content/browser/loader/signed_exchange_header.cc
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/loader/signed_exchange_header.h"
+
+#include <utility>
+
+namespace content {
+
+SignedExchangeHeader::SignedExchangeHeader() = default;
+SignedExchangeHeader::~SignedExchangeHeader() = default;
+
+void SignedExchangeHeader::AddResponseHeader(base::StringPiece name,
+                                             base::StringPiece value) {
+  response_headers_.insert(std::make_pair(name, value));
+}
+
+}  // namespace content
diff --git a/content/browser/loader/signed_exchange_header.h b/content/browser/loader/signed_exchange_header.h
new file mode 100644
index 0000000..61eb248e
--- /dev/null
+++ b/content/browser/loader/signed_exchange_header.h
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_LOADER_SIGNED_EXCHANGE_HEADER_H_
+#define CONTENT_BROWSER_LOADER_SIGNED_EXCHANGE_HEADER_H_
+
+#include <map>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
+#include "net/http/http_status_code.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// SignedExchangeHeader contains all information captured in signed exchange
+// envelope but the payload.
+// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html
+class CONTENT_EXPORT SignedExchangeHeader {
+ public:
+  SignedExchangeHeader();
+  ~SignedExchangeHeader();
+
+  void AddResponseHeader(base::StringPiece name, base::StringPiece value);
+
+  const GURL& request_url() const { return request_url_; };
+  void set_request_url(GURL url) { request_url_ = std::move(url); }
+
+  const std::string& request_method() const { return request_method_; }
+  void set_request_method(base::StringPiece s) {
+    s.CopyToString(&request_method_);
+  }
+
+  net::HttpStatusCode response_code() const { return response_code_; }
+  void set_response_code(net::HttpStatusCode c) { response_code_ = c; }
+
+  const std::map<std::string, std::string>& response_headers() const {
+    return response_headers_;
+  }
+
+ private:
+  GURL request_url_;
+  std::string request_method_;
+
+  net::HttpStatusCode response_code_;
+  std::map<std::string, std::string> response_headers_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_LOADER_SIGNED_EXCHANGE_HEADER_H_
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index ca594cb6..ac2f655 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -1463,55 +1463,29 @@
   EXPECT_TRUE(delegate.get()->request_to_lock_mouse_called_);
 }
 
-namespace {
-class TestResourceDispatcherHostDelegate
-    : public ShellResourceDispatcherHostDelegate {
- public:
-  explicit TestResourceDispatcherHostDelegate(bool* saw_override)
-      : saw_override_(saw_override) {}
-
-  void RequestBeginning(
-      net::URLRequest* request,
-      ResourceContext* resource_context,
-      AppCacheService* appcache_service,
-      ResourceType resource_type,
-      std::vector<std::unique_ptr<ResourceThrottle>>* throttles) override {
-    CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    ShellResourceDispatcherHostDelegate::RequestBeginning(
-        request, resource_context, appcache_service, resource_type, throttles);
-
-    net::HttpRequestHeaders headers = request->extra_request_headers();
-    std::string user_agent;
-    CHECK(headers.GetHeader(net::HttpRequestHeaders::kUserAgent, &user_agent));
-    if (user_agent.find("foo") != std::string::npos)
-      *saw_override_ = true;
-  }
-
- private:
-  bool* saw_override_;
-};
-}  // namespace
-
 // Checks that user agent override string is only used when it's overridden.
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, UserAgentOverride) {
-  bool saw_override = false;
-  TestResourceDispatcherHostDelegate new_delegate(&saw_override);
-  ResourceDispatcherHostDelegate* old_delegate =
-      ResourceDispatcherHostImpl::Get()->delegate();
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      base::BindOnce(&ResourceDispatcherHost::SetDelegate,
-                     base::Unretained(ResourceDispatcherHostImpl::Get()),
-                     &new_delegate));
-
   ASSERT_TRUE(embedded_test_server()->Start());
-  const GURL kUrl(embedded_test_server()->GetURL("/simple_page.html"));
+  const std::string kHeaderPath =
+      std::string("/echoheader?") + net::HttpRequestHeaders::kUserAgent;
+  const GURL kUrl(embedded_test_server()->GetURL(kHeaderPath));
+  const std::string kUserAgentOverride = "foo";
+
   NavigateToURL(shell(), kUrl);
-  ASSERT_FALSE(saw_override);
+  std::string header_value;
+  EXPECT_TRUE(ExecuteScriptAndExtractString(
+      shell()->web_contents(),
+      "window.domAutomationController.send(document.body.textContent);",
+      &header_value));
+  EXPECT_NE(kUserAgentOverride, header_value);
 
   shell()->web_contents()->SetUserAgentOverride("foo");
   NavigateToURL(shell(), kUrl);
-  ASSERT_FALSE(saw_override);
+  EXPECT_TRUE(ExecuteScriptAndExtractString(
+      shell()->web_contents(),
+      "window.domAutomationController.send(document.body.textContent);",
+      &header_value));
+  EXPECT_NE(kUserAgentOverride, header_value);
 
   shell()
       ->web_contents()
@@ -1521,13 +1495,11 @@
   TestNavigationObserver tab_observer(shell()->web_contents(), 1);
   shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
   tab_observer.Wait();
-  ASSERT_TRUE(saw_override);
-
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      base::BindOnce(&ResourceDispatcherHost::SetDelegate,
-                     base::Unretained(ResourceDispatcherHostImpl::Get()),
-                     old_delegate));
+  EXPECT_TRUE(ExecuteScriptAndExtractString(
+      shell()->web_contents(),
+      "window.domAutomationController.send(document.body.textContent);",
+      &header_value));
+  EXPECT_EQ(kUserAgentOverride, header_value);
 }
 
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
diff --git a/content/public/test/url_loader_interceptor.h b/content/public/test/url_loader_interceptor.h
index 1da372a..19a9173 100644
--- a/content/public/test/url_loader_interceptor.h
+++ b/content/public/test/url_loader_interceptor.h
@@ -25,20 +25,27 @@
 //     -http(s)://mock.failed.request/foo URLs internally, copying the behavior
 //      of net::URLRequestFailedJob
 //
+// Prefer not to use this class. In order of easy of use & simplicity:
+//  -if you need to serve static data, use net::test::EmbeddedTestServer and
+//   serve data from the source tree (e.g. in content/test/data)
+//  -if you need to control the response data at runtime, then use
+//   net::test_server::EmbeddedTestServer::RegisterRequestHandler
+//  -if you need to delay when the server sends the response, use
+//   net::test_server::ControllableHttpResponse
+//  -otherwise, if you need full control over the net::Error and/or want to
+//   inspect and/or modify the C++ structs used by URLoader interface, then use
+//   this helper class
+//
 // Notes:
 //  -intercepting frame requests doesn't work yet for non network-service case
 //   (will work once http://crbug.com/747130 is fixed)
-//  -the callback is always called on the IO thread
+//  -the callback is always called on the UI or IO threads depending on the
+//   factory that was hooked
 //    -this is done to avoid changing message order
 //  -intercepting resource requests for subresources when the network service is
 //   enabled changes message order by definition (since they would normally go
 //   directly from renderer->network process, but now they're routed through the
 //   browser). This is why |intercept_subresources| is false by default.
-//  -of course this only works when MojoLoading is enabled, which is default
-//   for all shipping configs (TODO(jam): delete this comment when old path is
-//   deleted)
-//  -it doesn't yet intercept other request types, e.g. browser-initiated
-//   requests that aren't for frames
 class URLLoaderInterceptor {
  public:
   struct RequestParams {
diff --git a/extensions/browser/api/cast_channel/DEPS b/extensions/browser/api/cast_channel/DEPS
index 44ac277a..b7f785b 100644
--- a/extensions/browser/api/cast_channel/DEPS
+++ b/extensions/browser/api/cast_channel/DEPS
@@ -3,3 +3,9 @@
   "+components/cast_channel",
   "+third_party/zlib",
 ]
+
+specific_include_rules = {
+  "cast_channel_apitest\.cc": [
+    "+chrome/browser/media/router",
+  ],
+}
diff --git a/extensions/browser/api/cast_channel/cast_channel_apitest.cc b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
index 14c4243..7bae881b 100644
--- a/extensions/browser/api/cast_channel/cast_channel_apitest.cc
+++ b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
@@ -10,6 +10,8 @@
 #include "build/build_config.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
+#include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h"
+#include "chrome/browser/media/router/test/noop_dual_media_sink_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "components/cast_channel/cast_socket.h"
 #include "components/cast_channel/cast_socket_service.h"
@@ -90,6 +92,13 @@
         extensions::switches::kWhitelistedExtensionID, kTestExtensionId);
   }
 
+  void SetUp() override {
+    // Stub out DualMediaSinkService so it does not interfere with the test.
+    media_router::DualMediaSinkService::SetInstanceForTest(
+        new media_router::NoopDualMediaSinkService());
+    ExtensionApiTest::SetUp();
+  }
+
   void SetUpMockCastSocket() {
     extensions::CastChannelAPI* api = GetApi();
 
diff --git a/net/spdy/core/spdy_alt_svc_wire_format_test.cc b/net/spdy/core/spdy_alt_svc_wire_format_test.cc
index 3b39d15d..94e26ab9 100644
--- a/net/spdy/core/spdy_alt_svc_wire_format_test.cc
+++ b/net/spdy/core/spdy_alt_svc_wire_format_test.cc
@@ -158,8 +158,6 @@
   }
 }
 
-class SpdyAltSvcWireFormatTest : public ::testing::Test {};
-
 // Tests of public API.
 
 TEST(SpdyAltSvcWireFormatTest, DefaultValues) {
diff --git a/net/spdy/core/spdy_bitmasks.h b/net/spdy/core/spdy_bitmasks.h
index 1e9ddd1..a0c4b1b 100644
--- a/net/spdy/core/spdy_bitmasks.h
+++ b/net/spdy/core/spdy_bitmasks.h
@@ -10,18 +10,9 @@
 // StreamId mask from the SpdyHeader
 const unsigned int kStreamIdMask = 0x7fffffff;
 
-// Control flag mask from the SpdyHeader
-const unsigned int kControlFlagMask = 0x8000;
-
 // Mask the lower 24 bits.
 const unsigned int kLengthMask = 0xffffff;
 
-// Legal flags on data packets.
-const int kDataFlagsMask = 0x01;
-
-// Legal flags on control packets.
-const int kControlFlagsMask = 0x03;
-
 }  // namespace net
 
 #endif  // NET_SPDY_CORE_SPDY_BITMASKS_H_
diff --git a/net/spdy/core/spdy_deframer_visitor_test.cc b/net/spdy/core/spdy_deframer_visitor_test.cc
index e834325f..0fb0fa3d 100644
--- a/net/spdy/core/spdy_deframer_visitor_test.cc
+++ b/net/spdy/core/spdy_deframer_visitor_test.cc
@@ -58,20 +58,6 @@
             decoder_.spdy_framer_error() == Http2DecoderAdapter::SPDY_NO_ERROR);
   }
 
-  SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame) {
-    return encoder_.SerializeFrame(frame);
-  }
-
-  SpdyString SerializeFrames(
-      const std::vector<std::unique_ptr<SpdyFrameIR>>& frames) {
-    SpdyString result;
-    for (const auto& frame_ptr : frames) {
-      auto sf = SerializeFrame(*frame_ptr);
-      result.append(sf.data(), sf.size());
-    }
-    return result;
-  }
-
   //       bool
 
   SpdyFramer encoder_;
diff --git a/net/spdy/core/spdy_framer_test.cc b/net/spdy/core/spdy_framer_test.cc
index 9c0c35d..9e8bc32 100644
--- a/net/spdy/core/spdy_framer_test.cc
+++ b/net/spdy/core/spdy_framer_test.cc
@@ -62,139 +62,6 @@
                     size_t frame_len));
 };
 
-class SpdyFramerTestUtil {
- public:
-  // Decompress a single frame using the decompression context held by
-  // the SpdyFramer.  The implemention is meant for use only in tests
-  // and will CHECK fail if the input is anything other than a single,
-  // well-formed compressed frame.
-  //
-  // Returns a new decompressed SpdySerializedFrame.
-  template <class SpdyFrameType>
-  static SpdySerializedFrame DecompressFrame(Http2DecoderAdapter* deframer,
-                                             const SpdyFrameType& frame) {
-    DecompressionVisitor visitor;
-    deframer->set_visitor(&visitor);
-    CHECK_EQ(frame.size(), deframer->ProcessInput(frame.data(), frame.size()));
-    CHECK_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer->state());
-    deframer->set_visitor(nullptr);
-    SpdyFramer serializer(SpdyFramer::DISABLE_COMPRESSION);
-    return serializer.SerializeFrame(visitor.GetFrame());
-  }
-
-  class DecompressionVisitor : public SpdyFramerVisitorInterface {
-   public:
-    DecompressionVisitor() : finished_(false) {}
-
-    const SpdyFrameIR& GetFrame() const {
-      CHECK(finished_);
-      return *frame_;
-    }
-
-    SpdyHeadersHandlerInterface* OnHeaderFrameStart(
-        SpdyStreamId stream_id) override {
-      if (headers_handler_ == nullptr) {
-        headers_handler_ = SpdyMakeUnique<TestHeadersHandler>();
-      }
-      return headers_handler_.get();
-    }
-
-    void OnHeaderFrameEnd(SpdyStreamId stream_id) override {
-      CHECK(!finished_);
-      frame_->set_header_block(headers_handler_->decoded_block().Clone());
-      finished_ = true;
-      headers_handler_.reset();
-    }
-
-    void OnHeaders(SpdyStreamId stream_id,
-                   bool has_priority,
-                   int weight,
-                   SpdyStreamId parent_stream_id,
-                   bool exclusive,
-                   bool fin,
-                   bool end) override {
-      auto headers = SpdyMakeUnique<SpdyHeadersIR>(stream_id);
-      headers->set_has_priority(has_priority);
-      headers->set_weight(weight);
-      headers->set_parent_stream_id(parent_stream_id);
-      headers->set_exclusive(exclusive);
-      headers->set_fin(fin);
-      frame_ = std::move(headers);
-    }
-
-    void OnPushPromise(SpdyStreamId stream_id,
-                       SpdyStreamId promised_stream_id,
-                       bool end) override {
-      frame_ = SpdyMakeUnique<SpdyPushPromiseIR>(stream_id, promised_stream_id);
-    }
-
-    // TODO(birenroy): Add support for CONTINUATION.
-    void OnContinuation(SpdyStreamId stream_id, bool end) override {
-      LOG(FATAL);
-    }
-
-    // All other methods just LOG(FATAL).
-    void OnError(Http2DecoderAdapter::SpdyFramerError error) override {
-      LOG(FATAL);
-    }
-    void OnDataFrameHeader(SpdyStreamId stream_id,
-                           size_t length,
-                           bool fin) override {
-      LOG(FATAL) << "Unexpected data frame header";
-    }
-    void OnStreamFrameData(SpdyStreamId stream_id,
-                           const char* data,
-                           size_t len) override {
-      LOG(FATAL);
-    }
-
-    void OnStreamEnd(SpdyStreamId stream_id) override { LOG(FATAL); }
-
-    void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
-      LOG(FATAL);
-    }
-
-    void OnRstStream(SpdyStreamId stream_id,
-                     SpdyErrorCode error_code) override {
-      LOG(FATAL);
-    }
-    void OnSetting(SpdySettingsIds id, uint32_t value) override { LOG(FATAL); }
-    void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
-    void OnSettingsEnd() override { LOG(FATAL); }
-    void OnGoAway(SpdyStreamId last_accepted_stream_id,
-                  SpdyErrorCode error_code) override {
-      LOG(FATAL);
-    }
-
-    void OnWindowUpdate(SpdyStreamId stream_id,
-                        int delta_window_size) override {
-      LOG(FATAL);
-    }
-
-    void OnPriority(SpdyStreamId stream_id,
-                    SpdyStreamId parent_stream_id,
-                    int weight,
-                    bool exclusive) override {
-      // Do nothing.
-    }
-
-    bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) override {
-      LOG(FATAL);
-      return false;
-    }
-
-   private:
-    std::unique_ptr<TestHeadersHandler> headers_handler_;
-    std::unique_ptr<SpdyFrameWithHeaderBlockIR> frame_;
-    bool finished_;
-
-    DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
-  };
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
-};
-
 MATCHER_P(IsFrameUnionOf, frame_list, "") {
   size_t size_verified = 0;
   for (const auto& frame : *frame_list) {
@@ -712,24 +579,6 @@
   using SpdyUnknownIR::set_length;
 };
 
-// Retrieves serialized headers from a HEADERS frame.
-SpdyStringPiece GetSerializedHeaders(const SpdySerializedFrame& frame,
-                                     const SpdyFramer& framer) {
-  SpdyFrameReader reader(frame.data(), frame.size());
-  reader.Seek(3);  // Seek past the frame length.
-
-  uint8_t serialized_type;
-  reader.ReadUInt8(&serialized_type);
-
-  SpdyFrameType type = ParseFrameType(serialized_type);
-  DCHECK_EQ(SpdyFrameType::HEADERS, type);
-  uint8_t flags;
-  reader.ReadUInt8(&flags);
-
-  return SpdyStringPiece(frame.data() + kHeadersFrameMinimumSize,
-                         frame.size() - kHeadersFrameMinimumSize);
-}
-
 enum Output { USE, NOT_USE };
 
 class SpdyFramerTest : public ::testing::TestWithParam<Output> {
@@ -763,17 +612,6 @@
                                   expected, expected_len);
   }
 
-  void CompareFrames(const SpdyString& description,
-                     const SpdySerializedFrame& expected_frame,
-                     const SpdySerializedFrame& actual_frame) {
-    CompareCharArraysWithHexError(
-        description,
-        reinterpret_cast<const unsigned char*>(expected_frame.data()),
-        expected_frame.size(),
-        reinterpret_cast<const unsigned char*>(actual_frame.data()),
-        actual_frame.size());
-  }
-
   bool use_output_ = false;
   ArrayOutputBuffer output_;
   SpdyFramer framer_;
diff --git a/net/spdy/core/spdy_pinnable_buffer_piece.h b/net/spdy/core/spdy_pinnable_buffer_piece.h
index 5a692af..07e7fac 100644
--- a/net/spdy/core/spdy_pinnable_buffer_piece.h
+++ b/net/spdy/core/spdy_pinnable_buffer_piece.h
@@ -27,8 +27,6 @@
 
   const char* buffer() const { return buffer_; }
 
-  size_t length() const { return length_; }
-
   explicit operator SpdyStringPiece() const {
     return SpdyStringPiece(buffer_, length_);
   }
diff --git a/net/spdy/core/spdy_protocol.cc b/net/spdy/core/spdy_protocol.cc
index 78af0aee8..162d1a8 100644
--- a/net/spdy/core/spdy_protocol.cc
+++ b/net/spdy/core/spdy_protocol.cc
@@ -7,6 +7,7 @@
 #include <ostream>
 
 #include "net/spdy/core/spdy_bug_tracker.h"
+#include "net/spdy/platform/api/spdy_flags.h"
 
 namespace net {
 
@@ -135,7 +136,25 @@
   }
 
   *setting_id = static_cast<SpdySettingsIds>(wire_setting_id);
-  return true;
+  if (GetSpdyReloadableFlag(http2_check_settings_id_007)) {
+    // This switch ensures that the casted value is valid. The default case is
+    // explicitly omitted to have compile-time guarantees that new additions to
+    // |SpdySettingsIds| must also be handled here.
+    switch (*setting_id) {
+      case SETTINGS_HEADER_TABLE_SIZE:
+      case SETTINGS_ENABLE_PUSH:
+      case SETTINGS_MAX_CONCURRENT_STREAMS:
+      case SETTINGS_INITIAL_WINDOW_SIZE:
+      case SETTINGS_MAX_FRAME_SIZE:
+      case SETTINGS_MAX_HEADER_LIST_SIZE:
+      case SETTINGS_ENABLE_CONNECT_PROTOCOL:
+        // FALLTHROUGH_INTENDED
+        return true;
+    }
+    return false;
+  } else {
+    return true;
+  }
 }
 
 bool SettingsIdToString(SpdySettingsIds id, const char** settings_id_string) {
diff --git a/net/spdy/core/spdy_protocol_test.cc b/net/spdy/core/spdy_protocol_test.cc
index b2620d3d..32a924c 100644
--- a/net/spdy/core/spdy_protocol_test.cc
+++ b/net/spdy/core/spdy_protocol_test.cc
@@ -10,6 +10,7 @@
 
 #include "net/spdy/core/spdy_bitmasks.h"
 #include "net/spdy/core/spdy_test_utils.h"
+#include "net/spdy/platform/api/spdy_flags.h"
 #include "net/test/gtest_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -118,6 +119,12 @@
   EXPECT_EQ(SETTINGS_MAX_FRAME_SIZE, setting_id);
   EXPECT_TRUE(ParseSettingsId(6, &setting_id));
   EXPECT_EQ(SETTINGS_MAX_HEADER_LIST_SIZE, setting_id);
+  if (GetSpdyReloadableFlag(http2_check_settings_id_007)) {
+    EXPECT_FALSE(ParseSettingsId(7, &setting_id));
+  } else {
+    EXPECT_TRUE(ParseSettingsId(7, &setting_id));
+    EXPECT_EQ(0x07, setting_id);
+  }
   EXPECT_TRUE(ParseSettingsId(8, &setting_id));
   EXPECT_EQ(SETTINGS_ENABLE_CONNECT_PROTOCOL, setting_id);
   EXPECT_FALSE(ParseSettingsId(9, &setting_id));
diff --git a/net/spdy/platform/impl/spdy_flags_impl.cc b/net/spdy/platform/impl/spdy_flags_impl.cc
index 81afb56..f02a351 100644
--- a/net/spdy/platform/impl/spdy_flags_impl.cc
+++ b/net/spdy/platform/impl/spdy_flags_impl.cc
@@ -9,4 +9,7 @@
 // Deliver OnPaddingLength separately from OnPadding.
 bool h2_on_stream_pad_length = true;
 
+// Consider SETTINGS identifier 0x07 as invalid.
+bool http2_check_settings_id_007 = true;
+
 }  // namespace net
diff --git a/net/spdy/platform/impl/spdy_flags_impl.h b/net/spdy/platform/impl/spdy_flags_impl.h
index 36f7dee1..52c17e5a 100644
--- a/net/spdy/platform/impl/spdy_flags_impl.h
+++ b/net/spdy/platform/impl/spdy_flags_impl.h
@@ -10,6 +10,7 @@
 namespace net {
 
 NET_EXPORT_PRIVATE extern bool h2_on_stream_pad_length;
+NET_EXPORT_PRIVATE extern bool http2_check_settings_id_007;
 
 inline bool GetSpdyReloadableFlagImpl(bool flag) {
   return flag;
diff --git a/services/network/public/cpp/resource_response_info.h b/services/network/public/cpp/resource_response_info.h
index 0b5e6c6..a1ff767 100644
--- a/services/network/public/cpp/resource_response_info.h
+++ b/services/network/public/cpp/resource_response_info.h
@@ -113,9 +113,9 @@
   // True if the response was fetched by a ServiceWorker.
   bool was_fetched_via_service_worker;
 
-  // True when the request whoes mode is |CORS| or |CORS-with-forced-preflight|
+  // True when a request whose mode is |CORS| or |CORS-with-forced-preflight|
   // is sent to a ServiceWorker but FetchEvent.respondWith is not called. So the
-  // renderer have to resend the request with skip service worker flag
+  // renderer has to resend the request with skip service worker flag
   // considering the CORS preflight logic.
   bool was_fallback_required_by_service_worker;
 
@@ -123,7 +123,8 @@
   // ServiceWorkerResponseInfo::url_list_via_service_worker().
   std::vector<GURL> url_list_via_service_worker;
 
-  // The type of the response which was fetched by the ServiceWorker.
+  // The type of the response, if it was returned by a service worker. This is
+  // kDefault if the response was not returned by a service worker.
   mojom::FetchResponseType response_type_via_service_worker;
 
   // The time immediately before starting ServiceWorker. If the response is not
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index 21a9d2be7..c416520f 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -18,10 +18,6 @@
 -DeclarativeContentApiTest.UninstallWhileActivePageAction
 -DevToolsSanityTest.TestRawHeadersWithRedirectAndHSTS
 -DisabledSignInIsolationBrowserTest.SyntheticTrial
-# DnsProbeBrowserTests that are flaky.
--DnsProbeBrowserTest.CorrectionsLoadStopped
--DnsProbeBrowserTest.CorrectionsLoadStoppedSlowProbe
--DnsProbeBrowserTest.NoInternetProbeResultWithSlowBrokenCorrections
 -DomainReliabilityBrowserTest.Upload
 -EnabledSignInIsolationBrowserTest.SyntheticTrial
 -ExpectCTBrowserTest.TestDynamicExpectCTHeaderProcessing
@@ -151,11 +147,19 @@
 -ContentSettingsTest.RedirectCrossOrigin
 -ContentSettingsTest.RedirectLoopCookies
 
+# https://crbug.com/810329 DnsProbe browsertests that rely on delaying requests:
+-DnsProbeBrowserTest.NxdomainProbeResultWithWorkingSlowCorrections
+# Addendum to the above: These three were previously marked as flaky. After
+# resolving https://crbug.com/810329, they will need to be monitored to see
+# if flake is still an issue.
+-DnsProbeBrowserTest.CorrectionsLoadStoppedSlowProbe
+-DnsProbeBrowserTest.CorrectionsLoadStopped
+-DnsProbeBrowserTest.NoInternetProbeResultWithSlowBrokenCorrections
+
 # crbug.com/776589 Intercepting requests with net::URLRequestFilter.
 -ClientHintsBrowserTest.ClientHintsLifetimeNotAttachedCookiesBlocked
 -ContinueWhereILeftOffTest.CookiesClearedOnExit
 -DevToolsSanityTest.TestNetworkPushTime
--DnsProbeBrowserTest.NxdomainProbeResultWithWorkingSlowCorrections
 -DownloadExtensionTest.DownloadExtensionTest_Download_FileSystemURL
 -LoadImageBrowserTest.LoadImage
 -MimeHandlerViewTests/MimeHandlerViewTest.SingleRequest/0
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
index 332708c..1ad7299a 100644
--- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -48,7 +48,6 @@
 -DevToolsDownloadContentTest.SingleDownload
 -DevToolsProtocolTest.ControlNavigationsMainFrame
 -DevToolsProtocolTest.SubresourceWithCertificateError
--DownloadContentTest.Resume_Hash
 -GetUserMediaVideoCaptureBrowserTest.RecoverFromCrashInVideoCaptureProcess
 -IsolatedDevToolsProtocolTest.ControlNavigationsChildFrames
 -IsolateIcelandFrameTreeBrowserTest.ProcessSwitchForIsolatedBlob
@@ -77,7 +76,6 @@
 -RequestDataResourceDispatcherHostBrowserTest.SameOriginNested
 -SitePerProcessIgnoreCertErrorsBrowserTest.SubresourceWithCertificateErrors
 -WebContentsImplBrowserTest.DownloadImage_Deny_FileImage
--WebContentsImplBrowserTest.UserAgentOverride
 -WorkerTest.WorkerTlsClientAuthFetch
 -WorkerTest.WorkerTlsClientAuthImportScripts
 
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/disable-blink-features=RootLayerScrolling b/third_party/WebKit/LayoutTests/FlagExpectations/disable-blink-features=RootLayerScrolling
index 39f1d01..44670f8 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/disable-blink-features=RootLayerScrolling
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/disable-blink-features=RootLayerScrolling
@@ -2718,8 +2718,6 @@
 # Crashes on win
 crbug.com/722943 media/audio-repaint.html [ Skip ]
 
-crbug.com/708175 external/wpt/IndexedDB/interleaved-cursors.html [ Failure Pass ]
-
 crbug.com/715718 external/wpt/media-source/mediasource-activesourcebuffers.html [ Failure Pass ]
 crbug.com/715718 external/wpt/media-source/mediasource-remove.html [ Failure Pass ]
 crbug.com/715718 [ Win ] external/wpt/xhr/FormData-append.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 10cd5973..bd72969 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -1024,7 +1024,6 @@
 crbug.com/591099 editing/unsupported-content/table-type-after.html [ Failure ]
 crbug.com/591099 editing/unsupported-content/table-type-before.html [ Failure ]
 crbug.com/591099 external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11.html [ Pass ]
-crbug.com/591099 external/wpt/IndexedDB/interleaved-cursors.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/hkdf.https.worker.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/test_hkdf.https.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures.worker.html [ Timeout ]
@@ -2777,7 +2776,7 @@
 crbug.com/591099 fast/css/transition-color-unspecified.html [ Failure ]
 crbug.com/591099 fast/css/universal-hover-quirk.html [ Failure ]
 crbug.com/591099 fast/css/unknown-pseudo-element-matching.html [ Failure ]
-crbug.com/714962 fast/css/user-drag-none.html [ Crash ]
+crbug.com/714962 fast/css/user-drag-none.html [ Failure ]
 crbug.com/591099 fast/css/vertical-align-lengths.html [ Failure ]
 crbug.com/591099 fast/css/vertical-lr-bfc-auto-margins-beside-float.html [ Failure ]
 crbug.com/591099 fast/css/vertical-lr-table-bfc-auto-margins-beside-float.html [ Failure ]
@@ -3234,7 +3233,7 @@
 crbug.com/714962 fast/forms/label/hover-on-moving-mouse-checkbox-to-parent-label.html [ Failure ]
 crbug.com/591099 fast/forms/label/label-click.html [ Pass ]
 crbug.com/591099 fast/forms/label/label-selection-by-textSelection-and-click.html [ Failure ]
-crbug.com/591099 fast/forms/label/selection-disabled-label.html [ Crash ]
+crbug.com/591099 fast/forms/label/selection-disabled-label.html [ Failure ]
 crbug.com/591099 fast/forms/long-text-in-input.html [ Crash Failure ]
 crbug.com/591099 fast/forms/mailto/advanced-get.html [ Failure ]
 crbug.com/591099 fast/forms/mailto/advanced-put.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index e9010dc7..65e1946 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -1543,7 +1543,5 @@
 Bug(none) css3/blending/mix-blend-mode-simple.html [ Pass Timeout ]
 Bug(none) css3/blending/mix-blend-mode-simple-text.html [ Pass Timeout ]
 
-crbug.com/708175 virtual/mojo-blobs/external/wpt/IndexedDB/interleaved-cursors.html [ Timeout ]
-
 crbug.com/529963 paint/invalidation/background/background-attachment-fixed-scrolled.html [ Failure ]
-Bug(none) fast/multicol/hit-test-translate-z.html [ Failure ]
\ No newline at end of file
+Bug(none) fast/multicol/hit-test-translate-z.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/MSANExpectations b/third_party/WebKit/LayoutTests/MSANExpectations
index d2a85e95..18c31c3 100644
--- a/third_party/WebKit/LayoutTests/MSANExpectations
+++ b/third_party/WebKit/LayoutTests/MSANExpectations
@@ -22,8 +22,10 @@
 crbug.com/522315 [ Linux ] virtual/gpu/fast/canvas/quadraticCurveTo.xml [ Crash ]
 
 crbug.com/517704 [ Linux ] external/wpt/encoding/api-invalid-label.html [ Timeout Pass ]
-crbug.com/708175 [ Linux ] external/wpt/IndexedDB/interleaved-cursors.html [ Timeout ]
-crbug.com/708175 [ Linux ] virtual/mojo-blobs/external/wpt/IndexedDB/interleaved-cursors.html [ Timeout ]
+crbug.com/708175 [ Linux ] external/wpt/IndexedDB/interleaved-cursors-small.html [ Timeout ]
+crbug.com/708175 [ Linux ] external/wpt/IndexedDB/interleaved-cursors-large.html [ Timeout ]
+crbug.com/708175 [ Linux ] virtual/mojo-blobs/external/wpt/IndexedDB/interleaved-cursors-small.html [ Timeout ]
+crbug.com/708175 [ Linux ] virtual/mojo-blobs/external/wpt/IndexedDB/interleaved-cursors-large.html [ Timeout ]
 
 crbug.com/701433 [ Linux ] crypto/subtle/worker-subtle-crypto-concurrent.html [ Timeout Pass ]
 crbug.com/701563 [ Linux ] external/wpt/svg/interfaces.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 3d2b262..ddaf99d 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2605,8 +2605,6 @@
 # Crashes on win
 crbug.com/722943 media/audio-repaint.html [ Skip ]
 
-crbug.com/708175 external/wpt/IndexedDB/interleaved-cursors.html [ Failure Pass ]
-
 crbug.com/715718 external/wpt/media-source/mediasource-activesourcebuffers.html [ Failure Pass ]
 crbug.com/715718 external/wpt/media-source/mediasource-remove.html [ Failure Pass ]
 crbug.com/715718 [ Win ] external/wpt/xhr/FormData-append.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/selectorText-modification-restyle-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/selectorText-modification-restyle-002.html
new file mode 100644
index 0000000..a6b37c2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/selectorText-modification-restyle-002.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>CSSOM: Modify selectorText in a shadow tree stylesheet</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/cssom/#dom-cssstylerule-selectortext">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+  #container { color: red }
+  .subtree * { color: pink }
+</style>
+<div id="container">
+  <div id="host"></div>
+</div>
+<script>
+  const root = host.attachShadow({mode:"open"});
+  root.innerHTML = "<style>nomatch { color: green }</style><div>Green</div>";
+  const div = root.querySelector("div");
+
+  test(() => {
+    assert_equals(getComputedStyle(div).color, "rgb(255, 0, 0)", "Color should initial be red.");
+  }, "Check initial color.");
+
+  test(() => {
+    // The combination of the .subtree and CSSOM selector style invalidations
+    // caused the Blink implementation to fail an assertion.
+    container.className = "subtree";
+    root.styleSheets[0].cssRules[0].selectorText = "div";
+    assert_equals(getComputedStyle(div).color, "rgb(0, 128, 0)", "Color should be green after stylesheet change.");
+  }, "Check that color changes correctly after shadow stylesheet selector and #container class is changed.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/Document-createElement.html b/third_party/WebKit/LayoutTests/external/wpt/custom-elements/Document-createElement.html
index 97a5659..3b891300 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/Document-createElement.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/custom-elements/Document-createElement.html
@@ -36,12 +36,18 @@
     customElements.define('autonomous-custom-element', AutonomousCustomElement);
     customElements.define('is-custom-element', IsCustomElement);
 
-    var instance = document.createElement('autonomous-custom-element', { is: "is-custom-element"});
+    var instance = document.createElement('autonomous-custom-element', { is: 'is-custom-element'});
 
     assert_true(instance instanceof AutonomousCustomElement);
     assert_equals(instance.localName, 'autonomous-custom-element');
     assert_equals(instance.namespaceURI, 'http://www.w3.org/1999/xhtml', 'A custom element HTML must use HTML namespace');
 
+    var instance2 = document.createElement('undefined-element', { is: 'is-custom-element'});
+    assert_false(instance2.matches(':defined'));
+    class DefinedLater extends HTMLElement {}
+    customElements.define('undefined-element', DefinedLater);
+    document.body.appendChild(instance2);
+    assert_true(instance2 instanceof DefinedLater);
 }, 'document.createElement must create an instance of autonomous custom elements when it has is attribute');
 
 function assert_reports(expected, testFunction, message) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/media/foo-no-cors.vtt b/third_party/WebKit/LayoutTests/external/wpt/media/foo-no-cors.vtt
new file mode 100644
index 0000000..b533895c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/media/foo-no-cors.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+Foo
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/vtt-frame.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/vtt-frame.html
new file mode 100644
index 0000000..c3ac803
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/vtt-frame.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Page Title</title>
+<video>
+  <track>
+</video>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/webvtt-cross-origin.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/webvtt-cross-origin.https.html
new file mode 100644
index 0000000..0f980607b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/webvtt-cross-origin.https.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>cross-origin webvtt returned by service worker is detected</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/test-helpers.sub.js?pipe=sub"></script>
+<body>
+<script>
+// This file tests opaque responses for WebVTT text track. It creates
+// an iframe with a <track> element, controlled by a service worker.
+// Each test tries to load a text track, the service worker intercepts the
+// requests and responds with opaque or non-opaque responses. The opaque
+// responses should result in load errors.
+
+const host_info = get_host_info();
+const kScript = 'resources/fetch-rewrite-worker.js';
+// Add '?ignore' so the service worker falls back for the navigation.
+const kScope = 'resources/vtt-frame.html?ignore';
+let frame;
+
+function load_track(url) {
+  const track = frame.contentDocument.querySelector('track');
+  const result = new Promise((resolve, reject) => {
+      track.onload = (e => {
+          resolve('load event');
+        });
+      track.onerror = (e => {
+          resolve('error event');
+        });
+    });
+
+  track.src = url;
+  // Setting mode to hidden seems needed, or else the text track requests don't
+  // occur.
+  track.track.mode = 'hidden';
+  return result;
+}
+
+promise_test(t => {
+    return service_worker_unregister_and_register(t, kScript, kScope)
+      .then(registration => {
+          promise_test(() => {
+              frame.remove();
+              return registration.unregister();
+            }, 'restore global state');
+
+          return wait_for_state(t, registration.installing, 'activated');
+        })
+      .then(() => {
+          return with_iframe(kScope);
+        })
+      .then(f => {
+          frame = f;
+        })
+  }, 'initialize global state');
+
+promise_test(t => {
+    let url = '/media/foo.vtt';
+    // Add '?url' and tell the service worker to return a same-origin URL.
+    url += '?url=' + host_info.HTTPS_ORIGIN + '/media/foo.vtt';
+    return load_track(url)
+      .then(result => {
+          assert_equals(result, 'load event');
+        });
+  }, 'same-origin text track should load');
+
+promise_test(t => {
+    let url = '/media/foo.vtt';
+    // Add '?url' and tell the service worker to return a cross-origin URL.
+    url += '?url=' + get_host_info().HTTPS_REMOTE_ORIGIN + '/media/foo.vtt';
+    return load_track(url)
+      .then(result => {
+          assert_equals(result, 'error event');
+        });
+  }, 'cross-origin text track with no-cors request should not load');
+
+promise_test(t => {
+    let url = '/media/foo.vtt';
+    // Add '?url' and tell the service worker to return a cross-origin URL that
+    // doesn't support CORS.
+    url += '?url=' + get_host_info().HTTPS_REMOTE_ORIGIN +
+        '/media/foo-no-cors.vtt';
+    // Add '&mode' to tell the service worker to do a CORS request.
+    url += '&mode=cors';
+    return load_track(url)
+      .then(result => {
+          assert_equals(result, 'error event');
+        });
+  }, 'cross-origin text track with rejected cors request should not load');
+
+promise_test(t => {
+    let url = '/media/foo.vtt';
+    // Add '?url' and tell the service worker to return a cross-origin URL.
+    url += '?url=' + get_host_info().HTTPS_REMOTE_ORIGIN + '/media/foo.vtt';
+    // Add '&mode' to tell the service worker to do a CORS request.
+    url += '&mode=cors';
+    // Add '&credentials=anonymous' to allow Access-Control-Allow-Origin=*.
+    url += '&credentials=anonymous';
+    return load_track(url)
+      .then(result => {
+          assert_equals(result, 'load event');
+        });
+  }, 'cross-origin text track with approved cors request should load');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/text/firstline/capitalize-transform.html b/third_party/WebKit/LayoutTests/fast/text/firstline/capitalize-transform.html
new file mode 100644
index 0000000..f8cc688
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/text/firstline/capitalize-transform.html
@@ -0,0 +1,15 @@
+<!doctype HTML>
+<style>div::first-line {
+    text-transform: uppercase
+</style>
+:<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<!-- The capitalized form of the text below has only one character, whereas
+the lowercase has two. -->
+<div lang=el>ά</div>
+<div id=target></div>
+<script>
+test(function() {
+  target.innerText += "test";
+}, "Should not crash");
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 27023a1..402007b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1983,6 +1983,7 @@
     method samplerParameterf
     method samplerParameteri
     method scissor
+    method setCompatibleXRDevice
     method shaderSource
     method stencilFunc
     method stencilFuncSeparate
@@ -2449,6 +2450,7 @@
     method renderbufferStorage
     method sampleCoverage
     method scissor
+    method setCompatibleXRDevice
     method shaderSource
     method stencilFunc
     method stencilFuncSeparate
diff --git a/third_party/WebKit/LayoutTests/media/media-controls.js b/third_party/WebKit/LayoutTests/media/media-controls.js
index 89837b9..4fe7219f 100644
--- a/third_party/WebKit/LayoutTests/media/media-controls.js
+++ b/third_party/WebKit/LayoutTests/media/media-controls.js
@@ -331,7 +331,7 @@
 }
 
 function pictureInPictureInterstitial(videoElement) {
-  var controlID = '-internal-picture-in-picture-message';
+  var controlID = '-internal-picture-in-picture-icon';
 
   var interstitial = getElementByPseudoId(window.internals.shadowRoot(videoElement).firstChild, controlID);
   if (!interstitial)
@@ -340,7 +340,7 @@
 }
 
 function checkPictureInPictureInterstitialDoesNotExist(videoElement) {
-  var controlID = '-internal-picture-in-picture-message';
+  var controlID = '-internal-picture-in-picture-icon';
 
   var interstitial = getElementByPseudoId(internals.oldestShadowRoot(videoElement), controlID);
   if (interstitial)
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 979dbc2..c70f15e 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1893,6 +1893,7 @@
 [Worker]     method samplerParameterf
 [Worker]     method samplerParameteri
 [Worker]     method scissor
+[Worker]     method setCompatibleXRDevice
 [Worker]     method shaderSource
 [Worker]     method stencilFunc
 [Worker]     method stencilFuncSeparate
@@ -2359,6 +2360,7 @@
 [Worker]     method renderbufferStorage
 [Worker]     method sampleCoverage
 [Worker]     method scissor
+[Worker]     method setCompatibleXRDevice
 [Worker]     method shaderSource
 [Worker]     method stencilFunc
 [Worker]     method stencilFuncSeparate
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index a298fd8..d398f9f5 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -8152,6 +8152,7 @@
     method samplerParameterf
     method samplerParameteri
     method scissor
+    method setCompatibleXRDevice
     method shaderSource
     method stencilFunc
     method stencilFuncSeparate
@@ -8643,6 +8644,7 @@
     method renderbufferStorage
     method sampleCoverage
     method scissor
+    method setCompatibleXRDevice
     method shaderSource
     method stencilFunc
     method stencilFuncSeparate
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
index ebd838a..b8dcbf3 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1893,6 +1893,7 @@
 [Worker]     method samplerParameterf
 [Worker]     method samplerParameteri
 [Worker]     method scissor
+[Worker]     method setCompatibleXRDevice
 [Worker]     method shaderSource
 [Worker]     method stencilFunc
 [Worker]     method stencilFuncSeparate
@@ -2359,6 +2360,7 @@
 [Worker]     method renderbufferStorage
 [Worker]     method sampleCoverage
 [Worker]     method scissor
+[Worker]     method setCompatibleXRDevice
 [Worker]     method shaderSource
 [Worker]     method stencilFunc
 [Worker]     method stencilFuncSeparate
diff --git a/third_party/WebKit/LayoutTests/xr/resources/xr-test-utils.js b/third_party/WebKit/LayoutTests/xr/resources/xr-test-utils.js
index 2b41ad3..4a2546d 100644
--- a/third_party/WebKit/LayoutTests/xr/resources/xr-test-utils.js
+++ b/third_party/WebKit/LayoutTests/xr/resources/xr-test-utils.js
@@ -11,54 +11,71 @@
   addFakeDevice(device);
 
   promise_test((t) => {
-    return navigator.xr.requestDevice().then(
-        (device) => new Promise((resolve, reject) => {
-          // Run the test with each set of sessionOptions from the array one at a time.
-          function nextSessionTest(i) {
-            if (i == sessionOptions.length) {
-              resolve();
-            }
-            // Perform the session request in a user gesture.
-            runWithUserGesture(() => {
-              let nextOptions = sessionOptions[i];
-              let testSession = null;
-              device.requestSession(nextOptions)
-                  .then((session) => {
-                    testSession = session;
-                    return func(session, t);
-                  })
-                  .then(() => {
-                    // Wrap in a try in case the session was ended in the
-                    // test itself.
-                    try {
-                      // If there's another test to run after this one make sure
-                      // to end the session so that we don't accidentally try to
-                      // have, for example, two exclusive sessions at once.
-                      if (i < sessionOptions.length - 1) {
-                        testSession.end();
-                      }
-                    } finally {
-                      nextSessionTest(++i);
-                    }
-                  })
-                  .catch((err) => {
-                    let optionsString = '{';
-                    let firstOption = true;
-                    for (let option in nextOptions) {
-                      if (!firstOption) {
-                        optionsString += ',';
-                      }
-                      optionsString += ` ${option}: ${nextOptions[option]}`;
-                      firstOption = false;
-                    }
-                    optionsString += ' }';
-                    reject(`Test failed while running with the following options: ${optionsString} ${err}`);
-                  });
-            });
+    return navigator.xr.requestDevice()
+        .then((device) => {
+          if (gl) {
+            return gl.setCompatibleXRDevice(device).then(
+                () => Promise.resolve(device));
+          } else {
+            return Promise.resolve(device);
           }
+        })
+        .then(
+            (device) => new Promise((resolve, reject) => {
+              // Run the test with each set of sessionOptions from the array one
+              // at a time.
+              function nextSessionTest(i) {
+                if (i == sessionOptions.length) {
+                  if (sessionOptions.length == 0) {
+                    reject('No option for the session. Test Did not run.');
+                  } else {
+                    resolve();
+                  }
+                }
+                // Perform the session request in a user gesture.
+                runWithUserGesture(() => {
+                  let nextOptions = sessionOptions[i];
+                  let testSession = null;
+                  device.requestSession(nextOptions)
+                      .then((session) => {
+                        testSession = session;
+                        return func(session, t);
+                      })
+                      .then(() => {
+                        // Wrap in a try in case the session was ended in the
+                        // test itself.
+                        try {
+                          // If there's another test to run after this one make
+                          // sure to end the session so that we don't
+                          // accidentally try to have, for example, two
+                          // exclusive sessions at once.
+                          if (i < sessionOptions.length - 1) {
+                            testSession.end();
+                          }
+                        } finally {
+                          nextSessionTest(++i);
+                        }
+                      })
+                      .catch((err) => {
+                        let optionsString = '{';
+                        let firstOption = true;
+                        for (let option in nextOptions) {
+                          if (!firstOption) {
+                            optionsString += ',';
+                          }
+                          optionsString += ` ${option}: ${nextOptions[option]}`;
+                          firstOption = false;
+                        }
+                        optionsString += ' }';
+                        reject(
+                            `Test failed while running with the following options:
+                            ${optionsString} ${err}`);
+                      });
+                });
+              }
 
-          nextSessionTest(0);
-        }));
+              nextSessionTest(0);
+            }));
   }, name, properties);
 }
 
diff --git a/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_create_with_xr_device.html b/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_create_with_xr_device.html
new file mode 100644
index 0000000..7b6c75a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_create_with_xr_device.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
+<script src="../xr/resources/xr-device-mocking.js"></script>
+<script src="../xr/resources/xr-test-utils.js"></script>
+<script src="../xr/resources/test-constants.js"></script>
+<canvas id="webgl-canvas"></canvas>
+
+<script>
+let fakeDevices = fakeXRDevices();
+
+promise_test( (t) => {
+  setFakeDevices([fakeDevices["FakeGooglePixelPhone"]]);
+  return navigator.xr.requestDevice().then( (device) => {
+    webglCanvas = document.getElementById('webgl-canvas');
+    gl = webglCanvas.getContext('webgl', {compatibleXRDevice: device});
+    assert_equals(gl.getContextAttributes().compatibleXRDevice, device);
+
+    // Check that an offscreen context behaves no different.
+    let offscreenCanvas = document.createElement('canvas');
+    let offscreenGl = webglCanvas.getContext('webgl', {compatibleXRDevice: device});
+    assert_equals(offscreenGl.getContextAttributes().compatibleXRDevice, device);
+  });
+}, "A webglCanvasContext created with an XRDevice has that device set");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_set_device_lost_context.html b/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_set_device_lost_context.html
new file mode 100644
index 0000000..e435a2e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_set_device_lost_context.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
+<script src="../xr/resources/xr-device-mocking.js"></script>
+<script src="../xr/resources/xr-test-utils.js"></script>
+<script src="../xr/resources/test-constants.js"></script>
+<canvas id="webgl-canvas"></canvas>
+
+<script>
+let fakeDevices = fakeXRDevices();
+promise_test( (t) => {
+  setFakeDevices([fakeDevices["FakeGooglePixelPhone"]]);
+  return navigator.xr.requestDevice().then( (device) => {
+    webglCanvas = document.getElementById('webgl-canvas');
+    gl = webglCanvas.getContext('webgl', {compatibleXRDevice: device});
+    gl.getExtension('WEBGL_lose_context').loseContext();
+    return promise_rejects(t, 'InvalidStateError',
+        gl.setCompatibleXRDevice(device));
+  });
+}, "A lost webglCanvasContext should not be able to set device");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrWebGLLayer_incompatible_device.html b/third_party/WebKit/LayoutTests/xr/xrWebGLLayer_incompatible_device.html
new file mode 100644
index 0000000..f6e45bd8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/xr/xrWebGLLayer_incompatible_device.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
+<script src="../xr/resources/xr-device-mocking.js"></script>
+<script src="../xr/resources/xr-test-utils.js"></script>
+<script src="../xr/resources/test-constants.js"></script>
+<canvas id="webgl-canvas"></canvas>
+
+<script>
+let fakeDevices = fakeXRDevices();
+
+promise_test( (t) => {
+  setFakeDevices([fakeDevices["FakeGooglePixelPhone"]]);
+  webglCanvasSetup();
+  return navigator.xr.requestDevice().then( (device) => new Promise((resolve) => {
+    runWithUserGesture( () => {
+      resolve(device.requestSession({ exclusive: true })
+        .then( (session) => new Promise((resolve) => {
+          try {
+            let webglLayer = new XRWebGLLayer(session, gl);
+            reject("XRWebGLLayer should fail with invalid arguments");
+          } catch (err) {
+            assert_equals(err.name, "InvalidStateError");
+            resolve();
+          }
+      })));
+    });
+  }));
+}, "XRWebGLLayer throws error when the session device is not the set device");
+
+</script>
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni
index f829ba4..54869cae 100644
--- a/third_party/WebKit/Source/core/core_idl_files.gni
+++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -615,7 +615,6 @@
                     "geometry/DOMRectInit.idl",
                     "html/FocusOptions.idl",
                     "html/AssignedNodesOptions.idl",
-                    "html/canvas/CanvasContextCreationAttributes.idl",
                     "html/canvas/ImageDataColorSettings.idl",
                     "html/track/TrackEventInit.idl",
                     "imagebitmap/ImageBitmapOptions.idl",
diff --git a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp
index 75a4ef9..53e50810 100644
--- a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp
@@ -11,14 +11,16 @@
 namespace blink {
 
 const CSSValue* InlineStylePropertyMap::GetProperty(CSSPropertyID property_id) {
-  return owner_element_->EnsureMutableInlineStyle().GetPropertyCSSValue(
-      property_id);
+  const CSSPropertyValueSet* inline_style = owner_element_->InlineStyle();
+  return inline_style ? inline_style->GetPropertyCSSValue(property_id)
+                      : nullptr;
 }
 
 const CSSValue* InlineStylePropertyMap::GetCustomProperty(
     AtomicString property_name) {
-  return owner_element_->EnsureMutableInlineStyle().GetPropertyCSSValue(
-      property_name);
+  const CSSPropertyValueSet* inline_style = owner_element_->InlineStyle();
+  return inline_style ? inline_style->GetPropertyCSSValue(property_name)
+                      : nullptr;
 }
 
 void InlineStylePropertyMap::SetProperty(CSSPropertyID property_id,
diff --git a/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp b/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
index 723a6208..831db6d 100644
--- a/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
+++ b/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
@@ -348,8 +348,12 @@
       return false;
     RecursionCheckpoint checkpoint(&recursion_data);
     SiblingData sibling_data;
-    if (UNLIKELY(root->NeedsStyleInvalidation()))
-      PushInvalidationSetsForContainerNode(*root, recursion_data, sibling_data);
+    if (!recursion_data.WholeSubtreeInvalid()) {
+      if (UNLIKELY(root->NeedsStyleInvalidation())) {
+        PushInvalidationSetsForContainerNode(*root, recursion_data,
+                                             sibling_data);
+      }
+    }
     for (Element* child = ElementTraversal::FirstChild(*root); child;
          child = ElementTraversal::NextSibling(*child)) {
       bool child_recalced = Invalidate(*child, recursion_data, sibling_data);
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 864b786..dd734c7 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -149,7 +149,6 @@
 #include "core/html/HTMLUnknownElement.h"
 #include "core/html/PluginDocument.h"
 #include "core/html/WindowNameCollection.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
 #include "core/html/canvas/CanvasFontCache.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/html/canvas/HTMLCanvasElement.h"
@@ -1027,7 +1026,7 @@
       CreateQualifiedName(namespace_uri, qualified_name, exception_state));
   if (q_name == QualifiedName::Null())
     return nullptr;
-  return createElement(q_name, CreateElementFlags::ByCreateElement());
+  return CreateElement(q_name, CreateElementFlags::ByCreateElement());
 }
 
 // https://dom.spec.whatwg.org/#internal-createelementns-steps
@@ -1087,26 +1086,25 @@
       definition = registry->DefinitionFor(desc);
   }
 
-  // 5. Let element be the result of creating an element
-  Element* element;
+  if (definition)
+    return definition->CreateElement(*this, q_name, flags);
 
-  if (definition) {
-    element = definition->CreateElement(*this, q_name, flags);
-  } else if (V0CustomElement::IsValidName(q_name.LocalName()) &&
-             RegistrationContext()) {
+  Element* element;
+  if (V0CustomElement::IsValidName(q_name.LocalName()) &&
+      RegistrationContext()) {
     element = RegistrationContext()->CreateCustomTagElement(*this, q_name);
   } else {
     element = CreateRawElement(q_name, flags);
-    // 7.3. If namespace is the HTML namespace, and either localName is
-    // a valid custom element name or is is non-null, then set result’s
-    // custom element state to "undefined".
-    if (q_name.NamespaceURI() == HTMLNames::xhtmlNamespaceURI &&
-        (CustomElement::IsValidName(q_name.LocalName()) || !is.IsEmpty()))
-      element->SetCustomElementState(CustomElementState::kUndefined);
-
     if (!is.IsEmpty() && flags.IsCustomElementsV0())
       V0CustomElementRegistrationContext::SetTypeExtension(element, is);
   }
+  // 7.3. If namespace is the HTML namespace, and either localName is a
+  // valid custom element name or is is non-null, then set result’s
+  // custom element state to "undefined".
+  if (q_name.NamespaceURI() == HTMLNames::xhtmlNamespaceURI &&
+      (CustomElement::IsValidName(q_name.LocalName()) || !is.IsEmpty()))
+    element->SetCustomElementState(CustomElementState::kUndefined);
+
   return element;
 }
 
@@ -1293,7 +1291,7 @@
             kNamespaceError, "The imported node has an invalid namespace.");
         return nullptr;
       }
-      Element* new_element = createElement(old_element->TagQName(),
+      Element* new_element = CreateElement(old_element->TagQName(),
                                            CreateElementFlags::ByImportNode());
       const AtomicString& is = old_element->IsValue();
       if (!is.IsNull() &&
@@ -1436,7 +1434,7 @@
 }
 
 // FIXME: This should really be in a possible ElementFactory class
-Element* Document::createElement(const QualifiedName& q_name,
+Element* Document::CreateElement(const QualifiedName& q_name,
                                  CreateElementFlags flags) {
   Element* element = nullptr;
 
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 43dc85d1..28a6b724 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -364,7 +364,7 @@
   // function is equivalent to CreateRawElement().
   // This function is equivalent to CreateElement(qname, flags, g_null_atom),
   // However this is faster.
-  Element* createElement(const QualifiedName&, const CreateElementFlags);
+  Element* CreateElement(const QualifiedName&, const CreateElementFlags);
   // Creates an element without custom element processing.
   Element* CreateRawElement(const QualifiedName&,
                             const CreateElementFlags = CreateElementFlags());
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 60fa62d8..1d0c7d6 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -280,7 +280,7 @@
 }
 
 Element* Element::CloneElementWithoutAttributesAndChildren() {
-  auto* element = GetDocument().createElement(
+  auto* element = GetDocument().CreateElement(
       TagQName(), CreateElementFlags::ByCloneNode());
   const AtomicString& is = IsValue();
   if (!is.IsNull() && !V0CustomElement::IsValidName(element->localName()))
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp
index e62f4550..ab04143 100644
--- a/third_party/WebKit/Source/core/editing/Editor.cpp
+++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -748,11 +748,6 @@
   return target;
 }
 
-Element* Editor::FindEventTargetFromSelection() const {
-  return FindEventTargetFrom(
-      GetFrameSelection().ComputeVisibleSelectionInDOMTreeDeprecated());
-}
-
 Element* Editor::FindEventTargetForClipboardEvent(
     EditorCommandSource source) const {
   // https://www.w3.org/TR/clipboard-apis/#fire-a-clipboard-event says:
@@ -762,7 +757,8 @@
   if (source == kCommandFromMenuOrKeyBinding && GetFrameSelection().IsHidden())
     return GetFrameSelection().GetDocument().body();
 
-  return FindEventTargetFromSelection();
+  return FindEventTargetFrom(
+      GetFrameSelection().ComputeVisibleSelectionInDOMTree());
 }
 
 void Editor::ApplyParagraphStyle(CSSPropertyValueSet* style,
diff --git a/third_party/WebKit/Source/core/editing/Editor.h b/third_party/WebKit/Source/core/editing/Editor.h
index 81e1af7..7e184a16 100644
--- a/third_party/WebKit/Source/core/editing/Editor.h
+++ b/third_party/WebKit/Source/core/editing/Editor.h
@@ -222,7 +222,6 @@
   void PasteAsPlainText(const String&, bool smart_replace, EditorCommandSource);
 
   Element* FindEventTargetFrom(const VisibleSelection&) const;
-  Element* FindEventTargetFromSelection() const;
   Element* FindEventTargetForClipboardEvent(EditorCommandSource) const;
 
   bool FindString(const String&, FindOptions);
diff --git a/third_party/WebKit/Source/core/editing/LocalCaretRect.cpp b/third_party/WebKit/Source/core/editing/LocalCaretRect.cpp
index 94ed4a3..f2e8b806 100644
--- a/third_party/WebKit/Source/core/editing/LocalCaretRect.cpp
+++ b/third_party/WebKit/Source/core/editing/LocalCaretRect.cpp
@@ -108,7 +108,13 @@
   if (adjusted.IsNull())
     return LocalCaretRect();
 
-  // TODO(xiaochengh): Plug in NG implementation here.
+  if (const LayoutBlockFlow* context =
+          NGInlineFormattingContextOf(adjusted.GetPosition())) {
+    // TODO(editing-dev): Use selection height instead of caret height, or
+    // decide if we need to keep the distinction between caret height and
+    // selection height in NG.
+    return ComputeNGLocalCaretRect(*context, adjusted);
+  }
 
   // TODO(editing-dev): This DCHECK is for ensuring the correctness of
   // breaking |ComputeInlineBoxPosition| into |ComputeInlineAdjustedPosition|
diff --git a/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp
index 56d4b408..ca10020 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp
@@ -334,7 +334,7 @@
   DCHECK_EQ(name.NamespaceURI(), HTMLNames::xhtmlNamespaceURI)
       << "Unexpected namespace: " << name;
   return ToHTMLElement(
-      document.createElement(name, CreateElementFlags::ByCloneNode()));
+      document.CreateElement(name, CreateElementFlags::ByCloneNode()));
 }
 
 HTMLElement* EnclosingList(const Node* node) {
diff --git a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
index c8519cd..c3485ab 100644
--- a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
@@ -92,7 +92,7 @@
   // We should calculate visible range in list item because inserting new
   // list element will change visibility of list item, e.g. :first-child
   // CSS selector.
-  HTMLElement* new_list = ToHTMLElement(GetDocument().createElement(
+  HTMLElement* new_list = ToHTMLElement(GetDocument().CreateElement(
       list_element->TagQName(), CreateElementFlags::ByCloneNode()));
   InsertNodeBefore(new_list, selected_list_item, editing_state);
   if (editing_state->IsAborted())
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
index 3e64212..0623a44b 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
@@ -496,8 +496,14 @@
 
   Document& current_document = *GetFrame().GetDocument();
 
+  // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
+  // needs to be audited.  See http://crbug.com/590369 for more details.
+  current_document.UpdateStyleAndLayoutIgnorePendingStylesheets();
+
   // Dispatch 'beforeinput'.
-  Element* const target = GetFrame().GetEditor().FindEventTargetFromSelection();
+  Element* const target = GetFrame().GetEditor().FindEventTargetFrom(
+      GetFrame().Selection().ComputeVisibleSelectionInDOMTree());
+
   DataTransfer* const data_transfer = DataTransfer::Create(
       DataTransfer::DataTransferType::kInsertReplacementText,
       DataTransferAccessPolicy::kDataTransferReadable,
diff --git a/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionController.cpp b/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionController.cpp
index 3529fbc..1eab1ba2 100644
--- a/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionController.cpp
+++ b/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionController.cpp
@@ -595,8 +595,16 @@
   GetFrame().Selection().SetSelectionAndEndTyping(
       SelectionInDOMTree::Builder().SetBaseAndExtent(range).Build());
 
+  // TODO(editing-dev): We should check whether |TextSuggestionController| is
+  // available or not.
+  // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
+  // needs to be audited.  See http://crbug.com/590369 for more details.
+  GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
+
   // Dispatch 'beforeinput'.
-  Element* const target = GetFrame().GetEditor().FindEventTargetFromSelection();
+  Element* const target = GetFrame().GetEditor().FindEventTargetFrom(
+      GetFrame().Selection().ComputeVisibleSelectionInDOMTree());
+
   DataTransfer* const data_transfer = DataTransfer::Create(
       DataTransfer::DataTransferType::kInsertReplacementText,
       DataTransferAccessPolicy::kDataTransferReadable,
diff --git a/third_party/WebKit/Source/core/html/BUILD.gn b/third_party/WebKit/Source/core/html/BUILD.gn
index 97c6290..02a6c90 100644
--- a/third_party/WebKit/Source/core/html/BUILD.gn
+++ b/third_party/WebKit/Source/core/html/BUILD.gn
@@ -198,6 +198,8 @@
     "WindowNameCollection.h",
     "canvas/CanvasAsyncBlobCreator.cpp",
     "canvas/CanvasAsyncBlobCreator.h",
+    "canvas/CanvasContextCreationAttributesCore.cpp",
+    "canvas/CanvasContextCreationAttributesCore.h",
     "canvas/CanvasDrawListener.cpp",
     "canvas/CanvasDrawListener.h",
     "canvas/CanvasFontCache.cpp",
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasContextCreationAttributesCore.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasContextCreationAttributesCore.cpp
new file mode 100644
index 0000000..51827a4
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasContextCreationAttributesCore.cpp
@@ -0,0 +1,20 @@
+// Copyright 2018 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 "CanvasContextCreationAttributesCore.h"
+
+namespace blink {
+
+CanvasContextCreationAttributesCore::CanvasContextCreationAttributesCore() {}
+
+CanvasContextCreationAttributesCore::CanvasContextCreationAttributesCore(
+    blink::CanvasContextCreationAttributesCore const& attrs) = default;
+
+CanvasContextCreationAttributesCore::~CanvasContextCreationAttributesCore() {}
+
+void CanvasContextCreationAttributesCore::Trace(blink::Visitor* visitor) {
+  visitor->Trace(compatible_xr_device);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasContextCreationAttributesCore.h b/third_party/WebKit/Source/core/html/canvas/CanvasContextCreationAttributesCore.h
new file mode 100644
index 0000000..ca4543a
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasContextCreationAttributesCore.h
@@ -0,0 +1,43 @@
+// Copyright 2018 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 CanvasContextCreationAttributesCore_h
+#define CanvasContextCreationAttributesCore_h
+
+#include "core/CoreExport.h"
+#include "platform/heap/Handle.h"
+#include "platform/wtf/text/WTFString.h"
+#include "third_party/WebKit/Source/core/dom/events/EventTarget.h"
+
+namespace blink {
+
+class CORE_EXPORT CanvasContextCreationAttributesCore {
+  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
+
+ public:
+  CanvasContextCreationAttributesCore();
+  CanvasContextCreationAttributesCore(
+      blink::CanvasContextCreationAttributesCore const&);
+  virtual ~CanvasContextCreationAttributesCore();
+
+  bool alpha = true;
+  bool antialias = true;
+  String color_space = "srgb";
+  bool depth = true;
+  bool fail_if_major_performance_caveat = false;
+  bool low_latency = false;
+  String pixel_format = "8-8-8-8";
+  bool premultiplied_alpha = true;
+  bool preserve_drawing_buffer = false;
+  bool stencil = false;
+
+  // This attribute is of type XRDevice, defined in modules/xr/XRDevice.h
+  Member<EventTargetWithInlineData> compatible_xr_device;
+
+  void Trace(blink::Visitor*);
+};
+
+}  // namespace blink
+
+#endif  // CanvasContextCreationAttributes_h
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasFontCacheTest.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasFontCacheTest.cpp
index 82e58e77..56da2cc 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasFontCacheTest.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasFontCacheTest.cpp
@@ -7,7 +7,7 @@
 #include <memory>
 #include "core/dom/Document.h"
 #include "core/frame/LocalFrameView.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/loader/EmptyClients.h"
 #include "core/testing/PageTestBase.h"
@@ -51,8 +51,8 @@
   GetDocument().View()->UpdateAllLifecyclePhases();
   canvas_element_ = ToHTMLCanvasElement(GetDocument().getElementById("c"));
   String canvas_type("2d");
-  CanvasContextCreationAttributes attributes;
-  attributes.setAlpha(true);
+  CanvasContextCreationAttributesCore attributes;
+  attributes.alpha = true;
   canvas_element_->GetCanvasRenderingContext(canvas_type, attributes);
   Context2d();  // Calling this for the checks
 }
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp
index 90243658..e7f4f88 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp
@@ -25,7 +25,7 @@
 
 #include "core/html/canvas/CanvasRenderingContext.h"
 
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/CanvasImageSource.h"
 #include "platform/runtime_enabled_features.h"
 #include "platform/weborigin/SecurityOrigin.h"
@@ -35,7 +35,7 @@
 
 CanvasRenderingContext::CanvasRenderingContext(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attrs)
+    const CanvasContextCreationAttributesCore& attrs)
     : host_(host),
       color_params_(kSRGBCanvasColorSpace, kRGBA8CanvasPixelFormat, kNonOpaque),
       creation_attributes_(attrs) {
@@ -43,26 +43,25 @@
   // gamut color spaces, user must explicitly request for float16 storage.
   // Otherwise, we fall back to srgb-8888. Invalid requests fall back to
   // srgb-8888 too.
-  if (creation_attributes_.pixelFormat() == kF16CanvasPixelFormatName) {
+  if (creation_attributes_.pixel_format == kF16CanvasPixelFormatName) {
     color_params_.SetCanvasPixelFormat(kF16CanvasPixelFormat);
-    if (creation_attributes_.colorSpace() == kRec2020CanvasColorSpaceName)
+    if (creation_attributes_.color_space == kRec2020CanvasColorSpaceName)
       color_params_.SetCanvasColorSpace(kRec2020CanvasColorSpace);
-    else if (creation_attributes_.colorSpace() == kP3CanvasColorSpaceName)
+    else if (creation_attributes_.color_space == kP3CanvasColorSpaceName)
       color_params_.SetCanvasColorSpace(kP3CanvasColorSpace);
   }
 
-  if (!creation_attributes_.alpha()) {
+  if (!creation_attributes_.alpha) {
     color_params_.SetOpacityMode(kOpaque);
   }
 
-  if (!RuntimeEnabledFeatures::LowLatencyCanvasEnabled() &&
-      creation_attributes_.hasLowLatency())
-    creation_attributes_.setLowLatency(false);
+  if (!RuntimeEnabledFeatures::LowLatencyCanvasEnabled())
+    creation_attributes_.low_latency = false;
 
   // Make m_creationAttributes reflect the effective colorSpace and pixelFormat
   // rather than the requested one.
-  creation_attributes_.setColorSpace(ColorSpaceAsString());
-  creation_attributes_.setPixelFormat(PixelFormatAsString());
+  creation_attributes_.color_space = ColorSpaceAsString();
+  creation_attributes_.pixel_format = PixelFormatAsString();
 }
 
 WTF::String CanvasRenderingContext::ColorSpaceAsString() const {
@@ -193,6 +192,7 @@
 
 void CanvasRenderingContext::Trace(blink::Visitor* visitor) {
   visitor->Trace(host_);
+  visitor->Trace(creation_attributes_);
   ScriptWrappable::Trace(visitor);
 }
 
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h
index bb948f0..4321b4bb 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h
@@ -28,7 +28,7 @@
 
 #include "base/macros.h"
 #include "core/CoreExport.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/HTMLCanvasElement.h"
 #include "core/layout/HitTestCanvasResult.h"
 #include "core/offscreencanvas/OffscreenCanvas.h"
@@ -187,7 +187,7 @@
 
   void DetachHost() { host_ = nullptr; }
 
-  const CanvasContextCreationAttributes& CreationAttributes() const {
+  const CanvasContextCreationAttributesCore& CreationAttributes() const {
     return creation_attributes_;
   }
 
@@ -196,7 +196,7 @@
 
  protected:
   CanvasRenderingContext(CanvasRenderingContextHost*,
-                         const CanvasContextCreationAttributes&);
+                         const CanvasContextCreationAttributesCore&);
 
  private:
   void Dispose();
@@ -205,7 +205,7 @@
   HashSet<String> clean_urls_;
   HashSet<String> dirty_urls_;
   CanvasColorParams color_params_;
-  CanvasContextCreationAttributes creation_attributes_;
+  CanvasContextCreationAttributesCore creation_attributes_;
   bool finalize_frame_scheduled_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(CanvasRenderingContext);
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextFactory.h b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextFactory.h
index 64517d1..2dcfd396 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextFactory.h
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextFactory.h
@@ -9,7 +9,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "core/CoreExport.h"
 #include "core/dom/Document.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "platform/wtf/Allocator.h"
 
@@ -27,7 +27,7 @@
 
   virtual CanvasRenderingContext* Create(
       CanvasRenderingContextHost*,
-      const CanvasContextCreationAttributes&) = 0;
+      const CanvasContextCreationAttributesCore&) = 0;
 
   virtual CanvasRenderingContext::ContextType GetContextType() const = 0;
   virtual void OnError(HTMLCanvasElement*, const String& error){};
diff --git a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp
index 87cf27c..4d3f12d 100644
--- a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp
@@ -49,7 +49,7 @@
 #include "core/frame/UseCounter.h"
 #include "core/html/HTMLImageElement.h"
 #include "core/html/canvas/CanvasAsyncBlobCreator.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/CanvasFontCache.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/html/canvas/CanvasRenderingContextFactory.h"
@@ -253,7 +253,7 @@
 
 CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContext(
     const String& type,
-    const CanvasContextCreationAttributes& attributes) {
+    const CanvasContextCreationAttributesCore& attributes) {
   CanvasRenderingContext::ContextType context_type =
       CanvasRenderingContext::ContextTypeFromId(type);
 
@@ -300,13 +300,13 @@
   }
 
   LayoutObject* layout_object = GetLayoutObject();
-  if (layout_object && Is2d() && !context_->CreationAttributes().alpha()) {
+  if (layout_object && Is2d() && !context_->CreationAttributes().alpha) {
     // In the alpha false case, canvas is initially opaque even though there is
     // no ImageBuffer, so we need to trigger an invalidation.
     DidDraw();
   }
 
-  if (attributes.lowLatency() &&
+  if (attributes.low_latency &&
       RuntimeEnabledFeatures::LowLatencyCanvasEnabled()) {
     CreateLayer();
     SetNeedsUnbufferedInputEvents(true);
@@ -691,7 +691,7 @@
   if (HasImageBuffer()) {
     if (!context.ContextDisabled()) {
       SkBlendMode composite_operator =
-          !context_ || context_->CreationAttributes().alpha()
+          !context_ || context_->CreationAttributes().alpha
               ? SkBlendMode::kSrcOver
               : SkBlendMode::kSrc;
       FloatRect src_rect = FloatRect(FloatPoint(), FloatSize(Size()));
@@ -708,7 +708,7 @@
     }
   } else {
     // When alpha is false, we should draw to opaque black.
-    if (!context_->CreationAttributes().alpha())
+    if (!context_->CreationAttributes().alpha)
       context.FillRect(FloatRect(r), Color(0, 0, 0));
   }
 
@@ -753,7 +753,7 @@
     return nullptr;
   scoped_refptr<StaticBitmapImage> image_bitmap = nullptr;
   if (Is3d()) {
-    if (context_->CreationAttributes().premultipliedAlpha()) {
+    if (context_->CreationAttributes().premultiplied_alpha) {
       context_->PaintRenderingResultsToCanvas(source_buffer);
       if (webgl_resource_provider_)
         image_bitmap = webgl_resource_provider_->Snapshot();
@@ -1366,7 +1366,7 @@
 }
 
 bool HTMLCanvasElement::IsOpaque() const {
-  return context_ && !context_->CreationAttributes().alpha();
+  return context_ && !context_->CreationAttributes().alpha;
 }
 
 bool HTMLCanvasElement::IsSupportedInteractiveCanvasFallback(
diff --git a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.h
index bac15fb..440f2563c 100644
--- a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.h
+++ b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.h
@@ -60,7 +60,7 @@
 
 class Canvas2DLayerBridge;
 class CanvasColorParams;
-class CanvasContextCreationAttributes;
+class CanvasContextCreationAttributesCore;
 class CanvasRenderingContext;
 class CanvasRenderingContextFactory;
 class GraphicsContext;
@@ -109,7 +109,7 @@
   // Called by Document::getCSSCanvasContext as well as above getContext().
   CanvasRenderingContext* GetCanvasRenderingContext(
       const String&,
-      const CanvasContextCreationAttributes&);
+      const CanvasContextCreationAttributesCore&);
 
   String toDataURL(const String& mime_type,
                    const ScriptValue& quality_argument,
diff --git a/third_party/WebKit/Source/core/html/canvas/ImageDataColorSettings.idl b/third_party/WebKit/Source/core/html/canvas/ImageDataColorSettings.idl
index 828808c..917e0e1 100644
--- a/third_party/WebKit/Source/core/html/canvas/ImageDataColorSettings.idl
+++ b/third_party/WebKit/Source/core/html/canvas/ImageDataColorSettings.idl
@@ -4,6 +4,12 @@
 
 // https://github.com/junov/CanvasColorSpace/blob/master/CanvasColorSpaceProposal.md#imageda
 
+enum CanvasColorSpace {
+    "srgb", // default
+    "rec2020",
+    "p3",
+};
+
 enum ImageDataStorageFormat {
   "uint8", // default
   "uint16",
diff --git a/third_party/WebKit/Source/core/html/media/MediaRemotingInterstitial.cpp b/third_party/WebKit/Source/core/html/media/MediaRemotingInterstitial.cpp
index 2d3b02f..05320949 100644
--- a/third_party/WebKit/Source/core/html/media/MediaRemotingInterstitial.cpp
+++ b/third_party/WebKit/Source/core/html/media/MediaRemotingInterstitial.cpp
@@ -43,7 +43,7 @@
 
   cast_text_message_ = HTMLDivElement::Create(GetDocument());
   cast_text_message_->SetShadowPseudoId(
-      AtomicString("-internal-media-remoting-cast-text-message"));
+      AtomicString("-internal-media-interstitial-message"));
   AppendChild(cast_text_message_);
 
   toast_message_ = HTMLDivElement::Create(GetDocument());
diff --git a/third_party/WebKit/Source/core/html/media/MediaRemotingInterstitial.h b/third_party/WebKit/Source/core/html/media/MediaRemotingInterstitial.h
index 19430a179..b8a37f1 100644
--- a/third_party/WebKit/Source/core/html/media/MediaRemotingInterstitial.h
+++ b/third_party/WebKit/Source/core/html/media/MediaRemotingInterstitial.h
@@ -19,11 +19,11 @@
 // MediaRemotingInterstitial
 //     (-internal-media-remoting-interstitial)
 // +-HTMLImageElement
-// |    (-internal-media-remoting-background-image)
+// |    (-internal-media-interstitial-background-image)
 // \-HTMLDivElement
 // |    (-internal-media-remoting-cast-icon)
 // \-HTMLDivElement
-// |    (-internal-media-remoting-cast-text-message)
+// |    (-internal-media-interstitial-message)
 // |-HTMLDivElement
 //      (-internal-media-remoting-toast-message)
 class MediaRemotingInterstitial final : public HTMLDivElement {
diff --git a/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.cpp b/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.cpp
index 128ae6b..f2668b0 100644
--- a/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.cpp
+++ b/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.cpp
@@ -34,9 +34,14 @@
   background_image_->SetSrc(videoElement.getAttribute(HTMLNames::posterAttr));
   AppendChild(background_image_);
 
+  pip_icon_ = HTMLDivElement::Create(GetDocument());
+  pip_icon_->SetShadowPseudoId(
+      AtomicString("-internal-picture-in-picture-icon"));
+  AppendChild(pip_icon_);
+
   HTMLDivElement* message_element_ = HTMLDivElement::Create(GetDocument());
   message_element_->SetShadowPseudoId(
-      AtomicString("-internal-picture-in-picture-message"));
+      AtomicString("-internal-media-interstitial-message"));
   message_element_->setInnerText(
       GetVideoElement().GetLocale().QueryString(
           WebLocalizedString::kPictureInPictureInterstitialText),
@@ -86,6 +91,7 @@
 void PictureInPictureInterstitial::Trace(blink::Visitor* visitor) {
   visitor->Trace(video_element_);
   visitor->Trace(background_image_);
+  visitor->Trace(pip_icon_);
   visitor->Trace(message_element_);
   HTMLDivElement::Trace(visitor);
 }
diff --git a/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.h b/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.h
index 1ae92e2..ec2f7364 100644
--- a/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.h
+++ b/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.h
@@ -19,9 +19,11 @@
 // PictureInPictureInterstitial
 //     (-internal-picture-in-picture-interstitial)
 // +-HTMLImageElement
-// |    (-internal-picture-in-picture-background-image)
-// \-PictureInPictureMessageElement
-// |    (-internal-picture-in-picture-message)
+// |    (-internal-media-interstitial-background-image)
+// \-HTMLDivElement
+// |    (-internal-picture-in-picture-icon)
+// \-HTMLDivElement
+// |    (-internal-media-interstitial-message)
 class PictureInPictureInterstitial final : public HTMLDivElement {
  public:
   explicit PictureInPictureInterstitial(HTMLVideoElement&);
@@ -50,6 +52,7 @@
   TaskRunnerTimer<PictureInPictureInterstitial> interstitial_timer_;
   Member<HTMLVideoElement> video_element_;
   Member<HTMLImageElement> background_image_;
+  Member<HTMLDivElement> pip_icon_;
   Member<HTMLDivElement> message_element_;
 };
 
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
index 4e5c3c1..849af633 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
@@ -927,7 +927,7 @@
       element = definition->CreateElement(document, tag_name,
                                           GetCreateElementFlags());
     } else {
-      element = document.createElement(tag_name, GetCreateElementFlags());
+      element = document.CreateElement(tag_name, GetCreateElementFlags());
       // Step 7.3 of "create an element". The above createElement()
       // doesn't take care of "is" attribute.
       if (!is.IsNull()) {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
index a284cf8..0f9ffed 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
@@ -37,6 +37,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/SourceLocation.h"
+#include "build/build_config.h"
 #include "core/dom/Document.h"
 #include "core/dom/ScriptableDocumentParser.h"
 #include "core/fileapi/FileReaderLoader.h"
@@ -103,11 +104,18 @@
 }
 
 namespace {
+
+#if defined(OS_ANDROID)
+// 10MB
+static size_t g_maximum_total_buffer_size = 10 * 1000 * 1000;
+// 5MB
+static size_t g_maximum_resource_buffer_size = 5 * 1000 * 1000;
+#else
 // 100MB
 static size_t g_maximum_total_buffer_size = 100 * 1000 * 1000;
-
 // 10MB
 static size_t g_maximum_resource_buffer_size = 10 * 1000 * 1000;
+#endif
 
 // Pattern may contain stars ('*') which match to any (possibly empty) string.
 // Stars implicitly assumed at the begin/end of pattern.
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index ea0266367..d392f0a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -5083,59 +5083,28 @@
 }
 
 LayoutRectOutsets LayoutBox::ComputeVisualEffectOverflowOutsets() {
-  DCHECK(Style()->HasVisualOverflowingEffect());
+  const ComputedStyle& style = StyleRef();
+  DCHECK(style.HasVisualOverflowingEffect());
 
-  LayoutUnit top;
-  LayoutUnit right;
-  LayoutUnit bottom;
-  LayoutUnit left;
-
-  if (const ShadowList* box_shadow = Style()->BoxShadow()) {
-    // FIXME: Use LayoutUnit edge outsets, and then simplify this.
-    FloatRectOutsets outsets = box_shadow->RectOutsetsIncludingOriginal();
-    top = LayoutUnit(outsets.Top());
-    right = LayoutUnit(outsets.Right());
-    bottom = LayoutUnit(outsets.Bottom());
-    left = LayoutUnit(outsets.Left());
-  }
-
-  if (Style()->HasBorderImageOutsets()) {
-    LayoutRectOutsets border_outsets = Style()->BorderImageOutsets();
-    top = std::max(top, border_outsets.Top());
-    right = std::max(right, border_outsets.Right());
-    bottom = std::max(bottom, border_outsets.Bottom());
-    left = std::max(left, border_outsets.Left());
-  }
-
-  if (Style()->HasMaskBoxImageOutsets()) {
-    LayoutRectOutsets outsets = Style()->MaskBoxImageOutsets();
-    top = std::max(top, outsets.Top());
-    right = std::max(right, outsets.Right());
-    bottom = std::max(bottom, outsets.Bottom());
-    left = std::max(left, outsets.Left());
-  }
+  LayoutRectOutsets outsets = style.BoxDecorationOutsets();
 
   // Box-shadow and border-image-outsets are in physical direction. Flip into
   // block direction.
   if (UNLIKELY(HasFlippedBlocksWritingMode()))
-    std::swap(left, right);
+    outsets.FlipHorizontally();
 
-  if (Style()->HasOutline()) {
+  if (style.HasOutline()) {
     Vector<LayoutRect> outline_rects;
     // The result rects are in coordinates of this object's border box.
     AddOutlineRects(outline_rects, LayoutPoint(),
                     OutlineRectsShouldIncludeBlockVisualOverflow());
     LayoutRect rect = UnionRectEvenIfEmpty(outline_rects);
     SetOutlineMayBeAffectedByDescendants(rect.Size() != Size());
-
-    int outline_outset = Style()->OutlineOutsetExtent();
-    top = std::max(top, -rect.Y() + outline_outset);
-    right = std::max(right, rect.MaxX() - Size().Width() + outline_outset);
-    bottom = std::max(bottom, rect.MaxY() - Size().Height() + outline_outset);
-    left = std::max(left, -rect.X() + outline_outset);
+    rect.Inflate(style.OutlineOutsetExtent());
+    outsets.Unite(rect.ToOutsets(Size()));
   }
 
-  return LayoutRectOutsets(top, right, bottom, left);
+  return outsets;
 }
 
 DISABLE_CFI_PERF
diff --git a/third_party/WebKit/Source/core/layout/LayoutGeometryMap.cpp b/third_party/WebKit/Source/core/layout/LayoutGeometryMap.cpp
index 5c43e56..8887288 100644
--- a/third_party/WebKit/Source/core/layout/LayoutGeometryMap.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutGeometryMap.cpp
@@ -177,11 +177,8 @@
             ->LocalToAncestorQuad(rect, ancestor, map_coordinates_flags_)
             .BoundingBox();
 
-    // Inspector creates layoutObjects with negative width
-    // <https://bugs.webkit.org/show_bug.cgi?id=87194>.
-    // Taking FloatQuad bounds avoids spurious assertions because of that.
-    DCHECK(RoundedIntRect(layout_object_mapped_result) ==
-               RoundedIntRect(result.BoundingBox()) ||
+    DCHECK(layout_object_mapped_result.EqualWithinEpsilon(result.BoundingBox(),
+                                                          0.1f) ||
            layout_object_mapped_result.MayNotHaveExactIntRectRepresentation() ||
            result.BoundingBox().MayNotHaveExactIntRectRepresentation())
         << "Rounded: " << RoundedIntRect(layout_object_mapped_result) << " vs "
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_caret_rect.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_caret_rect.cc
index 770cbd8..17658b55 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_caret_rect.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_caret_rect.cc
@@ -9,7 +9,6 @@
 #include "core/layout/LayoutBlockFlow.h"
 #include "core/layout/LayoutTextFragment.h"
 #include "core/layout/ng/geometry/ng_physical_offset_rect.h"
-#include "core/layout/ng/inline/ng_inline_break_token.h"
 #include "core/layout/ng/inline/ng_inline_fragment_traversal.h"
 #include "core/layout/ng/inline/ng_offset_mapping.h"
 #include "core/layout/ng/inline/ng_physical_line_box_fragment.h"
@@ -50,22 +49,6 @@
   NGCaretPosition caret_position;
 };
 
-// TODO(xiaochengh): Try to avoid passing the seemingly redundant line boxes.
-// TODO(xiaochengh): Move this function to NGPhysicalFragment.
-bool IsFragmentAfterLineWrap(const NGPhysicalFragment& fragment,
-                             const NGPhysicalLineBoxFragment& current_line,
-                             const NGPhysicalLineBoxFragment* last_line) {
-  if (!last_line)
-    return false;
-  // A fragment after line wrap must be the first logical leaf in its line.
-  if (&fragment != current_line.FirstLogicalLeaf())
-    return false;
-  DCHECK(last_line->BreakToken());
-  DCHECK(last_line->BreakToken()->IsInlineType());
-  DCHECK(!last_line->BreakToken()->IsFinished());
-  return !ToNGInlineBreakToken(last_line->BreakToken())->IsForcedBreak();
-}
-
 bool CanResolveCaretPositionBeforeFragment(
     const NGPhysicalFragment& fragment,
     TextAffinity affinity,
@@ -73,21 +56,10 @@
     const NGPhysicalLineBoxFragment* last_line) {
   if (affinity == TextAffinity::kDownstream)
     return true;
-  return !IsFragmentAfterLineWrap(fragment, current_line, last_line);
-}
-
-// TODO(xiaochengh): Try to avoid passing the seemingly redundant line box.
-// TODO(xiaochengh): Move this function to NGPhysicalFragment.
-bool IsFragmentBeforeLineWrap(const NGPhysicalFragment& fragment,
-                              const NGPhysicalLineBoxFragment& current_line) {
-  // A fragment before line wrap must be the last logical leaf in its line.
-  if (&fragment != current_line.LastLogicalLeaf())
-    return false;
-  DCHECK(current_line.BreakToken());
-  DCHECK(current_line.BreakToken()->IsInlineType());
-  const NGInlineBreakToken& break_token =
-      ToNGInlineBreakToken(*current_line.BreakToken());
-  return !break_token.IsFinished() && !break_token.IsForcedBreak();
+  // A fragment after line wrap must be the first logical leaf in its line.
+  if (&fragment != current_line.FirstLogicalLeaf())
+    return true;
+  return !current_line.HasSoftWrapFromPreviousLine(last_line);
 }
 
 bool CanResolveCaretPositionAfterFragment(
@@ -96,7 +68,10 @@
     const NGPhysicalLineBoxFragment& current_line) {
   if (affinity == TextAffinity::kUpstream)
     return true;
-  return !IsFragmentBeforeLineWrap(fragment, current_line);
+  // A fragment before line wrap must be the last logical leaf in its line.
+  if (&fragment != current_line.LastLogicalLeaf())
+    return true;
+  return !current_line.HasSoftWrapToNextLine();
 }
 
 CaretPositionResolution TryResolveCaretPositionInTextFragment(
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_line_box_fragment.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_line_box_fragment.cc
index 72cced2..416e05fb 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_line_box_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_line_box_fragment.cc
@@ -4,6 +4,7 @@
 
 #include "core/layout/ng/inline/ng_physical_line_box_fragment.h"
 
+#include "core/layout/ng/inline/ng_inline_break_token.h"
 #include "core/style/ComputedStyle.h"
 
 namespace blink {
@@ -75,4 +76,19 @@
   return runner;
 }
 
+bool NGPhysicalLineBoxFragment::HasSoftWrapToNextLine() const {
+  DCHECK(BreakToken());
+  DCHECK(BreakToken()->IsInlineType());
+  const NGInlineBreakToken& break_token = ToNGInlineBreakToken(*BreakToken());
+  return !break_token.IsFinished() && !break_token.IsForcedBreak();
+}
+
+// TODO(xiaochengh): Try avoid passing |previous_line|.
+bool NGPhysicalLineBoxFragment::HasSoftWrapFromPreviousLine(
+    const NGPhysicalLineBoxFragment* previous_line) const {
+  if (!previous_line)
+    return false;
+  return previous_line->HasSoftWrapToNextLine();
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_line_box_fragment.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_line_box_fragment.h
index fde1344f..08b7d376 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_line_box_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_line_box_fragment.h
@@ -36,6 +36,13 @@
   const NGPhysicalFragment* FirstLogicalLeaf() const;
   const NGPhysicalFragment* LastLogicalLeaf() const;
 
+  // Whether the content soft-wraps to the next line.
+  bool HasSoftWrapToNextLine() const;
+
+  // Whether the content is following a soft-wrap from the previous line.
+  // TODO(xiaochengh): Try to avoid passing the previous line.
+  bool HasSoftWrapFromPreviousLine(const NGPhysicalLineBoxFragment*) const;
+
   scoped_refptr<NGPhysicalFragment> CloneWithoutOffset() const {
     Vector<scoped_refptr<NGPhysicalFragment>> children_copy(children_);
     return base::AdoptRef(new NGPhysicalLineBoxFragment(
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc
index 125f5e292..26ac797e 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc
@@ -77,11 +77,20 @@
     return {{}, Size()};
 
   LayoutObject* layout_object = GetLayoutObject();
+  DCHECK(layout_object);
   if (layout_object->IsBox()) {
-    // TODO(kojii): Should move the logic to a common place.
     LayoutRect visual_rect({}, Size().ToLayoutSize());
-    visual_rect.Expand(
-        ToLayoutBox(layout_object)->ComputeVisualEffectOverflowOutsets());
+    visual_rect.Expand(style.BoxDecorationOutsets());
+
+    if (style.HasOutline()) {
+      Vector<LayoutRect> outline_rects;
+      // The result rects are in coordinates of this object's border box.
+      AddSelfOutlineRects(&outline_rects, LayoutPoint());
+      LayoutRect rect = UnionRectEvenIfEmpty(outline_rects);
+      rect.Inflate(style.OutlineOutsetExtent());
+      visual_rect.Unite(rect);
+    }
+
     return NGPhysicalOffsetRect(visual_rect);
   }
 
@@ -90,6 +99,25 @@
   return {{}, Size()};
 }
 
+void NGPhysicalBoxFragment::AddSelfOutlineRects(
+    Vector<LayoutRect>* outline_rects,
+    const LayoutPoint& additional_offset) const {
+  DCHECK(outline_rects);
+  // TODO(kojii): Implement. This is quite incomplete yet.
+
+  // bool include_block_visual_overflow =
+  // layout_object->OutlineRectsShouldIncludeBlockVisualOverflow();
+
+  //
+  LayoutRect outline_rect(additional_offset, Size().ToLayoutSize());
+  // LayoutRect outline_rect = VisualRect();
+  // outline_rect.MoveBy(additional_offset);
+  // outline_rect.Inflate(-Style().OutlineOffset());
+  // outline_rect.Inflate(-Style().OutlineWidth());
+
+  outline_rects->push_back(outline_rect);
+}
+
 NGPhysicalOffsetRect NGPhysicalBoxFragment::VisualRectWithContents() const {
   if (HasOverflowClip() || Style().HasMask())
     return SelfVisualRect();
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h
index 501e4ad..6f718b5 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h
@@ -47,6 +47,9 @@
   // VisualRect of itself including contents, in the local coordinate.
   NGPhysicalOffsetRect VisualRectWithContents() const;
 
+  void AddSelfOutlineRects(Vector<LayoutRect>*,
+                           const LayoutPoint& additional_offset) const;
+
   scoped_refptr<NGPhysicalFragment> CloneWithoutOffset() const;
 
  private:
diff --git a/third_party/WebKit/Source/core/loader/TextTrackLoader.cpp b/third_party/WebKit/Source/core/loader/TextTrackLoader.cpp
index a984c62c..c0abc6a6 100644
--- a/third_party/WebKit/Source/core/loader/TextTrackLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/TextTrackLoader.cpp
@@ -66,14 +66,24 @@
   ClearResource();
 }
 
+void TextTrackLoader::ResponseReceived(Resource*,
+                                       const ResourceResponse& response,
+                                       std::unique_ptr<WebDataConsumerHandle>) {
+  if (response.IsOpaqueResponseFromServiceWorker()) {
+    CorsPolicyPreventedLoad(GetDocument().GetSecurityOrigin(),
+                            response.OriginalURLViaServiceWorker());
+  }
+}
+
 bool TextTrackLoader::RedirectReceived(Resource* resource,
                                        const ResourceRequest& request,
                                        const ResourceResponse&) {
   DCHECK_EQ(GetResource(), resource);
   if (resource->GetResourceRequest().GetFetchRequestMode() ==
           network::mojom::FetchRequestMode::kCORS ||
-      GetDocument().GetSecurityOrigin()->CanRequestNoSuborigin(request.Url()))
+      GetDocument().GetSecurityOrigin()->CanRequestNoSuborigin(request.Url())) {
     return true;
+  }
 
   CorsPolicyPreventedLoad(GetDocument().GetSecurityOrigin(), request.Url());
   if (!cue_load_timer_.IsActive())
diff --git a/third_party/WebKit/Source/core/loader/TextTrackLoader.h b/third_party/WebKit/Source/core/loader/TextTrackLoader.h
index a9c892a..f795c08 100644
--- a/third_party/WebKit/Source/core/loader/TextTrackLoader.h
+++ b/third_party/WebKit/Source/core/loader/TextTrackLoader.h
@@ -68,6 +68,9 @@
 
  private:
   // RawResourceClient
+  void ResponseReceived(Resource*,
+                        const ResourceResponse&,
+                        std::unique_ptr<WebDataConsumerHandle>) override;
   bool RedirectReceived(Resource*,
                         const ResourceRequest&,
                         const ResourceResponse&) override;
diff --git a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
index ea89aacd..b126204 100644
--- a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
+++ b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
@@ -12,7 +12,7 @@
 #include "core/dom/ExecutionContext.h"
 #include "core/fileapi/Blob.h"
 #include "core/html/canvas/CanvasAsyncBlobCreator.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/html/canvas/CanvasRenderingContextFactory.h"
 #include "core/html/canvas/ImageData.h"
@@ -153,13 +153,13 @@
 bool OffscreenCanvas::IsOpaque() const {
   if (!context_)
     return false;
-  return !context_->CreationAttributes().hasAlpha();
+  return !context_->CreationAttributes().alpha;
 }
 
 CanvasRenderingContext* OffscreenCanvas::GetCanvasRenderingContext(
     ExecutionContext* execution_context,
     const String& id,
-    const CanvasContextCreationAttributes& attributes) {
+    const CanvasContextCreationAttributesCore& attributes) {
   execution_context_ = execution_context;
 
   CanvasRenderingContext::ContextType context_type =
diff --git a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h
index a4deeab..d54dfa6a 100644
--- a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h
+++ b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h
@@ -22,7 +22,7 @@
 
 namespace blink {
 
-class CanvasContextCreationAttributes;
+class CanvasContextCreationAttributesCore;
 class CanvasResourceProvider;
 class ImageBitmap;
 class
@@ -73,7 +73,7 @@
   CanvasRenderingContext* GetCanvasRenderingContext(
       ExecutionContext*,
       const String&,
-      const CanvasContextCreationAttributes&);
+      const CanvasContextCreationAttributesCore&);
 
   static void RegisterRenderingContextFactory(
       std::unique_ptr<CanvasRenderingContextFactory>);
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp
index 12803017..d3e32e5c 100644
--- a/third_party/WebKit/Source/core/page/DragController.cpp
+++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -645,7 +645,9 @@
               : InsertMode::kSimple;
 
       if (!inner_frame->GetEditor().DeleteSelectionAfterDraggingWithEvents(
-              inner_frame->GetEditor().FindEventTargetFromSelection(),
+              inner_frame->GetEditor().FindEventTargetFrom(
+                  inner_frame->Selection()
+                      .ComputeVisibleSelectionInDOMTreeDeprecated()),
               delete_mode, drag_caret.Base()))
         return false;
 
diff --git a/third_party/WebKit/Source/core/paint/HTMLCanvasPainterTest.cpp b/third_party/WebKit/Source/core/paint/HTMLCanvasPainterTest.cpp
index 38c7321..86d3780 100644
--- a/third_party/WebKit/Source/core/paint/HTMLCanvasPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/HTMLCanvasPainterTest.cpp
@@ -5,7 +5,7 @@
 #include "core/paint/HTMLCanvasPainter.h"
 
 #include "core/frame/LocalFrameView.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/html/canvas/HTMLCanvasElement.h"
 #include "core/paint/PaintControllerPaintTest.h"
@@ -86,8 +86,8 @@
   GetDocument().body()->SetInnerHTMLFromString("<canvas width=300 height=200>");
   HTMLCanvasElement* element =
       ToHTMLCanvasElement(GetDocument().body()->firstChild());
-  CanvasContextCreationAttributes attributes;
-  attributes.setAlpha(true);
+  CanvasContextCreationAttributesCore attributes;
+  attributes.alpha = true;
   CanvasRenderingContext* context =
       element->GetCanvasRenderingContext("2d", attributes);
   IntSize size(300, 200);
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
index d24007e..fa16c9b 100644
--- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
@@ -184,11 +184,10 @@
   LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(),
                                              inline_text_box_.LogicalHeight()));
 
-  int length = inline_text_box_.Len();
+  unsigned length = inline_text_box_.Len();
   const String& layout_item_string =
       inline_text_box_.GetLineLayoutItem().GetText();
-  // TODO(szager): Figure out why this CHECK sometimes fails, it shouldn't.
-  CHECK(inline_text_box_.Start() + length <= layout_item_string.length());
+
   String first_line_string;
   if (inline_text_box_.IsFirstLineStyle()) {
     first_line_string = layout_item_string;
@@ -197,6 +196,17 @@
             inline_text_box_.IsFirstLineStyle()),
         first_line_string,
         inline_text_box_.GetLineLayoutItem().PreviousCharacter());
+    // TODO(crbug.com/795498): this is a hack. The root issue is that
+    // capitalizing letters can change the length of the backing string.
+    // That needs to be taken into account when computing the size of the box
+    // or its painting.
+    length = std::min(length, first_line_string.length());
+
+    // TODO(szager): Figure out why this CHECK sometimes fails, it shouldn't.
+    CHECK(inline_text_box_.Start() + length <= first_line_string.length());
+  } else {
+    // TODO(szager): Figure out why this CHECK sometimes fails, it shouldn't.
+    CHECK(inline_text_box_.Start() + length <= layout_item_string.length());
   }
   StringView string =
       StringView(inline_text_box_.IsFirstLineStyle() ? first_line_string
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
index 066217d..65cce67 100644
--- a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
@@ -445,7 +445,7 @@
         layer->Bounds() == graphics_layer_->PlatformLayer()->Bounds()) {
       // Determine whether the rendering context's external texture layer is
       // opaque.
-      if (!context->CreationAttributes().alpha()) {
+      if (!context->CreationAttributes().alpha) {
         graphics_layer_->SetContentsOpaque(true);
       } else {
         graphics_layer_->SetContentsOpaque(
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinder.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinder.cpp
index 15768157..33baf01c 100644
--- a/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinder.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinder.cpp
@@ -13,6 +13,8 @@
 #include "core/page/scrolling/RootScrollerUtil.h"
 #include "core/paint/PaintLayer.h"
 
+#include "public/platform/Platform.h"
+
 namespace blink {
 
 CompositingReasonFinder::CompositingReasonFinder(LayoutView& layout_view)
@@ -136,7 +138,12 @@
   // may have transforms, but the layoutObject may be an inline that doesn't
   // support them.
   return layout_object.HasTransformRelatedProperty() &&
-         layout_object.StyleRef().Has3DTransform();
+         layout_object.StyleRef().Has3DTransform() &&
+         // Don't composite "trivial" 3D transforms such as translateZ(0) on
+         // low-end devices. These devices are much more sensitive to memory
+         // and per-composited-layer commit overhead.
+         (!Platform::Current()->IsLowEndDevice() ||
+          layout_object.StyleRef().Transform().HasNonTrivial3DComponent());
 }
 
 CompositingReasons CompositingReasonFinder::NonStyleDeterminedDirectReasons(
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinderTest.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinderTest.cpp
index 54aa566..417ea077 100644
--- a/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinderTest.cpp
@@ -11,6 +11,7 @@
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/scroll/ScrollTypes.h"
 #include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h"
+#include "platform/testing/TestingPlatformSupport.h"
 
 namespace blink {
 
@@ -26,6 +27,63 @@
   }
 };
 
+class CompositingReasonFinderTestPlatform : public TestingPlatformSupport {
+ public:
+  bool IsLowEndDevice() override { return true; }
+};
+
+TEST_F(CompositingReasonFinderTest, DontPromoteTrivial3DLowEnd) {
+  ScopedTestingPlatformSupport<CompositingReasonFinderTestPlatform> platform;
+
+  SetBodyInnerHTML(R"HTML(
+    <div id='target'
+      style='width: 100px; height: 100px; transform: translateZ(0)'></div>
+  )HTML");
+
+  Element* target = GetDocument().getElementById("target");
+  PaintLayer* paint_layer =
+      ToLayoutBoxModelObject(target->GetLayoutObject())->Layer();
+  EXPECT_EQ(kNotComposited, paint_layer->GetCompositingState());
+}
+
+TEST_F(CompositingReasonFinderTest, PromoteNonTrivial3DLowEnd) {
+  ScopedTestingPlatformSupport<CompositingReasonFinderTestPlatform> platform;
+
+  SetBodyInnerHTML(R"HTML(
+    <div id='target'
+      style='width: 100px; height: 100px; transform: translateZ(1px)'></div>
+  )HTML");
+
+  Element* target = GetDocument().getElementById("target");
+  PaintLayer* paint_layer =
+      ToLayoutBoxModelObject(target->GetLayoutObject())->Layer();
+  EXPECT_EQ(kPaintsIntoOwnBacking, paint_layer->GetCompositingState());
+}
+
+TEST_F(CompositingReasonFinderTest, PromoteTrivial3DByDefault) {
+  SetBodyInnerHTML(R"HTML(
+    <div id='target'
+      style='width: 100px; height: 100px; transform: translateZ(0)'></div>
+  )HTML");
+
+  Element* target = GetDocument().getElementById("target");
+  PaintLayer* paint_layer =
+      ToLayoutBoxModelObject(target->GetLayoutObject())->Layer();
+  EXPECT_EQ(kPaintsIntoOwnBacking, paint_layer->GetCompositingState());
+}
+
+TEST_F(CompositingReasonFinderTest, PromoteNonTrivial3DByDefault) {
+  SetBodyInnerHTML(R"HTML(
+    <div id='target'
+      style='width: 100px; height: 100px; transform: translateZ(1px)'></div>
+  )HTML");
+
+  Element* target = GetDocument().getElementById("target");
+  PaintLayer* paint_layer =
+      ToLayoutBoxModelObject(target->GetLayoutObject())->Layer();
+  EXPECT_EQ(kPaintsIntoOwnBacking, paint_layer->GetCompositingState());
+}
+
 TEST_F(CompositingReasonFinderTest, PromoteOpaqueFixedPosition) {
   ScopedCompositeOpaqueFixedPositionForTest composite_fixed_position(true);
 
@@ -40,8 +98,6 @@
     <div id='spacer' style='height: 2000px'></div>
   )HTML");
 
-  GetDocument().View()->UpdateAllLifecyclePhases();
-
   // The translucent fixed box should not be promoted.
   Element* element = GetDocument().getElementById("translucent");
   PaintLayer* paint_layer =
@@ -74,7 +130,6 @@
       <div style='height: 2000px;'></div>
     </div>
   )HTML");
-  GetDocument().View()->UpdateAllLifecyclePhases();
 
   EXPECT_EQ(kPaintsIntoOwnBacking,
             ToLayoutBoxModelObject(GetLayoutObjectByElementId("sticky-top"))
@@ -100,7 +155,6 @@
       <div id='sticky-no-scrolling' class='sticky'></div>
     </div>
   )HTML");
-  GetDocument().View()->UpdateAllLifecyclePhases();
 
   EXPECT_EQ(
       kPaintsIntoOwnBacking,
@@ -131,7 +185,6 @@
       <div id="spacer"></div>
     </div>
   )HTML");
-  GetDocument().View()->UpdateAllLifecyclePhases();
 
   EXPECT_TRUE(RuntimeEnabledFeatures::CompositeOpaqueScrollersEnabled());
   Element* parent = GetDocument().getElementById("parent");
@@ -181,7 +234,6 @@
       <div id="spacer"></div>
     </div>
   )HTML");
-  GetDocument().View()->UpdateAllLifecyclePhases();
 
   EXPECT_TRUE(RuntimeEnabledFeatures::CompositeOpaqueScrollersEnabled());
   Element* parent = GetDocument().getElementById("parent");
@@ -319,7 +371,6 @@
       </div>
     </div>
   )HTML");
-  GetDocument().View()->UpdateAllLifecyclePhases();
 
   Element* outer_sticky = GetDocument().getElementById("outerSticky");
   PaintLayer* outer_sticky_layer =
diff --git a/third_party/WebKit/Source/core/paint/ng/ng_paint_fragment.cc b/third_party/WebKit/Source/core/paint/ng/ng_paint_fragment.cc
index 734cee0..07451d66 100644
--- a/third_party/WebKit/Source/core/paint/ng/ng_paint_fragment.cc
+++ b/third_party/WebKit/Source/core/paint/ng/ng_paint_fragment.cc
@@ -200,15 +200,11 @@
 void NGPaintFragment::AddSelfOutlineRect(
     Vector<LayoutRect>* outline_rects,
     const LayoutPoint& additional_offset) const {
-  DCHECK(outline_rects);
-  //
-  LayoutRect outline_rect(additional_offset, Size().ToLayoutSize());
-  // LayoutRect outline_rect = VisualRect();
-  // outline_rect.MoveBy(additional_offset);
-  // outline_rect.Inflate(-Style().OutlineOffset());
-  // outline_rect.Inflate(-Style().OutlineWidth());
-
-  outline_rects->push_back(outline_rect);
+  const NGPhysicalFragment& fragment = PhysicalFragment();
+  if (fragment.IsBox()) {
+    ToNGPhysicalBoxFragment(fragment).AddSelfOutlineRects(outline_rects,
+                                                          additional_offset);
+  }
 }
 
 void NGPaintFragment::PaintInlineBoxForDescendants(
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index ec683f3e..e838278 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -1963,6 +1963,22 @@
   return true;
 }
 
+LayoutRectOutsets ComputedStyle::BoxDecorationOutsets() const {
+  DCHECK(HasVisualOverflowingEffect());
+  LayoutRectOutsets outsets;
+
+  if (const ShadowList* box_shadow = BoxShadow())
+    outsets = LayoutRectOutsets(box_shadow->RectOutsetsIncludingOriginal());
+
+  if (HasBorderImageOutsets())
+    outsets.Unite(BorderImageOutsets());
+
+  if (HasMaskBoxImageOutsets())
+    outsets.Unite(MaskBoxImageOutsets());
+
+  return outsets;
+}
+
 void ComputedStyle::GetBorderEdgeInfo(BorderEdge edges[],
                                       bool include_logical_left_edge,
                                       bool include_logical_right_edge) const {
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index f9f46cb..12d6338 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -2171,6 +2171,8 @@
            BoxShadow();
   }
 
+  LayoutRectOutsets BoxDecorationOutsets() const;
+
   // Background utility functions.
   FillLayer& AccessBackgroundLayers() { return MutableBackgroundInternal(); }
   const FillLayer& BackgroundLayers() const { return BackgroundInternal(); }
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index 8afc038..e054a46 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -145,11 +145,12 @@
   "front_end/components/domBreakpointsSidebarPane.css",
   "front_end/components/DOMBreakpointsSidebarPane.js",
   "front_end/components/DOMPresentationUtils.js",
+  "front_end/components/Linkifier.js",
+  "front_end/components/TargetDetachedDialog.js",
+  "front_end/components/Reload.js",
   "front_end/components/domUtils.css",
   "front_end/components/imagePreview.css",
-  "front_end/components/Linkifier.js",
   "front_end/components/module.json",
-  "front_end/components/Reload.js",
   "front_end/console/ConsoleContextSelector.js",
   "front_end/console/ConsoleFilter.js",
   "front_end/console/ConsoleSidebar.js",
@@ -332,13 +333,14 @@
   "front_end/inspector_main/InspectorMain.js",
   "front_end/inspector_main/module.json",
   "front_end/inspector_main/nodeIcon.css",
-  "front_end/inspector_main/remoteDebuggingTerminatedScreen.css",
   "front_end/inspector_main/renderingOptions.css",
   "front_end/inspector_main/RenderingOptions.js",
   "front_end/inspector_main/RequestAppBannerActionDelegate.js",
-  "front_end/inspector_main/targetCrashedScreen.css",
   "front_end/integration_test_runner.js",
   "front_end/integration_test_runner.json",
+  "front_end/js_main/JsMain.js",
+  "front_end/js_main/module.json",
+  "front_end/js_profiler/module.json",
   "front_end/layer_viewer/layerDetailsView.css",
   "front_end/layer_viewer/LayerDetailsView.js",
   "front_end/layer_viewer/layers3DView.css",
@@ -361,12 +363,13 @@
   "front_end/main/SimpleApp.js",
   "front_end/mobile_throttling/MobileThrottlingSelector.js",
   "front_end/mobile_throttling/module.json",
+  "front_end/mobile_throttling/NetworkPanelIndicator.js",
   "front_end/mobile_throttling/NetworkThrottlingSelector.js",
   "front_end/mobile_throttling/ThrottlingManager.js",
   "front_end/mobile_throttling/ThrottlingPresets.js",
   "front_end/mobile_throttling/throttlingSettingsTab.css",
   "front_end/mobile_throttling/ThrottlingSettingsTab.js",
-  "front_end/ndb.json",
+  "front_end/ndb_app.json",
   "front_end/network/blockedURLsPane.css",
   "front_end/network/BlockedURLsPane.js",
   "front_end/network/eventSourceMessagesView.css",
@@ -528,6 +531,7 @@
   "front_end/screencast/ScreencastApp.js",
   "front_end/screencast/screencastView.css",
   "front_end/screencast/ScreencastView.js",
+  "front_end/sdk/ChildTargetManager.js",
   "front_end/sdk/Connections.js",
   "front_end/sdk/ContentProviders.js",
   "front_end/sdk/CookieModel.js",
@@ -777,6 +781,8 @@
   "front_end/ui/reportView.css",
   "front_end/ui/ReportView.js",
   "front_end/ui/ResizerWidget.js",
+  "front_end/ui/RemoteDebuggingTerminatedScreen.js",
+  "front_end/ui/remoteDebuggingTerminatedScreen.css",
   "front_end/ui/rootView.css",
   "front_end/ui/RootView.js",
   "front_end/ui/searchableView.css",
@@ -797,6 +803,8 @@
   "front_end/ui/SuggestBox.js",
   "front_end/ui/tabbedPane.css",
   "front_end/ui/TabbedPane.js",
+  "front_end/ui/TargetCrashedScreen.js",
+  "front_end/ui/targetCrashedScreen.css",
   "front_end/ui/textButton.css",
   "front_end/ui/TextEditor.js",
   "front_end/ui/textPrompt.css",
@@ -816,6 +824,8 @@
   "front_end/ui/XLink.js",
   "front_end/ui/XWidget.js",
   "front_end/ui/ZoomManager.js",
+  "front_end/worker_main/WorkerMain.js",
+  "front_end/worker_main/module.json",
   "front_end/worker_service/ServiceDispatcher.js",
   "front_end/workspace/FileManager.js",
   "front_end/workspace/module.json",
@@ -942,17 +952,34 @@
   "$resources_out_dir/SupportedCSSProperties.js",
 ]
 
+application_templates = [
+  "front_end/devtools_app.html",
+  "front_end/inspector.html",
+  "front_end/integration_test_runner.html",
+  "front_end/js_app.html",
+  "front_end/ndb_app.html",
+  "front_end/node_app.html",
+  "front_end/toolbox.html",
+  "front_end/worker_app.html",
+]
+
 generated_applications = [
   "$resources_out_dir/audits2_worker.js",
+  "$resources_out_dir/devtools_app.html",
+  "$resources_out_dir/devtools_app.js",
   "$resources_out_dir/formatter_worker.js",
   "$resources_out_dir/heap_snapshot_worker.js",
   "$resources_out_dir/inspector.html",
   "$resources_out_dir/inspector.js",
+  "$resources_out_dir/js_app.html",
+  "$resources_out_dir/js_app.js",
   "$resources_out_dir/node_app.html",
   "$resources_out_dir/node_app.js",
   "$resources_out_dir/shell.js",
   "$resources_out_dir/toolbox.html",
   "$resources_out_dir/toolbox.js",
+  "$resources_out_dir/worker_app.html",
+  "$resources_out_dir/worker_app.js",
 ]
 
 generated_non_autostart_non_remote_modules = [
@@ -974,6 +1001,7 @@
   "$resources_out_dir/heap_snapshot_model/heap_snapshot_model_module.js",
   "$resources_out_dir/help/help_module.js",
   "$resources_out_dir/inline_editor/inline_editor_module.js",
+  "$resources_out_dir/js_profiler/js_profiler_module.js",
   "$resources_out_dir/layer_viewer/layer_viewer_module.js",
   "$resources_out_dir/layers/layers_module.js",
   "$resources_out_dir/network/network_module.js",
@@ -1006,15 +1034,18 @@
 ]
 
 devtools_applications = [
-  "shell",
-  "inspector",
-  "toolbox",
-  "integration_test_runner",
-  "formatter_worker",
   "audits2_worker",
+  "devtools_app",
+  "formatter_worker",
   "heap_snapshot_worker",
-  "ndb",
+  "inspector",
+  "integration_test_runner",
+  "js_app",
+  "ndb_app",
   "node_app",
+  "shell",
+  "toolbox",
+  "worker_app",
 ]
 
 #-------------------------------------------------------------------------------
@@ -1150,14 +1181,8 @@
     "scripts/build/rjsmin.py",
   ]
 
-  inputs = helper_scripts + all_devtools_files + generated_scripts + [
-             "front_end/inspector.html",
-             "front_end/integration_test_runner.html",
-             "front_end/node_app.html",
-             "front_end/ndb.html",
-             "front_end/toolbox.html",
-           ]
-
+  inputs = helper_scripts + all_devtools_files + generated_scripts +
+           application_templates
   outputs = generated_resources + generated_remote_modules
 
   args = devtools_applications + [
@@ -1178,20 +1203,16 @@
       ":copy_generated_scripts",
     ]
 
-    inputs = all_devtools_files + [
-               "front_end/inspector.html",
-               "front_end/integration_test_runner.html",
-               "front_end/ndb.html",
-               "front_end/node_app.html",
-               "front_end/toolbox.html",
-             ]
-
+    inputs = all_devtools_files + application_templates
     outputs = [
+      "$resources_out_debug_dir/devtools_app.html",
       "$resources_out_debug_dir/inspector.html",
       "$resources_out_debug_dir/integration_test_runner.html",
-      "$resources_out_debug_dir/ndb.html",
+      "$resources_out_debug_dir/js_app.html",
+      "$resources_out_debug_dir/ndb_app.html",
       "$resources_out_debug_dir/node_app.html",
       "$resources_out_debug_dir/toolbox.html",
+      "$resources_out_debug_dir/worker_app.html",
     ]
 
     args = devtools_applications + [
diff --git a/third_party/WebKit/Source/devtools/front_end/components/TargetDetachedDialog.js b/third_party/WebKit/Source/devtools/front_end/components/TargetDetachedDialog.js
new file mode 100644
index 0000000..ba82f38
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/components/TargetDetachedDialog.js
@@ -0,0 +1,59 @@
+// Copyright 2018 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.
+
+/**
+ * @implements {Protocol.InspectorDispatcher}
+ */
+Components.TargetDetachedDialog = class extends SDK.SDKModel {
+  /**
+   * @param {!SDK.Target} target
+   */
+  constructor(target) {
+    super(target);
+    if (target.parentTarget())
+      return;
+    target.registerInspectorDispatcher(this);
+    target.inspectorAgent().enable();
+    this._hideCrashedDialog = null;
+    Components.TargetDetachedDialog._disconnectedScreenWithReasonWasShown = false;
+  }
+
+  /**
+   * @override
+   * @param {string} reason
+   */
+  detached(reason) {
+    Components.TargetDetachedDialog._disconnectedScreenWithReasonWasShown = true;
+    UI.RemoteDebuggingTerminatedScreen.show(reason);
+  }
+
+  static webSocketConnectionLost() {
+    UI.RemoteDebuggingTerminatedScreen.show('WebSocket disconnected');
+  }
+
+  /**
+   * @override
+   */
+  targetCrashed() {
+    var dialog = new UI.Dialog();
+    dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
+    dialog.addCloseButton();
+    dialog.setDimmed(true);
+    this._hideCrashedDialog = dialog.hide.bind(dialog);
+    new UI.TargetCrashedScreen(() => this._hideCrashedDialog = null).show(dialog.contentElement);
+    dialog.show();
+  }
+
+  /**
+   * @override;
+   */
+  targetReloadedAfterCrash() {
+    if (this._hideCrashedDialog) {
+      this._hideCrashedDialog.call(null);
+      this._hideCrashedDialog = null;
+    }
+  }
+};
+
+SDK.SDKModel.register(Components.TargetDetachedDialog, 0, true);
diff --git a/third_party/WebKit/Source/devtools/front_end/components/module.json b/third_party/WebKit/Source/devtools/front_end/components/module.json
index 03a5e3a..768443f 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/components/module.json
@@ -51,7 +51,8 @@
         "DOMPresentationUtils.js",
         "DockController.js",
         "Linkifier.js",
-        "Reload.js"
+        "Reload.js",
+        "TargetDetachedDialog.js"
     ],
     "resources": [
         "domBreakpointsSidebarPane.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/devices/module.json b/third_party/WebKit/Source/devtools/front_end/devices/module.json
index e50841f..4231f0a 100644
--- a/third_party/WebKit/Source/devtools/front_end/devices/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/devices/module.json
@@ -8,7 +8,6 @@
             "persistence": "closeable",
             "order": 50,
             "className": "Devices.DevicesView",
-            "condition": "!v8only",
             "tags": "usb, android, mobile"
         }
     ],
diff --git a/third_party/WebKit/Source/devtools/front_end/ndb.html b/third_party/WebKit/Source/devtools/front_end/devtools_app.html
similarity index 90%
rename from third_party/WebKit/Source/devtools/front_end/ndb.html
rename to third_party/WebKit/Source/devtools/front_end/devtools_app.html
index 3c7b338..c0b162b1 100644
--- a/third_party/WebKit/Source/devtools/front_end/ndb.html
+++ b/third_party/WebKit/Source/devtools/front_end/devtools_app.html
@@ -10,7 +10,7 @@
     <meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
     <meta name="referrer" content="no-referrer">
     <script type="text/javascript" src="Runtime.js"></script>
-    <script type="text/javascript" src="ndb.js"></script>
+    <script type="text/javascript" src="devtools_app.js"></script>
 </head>
 <body class="undocked" id="-blink-dev-tools"></body>
 </html>
diff --git a/third_party/WebKit/Source/devtools/front_end/ndb.js b/third_party/WebKit/Source/devtools/front_end/devtools_app.js
similarity index 79%
copy from third_party/WebKit/Source/devtools/front_end/ndb.js
copy to third_party/WebKit/Source/devtools/front_end/devtools_app.js
index a028d00e..17310fa 100644
--- a/third_party/WebKit/Source/devtools/front_end/ndb.js
+++ b/third_party/WebKit/Source/devtools/front_end/devtools_app.js
@@ -1,4 +1,4 @@
 // Copyright 2018 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.
-Runtime.startApplication('ndb');
+Runtime.startApplication('devtools_app');
diff --git a/third_party/WebKit/Source/devtools/front_end/devtools_app.json b/third_party/WebKit/Source/devtools/front_end/devtools_app.json
new file mode 100644
index 0000000..b25d72e
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/devtools_app.json
@@ -0,0 +1,27 @@
+{
+  "modules" : [
+    { "name": "emulation", "type": "autostart" },
+    { "name": "inspector_main", "type": "autostart" },
+    { "name": "mobile_throttling", "type": "autostart" },
+
+    { "name": "accessibility", "type": "remote" },
+    { "name": "animation" },
+    { "name": "audits2" },
+    { "name": "cookie_table" },
+    { "name": "devices" },
+    { "name": "elements" },
+    { "name": "emulated_devices" , "type": "remote" },
+    { "name": "har_importer" },
+    { "name": "help" },
+    { "name": "layers" },
+    { "name": "layer_viewer" },
+    { "name": "network" },
+    { "name": "product_registry_impl", "type": "remote" },
+    { "name": "resources" },
+    { "name": "security" },
+    { "name": "timeline" },
+    { "name": "timeline_model" }
+  ],
+  "extends": "shell",
+  "has_html": true
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/devtools_compatibility.js b/third_party/WebKit/Source/devtools/front_end/devtools_compatibility.js
index 812722b..48e10b1 100644
--- a/third_party/WebKit/Source/devtools/front_end/devtools_compatibility.js
+++ b/third_party/WebKit/Source/devtools/front_end/devtools_compatibility.js
@@ -1208,7 +1208,7 @@
   }
 
   function installBackwardsCompatibility() {
-    if (window.location.search.indexOf('remoteFrontend') === -1)
+    if (window.location.href.indexOf('/remote/') === -1)
       return;
 
     // Support for legacy (<M65) frontends.
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/AdvancedApp.js b/third_party/WebKit/Source/devtools/front_end/emulation/AdvancedApp.js
index 4bdeda200..c94b183 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/AdvancedApp.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/AdvancedApp.js
@@ -62,7 +62,7 @@
     if (this._toolboxWindow)
       return;
 
-    var url = window.location.href.replace('inspector.html', 'toolbox.html');
+    var url = window.location.href.replace('devtools_app.html', 'toolbox.html');
     this._toolboxWindow = window.open(url, undefined);
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/module.json b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
index 4a04675e..f39ff9ae 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
@@ -138,7 +138,6 @@
             "type": "action",
             "actionId": "emulation.show-sensors",
             "title": "Sensors",
-            "condition": "!v8only",
             "className": "Emulation.SensorsView.ShowActionDelegate"
         },
         {
@@ -146,7 +145,6 @@
             "location": "drawer-view",
             "id": "sensors",
             "title": "Sensors",
-            "condition": "!v8only",
             "persistence": "closeable",
             "order": 100,
             "className": "Emulation.SensorsView",
diff --git a/third_party/WebKit/Source/devtools/front_end/inspector.json b/third_party/WebKit/Source/devtools/front_end/inspector.json
index 557ff97..36c222f5 100644
--- a/third_party/WebKit/Source/devtools/front_end/inspector.json
+++ b/third_party/WebKit/Source/devtools/front_end/inspector.json
@@ -1,27 +1,7 @@
 {
   "modules" : [
-    { "name": "emulation", "type": "autostart" },
-    { "name": "mobile_throttling", "type": "autostart" },
-    { "name": "accessibility", "condition": "!v8only", "type": "remote" },
-    { "name": "animation", "condition": "!v8only" },
-    { "name": "audits2", "condition": "!v8only" },
-    { "name": "cookie_table" },
-    { "name": "devices" },
-    { "name": "elements", "condition": "!v8only" },
-    { "name": "emulated_devices", "condition": "!v8only" , "type": "remote" },
-    { "name": "har_importer", "condition": "!v8only" },
-    { "name": "help" },
-    { "name": "inspector_main", "type": "autostart" },
-    { "name": "layers", "condition": "!v8only" },
-    { "name": "layer_viewer", "condition": "!v8only" },
-    { "name": "network", "condition": "!v8only" },
-    { "name": "product_registry_impl", "condition": "!v8only", "type": "remote" },
-    { "name": "resources", "condition": "!v8only" },
-    { "name": "screencast", "condition": "remoteFrontend", "type": "remote" },
-    { "name": "security", "condition": "!v8only" },
-    { "name": "timeline", "condition": "!v8only" },
-    { "name": "timeline_model", "condition": "!v8only" }
+    { "name": "screencast", "type": "remote" }
   ],
-  "extends": "shell",
+  "extends": "devtools_app",
   "has_html": true
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/inspector_main/InspectorMain.js b/third_party/WebKit/Source/devtools/front_end/inspector_main/InspectorMain.js
index b0b1a60f..24da8b06 100644
--- a/third_party/WebKit/Source/devtools/front_end/inspector_main/InspectorMain.js
+++ b/third_party/WebKit/Source/devtools/front_end/inspector_main/InspectorMain.js
@@ -18,41 +18,33 @@
   run() {
     this._connectAndCreateMainTarget();
     InspectorFrontendHost.connectionReady();
+
     new InspectorMain.InspectedNodeRevealer();
-    new InspectorMain.NetworkPanelIndicator();
     new InspectorMain.SourcesPanelIndicator();
     new InspectorMain.BackendSettingsSync();
+    new MobileThrottling.NetworkPanelIndicator();
+
+    InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ReloadInspectedPage, event => {
+      var hard = /** @type {boolean} */ (event.data);
+      SDK.ResourceTreeModel.reloadAllPages(hard);
+    });
   }
 
   _connectAndCreateMainTarget() {
-    if (Runtime.queryParam('v8only'))
-      Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConnectToNodeJSDirectly);
-
     var target = SDK.targetManager.createTarget(
         'main', Common.UIString('Main'), this._capabilitiesForMainTarget(), this._createMainConnection.bind(this),
         null);
-
-    if (target.hasJSCapability())
-      target.runtimeAgent().runIfWaitingForDebugger();
+    target.runtimeAgent().runIfWaitingForDebugger();
   }
 
   /**
    * @return {number}
    */
   _capabilitiesForMainTarget() {
-    if (Runtime.queryParam('isSharedWorker')) {
-      return SDK.Target.Capability.Browser | SDK.Target.Capability.Inspector | SDK.Target.Capability.Log |
-          SDK.Target.Capability.Network | SDK.Target.Capability.Target;
-    }
-
-    if (Runtime.queryParam('v8only'))
-      return SDK.Target.Capability.JS;
-
     return SDK.Target.Capability.Browser | SDK.Target.Capability.DOM | SDK.Target.Capability.DeviceEmulation |
-        SDK.Target.Capability.Emulation | SDK.Target.Capability.Input | SDK.Target.Capability.Inspector |
-        SDK.Target.Capability.JS | SDK.Target.Capability.Log | SDK.Target.Capability.Network |
-        SDK.Target.Capability.ScreenCapture | SDK.Target.Capability.Security | SDK.Target.Capability.Target |
-        SDK.Target.Capability.Tracing;
+        SDK.Target.Capability.Emulation | SDK.Target.Capability.Input | SDK.Target.Capability.JS |
+        SDK.Target.Capability.Log | SDK.Target.Capability.Network | SDK.Target.Capability.ScreenCapture |
+        SDK.Target.Capability.Security | SDK.Target.Capability.Target | SDK.Target.Capability.Tracing;
   }
 
   /**
@@ -60,16 +52,8 @@
    * @return {!Protocol.InspectorBackend.Connection}
    */
   _createMainConnection(params) {
-    var wsParam = Runtime.queryParam('ws');
-    var wssParam = Runtime.queryParam('wss');
-    if (wsParam || wssParam) {
-      var ws = wsParam ? `ws://${wsParam}` : `wss://${wssParam}`;
-      this._mainConnection = new SDK.WebSocketConnection(ws, () => this._webSocketConnectionLost(), params);
-    } else if (InspectorFrontendHost.isHostedMode()) {
-      this._mainConnection = new SDK.StubConnection(params);
-    } else {
-      this._mainConnection = new SDK.MainConnection(params);
-    }
+    this._mainConnection =
+        SDK.createMainConnection(params, () => Components.TargetDetachedDialog.webSocketConnectionLost());
     return this._mainConnection;
   }
 
@@ -81,15 +65,6 @@
     var params = {onMessage: onMessage, onDisconnect: this._connectAndCreateMainTarget.bind(this)};
     return this._mainConnection.disconnect().then(this._createMainConnection.bind(this, params));
   }
-
-  _webSocketConnectionLost() {
-    if (!InspectorMain._disconnectedScreenWithReasonWasShown)
-      InspectorMain.RemoteDebuggingTerminatedScreen.show('WebSocket disconnected');
-  }
-};
-
-InspectorMain.InspectorMain.Events = {
-  AvailableTargetsChanged: Symbol('AvailableTargetsChanged')
 };
 
 /**
@@ -101,242 +76,6 @@
 };
 
 /**
- * @implements {Common.Runnable}
- */
-InspectorMain.InspectorMainLate = class {
-  /**
-   * @override
-   */
-  run() {
-    InspectorFrontendHost.events.addEventListener(
-        InspectorFrontendHostAPI.Events.ReloadInspectedPage, this._reloadInspectedPage, this);
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _reloadInspectedPage(event) {
-    var hard = /** @type {boolean} */ (event.data);
-    SDK.ResourceTreeModel.reloadAllPages(hard);
-  }
-};
-
-/**
- * @implements {Protocol.TargetDispatcher}
- */
-InspectorMain.BrowserChildTargetManager = class extends SDK.SDKModel {
-  /**
-   * @param {!SDK.Target} parentTarget
-   */
-  constructor(parentTarget) {
-    super(parentTarget);
-    this._targetManager = parentTarget.targetManager();
-    this._parentTarget = parentTarget;
-    this._targetAgent = parentTarget.targetAgent();
-    /** @type {!Map<string, !Protocol.Target.TargetInfo>} */
-    this._targetInfos = new Map();
-
-    /** @type {!Map<string, !SDK.ChildConnection>} */
-    this._childConnections = new Map();
-
-    parentTarget.registerTargetDispatcher(this);
-    this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true});
-
-    if (!parentTarget.parentTarget()) {
-      this._targetAgent.setDiscoverTargets(true);
-      this._targetAgent.setRemoteLocations([{host: 'localhost', port: 9229}]);
-    }
-  }
-
-  /**
-   * @override
-   * @return {!Promise}
-   */
-  suspendModel() {
-    return this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false});
-  }
-
-  /**
-   * @override
-   * @return {!Promise}
-   */
-  resumeModel() {
-    return this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true});
-  }
-
-  /**
-   * @override
-   */
-  dispose() {
-    for (var sessionId of this._childConnections.keys())
-      this.detachedFromTarget(sessionId, undefined);
-  }
-
-  /**
-   * @param {string} type
-   * @return {number}
-   */
-  _capabilitiesForType(type) {
-    if (type === 'worker')
-      return SDK.Target.Capability.JS | SDK.Target.Capability.Log | SDK.Target.Capability.Network;
-    if (type === 'service_worker')
-      return SDK.Target.Capability.Log | SDK.Target.Capability.Network | SDK.Target.Capability.Target;
-    if (type === 'iframe') {
-      return SDK.Target.Capability.Browser | SDK.Target.Capability.DOM | SDK.Target.Capability.JS |
-          SDK.Target.Capability.Log | SDK.Target.Capability.Network | SDK.Target.Capability.Target |
-          SDK.Target.Capability.Tracing | SDK.Target.Capability.Emulation | SDK.Target.Capability.Input;
-    }
-    return 0;
-  }
-
-  /**
-   * @override
-   * @param {!Protocol.Target.TargetInfo} targetInfo
-   */
-  targetCreated(targetInfo) {
-    this._targetInfos.set(targetInfo.targetId, targetInfo);
-    this._fireAvailableTargetsChanged();
-  }
-
-  /**
-   * @override
-   * @param {!Protocol.Target.TargetInfo} targetInfo
-   */
-  targetInfoChanged(targetInfo) {
-    this._targetInfos.set(targetInfo.targetId, targetInfo);
-    this._fireAvailableTargetsChanged();
-  }
-
-  /**
-   * @override
-   * @param {string} targetId
-   */
-  targetDestroyed(targetId) {
-    this._targetInfos.delete(targetId);
-    this._fireAvailableTargetsChanged();
-  }
-
-  _fireAvailableTargetsChanged() {
-    self.runtime.sharedInstance(InspectorMain.InspectorMain)
-        .dispatchEventToListeners(
-            InspectorMain.InspectorMain.Events.AvailableTargetsChanged, this._targetInfos.valuesArray());
-  }
-
-  /**
-   * @override
-   * @param {string} sessionId
-   * @param {!Protocol.Target.TargetInfo} targetInfo
-   * @param {boolean} waitingForDebugger
-   */
-  attachedToTarget(sessionId, targetInfo, waitingForDebugger) {
-    var targetName = '';
-    if (targetInfo.type !== 'iframe') {
-      var parsedURL = targetInfo.url.asParsedURL();
-      targetName = parsedURL ? parsedURL.lastPathComponentWithFragment() :
-                               '#' + (++InspectorMain.BrowserChildTargetManager._lastAnonymousTargetId);
-    }
-    var target = this._targetManager.createTarget(
-        targetInfo.targetId, targetName, this._capabilitiesForType(targetInfo.type),
-        this._createChildConnection.bind(this, this._targetAgent, sessionId), this._parentTarget);
-
-    // Only pause the new worker if debugging SW - we are going through the pause on start checkbox.
-    if (!this._parentTarget.parentTarget() && Runtime.queryParam('isSharedWorker') && waitingForDebugger) {
-      var debuggerModel = target.model(SDK.DebuggerModel);
-      if (debuggerModel)
-        debuggerModel.pause();
-    }
-    target.runtimeAgent().runIfWaitingForDebugger();
-  }
-
-  /**
-   * @override
-   * @param {string} sessionId
-   * @param {string=} childTargetId
-   */
-  detachedFromTarget(sessionId, childTargetId) {
-    this._childConnections.get(sessionId).onDisconnect.call(null, 'target terminated');
-    this._childConnections.delete(sessionId);
-  }
-
-  /**
-   * @override
-   * @param {string} sessionId
-   * @param {string} message
-   * @param {string=} childTargetId
-   */
-  receivedMessageFromTarget(sessionId, message, childTargetId) {
-    var connection = this._childConnections.get(sessionId);
-    if (connection)
-      connection.onMessage.call(null, message);
-  }
-
-  /**
-   * @param {!Protocol.TargetAgent} agent
-   * @param {string} sessionId
-   * @param {!Protocol.InspectorBackend.Connection.Params} params
-   * @return {!Protocol.InspectorBackend.Connection}
-   */
-  _createChildConnection(agent, sessionId, params) {
-    var connection = new SDK.ChildConnection(agent, sessionId, params);
-    this._childConnections.set(sessionId, connection);
-    return connection;
-  }
-};
-
-InspectorMain.BrowserChildTargetManager._lastAnonymousTargetId = 0;
-
-SDK.SDKModel.register(InspectorMain.BrowserChildTargetManager, SDK.Target.Capability.Target, true);
-
-/**
- * @implements {Protocol.InspectorDispatcher}
- */
-InspectorMain.InspectorModel = class extends SDK.SDKModel {
-  /**
-   * @param {!SDK.Target} target
-   */
-  constructor(target) {
-    super(target);
-    target.registerInspectorDispatcher(this);
-    target.inspectorAgent().enable();
-    this._hideCrashedDialog = null;
-  }
-
-  /**
-   * @override
-   * @param {string} reason
-   */
-  detached(reason) {
-    InspectorMain._disconnectedScreenWithReasonWasShown = true;
-    InspectorMain.RemoteDebuggingTerminatedScreen.show(reason);
-  }
-
-  /**
-   * @override
-   */
-  targetCrashed() {
-    var dialog = new UI.Dialog();
-    dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
-    dialog.addCloseButton();
-    dialog.setDimmed(true);
-    this._hideCrashedDialog = dialog.hide.bind(dialog);
-    new InspectorMain.TargetCrashedScreen(() => this._hideCrashedDialog = null).show(dialog.contentElement);
-    dialog.show();
-  }
-
-  /**
-   * @override;
-   */
-  targetReloadedAfterCrash() {
-    if (this._hideCrashedDialog) {
-      this._hideCrashedDialog.call(null);
-      this._hideCrashedDialog = null;
-    }
-  }
-};
-
-SDK.SDKModel.register(InspectorMain.InspectorModel, SDK.Target.Capability.Inspector, true);
-
-/**
  * @implements {UI.ActionDelegate}
  * @unrestricted
  */
@@ -390,7 +129,7 @@
     this._button.setTitle(Common.UIString('Open dedicated DevTools for Node.js'));
     self.runtime.sharedInstance(InspectorMain.InspectorMain)
         .addEventListener(
-            InspectorMain.InspectorMain.Events.AvailableTargetsChanged,
+            SDK.TargetManager.Events.AvailableTargetsChanged,
             event => this._update(/** @type {!Array<!Protocol.Target.TargetInfo>} */ (event.data)));
     this._button.setVisible(false);
     this._update([]);
@@ -415,34 +154,6 @@
   }
 };
 
-InspectorMain.NetworkPanelIndicator = class {
-  constructor() {
-    // TODO: we should not access network from other modules.
-    if (!UI.inspectorView.hasPanel('network'))
-      return;
-    var manager = SDK.multitargetNetworkManager;
-    manager.addEventListener(SDK.MultitargetNetworkManager.Events.ConditionsChanged, updateVisibility);
-    manager.addEventListener(SDK.MultitargetNetworkManager.Events.BlockedPatternsChanged, updateVisibility);
-    manager.addEventListener(SDK.MultitargetNetworkManager.Events.InterceptorsChanged, updateVisibility);
-    updateVisibility();
-
-    function updateVisibility() {
-      var icon = null;
-      if (manager.isThrottling()) {
-        icon = UI.Icon.create('smallicon-warning');
-        icon.title = Common.UIString('Network throttling is enabled');
-      } else if (SDK.multitargetNetworkManager.isIntercepting()) {
-        icon = UI.Icon.create('smallicon-warning');
-        icon.title = Common.UIString('Requests may be rewritten');
-      } else if (manager.isBlocking()) {
-        icon = UI.Icon.create('smallicon-warning');
-        icon.title = Common.UIString('Requests may be blocked');
-      }
-      UI.inspectorView.setPanelIcon('network', icon);
-    }
-  }
-};
-
 /**
  * @unrestricted
  */
@@ -482,64 +193,6 @@
 };
 
 /**
- * @unrestricted
- */
-InspectorMain.RemoteDebuggingTerminatedScreen = class extends UI.VBox {
-  /**
-   * @param {string} reason
-   */
-  constructor(reason) {
-    super(true);
-    this.registerRequiredCSS('inspector_main/remoteDebuggingTerminatedScreen.css');
-    var message = this.contentElement.createChild('div', 'message');
-    message.createChild('span').textContent = Common.UIString('Debugging connection was closed. Reason: ');
-    message.createChild('span', 'reason').textContent = reason;
-    this.contentElement.createChild('div', 'message').textContent =
-        Common.UIString('Reconnect when ready by reopening DevTools.');
-    var button = UI.createTextButton(Common.UIString('Reconnect DevTools'), () => window.location.reload());
-    this.contentElement.createChild('div', 'button').appendChild(button);
-  }
-
-  /**
-   * @param {string} reason
-   */
-  static show(reason) {
-    var dialog = new UI.Dialog();
-    dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
-    dialog.addCloseButton();
-    dialog.setDimmed(true);
-    new InspectorMain.RemoteDebuggingTerminatedScreen(reason).show(dialog.contentElement);
-    dialog.show();
-  }
-};
-
-/**
- * @unrestricted
- */
-InspectorMain.TargetCrashedScreen = class extends UI.VBox {
-  /**
-   * @param {function()} hideCallback
-   */
-  constructor(hideCallback) {
-    super(true);
-    this.registerRequiredCSS('inspector_main/targetCrashedScreen.css');
-    this.contentElement.createChild('div', 'message').textContent =
-        Common.UIString('DevTools was disconnected from the page.');
-    this.contentElement.createChild('div', 'message').textContent =
-        Common.UIString('Once page is reloaded, DevTools will automatically reconnect.');
-    this._hideCallback = hideCallback;
-  }
-
-  /**
-   * @override
-   */
-  willHide() {
-    this._hideCallback.call(null);
-  }
-};
-
-
-/**
  * @implements {SDK.TargetManager.Observer}
  * @unrestricted
  */
@@ -585,3 +238,5 @@
   targetRemoved(target) {
   }
 };
+
+SDK.ChildTargetManager.install();
diff --git a/third_party/WebKit/Source/devtools/front_end/inspector_main/module.json b/third_party/WebKit/Source/devtools/front_end/inspector_main/module.json
index a0f7a2a9..24aa03bb 100644
--- a/third_party/WebKit/Source/devtools/front_end/inspector_main/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/inspector_main/module.json
@@ -5,10 +5,6 @@
             "className": "InspectorMain.InspectorMain"
         },
         {
-            "type": "late-initialization",
-            "className": "InspectorMain.InspectorMainLate"
-        },
-        {
             "type": "action",
             "category": "Navigation",
             "actionId": "inspector_main.reload",
@@ -52,26 +48,6 @@
         {
             "type": "setting",
             "category": "Network",
-            "title": "Disable cache (while DevTools is open)",
-            "settingName": "cacheDisabled",
-            "settingType": "boolean",
-            "order": 0,
-            "defaultValue": false,
-            "userActionCondition": "hasOtherClients",
-            "options": [
-                {
-                    "value": true,
-                    "title": "Disable cache (while DevTools is open)"
-                },
-                {
-                    "value": false,
-                    "title": "Enable cache"
-                }
-            ]
-        },
-        {
-            "type": "setting",
-            "category": "Network",
             "title": "Force ad blocking on this site",
             "settingName": "network.adBlockingEnabled",
             "settingType": "boolean",
@@ -130,7 +106,6 @@
             "title": "Rendering",
             "persistence": "closeable",
             "order": 50,
-            "condition": "!v8only",
             "className": "InspectorMain.RenderingOptionsView"
         },
         {
@@ -142,7 +117,8 @@
         }
     ],
     "dependencies": [
-        "components"
+        "components",
+        "mobile_throttling"
     ],
     "scripts": [
         "RenderingOptions.js",
@@ -151,8 +127,6 @@
     ],
     "resources": [
         "nodeIcon.css",
-        "remoteDebuggingTerminatedScreen.css",
-        "renderingOptions.css",
-        "targetCrashedScreen.css"
+        "renderingOptions.css"
     ]
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json
index c9d46181..0d10106 100644
--- a/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json
+++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json
@@ -23,6 +23,6 @@
     { "name": "security_test_runner" },
     { "name": "sources_test_runner" }
   ],
-  "extends": "inspector",
+  "extends": "devtools_app",
   "has_html": true
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/ndb.html b/third_party/WebKit/Source/devtools/front_end/js_app.html
similarity index 90%
copy from third_party/WebKit/Source/devtools/front_end/ndb.html
copy to third_party/WebKit/Source/devtools/front_end/js_app.html
index 3c7b338..dff8942 100644
--- a/third_party/WebKit/Source/devtools/front_end/ndb.html
+++ b/third_party/WebKit/Source/devtools/front_end/js_app.html
@@ -10,7 +10,7 @@
     <meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
     <meta name="referrer" content="no-referrer">
     <script type="text/javascript" src="Runtime.js"></script>
-    <script type="text/javascript" src="ndb.js"></script>
+    <script type="text/javascript" src="js_app.js"></script>
 </head>
 <body class="undocked" id="-blink-dev-tools"></body>
 </html>
diff --git a/third_party/WebKit/Source/devtools/front_end/ndb.js b/third_party/WebKit/Source/devtools/front_end/js_app.js
similarity index 81%
rename from third_party/WebKit/Source/devtools/front_end/ndb.js
rename to third_party/WebKit/Source/devtools/front_end/js_app.js
index a028d00e..11427a08 100644
--- a/third_party/WebKit/Source/devtools/front_end/ndb.js
+++ b/third_party/WebKit/Source/devtools/front_end/js_app.js
@@ -1,4 +1,4 @@
 // Copyright 2018 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.
-Runtime.startApplication('ndb');
+Runtime.startApplication('js_app');
diff --git a/third_party/WebKit/Source/devtools/front_end/js_app.json b/third_party/WebKit/Source/devtools/front_end/js_app.json
new file mode 100644
index 0000000..3e9deed9
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/js_app.json
@@ -0,0 +1,8 @@
+{
+  "modules" : [
+    { "name": "js_main", "type": "autostart" },
+    { "name": "js_profiler" }
+  ],
+  "extends": "shell",
+  "has_html": true
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/js_main/JsMain.js b/third_party/WebKit/Source/devtools/front_end/js_main/JsMain.js
new file mode 100644
index 0000000..1cdd4c6
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/js_main/JsMain.js
@@ -0,0 +1,27 @@
+// Copyright 2018 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.
+
+/**
+ * @implements {Common.Runnable}
+ */
+JsMain.JsMain = class extends Common.Object {
+  /**
+   * @override
+   */
+  run() {
+    Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConnectToNodeJSDirectly);
+    var target = SDK.targetManager.createTarget(
+        'main', Common.UIString('Main'), SDK.Target.Capability.JS, this._createMainConnection.bind(this), null);
+    target.runtimeAgent().runIfWaitingForDebugger();
+    InspectorFrontendHost.connectionReady();
+  }
+
+  /**
+   * @param {!Protocol.InspectorBackend.Connection.Params} params
+   * @return {!Protocol.InspectorBackend.Connection}
+   */
+  _createMainConnection(params) {
+    return SDK.createMainConnection(params, () => Components.TargetDetachedDialog.webSocketConnectionLost());
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/js_main/module.json b/third_party/WebKit/Source/devtools/front_end/js_main/module.json
new file mode 100644
index 0000000..5ea75e6b
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/js_main/module.json
@@ -0,0 +1,14 @@
+{
+    "extensions": [
+        {
+            "type": "early-initialization",
+            "className": "JsMain.JsMain"
+        }
+    ],
+    "dependencies": [
+        "components"
+    ],
+    "scripts": [
+        "JsMain.js"
+    ]
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/js_profiler/module.json b/third_party/WebKit/Source/devtools/front_end/js_profiler/module.json
new file mode 100644
index 0000000..fb092193
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/js_profiler/module.json
@@ -0,0 +1,15 @@
+{
+    "extensions": [
+        {
+            "type": "view",
+            "location": "panel",
+            "id": "js_profiler",
+            "title": "Profiler",
+            "order": 65,
+            "className": "Profiler.JSProfilerPanel"
+        }
+    ],
+    "dependencies": [
+        "profiler"
+    ]
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index bc2c8b7..ee032fa 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -144,7 +144,7 @@
   /**
    * @suppressGlobalPropertiesCheck
    */
-  _createAppUI() {
+  async _createAppUI() {
     Main.Main.time('Main._createAppUI');
 
     UI.viewManager = new UI.ViewManager();
@@ -207,7 +207,18 @@
     this._registerForwardedShortcuts();
     this._registerMessageSinkListener();
 
-    self.runtime.extension(Common.AppProvider).instance().then(this._showAppUI.bind(this));
+    // Pick first app we could instantiate (for test harness).
+    for (var extension of self.runtime.extensions(Common.AppProvider)) {
+      try {
+        var instance = await extension.instance();
+        if (instance) {
+          this._showAppUI(instance);
+          break;
+        }
+      } catch (e) {
+        console.error(e);
+      }
+    }
     Main.Main.timeEnd('Main._createAppUI');
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/mobile_throttling/NetworkPanelIndicator.js b/third_party/WebKit/Source/devtools/front_end/mobile_throttling/NetworkPanelIndicator.js
new file mode 100644
index 0000000..95765165
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/mobile_throttling/NetworkPanelIndicator.js
@@ -0,0 +1,31 @@
+// Copyright 2017 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.
+
+MobileThrottling.NetworkPanelIndicator = class {
+  constructor() {
+    // TODO: we should not access network from other modules.
+    if (!UI.inspectorView.hasPanel('network'))
+      return;
+    var manager = SDK.multitargetNetworkManager;
+    manager.addEventListener(SDK.MultitargetNetworkManager.Events.ConditionsChanged, updateVisibility);
+    manager.addEventListener(SDK.MultitargetNetworkManager.Events.BlockedPatternsChanged, updateVisibility);
+    manager.addEventListener(SDK.MultitargetNetworkManager.Events.InterceptorsChanged, updateVisibility);
+    updateVisibility();
+
+    function updateVisibility() {
+      var icon = null;
+      if (manager.isThrottling()) {
+        icon = UI.Icon.create('smallicon-warning');
+        icon.title = Common.UIString('Network throttling is enabled');
+      } else if (SDK.multitargetNetworkManager.isIntercepting()) {
+        icon = UI.Icon.create('smallicon-warning');
+        icon.title = Common.UIString('Requests may be rewritten');
+      } else if (manager.isBlocking()) {
+        icon = UI.Icon.create('smallicon-warning');
+        icon.title = Common.UIString('Requests may be blocked');
+      }
+      UI.inspectorView.setPanelIcon('network', icon);
+    }
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/mobile_throttling/module.json b/third_party/WebKit/Source/devtools/front_end/mobile_throttling/module.json
index a06d017d..217bc85 100644
--- a/third_party/WebKit/Source/devtools/front_end/mobile_throttling/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/mobile_throttling/module.json
@@ -43,6 +43,7 @@
     "scripts": [
         "ThrottlingPresets.js",
         "MobileThrottlingSelector.js",
+        "NetworkPanelIndicator.js",
         "NetworkThrottlingSelector.js",
         "ThrottlingSettingsTab.js",
         "ThrottlingManager.js"
diff --git a/third_party/WebKit/Source/devtools/front_end/ndb.html b/third_party/WebKit/Source/devtools/front_end/ndb_app.html
similarity index 90%
copy from third_party/WebKit/Source/devtools/front_end/ndb.html
copy to third_party/WebKit/Source/devtools/front_end/ndb_app.html
index 3c7b338..13977f75 100644
--- a/third_party/WebKit/Source/devtools/front_end/ndb.html
+++ b/third_party/WebKit/Source/devtools/front_end/ndb_app.html
@@ -10,7 +10,7 @@
     <meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
     <meta name="referrer" content="no-referrer">
     <script type="text/javascript" src="Runtime.js"></script>
-    <script type="text/javascript" src="ndb.js"></script>
+    <script type="text/javascript" src="ndb_app.js"></script>
 </head>
 <body class="undocked" id="-blink-dev-tools"></body>
 </html>
diff --git a/third_party/WebKit/Source/devtools/front_end/ndb.js b/third_party/WebKit/Source/devtools/front_end/ndb_app.js
similarity index 81%
copy from third_party/WebKit/Source/devtools/front_end/ndb.js
copy to third_party/WebKit/Source/devtools/front_end/ndb_app.js
index a028d00e..c3eb0e5 100644
--- a/third_party/WebKit/Source/devtools/front_end/ndb.js
+++ b/third_party/WebKit/Source/devtools/front_end/ndb_app.js
@@ -1,4 +1,4 @@
 // Copyright 2018 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.
-Runtime.startApplication('ndb');
+Runtime.startApplication('ndb_app');
diff --git a/third_party/WebKit/Source/devtools/front_end/ndb.json b/third_party/WebKit/Source/devtools/front_end/ndb_app.json
similarity index 100%
rename from third_party/WebKit/Source/devtools/front_end/ndb.json
rename to third_party/WebKit/Source/devtools/front_end/ndb_app.json
diff --git a/third_party/WebKit/Source/devtools/front_end/node_app.json b/third_party/WebKit/Source/devtools/front_end/node_app.json
index fa90b10..d0342ad2 100644
--- a/third_party/WebKit/Source/devtools/front_end/node_app.json
+++ b/third_party/WebKit/Source/devtools/front_end/node_app.json
@@ -1,7 +1,8 @@
 {
   "modules" : [
-     { "name": "node_main", "type": "autostart" }
- ],
+    { "name": "node_main", "type": "autostart" },
+    { "name": "js_profiler" }
+  ],
   "extends": "shell",
   "has_html": true
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/module.json b/third_party/WebKit/Source/devtools/front_end/profiler/module.json
index 9d608572..7e6d7328 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/module.json
@@ -9,25 +9,6 @@
             "className": "Profiler.HeapProfilerPanel"
         },
         {
-            "type": "view",
-            "location": "panel",
-            "id": "js_profiler",
-            "title": "Profiler",
-            "order": 65,
-            "className": "Profiler.JSProfilerPanel",
-            "condition": "v8only"
-        },
-        {
-            "type": "view",
-            "location": "panel",
-            "id": "js_profiler",
-            "title": "JavaScript Profiler",
-            "persistence": "closeable",
-            "order": 65,
-            "className": "Profiler.JSProfilerPanel",
-            "condition": "!v8only"
-        },
-        {
             "type": "@UI.ContextMenu.Provider",
             "contextTypes": [
                 "SDK.RemoteObject"
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/module.json b/third_party/WebKit/Source/devtools/front_end/screencast/module.json
index 7ae80c0a..9dbb35d7 100644
--- a/third_party/WebKit/Source/devtools/front_end/screencast/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/screencast/module.json
@@ -13,7 +13,6 @@
         },
         {
             "type": "context-menu-item",
-            "condition": "remoteFrontend",
             "location": "mainMenu",
             "order": 10,
             "actionId": "components.request-app-banner"
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ChildTargetManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/ChildTargetManager.js
new file mode 100644
index 0000000..07b635d8
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/ChildTargetManager.js
@@ -0,0 +1,173 @@
+// Copyright 2018 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.
+
+/**
+ * @implements {Protocol.TargetDispatcher}
+ */
+SDK.ChildTargetManager = class extends SDK.SDKModel {
+  /**
+   * @param {!SDK.Target} parentTarget
+   */
+  constructor(parentTarget) {
+    super(parentTarget);
+    this._targetManager = parentTarget.targetManager();
+    this._parentTarget = parentTarget;
+    this._targetAgent = parentTarget.targetAgent();
+    /** @type {!Map<string, !Protocol.Target.TargetInfo>} */
+    this._targetInfos = new Map();
+
+    /** @type {!Map<string, !SDK.ChildConnection>} */
+    this._childConnections = new Map();
+
+    parentTarget.registerTargetDispatcher(this);
+    this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true});
+
+    if (!parentTarget.parentTarget()) {
+      this._targetAgent.setDiscoverTargets(true);
+      this._targetAgent.setRemoteLocations([{host: 'localhost', port: 9229}]);
+    }
+  }
+
+  /**
+   * @param {function({target: !SDK.Target, waitingForDebugger: boolean})=} attachCallback
+   */
+  static install(attachCallback) {
+    SDK.ChildTargetManager._attachCallback = attachCallback;
+    SDK.SDKModel.register(SDK.ChildTargetManager, SDK.Target.Capability.Target, true);
+  }
+
+  /**
+   * @override
+   * @return {!Promise}
+   */
+  suspendModel() {
+    return this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false});
+  }
+
+  /**
+   * @override
+   * @return {!Promise}
+   */
+  resumeModel() {
+    return this._targetAgent.invoke_setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true});
+  }
+
+  /**
+   * @override
+   */
+  dispose() {
+    for (var sessionId of this._childConnections.keys())
+      this.detachedFromTarget(sessionId, undefined);
+  }
+
+  /**
+   * @param {string} type
+   * @return {number}
+   */
+  _capabilitiesForType(type) {
+    if (type === 'worker')
+      return SDK.Target.Capability.JS | SDK.Target.Capability.Log | SDK.Target.Capability.Network;
+    if (type === 'service_worker')
+      return SDK.Target.Capability.Log | SDK.Target.Capability.Network | SDK.Target.Capability.Target;
+    if (type === 'iframe') {
+      return SDK.Target.Capability.Browser | SDK.Target.Capability.DOM | SDK.Target.Capability.JS |
+          SDK.Target.Capability.Log | SDK.Target.Capability.Network | SDK.Target.Capability.Target |
+          SDK.Target.Capability.Tracing | SDK.Target.Capability.Emulation | SDK.Target.Capability.Input;
+    }
+    return 0;
+  }
+
+  /**
+   * @override
+   * @param {!Protocol.Target.TargetInfo} targetInfo
+   */
+  targetCreated(targetInfo) {
+    this._targetInfos.set(targetInfo.targetId, targetInfo);
+    this._fireAvailableTargetsChanged();
+  }
+
+  /**
+   * @override
+   * @param {!Protocol.Target.TargetInfo} targetInfo
+   */
+  targetInfoChanged(targetInfo) {
+    this._targetInfos.set(targetInfo.targetId, targetInfo);
+    this._fireAvailableTargetsChanged();
+  }
+
+  /**
+   * @override
+   * @param {string} targetId
+   */
+  targetDestroyed(targetId) {
+    this._targetInfos.delete(targetId);
+    this._fireAvailableTargetsChanged();
+  }
+
+  _fireAvailableTargetsChanged() {
+    SDK.targetManager.dispatchEventToListeners(
+        SDK.TargetManager.Events.AvailableTargetsChanged, this._targetInfos.valuesArray());
+  }
+
+  /**
+   * @override
+   * @param {string} sessionId
+   * @param {!Protocol.Target.TargetInfo} targetInfo
+   * @param {boolean} waitingForDebugger
+   */
+  attachedToTarget(sessionId, targetInfo, waitingForDebugger) {
+    var targetName = '';
+    if (targetInfo.type !== 'iframe') {
+      var parsedURL = targetInfo.url.asParsedURL();
+      targetName = parsedURL ? parsedURL.lastPathComponentWithFragment() :
+                               '#' + (++SDK.ChildTargetManager._lastAnonymousTargetId);
+    }
+    var target = this._targetManager.createTarget(
+        targetInfo.targetId, targetName, this._capabilitiesForType(targetInfo.type),
+        this._createChildConnection.bind(this, this._targetAgent, sessionId), this._parentTarget);
+
+    if (SDK.ChildTargetManager._attachCallback)
+      SDK.ChildTargetManager._attachCallback({target, waitingForDebugger});
+    target.runtimeAgent().runIfWaitingForDebugger();
+  }
+
+  /**
+   * @override
+   * @param {string} sessionId
+   * @param {string=} childTargetId
+   */
+  detachedFromTarget(sessionId, childTargetId) {
+    this._childConnections.get(sessionId).onDisconnect.call(null, 'target terminated');
+    this._childConnections.delete(sessionId);
+  }
+
+  /**
+   * @override
+   * @param {string} sessionId
+   * @param {string} message
+   * @param {string=} childTargetId
+   */
+  receivedMessageFromTarget(sessionId, message, childTargetId) {
+    var connection = this._childConnections.get(sessionId);
+    if (connection)
+      connection.onMessage.call(null, message);
+  }
+
+  /**
+   * @param {!Protocol.TargetAgent} agent
+   * @param {string} sessionId
+   * @param {!Protocol.InspectorBackend.Connection.Params} params
+   * @return {!Protocol.InspectorBackend.Connection}
+   */
+  _createChildConnection(agent, sessionId, params) {
+    var connection = new SDK.ChildConnection(agent, sessionId, params);
+    this._childConnections.set(sessionId, connection);
+    return connection;
+  }
+};
+
+SDK.ChildTargetManager._lastAnonymousTargetId = 0;
+
+/** @type {function({target: !SDK.Target, waitingForDebugger: boolean})|undefined} */
+SDK.ChildTargetManager._attachCallback;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/Connections.js b/third_party/WebKit/Source/devtools/front_end/sdk/Connections.js
index 230f1ce2..f538784 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/Connections.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/Connections.js
@@ -237,3 +237,22 @@
     throw 'Not implemented';
   }
 };
+
+/**
+ * @param {!Protocol.InspectorBackend.Connection.Params} params
+ * @param {function()} connectionLostCallback
+ * @return {!Protocol.InspectorBackend.Connection}
+ */
+SDK.createMainConnection = function(params, connectionLostCallback) {
+  var wsParam = Runtime.queryParam('ws');
+  var wssParam = Runtime.queryParam('wss');
+
+  if (wsParam || wssParam) {
+    var ws = wsParam ? `ws://${wsParam}` : `wss://${wssParam}`;
+    return new SDK.WebSocketConnection(ws, connectionLostCallback, params);
+  }
+
+  if (InspectorFrontendHost.isHostedMode())
+    return new SDK.StubConnection(params);
+  return new SDK.MainConnection(params);
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
index bd7611cc..daa8ad6 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
@@ -43,11 +43,7 @@
     if (Common.moduleSetting('cacheDisabled').get())
       this._networkAgent.setCacheDisabled(true);
 
-    // Limit buffer when talking to a remote device.
-    if (Runtime.queryParam('remoteFrontend') || Runtime.queryParam('ws'))
-      this._networkAgent.enable(10000000, 5000000, SDK.NetworkManager.MAX_EAGER_POST_REQUEST_BODY_LENGTH);
-    else
-      this._networkAgent.enable(undefined, undefined, SDK.NetworkManager.MAX_EAGER_POST_REQUEST_BODY_LENGTH);
+    this._networkAgent.enable(undefined, undefined, SDK.NetworkManager.MAX_EAGER_POST_REQUEST_BODY_LENGTH);
 
     this._bypassServiceWorkerSetting = Common.settings.createSetting('bypassServiceWorker', false);
     if (this._bypassServiceWorkerSetting.get())
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
index 1d88b82..72bbfa8 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
@@ -285,6 +285,7 @@
 
 /** @enum {symbol} */
 SDK.TargetManager.Events = {
+  AvailableTargetsChanged: Symbol('AvailableTargetsChanged'),
   InspectedURLChanged: Symbol('InspectedURLChanged'),
   NameChanged: Symbol('NameChanged'),
   SuspendStateChanged: Symbol('SuspendStateChanged')
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/module.json b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
index f72ac2b..df1c638 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
@@ -230,6 +230,26 @@
                     "title": "Disable request blocking"
                 }
             ]
+        },
+        {
+            "type": "setting",
+            "category": "Network",
+            "title": "Disable cache (while DevTools is open)",
+            "settingName": "cacheDisabled",
+            "settingType": "boolean",
+            "order": 0,
+            "defaultValue": false,
+            "userActionCondition": "hasOtherClients",
+            "options": [
+                {
+                    "value": true,
+                    "title": "Disable cache (while DevTools is open)"
+                },
+                {
+                    "value": false,
+                    "title": "Enable cache"
+                }
+            ]
         }
     ],
     "scripts": [
@@ -251,6 +271,7 @@
         "CSSRule.js",
         "CSSStyleDeclaration.js",
         "CSSStyleSheetHeader.js",
+        "ChildTargetManager.js",
         "DOMDebuggerModel.js",
         "DOMModel.js",
         "DebuggerModel.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/module.json b/third_party/WebKit/Source/devtools/front_end/timeline/module.json
index 7426be2e..21b2a83 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/module.json
@@ -181,6 +181,15 @@
                     "shortcut": "Meta+Y"
                 }
             ]
+        },
+        {
+            "type": "view",
+            "location": "panel",
+            "id": "js_profiler",
+            "title": "JavaScript Profiler",
+            "persistence": "closeable",
+            "order": 65,
+            "className": "Profiler.JSProfilerPanel"
         }
     ],
     "dependencies": [
@@ -191,6 +200,7 @@
         "extensions",
         "data_grid",
         "product_registry",
+        "profiler",
         "mobile_throttling"
     ],
     "scripts": [
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/RemoteDebuggingTerminatedScreen.js b/third_party/WebKit/Source/devtools/front_end/ui/RemoteDebuggingTerminatedScreen.js
new file mode 100644
index 0000000..1821175c
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/ui/RemoteDebuggingTerminatedScreen.js
@@ -0,0 +1,32 @@
+// Copyright 2018 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.
+
+UI.RemoteDebuggingTerminatedScreen = class extends UI.VBox {
+  /**
+   * @param {string} reason
+   */
+  constructor(reason) {
+    super(true);
+    this.registerRequiredCSS('ui/remoteDebuggingTerminatedScreen.css');
+    var message = this.contentElement.createChild('div', 'message');
+    message.createChild('span').textContent = Common.UIString('Debugging connection was closed. Reason: ');
+    message.createChild('span', 'reason').textContent = reason;
+    this.contentElement.createChild('div', 'message').textContent =
+        Common.UIString('Reconnect when ready by reopening DevTools.');
+    var button = UI.createTextButton(Common.UIString('Reconnect DevTools'), () => window.location.reload());
+    this.contentElement.createChild('div', 'button').appendChild(button);
+  }
+
+  /**
+   * @param {string} reason
+   */
+  static show(reason) {
+    var dialog = new UI.Dialog();
+    dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
+    dialog.addCloseButton();
+    dialog.setDimmed(true);
+    new UI.RemoteDebuggingTerminatedScreen(reason).show(dialog.contentElement);
+    dialog.show();
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TargetCrashedScreen.js b/third_party/WebKit/Source/devtools/front_end/ui/TargetCrashedScreen.js
new file mode 100644
index 0000000..5d0f2a1
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/ui/TargetCrashedScreen.js
@@ -0,0 +1,25 @@
+// Copyright 2018 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.
+
+UI.TargetCrashedScreen = class extends UI.VBox {
+  /**
+   * @param {function()} hideCallback
+   */
+  constructor(hideCallback) {
+    super(true);
+    this.registerRequiredCSS('ui/targetCrashedScreen.css');
+    this.contentElement.createChild('div', 'message').textContent =
+        Common.UIString('DevTools was disconnected from the page.');
+    this.contentElement.createChild('div', 'message').textContent =
+        Common.UIString('Once page is reloaded, DevTools will automatically reconnect.');
+    this._hideCallback = hideCallback;
+  }
+
+  /**
+   * @override
+   */
+  willHide() {
+    this._hideCallback.call(null);
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/module.json b/third_party/WebKit/Source/devtools/front_end/ui/module.json
index ec0c9740..fca3c687 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/ui/module.json
@@ -37,6 +37,7 @@
         "Popover.js",
         "ProgressIndicator.js",
         "ResizerWidget.js",
+        "RemoteDebuggingTerminatedScreen.js",
         "ReportView.js",
         "RootView.js",
         "SearchableView.js",
@@ -44,6 +45,7 @@
         "SoftContextMenu.js",
         "SoftDropDown.js",
         "SplitWidget.js",
+        "TargetCrashedScreen.js",
         "TextPrompt.js",
         "ThrottledWidget.js",
         "Toolbar.js",
@@ -79,10 +81,10 @@
         "popover.css",
         "progressIndicator.css",
         "radioButton.css",
+        "remoteDebuggingTerminatedScreen.css",
         "reportView.css",
         "rootView.css",
         "searchableView.css",
-        "viewContainers.css",
         "slider.css",
         "smallBubble.css",
         "softContextMenu.css",
@@ -92,9 +94,11 @@
         "toolbar.css",
         "suggestBox.css",
         "tabbedPane.css",
+        "targetCrashedScreen.css",
         "textButton.css",
         "textPrompt.css",
         "tooltip.css",
-        "treeoutline.css"
+        "treeoutline.css",
+        "viewContainers.css"
     ]
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/inspector_main/remoteDebuggingTerminatedScreen.css b/third_party/WebKit/Source/devtools/front_end/ui/remoteDebuggingTerminatedScreen.css
similarity index 100%
rename from third_party/WebKit/Source/devtools/front_end/inspector_main/remoteDebuggingTerminatedScreen.css
rename to third_party/WebKit/Source/devtools/front_end/ui/remoteDebuggingTerminatedScreen.css
diff --git a/third_party/WebKit/Source/devtools/front_end/inspector_main/targetCrashedScreen.css b/third_party/WebKit/Source/devtools/front_end/ui/targetCrashedScreen.css
similarity index 100%
rename from third_party/WebKit/Source/devtools/front_end/inspector_main/targetCrashedScreen.css
rename to third_party/WebKit/Source/devtools/front_end/ui/targetCrashedScreen.css
diff --git a/third_party/WebKit/Source/devtools/front_end/ndb.html b/third_party/WebKit/Source/devtools/front_end/worker_app.html
similarity index 90%
copy from third_party/WebKit/Source/devtools/front_end/ndb.html
copy to third_party/WebKit/Source/devtools/front_end/worker_app.html
index 3c7b338..82f8321 100644
--- a/third_party/WebKit/Source/devtools/front_end/ndb.html
+++ b/third_party/WebKit/Source/devtools/front_end/worker_app.html
@@ -10,7 +10,7 @@
     <meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
     <meta name="referrer" content="no-referrer">
     <script type="text/javascript" src="Runtime.js"></script>
-    <script type="text/javascript" src="ndb.js"></script>
+    <script type="text/javascript" src="worker_app.js"></script>
 </head>
 <body class="undocked" id="-blink-dev-tools"></body>
 </html>
diff --git a/third_party/WebKit/Source/devtools/front_end/ndb.js b/third_party/WebKit/Source/devtools/front_end/worker_app.js
similarity index 79%
copy from third_party/WebKit/Source/devtools/front_end/ndb.js
copy to third_party/WebKit/Source/devtools/front_end/worker_app.js
index a028d00e..4cd27a8 100644
--- a/third_party/WebKit/Source/devtools/front_end/ndb.js
+++ b/third_party/WebKit/Source/devtools/front_end/worker_app.js
@@ -1,4 +1,5 @@
 // Copyright 2018 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.
-Runtime.startApplication('ndb');
+
+Runtime.startApplication('worker_app');
diff --git a/third_party/WebKit/Source/devtools/front_end/worker_app.json b/third_party/WebKit/Source/devtools/front_end/worker_app.json
new file mode 100644
index 0000000..4b5ae2f
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/worker_app.json
@@ -0,0 +1,18 @@
+{
+  "modules" : [
+    { "name": "mobile_throttling", "type": "autostart"  },
+    { "name": "worker_main", "type": "autostart" },
+
+    { "name": "cookie_table" },
+    { "name": "har_importer" },
+    { "name": "help" },
+    { "name": "layer_viewer" },
+    { "name": "network" },
+    { "name": "product_registry_impl", "type": "remote" },
+    { "name": "resources" },
+    { "name": "timeline" },
+    { "name": "timeline_model" }
+  ],
+  "extends": "shell",
+  "has_html": true
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/worker_main/WorkerMain.js b/third_party/WebKit/Source/devtools/front_end/worker_main/WorkerMain.js
new file mode 100644
index 0000000..5c19613a
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/worker_main/WorkerMain.js
@@ -0,0 +1,38 @@
+// Copyright 2018 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.
+
+/**
+ * @implements {Common.Runnable}
+ */
+WorkerMain.WorkerMain = class extends Common.Object {
+  /**
+   * @override
+   */
+  run() {
+    var capabilities = SDK.Target.Capability.Browser | SDK.Target.Capability.Log | SDK.Target.Capability.Network |
+        SDK.Target.Capability.Target;
+    SDK.targetManager.createTarget(
+        'main', Common.UIString('Main'), capabilities, this._createMainConnection.bind(this), null);
+    InspectorFrontendHost.connectionReady();
+    new MobileThrottling.NetworkPanelIndicator();
+  }
+
+  /**
+   * @param {!Protocol.InspectorBackend.Connection.Params} params
+   * @return {!Protocol.InspectorBackend.Connection}
+   */
+  _createMainConnection(params) {
+    return SDK.createMainConnection(params, () => Components.TargetDetachedDialog.webSocketConnectionLost());
+  }
+};
+
+SDK.ChildTargetManager.install(({target, waitingForDebugger}) => {
+  var parentTarget = target.parentTarget();
+  // Only pause the new worker if debugging SW - we are going through the pause on start checkbox.
+  if (!parentTarget.parentTarget() && waitingForDebugger) {
+    var debuggerModel = target.model(SDK.DebuggerModel);
+    if (debuggerModel)
+      debuggerModel.pause();
+  }
+});
diff --git a/third_party/WebKit/Source/devtools/front_end/worker_main/module.json b/third_party/WebKit/Source/devtools/front_end/worker_main/module.json
new file mode 100644
index 0000000..4029b308
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/worker_main/module.json
@@ -0,0 +1,15 @@
+{
+    "extensions": [
+        {
+            "type": "early-initialization",
+            "className": "WorkerMain.WorkerMain"
+        }
+    ],
+    "dependencies": [
+        "components",
+        "mobile_throttling"
+    ],
+    "scripts": [
+        "WorkerMain.js"
+    ]
+}
diff --git a/third_party/WebKit/Source/devtools/scripts/check_gn.js b/third_party/WebKit/Source/devtools/scripts/check_gn.js
index 73553c9..2df36ad 100644
--- a/third_party/WebKit/Source/devtools/scripts/check_gn.js
+++ b/third_party/WebKit/Source/devtools/scripts/check_gn.js
@@ -7,8 +7,11 @@
 const path = require('path');
 
 const FRONTEND_PATH = path.resolve(__dirname, '..', 'front_end');
-const inspectorManifest = require(path.resolve(FRONTEND_PATH, 'inspector.json'));
-const shellManifest = require(path.resolve(FRONTEND_PATH, 'shell.json'));
+
+const manifestModules = [];
+for (var config of ['inspector.json', 'devtools_app.json', 'js_app.json', 'node_app.json', 'shell.json', 'worker_app.json'])
+  manifestModules.push(...require(path.resolve(FRONTEND_PATH, config)).modules);
+
 const utils = require('./utils');
 
 const gnPath = path.resolve(__dirname, '..', 'BUILD.gn');
@@ -46,7 +49,7 @@
     ];
   }
   const text = lines.join('\n');
-  const modules = inspectorManifest.modules.concat(shellManifest.modules).filter(m => m.type !== 'autostart' && m.type !== 'remote').map(m => m.name);
+  const modules = manifestModules.filter(m => m.type !== 'autostart' && m.type !== 'remote').map(m => m.name);
 
   const missingModules = modules.filter(m => !utils.includes(text, `${m}/${m}_module.js`));
   if (missingModules.length)
diff --git a/third_party/WebKit/Source/modules/canvas/BUILD.gn b/third_party/WebKit/Source/modules/canvas/BUILD.gn
index bf252f5a..e8f3c22a 100644
--- a/third_party/WebKit/Source/modules/canvas/BUILD.gn
+++ b/third_party/WebKit/Source/modules/canvas/BUILD.gn
@@ -25,6 +25,8 @@
     "canvas2d/HitRegion.cpp",
     "canvas2d/HitRegion.h",
     "canvas2d/Path2D.h",
+    "htmlcanvas/CanvasContextCreationAttributesHelpers.cpp",
+    "htmlcanvas/CanvasContextCreationAttributesHelpers.h",
     "htmlcanvas/HTMLCanvasElementModule.cpp",
     "htmlcanvas/HTMLCanvasElementModule.h",
     "imagebitmap/ImageBitmapRenderingContext.cpp",
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
index 94de909..1e89cab 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
@@ -112,7 +112,7 @@
 
 CanvasRenderingContext2D::CanvasRenderingContext2D(
     HTMLCanvasElement* canvas,
-    const CanvasContextCreationAttributes& attrs)
+    const CanvasContextCreationAttributesCore& attrs)
     : CanvasRenderingContext(canvas, attrs),
       context_lost_mode_(kNotLostContext),
       context_restorable_(true),
@@ -804,7 +804,7 @@
     return;
 
   // Currently, SkPictureImageFilter does not support subpixel text
-  // anti-aliasing, which is expected when !creationAttributes().alpha(), so we
+  // anti-aliasing, which is expected when !creationAttributes().alpha, so we
   // need to fall out of display list mode when drawing text to an opaque
   // canvas. crbug.com/583809
   if (!IsComposited()) {
@@ -914,7 +914,7 @@
 
 void CanvasRenderingContext2D::getContextAttributes(
     CanvasRenderingContext2DSettings& settings) const {
-  settings.setAlpha(CreationAttributes().alpha());
+  settings.setAlpha(CreationAttributes().alpha);
   settings.setColorSpace(ColorSpaceAsString());
   settings.setPixelFormat(PixelFormatAsString());
 }
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
index 1fface0..31ffaa7e 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
@@ -27,7 +27,7 @@
 #ifndef CanvasRenderingContext2D_h
 #define CanvasRenderingContext2D_h
 
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/html/canvas/CanvasRenderingContextFactory.h"
 #include "core/style/FilterOperations.h"
@@ -79,7 +79,7 @@
 
     CanvasRenderingContext* Create(
         CanvasRenderingContextHost* host,
-        const CanvasContextCreationAttributes& attrs) override {
+        const CanvasContextCreationAttributesCore& attrs) override {
       DCHECK(!host->IsOffscreenCanvas());
       return new CanvasRenderingContext2D(static_cast<HTMLCanvasElement*>(host),
                                           attrs);
@@ -214,7 +214,7 @@
   friend class CanvasRenderingContext2DAutoRestoreSkCanvas;
 
   CanvasRenderingContext2D(HTMLCanvasElement*,
-                           const CanvasContextCreationAttributes&);
+                           const CanvasContextCreationAttributesCore&);
   void DispatchContextLostEvent(TimerBase*);
   void DispatchContextRestoredEvent(TimerBase*);
   void TryRestoreContextEvent(TimerBase*);
@@ -246,7 +246,7 @@
   bool Is2d() const override { return true; }
   bool IsComposited() const override;
   bool IsAccelerated() const override;
-  bool HasAlpha() const override { return CreationAttributes().alpha(); }
+  bool HasAlpha() const override { return CreationAttributes().alpha; }
   void SetIsHidden(bool) override;
   void Stop() final;
 
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DAPITest.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DAPITest.cpp
index b5087ae..ec1fc28 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DAPITest.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DAPITest.cpp
@@ -52,8 +52,8 @@
 
 void CanvasRenderingContext2DAPITest::CreateContext(OpacityMode opacity_mode) {
   String canvas_type("2d");
-  CanvasContextCreationAttributes attributes;
-  attributes.setAlpha(opacity_mode == kNonOpaque);
+  CanvasContextCreationAttributesCore attributes;
+  attributes.alpha = opacity_mode == kNonOpaque;
   canvas_element_->GetCanvasRenderingContext(canvas_type, attributes);
   Context2d();  // Calling this for the checks
 }
@@ -298,8 +298,8 @@
       ToHTMLCanvasElement(document.getElementById("canvas"));
 
   String canvas_type("2d");
-  CanvasContextCreationAttributes attributes;
-  attributes.setAlpha(true);
+  CanvasContextCreationAttributesCore attributes;
+  attributes.alpha = true;
   canvas->GetCanvasRenderingContext(canvas_type, attributes);
 
   EXPECT_NE(nullptr, canvas->RenderingContext());
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp
index e1e26c4..2eff91a 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -185,12 +185,12 @@
     String color_space,
     LinearPixelMathState LinearPixelMath_state) {
   String canvas_type("2d");
-  CanvasContextCreationAttributes attributes;
-  attributes.setAlpha(opacity_mode == kNonOpaque);
+  CanvasContextCreationAttributesCore attributes;
+  attributes.alpha = opacity_mode == kNonOpaque;
   if (!color_space.IsEmpty()) {
-    attributes.setColorSpace(color_space);
+    attributes.color_space = color_space;
     if (LinearPixelMath_state == kLinearPixelMathEnabled) {
-      attributes.setPixelFormat("float16");
+      attributes.pixel_format = "float16";
     }
   }
   canvas_element_->GetCanvasRenderingContext(canvas_type, attributes);
@@ -533,7 +533,7 @@
     image_bitmap_derived = ImageBitmap::Create(image_bitmap_from_canvas,
                                                crop_rect, default_options);
   }
-  CanvasContextCreationAttributes attributes;
+  CanvasContextCreationAttributesCore attributes;
   CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(
       canvas->GetCanvasRenderingContext("2d", attributes));
   DummyExceptionStateForTesting exception_state;
@@ -576,7 +576,7 @@
   // Creating a different accelerated image buffer
   HTMLCanvasElement* anotherCanvas =
       ToHTMLCanvasElement(GetDocument().getElementById("d"));
-  CanvasContextCreationAttributes attributes;
+  CanvasContextCreationAttributesCore attributes;
   anotherCanvas->GetCanvasRenderingContext("2d", attributes);
   IntSize size2(10, 5);
   auto fake_accelerate_surface2 = std::make_unique<FakeCanvas2DLayerBridge>(
@@ -840,9 +840,9 @@
 
   Persistent<HTMLCanvasElement> canvas =
       Persistent<HTMLCanvasElement>(CanvasElement());
-  CanvasContextCreationAttributes attributes;
-  attributes.setAlpha(true);
-  attributes.setColorSpace("srgb");
+  CanvasContextCreationAttributesCore attributes;
+  attributes.alpha = true;
+  attributes.color_space = "srgb";
   CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(
       canvas->GetCanvasRenderingContext("2d", attributes));
   StringOrCanvasGradientOrCanvasPattern fill_style;
@@ -1056,10 +1056,10 @@
 
       // Create a canvas and call putImageData and getImageData to make sure
       // the conversion is done correctly.
-      CanvasContextCreationAttributes attributes;
-      attributes.setAlpha(true);
-      attributes.setColorSpace(canvas_color_space_names[k]);
-      attributes.setPixelFormat(canvas_pixel_format_names[k]);
+      CanvasContextCreationAttributesCore attributes;
+      attributes.alpha = true;
+      attributes.color_space = canvas_color_space_names[k];
+      attributes.pixel_format = canvas_pixel_format_names[k];
       CanvasRenderingContext2D* context =
           static_cast<CanvasRenderingContext2D*>(
               canvas_element.GetCanvasRenderingContext("2d", attributes));
diff --git a/third_party/WebKit/Source/modules/canvas/htmlcanvas/CanvasContextCreationAttributesHelpers.cpp b/third_party/WebKit/Source/modules/canvas/htmlcanvas/CanvasContextCreationAttributesHelpers.cpp
new file mode 100644
index 0000000..878084a
--- /dev/null
+++ b/third_party/WebKit/Source/modules/canvas/htmlcanvas/CanvasContextCreationAttributesHelpers.cpp
@@ -0,0 +1,30 @@
+// Copyright 2018 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 "modules/canvas/htmlcanvas/CanvasContextCreationAttributesHelpers.h"
+
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
+#include "modules/canvas/htmlcanvas/CanvasContextCreationAttributesModule.h"
+#include "third_party/WebKit/Source/modules/xr/XRDevice.h"
+
+namespace blink {
+
+CanvasContextCreationAttributesCore ToCanvasContextCreationAttributes(
+    const CanvasContextCreationAttributesModule& attrs) {
+  CanvasContextCreationAttributesCore result;
+  result.alpha = attrs.alpha();
+  result.antialias = attrs.antialias();
+  result.color_space = attrs.colorSpace();
+  result.depth = attrs.depth();
+  result.fail_if_major_performance_caveat =
+      attrs.failIfMajorPerformanceCaveat();
+  result.low_latency = attrs.lowLatency();
+  result.pixel_format = attrs.pixelFormat();
+  result.premultiplied_alpha = attrs.premultipliedAlpha();
+  result.preserve_drawing_buffer = attrs.preserveDrawingBuffer();
+  result.stencil = attrs.stencil();
+  result.compatible_xr_device = attrs.compatibleXRDevice();
+  return result;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/canvas/htmlcanvas/CanvasContextCreationAttributesHelpers.h b/third_party/WebKit/Source/modules/canvas/htmlcanvas/CanvasContextCreationAttributesHelpers.h
new file mode 100644
index 0000000..0d1c243
--- /dev/null
+++ b/third_party/WebKit/Source/modules/canvas/htmlcanvas/CanvasContextCreationAttributesHelpers.h
@@ -0,0 +1,18 @@
+// Copyright 2018 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 CanvasContextCreationAttributesHelpers_h
+#define CanvasContextCreationAttributesHelpers_h
+
+namespace blink {
+
+class CanvasContextCreationAttributesCore;
+class CanvasContextCreationAttributesModule;
+
+CanvasContextCreationAttributesCore ToCanvasContextCreationAttributes(
+    const CanvasContextCreationAttributesModule&);
+
+}  // namespace blink
+
+#endif  // CanvasContextCreationAttributesHelpers_h
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasContextCreationAttributes.idl b/third_party/WebKit/Source/modules/canvas/htmlcanvas/CanvasContextCreationAttributesModule.idl
similarity index 93%
rename from third_party/WebKit/Source/core/html/canvas/CanvasContextCreationAttributes.idl
rename to third_party/WebKit/Source/modules/canvas/htmlcanvas/CanvasContextCreationAttributesModule.idl
index c1519c5..7419bb2 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasContextCreationAttributes.idl
+++ b/third_party/WebKit/Source/modules/canvas/htmlcanvas/CanvasContextCreationAttributesModule.idl
@@ -21,12 +21,6 @@
 //
 // N.B.: Web IDL doesn't support multiple inheritance of dictionaries.
 
-enum CanvasColorSpace {
-    "srgb", // default
-    "rec2020",
-    "p3",
-};
-
 enum CanvasPixelFormat {
     "8-8-8-8", // default
     "10-10-10-2",
@@ -35,7 +29,7 @@
 };
 
 [PermissiveDictionaryConversion]
-dictionary CanvasContextCreationAttributes {
+dictionary CanvasContextCreationAttributesModule {
     // This is an experimental feature, but it is not hidden behind a flag in
     // the bindings because origin trial bindings don't work in extensions.
     // The trial's runtime flag is instead checked inside
@@ -54,4 +48,5 @@
     boolean premultipliedAlpha = true;
     boolean preserveDrawingBuffer = false;
     boolean failIfMajorPerformanceCaveat = false;
+    [RuntimeEnabled=WebXR] XRDevice compatibleXRDevice = null;
 };
diff --git a/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.cpp b/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.cpp
index 05eb15e..cde2ea0 100644
--- a/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.cpp
+++ b/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.cpp
@@ -5,16 +5,17 @@
 #include "modules/canvas/htmlcanvas/HTMLCanvasElementModule.h"
 
 #include "core/dom/DOMNodeIds.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/offscreencanvas/OffscreenCanvas.h"
+#include "modules/canvas/htmlcanvas/CanvasContextCreationAttributesHelpers.h"
+#include "modules/canvas/htmlcanvas/CanvasContextCreationAttributesModule.h"
 
 namespace blink {
 
 void HTMLCanvasElementModule::getContext(
     HTMLCanvasElement& canvas,
     const String& type,
-    const CanvasContextCreationAttributes& attributes,
+    const CanvasContextCreationAttributesModule& attributes,
     ExceptionState& exception_state,
     RenderingContext& result) {
   if (canvas.SurfaceLayerBridge()) {
@@ -27,8 +28,8 @@
     return;
   }
 
-  CanvasRenderingContext* context =
-      canvas.GetCanvasRenderingContext(type, attributes);
+  CanvasRenderingContext* context = canvas.GetCanvasRenderingContext(
+      type, ToCanvasContextCreationAttributes(attributes));
   if (context) {
     context->SetCanvasGetContextResult(result);
   }
diff --git a/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.h b/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.h
index 93df98d..1d7a7330 100644
--- a/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.h
+++ b/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.h
@@ -11,7 +11,7 @@
 
 namespace blink {
 
-class CanvasContextCreationAttributes;
+class CanvasContextCreationAttributesModule;
 class HTMLCanvasElement;
 class OffscreenCanvas;
 
@@ -23,7 +23,7 @@
  public:
   static void getContext(HTMLCanvasElement&,
                          const String&,
-                         const CanvasContextCreationAttributes&,
+                         const CanvasContextCreationAttributesModule&,
                          ExceptionState&,
                          RenderingContext&);
   static OffscreenCanvas* transferControlToOffscreen(HTMLCanvasElement&,
diff --git a/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.idl b/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.idl
index b60a5fa..0b7bbf2 100644
--- a/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.idl
+++ b/third_party/WebKit/Source/modules/canvas/htmlcanvas/HTMLCanvasElementModule.idl
@@ -19,6 +19,6 @@
     // requires throwing TypeError if the incoming argument is not an object type
     // (and is not undefined or null). The binding must ignore this.
     // Related spec issue: https://github.com/whatwg/html/issues/595
-    [RaisesException] RenderingContext? getContext(DOMString contextId, [PermissiveDictionaryConversion] optional CanvasContextCreationAttributes attributes);
+    [RaisesException] RenderingContext? getContext(DOMString contextId, [PermissiveDictionaryConversion] optional CanvasContextCreationAttributesModule attributes);
     [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException, MeasureAs=OffscreenCanvas] OffscreenCanvas transferControlToOffscreen();
 };
diff --git a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContext.cpp b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContext.cpp
index 611604cc..65da402 100644
--- a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContext.cpp
+++ b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContext.cpp
@@ -12,7 +12,7 @@
 
 ImageBitmapRenderingContext::ImageBitmapRenderingContext(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attrs)
+    const CanvasContextCreationAttributesCore& attrs)
     : ImageBitmapRenderingContextBase(host, attrs) {}
 
 ImageBitmapRenderingContext::~ImageBitmapRenderingContext() = default;
@@ -36,7 +36,7 @@
 
 CanvasRenderingContext* ImageBitmapRenderingContext::Factory::Create(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attrs) {
+    const CanvasContextCreationAttributesCore& attrs) {
   if (!RuntimeEnabledFeatures::ExperimentalCanvasFeaturesEnabled())
     return nullptr;
   return new ImageBitmapRenderingContext(host, attrs);
diff --git a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContext.h b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContext.h
index f6bb5b3..44d9999 100644
--- a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContext.h
+++ b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContext.h
@@ -28,7 +28,7 @@
 
     CanvasRenderingContext* Create(
         CanvasRenderingContextHost*,
-        const CanvasContextCreationAttributes&) override;
+        const CanvasContextCreationAttributesCore&) override;
     CanvasRenderingContext::ContextType GetContextType() const override {
       return CanvasRenderingContext::kContextImageBitmap;
     }
@@ -48,7 +48,7 @@
 
  private:
   ImageBitmapRenderingContext(CanvasRenderingContextHost*,
-                              const CanvasContextCreationAttributes&);
+                              const CanvasContextCreationAttributesCore&);
 };
 
 DEFINE_TYPE_CASTS(ImageBitmapRenderingContext,
diff --git a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.cpp b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.cpp
index 6ddf07e..af9c6cb5 100644
--- a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.cpp
@@ -16,10 +16,10 @@
 
 ImageBitmapRenderingContextBase::ImageBitmapRenderingContextBase(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attrs)
+    const CanvasContextCreationAttributesCore& attrs)
     : CanvasRenderingContext(host, attrs),
       image_layer_bridge_(
-          new ImageLayerBridge(attrs.alpha() ? kNonOpaque : kOpaque)) {}
+          new ImageLayerBridge(attrs.alpha ? kNonOpaque : kOpaque)) {}
 
 ImageBitmapRenderingContextBase::~ImageBitmapRenderingContextBase() = default;
 
diff --git a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.h b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.h
index 4c1db86..2725998 100644
--- a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.h
@@ -19,7 +19,7 @@
     : public CanvasRenderingContext {
  public:
   ImageBitmapRenderingContextBase(CanvasRenderingContextHost*,
-                                  const CanvasContextCreationAttributes&);
+                                  const CanvasContextCreationAttributesCore&);
   virtual ~ImageBitmapRenderingContextBase();
 
   void Trace(blink::Visitor*);
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.cpp b/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.cpp
index 45e62895..fe508fa 100644
--- a/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.cpp
+++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.cpp
@@ -5,8 +5,9 @@
 #include "modules/canvas/offscreencanvas/OffscreenCanvasModule.h"
 
 #include "core/dom/ExecutionContext.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
 #include "core/offscreencanvas/OffscreenCanvas.h"
+#include "modules/canvas/htmlcanvas/CanvasContextCreationAttributesHelpers.h"
+#include "modules/canvas/htmlcanvas/CanvasContextCreationAttributesModule.h"
 #include "modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h"
 
 namespace blink {
@@ -15,7 +16,7 @@
     ExecutionContext* execution_context,
     OffscreenCanvas& offscreen_canvas,
     const String& id,
-    const CanvasContextCreationAttributes& attributes,
+    const CanvasContextCreationAttributesModule& attributes,
     ExceptionState& exception_state,
     OffscreenRenderingContext& result) {
   if (offscreen_canvas.IsNeutered()) {
@@ -27,7 +28,7 @@
   // OffscreenCanvas cannot be transferred after getContext, so this execution
   // context will always be the right one from here on.
   CanvasRenderingContext* context = offscreen_canvas.GetCanvasRenderingContext(
-      execution_context, id, attributes);
+      execution_context, id, ToCanvasContextCreationAttributes(attributes));
   if (context)
     context->SetOffscreenCanvasGetContextResult(result);
 }
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.h b/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.h
index eb7897cc..0fc137f9 100644
--- a/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.h
+++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.h
@@ -13,7 +13,7 @@
 
 namespace blink {
 
-class CanvasContextCreationAttributes;
+class CanvasContextCreationAttributesModule;
 class OffscreenCanvas;
 
 class MODULES_EXPORT OffscreenCanvasModule {
@@ -23,7 +23,7 @@
   static void getContext(ExecutionContext*,
                          OffscreenCanvas&,
                          const String&,
-                         const CanvasContextCreationAttributes&,
+                         const CanvasContextCreationAttributesModule&,
                          ExceptionState&,
                          OffscreenRenderingContext&);
 };
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.idl b/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.idl
index 33041ab..f122f96 100644
--- a/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.idl
+++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasModule.idl
@@ -12,5 +12,5 @@
 [
     ImplementedAs=OffscreenCanvasModule
 ] partial interface OffscreenCanvas {
-    [CallWith=ExecutionContext, RaisesException, RuntimeEnabled=ExperimentalCanvasFeatures] OffscreenRenderingContext? getContext(OffscreenRenderingContextType contextType, optional CanvasContextCreationAttributes attributes);
+    [CallWith=ExecutionContext, RaisesException, RuntimeEnabled=ExperimentalCanvasFeatures] OffscreenRenderingContext? getContext(OffscreenRenderingContextType contextType, optional CanvasContextCreationAttributesModule attributes);
 };
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasTest.cpp b/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasTest.cpp
index 328b9075..4500bfe 100644
--- a/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas/OffscreenCanvasTest.cpp
@@ -69,7 +69,7 @@
   DummyExceptionStateForTesting exception_state;
   offscreen_canvas_ = HTMLCanvasElementModule::transferControlToOffscreen(
       *canvas_element_, exception_state);
-  CanvasContextCreationAttributes attrs;
+  CanvasContextCreationAttributesCore attrs;
   context_ = static_cast<OffscreenCanvasRenderingContext2D*>(
       offscreen_canvas_->GetCanvasRenderingContext(&GetDocument(), String("2d"),
                                                    attrs));
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
index 85ae77ed..ee1282e4 100644
--- a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
@@ -29,7 +29,7 @@
 
 OffscreenCanvasRenderingContext2D::OffscreenCanvasRenderingContext2D(
     OffscreenCanvas* canvas,
-    const CanvasContextCreationAttributes& attrs)
+    const CanvasContextCreationAttributesCore& attrs)
     : CanvasRenderingContext(canvas, attrs) {
   ExecutionContext* execution_context = canvas->GetTopExecutionContext();
   if (execution_context->IsDocument()) {
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h
index e76e909..fc1597b 100644
--- a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h
+++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h
@@ -6,7 +6,7 @@
 #define OffscreenCanvasRenderingContext2D_h
 
 #include <memory>
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/html/canvas/CanvasRenderingContextFactory.h"
 #include "modules/canvas/canvas2d/BaseRenderingContext2D.h"
@@ -31,7 +31,7 @@
 
     CanvasRenderingContext* Create(
         CanvasRenderingContextHost* host,
-        const CanvasContextCreationAttributes& attrs) override {
+        const CanvasContextCreationAttributesCore& attrs) override {
       DCHECK(host->IsOffscreenCanvas());
       return new OffscreenCanvasRenderingContext2D(
           static_cast<OffscreenCanvas*>(host), attrs);
@@ -107,7 +107,7 @@
 
   void ValidateStateStack() const final;
 
-  bool HasAlpha() const final { return CreationAttributes().alpha(); }
+  bool HasAlpha() const final { return CreationAttributes().alpha; }
   bool isContextLost() const override;
 
   ImageBitmap* TransferToImageBitmap(ScriptState*) final;
@@ -117,7 +117,7 @@
  protected:
   OffscreenCanvasRenderingContext2D(
       OffscreenCanvas*,
-      const CanvasContextCreationAttributes& attrs);
+      const CanvasContextCreationAttributesCore& attrs);
 
   virtual void NeedsFinalizeFrame() {
     CanvasRenderingContext::NeedsFinalizeFrame();
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/mediaInterstitials.css b/third_party/WebKit/Source/modules/media_controls/resources/mediaInterstitials.css
index d6eb09e1..e88476d 100644
--- a/third_party/WebKit/Source/modules/media_controls/resources/mediaInterstitials.css
+++ b/third_party/WebKit/Source/modules/media_controls/resources/mediaInterstitials.css
@@ -37,11 +37,9 @@
     filter: grayscale(100%) blur(5px) opacity(40%);
 }
 
-video::-internal-media-remoting-cast-icon {
+video::-internal-media-remoting-cast-icon,
+video::-internal-picture-in-picture-icon {
     -webkit-appearance: none;
-    background-image: -webkit-image-set(
-      url(default_100_percent/legacy/mediaremoting_cast.png) 1x,
-      url(default_200_percent/legacy/mediaremoting_cast.png) 2x);
     background-size: 100% 100%;
     background-repeat: no-repeat;
     background-position: center center;
@@ -57,8 +55,7 @@
     top: calc(50% - 3vw);
 }
 
-video::-internal-media-remoting-cast-text-message,
-video::-internal-picture-in-picture-message {
+video::-internal-media-interstitial-message {
     display: inline;
     position: absolute;
     top: calc(50% + 1vw);
@@ -74,10 +71,6 @@
     margin: 0px;
 }
 
-video::-internal-picture-in-picture-message {
-    top: calc(50%);
-}
-
 video::-internal-media-remoting-toast-message {
     display: inline;
     position: absolute;
@@ -94,3 +87,14 @@
     padding: 10pt 24pt 10pt 24pt;
     margin: 0px;
 }
+
+video::-internal-media-remoting-cast-icon {
+  background-image: -webkit-image-set(
+    url(default_100_percent/legacy/mediaremoting_cast.png) 1x,
+    url(default_200_percent/legacy/mediaremoting_cast.png) 2x);
+}
+
+video::-internal-picture-in-picture-icon {
+  background-image: -webkit-image-set(
+    url(default_100_percent/legacy/mediaplayer_pictureinpicture.png) 1x);
+}
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
index 4632ff52..d70a97e 100644
--- a/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
+++ b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
@@ -148,12 +148,6 @@
     url(default_200_percent/modern/ic_volume_off.png) 2x);
 }
 
-video::-internal-media-remoting-cast-icon {
-  background-image: -webkit-image-set(
-    url(default_100_percent/legacy/mediaremoting_cast.png) 1x,
-    url(default_200_percent/legacy/mediaremoting_cast.png) 2x);
-}
-
 audio::-webkit-media-controls-fullscreen-button,
 video::-webkit-media-controls-fullscreen-button {
   background-image: -webkit-image-set(
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index d428b82..8989245 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -435,198 +435,200 @@
                   "abspath")
 
 modules_dictionary_idl_files =
-    get_path_info([
-                    "app_banner/AppBannerPromptResult.idl",
-                    "app_banner/BeforeInstallPromptEventInit.idl",
-                    "background_fetch/BackgroundFetchClickEventInit.idl",
-                    "background_fetch/BackgroundFetchEventInit.idl",
-                    "background_fetch/BackgroundFetchFailEventInit.idl",
-                    "background_fetch/BackgroundFetchOptions.idl",
-                    "background_fetch/BackgroundFetchedEventInit.idl",
-                    "background_fetch/IconDefinition.idl",
-                    "background_sync/SyncEventInit.idl",
-                    "bluetooth/BluetoothLEScanFilterInit.idl",
-                    "bluetooth/RequestDeviceOptions.idl",
-                    "cachestorage/CacheQueryOptions.idl",
-                    "canvas/canvas2d/CanvasRenderingContext2DSettings.idl",
-                    "canvas/canvas2d/HitRegionOptions.idl",
-                    "cookie_store/CookieListItem.idl",
-                    "cookie_store/CookieStoreGetOptions.idl",
-                    "cookie_store/CookieStoreSetOptions.idl",
-                    "credentialmanager/AuthenticatorSelectionCriteria.idl",
-                    "credentialmanager/CollectedClientData.idl",
-                    "credentialmanager/MakePublicKeyCredentialOptions.idl",
-                    "credentialmanager/CredentialCreationOptions.idl",
-                    "credentialmanager/CredentialData.idl",
-                    "credentialmanager/CredentialRequestOptions.idl",
-                    "credentialmanager/FederatedCredentialInit.idl",
-                    "credentialmanager/FederatedCredentialRequestOptions.idl",
-                    "credentialmanager/PasswordCredentialData.idl",
-                    "credentialmanager/PublicKeyCredentialDescriptor.idl",
-                    "credentialmanager/PublicKeyCredentialEntity.idl",
-                    "credentialmanager/PublicKeyCredentialParameters.idl",
-                    "credentialmanager/PublicKeyCredentialRequestOptions.idl",
-                    "credentialmanager/PublicKeyCredentialRpEntity.idl",
-                    "credentialmanager/PublicKeyCredentialUserEntity.idl",
-                    "csspaint/PaintRenderingContext2DSettings.idl",
-                    "device_orientation/DeviceAccelerationInit.idl",
-                    "device_orientation/DeviceMotionEventInit.idl",
-                    "device_orientation/DeviceOrientationEventInit.idl",
-                    "device_orientation/DeviceRotationRateInit.idl",
-                    "encoding/TextDecodeOptions.idl",
-                    "encoding/TextDecoderOptions.idl",
-                    "encryptedmedia/MediaEncryptedEventInit.idl",
-                    "encryptedmedia/MediaKeysPolicy.idl",
-                    "encryptedmedia/MediaKeyMessageEventInit.idl",
-                    "encryptedmedia/MediaKeySystemConfiguration.idl",
-                    "encryptedmedia/MediaKeySystemMediaCapability.idl",
-                    "eventsource/EventSourceInit.idl",
-                    "filesystem/FileSystemFlags.idl",
-                    "gamepad/GamepadEffectParameters.idl",
-                    "gamepad/GamepadEventInit.idl",
-                    "geolocation/PositionOptions.idl",
-                    "imagecapture/ConstrainPoint2DParameters.idl",
-                    "imagecapture/Point2D.idl",
-                    "imagecapture/PhotoSettings.idl",
-                    "indexeddb/IDBIndexParameters.idl",
-                    "indexeddb/IDBObjectStoreParameters.idl",
-                    "indexeddb/IDBObserverInit.idl",
-                    "indexeddb/IDBVersionChangeEventInit.idl",
-                    "locks/LockInfo.idl",
-                    "locks/LockManagerSnapshot.idl",
-                    "locks/LockOptions.idl",
-                    "media_capabilities/AudioConfiguration.idl",
-                    "media_capabilities/MediaConfiguration.idl",
-                    "media_capabilities/MediaDecodingConfiguration.idl",
-                    "media_capabilities/MediaEncodingConfiguration.idl",
-                    "media_capabilities/VideoConfiguration.idl",
-                    "mediarecorder/BlobEventInit.idl",
-                    "mediarecorder/MediaRecorderOptions.idl",
-                    "mediasession/MediaImage.idl",
-                    "mediasession/MediaMetadataInit.idl",
-                    "mediastream/ConstrainBooleanParameters.idl",
-                    "mediastream/ConstrainDOMStringParameters.idl",
-                    "mediastream/ConstrainDoubleRange.idl",
-                    "mediastream/ConstrainLongRange.idl",
-                    "mediastream/DoubleRange.idl",
-                    "mediastream/LongRange.idl",
-                    "mediastream/MediaStreamConstraints.idl",
-                    "mediastream/MediaStreamEventInit.idl",
-                    "mediastream/MediaStreamTrackEventInit.idl",
-                    "mediastream/MediaTrackCapabilities.idl",
-                    "mediastream/MediaTrackConstraintSet.idl",
-                    "mediastream/MediaTrackConstraints.idl",
-                    "mediastream/MediaTrackSettings.idl",
-                    "mediastream/MediaTrackSupportedConstraints.idl",
-                    "nfc/NFCMessage.idl",
-                    "nfc/NFCPushOptions.idl",
-                    "nfc/NFCRecord.idl",
-                    "nfc/NFCWatchOptions.idl",
-                    "notifications/GetNotificationOptions.idl",
-                    "notifications/NotificationAction.idl",
-                    "notifications/NotificationEventInit.idl",
-                    "notifications/NotificationOptions.idl",
-                    "payments/AndroidPayMethodData.idl",
-                    "payments/AndroidPayTokenization.idl",
-                    "payments/BasicCardRequest.idl",
-                    "payments/CanMakePaymentEventInit.idl",
-                    "payments/ImageObject.idl",
-                    "payments/PaymentHandlerResponse.idl",
-                    "payments/PaymentRequestEventInit.idl",
-                    "payments/PaymentCurrencyAmount.idl",
-                    "payments/PaymentDetailsBase.idl",
-                    "payments/PaymentDetailsInit.idl",
-                    "payments/PaymentDetailsModifier.idl",
-                    "payments/PaymentDetailsUpdate.idl",
-                    "payments/PaymentItem.idl",
-                    "payments/PaymentMethodData.idl",
-                    "payments/PaymentOptions.idl",
-                    "payments/PaymentInstrument.idl",
-                    "payments/PaymentRequestUpdateEventInit.idl",
-                    "payments/PaymentShippingOption.idl",
-                    "peerconnection/RTCAnswerOptions.idl",
-                    "peerconnection/RTCConfiguration.idl",
-                    "peerconnection/RTCDataChannelEventInit.idl",
-                    "peerconnection/RTCDtlsFingerprint.idl",
-                    "peerconnection/RTCDTMFToneChangeEventInit.idl",
-                    "peerconnection/RTCDataChannelInit.idl",
-                    "peerconnection/RTCIceCandidateInit.idl",
-                    "peerconnection/RTCIceServer.idl",
-                    "peerconnection/RTCOfferAnswerOptions.idl",
-                    "peerconnection/RTCOfferOptions.idl",
-                    "peerconnection/RTCPeerConnectionIceEventInit.idl",
-                    "peerconnection/RTCSessionDescriptionInit.idl",
-                    "peerconnection/RTCTrackEventInit.idl",
-                    "permissions/ClipboardPermissionDescriptor.idl",
-                    "permissions/MidiPermissionDescriptor.idl",
-                    "permissions/PermissionDescriptor.idl",
-                    "permissions/PushPermissionDescriptor.idl",
-                    "presentation/PresentationConnectionAvailableEventInit.idl",
-                    "presentation/PresentationConnectionCloseEventInit.idl",
-                    "push_messaging/PushEventInit.idl",
-                    "push_messaging/PushSubscriptionOptionsInit.idl",
-                    "quota/StorageEstimate.idl",
-                    "sensor/SensorErrorEventInit.idl",
-                    "sensor/SensorOptions.idl",
-                    "sensor/SpatialSensorOptions.idl",
-                    "serviceworkers/ClientQueryOptions.idl",
-                    "serviceworkers/ExtendableEventInit.idl",
-                    "serviceworkers/ExtendableMessageEventInit.idl",
-                    "serviceworkers/FetchEventInit.idl",
-                    "serviceworkers/NavigationPreloadState.idl",
-                    "serviceworkers/RegistrationOptions.idl",
-                    "shapedetection/FaceDetectorOptions.idl",
-                    "shapedetection/Landmark.idl",
-                    "speech/SpeechRecognitionErrorInit.idl",
-                    "speech/SpeechRecognitionEventInit.idl",
-                    "storage/StorageEventInit.idl",
-                    "vr/VRDisplayEventInit.idl",
-                    "vr/VRLayerInit.idl",
-                    "webaudio/AnalyserOptions.idl",
-                    "webaudio/AudioBufferOptions.idl",
-                    "webaudio/AudioBufferSourceOptions.idl",
-                    "webaudio/AudioContextOptions.idl",
-                    "webaudio/AudioNodeOptions.idl",
-                    "webaudio/AudioWorkletNodeOptions.idl",
-                    "webaudio/AudioParamDescriptor.idl",
-                    "webaudio/AudioProcessingEventInit.idl",
-                    "webaudio/AudioTimestamp.idl",
-                    "webaudio/BiquadFilterOptions.idl",
-                    "webaudio/ChannelMergerOptions.idl",
-                    "webaudio/ChannelSplitterOptions.idl",
-                    "webaudio/ConstantSourceOptions.idl",
-                    "webaudio/ConvolverOptions.idl",
-                    "webaudio/DelayOptions.idl",
-                    "webaudio/DynamicsCompressorOptions.idl",
-                    "webaudio/GainOptions.idl",
-                    "webaudio/IIRFilterOptions.idl",
-                    "webaudio/MediaElementAudioSourceOptions.idl",
-                    "webaudio/MediaStreamAudioSourceOptions.idl",
-                    "webaudio/PannerOptions.idl",
-                    "webaudio/PeriodicWaveConstraints.idl",
-                    "webaudio/PeriodicWaveOptions.idl",
-                    "webaudio/OscillatorOptions.idl",
-                    "webaudio/OfflineAudioCompletionEventInit.idl",
-                    "webaudio/OfflineAudioContextOptions.idl",
-                    "webaudio/StereoPannerOptions.idl",
-                    "webaudio/WaveShaperOptions.idl",
-                    "webgl/WebGLContextAttributes.idl",
-                    "webgl/WebGLContextEventInit.idl",
-                    "webmidi/MIDIConnectionEventInit.idl",
-                    "webmidi/MIDIMessageEventInit.idl",
-                    "webmidi/MIDIOptions.idl",
-                    "webshare/ShareData.idl",
-                    "websockets/CloseEventInit.idl",
-                    "webusb/USBConnectionEventInit.idl",
-                    "webusb/USBControlTransferParameters.idl",
-                    "webusb/USBDeviceFilter.idl",
-                    "webusb/USBDeviceRequestOptions.idl",
-                    "xr/XRFrameOfReferenceOptions.idl",
-                    "xr/XRSessionCreationOptions.idl",
-                    "xr/XRSessionEventInit.idl",
-                    "xr/XRWebGLLayerInit.idl",
-                  ],
-                  "abspath")
+    get_path_info(
+        [
+          "app_banner/AppBannerPromptResult.idl",
+          "app_banner/BeforeInstallPromptEventInit.idl",
+          "background_fetch/BackgroundFetchClickEventInit.idl",
+          "background_fetch/BackgroundFetchEventInit.idl",
+          "background_fetch/BackgroundFetchFailEventInit.idl",
+          "background_fetch/BackgroundFetchOptions.idl",
+          "background_fetch/BackgroundFetchedEventInit.idl",
+          "background_fetch/IconDefinition.idl",
+          "background_sync/SyncEventInit.idl",
+          "bluetooth/BluetoothLEScanFilterInit.idl",
+          "bluetooth/RequestDeviceOptions.idl",
+          "cachestorage/CacheQueryOptions.idl",
+          "canvas/canvas2d/CanvasRenderingContext2DSettings.idl",
+          "canvas/canvas2d/HitRegionOptions.idl",
+          "canvas/htmlcanvas/CanvasContextCreationAttributesModule.idl",
+          "cookie_store/CookieListItem.idl",
+          "cookie_store/CookieStoreGetOptions.idl",
+          "cookie_store/CookieStoreSetOptions.idl",
+          "credentialmanager/AuthenticatorSelectionCriteria.idl",
+          "credentialmanager/CollectedClientData.idl",
+          "credentialmanager/MakePublicKeyCredentialOptions.idl",
+          "credentialmanager/CredentialCreationOptions.idl",
+          "credentialmanager/CredentialData.idl",
+          "credentialmanager/CredentialRequestOptions.idl",
+          "credentialmanager/FederatedCredentialInit.idl",
+          "credentialmanager/FederatedCredentialRequestOptions.idl",
+          "credentialmanager/PasswordCredentialData.idl",
+          "credentialmanager/PublicKeyCredentialDescriptor.idl",
+          "credentialmanager/PublicKeyCredentialEntity.idl",
+          "credentialmanager/PublicKeyCredentialParameters.idl",
+          "credentialmanager/PublicKeyCredentialRequestOptions.idl",
+          "credentialmanager/PublicKeyCredentialRpEntity.idl",
+          "credentialmanager/PublicKeyCredentialUserEntity.idl",
+          "csspaint/PaintRenderingContext2DSettings.idl",
+          "device_orientation/DeviceAccelerationInit.idl",
+          "device_orientation/DeviceMotionEventInit.idl",
+          "device_orientation/DeviceOrientationEventInit.idl",
+          "device_orientation/DeviceRotationRateInit.idl",
+          "encoding/TextDecodeOptions.idl",
+          "encoding/TextDecoderOptions.idl",
+          "encryptedmedia/MediaEncryptedEventInit.idl",
+          "encryptedmedia/MediaKeysPolicy.idl",
+          "encryptedmedia/MediaKeyMessageEventInit.idl",
+          "encryptedmedia/MediaKeySystemConfiguration.idl",
+          "encryptedmedia/MediaKeySystemMediaCapability.idl",
+          "eventsource/EventSourceInit.idl",
+          "filesystem/FileSystemFlags.idl",
+          "gamepad/GamepadEffectParameters.idl",
+          "gamepad/GamepadEventInit.idl",
+          "geolocation/PositionOptions.idl",
+          "imagecapture/ConstrainPoint2DParameters.idl",
+          "imagecapture/Point2D.idl",
+          "imagecapture/PhotoSettings.idl",
+          "indexeddb/IDBIndexParameters.idl",
+          "indexeddb/IDBObjectStoreParameters.idl",
+          "indexeddb/IDBObserverInit.idl",
+          "indexeddb/IDBVersionChangeEventInit.idl",
+          "locks/LockInfo.idl",
+          "locks/LockManagerSnapshot.idl",
+          "locks/LockOptions.idl",
+          "media_capabilities/AudioConfiguration.idl",
+          "media_capabilities/MediaConfiguration.idl",
+          "media_capabilities/MediaDecodingConfiguration.idl",
+          "media_capabilities/MediaEncodingConfiguration.idl",
+          "media_capabilities/VideoConfiguration.idl",
+          "mediarecorder/BlobEventInit.idl",
+          "mediarecorder/MediaRecorderOptions.idl",
+          "mediasession/MediaImage.idl",
+          "mediasession/MediaMetadataInit.idl",
+          "mediastream/ConstrainBooleanParameters.idl",
+          "mediastream/ConstrainDOMStringParameters.idl",
+          "mediastream/ConstrainDoubleRange.idl",
+          "mediastream/ConstrainLongRange.idl",
+          "mediastream/DoubleRange.idl",
+          "mediastream/LongRange.idl",
+          "mediastream/MediaStreamConstraints.idl",
+          "mediastream/MediaStreamEventInit.idl",
+          "mediastream/MediaStreamTrackEventInit.idl",
+          "mediastream/MediaTrackCapabilities.idl",
+          "mediastream/MediaTrackConstraintSet.idl",
+          "mediastream/MediaTrackConstraints.idl",
+          "mediastream/MediaTrackSettings.idl",
+          "mediastream/MediaTrackSupportedConstraints.idl",
+          "nfc/NFCMessage.idl",
+          "nfc/NFCPushOptions.idl",
+          "nfc/NFCRecord.idl",
+          "nfc/NFCWatchOptions.idl",
+          "notifications/GetNotificationOptions.idl",
+          "notifications/NotificationAction.idl",
+          "notifications/NotificationEventInit.idl",
+          "notifications/NotificationOptions.idl",
+          "payments/AndroidPayMethodData.idl",
+          "payments/AndroidPayTokenization.idl",
+          "payments/BasicCardRequest.idl",
+          "payments/CanMakePaymentEventInit.idl",
+          "payments/ImageObject.idl",
+          "payments/PaymentHandlerResponse.idl",
+          "payments/PaymentRequestEventInit.idl",
+          "payments/PaymentCurrencyAmount.idl",
+          "payments/PaymentDetailsBase.idl",
+          "payments/PaymentDetailsInit.idl",
+          "payments/PaymentDetailsModifier.idl",
+          "payments/PaymentDetailsUpdate.idl",
+          "payments/PaymentItem.idl",
+          "payments/PaymentMethodData.idl",
+          "payments/PaymentOptions.idl",
+          "payments/PaymentInstrument.idl",
+          "payments/PaymentRequestUpdateEventInit.idl",
+          "payments/PaymentShippingOption.idl",
+          "peerconnection/RTCAnswerOptions.idl",
+          "peerconnection/RTCConfiguration.idl",
+          "peerconnection/RTCDataChannelEventInit.idl",
+          "peerconnection/RTCDtlsFingerprint.idl",
+          "peerconnection/RTCDTMFToneChangeEventInit.idl",
+          "peerconnection/RTCDataChannelInit.idl",
+          "peerconnection/RTCIceCandidateInit.idl",
+          "peerconnection/RTCIceServer.idl",
+          "peerconnection/RTCOfferAnswerOptions.idl",
+          "peerconnection/RTCOfferOptions.idl",
+          "peerconnection/RTCPeerConnectionIceEventInit.idl",
+          "peerconnection/RTCSessionDescriptionInit.idl",
+          "peerconnection/RTCTrackEventInit.idl",
+          "permissions/ClipboardPermissionDescriptor.idl",
+          "permissions/MidiPermissionDescriptor.idl",
+          "permissions/PermissionDescriptor.idl",
+          "permissions/PushPermissionDescriptor.idl",
+          "presentation/PresentationConnectionAvailableEventInit.idl",
+          "presentation/PresentationConnectionCloseEventInit.idl",
+          "push_messaging/PushEventInit.idl",
+          "push_messaging/PushSubscriptionOptionsInit.idl",
+          "quota/StorageEstimate.idl",
+          "sensor/SensorErrorEventInit.idl",
+          "sensor/SensorOptions.idl",
+          "sensor/SpatialSensorOptions.idl",
+          "serviceworkers/ClientQueryOptions.idl",
+          "serviceworkers/ExtendableEventInit.idl",
+          "serviceworkers/ExtendableMessageEventInit.idl",
+          "serviceworkers/FetchEventInit.idl",
+          "serviceworkers/NavigationPreloadState.idl",
+          "serviceworkers/RegistrationOptions.idl",
+          "shapedetection/FaceDetectorOptions.idl",
+          "shapedetection/Landmark.idl",
+          "speech/SpeechRecognitionErrorInit.idl",
+          "speech/SpeechRecognitionEventInit.idl",
+          "storage/StorageEventInit.idl",
+          "vr/VRDisplayEventInit.idl",
+          "vr/VRLayerInit.idl",
+          "webaudio/AnalyserOptions.idl",
+          "webaudio/AudioBufferOptions.idl",
+          "webaudio/AudioBufferSourceOptions.idl",
+          "webaudio/AudioContextOptions.idl",
+          "webaudio/AudioNodeOptions.idl",
+          "webaudio/AudioWorkletNodeOptions.idl",
+          "webaudio/AudioParamDescriptor.idl",
+          "webaudio/AudioProcessingEventInit.idl",
+          "webaudio/AudioTimestamp.idl",
+          "webaudio/BiquadFilterOptions.idl",
+          "webaudio/ChannelMergerOptions.idl",
+          "webaudio/ChannelSplitterOptions.idl",
+          "webaudio/ConstantSourceOptions.idl",
+          "webaudio/ConvolverOptions.idl",
+          "webaudio/DelayOptions.idl",
+          "webaudio/DynamicsCompressorOptions.idl",
+          "webaudio/GainOptions.idl",
+          "webaudio/IIRFilterOptions.idl",
+          "webaudio/MediaElementAudioSourceOptions.idl",
+          "webaudio/MediaStreamAudioSourceOptions.idl",
+          "webaudio/PannerOptions.idl",
+          "webaudio/PeriodicWaveConstraints.idl",
+          "webaudio/PeriodicWaveOptions.idl",
+          "webaudio/OscillatorOptions.idl",
+          "webaudio/OfflineAudioCompletionEventInit.idl",
+          "webaudio/OfflineAudioContextOptions.idl",
+          "webaudio/StereoPannerOptions.idl",
+          "webaudio/WaveShaperOptions.idl",
+          "webgl/WebGLContextAttributes.idl",
+          "webgl/WebGLContextEventInit.idl",
+          "webmidi/MIDIConnectionEventInit.idl",
+          "webmidi/MIDIMessageEventInit.idl",
+          "webmidi/MIDIOptions.idl",
+          "webshare/ShareData.idl",
+          "websockets/CloseEventInit.idl",
+          "webusb/USBConnectionEventInit.idl",
+          "webusb/USBControlTransferParameters.idl",
+          "webusb/USBDeviceFilter.idl",
+          "webusb/USBDeviceRequestOptions.idl",
+          "xr/XRFrameOfReferenceOptions.idl",
+          "xr/XRSessionCreationOptions.idl",
+          "xr/XRSessionEventInit.idl",
+          "xr/XRWebGLLayerInit.idl",
+        ],
+        "abspath")
 
 # 'partial interface' or target (right side of) 'implements'
 modules_dependency_idl_files =
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
index 094d232..d25a9eb 100644
--- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
+++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -484,7 +484,7 @@
     device::mojom::blink::VRRequestPresentOptionsPtr options =
         device::mojom::blink::VRRequestPresentOptions::New();
     options->preserve_drawing_buffer =
-        rendering_context_->CreationAttributes().preserveDrawingBuffer();
+        rendering_context_->CreationAttributes().preserve_drawing_buffer;
 
     display_->RequestPresent(
         frame_transport_->GetSubmitFrameClient(),
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
index 6ff80cf..5d41db0 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
@@ -61,7 +61,7 @@
 
 CanvasRenderingContext* WebGL2RenderingContext::Factory::Create(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attrs) {
+    const CanvasContextCreationAttributesCore& attrs) {
   bool using_gpu_compositing;
   std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
       CreateWebGraphicsContext3DProvider(host, attrs, 2,
@@ -94,7 +94,7 @@
     CanvasRenderingContextHost* host,
     std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
     bool using_gpu_compositing,
-    const CanvasContextCreationAttributes& requested_attributes)
+    const CanvasContextCreationAttributesCore& requested_attributes)
     : WebGL2RenderingContextBase(host,
                                  std::move(context_provider),
                                  using_gpu_compositing,
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h
index 90ce519..5b22b23 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h
@@ -11,7 +11,7 @@
 
 namespace blink {
 
-class CanvasContextCreationAttributes;
+class CanvasContextCreationAttributesCore;
 class EXTColorBufferFloat;
 class EXTTextureFilterAnisotropic;
 class OESTextureFloatLinear;
@@ -31,7 +31,7 @@
 
     CanvasRenderingContext* Create(
         CanvasRenderingContextHost*,
-        const CanvasContextCreationAttributes&) override;
+        const CanvasContextCreationAttributesCore&) override;
     CanvasRenderingContext::ContextType GetContextType() const override {
       return CanvasRenderingContext::kContextWebgl2;
     }
@@ -56,7 +56,7 @@
       CanvasRenderingContextHost*,
       std::unique_ptr<WebGraphicsContext3DProvider>,
       bool using_gpu_compositing,
-      const CanvasContextCreationAttributes& requested_attributes);
+      const CanvasContextCreationAttributesCore& requested_attributes);
 
   Member<EXTColorBufferFloat> ext_color_buffer_float_;
   Member<EXTDisjointTimerQueryWebGL2> ext_disjoint_timer_query_web_gl2_;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
index dd86768ee..2377614 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -139,7 +139,7 @@
     CanvasRenderingContextHost* host,
     std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
     bool using_gpu_compositing,
-    const CanvasContextCreationAttributes& requested_attributes)
+    const CanvasContextCreationAttributesCore& requested_attributes)
     : WebGLRenderingContextBase(host,
                                 std::move(context_provider),
                                 using_gpu_compositing,
@@ -5443,9 +5443,9 @@
   if (!framebuffer_binding) {
     // We can use creationAttributes() because in WebGL 2, they are required to
     // be honored.
-    bool has_depth = CreationAttributes().depth();
-    bool has_stencil = CreationAttributes().stencil();
-    bool has_alpha = CreationAttributes().alpha();
+    bool has_depth = CreationAttributes().depth;
+    bool has_stencil = CreationAttributes().stencil;
+    bool has_alpha = CreationAttributes().alpha;
     bool missing_image = (attachment == GL_DEPTH && !has_depth) ||
                          (attachment == GL_STENCIL && !has_stencil);
     if (missing_image) {
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
index 7257f62e..a5c6b42 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
@@ -987,7 +987,7 @@
       CanvasRenderingContextHost*,
       std::unique_ptr<WebGraphicsContext3DProvider>,
       bool using_gpu_compositing,
-      const CanvasContextCreationAttributes& requested_attributes);
+      const CanvasContextCreationAttributesCore& requested_attributes);
 
   // DrawingBuffer::Client implementation.
   void DrawingBufferClientRestorePixelUnpackBufferBinding() override;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLContextAttributeHelpers.cpp b/third_party/WebKit/Source/modules/webgl/WebGLContextAttributeHelpers.cpp
index 2812a95f..332fa9fb 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLContextAttributeHelpers.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLContextAttributeHelpers.cpp
@@ -3,39 +3,43 @@
 // found in the LICENSE file.
 
 #include "modules/webgl/WebGLContextAttributeHelpers.h"
+#include "modules/xr/XRDevice.h"
 
 #include "core/frame/Settings.h"
 
 namespace blink {
 
 WebGLContextAttributes ToWebGLContextAttributes(
-    const CanvasContextCreationAttributes& attrs) {
+    const CanvasContextCreationAttributesCore& attrs) {
   WebGLContextAttributes result;
-  result.setAlpha(attrs.alpha());
-  result.setDepth(attrs.depth());
-  result.setStencil(attrs.stencil());
-  result.setAntialias(attrs.antialias());
-  result.setPremultipliedAlpha(attrs.premultipliedAlpha());
-  result.setPreserveDrawingBuffer(attrs.preserveDrawingBuffer());
-  result.setFailIfMajorPerformanceCaveat(attrs.failIfMajorPerformanceCaveat());
+  result.setAlpha(attrs.alpha);
+  result.setDepth(attrs.depth);
+  result.setStencil(attrs.stencil);
+  result.setAntialias(attrs.antialias);
+  result.setPremultipliedAlpha(attrs.premultiplied_alpha);
+  result.setPreserveDrawingBuffer(attrs.preserve_drawing_buffer);
+  result.setFailIfMajorPerformanceCaveat(
+      attrs.fail_if_major_performance_caveat);
+  result.setCompatibleXRDevice(
+      static_cast<XRDevice*>(attrs.compatible_xr_device.Get()));
   return result;
 }
 
 Platform::ContextAttributes ToPlatformContextAttributes(
-    const CanvasContextCreationAttributes& attrs,
+    const CanvasContextCreationAttributesCore& attrs,
     unsigned web_gl_version,
     bool support_own_offscreen_surface) {
   Platform::ContextAttributes result;
   result.fail_if_major_performance_caveat =
-      attrs.failIfMajorPerformanceCaveat();
+      attrs.fail_if_major_performance_caveat;
   result.web_gl_version = web_gl_version;
   if (support_own_offscreen_surface) {
     // Only ask for alpha/depth/stencil/antialias if we may be using the default
     // framebuffer. They are not needed for standard offscreen rendering.
-    result.support_alpha = attrs.alpha();
-    result.support_depth = attrs.depth();
-    result.support_stencil = attrs.stencil();
-    result.support_antialias = attrs.antialias();
+    result.support_alpha = attrs.alpha;
+    result.support_depth = attrs.depth;
+    result.support_stencil = attrs.stencil;
+    result.support_antialias = attrs.antialias;
   }
   return result;
 }
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLContextAttributeHelpers.h b/third_party/WebKit/Source/modules/webgl/WebGLContextAttributeHelpers.h
index 0f0fc6b..789b18c 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLContextAttributeHelpers.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLContextAttributeHelpers.h
@@ -5,19 +5,19 @@
 #ifndef WebGLContextAttributeHelpers_h
 #define WebGLContextAttributeHelpers_h
 
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "modules/webgl/WebGLContextAttributes.h"
 #include "public/platform/Platform.h"
 
 namespace blink {
 
 WebGLContextAttributes ToWebGLContextAttributes(
-    const CanvasContextCreationAttributes&);
+    const CanvasContextCreationAttributesCore&);
 
 // Set up the attributes that can be used to create a GL context via the
 // Platform API.
 Platform::ContextAttributes ToPlatformContextAttributes(
-    const CanvasContextCreationAttributes&,
+    const CanvasContextCreationAttributesCore&,
     unsigned web_gl_version,
     bool support_own_offscreen_surface);
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLContextAttributes.idl b/third_party/WebKit/Source/modules/webgl/WebGLContextAttributes.idl
index 9a48073..180673be 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLContextAttributes.idl
+++ b/third_party/WebKit/Source/modules/webgl/WebGLContextAttributes.idl
@@ -34,4 +34,5 @@
     boolean premultipliedAlpha = true;
     boolean preserveDrawingBuffer = false;
     boolean failIfMajorPerformanceCaveat = false;
+    [RuntimeEnabled=WebXR] XRDevice compatibleXRDevice = null;
 };
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
index df071cb4..9b303b6 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
@@ -90,7 +90,7 @@
 
 CanvasRenderingContext* WebGLRenderingContext::Factory::Create(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attrs) {
+    const CanvasContextCreationAttributesCore& attrs) {
   bool using_gpu_compositing;
   std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
       CreateWebGraphicsContext3DProvider(host, attrs, 1,
@@ -122,7 +122,7 @@
     CanvasRenderingContextHost* host,
     std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
     bool using_gpu_compositing,
-    const CanvasContextCreationAttributes& requested_attributes)
+    const CanvasContextCreationAttributesCore& requested_attributes)
     : WebGLRenderingContextBase(host,
                                 std::move(context_provider),
                                 using_gpu_compositing,
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h
index 98dfc1e..60690d0 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h
@@ -33,7 +33,7 @@
 namespace blink {
 
 class ANGLEInstancedArrays;
-class CanvasContextCreationAttributes;
+class CanvasContextCreationAttributesCore;
 class EXTBlendMinMax;
 class EXTColorBufferHalfFloat;
 class EXTFragDepth;
@@ -64,7 +64,7 @@
 
     CanvasRenderingContext* Create(
         CanvasRenderingContextHost*,
-        const CanvasContextCreationAttributes&) override;
+        const CanvasContextCreationAttributesCore&) override;
 
     CanvasRenderingContext::ContextType GetContextType() const override {
       return CanvasRenderingContext::kContextWebgl;
@@ -89,7 +89,7 @@
   WebGLRenderingContext(CanvasRenderingContextHost*,
                         std::unique_ptr<WebGraphicsContext3DProvider>,
                         bool using_gpu_compositing,
-                        const CanvasContextCreationAttributes&);
+                        const CanvasContextCreationAttributesCore&);
 
   // Enabled extension objects.
   Member<ANGLEInstancedArrays> angle_instanced_arrays_;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index 9d4ebb1..4fdec527 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -89,6 +89,7 @@
 #include "modules/webgl/WebGLUniformLocation.h"
 #include "modules/webgl/WebGLVertexArrayObject.h"
 #include "modules/webgl/WebGLVertexArrayObjectOES.h"
+#include "modules/xr/XRDevice.h"
 #include "platform/CrossThreadFunctional.h"
 #include "platform/WaitableEvent.h"
 #include "platform/bindings/ScriptWrappableVisitor.h"
@@ -636,7 +637,7 @@
 std::unique_ptr<WebGraphicsContext3DProvider>
 WebGLRenderingContextBase::CreateContextProviderInternal(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attributes,
+    const CanvasContextCreationAttributesCore& attributes,
     unsigned web_gl_version,
     bool* using_gpu_compositing) {
   DCHECK(host);
@@ -687,7 +688,7 @@
 std::unique_ptr<WebGraphicsContext3DProvider>
 WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attributes,
+    const CanvasContextCreationAttributesCore& attributes,
     unsigned webgl_version,
     bool* using_gpu_compositing) {
   if (host->IsWebGLBlocked()) {
@@ -750,7 +751,7 @@
   if (!GetDrawingBuffer())
     return nullptr;
 
-  if (CreationAttributes().preserveDrawingBuffer()) {
+  if (CreationAttributes().preserve_drawing_buffer) {
     int width = GetDrawingBuffer()->Size().Width();
     int height = GetDrawingBuffer()->Size().Height();
     SkImageInfo image_info = SkImageInfo::Make(
@@ -792,7 +793,7 @@
   int height = GetDrawingBuffer()->Size().Height();
   SkImageInfo image_info = SkImageInfo::Make(
       width, height, kRGBA_8888_SkColorType,
-      CreationAttributes().alpha() ? kPremul_SkAlphaType : kOpaque_SkAlphaType);
+      CreationAttributes().alpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType);
   return this->MakeImageSnapshot(image_info);
 }
 
@@ -824,6 +825,43 @@
       surface->makeImageSnapshot(), std::move(shared_context_wrapper));
 }
 
+ScriptPromise WebGLRenderingContextBase::setCompatibleXRDevice(
+    ScriptState* script_state,
+    XRDevice* xr_device) {
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+  ScriptPromise promise = resolver->Promise();
+
+  if (isContextLost()) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state,
+        DOMException::Create(kInvalidStateError, "Context lost."));
+  }
+
+  if (xr_device == compatible_xr_device_) {
+    resolver->Resolve();
+    return promise;
+  }
+
+  if (ContextCreatedOnCompatibleAdapter(xr_device)) {
+    compatible_xr_device_ = xr_device;
+    resolver->Resolve();
+  } else {
+    // TODO(offenwanger): Trigger context loss and recreate on compatible GPU.
+    return ScriptPromise::RejectWithDOMException(
+        script_state,
+        DOMException::Create(
+            kNotSupportedError,
+            "Context is not compatible. Switching not yet implemented."));
+  }
+
+  return promise;
+}
+
+bool WebGLRenderingContextBase::IsXRDeviceCompatible(
+    const XRDevice* xr_device) {
+  return xr_device == compatible_xr_device_;
+}
+
 namespace {
 
 // Exposed by GL_ANGLE_depth_texture
@@ -968,7 +1006,7 @@
     CanvasRenderingContextHost* host,
     std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
     bool using_gpu_compositing,
-    const CanvasContextCreationAttributes& requested_attributes,
+    const CanvasContextCreationAttributesCore& requested_attributes,
     unsigned version)
     : WebGLRenderingContextBase(
           host,
@@ -983,7 +1021,7 @@
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
     bool using_gpu_compositing,
-    const CanvasContextCreationAttributes& requested_attributes,
+    const CanvasContextCreationAttributesCore& requested_attributes,
     unsigned version)
     : CanvasRenderingContext(host, requested_attributes),
       context_group_(new WebGLContextGroup()),
@@ -1014,6 +1052,10 @@
       version_(version) {
   DCHECK(context_provider);
 
+  // TODO(offenwanger) Make sure this is being created on a compatible adapter.
+  compatible_xr_device_ =
+      static_cast<XRDevice*>(requested_attributes.compatible_xr_device.Get());
+
   context_group_->AddContext(this);
 
   max_viewport_dims_[0] = max_viewport_dims_[1] = 0;
@@ -1061,13 +1103,13 @@
 scoped_refptr<DrawingBuffer> WebGLRenderingContextBase::CreateDrawingBuffer(
     std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
     bool using_gpu_compositing) {
-  bool premultiplied_alpha = CreationAttributes().premultipliedAlpha();
-  bool want_alpha_channel = CreationAttributes().alpha();
-  bool want_depth_buffer = CreationAttributes().depth();
-  bool want_stencil_buffer = CreationAttributes().stencil();
-  bool want_antialiasing = CreationAttributes().antialias();
+  bool premultiplied_alpha = CreationAttributes().premultiplied_alpha;
+  bool want_alpha_channel = CreationAttributes().alpha;
+  bool want_depth_buffer = CreationAttributes().depth;
+  bool want_stencil_buffer = CreationAttributes().stencil;
+  bool want_antialiasing = CreationAttributes().antialias;
   DrawingBuffer::PreserveDrawingBuffer preserve =
-      CreationAttributes().preserveDrawingBuffer() ? DrawingBuffer::kPreserve
+      CreationAttributes().preserve_drawing_buffer ? DrawingBuffer::kPreserve
                                                    : DrawingBuffer::kDiscard;
   DrawingBuffer::WebGLVersion web_gl_version = DrawingBuffer::kWebGL1;
   if (Version() == 1) {
@@ -1101,6 +1143,9 @@
   DCHECK(!isContextLost());
   DCHECK(GetDrawingBuffer());
 
+  // TODO(offenwanger): Check if compatible_xr_device needs to be taken into
+  // account here.
+
   marked_canvas_dirty_ = false;
   animation_frame_in_progress_ = false;
   active_texture_unit_ = 0;
@@ -1499,6 +1544,12 @@
   return true;
 }
 
+bool WebGLRenderingContextBase::ContextCreatedOnCompatibleAdapter(
+    const XRDevice* device) {
+  // TODO(offenwanger): Determine if device is compatible with current context.
+  return true;
+}
+
 bool WebGLRenderingContextBase::CopyRenderingResultsFromDrawingBuffer(
     CanvasResourceProvider* resource_provider,
     SourceDrawingBuffer source_buffer) const {
@@ -2772,11 +2823,14 @@
   result = ToWebGLContextAttributes(CreationAttributes());
   // Some requested attributes may not be honored, so we need to query the
   // underlying context/drawing buffer and adjust accordingly.
-  if (CreationAttributes().depth() && !GetDrawingBuffer()->HasDepthBuffer())
+  if (CreationAttributes().depth && !GetDrawingBuffer()->HasDepthBuffer())
     result->setDepth(false);
-  if (CreationAttributes().stencil() && !GetDrawingBuffer()->HasStencilBuffer())
+  if (CreationAttributes().stencil && !GetDrawingBuffer()->HasStencilBuffer())
     result->setStencil(false);
   result->setAntialias(GetDrawingBuffer()->Multisample());
+  if (compatible_xr_device_) {
+    result->setCompatibleXRDevice(compatible_xr_device_);
+  }
 }
 
 GLenum WebGLRenderingContextBase::getError() {
@@ -2996,7 +3050,7 @@
     case GL_CURRENT_PROGRAM:
       return WebGLAny(script_state, current_program_.Get());
     case GL_DEPTH_BITS:
-      if (!framebuffer_binding_ && !CreationAttributes().depth())
+      if (!framebuffer_binding_ && !CreationAttributes().depth)
         return WebGLAny(script_state, kIntZero);
       return GetIntParameter(script_state, pname);
     case GL_DEPTH_CLEAR_VALUE:
@@ -3104,7 +3158,7 @@
     case GL_STENCIL_BACK_WRITEMASK:
       return GetUnsignedIntParameter(script_state, pname);
     case GL_STENCIL_BITS:
-      if (!framebuffer_binding_ && !CreationAttributes().stencil())
+      if (!framebuffer_binding_ && !CreationAttributes().stencil)
         return WebGLAny(script_state, kIntZero);
       return GetIntParameter(script_state, pname);
     case GL_STENCIL_CLEAR_VALUE:
@@ -7827,6 +7881,7 @@
   visitor->Trace(current_program_);
   visitor->Trace(framebuffer_binding_);
   visitor->Trace(renderbuffer_binding_);
+  visitor->Trace(compatible_xr_device_);
   visitor->Trace(texture_units_);
   visitor->Trace(extensions_);
   CanvasRenderingContext::Trace(visitor);
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
index 50158067..5947464 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
@@ -30,7 +30,7 @@
 #include <set>
 #include "bindings/core/v8/ScriptValue.h"
 #include "core/CoreExport.h"
-#include "core/html/canvas/CanvasContextCreationAttributes.h"
+#include "core/html/canvas/CanvasContextCreationAttributesCore.h"
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/layout/ContentChangeType.h"
 #include "core/typed_arrays/ArrayBufferViewHelpers.h"
@@ -40,6 +40,7 @@
 #include "modules/webgl/WebGLExtensionName.h"
 #include "modules/webgl/WebGLTexture.h"
 #include "modules/webgl/WebGLVertexArrayObjectBase.h"
+#include "modules/xr/XRDevice.h"
 #include "platform/Timer.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/bindings/ScriptWrappable.h"
@@ -141,7 +142,7 @@
 
   static std::unique_ptr<WebGraphicsContext3DProvider>
   CreateWebGraphicsContext3DProvider(CanvasRenderingContextHost*,
-                                     const CanvasContextCreationAttributes&,
+                                     const CanvasContextCreationAttributesCore&,
                                      unsigned web_gl_version,
                                      bool* using_gpu_compositing);
   static void ForceNextWebGLContextCreationToFail();
@@ -608,6 +609,9 @@
   scoped_refptr<StaticBitmapImage> GetStaticBitmapImage(
       std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback);
 
+  ScriptPromise setCompatibleXRDevice(ScriptState*, XRDevice*);
+  bool IsXRDeviceCompatible(const XRDevice*);
+
  protected:
   friend class EXTDisjointTimerQuery;
   friend class EXTDisjointTimerQueryWebGL2;
@@ -634,7 +638,7 @@
   WebGLRenderingContextBase(CanvasRenderingContextHost*,
                             std::unique_ptr<WebGraphicsContext3DProvider>,
                             bool using_gpu_compositing,
-                            const CanvasContextCreationAttributes&,
+                            const CanvasContextCreationAttributesCore&,
                             unsigned);
   scoped_refptr<DrawingBuffer> CreateDrawingBuffer(
       std::unique_ptr<WebGraphicsContext3DProvider>,
@@ -738,6 +742,8 @@
   TraceWrapperMember<WebGLFramebuffer> framebuffer_binding_;
   TraceWrapperMember<WebGLRenderbuffer> renderbuffer_binding_;
 
+  Member<XRDevice> compatible_xr_device_;
+
   HeapVector<TextureUnitState> texture_units_;
   unsigned long active_texture_unit_;
 
@@ -1670,12 +1676,12 @@
                             scoped_refptr<base::SingleThreadTaskRunner>,
                             std::unique_ptr<WebGraphicsContext3DProvider>,
                             bool using_gpu_compositing,
-                            const CanvasContextCreationAttributes&,
+                            const CanvasContextCreationAttributesCore&,
                             unsigned);
   static bool SupportOwnOffscreenSurface(ExecutionContext*);
   static std::unique_ptr<WebGraphicsContext3DProvider>
   CreateContextProviderInternal(CanvasRenderingContextHost*,
-                                const CanvasContextCreationAttributes&,
+                                const CanvasContextCreationAttributesCore&,
                                 unsigned web_gl_version,
                                 bool* using_gpu_compositing);
   void TexImageCanvasByGPU(TexImageFunctionID,
@@ -1696,6 +1702,11 @@
   const unsigned version_;
 
   bool IsPaintable() const final { return GetDrawingBuffer(); }
+
+  // Returns true if the context is compatible with the given device as defined
+  // by https://immersive-web.github.io/webxr/spec/latest/#contextcompatibility
+  bool ContextCreatedOnCompatibleAdapter(const XRDevice*);
+
   bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*,
                                              SourceDrawingBuffer) const;
   void HoldReferenceToDrawingBuffer(DrawingBuffer*);
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.idl b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.idl
index fbac5cd..cea13bf4 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.idl
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.idl
@@ -706,4 +706,7 @@
     void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 
     [RuntimeEnabled=ExperimentalCanvasFeatures, CallWith=ScriptState, RaisesException] Promise commit();
+
+    // WebXR Device API support
+    [RuntimeEnabled=WebXR, SecureContext, CallWith=ScriptState] Promise setCompatibleXRDevice(XRDevice device);
 };
diff --git a/third_party/WebKit/Source/modules/xr/XRPresentationContext.cpp b/third_party/WebKit/Source/modules/xr/XRPresentationContext.cpp
index 88576bb..7651d3d 100644
--- a/third_party/WebKit/Source/modules/xr/XRPresentationContext.cpp
+++ b/third_party/WebKit/Source/modules/xr/XRPresentationContext.cpp
@@ -10,7 +10,7 @@
 
 XRPresentationContext::XRPresentationContext(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attrs)
+    const CanvasContextCreationAttributesCore& attrs)
     : ImageBitmapRenderingContextBase(host, attrs) {}
 
 XRPresentationContext::~XRPresentationContext() {}
@@ -22,7 +22,7 @@
 
 CanvasRenderingContext* XRPresentationContext::Factory::Create(
     CanvasRenderingContextHost* host,
-    const CanvasContextCreationAttributes& attrs) {
+    const CanvasContextCreationAttributesCore& attrs) {
   if (!RuntimeEnabledFeatures::WebXREnabled())
     return nullptr;
   return new XRPresentationContext(host, attrs);
diff --git a/third_party/WebKit/Source/modules/xr/XRPresentationContext.h b/third_party/WebKit/Source/modules/xr/XRPresentationContext.h
index 4baaa09..97c4132 100644
--- a/third_party/WebKit/Source/modules/xr/XRPresentationContext.h
+++ b/third_party/WebKit/Source/modules/xr/XRPresentationContext.h
@@ -26,7 +26,7 @@
 
     CanvasRenderingContext* Create(
         CanvasRenderingContextHost*,
-        const CanvasContextCreationAttributes&) override;
+        const CanvasContextCreationAttributesCore&) override;
     CanvasRenderingContext::ContextType GetContextType() const override {
       return CanvasRenderingContext::kContextXRPresent;
     }
@@ -42,7 +42,7 @@
 
  private:
   XRPresentationContext(CanvasRenderingContextHost*,
-                        const CanvasContextCreationAttributes&);
+                        const CanvasContextCreationAttributesCore&);
 };
 
 DEFINE_TYPE_CASTS(XRPresentationContext,
diff --git a/third_party/WebKit/Source/modules/xr/XRWebGLLayer.cpp b/third_party/WebKit/Source/modules/xr/XRWebGLLayer.cpp
index 7961fff..8c3799f 100644
--- a/third_party/WebKit/Source/modules/xr/XRWebGLLayer.cpp
+++ b/third_party/WebKit/Source/modules/xr/XRWebGLLayer.cpp
@@ -62,6 +62,13 @@
     return nullptr;
   }
 
+  if (!webgl_context->IsXRDeviceCompatible(session->device())) {
+    exception_state.ThrowDOMException(
+        kInvalidStateError,
+        "The session's device is not the compatible device for this context.");
+    return nullptr;
+  }
+
   bool want_antialiasing = initializer.antialias();
   bool want_depth_buffer = initializer.depth();
   bool want_stencil_buffer = initializer.stencil();
diff --git a/third_party/WebKit/Source/platform/geometry/FloatRect.cpp b/third_party/WebKit/Source/platform/geometry/FloatRect.cpp
index e3b6002..c380c2d7 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatRect.cpp
+++ b/third_party/WebKit/Source/platform/geometry/FloatRect.cpp
@@ -70,6 +70,15 @@
          fabs(MaxX()) > kMaxExactlyExpressible ||
          fabs(MaxY()) > kMaxExactlyExpressible;
 }
+
+bool FloatRect::EqualWithinEpsilon(const FloatRect& other,
+                                   float epsilon) const {
+  return std::abs(other.X() - X()) <= epsilon &&
+         std::abs(other.Y() - Y()) <= epsilon &&
+         std::abs(other.Width() - Width()) <= epsilon &&
+         std::abs(other.Height() - Height()) <= epsilon;
+}
+
 #endif
 
 bool FloatRect::IsExpressibleAsIntRect() const {
diff --git a/third_party/WebKit/Source/platform/geometry/FloatRect.h b/third_party/WebKit/Source/platform/geometry/FloatRect.h
index f404923..db1c951 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatRect.h
+++ b/third_party/WebKit/Source/platform/geometry/FloatRect.h
@@ -183,6 +183,7 @@
 
 #if DCHECK_IS_ON()
   bool MayNotHaveExactIntRectRepresentation() const;
+  bool EqualWithinEpsilon(const FloatRect& other, float epsilon) const;
 #endif
 
   String ToString() const;
diff --git a/third_party/WebKit/Source/platform/geometry/LayoutRect.h b/third_party/WebKit/Source/platform/geometry/LayoutRect.h
index 83c7d040..dd68e50 100644
--- a/third_party/WebKit/Source/platform/geometry/LayoutRect.h
+++ b/third_party/WebKit/Source/platform/geometry/LayoutRect.h
@@ -145,6 +145,12 @@
     size_.Shrink(left + right, top + bottom);
   }
 
+  // Convert to an outsets for {{0, 0}, size} rect.
+  LayoutRectOutsets ToOutsets(const LayoutSize& size) const {
+    return LayoutRectOutsets(-Y(), MaxX() - size.Width(),
+                             MaxY() - size.Height(), -X());
+  }
+
   void ShiftXEdgeTo(LayoutUnit edge) {
     LayoutUnit delta = edge - X();
     SetX(edge);
diff --git a/third_party/WebKit/Source/platform/geometry/LayoutRectOutsets.cpp b/third_party/WebKit/Source/platform/geometry/LayoutRectOutsets.cpp
index 5934e843c..65e75d3b 100644
--- a/third_party/WebKit/Source/platform/geometry/LayoutRectOutsets.cpp
+++ b/third_party/WebKit/Source/platform/geometry/LayoutRectOutsets.cpp
@@ -42,6 +42,13 @@
   left_ = left_.ClampNegativeToZero();
 }
 
+void LayoutRectOutsets::Unite(const LayoutRectOutsets& other) {
+  top_ = std::max(top_, other.top_);
+  right_ = std::max(right_, other.right_);
+  bottom_ = std::max(bottom_, other.bottom_);
+  left_ = std::max(left_, other.left_);
+}
+
 LayoutRectOutsets LayoutRectOutsets::LineOrientationOutsets(
     WritingMode writing_mode) const {
   if (!IsHorizontalWritingMode(writing_mode))
diff --git a/third_party/WebKit/Source/platform/geometry/LayoutRectOutsets.h b/third_party/WebKit/Source/platform/geometry/LayoutRectOutsets.h
index aedafc5..2cc1523b 100644
--- a/third_party/WebKit/Source/platform/geometry/LayoutRectOutsets.h
+++ b/third_party/WebKit/Source/platform/geometry/LayoutRectOutsets.h
@@ -85,6 +85,10 @@
 
   void ClampNegativeToZero();
 
+  void Unite(const LayoutRectOutsets&);
+
+  void FlipHorizontally() { std::swap(left_, right_); }
+
   // Produces a new LayoutRectOutsets in line orientation
   // (https://www.w3.org/TR/css-writing-modes-3/#line-orientation), whose
   // - |top| is the logical 'over',
diff --git a/third_party/WebKit/Source/platform/graphics/GpuMemoryBufferImageCopy.cpp b/third_party/WebKit/Source/platform/graphics/GpuMemoryBufferImageCopy.cpp
index 9515a50..e8c853f 100644
--- a/third_party/WebKit/Source/platform/graphics/GpuMemoryBufferImageCopy.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GpuMemoryBufferImageCopy.cpp
@@ -31,7 +31,7 @@
       return false;
 
     gpu_memory_buffer_ = gpu_memory_buffer_manager->CreateGpuMemoryBuffer(
-        gfx::Size(width, height), gfx::BufferFormat::RGBX_8888,
+        gfx::Size(width, height), gfx::BufferFormat::RGBA_8888,
         gfx::BufferUsage::SCANOUT, gpu::kNullSurfaceHandle);
     if (!gpu_memory_buffer_)
       return false;
@@ -55,7 +55,7 @@
 
   // Bind the write framebuffer to our memory buffer.
   GLuint image_id = gl_->CreateImageCHROMIUM(
-      gpu_memory_buffer_->AsClientBuffer(), width, height, GL_RGB);
+      gpu_memory_buffer_->AsClientBuffer(), width, height, GL_RGBA);
   if (!image_id)
     return nullptr;
   GLuint dest_texture_id;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
index 3b000613..7e10485 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
@@ -520,6 +520,21 @@
   ct_policy_compliance_ = compliance;
 }
 
+bool ResourceResponse::IsOpaqueResponseFromServiceWorker() const {
+  switch (response_type_via_service_worker_) {
+    case network::mojom::FetchResponseType::kBasic:
+    case network::mojom::FetchResponseType::kCORS:
+    case network::mojom::FetchResponseType::kDefault:
+    case network::mojom::FetchResponseType::kError:
+      return false;
+    case network::mojom::FetchResponseType::kOpaque:
+    case network::mojom::FetchResponseType::kOpaqueRedirect:
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
 KURL ResourceResponse::OriginalURLViaServiceWorker() const {
   if (url_list_via_service_worker_.IsEmpty())
     return KURL();
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
index 730f460..04e48cc 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
@@ -313,6 +313,7 @@
       network::mojom::FetchResponseType value) {
     response_type_via_service_worker_ = value;
   }
+  bool IsOpaqueResponseFromServiceWorker() const;
 
   // See ServiceWorkerResponseInfo::url_list_via_service_worker.
   const Vector<KURL>& UrlListViaServiceWorker() const {
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
index 8c024ed..5ca87485 100644
--- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5
+++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -902,7 +902,7 @@
     // crbug.com/417782 tracks enabling this by default.
     {
       name: "RootLayerScrolling",
-      status: "experimental",
+      status: "stable",
     },
     {
       name: "RTCUnifiedPlan",
diff --git a/third_party/WebKit/Source/platform/transforms/ScaleTransformOperation.h b/third_party/WebKit/Source/platform/transforms/ScaleTransformOperation.h
index d1097331..13dde20 100644
--- a/third_party/WebKit/Source/platform/transforms/ScaleTransformOperation.h
+++ b/third_party/WebKit/Source/platform/transforms/ScaleTransformOperation.h
@@ -80,6 +80,8 @@
     return x_ == s->x_ && y_ == s->y_ && z_ == s->z_;
   }
 
+  virtual bool HasNonTrivial3DComponent() const { return z_ != 1.0; }
+
   scoped_refptr<TransformOperation> Zoom(double factor) final { return this; }
 
   ScaleTransformOperation(double sx, double sy, double sz, OperationType type)
diff --git a/third_party/WebKit/Source/platform/transforms/TransformOperation.h b/third_party/WebKit/Source/platform/transforms/TransformOperation.h
index 776b66fe..2644a14 100644
--- a/third_party/WebKit/Source/platform/transforms/TransformOperation.h
+++ b/third_party/WebKit/Source/platform/transforms/TransformOperation.h
@@ -101,6 +101,8 @@
            op_type == kInterpolated;
   }
 
+  virtual bool HasNonTrivial3DComponent() const { return Is3DOperation(); }
+
   virtual bool DependsOnBoxSize() const { return false; }
 };
 
diff --git a/third_party/WebKit/Source/platform/transforms/TransformOperations.h b/third_party/WebKit/Source/platform/transforms/TransformOperations.h
index 2fe5622..0414608 100644
--- a/third_party/WebKit/Source/platform/transforms/TransformOperations.h
+++ b/third_party/WebKit/Source/platform/transforms/TransformOperations.h
@@ -49,22 +49,32 @@
   bool operator!=(const TransformOperations& o) const { return !(*this == o); }
 
   void Apply(const FloatSize& sz, TransformationMatrix& t) const {
-    for (unsigned i = 0; i < operations_.size(); ++i)
-      operations_[i]->Apply(t, sz);
+    for (auto& operation : operations_)
+      operation->Apply(t, sz);
   }
 
   // Return true if any of the operation types are 3D operation types (even if
   // the values describe affine transforms)
   bool Has3DOperation() const {
-    for (unsigned i = 0; i < operations_.size(); ++i)
-      if (operations_[i]->Is3DOperation())
+    for (auto& operation : operations_)
+      if (operation->Is3DOperation())
         return true;
     return false;
   }
 
+  // Returns true if any operation has a non-trivial component in the Z
+  // axis.
+  bool HasNonTrivial3DComponent() const {
+    for (auto& operation : operations_) {
+      if (operation->HasNonTrivial3DComponent())
+        return true;
+    }
+    return false;
+  }
+
   bool DependsOnBoxSize() const {
-    for (unsigned i = 0; i < operations_.size(); ++i) {
-      if (operations_[i]->DependsOnBoxSize())
+    for (auto& operation : operations_) {
+      if (operation->DependsOnBoxSize())
         return true;
     }
     return false;
diff --git a/third_party/WebKit/Source/platform/transforms/TranslateTransformOperation.h b/third_party/WebKit/Source/platform/transforms/TranslateTransformOperation.h
index ebbb2bba..3e013ce 100644
--- a/third_party/WebKit/Source/platform/transforms/TranslateTransformOperation.h
+++ b/third_party/WebKit/Source/platform/transforms/TranslateTransformOperation.h
@@ -107,6 +107,8 @@
     DCHECK(IsMatchingOperationType(type));
   }
 
+  bool HasNonTrivial3DComponent() const override { return z_ != 0.0; }
+
   Length x_;
   Length y_;
   double z_;
diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
index e545ae5..a9294d4b 100644
--- a/third_party/zlib/BUILD.gn
+++ b/third_party/zlib/BUILD.gn
@@ -56,11 +56,10 @@
 
 config("zlib_inflate_chunk_simd_config") {
   if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
-    defines = [ "INFLATE_CHUNK_SIMD_SSE2" ]
-
-    if (current_cpu == "x64") {
-      defines += [ "INFLATE_CHUNK_READ_64LE" ]
-    }
+    defines = [
+      "INFLATE_CHUNK_READ_64LE",
+      "INFLATE_CHUNK_SIMD_SSE2",
+    ]
   }
 
   if (current_cpu == "arm" || current_cpu == "arm64") {
@@ -242,6 +241,7 @@
 
 config("minizip_warnings") {
   visibility = [ ":*" ]
+
   if (is_clang) {
     # zlib uses `if ((a == b))` for some reason.
     cflags = [ "-Wno-parentheses-equality" ]
@@ -266,6 +266,7 @@
       "contrib/minizip/iowin32.h",
     ]
   }
+
   if (is_mac || is_ios || is_android || is_nacl) {
     # Mac, Android and the BSDs don't have fopen64, ftello64, or fseeko64. We
     # use fopen, ftell, and fseek instead on these systems.
@@ -303,7 +304,7 @@
   configs += [ "//build/config/compiler:no_chromium_code" ]
 
   deps = [
-    "//build/config:exe_and_shlib_deps",
     ":zlib",
+    "//build/config:exe_and_shlib_deps",
   ]
 }
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index a8eecd23..d732b0d 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -1717,7 +1717,8 @@
   </description>
 </action>
 
-<action name="Android.InstantApps.InstantAppsEligiblePageLoaded">
+<action name="Android.InstantApps.InstantAppsEligiblePageLoaded"
+    not_user_triggered="true">
   <owner>mariakhomenko@chromium.org</owner>
   <description>
     A page finished loading in Chrome that could have been loaded in an Instant
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 2f7ca9e..41f71f7 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -9027,6 +9027,12 @@
   <int value="2" label="Migration resumed"/>
 </enum>
 
+<enum name="DirectIntentType">
+  <int value="0" label="Fallback URL activated"/>
+  <int value="1" label="Intent URL clicked on SERP"/>
+  <int value="2" label="Intent URL clicked elsewhere"/>
+</enum>
+
 <enum name="DirectoryDatabaseRepairResult">
   <int value="0" label="Succeeded"/>
   <int value="1" label="Failed"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index c6a1e54..2cba283 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1201,6 +1201,15 @@
   </summary>
 </histogram>
 
+<histogram name="Android.InstantApps.DirectInstantAppsIntent"
+    enum="DirectIntentType">
+  <owner>mariakhomenko@chromium.org</owner>
+  <summary>
+    Records events that occur when a user clicks on an intent:// URL that is
+    dispatched to instant apps.
+  </summary>
+</histogram>
+
 <histogram name="Android.InstantApps.FallbackDuration" units="ms">
   <owner>mariakhomenko@chromium.org</owner>
   <summary>
diff --git a/ui/app_list/vector_icons/vector_icons.cc.template b/ui/app_list/vector_icons/vector_icons.cc.template
index 9a44601..ab13ead 100644
--- a/ui/app_list/vector_icons/vector_icons.cc.template
+++ b/ui/app_list/vector_icons/vector_icons.cc.template
@@ -10,11 +10,7 @@
 #include "base/logging.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
 
 namespace app_list {
 
diff --git a/ui/gfx/paint_vector_icon.cc b/ui/gfx/paint_vector_icon.cc
index 7761ec1..b9832d0 100644
--- a/ui/gfx/paint_vector_icon.cc
+++ b/ui/gfx/paint_vector_icon.cc
@@ -562,6 +562,14 @@
                      SkColor color,
                      const base::TimeDelta& elapsed_time) {
   DCHECK(!icon.is_empty());
+  if (icon.path) {
+    DCHECK(icon.path_size > 0);
+    DCHECK_EQ(END, icon.path[icon.path_size - 1].command) << icon.name;
+  }
+  if (icon.path_1x) {
+    DCHECK(icon.path_1x_size > 0);
+    DCHECK_EQ(END, icon.path_1x[icon.path_1x_size - 1].command) << icon.name;
+  }
   const PathElement* path =
       (canvas->image_scale() == 1.f && icon.path_1x) ? icon.path_1x : icon.path;
   PaintPath(canvas, path, dip_size, color, elapsed_time);
diff --git a/ui/gfx/paint_vector_icon_unittest.cc b/ui/gfx/paint_vector_icon_unittest.cc
index bc4a4327..6570dc5 100644
--- a/ui/gfx/paint_vector_icon_unittest.cc
+++ b/ui/gfx/paint_vector_icon_unittest.cc
@@ -51,7 +51,7 @@
       R_LINE_TO, 50, 51,
       END,
   };
-  const VectorIcon icon = {elements, nullptr};
+  const VectorIcon icon = {elements, arraysize(elements)};
 
   PaintVectorIcon(&canvas, icon, 100, SK_ColorMAGENTA);
   sk_sp<cc::PaintRecord> record = recorder.finishRecordingAsPicture();
@@ -88,7 +88,7 @@
       CLOSE,
       END,
   };
-  const VectorIcon icon = {elements, nullptr};
+  const VectorIcon icon = {elements, arraysize(elements)};
   PaintVectorIcon(&canvas, icon, canvas_size, color);
 
   // Count the number of pixels in the canvas.
diff --git a/ui/gfx/vector_icon_types.h b/ui/gfx/vector_icon_types.h
index d1cba9b3..fae6871 100644
--- a/ui/gfx/vector_icon_types.h
+++ b/ui/gfx/vector_icon_types.h
@@ -2,9 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// This file provides defines needed by PaintVectorIcon and is implemented
-// by the generated file vector_icons.cc.
-
 #ifndef UI_GFX_VECTOR_ICON_TYPES_H_
 #define UI_GFX_VECTOR_ICON_TYPES_H_
 
@@ -66,7 +63,8 @@
   // Parameters are delay (ms), duration (ms), and tween type
   // (gfx::Tween::Type).
   TRANSITION_END,
-  // Marks the end of the list of commands.
+  // Marks the end of the list of commands. TODO(estade): remove this sentinel
+  // value and rely on VectorIcon::path_size.
   END
 };
 
@@ -86,8 +84,20 @@
 
   bool is_empty() const { return !path; }
 
-  const gfx::PathElement* path;
-  const gfx::PathElement* path_1x;
+  const gfx::PathElement* path = nullptr;
+  // The length of |path|.
+  size_t path_size = 0u;
+
+  const gfx::PathElement* path_1x = nullptr;
+  // The length of |path_1x|.
+  size_t path_1x_size = 0u;
+
+  // A human-readable name, useful for debugging, derived from the name of the
+  // icon file. This can also be used as an identifier, but vector icon targets
+  // should be careful to ensure this is unique.
+  const char* name = nullptr;
+
+  bool operator<(const VectorIcon& other) const;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(VectorIcon);
diff --git a/ui/message_center/vector_icons/vector_icons.cc.template b/ui/message_center/vector_icons/vector_icons.cc.template
index 7a94527..7473cb4 100644
--- a/ui/message_center/vector_icons/vector_icons.cc.template
+++ b/ui/message_center/vector_icons/vector_icons.cc.template
@@ -10,11 +10,7 @@
 #include "base/logging.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
 
 namespace message_center {
 
diff --git a/ui/ozone/platform/drm/gpu/drm_device.cc b/ui/ozone/platform/drm/gpu/drm_device.cc
index 95a473a..9fd0bd1 100644
--- a/ui/ozone/platform/drm/gpu/drm_device.cc
+++ b/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -365,6 +365,10 @@
     return false;
   }
 
+  uint64_t value;
+  allow_addfb2_modifiers_ =
+      GetCapability(DRM_CAP_ADDFB2_MODIFIERS, &value) && value;
+
   watcher_.reset(
       new IOWatcher(file_.GetPlatformFile(), page_flip_manager_.get()));
 
diff --git a/ui/ozone/platform/drm/gpu/drm_device.h b/ui/ozone/platform/drm/gpu/drm_device.h
index 4e19784..af32dfb 100644
--- a/ui/ozone/platform/drm/gpu/drm_device.h
+++ b/ui/ozone/platform/drm/gpu/drm_device.h
@@ -50,6 +50,8 @@
 
   bool is_primary_device() const { return is_primary_device_; }
 
+  bool allow_addfb2_modifiers() const { return allow_addfb2_modifiers_; }
+
   // Open device.
   virtual bool Initialize(bool use_atomic);
 
@@ -206,6 +208,8 @@
 
   bool is_primary_device_;
 
+  bool allow_addfb2_modifiers_;
+
   DISALLOW_COPY_AND_ASSIGN(DrmDevice);
 };
 
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
index 78091de..1794826 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -70,6 +70,7 @@
     // a bo with modifiers, otherwise, we rely on the "no modifiers"
     // behavior doing the right thing.
     const uint32_t addfb_flags =
+        gbm->allow_addfb2_modifiers() &&
         modifier != DRM_FORMAT_MOD_INVALID ? DRM_MODE_FB_MODIFIERS : 0;
     bool ret = drm_->AddFramebuffer2(
         gbm_bo_get_width(bo), gbm_bo_get_height(bo), framebuffer_pixel_format_,
@@ -189,12 +190,12 @@
     gbm_bo* bo,
     uint32_t format,
     const gfx::Size& size,
-    uint32_t flags,
-    uint64_t modifier) {
+    uint32_t flags) {
   DCHECK(bo);
   std::vector<base::ScopedFD> fds;
   std::vector<gfx::NativePixmapPlane> planes;
 
+  const uint64_t modifier = gbm_bo_get_format_modifier(bo);
   for (size_t i = 0; i < gbm_bo_get_num_planes(bo); ++i) {
     // The fd returned by gbm_bo_get_fd is not ref-counted and need to be
     // kept open for the lifetime of the buffer.
@@ -240,8 +241,7 @@
   if (!bo)
     return nullptr;
 
-  return CreateBufferForBO(gbm, bo, format, size, flags,
-                           gbm_bo_get_format_modifier(bo));
+  return CreateBufferForBO(gbm, bo, format, size, flags);
 }
 
 // static
@@ -258,15 +258,7 @@
   if (!bo)
     return nullptr;
 
-  // minigbm knows which modifier it chose for the bo it created, and will
-  // tell us if we ask. However, we have to track it as DRM_FORMAT_MOD_INVALID
-  // at this level so we don't try to pass it to addfb2, which may not support
-  // that.  Only when the bo is created with modifiers
-  // (CreateBufferWithModifiers above) do we track the actual modifier, since
-  // we know we can pass it to addfb2 in that case.
-
-  return CreateBufferForBO(gbm, bo, format, size, flags,
-                           DRM_FORMAT_MOD_INVALID);
+  return CreateBufferForBO(gbm, bo, format, size, flags);
 }
 
 // static
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.h b/ui/ozone/platform/drm/gpu/gbm_buffer.h
index 59b0d409..984e7df 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.h
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -79,8 +79,7 @@
       gbm_bo* bo,
       uint32_t format,
       const gfx::Size& size,
-      uint32_t flags,
-      uint64_t modifier);
+      uint32_t flags);
 
   scoped_refptr<GbmDevice> drm_;
   gbm_bo* bo_;
diff --git a/ui/views/vector_icons/vector_icons.cc.template b/ui/views/vector_icons/vector_icons.cc.template
index 9411587..c0e98199 100644
--- a/ui/views/vector_icons/vector_icons.cc.template
+++ b/ui/views/vector_icons/vector_icons.cc.template
@@ -10,11 +10,7 @@
 #include "base/logging.h"
 #include "ui/gfx/vector_icon_types.h"
 
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
 
 namespace views {