diff --git a/DEPS b/DEPS
index a26d3020..2629f49d8 100644
--- a/DEPS
+++ b/DEPS
@@ -64,7 +64,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': '1fe7d8c3819f6c6fdbf34a92146587a2eee8296a',
+  'pdfium_revision': '012ae898a069bda7afbfdad4eb4c8ba042b68dc7',
   # 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.
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 0e15da5..7a74be9 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -310,8 +310,6 @@
     "shelf/wm_shelf.cc",
     "shelf/wm_shelf.h",
     "shelf/wm_shelf_observer.h",
-    "shelf/wm_shelf_util.cc",
-    "shelf/wm_shelf_util.h",
     "shell.cc",
     "shell.h",
     "shell_delegate.h",
@@ -373,7 +371,6 @@
     "system/locale/locale_notification_controller.h",
     "system/media_security/multi_profile_media_tray_item.cc",
     "system/media_security/multi_profile_media_tray_item.h",
-    "system/network/network_detailed_view.h",
     "system/network/network_icon.cc",
     "system/network/network_icon.h",
     "system/network/network_icon_animation.cc",
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 6a6b7c1..7afc2022 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -14,7 +14,6 @@
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_view.h"
 #include "ash/shelf/wm_shelf.h"
-#include "ash/shelf/wm_shelf_util.h"
 #include "ash/shell.h"
 #include "ash/system/status_area_layout_manager.h"
 #include "ash/system/status_area_widget.h"
diff --git a/ash/shelf/wm_shelf_util.cc b/ash/shelf/wm_shelf_util.cc
deleted file mode 100644
index 41934c5..0000000
--- a/ash/shelf/wm_shelf_util.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/shelf/wm_shelf_util.h"
-
-namespace ash {
-
-bool IsHorizontalAlignment(ShelfAlignment alignment) {
-  return alignment == SHELF_ALIGNMENT_BOTTOM ||
-         alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED;
-}
-
-}  // namespace ash
diff --git a/ash/shelf/wm_shelf_util.h b/ash/shelf/wm_shelf_util.h
deleted file mode 100644
index 5176ec9..0000000
--- a/ash/shelf/wm_shelf_util.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SHELF_WM_SHELF_UTIL_H_
-#define ASH_SHELF_WM_SHELF_UTIL_H_
-
-#include "ash/ash_export.h"
-#include "ash/public/cpp/shelf_types.h"
-
-namespace ash {
-
-// Returns true if the shelf |alignment| is horizontal.
-// TODO(jamescook): Remove this in favor of WmShelf::IsHorizontalAlignment().
-ASH_EXPORT bool IsHorizontalAlignment(ShelfAlignment alignment);
-
-}  // namespace ash
-
-#endif  // ASH_SHELF_WM_SHELF_UTIL_H_
diff --git a/ash/system/ime_menu/ime_menu_tray.cc b/ash/system/ime_menu/ime_menu_tray.cc
index e160dbf..721c4385 100644
--- a/ash/system/ime_menu/ime_menu_tray.cc
+++ b/ash/system/ime_menu/ime_menu_tray.cc
@@ -11,7 +11,6 @@
 #include "ash/root_window_controller.h"
 #include "ash/session/session_controller.h"
 #include "ash/shelf/wm_shelf.h"
-#include "ash/shelf/wm_shelf_util.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/strings/grit/ash_strings.h"
diff --git a/ash/system/network/network_detailed_view.h b/ash/system/network/network_detailed_view.h
deleted file mode 100644
index 11a0d451..0000000
--- a/ash/system/network/network_detailed_view.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_NETWORK_NETWORK_DETAILED_VIEW_H_
-#define ASH_SYSTEM_NETWORK_NETWORK_DETAILED_VIEW_H_
-
-#include "ash/system/tray/tray_details_view.h"
-#include "chromeos/network/network_state_handler.h"
-
-namespace ash {
-namespace tray {
-
-// Abstract base class for all NetworkDetailedView derived subclasses,
-// which includes NetworkWifiDetailedView and NetworkStateListDetailedView.
-class NetworkDetailedView : public TrayDetailsView {
- public:
-  enum DetailedViewType {
-    LIST_VIEW,
-    STATE_LIST_VIEW,
-    WIFI_VIEW,
-  };
-
-  explicit NetworkDetailedView(SystemTrayItem* owner)
-      : TrayDetailsView(owner) {}
-
-  virtual void Init() = 0;
-
-  virtual DetailedViewType GetViewType() const = 0;
-
-  // Called when the contents of the network list have changed or when any
-  // Manager properties (e.g. technology state) have changed.
-  // (Called only from TrayNetworkStateObserver).
-  virtual void Update() = 0;
-
- protected:
-  ~NetworkDetailedView() override {}
-};
-
-}  // namespace tray
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_NETWORK_NETWORK_DETAILED_VIEW_H_
diff --git a/ash/system/network/network_state_list_detailed_view.cc b/ash/system/network/network_state_list_detailed_view.cc
index 0a674735..9a01efe 100644
--- a/ash/system/network/network_state_list_detailed_view.cc
+++ b/ash/system/network/network_state_list_detailed_view.cc
@@ -225,7 +225,7 @@
     SystemTrayItem* owner,
     ListType list_type,
     LoginStatus login)
-    : NetworkDetailedView(owner),
+    : TrayDetailsView(owner),
       list_type_(list_type),
       login_(login),
       info_button_(nullptr),
@@ -251,8 +251,6 @@
   Layout();
 }
 
-// Overridden from NetworkDetailedView:
-
 void NetworkStateListDetailedView::Init() {
   Reset();
   info_button_ = nullptr;
@@ -271,11 +269,6 @@
     CallRequestScan();
 }
 
-NetworkDetailedView::DetailedViewType
-NetworkStateListDetailedView::GetViewType() const {
-  return STATE_LIST_VIEW;
-}
-
 void NetworkStateListDetailedView::HandleButtonPressed(views::Button* sender,
                                                        const ui::Event& event) {
   if (sender == info_button_) {
diff --git a/ash/system/network/network_state_list_detailed_view.h b/ash/system/network/network_state_list_detailed_view.h
index 02a036a..50d87dc 100644
--- a/ash/system/network/network_state_list_detailed_view.h
+++ b/ash/system/network/network_state_list_detailed_view.h
@@ -9,8 +9,8 @@
 #include <string>
 
 #include "ash/login_status.h"
-#include "ash/system/network/network_detailed_view.h"
 #include "ash/system/network/network_list_delegate.h"
+#include "ash/system/tray/tray_details_view.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "ui/gfx/image/image.h"
@@ -35,7 +35,7 @@
 namespace tray {
 
 class NetworkStateListDetailedView
-    : public NetworkDetailedView,
+    : public TrayDetailsView,
       public NetworkListDelegate,
       public base::SupportsWeakPtr<NetworkStateListDetailedView> {
  public:
@@ -46,10 +46,11 @@
                                LoginStatus login);
   ~NetworkStateListDetailedView() override;
 
-  // Overridden from NetworkDetailedView:
-  void Init() override;
-  DetailedViewType GetViewType() const override;
-  void Update() override;
+  void Init();
+
+  // Called when the contents of the network list have changed or when any
+  // Manager properties (e.g. technology state) have changed.
+  void Update();
 
  private:
   class InfoBubble;
diff --git a/ash/system/network/tray_network.cc b/ash/system/network/tray_network.cc
index 3081eea..5e71342a 100644
--- a/ash/system/network/tray_network.cc
+++ b/ash/system/network/tray_network.cc
@@ -4,7 +4,6 @@
 
 #include "ash/system/network/tray_network.h"
 
-#include "ash/shelf/wm_shelf_util.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/strings/grit/ash_strings.h"
diff --git a/ash/system/network/tray_network.h b/ash/system/network/tray_network.h
index b023d195..0edcbac 100644
--- a/ash/system/network/tray_network.h
+++ b/ash/system/network/tray_network.h
@@ -18,7 +18,7 @@
 namespace ash {
 namespace tray {
 class NetworkDefaultView;
-class NetworkDetailedView;
+class NetworkStateListDetailedView;
 class NetworkTrayView;
 }
 
@@ -30,7 +30,7 @@
   explicit TrayNetwork(SystemTray* system_tray);
   ~TrayNetwork() override;
 
-  tray::NetworkDetailedView* detailed() { return detailed_; }
+  tray::NetworkStateListDetailedView* detailed() { return detailed_; }
 
   // SystemTrayItem
   views::View* CreateTrayView(LoginStatus status) override;
@@ -52,7 +52,7 @@
  private:
   tray::NetworkTrayView* tray_;
   tray::NetworkDefaultView* default_;
-  tray::NetworkDetailedView* detailed_;
+  tray::NetworkStateListDetailedView* detailed_;
   std::unique_ptr<TrayNetworkStateObserver> network_state_observer_;
 
   DISALLOW_COPY_AND_ASSIGN(TrayNetwork);
diff --git a/ash/system/network/tray_vpn.h b/ash/system/network/tray_vpn.h
index 21a4bd6..80e9622 100644
--- a/ash/system/network/tray_vpn.h
+++ b/ash/system/network/tray_vpn.h
@@ -15,7 +15,7 @@
 class TrayNetworkStateObserver;
 
 namespace tray {
-class NetworkDetailedView;
+class NetworkStateListDetailedView;
 class VpnDefaultView;
 }
 
@@ -36,7 +36,7 @@
 
  private:
   tray::VpnDefaultView* default_;
-  tray::NetworkDetailedView* detailed_;
+  tray::NetworkStateListDetailedView* detailed_;
   std::unique_ptr<TrayNetworkStateObserver> network_state_observer_;
 
   DISALLOW_COPY_AND_ASSIGN(TrayVPN);
diff --git a/ash/system/palette/palette_tray.cc b/ash/system/palette/palette_tray.cc
index f6c46f8..97a2cca 100644
--- a/ash/system/palette/palette_tray.cc
+++ b/ash/system/palette/palette_tray.cc
@@ -11,7 +11,6 @@
 #include "ash/session/session_controller.h"
 #include "ash/shelf/shelf_constants.h"
 #include "ash/shelf/wm_shelf.h"
-#include "ash/shelf/wm_shelf_util.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/palette/palette_tool_manager.h"
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
index 5c963cf..65de3c1 100644
--- a/ash/system/tray/system_tray.cc
+++ b/ash/system/tray/system_tray.cc
@@ -14,7 +14,6 @@
 #include "ash/root_window_controller.h"
 #include "ash/session/session_controller.h"
 #include "ash/shelf/wm_shelf.h"
-#include "ash/shelf/wm_shelf_util.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/strings/grit/ash_strings.h"
diff --git a/ash/system/tray/tray_image_item.cc b/ash/system/tray/tray_image_item.cc
index bc90194a..ca45de2f 100644
--- a/ash/system/tray/tray_image_item.cc
+++ b/ash/system/tray/tray_image_item.cc
@@ -5,7 +5,6 @@
 #include "ash/system/tray/tray_image_item.h"
 
 #include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/shelf/wm_shelf_util.h"
 #include "ash/system/tray/system_tray.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ash/system/tray/tray_item_view.h"
diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc
index e3bc136..2b0b8d4 100644
--- a/ash/system/web_notification/web_notification_tray.cc
+++ b/ash/system/web_notification/web_notification_tray.cc
@@ -10,7 +10,6 @@
 #include "ash/session/session_controller.h"
 #include "ash/shelf/shelf_constants.h"
 #include "ash/shelf/wm_shelf.h"
-#include "ash/shelf/wm_shelf_util.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/status_area_widget.h"
diff --git a/ash/wm/panels/panel_layout_manager.cc b/ash/wm/panels/panel_layout_manager.cc
index 6478520..aaedc7c 100644
--- a/ash/wm/panels/panel_layout_manager.cc
+++ b/ash/wm/panels/panel_layout_manager.cc
@@ -13,7 +13,6 @@
 #include "ash/public/cpp/window_properties.h"
 #include "ash/root_window_controller.h"
 #include "ash/shelf/wm_shelf.h"
-#include "ash/shelf/wm_shelf_util.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/wm/overview/window_selector_controller.h"
@@ -188,10 +187,11 @@
     InitWidget(container);
   }
 
-  void SetAlignment(ShelfAlignment alignment) {
+  // Updates the bounds based on the shelf alignment.
+  void UpdateBounds(WmShelf* shelf) {
     WmWindow* window = WmWindow::Get(this->GetNativeWindow());
     gfx::Rect callout_bounds = window->GetBounds();
-    if (IsHorizontalAlignment(alignment)) {
+    if (shelf->IsHorizontalAlignment()) {
       callout_bounds.set_width(kArrowWidth);
       callout_bounds.set_height(kArrowHeight);
     } else {
@@ -204,8 +204,8 @@
     window->SetBounds(callout_bounds);
     // Setting the bounds should not trigger changing the parent.
     DCHECK_EQ(parent, window->GetParent());
-    if (background_->alignment() != alignment) {
-      background_->set_alignment(alignment);
+    if (background_->alignment() != shelf->alignment()) {
+      background_->set_alignment(shelf->alignment());
       SchedulePaintInRect(gfx::Rect(callout_bounds.size()));
     }
   }
@@ -623,7 +623,6 @@
 
   base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
 
-  const ShelfAlignment alignment = shelf_->GetAlignment();
   const bool horizontal = shelf_->IsHorizontalAlignment();
   gfx::Rect shelf_bounds = panel_container_->ConvertRectFromScreen(
       shelf_->GetWindow()->GetBoundsInScreen());
@@ -636,7 +635,7 @@
   for (PanelList::iterator iter = panel_windows_.begin();
        iter != panel_windows_.end(); ++iter) {
     WmWindow* panel = iter->window;
-    iter->callout_widget->SetAlignment(alignment);
+    iter->callout_widget->UpdateBounds(shelf_);
 
     // Consider the dragged panel as part of the layout as long as it is
     // touching the shelf.
@@ -715,9 +714,9 @@
       continue;
     bool slide_in = visible_panels[i].slide_in;
     gfx::Rect bounds = visible_panels[i].window->GetTargetBounds();
-    if (alignment == SHELF_ALIGNMENT_LEFT)
+    if (shelf_->alignment() == SHELF_ALIGNMENT_LEFT)
       bounds.set_x(shelf_bounds.right());
-    else if (alignment == SHELF_ALIGNMENT_RIGHT)
+    else if (shelf_->alignment() == SHELF_ALIGNMENT_RIGHT)
       bounds.set_x(shelf_bounds.x() - bounds.width());
     else
       bounds.set_y(shelf_bounds.y() - bounds.height());
@@ -736,7 +735,7 @@
       // New windows shift up from the shelf into position and fade in.
       layer->SetOpacity(0);
       gfx::Rect initial_bounds(bounds);
-      initial_bounds.Offset(GetSlideInAnimationOffset(alignment));
+      initial_bounds.Offset(GetSlideInAnimationOffset(shelf_->alignment()));
       visible_panels[i].window->SetBoundsDirect(initial_bounds);
       // Set on shelf so that the panel animates into its target position.
       on_shelf = true;
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index 0f4c058..34b0c2d 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -71,14 +71,13 @@
 
 #endif  // COMPILER_MSVC
 
-
 // Annotate a variable indicating it's ok if the variable is not used.
 // (Typically used to silence a compiler warning when the assignment
 // is important for some other reason.)
 // Use like:
 //   int x = ...;
 //   ALLOW_UNUSED_LOCAL(x);
-#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0
+#define ALLOW_UNUSED_LOCAL(x) (void)x
 
 // Annotate a typedef or function indicating it's ok if it's not used.
 // Use like:
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index 10e5d1b1..02f2a6a 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -181,7 +181,8 @@
 }
 
 MemoryDumpManager::MemoryDumpManager()
-    : memory_tracing_enabled_(0),
+    : is_coordinator_(false),
+      memory_tracing_enabled_(0),
       tracing_process_id_(kInvalidTracingProcessId),
       dumper_registrations_ignored_for_testing_(false),
       heap_profiling_enabled_(false) {
@@ -237,12 +238,14 @@
 }
 
 void MemoryDumpManager::Initialize(
-    std::unique_ptr<MemoryDumpManagerDelegate> delegate) {
+    RequestGlobalDumpFunction request_dump_function,
+    bool is_coordinator) {
   {
     AutoLock lock(lock_);
-    DCHECK(delegate);
-    DCHECK(!delegate_);
-    delegate_ = std::move(delegate);
+    DCHECK(!request_dump_function.is_null());
+    DCHECK(request_dump_function_.is_null());
+    request_dump_function_ = request_dump_function;
+    is_coordinator_ = is_coordinator;
     EnableHeapProfilingIfNeeded();
   }
 
@@ -456,10 +459,10 @@
       MemoryDumpLevelOfDetailToString(level_of_detail));
   GlobalMemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback);
 
-  // The delegate will coordinate the IPC broadcast and at some point invoke
+  // The embedder will coordinate the IPC broadcast and at some point invoke
   // CreateProcessDump() to get a dump for the current process.
   MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail};
-  delegate_->RequestGlobalMemoryDump(args, wrapped_callback);
+  request_dump_function_.Run(args, wrapped_callback);
 }
 
 void MemoryDumpManager::GetDumpProvidersForPolling(
@@ -823,7 +826,8 @@
 
   AutoLock lock(lock_);
 
-  DCHECK(delegate_);  // At this point we must have a delegate.
+  // At this point we must have the ability to request global dumps.
+  DCHECK(!request_dump_function_.is_null());
   session_state_ = session_state;
 
   DCHECK(!dump_thread_);
@@ -863,7 +867,7 @@
 
       // When peak detection is enabled, trigger a dump straight away as it
       // gives a good reference point for analyzing the trace.
-      if (delegate_->IsCoordinator()) {
+      if (is_coordinator_) {
         dump_thread_->task_runner()->PostTask(
             FROM_HERE, BindRepeating(&OnPeakDetected, trigger.level_of_detail));
       }
@@ -871,7 +875,7 @@
   }
 
   // Only coordinator process triggers periodic global memory dumps.
-  if (delegate_->IsCoordinator() && !periodic_config.triggers.empty()) {
+  if (is_coordinator_ && !periodic_config.triggers.empty()) {
     MemoryDumpScheduler::GetInstance()->Start(periodic_config,
                                               dump_thread_->task_runner());
   }
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h
index 1583c9e..7d35ca5c 100644
--- a/base/trace_event/memory_dump_manager.h
+++ b/base/trace_event/memory_dump_manager.h
@@ -24,11 +24,11 @@
 #include "base/trace_event/process_memory_dump.h"
 #include "base/trace_event/trace_event.h"
 
-// Forward declare |MemoryDumpManagerDelegateImplTest| so that we can make it a
+// Forward declare |ProcessLocalDumpManagerImplTest| so that we can make it a
 // friend of |MemoryDumpManager| and give it access to |SetInstanceForTesting|.
 namespace memory_instrumentation {
 
-class MemoryDumpManagerDelegateImplTest;
+class ProcessLocalDumpManagerImplTest;
 
 }  // namespace memory_instrumentation
 
@@ -40,7 +40,6 @@
 namespace trace_event {
 
 class MemoryTracingObserver;
-class MemoryDumpManagerDelegate;
 class MemoryDumpProvider;
 class MemoryDumpSessionState;
 
@@ -49,6 +48,10 @@
 // RequestDumpPoint(). The extension by Un(RegisterDumpProvider).
 class BASE_EXPORT MemoryDumpManager {
  public:
+  using RequestGlobalDumpFunction =
+      RepeatingCallback<void(const MemoryDumpRequestArgs& args,
+                             const GlobalMemoryDumpCallback& callback)>;
+
   static const char* const kTraceCategory;
   static const char* const kLogPrefix;
 
@@ -64,10 +67,12 @@
   // On the other side, the MemoryDumpManager will not be fully operational
   // (i.e. will NACK any RequestGlobalMemoryDump()) until initialized.
   // Arguments:
-  //  delegate: inversion-of-control interface for embedder-specific behaviors
-  //      (multiprocess handshaking). See the lifetime and thread-safety
-  //      requirements in the |MemoryDumpManagerDelegate| docstring.
-  void Initialize(std::unique_ptr<MemoryDumpManagerDelegate> delegate);
+  //  request_dump_function: Function to invoke a global dump. Global dump
+  //      involves embedder-specific behaviors like multiprocess handshaking.
+  //  is_coordinator: True when current process coodinates the periodic dump
+  //      triggering.
+  void Initialize(RequestGlobalDumpFunction request_dump_function,
+                  bool is_coordinator);
 
   // (Un)Registers a MemoryDumpProvider instance.
   // Args:
@@ -130,6 +135,14 @@
   // Enable.
   void Disable();
 
+  // NOTE: Use RequestGlobalDump() to create memory dumps. Creates a memory dump
+  // for the current process and appends it to the trace. |callback| will be
+  // invoked asynchronously upon completion on the same thread on which
+  // CreateProcessDump() was called. This method should only be used by the
+  // embedder while creating a global memory dump.
+  void CreateProcessDump(const MemoryDumpRequestArgs& args,
+                         const ProcessMemoryDumpCallback& callback);
+
   // Enable heap profiling if kEnableHeapProfiling is specified.
   void EnableHeapProfilingIfNeeded();
 
@@ -172,9 +185,8 @@
  private:
   friend std::default_delete<MemoryDumpManager>;  // For the testing instance.
   friend struct DefaultSingletonTraits<MemoryDumpManager>;
-  friend class MemoryDumpManagerDelegate;
   friend class MemoryDumpManagerTest;
-  friend class memory_instrumentation::MemoryDumpManagerDelegateImplTest;
+  friend class memory_instrumentation::ProcessLocalDumpManagerImplTest;
 
   // Holds the state of a process memory dump that needs to be carried over
   // across task runners in order to fulfil an asynchronous CreateProcessDump()
@@ -245,13 +257,6 @@
   void FinalizeDumpAndAddToTrace(
       std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state);
 
-  // Internal, used only by MemoryDumpManagerDelegate.
-  // Creates a memory dump for the current process and appends it to the trace.
-  // |callback| will be invoked asynchronously upon completion on the same
-  // thread on which CreateProcessDump() was called.
-  void CreateProcessDump(const MemoryDumpRequestArgs& args,
-                         const ProcessMemoryDumpCallback& callback);
-
   // Calls InvokeOnMemoryDump() for the next MDP on the task runner specified by
   // the MDP while registration. On failure to do so, skips and continues to
   // next MDP.
@@ -291,11 +296,16 @@
   std::unordered_set<StringPiece, StringPieceHash>
       strict_thread_check_blacklist_;
 
-  std::unique_ptr<MemoryDumpManagerDelegate> delegate_;
   std::unique_ptr<MemoryTracingObserver> tracing_observer_;
 
-  // Protects from concurrent accesses to the |dump_providers_*| and |delegate_|
-  // to guard against disabling logging while dumping on another thread.
+  // Function provided by the embedder to handle global dump requests.
+  RequestGlobalDumpFunction request_dump_function_;
+
+  // True when current process coordinates the periodic dump triggering.
+  bool is_coordinator_;
+
+  // Protects from concurrent accesses to the local state, eg: to guard against
+  // disabling logging while dumping on another thread.
   Lock lock_;
 
   // Optimization to avoid attempting any memory dump (i.e. to not walk an empty
@@ -319,29 +329,6 @@
   DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager);
 };
 
-// The delegate is supposed to be long lived (read: a Singleton) and thread
-// safe (i.e. should expect calls from any thread and handle thread hopping).
-class BASE_EXPORT MemoryDumpManagerDelegate {
- public:
-  MemoryDumpManagerDelegate() {}
-  virtual ~MemoryDumpManagerDelegate() {}
-
-  virtual void RequestGlobalMemoryDump(
-      const MemoryDumpRequestArgs& args,
-      const GlobalMemoryDumpCallback& callback) = 0;
-
-  virtual bool IsCoordinator() const = 0;
-
- protected:
-  void CreateProcessDump(const MemoryDumpRequestArgs& args,
-                         const ProcessMemoryDumpCallback& callback) {
-    MemoryDumpManager::GetInstance()->CreateProcessDump(args, callback);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MemoryDumpManagerDelegate);
-};
-
 }  // namespace trace_event
 }  // namespace base
 
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
index 2bbfd3b..732b5c8 100644
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -128,32 +128,25 @@
   callback.Run(dump_guid, success);
 }
 
-// Testing MemoryDumpManagerDelegate which, by default, short-circuits dump
-// requests locally to the MemoryDumpManager instead of performing IPC dances.
-class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate {
+// This mocks the RequestGlobalDumpFunction which is typically handled by
+// process_local_dump_manager_impl.cc, by short-circuiting dump requests locally
+// to the MemoryDumpManager without an actual service.
+class GlobalMemoryDumpHandler {
  public:
-  MemoryDumpManagerDelegateForTesting(bool is_coordinator)
-      : is_coordinator_(is_coordinator) {
+  MOCK_METHOD2(RequestGlobalMemoryDump,
+               void(const MemoryDumpRequestArgs& args,
+                    const GlobalMemoryDumpCallback& callback));
+
+  GlobalMemoryDumpHandler() {
     ON_CALL(*this, RequestGlobalMemoryDump(_, _))
         .WillByDefault(Invoke([this](const MemoryDumpRequestArgs& args,
                                      const GlobalMemoryDumpCallback& callback) {
           ProcessMemoryDumpCallback process_callback =
               Bind(&ProcessDumpCallbackAdapter, callback);
-          CreateProcessDump(args, process_callback);
+          MemoryDumpManager::GetInstance()->CreateProcessDump(args,
+                                                              process_callback);
         }));
   }
-
-  MOCK_METHOD2(RequestGlobalMemoryDump,
-               void(const MemoryDumpRequestArgs& args,
-                    const GlobalMemoryDumpCallback& callback));
-
-  bool IsCoordinator() const override { return is_coordinator_; }
-
-  // Promote the CreateProcessDump to public so it can be used by test fixtures.
-  using MemoryDumpManagerDelegate::CreateProcessDump;
-
- private:
-  bool is_coordinator_;
 };
 
 class MockMemoryDumpProvider : public MemoryDumpProvider {
@@ -244,7 +237,6 @@
 
   void TearDown() override {
     MemoryDumpManager::SetInstanceForTesting(nullptr);
-    delegate_ = nullptr;
     mdm_.reset();
     message_loop_.reset();
     TraceLog::DeleteForTesting();
@@ -265,8 +257,10 @@
  protected:
   void InitializeMemoryDumpManager(bool is_coordinator) {
     mdm_->set_dumper_registrations_ignored_for_testing(true);
-    delegate_ = new MemoryDumpManagerDelegateForTesting(is_coordinator);
-    mdm_->Initialize(base::WrapUnique(delegate_));
+    mdm_->Initialize(
+        BindRepeating(&GlobalMemoryDumpHandler::RequestGlobalMemoryDump,
+                      Unretained(&global_dump_handler_)),
+        is_coordinator);
   }
 
   void RequestGlobalDumpAndWait(MemoryDumpType dump_type,
@@ -301,7 +295,7 @@
 
   const MemoryDumpProvider::Options kDefaultOptions;
   std::unique_ptr<MemoryDumpManager> mdm_;
-  MemoryDumpManagerDelegateForTesting* delegate_;
+  GlobalMemoryDumpHandler global_dump_handler_;
   bool last_callback_success_;
 
  private:
@@ -320,7 +314,7 @@
 
   // Check that the dumper is not called if the memory category is not enabled.
   EnableTracingWithLegacyCategories("foobar-but-not-memory");
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(0);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(0);
   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
                            MemoryDumpLevelOfDetail::DETAILED);
@@ -329,7 +323,7 @@
   // Now repeat enabling the memory category and check that the dumper is
   // invoked this time.
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(3);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(3);
   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(3).WillRepeatedly(Return(true));
   for (int i = 0; i < 3; ++i) {
     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
@@ -339,10 +333,10 @@
 
   mdm_->UnregisterDumpProvider(&mdp);
 
-  // Finally check the unregister logic: the delegate will be invoked but not
-  // the dump provider, as it has been unregistered.
+  // Finally check the unregister logic: the global dump handler will be invoked
+  // but not the dump provider, as it has been unregistered.
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(3);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(3);
   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
 
   for (int i = 0; i < 3; ++i) {
@@ -360,7 +354,7 @@
 
   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
   EXPECT_CALL(mdp, OnMemoryDump(IsDetailedDump(), _)).WillOnce(Return(true));
   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
                            MemoryDumpLevelOfDetail::DETAILED);
@@ -371,7 +365,7 @@
   // OnMemoryDump() call on dump providers.
   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
   EXPECT_CALL(mdp, OnMemoryDump(IsLightDump(), _)).WillOnce(Return(true));
   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
                            MemoryDumpLevelOfDetail::LIGHT);
@@ -390,7 +384,7 @@
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
   const MemoryDumpSessionState* session_state =
       mdm_->session_state_for_testing().get();
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(2);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(2);
   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
       .Times(2)
       .WillRepeatedly(Invoke([session_state](const MemoryDumpArgs&,
@@ -423,7 +417,7 @@
   // Enable only mdp1.
   RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get());
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).WillOnce(Return(true));
   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(0);
   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
@@ -434,7 +428,7 @@
   mdm_->UnregisterDumpProvider(&mdp1);
   RegisterDumpProvider(&mdp2, nullptr);
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0);
   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).WillOnce(Return(true));
   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
@@ -444,7 +438,7 @@
   // Enable both mdp1 and mdp2.
   RegisterDumpProvider(&mdp1, nullptr);
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).WillOnce(Return(true));
   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).WillOnce(Return(true));
   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
@@ -467,7 +461,7 @@
   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
 
   {
-    EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+    EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
     EXPECT_CALL(mdp, OnMemoryDump(_, _)).WillOnce(Return(true));
     EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
@@ -478,7 +472,7 @@
   mdm_->UnregisterDumpProvider(&mdp);
 
   {
-    EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+    EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
     EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
@@ -490,7 +484,7 @@
   mdm_->UnregisterDumpProvider(&mdp);
 
   {
-    EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+    EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
     EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
@@ -503,7 +497,7 @@
   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
 
   {
-    EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+    EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
     EXPECT_CALL(mdp, OnMemoryDump(_, _)).WillOnce(Return(true));
     EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
@@ -546,7 +540,7 @@
 
   while (!threads.empty()) {
     last_callback_success_ = false;
-    EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+    EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
                              MemoryDumpLevelOfDetail::DETAILED);
     EXPECT_TRUE(last_callback_success_);
@@ -591,7 +585,7 @@
   EXPECT_CALL(mdps[0], OnMemoryDump(_, _)).Times(0);
   EXPECT_CALL(mdps[1], OnMemoryDump(_, _)).Times(2);
   EXPECT_CALL(mdps[2], OnMemoryDump(_, _)).Times(2);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(2);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(2);
 
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
 
@@ -627,7 +621,8 @@
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
 
   const int kNumDumps = 2 * GetMaxConsecutiveFailuresCount();
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(kNumDumps);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _))
+      .Times(kNumDumps);
 
   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
       .Times(GetMaxConsecutiveFailuresCount())
@@ -659,7 +654,7 @@
   RegisterDumpProvider(&mdp1, nullptr);
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
 
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(4);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(4);
 
   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
       .Times(4)
@@ -695,7 +690,7 @@
   RegisterDumpProvider(&mdp2, ThreadTaskRunnerHandle::Get(), kDefaultOptions);
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
 
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(4);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(4);
 
   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
       .Times(4)
@@ -765,7 +760,7 @@
 
   last_callback_success_ = false;
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
                            MemoryDumpLevelOfDetail::DETAILED);
   ASSERT_EQ(1, on_memory_dump_call_count);
@@ -867,7 +862,7 @@
 
   last_callback_success_ = false;
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
                            MemoryDumpLevelOfDetail::DETAILED);
   ASSERT_EQ(1, on_memory_dump_call_count);
@@ -883,7 +878,7 @@
   MockMemoryDumpProvider mdp1;
   RegisterDumpProvider(&mdp1, nullptr);
 
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(0);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(0);
   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0);
 
   last_callback_success_ = true;
@@ -913,7 +908,7 @@
   {
     InitializeMemoryDumpManager(false /* is_coordinator */);
     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(1);
-    EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+    EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
                              MemoryDumpLevelOfDetail::DETAILED);
     EXPECT_TRUE(last_callback_success_);
@@ -927,14 +922,14 @@
 // and the new-style (JSON-based) TraceConfig.
 TEST_F(MemoryDumpManagerTest, TraceConfigExpectations) {
   InitializeMemoryDumpManager(false /* is_coordinator */);
-  MemoryDumpManagerDelegateForTesting& delegate = *delegate_;
 
-  // Don't trigger the default behavior of the mock delegate in this test,
+  // Don't trigger the default behavior of the global dump handler in this test,
   // which would short-circuit the dump request to the actual
   // CreateProcessDump().
   // We don't want to create any dump in this test, only check whether the dumps
   // are requested or not.
-  ON_CALL(delegate, RequestGlobalMemoryDump(_, _)).WillByDefault(Return());
+  ON_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _))
+      .WillByDefault(Return());
 
   // Enabling memory-infra in a non-coordinator process should not trigger any
   // periodic dumps.
@@ -953,8 +948,8 @@
 
 TEST_F(MemoryDumpManagerTest, TraceConfigExpectationsWhenIsCoordinator) {
   InitializeMemoryDumpManager(true /* is_coordinator */);
-  MemoryDumpManagerDelegateForTesting& delegate = *delegate_;
-  ON_CALL(delegate, RequestGlobalMemoryDump(_, _)).WillByDefault(Return());
+  ON_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _))
+      .WillByDefault(Return());
 
   // Enabling memory-infra with the legacy TraceConfig (category filter) in
   // a coordinator process should enable periodic dumps.
@@ -992,13 +987,15 @@
   const int kHeavyDumpPeriodMs = kHeavyDumpRate * kLightDumpPeriodMs;
   // The expected sequence with light=1ms, heavy=5ms is H,L,L,L,L,H,...
   testing::InSequence sequence;
-  EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsDetailedDump(), _));
-  EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLightDump(), _))
+  EXPECT_CALL(global_dump_handler_,
+              RequestGlobalMemoryDump(IsDetailedDump(), _));
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(IsLightDump(), _))
       .Times(kHeavyDumpRate - 1);
-  EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsDetailedDump(), _));
-  EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLightDump(), _))
+  EXPECT_CALL(global_dump_handler_,
+              RequestGlobalMemoryDump(IsDetailedDump(), _));
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(IsLightDump(), _))
       .Times(kHeavyDumpRate - 2);
-  EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLightDump(), _))
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(IsLightDump(), _))
       .WillOnce(Invoke([test_task_runner, quit_closure](
                            const MemoryDumpRequestArgs& args,
                            const GlobalMemoryDumpCallback& callback) {
@@ -1006,7 +1003,8 @@
       }));
 
   // Swallow all the final spurious calls until tracing gets disabled.
-  EXPECT_CALL(delegate, RequestGlobalMemoryDump(_, _)).Times(AnyNumber());
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _))
+      .Times(AnyNumber());
 
   EnableTracingWithTraceConfig(
       TraceConfigMemoryTestUtil::GetTraceConfig_PeriodicTriggers(
@@ -1033,13 +1031,13 @@
   RegisterDumpProvider(&mdp2, mdp_thread->task_runner(), kDefaultOptions);
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
 
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _))
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _))
       .WillOnce(Invoke([this](const MemoryDumpRequestArgs& args,
                               const GlobalMemoryDumpCallback& callback) {
         DisableTracing();
         ProcessMemoryDumpCallback process_callback =
             Bind(&ProcessDumpCallbackAdapter, callback);
-        delegate_->CreateProcessDump(args, process_callback);
+        mdm_->CreateProcessDump(args, process_callback);
       }));
 
   // If tracing is disabled for current session CreateProcessDump() should NOT
@@ -1074,7 +1072,7 @@
   RegisterDumpProvider(&mdp3, nullptr, options);
 
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true));
   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true));
   EXPECT_CALL(mdp3, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true));
@@ -1168,7 +1166,7 @@
       }));
 
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(2);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(2);
   for (int i = 0; i < 2; ++i) {
     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
                              MemoryDumpLevelOfDetail::DETAILED);
@@ -1187,7 +1185,7 @@
 
   EXPECT_CALL(*mdp1, OnMemoryDump(_, _)).Times(0);
   EXPECT_CALL(*mdp2, OnMemoryDump(_, _)).Times(1).WillOnce(Return(true));
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(1);
 
   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
   EXPECT_FALSE(IsPeriodicDumpingEnabled());
@@ -1204,15 +1202,18 @@
   auto quit_closure = run_loop.QuitClosure();
 
   testing::InSequence sequence;
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(IsBackgroundDump(), _))
+  EXPECT_CALL(global_dump_handler_,
+              RequestGlobalMemoryDump(IsBackgroundDump(), _))
       .Times(5);
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(IsBackgroundDump(), _))
+  EXPECT_CALL(global_dump_handler_,
+              RequestGlobalMemoryDump(IsBackgroundDump(), _))
       .WillOnce(Invoke([test_task_runner, quit_closure](
                            const MemoryDumpRequestArgs& args,
                            const GlobalMemoryDumpCallback& callback) {
         test_task_runner->PostTask(FROM_HERE, quit_closure);
       }));
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(AnyNumber());
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _))
+      .Times(AnyNumber());
 
   EnableTracingWithTraceConfig(
       TraceConfigMemoryTestUtil::GetTraceConfig_BackgroundTrigger(
@@ -1265,7 +1266,7 @@
 
   mdm_->Enable(memory_dump_config);
 
-  EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(3);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(3);
   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(3).WillRepeatedly(Return(true));
   last_callback_success_ = true;
   for (int i = 0; i < 3; ++i)
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 94edce6..6d0b4b1 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -2133,7 +2133,7 @@
                                                    pending_raster_source);
   pending_layer->SetDrawsContent(true);
   pending_tree->SetRootLayerForTesting(std::move(pending_layer));
-  pending_tree->BuildLayerListForTesting();
+  pending_tree->BuildLayerListAndPropertyTreesForTesting();
 
   FakePictureLayerImpl* raw_pending_layer = static_cast<FakePictureLayerImpl*>(
       host_impl()->pending_tree()->LayerById(layer_id()));
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index 1ba4387..e7dfd332 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -186,6 +186,7 @@
 
   layer->SavePaintProperties();
   layer->Update();
+  host->BuildPropertyTreesForTesting();
 
   FakeImplTaskRunnerProvider impl_task_runner_provider;
 
@@ -201,7 +202,7 @@
   host_impl.CreatePendingTree();
   host_impl.pending_tree()->SetRootLayerForTesting(
       FakePictureLayerImpl::Create(host_impl.pending_tree(), 1));
-  host_impl.pending_tree()->BuildLayerListForTesting();
+  host_impl.pending_tree()->BuildLayerListAndPropertyTreesForTesting();
 
   FakePictureLayerImpl* layer_impl = static_cast<FakePictureLayerImpl*>(
       host_impl.pending_tree()->root_layer_for_testing());
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index da575b2..6e8cf704 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -385,6 +385,7 @@
   LayerImpl* root_clip_layer_impl = nullptr;
   PaintedScrollbarLayerImpl* scrollbar_layer_impl = nullptr;
 
+  layer_tree_host_->BuildPropertyTreesForTesting();
   UPDATE_AND_EXTRACT_LAYER_POINTERS();
   EXPECT_EQ(gfx::Rect(10, 0, 4, 10).ToString(),
             scrollbar_layer_impl->ComputeThumbQuadRect().ToString());
@@ -744,8 +745,10 @@
   layer_tree_root->SetBounds(gfx::Size(2, 2));
   scroll_layer->SetBounds(gfx::Size(10, 10));
   layer_tree_host_->UpdateLayers();
-  layer_tree_host_->CommitAndCreateLayerImplTree();
   LayerTreeHostImpl* host_impl = layer_tree_host_->host_impl();
+  host_impl->CreatePendingTree();
+  layer_tree_host_->CommitAndCreatePendingTree();
+  host_impl->ActivateSyncTree();
   EXPECT_TRUE(host_impl->ScrollbarAnimationControllerForElementId(
       scroll_layer->element_id()));
 
diff --git a/cc/trees/tree_synchronizer.cc b/cc/trees/tree_synchronizer.cc
index 52f1bb38..87efee0 100644
--- a/cc/trees/tree_synchronizer.cc
+++ b/cc/trees/tree_synchronizer.cc
@@ -74,6 +74,25 @@
   return layer_impl;
 }
 
+#if DCHECK_IS_ON()
+template <typename LayerType>
+static void AssertValidPropertyTreeIndices(LayerType* layer) {
+  DCHECK(layer);
+  DCHECK_NE(layer->transform_tree_index(), TransformTree::kInvalidNodeId);
+  DCHECK_NE(layer->effect_tree_index(), EffectTree::kInvalidNodeId);
+  DCHECK_NE(layer->clip_tree_index(), ClipTree::kInvalidNodeId);
+  DCHECK_NE(layer->scroll_tree_index(), ScrollTree::kInvalidNodeId);
+}
+
+static bool LayerHasValidPropertyTreeIndices(LayerImpl* layer) {
+  DCHECK(layer);
+  return layer->transform_tree_index() != TransformTree::kInvalidNodeId &&
+         layer->effect_tree_index() != EffectTree::kInvalidNodeId &&
+         layer->clip_tree_index() != ClipTree::kInvalidNodeId &&
+         layer->scroll_tree_index() != ScrollTree::kInvalidNodeId;
+}
+#endif
+
 template <typename LayerTreeType>
 void PushLayerList(OwnedLayerImplMap* old_layers,
                    LayerTreeType* host,
@@ -83,6 +102,15 @@
     std::unique_ptr<LayerImpl> layer_impl(
         ReuseOrCreateLayerImpl(old_layers, layer, tree_impl));
 
+#if DCHECK_IS_ON()
+    // Every layer should have valid property tree indices
+    AssertValidPropertyTreeIndices(layer);
+    // Every layer_impl should either have valid property tree indices already
+    // or the corresponding layer should push them onto layer_impl.
+    DCHECK(LayerHasValidPropertyTreeIndices(layer_impl.get()) ||
+           host->LayerNeedsPushPropertiesForTesting(layer));
+#endif
+
     tree_impl->AddToLayerList(layer_impl.get());
     tree_impl->AddLayer(std::move(layer_impl));
   }
diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc
index cbae4e4a..f06a4ad 100644
--- a/cc/trees/tree_synchronizer_unittest.cc
+++ b/cc/trees/tree_synchronizer_unittest.cc
@@ -165,6 +165,7 @@
   layer_tree_root->AddChild(Layer::Create());
 
   host_->SetRootLayer(layer_tree_root);
+  host_->BuildPropertyTreesForTesting();
 
   TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
                                      host_->active_tree());
@@ -186,6 +187,7 @@
   int second_layer_impl_id = layer_tree_root->children()[1]->id();
 
   host_->SetRootLayer(layer_tree_root);
+  host_->BuildPropertyTreesForTesting();
 
   TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
                                      host_->active_tree());
@@ -206,6 +208,7 @@
 
   // Synchronize again. After the sync the trees should be equivalent and we
   // should have created and destroyed one LayerImpl.
+  host_->BuildPropertyTreesForTesting();
   TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
                                      host_->active_tree());
   layer_impl_tree_root = host_->active_tree()->root_layer_for_testing();
@@ -236,6 +239,7 @@
 
   host_->SetRootLayer(layer_tree_root);
 
+  host_->BuildPropertyTreesForTesting();
   TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
                                      host_->active_tree());
   LayerImpl* layer_impl_tree_root =
@@ -252,12 +256,15 @@
   // re-insert the layer and sync again.
   child2->RemoveFromParent();
   layer_tree_root->AddChild(child2);
+  host_->BuildPropertyTreesForTesting();
   TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
                                      host_->active_tree());
   layer_impl_tree_root = host_->active_tree()->root_layer_for_testing();
   ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root,
                           host_->active_tree());
 
+  host_->active_tree()->SetPropertyTrees(
+      layer_tree_root->layer_tree_host()->property_trees());
   TreeSynchronizer::PushLayerProperties(layer_tree_root->layer_tree_host(),
                                         host_->active_tree());
 
@@ -287,6 +294,7 @@
   layer_tree_root->children()[1]->SavePaintProperties();
   int second_child_id = layer_tree_root->children()[1]->id();
 
+  host_->BuildPropertyTreesForTesting();
   TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
                                      host_->active_tree());
   LayerImpl* layer_impl_tree_root =
@@ -335,6 +343,7 @@
   scoped_refptr<Layer> layer_d = layer_b->children()[1];
 
   host_->SetRootLayer(layer_tree_root);
+  host_->BuildPropertyTreesForTesting();
 
   TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
                                      host_->active_tree());
@@ -363,6 +372,7 @@
 
   // After another synchronize our trees should match and we should not have
   // destroyed any LayerImpls
+  host_->BuildPropertyTreesForTesting();
   TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
                                      host_->active_tree());
   layer_impl_tree_root = host_->active_tree()->root_layer_for_testing();
@@ -392,6 +402,7 @@
   int old_tree_first_child_layer_id = old_layer_tree_root->children()[0]->id();
   int old_tree_second_child_layer_id = old_layer_tree_root->children()[1]->id();
 
+  host_->BuildPropertyTreesForTesting();
   TreeSynchronizer::SynchronizeTrees(old_layer_tree_root.get(),
                                      host_->active_tree());
   LayerImpl* layer_impl_tree_root =
@@ -411,6 +422,7 @@
   scoped_refptr<Layer> new_layer_tree_root = Layer::Create();
   host_->SetRootLayer(new_layer_tree_root);
 
+  host_->BuildPropertyTreesForTesting();
   TreeSynchronizer::SynchronizeTrees(new_layer_tree_root.get(),
                                      host_->active_tree());
   layer_impl_tree_root = host_->active_tree()->root_layer_for_testing();
diff --git a/chrome/VERSION b/chrome/VERSION
index 8af47d7..931f8b6 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=60
 MINOR=0
-BUILD=3081
+BUILD=3082
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
index 023dd086..272f5777 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
@@ -6,21 +6,31 @@
 
 import android.support.design.widget.TabLayout;
 import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
 import android.widget.LinearLayout;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.infobar.translate.TranslateMenu;
+import org.chromium.chrome.browser.infobar.translate.TranslateMenuHelper;
 import org.chromium.chrome.browser.infobar.translate.TranslateTabLayout;
 
 /**
  * Java version of the compcat translate infobar
  */
-class TranslateCompactInfoBar extends InfoBar implements TabLayout.OnTabSelectedListener {
+class TranslateCompactInfoBar extends InfoBar
+        implements TabLayout.OnTabSelectedListener, TranslateMenuHelper.TranslateMenuListener {
+    private static final int SOURCE_TAB_INDEX = 0;
+    private static final int TARGET_TAB_INDEX = 1;
+
     private final TranslateOptions mOptions;
 
     private long mNativeTranslateInfoBarPtr;
     private TranslateTabLayout mTabLayout;
 
+    private TranslateMenuHelper mMenuHelper;
+
     @CalledByNative
     private static InfoBar create(String sourceLanguageCode, String targetLanguageCode,
             String[] languages, String[] codes) {
@@ -51,9 +61,34 @@
         mTabLayout.addTabs(mOptions.sourceLanguageName(), mOptions.targetLanguageName());
         mTabLayout.addOnTabSelectedListener(this);
 
+        content.findViewById(R.id.translate_infobar_menu_button)
+                .setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        initMenuHelper(v);
+                        mMenuHelper.show(TranslateMenu.MENU_OVERFLOW);
+                    }
+                });
+
         parent.addContent(content, 1.0f);
     }
 
+    private void initMenuHelper(View anchorView) {
+        if (mMenuHelper == null) {
+            mMenuHelper = new TranslateMenuHelper(getContext(), anchorView, mOptions, this);
+        }
+    }
+
+    private void startTranslating(int tabPostion) {
+        if (TARGET_TAB_INDEX == tabPostion) {
+            // Already on the target tab.
+            mTabLayout.showProgressBarOnTab(TARGET_TAB_INDEX);
+            onButtonClicked(ActionType.TRANSLATE);
+        } else {
+            mTabLayout.getTabAt(TARGET_TAB_INDEX).select();
+        }
+    }
+
     @CalledByNative
     private void onPageTranslated(int errorType) {
         if (mTabLayout != null) {
@@ -79,11 +114,15 @@
 
     @Override
     public void onTabSelected(TabLayout.Tab tab) {
-        if (tab.getPosition() == 0) {
-            onButtonClicked(ActionType.TRANSLATE_SHOW_ORIGINAL);
-        } else {
-            mTabLayout.showProgressBarOnTab(tab.getPosition());
-            onButtonClicked(ActionType.TRANSLATE);
+        switch (tab.getPosition()) {
+            case SOURCE_TAB_INDEX:
+                onButtonClicked(ActionType.TRANSLATE_SHOW_ORIGINAL);
+                return;
+            case TARGET_TAB_INDEX:
+                startTranslating(TARGET_TAB_INDEX);
+                return;
+            default:
+                assert false : "Unexpected Tab Index";
         }
     }
 
@@ -93,6 +132,56 @@
     @Override
     public void onTabReselected(TabLayout.Tab tab) {}
 
+    @Override
+    public void onOverflowMenuItemClicked(int itemId) {
+        switch (itemId) {
+            case TranslateMenu.ID_OVERFLOW_MORE_LANGUAGE:
+                mMenuHelper.show(TranslateMenu.MENU_TARGET_LANGUAGE);
+                return;
+            case TranslateMenu.ID_OVERFLOW_ALWAYS_TRANSLATE:
+                nativeApplyBoolTranslateOption(
+                        mNativeTranslateInfoBarPtr, TranslateOption.ALWAYS_TRANSLATE, true);
+                return;
+            case TranslateMenu.ID_OVERFLOW_NEVER_LANGUAGE:
+                nativeApplyBoolTranslateOption(
+                        mNativeTranslateInfoBarPtr, TranslateOption.NEVER_TRANSLATE, true);
+                return;
+            case TranslateMenu.ID_OVERFLOW_NEVER_SITE:
+                nativeApplyBoolTranslateOption(
+                        mNativeTranslateInfoBarPtr, TranslateOption.NEVER_TRANSLATE_SITE, true);
+                return;
+            case TranslateMenu.ID_OVERFLOW_NOT_THIS_LANGUAGE:
+                mMenuHelper.show(TranslateMenu.MENU_SOURCE_LANGUAGE);
+                return;
+            default:
+                assert false : "Unexpected overflow menu code";
+        }
+    }
+
+    @Override
+    public void onTargetMenuItemClicked(String code) {
+        // Reset target code in both UI and native.
+        if (mOptions.setTargetLanguage(code)) {
+            nativeApplyStringTranslateOption(
+                    mNativeTranslateInfoBarPtr, TranslateOption.TARGET_CODE, code);
+            // Adjust UI.
+            mTabLayout.replaceTabTitle(TARGET_TAB_INDEX, mOptions.getRepresentationFromCode(code));
+            startTranslating(mTabLayout.getSelectedTabPosition());
+        }
+    }
+
+    @Override
+    public void onSourceMenuItemClicked(String code) {
+        // Reset source code in both UI and native.
+        if (mOptions.setSourceLanguage(code)) {
+            nativeApplyStringTranslateOption(
+                    mNativeTranslateInfoBarPtr, TranslateOption.SOURCE_CODE, code);
+            // Adjust UI.
+            mTabLayout.replaceTabTitle(SOURCE_TAB_INDEX, mOptions.getRepresentationFromCode(code));
+            startTranslating(mTabLayout.getSelectedTabPosition());
+        }
+    }
+
     private native void nativeApplyStringTranslateOption(
             long nativeTranslateCompactInfoBar, int option, String value);
     private native void nativeApplyBoolTranslateOption(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateOptions.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateOptions.java
index 98a7ff17..4c5c2d1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateOptions.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateOptions.java
@@ -131,17 +131,11 @@
     }
 
     public String sourceLanguageName() {
-        if (isValidLanguageCode(mSourceLanguageCode)) {
-            return mCodeToRepresentation.get(mSourceLanguageCode);
-        }
-        return "";
+        return getRepresentationFromCode(mSourceLanguageCode);
     }
 
     public String targetLanguageName() {
-        if (isValidLanguageCode(mTargetLanguageCode)) {
-            return mCodeToRepresentation.get(mTargetLanguageCode);
-        }
-        return "";
+        return getRepresentationFromCode(mTargetLanguageCode);
     }
 
     public String sourceLanguageCode() {
@@ -232,6 +226,18 @@
         return toggleState(ALWAYS_LANGUAGE, value);
     }
 
+    /**
+     * Gets the language's translated representation from a given language code.
+     * @param languageCode ISO code for the language
+     * @return The translated representation of the language, or "" if not found.
+     */
+    public String getRepresentationFromCode(String languageCode) {
+        if (isValidLanguageCode(languageCode)) {
+            return mCodeToRepresentation.get(languageCode);
+        }
+        return "";
+    }
+
     private boolean toggleState(int element, boolean newValue) {
         if (!checkElementBoundaries(element)) return false;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenu.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenu.java
new file mode 100644
index 0000000..35230f1
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenu.java
@@ -0,0 +1,76 @@
+// 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.
+
+package org.chromium.chrome.browser.infobar.translate;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Translate menu config and its item entity definition.
+ */
+public final class TranslateMenu {
+    /**
+     * The menu item entity.
+     */
+    static final class MenuItem {
+        public final int mType;
+        public final int mId;
+        public final String mCode;
+
+        MenuItem(int itemType, int itemId) {
+            this(itemType, itemId, EMPTY_STRING);
+        }
+
+        MenuItem(int itemType, int itemId, String code) {
+            mType = itemType;
+            mId = itemId;
+            mCode = code;
+        }
+    }
+
+    public static final String EMPTY_STRING = "";
+
+    // Menu type config.
+    public static final int MENU_OVERFLOW = 0;
+    public static final int MENU_TARGET_LANGUAGE = 1;
+    public static final int MENU_SOURCE_LANGUAGE = 2;
+
+    // Menu item type config.
+    public static final int ITEM_DIVIDER = 0;
+    public static final int ITEM_LANGUAGE = 1;
+    public static final int ITEM_TEXT_OPTION = 2;
+    public static final int ITEM_CHECKBOX_OPTION = 3;
+    public static final int MENU_ITEM_TYPE_COUNT = 4;
+
+    // Menu Item ID config for MENU_OVERFLOW .
+    public static final int ID_UNDEFINED = 0;
+    public static final int ID_OVERFLOW_MORE_LANGUAGE = 1;
+    public static final int ID_OVERFLOW_ALWAYS_TRANSLATE = 2;
+    public static final int ID_OVERFLOW_NEVER_SITE = 3;
+    public static final int ID_OVERFLOW_NEVER_LANGUAGE = 4;
+    public static final int ID_OVERFLOW_NOT_THIS_LANGUAGE = 5;
+
+    private static final List<MenuItem> OVERFLOW_MENU = new ArrayList<MenuItem>();
+
+    /**
+     * Build overflow menu item list.
+     */
+    static List<MenuItem> getOverflowMenu() {
+        // Load overflow menu item if it's empty.
+        synchronized (OVERFLOW_MENU) {
+            if (OVERFLOW_MENU.isEmpty()) {
+                OVERFLOW_MENU.add(new MenuItem(ITEM_TEXT_OPTION, ID_OVERFLOW_MORE_LANGUAGE));
+                OVERFLOW_MENU.add(new MenuItem(ITEM_DIVIDER, ID_UNDEFINED));
+                OVERFLOW_MENU.add(new MenuItem(ITEM_CHECKBOX_OPTION, ID_OVERFLOW_ALWAYS_TRANSLATE));
+                OVERFLOW_MENU.add(new MenuItem(ITEM_TEXT_OPTION, ID_OVERFLOW_NEVER_LANGUAGE));
+                OVERFLOW_MENU.add(new MenuItem(ITEM_TEXT_OPTION, ID_OVERFLOW_NEVER_SITE));
+                OVERFLOW_MENU.add(new MenuItem(ITEM_TEXT_OPTION, ID_OVERFLOW_NOT_THIS_LANGUAGE));
+            }
+        }
+        return OVERFLOW_MENU;
+    }
+
+    private TranslateMenu() {}
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java
index 24bbc3c3..7bfe865 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java
@@ -17,88 +17,69 @@
 import android.widget.TextView;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.infobar.TranslateOptions;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
  * A Helper class for managing the Translate Overflow Menu.
  */
 public class TranslateMenuHelper implements AdapterView.OnItemClickListener {
-    private static final String EMPTY_STRING = "";
-    private final TranslateMenuItemListener mItemListener;
-    private ContextThemeWrapper mWrapper;
-    private View mAnchorView;
+    private final TranslateMenuListener mMenuListener;
+    private final TranslateOptions mOptions;
+
+    private ContextThemeWrapper mContextWrapper;
     private TranslateMenuAdapter mAdapter;
+    private View mAnchorView;
+
     private ListPopupWindow mPopup;
 
     /**
-     * Add a divider menu item to list.
-     * @param list The list of items to show in the menu.
-     */
-    public static void addDivider(List<TranslateMenuElement> list) {
-        list.add(new TranslateMenuElement(
-                EMPTY_STRING, EMPTY_STRING, TranslateMenuAdapter.MENU_DIVIDER));
-    }
-
-    /**
-     * Add an overflow menu item to list.
-     * @param title Title of the menu item
-     * @param code  Code of the menu item
-     * @param list  The list of items to show in the menu.
-     */
-    public static void addOverflowMenuItem(
-            String title, String code, List<TranslateMenuElement> list) {
-        list.add(new TranslateMenuElement(title, code, TranslateMenuAdapter.OVERFLOW_MENU_ITEM));
-    }
-
-    /**
-     * Add a source language menu item to list.
-     * @param title Title of the language
-     * @param code  ISO code of the language
-     * @param list  The list of items to show in the menu.
-     */
-    public static void addSourceLanguageMenuItem(
-            String title, String code, List<TranslateMenuElement> list) {
-        list.add(new TranslateMenuElement(
-                title, code, TranslateMenuAdapter.SOURCE_LANGUAGE_MENU_ITEM));
-    }
-
-    /**
-     * Add a target language menu item to list.
-     * @param title Title of the language
-     * @param code  ISO code of the language
-     * @param list  The list of items to show in the menu.
-     */
-    public static void addTargetLanguageMenuItem(
-            String title, String code, List<TranslateMenuElement> list) {
-        list.add(new TranslateMenuElement(
-                title, code, TranslateMenuAdapter.TARGET_LANGUAGE_MENU_ITEM));
-    }
-
-    /**
      * Interface for receiving the click event of menu item.
      */
-    public interface TranslateMenuItemListener {
-        // return true if the menu is dismissed after clicking on the item;  return false otherwise.
-        // (when clicking on 'More languages' or 'Page not in this language', we show the language
-        // menu by keeping the menu but replace the items inside.)
-        boolean onTranslateMenuItemClicked(String code, int type);
+    public interface TranslateMenuListener {
+        void onOverflowMenuItemClicked(int itemId);
+        void onTargetMenuItemClicked(String code);
+        void onSourceMenuItemClicked(String code);
     }
 
-    public TranslateMenuHelper(
-            Context context, View anchorView, TranslateMenuItemListener itemListener) {
-        mWrapper = new ContextThemeWrapper(context, R.style.OverflowMenuTheme);
+    public TranslateMenuHelper(Context context, View anchorView, TranslateOptions options,
+            TranslateMenuListener itemListener) {
+        mContextWrapper = new ContextThemeWrapper(context, R.style.OverflowMenuTheme);
         mAnchorView = anchorView;
-        mItemListener = itemListener;
+        mOptions = options;
+        mMenuListener = itemListener;
+    }
+
+    /**
+     * Build transalte menu by menu type.
+     */
+    private List<TranslateMenu.MenuItem> getMenuList(int menuType) {
+        List<TranslateMenu.MenuItem> menuList = new ArrayList<TranslateMenu.MenuItem>();
+        if (menuType == TranslateMenu.MENU_OVERFLOW) {
+            // TODO(googleo): Add language short list above static menu after its data is ready.
+            menuList.addAll(TranslateMenu.getOverflowMenu());
+        } else {
+            for (int i = 0; i < mOptions.allLanguages().size(); ++i) {
+                String code = mOptions.allLanguages().get(i).mLanguageCode;
+                // Don't show target or source language in the menu list.
+                if (code.equals(mOptions.targetLanguageCode())
+                        || code.equals(mOptions.sourceLanguageCode())) {
+                    continue;
+                }
+                menuList.add(new TranslateMenu.MenuItem(TranslateMenu.ITEM_LANGUAGE, i, code));
+            }
+        }
+        return menuList;
     }
 
     /**
      * Show the overflow menu.
-     * @param list List of menuitems.
      */
-    public void show(List<TranslateMenuElement> list) {
+    public void show(int menuType) {
         if (mPopup == null) {
-            mPopup = new ListPopupWindow(mWrapper, null, android.R.attr.popupMenuStyle);
+            mPopup = new ListPopupWindow(mContextWrapper, null, android.R.attr.popupMenuStyle);
             mPopup.setModal(true);
             mPopup.setAnchorView(mAnchorView);
             mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
@@ -106,22 +87,19 @@
             // Need to explicitly set the background here.  Relying on it being set in the style
             // caused an incorrectly drawn background.
             mPopup.setBackgroundDrawable(
-                    ContextCompat.getDrawable(mWrapper, R.drawable.edge_menu_bg));
+                    ContextCompat.getDrawable(mContextWrapper, R.drawable.edge_menu_bg));
 
-            int popupWidth = mWrapper.getResources().getDimensionPixelSize(
+            mPopup.setOnItemClickListener(this);
+
+            int popupWidth = mContextWrapper.getResources().getDimensionPixelSize(
                     R.dimen.infobar_translate_menu_width);
-
             // TODO (martiw) make the width dynamic to handle longer items.
             mPopup.setWidth(popupWidth);
 
-            mAdapter = new TranslateMenuAdapter(
-                    mWrapper, R.id.menu_item_text, list, LayoutInflater.from(mWrapper));
+            mAdapter = new TranslateMenuAdapter(menuType);
             mPopup.setAdapter(mAdapter);
-
-            mPopup.setOnItemClickListener(this);
         } else {
-            mAdapter.clear();
-            mAdapter.addAll(list);
+            mAdapter.refreshMenu(menuType);
         }
 
         if (!mPopup.isShowing()) {
@@ -132,16 +110,28 @@
 
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        if (mItemListener.onTranslateMenuItemClicked(
-                    mAdapter.getItem(position).getCode(), mAdapter.getItemViewType(position))) {
-            dismiss();
+        dismiss();
+
+        TranslateMenu.MenuItem item = mAdapter.getItem(position);
+        switch (mAdapter.mMenuType) {
+            case TranslateMenu.MENU_OVERFLOW:
+                mMenuListener.onOverflowMenuItemClicked(item.mId);
+                return;
+            case TranslateMenu.MENU_TARGET_LANGUAGE:
+                mMenuListener.onTargetMenuItemClicked(item.mCode);
+                return;
+            case TranslateMenu.MENU_SOURCE_LANGUAGE:
+                mMenuListener.onSourceMenuItemClicked(item.mCode);
+                return;
+            default:
+                assert false : "Unsupported Menu Item Id";
         }
     }
 
     /**
-     * Dismisses the app menu.
+     * Dismisses the translate option menu.
      */
-    void dismiss() {
+    private void dismiss() {
         if (isShowing()) {
             mPopup.dismiss();
         }
@@ -150,7 +140,7 @@
     /**
      * @return Whether the app menu is currently showing.
      */
-    boolean isShowing() {
+    private boolean isShowing() {
         if (mPopup == null) {
             return false;
         }
@@ -160,81 +150,97 @@
     /**
      * The provides the views of the menu items and dividers.
      */
-    public static final class TranslateMenuAdapter extends ArrayAdapter<TranslateMenuElement> {
-        public static final int MENU_DIVIDER = 0;
-        public static final int OVERFLOW_MENU_ITEM = 1;
-        public static final int SOURCE_LANGUAGE_MENU_ITEM = 2;
-        public static final int TARGET_LANGUAGE_MENU_ITEM = 3;
+    private final class TranslateMenuAdapter extends ArrayAdapter<TranslateMenu.MenuItem> {
         // TODO(martiw) create OVERFLOW_MENU_ITEM_WITH_CHECKBOX_CHECKED and
         // OVERFLOW_MENU_ITEM_WITH_CHECKBOX_UNCHECKED for "Always Translate Language"
 
-        LayoutInflater mInflater;
+        private final LayoutInflater mInflater;
+        private int mMenuType;
 
-        public TranslateMenuAdapter(Context context, int textViewResourceId,
-                List<TranslateMenuElement> items, LayoutInflater inflater) {
-            super(context, textViewResourceId, items);
-            mInflater = inflater;
+        public TranslateMenuAdapter(int menuType) {
+            super(mContextWrapper, R.layout.translate_menu_item, getMenuList(menuType));
+            mInflater = LayoutInflater.from(mContextWrapper);
+            mMenuType = menuType;
+        }
+
+        private void refreshMenu(int menuType) {
+            // Don't refresh if the type is same as previous.
+            if (menuType == mMenuType) return;
+
+            clear();
+
+            mMenuType = menuType;
+            addAll(getMenuList(menuType));
+            notifyDataSetChanged();
+        }
+
+        private String getItemViewText(TranslateMenu.MenuItem item) {
+            if (mMenuType == TranslateMenu.MENU_OVERFLOW) {
+                // Overflow menu items are manually defined one by one.
+                String source = mOptions.sourceLanguageName();
+                switch (item.mId) {
+                    case TranslateMenu.ID_OVERFLOW_ALWAYS_TRANSLATE:
+                        return mContextWrapper.getString(R.string.translate_always_text, source);
+                    case TranslateMenu.ID_OVERFLOW_MORE_LANGUAGE:
+                        return mContextWrapper.getString(R.string.translate_infobar_more_language);
+                    case TranslateMenu.ID_OVERFLOW_NEVER_SITE:
+                        return mContextWrapper.getString(R.string.translate_never_translate_site);
+                    case TranslateMenu.ID_OVERFLOW_NEVER_LANGUAGE:
+                        return mContextWrapper.getString(
+                                R.string.translate_never_translate_language, source);
+                    case TranslateMenu.ID_OVERFLOW_NOT_THIS_LANGUAGE:
+                        return mContextWrapper.getString(
+                                R.string.translate_infobar_not_source_language, source);
+                    default:
+                        assert false : "Unexpected Overflow Item Id";
+                }
+            } else {
+                // Get source and tagert language menu items text by language code.
+                return mOptions.getRepresentationFromCode(item.mCode);
+            }
+            return "";
         }
 
         @Override
         public int getItemViewType(int position) {
-            return getItem(position).getType();
+            return getItem(position).mType;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return TranslateMenu.MENU_ITEM_TYPE_COUNT;
         }
 
         @Override
         public boolean isEnabled(int position) {
-            return getItemViewType(position) != MENU_DIVIDER;
+            return getItem(position).mId != TranslateMenu.ID_UNDEFINED;
         }
 
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
+            View menuItemView = convertView;
             switch (getItemViewType(position)) {
-                case MENU_DIVIDER:
-                    convertView = mInflater.inflate(R.layout.translate_menu_divider, parent, false);
+                case TranslateMenu.ITEM_DIVIDER:
+                    if (menuItemView == null) {
+                        menuItemView =
+                                mInflater.inflate(R.layout.translate_menu_divider, parent, false);
+                    }
                     break;
-                case OVERFLOW_MENU_ITEM:
-                case SOURCE_LANGUAGE_MENU_ITEM:
-                case TARGET_LANGUAGE_MENU_ITEM:
-                    convertView = mInflater.inflate(R.layout.translate_menu_item, parent, false);
-                    ((TextView) convertView.findViewById(R.id.menu_item_text))
-                            .setText(getItem(position).toString());
+                case TranslateMenu.ITEM_CHECKBOX_OPTION:
+                case TranslateMenu.ITEM_TEXT_OPTION:
+                // TODO(martiw) create the layout for ITEM_TEXT_OPTION and ITEM_CHECKBOX_OPTION
+                case TranslateMenu.ITEM_LANGUAGE:
+                    if (menuItemView == null) {
+                        menuItemView =
+                                mInflater.inflate(R.layout.translate_menu_item, parent, false);
+                    }
+                    ((TextView) menuItemView.findViewById(R.id.menu_item_text))
+                            .setText(getItemViewText(getItem(position)));
                     break;
-                // TODO(martiw) create the layout for OVERFLOW_MENU_ITEM_WITH_CHECKBOX_CHECKED and
-                // OVERFLOW_MENU_ITEM_WITH_CHECKBOX_UNCHECKED for "Always Translate Language"
                 default:
                     assert false : "Unexpected MenuItem type";
             }
-            return convertView;
-        }
-    }
-
-    /**
-     * The element that goes inside the menu.
-     */
-    public static final class TranslateMenuElement {
-        private final String mTitle;
-        private final String mCode;
-        private final int mType;
-
-        public TranslateMenuElement(String title, String code, int type) {
-            mTitle = title;
-            mCode = code;
-            mType = type;
-        }
-
-        public String getCode() {
-            return mCode;
-        }
-
-        public int getType() {
-            return mType;
-        }
-
-        /**
-         * This is the text displayed in the menu item.
-         */
-        public String toString() {
-            return mTitle;
+            return menuItemView;
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionSiteBreakdownView.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionSiteBreakdownView.java
index 8070d11..1a72748 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionSiteBreakdownView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionSiteBreakdownView.java
@@ -29,7 +29,8 @@
  * with the most data use or data savings.
  */
 public class DataReductionSiteBreakdownView extends LinearLayout {
-    private static final int NUM_DATA_USE_ITEMS_TO_DISPLAY = 10;
+    private static final int NUM_DATA_USE_ITEMS_TO_ADD = 10;
+    private int mNumDataUseItemsToDisplay = 10;
 
     private TableLayout mTableLayout;
     private TextView mDataUsedTitle;
@@ -166,7 +167,7 @@
         int everythingElseDataSavings = 0;
 
         for (int i = 0; i < mDataUseItems.size(); i++) {
-            if (i < NUM_DATA_USE_ITEMS_TO_DISPLAY) {
+            if (i < mNumDataUseItemsToDisplay) {
                 TableRow row = (TableRow) LayoutInflater.from(getContext())
                                        .inflate(R.layout.data_usage_breakdown_row, null);
 
@@ -207,7 +208,15 @@
             dataUsedView.setTextColor(lightActiveColor);
             dataSavedView.setTextColor(lightActiveColor);
 
-            mTableLayout.addView(row, NUM_DATA_USE_ITEMS_TO_DISPLAY + 1);
+            row.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mNumDataUseItemsToDisplay += NUM_DATA_USE_ITEMS_TO_ADD;
+                    updateSiteBreakdown();
+                }
+            });
+
+            mTableLayout.addView(row, mNumDataUseItemsToDisplay + 1);
         }
 
         mTableLayout.requestLayout();
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 803d3e4..22ccc19 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -467,6 +467,7 @@
   "java/src/org/chromium/chrome/browser/infobar/TranslateOptions.java",
   "java/src/org/chromium/chrome/browser/infobar/TranslateSubPanel.java",
   "java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java",
+  "java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenu.java",
   "java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java",
   "java/src/org/chromium/chrome/browser/infobar/translate/TranslateTabContent.java",
   "java/src/org/chromium/chrome/browser/infobar/translate/TranslateTabLayout.java",
diff --git a/chrome/browser/ui/ash/networking_config_delegate_chromeos_browsertest.cc b/chrome/browser/ui/ash/networking_config_delegate_chromeos_browsertest.cc
index 1e8b81f..d9994f2 100644
--- a/chrome/browser/ui/ash/networking_config_delegate_chromeos_browsertest.cc
+++ b/chrome/browser/ui/ash/networking_config_delegate_chromeos_browsertest.cc
@@ -8,7 +8,7 @@
 #include "ash/root_window_controller.h"
 #include "ash/shell_port.h"
 #include "ash/strings/grit/ash_strings.h"
-#include "ash/system/network/network_detailed_view.h"
+#include "ash/system/network/network_state_list_detailed_view.h"
 #include "ash/system/network/tray_network.h"
 #include "ash/system/tray/system_tray.h"
 #include "base/macros.h"
diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h
index 11f6915..e827860 100644
--- a/chrome/browser/ui/browser_dialogs.h
+++ b/chrome/browser/ui/browser_dialogs.h
@@ -208,6 +208,14 @@
   CONFLICTING_MODULE = 16,
   CRITICAL_NOTIFICATION = 17,
   IME_WARNING = 18,
+  TOOLBAR_ACTIONS_BAR = 19,
+  GLOBAL_ERROR = 20,
+  EXTENSION_INSTALL = 21,
+  EXTENSION_UNINSTALL = 22,
+  EXTENSION_INSTALLED = 23,
+  PAYMENT_REQUEST = 24,
+  SAVE_CARD = 25,
+  CARD_UNMASK = 26,
   MAX_VALUE
 };
 
diff --git a/chrome/browser/ui/views/ash/tab_scrubber_browsertest.cc b/chrome/browser/ui/views/ash/tab_scrubber_browsertest.cc
index 8e484e30..7d890c4 100644
--- a/chrome/browser/ui/views/ash/tab_scrubber_browsertest.cc
+++ b/chrome/browser/ui/views/ash/tab_scrubber_browsertest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/interactive_test_utils.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/test_utils.h"
@@ -329,8 +330,11 @@
 }
 
 // Tests that tab scrubbing works correctly for a full-screen browser.
-// TODO(crbug.com/708612): Re-enable the test after the bug is fixed.
-IN_PROC_BROWSER_TEST_F(TabScrubberTest, DISABLED_FullScreenBrowser) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, FullScreenBrowser) {
+  // Initializes the position of mouse. Makes the mouse away from the tabstrip
+  // to prevent any interference on this test.
+  ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
+      gfx::Point(0, browser()->window()->GetBounds().height())));
   AddTabs(browser(), 6);
   browser()->tab_strip_model()->ActivateTabAt(4, false);
 
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
index 32dd011..b6b82af 100644
--- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
+++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
@@ -9,6 +9,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/ui/autofill/create_card_unmask_prompt_view.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/views/autofill/view_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
@@ -79,6 +80,7 @@
       progress_label_(nullptr),
       overlay_animation_(this),
       weak_ptr_factory_(this) {
+  chrome::RecordDialogCreation(chrome::DialogIdentifier::CARD_UNMASK);
 }
 
 CardUnmaskPromptViews::~CardUnmaskPromptViews() {
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
index ecddc83..0425f6f8 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
@@ -8,6 +8,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/views/autofill/view_util.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/legal_message_line.h"
@@ -57,6 +58,7 @@
       learn_more_link_(nullptr) {
   DCHECK(controller);
   views::BubbleDialogDelegateView::CreateBubble(this);
+  chrome::RecordDialogCreation(chrome::DialogIdentifier::SAVE_CARD);
 }
 
 SaveCardBubbleViews::~SaveCardBubbleViews() {}
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
index 0491b93..7a3ffa6 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/extensions/extension_install_prompt_show_params.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/harmony/chrome_typography.h"
@@ -188,6 +189,7 @@
       handled_result_(false),
       install_button_enabled_(false) {
   InitView();
+  chrome::RecordDialogCreation(chrome::DialogIdentifier::EXTENSION_INSTALL);
 }
 
 ExtensionInstallDialogView::~ExtensionInstallDialogView() {
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
index 19a0014..2ed8929a 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
@@ -11,6 +11,7 @@
 #include "base/metrics/user_metrics_action.h"
 #include "chrome/browser/extensions/extension_action_manager.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/extensions/extension_installed_bubble.h"
 #include "chrome/browser/ui/singleton_tabs.h"
@@ -111,7 +112,9 @@
                                    ? views::BubbleBorder::TOP_LEFT
                                    : views::BubbleBorder::TOP_RIGHT),
       controller_(controller),
-      manage_shortcut_(nullptr) {}
+      manage_shortcut_(nullptr) {
+  chrome::RecordDialogCreation(chrome::DialogIdentifier::EXTENSION_INSTALLED);
+}
 
 ExtensionInstalledBubbleView::~ExtensionInstalledBubbleView() {}
 
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
index 21746f13..21f5834 100644
--- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
@@ -10,6 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
 #include "chrome/browser/ui/app_list/app_list_service.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/native_window_tracker.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/grit/generated_resources.h"
@@ -188,6 +189,8 @@
   heading_->SetAllowCharacterBreak(true);
   heading_->SizeToFit(kRightColumnWidth);
   AddChildView(heading_);
+
+  chrome::RecordDialogCreation(chrome::DialogIdentifier::EXTENSION_UNINSTALL);
 }
 
 ExtensionUninstallDialogDelegateView::~ExtensionUninstallDialogDelegateView() {
diff --git a/chrome/browser/ui/views/global_error_bubble_view.cc b/chrome/browser/ui/views/global_error_bubble_view.cc
index eed9dce..46f7934 100644
--- a/chrome/browser/ui/views/global_error_bubble_view.cc
+++ b/chrome/browser/ui/views/global_error_bubble_view.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/global_error/global_error.h"
 #include "chrome/browser/ui/global_error/global_error_service.h"
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
@@ -69,6 +70,7 @@
       error_(error) {
   if (!anchor_view)
     SetAnchorRect(gfx::Rect(anchor_point, gfx::Size()));
+  chrome::RecordDialogCreation(chrome::DialogIdentifier::GLOBAL_ERROR);
 }
 
 GlobalErrorBubbleView::~GlobalErrorBubbleView() {}
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
index c13288d..2f21989 100644
--- a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
+++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
@@ -8,6 +8,7 @@
 
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/views/payments/contact_info_editor_view_controller.h"
 #include "chrome/browser/ui/views/payments/credit_card_editor_view_controller.h"
 #include "chrome/browser/ui/views/payments/cvc_unmask_view_controller.h"
@@ -75,6 +76,8 @@
   SetupSpinnerOverlay();
 
   ShowInitialPaymentSheet();
+
+  chrome::RecordDialogCreation(chrome::DialogIdentifier::PAYMENT_REQUEST);
 }
 
 PaymentRequestDialogView::~PaymentRequestDialogView() {}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views.cc b/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views.cc
index 2986540..2f59d3d 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views.h"
 
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/grit/locale_settings.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -34,6 +35,7 @@
   set_close_on_deactivate(delegate_->ShouldCloseOnDeactivate());
   if (!anchor_view)
     SetAnchorRect(gfx::Rect(anchor_point, gfx::Size()));
+  chrome::RecordDialogCreation(chrome::DialogIdentifier::TOOLBAR_ACTIONS_BAR);
 }
 
 ToolbarActionsBarBubbleViews::~ToolbarActionsBarBubbleViews() {}
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 8b97003..1e836d7 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -322,6 +322,9 @@
     run_list_path = "$root_out_dir/junit/run_junit_test_list.txt"
     build_tests = true
     test_groups = [ ":cast_junit_tests" ]
+    if (chromecast_branding != "public") {
+      test_groups += [ "//chromecast/internal:internal_cast_junit_tests" ]
+    }
   }
 }
 
diff --git a/chromeos/login/auth/auth_status_consumer.h b/chromeos/login/auth/auth_status_consumer.h
index 0c1158b..29b0eeb 100644
--- a/chromeos/login/auth/auth_status_consumer.h
+++ b/chromeos/login/auth/auth_status_consumer.h
@@ -105,6 +105,14 @@
   GoogleServiceAuthError error_;
 };
 
+// Enum used for UMA. Do NOT reorder or remove entry. Don't forget to
+// update histograms.xml when adding new entries.
+enum SuccessReason {
+  OFFLINE_AND_ONLINE = 0,
+  OFFLINE_ONLY = 1,
+  NUM_SUCCESS_REASONS,  // This has to be the last item.
+};
+
 // An interface that defines the callbacks for objects that the
 // Authenticator class will call to report the success/failure of
 // authentication for Chromium OS.
diff --git a/chromeos/login/auth/login_performer.cc b/chromeos/login/auth/login_performer.cc
index e35c436d..405d123 100644
--- a/chromeos/login/auth/login_performer.cc
+++ b/chromeos/login/auth/login_performer.cc
@@ -79,6 +79,11 @@
 void LoginPerformer::OnAuthSuccess(const UserContext& user_context) {
   DCHECK(task_runner_->RunsTasksOnCurrentThread());
   base::RecordAction(UserMetricsAction("Login_Success"));
+
+  // Do not distinguish between offline and online success.
+  UMA_HISTOGRAM_ENUMERATION("Login.SuccessReason", OFFLINE_AND_ONLINE,
+                            NUM_SUCCESS_REASONS);
+
   VLOG(1) << "LoginSuccess hash: " << user_context.GetUserIDHash();
   DCHECK(delegate_);
   // After delegate_->OnAuthSuccess(...) is called, delegate_ releases
diff --git a/components/history/core/browser/typed_url_sync_metadata_database.cc b/components/history/core/browser/typed_url_sync_metadata_database.cc
index 6cc6d157..f0b2ce6 100644
--- a/components/history/core/browser/typed_url_sync_metadata_database.cc
+++ b/components/history/core/browser/typed_url_sync_metadata_database.cc
@@ -48,8 +48,12 @@
 }
 
 bool TypedURLSyncMetadataDatabase::UpdateSyncMetadata(
+    syncer::ModelType model_type,
     const std::string& storage_key,
     const sync_pb::EntityMetadata& metadata) {
+  DCHECK_EQ(model_type, syncer::TYPED_URLS)
+      << "Only the TYPED_URLS model type is supported";
+
   int64_t storage_key_int = 0;
   if (!base::StringToInt64(storage_key, &storage_key_int)) {
     return false;
@@ -64,7 +68,11 @@
 }
 
 bool TypedURLSyncMetadataDatabase::ClearSyncMetadata(
+    syncer::ModelType model_type,
     const std::string& storage_key) {
+  DCHECK_EQ(model_type, syncer::TYPED_URLS)
+      << "Only the TYPED_URLS model type is supported";
+
   int64_t storage_key_int = 0;
   if (!base::StringToInt64(storage_key, &storage_key_int)) {
     return false;
@@ -77,14 +85,20 @@
 }
 
 bool TypedURLSyncMetadataDatabase::UpdateModelTypeState(
+    syncer::ModelType model_type,
     const sync_pb::ModelTypeState& model_type_state) {
+  DCHECK_EQ(model_type, syncer::TYPED_URLS)
+      << "Only the TYPED_URLS model type is supported";
   DCHECK_GT(GetMetaTable().GetVersionNumber(), 0);
 
   std::string serialized_state = model_type_state.SerializeAsString();
   return GetMetaTable().SetValue(kTypedURLModelTypeStateKey, serialized_state);
 }
 
-bool TypedURLSyncMetadataDatabase::ClearModelTypeState() {
+bool TypedURLSyncMetadataDatabase::ClearModelTypeState(
+    syncer::ModelType model_type) {
+  DCHECK_EQ(model_type, syncer::TYPED_URLS)
+      << "Only the TYPED_URLS model type is supported";
   DCHECK_GT(GetMetaTable().GetVersionNumber(), 0);
   return GetMetaTable().DeleteKey(kTypedURLModelTypeStateKey);
 }
diff --git a/components/history/core/browser/typed_url_sync_metadata_database.h b/components/history/core/browser/typed_url_sync_metadata_database.h
index 0b68753..6967f486 100644
--- a/components/history/core/browser/typed_url_sync_metadata_database.h
+++ b/components/history/core/browser/typed_url_sync_metadata_database.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/model/metadata_batch.h"
+#include "components/sync/model/sync_metadata_store.h"
 #include "sql/meta_table.h"
 
 namespace sql {
@@ -20,30 +21,27 @@
 // and datatype state table. Entity metadata table contains metadata(sync
 // states) for each url. Datatype state table contains the state of typed url
 // datatype.
-class TypedURLSyncMetadataDatabase {
+class TypedURLSyncMetadataDatabase : public syncer::SyncMetadataStore {
  public:
   // Must call InitVisitTable() before using to make sure the database is
   // initialized.
   TypedURLSyncMetadataDatabase();
-  virtual ~TypedURLSyncMetadataDatabase();
+  ~TypedURLSyncMetadataDatabase() override;
 
   // Read all the stored metadata for typed URL and fill |metadata_batch|
   // with it.
   bool GetAllSyncMetadata(syncer::MetadataBatch* metadata_batch);
 
-  // Update the metadata row for typed URL, keyed by |storage_key|, to
-  // contain the contents of |metadata|.
-  bool UpdateSyncMetadata(const std::string& storage_key,
-                          const sync_pb::EntityMetadata& metadata);
-
-  // Remove the metadata row of typed URL keyed by |storage_key|.
-  bool ClearSyncMetadata(const std::string& storage_key);
-
-  // Update the stored sync state for the typed URL.
-  bool UpdateModelTypeState(const sync_pb::ModelTypeState& model_type_state);
-
-  // Clear the stored sync state for typed URL.
-  bool ClearModelTypeState();
+  // syncer::SyncMetadataStore implementation.
+  bool UpdateSyncMetadata(syncer::ModelType model_type,
+                          const std::string& storage_key,
+                          const sync_pb::EntityMetadata& metadata) override;
+  bool ClearSyncMetadata(syncer::ModelType model_type,
+                         const std::string& storage_key) override;
+  bool UpdateModelTypeState(
+      syncer::ModelType model_type,
+      const sync_pb::ModelTypeState& model_type_state) override;
+  bool ClearModelTypeState(syncer::ModelType model_type) override;
 
  protected:
   // Returns the database for the functions in this interface.
diff --git a/components/history/core/browser/typed_url_sync_metadata_database_unittest.cc b/components/history/core/browser/typed_url_sync_metadata_database_unittest.cc
index 31810c61..c37bf3ee 100644
--- a/components/history/core/browser/typed_url_sync_metadata_database_unittest.cc
+++ b/components/history/core/browser/typed_url_sync_metadata_database_unittest.cc
@@ -64,15 +64,15 @@
   std::string storage_key2 = "2";
   metadata.set_sequence_number(1);
 
-  EXPECT_TRUE(UpdateSyncMetadata(storage_key, metadata));
+  EXPECT_TRUE(UpdateSyncMetadata(syncer::TYPED_URLS, storage_key, metadata));
 
   ModelTypeState model_type_state;
   model_type_state.set_initial_sync_done(true);
 
-  EXPECT_TRUE(UpdateModelTypeState(model_type_state));
+  EXPECT_TRUE(UpdateModelTypeState(syncer::TYPED_URLS, model_type_state));
 
   metadata.set_sequence_number(2);
-  EXPECT_TRUE(UpdateSyncMetadata(storage_key2, metadata));
+  EXPECT_TRUE(UpdateSyncMetadata(syncer::TYPED_URLS, storage_key2, metadata));
 
   MetadataBatch metadata_batch;
   EXPECT_TRUE(GetAllSyncMetadata(&metadata_batch));
@@ -87,7 +87,7 @@
 
   // Now check that a model type state update replaces the old value
   model_type_state.set_initial_sync_done(false);
-  EXPECT_TRUE(UpdateModelTypeState(model_type_state));
+  EXPECT_TRUE(UpdateModelTypeState(syncer::TYPED_URLS, model_type_state));
 
   EXPECT_TRUE(GetAllSyncMetadata(&metadata_batch));
   EXPECT_FALSE(metadata_batch.GetModelTypeState().initial_sync_done());
@@ -104,10 +104,10 @@
   metadata.set_client_tag_hash("client_hash");
 
   // Write the data into the store.
-  EXPECT_TRUE(UpdateSyncMetadata(storage_key, metadata));
-  EXPECT_TRUE(UpdateModelTypeState(model_type_state));
+  EXPECT_TRUE(UpdateSyncMetadata(syncer::TYPED_URLS, storage_key, metadata));
+  EXPECT_TRUE(UpdateModelTypeState(syncer::TYPED_URLS, model_type_state));
   // Delete the data we just wrote.
-  EXPECT_TRUE(ClearSyncMetadata(storage_key));
+  EXPECT_TRUE(ClearSyncMetadata(syncer::TYPED_URLS, storage_key));
   // It shouldn't be there any more.
   EXPECT_TRUE(GetAllSyncMetadata(&metadata_batch));
 
@@ -115,7 +115,7 @@
   EXPECT_EQ(metadata_records.size(), 0u);
 
   // Now delete the model type state.
-  EXPECT_TRUE(ClearModelTypeState());
+  EXPECT_TRUE(ClearModelTypeState(syncer::TYPED_URLS));
   EXPECT_TRUE(GetAllSyncMetadata(&metadata_batch));
   EXPECT_EQ(ModelTypeState().SerializeAsString(),
             metadata_batch.GetModelTypeState().SerializeAsString());
diff --git a/content/browser/media/media_capabilities_browsertest.cc b/content/browser/media/media_capabilities_browsertest.cc
new file mode 100644
index 0000000..1174f3b
--- /dev/null
+++ b/content/browser/media/media_capabilities_browsertest.cc
@@ -0,0 +1,147 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "media/base/media_switches.h"
+#include "media/base/test_data_util.h"
+
+const char kDecodeTestFile[] = "decode_capabilities_test.html";
+const char kSupported[] = "SUPPORTED";
+const char kUnsupported[] = "UNSUPPORTED";
+const char kError[] = "ERROR";
+
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+const char* kPropSupported = kSupported;
+#else
+const char* kPropSupported = kUnsupported;
+#endif  // USE_PROPRIETARY_CODECS
+
+enum ConfigType { AUDIO, VIDEO };
+
+namespace content {
+
+class MediaCapabilitiesTest : public ContentBrowserTest {
+ public:
+  MediaCapabilitiesTest() = default;
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
+                                    "MediaCapabilities");
+    command_line->AppendSwitch(switches::kEnableNewVp9CodecString);
+    command_line->AppendSwitch(switches::kEnableVp9InMp4);
+  }
+
+  std::string CanDecodeAudio(const std::string& content_type) {
+    return CanDecode(content_type, ConfigType::AUDIO);
+  }
+
+  std::string CanDecodeVideo(const std::string& content_type) {
+    return CanDecode(content_type, ConfigType::VIDEO);
+  }
+
+  std::string CanDecode(const std::string& content_type,
+                        ConfigType configType) {
+    std::string command;
+    if (configType == ConfigType::AUDIO) {
+      command.append("testAudioDecodeContentType(");
+    } else {
+      command.append("testVideoDecodeContentType(");
+    }
+
+    command.append(content_type);
+    command.append(");");
+
+    EXPECT_TRUE(ExecuteScript(shell(), command));
+
+    TitleWatcher title_watcher(shell()->web_contents(),
+                               base::ASCIIToUTF16(kSupported));
+    title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(kUnsupported));
+    title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(kError));
+    return base::UTF16ToASCII(title_watcher.WaitAndGetTitle());
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MediaCapabilitiesTest);
+};
+
+// Cover basic codec support. See media_canplaytype_browsertest.cc for more
+// exhaustive codec string testing.
+IN_PROC_BROWSER_TEST_F(MediaCapabilitiesTest, VideoDecodeTypes) {
+  base::FilePath file_path = media::GetTestDataFilePath(kDecodeTestFile);
+
+  EXPECT_TRUE(
+      NavigateToURL(shell(), content::GetFileUrlWithQuery(file_path, "")));
+
+  EXPECT_EQ(kSupported, CanDecodeVideo("'video/webm; codecs=\"vp8\"'"));
+
+  // TODO(chcunningham): Drop support for the old VP9 string. Only support
+  // the new vp09 format which provides critical profile information.
+  EXPECT_EQ(kSupported, CanDecodeVideo("'video/webm; codecs=\"vp9\"'"));
+  // Requires command line flag switches::kEnableNewVp9CodecString
+  EXPECT_EQ(kSupported,
+            CanDecodeVideo("'video/webm; codecs=\"vp09.00.10.08\"'"));
+
+  // Supported when built with USE_PROPRIETARY_CODECS
+  EXPECT_EQ(kPropSupported,
+            CanDecodeVideo("'video/mp4; codecs=\"avc1.42E01E\"'"));
+  EXPECT_EQ(kPropSupported,
+            CanDecodeVideo("'video/mp4; codecs=\"avc1.42101E\"'"));
+  EXPECT_EQ(kPropSupported,
+            CanDecodeVideo("'video/mp4; codecs=\"avc1.42701E\"'"));
+  EXPECT_EQ(kPropSupported,
+            CanDecodeVideo("'video/mp4; codecs=\"avc1.42F01E\"'"));
+  // Requires command line flag switches::kEnableVp9InMp4
+  EXPECT_EQ(kPropSupported,
+            CanDecodeVideo("'video/mp4; codecs=\"vp09.00.10.08\"'"));
+
+  // Test a handful of invalid strings.
+  EXPECT_EQ(kUnsupported, CanDecodeVideo("'video/webm; codecs=\"theora\"'"));
+  EXPECT_EQ(kUnsupported,
+            CanDecodeVideo("'video/webm; codecs=\"avc1.42E01E\"'"));
+  // Only new vp09 format is supported with MP4.
+  EXPECT_EQ(kUnsupported, CanDecodeVideo("'video/mp4; codecs=\"vp9\"'"));
+}
+
+// Cover basic codec support. See media_canplaytype_browsertest.cc for more
+// exhaustive codec string testing.
+IN_PROC_BROWSER_TEST_F(MediaCapabilitiesTest, AudioDecodeTypes) {
+  base::FilePath file_path = media::GetTestDataFilePath(kDecodeTestFile);
+
+  EXPECT_TRUE(
+      NavigateToURL(shell(), content::GetFileUrlWithQuery(file_path, "")));
+
+  EXPECT_EQ(kSupported, CanDecodeAudio("'audio/ogg; codecs=\"flac\"'"));
+  EXPECT_EQ(kSupported, CanDecodeAudio("'audio/ogg; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kSupported, CanDecodeAudio("'audio/ogg; codecs=\"opus\"'"));
+
+  EXPECT_EQ(kSupported, CanDecodeAudio("'audio/webm; codecs=\"opus\"'"));
+  EXPECT_EQ(kSupported, CanDecodeAudio("'audio/webm; codecs=\"vorbis\"'"));
+
+  EXPECT_EQ(kSupported, CanDecodeAudio("'audio/flac'"));
+
+  // Supported when built with USE_PROPRIETARY_CODECS
+  EXPECT_EQ(kPropSupported, CanDecodeAudio("'audio/mpeg; codecs=\"mp4a.69\"'"));
+  EXPECT_EQ(kPropSupported,
+            CanDecodeAudio("'audio/mp4; codecs=\"mp4a.40.02\"'"));
+  EXPECT_EQ(kPropSupported, CanDecodeAudio("'audio/aac'"));
+
+  // Test a handful of invalid strings.
+  EXPECT_EQ(kUnsupported, CanDecodeAudio("'audio/wav; codecs=\"mp3\"'"));
+  EXPECT_EQ(kUnsupported, CanDecodeAudio("'audio/webm; codecs=\"vp8\"'"));
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index ed09e523..d9686c76 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -141,6 +141,7 @@
 #include "content/common/service_manager/service_manager_connection_impl.h"
 #include "content/common/site_isolation_policy.h"
 #include "content/common/view_messages.h"
+#include "content/common/worker_url_loader_factory_provider.mojom.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
@@ -178,6 +179,7 @@
 #include "media/media_features.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "ppapi/features/features.h"
 #include "services/resource_coordinator/memory/coordinator/coordinator_impl.h"
@@ -471,6 +473,52 @@
                            std::move(request));
 }
 
+class WorkerURLLoaderFactoryProviderImpl
+    : public mojom::WorkerURLLoaderFactoryProvider {
+ public:
+  static void Create(
+      int render_process_id,
+      scoped_refptr<ResourceMessageFilter> resource_message_filter,
+      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+      mojom::WorkerURLLoaderFactoryProviderRequest request) {
+    DCHECK(base::FeatureList::IsEnabled(features::kOffMainThreadFetch));
+    mojo::MakeStrongBinding(
+        base::MakeUnique<WorkerURLLoaderFactoryProviderImpl>(
+            render_process_id, resource_message_filter->GetWeakPtr(),
+            std::move(service_worker_context)),
+        std::move(request));
+  }
+  WorkerURLLoaderFactoryProviderImpl(
+      int render_process_id,
+      base::WeakPtr<ResourceMessageFilter> resource_message_filter,
+      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+      : render_process_id_(render_process_id),
+        url_loader_factory_binding_(resource_message_filter.get()),
+        service_worker_context_(std::move(service_worker_context)) {}
+  ~WorkerURLLoaderFactoryProviderImpl() override {}
+
+  void GetURLLoaderFactoryAndRegisterClient(
+      mojom::URLLoaderFactoryAssociatedRequest loader_request,
+      mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info,
+      int service_worker_provider_id) override {
+    url_loader_factory_binding_.Bind(std::move(loader_request));
+    service_worker_context_->BindWorkerFetchContext(render_process_id_,
+                                                    service_worker_provider_id,
+                                                    std::move(client_ptr_info));
+  }
+
+  void GetURLLoaderFactory(
+      mojom::URLLoaderFactoryAssociatedRequest loader_request) override {
+    url_loader_factory_binding_.Bind(std::move(loader_request));
+  }
+
+ private:
+  const int render_process_id_;
+  mojo::AssociatedBinding<mojom::URLLoaderFactory> url_loader_factory_binding_;
+
+  scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+};
+
 }  // namespace
 
 RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL;
@@ -1294,6 +1342,15 @@
       base::Bind(&VideoCaptureHost::Create,
                  BrowserMainLoop::GetInstance()->media_stream_manager()));
 
+  if (base::FeatureList::IsEnabled(features::kOffMainThreadFetch)) {
+    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context(
+        static_cast<ServiceWorkerContextWrapper*>(
+            storage_partition_impl_->GetServiceWorkerContext()));
+    registry->AddInterface(
+        base::Bind(&WorkerURLLoaderFactoryProviderImpl::Create, GetID(),
+                   resource_message_filter_, service_worker_context));
+  }
+
   // This is to support usage of WebSockets in cases in which there is no
   // associated RenderFrame (e.g., Shared Workers).
   AddUIThreadInterface(
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index 53997c63..8bf299bc 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -913,4 +913,15 @@
   CheckFetchHandlerOfInstalledServiceWorker(callback, registration);
 }
 
+void ServiceWorkerContextCore::BindWorkerFetchContext(
+    int render_process_id,
+    int service_worker_provider_id,
+    mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info) {
+  ServiceWorkerProviderHost* provider_host =
+      GetProviderHost(render_process_id, service_worker_provider_id);
+  if (!provider_host)
+    return;
+  provider_host->BindWorkerFetchContext(std::move(client_ptr_info));
+}
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h
index bb1fc89..6505037 100644
--- a/content/browser/service_worker/service_worker_context_core.h
+++ b/content/browser/service_worker/service_worker_context_core.h
@@ -24,6 +24,7 @@
 #include "content/browser/service_worker/service_worker_registration_status.h"
 #include "content/browser/service_worker/service_worker_storage.h"
 #include "content/common/content_export.h"
+#include "content/common/worker_url_loader_factory_provider.mojom.h"
 #include "content/public/browser/service_worker_context.h"
 
 class GURL;
@@ -295,6 +296,14 @@
   // version. The count resets to zero when the worker successfully starts.
   int GetVersionFailureCount(int64_t version_id);
 
+  // Binds the ServiceWorkerWorkerClient of a dedicated (or shared) worker to
+  // the parent frame's ServiceWorkerProviderHost. (This is used only when
+  // off-main-thread-fetch is enabled.)
+  void BindWorkerFetchContext(
+      int render_process_id,
+      int service_worker_provider_id,
+      mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info);
+
   base::WeakPtr<ServiceWorkerContextCore> AsWeakPtr() {
     return weak_factory_.GetWeakPtr();
   }
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc
index b5cda10..04c021d 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -799,6 +799,16 @@
                          &ServiceWorkerContextObserver::OnStorageWiped);
 }
 
+void ServiceWorkerContextWrapper::BindWorkerFetchContext(
+    int render_process_id,
+    int service_worker_provider_id,
+    mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  context()->BindWorkerFetchContext(render_process_id,
+                                    service_worker_provider_id,
+                                    std::move(client_ptr_info));
+}
+
 ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   return context_core_.get();
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h
index 84d8a580..7fe964f5 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -16,6 +16,7 @@
 #include "base/memory/ref_counted.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/common/content_export.h"
+#include "content/common/worker_url_loader_factory_provider.mojom.h"
 #include "content/public/browser/service_worker_context.h"
 
 namespace base {
@@ -218,6 +219,14 @@
   // Must be called from the IO thread.
   bool OriginHasForeignFetchRegistrations(const GURL& origin);
 
+  // Binds the ServiceWorkerWorkerClient of a dedicated (or shared) worker to
+  // the parent frame's ServiceWorkerProviderHost. (This is used only when
+  // off-main-thread-fetch is enabled.)
+  void BindWorkerFetchContext(
+      int render_process_id,
+      int service_worker_provider_id,
+      mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info);
+
  private:
   friend class BackgroundSyncManagerTest;
   friend class base::RefCountedThreadSafe<ServiceWorkerContextWrapper>;
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 92fc4cf..3e6025d 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/feature_list.h"
 #include "base/guid.h"
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
@@ -26,7 +27,9 @@
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/origin_util.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
 #include "net/base/url_util.h"
 
 namespace content {
@@ -112,6 +115,31 @@
       info.is_parent_frame_secure, context, dispatcher_host));
 }
 
+void ServiceWorkerProviderHost::BindWorkerFetchContext(
+    mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info) {
+  DCHECK(base::FeatureList::IsEnabled(features::kOffMainThreadFetch));
+  mojom::ServiceWorkerWorkerClientAssociatedPtr client;
+  client.Bind(std::move(client_ptr_info));
+  client.set_connection_error_handler(
+      base::Bind(&ServiceWorkerProviderHost::UnregisterWorkerFetchContext,
+                 base::Unretained(this), client.get()));
+
+  if (controlling_version_)
+    client->SetControllerServiceWorker(controlling_version_->version_id());
+
+  auto result = worker_clients_.insert(
+      std::make_pair<mojom::ServiceWorkerWorkerClient*,
+                     mojom::ServiceWorkerWorkerClientAssociatedPtr>(
+          client.get(), std::move(client)));
+  DCHECK(result.second);
+}
+
+void ServiceWorkerProviderHost::UnregisterWorkerFetchContext(
+    mojom::ServiceWorkerWorkerClient* client) {
+  DCHECK(worker_clients_.count(client));
+  worker_clients_.erase(client);
+}
+
 ServiceWorkerProviderHost::ServiceWorkerProviderHost(
     int render_process_id,
     int route_id,
@@ -247,8 +275,12 @@
 
   scoped_refptr<ServiceWorkerVersion> previous_version = controlling_version_;
   controlling_version_ = version;
-  if (version)
+  if (version) {
     version->AddControllee(this);
+    for (const auto& pair : worker_clients_) {
+      pair.second->SetControllerServiceWorker(version->version_id());
+    }
+  }
   if (previous_version.get())
     previous_version->RemoveControllee(this);
 
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 585bc59..f8ab188 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -12,6 +12,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 #include "base/gtest_prod_util.h"
@@ -22,6 +23,7 @@
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_provider_host_info.h"
 #include "content/common/service_worker/service_worker_types.h"
+#include "content/common/worker_url_loader_factory_provider.mojom.h"
 #include "content/public/common/request_context_frame_type.h"
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_type.h"
@@ -285,6 +287,12 @@
   // cache.
   void NotifyControllerLost();
 
+  // Binds the ServiceWorkerWorkerClient of a dedicated (or shared) worker to
+  // the parent frame's ServiceWorkerProviderHost. (This is used only when
+  // off-main-thread-fetch is enabled.)
+  void BindWorkerFetchContext(
+      mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info);
+
  private:
   friend class ForeignFetchRequestHandlerTest;
   friend class LinkHeaderServiceWorkerTest;
@@ -361,6 +369,10 @@
                               int frame_routing_id,
                               ServiceWorkerDispatcherHost* dispatcher_host);
 
+  // Clears the information of the ServiceWorkerWorkerClient of dedicated (or
+  // shared) worker, when the connection to the worker is disconnected.
+  void UnregisterWorkerFetchContext(mojom::ServiceWorkerWorkerClient*);
+
   std::string client_uuid_;
   int render_process_id_;
 
@@ -406,6 +418,12 @@
 
   std::vector<base::Closure> queued_events_;
 
+  // Keeps ServiceWorkerWorkerClient pointers of dedicated or shared workers
+  // which are associated with the ServiceWorkerProviderHost.
+  std::unordered_map<mojom::ServiceWorkerWorkerClient*,
+                     mojom::ServiceWorkerWorkerClientAssociatedPtr>
+      worker_clients_;
+
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHost);
 };
 
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn
index f1ff86d..893418e 100644
--- a/content/child/BUILD.gn
+++ b/content/child/BUILD.gn
@@ -241,7 +241,7 @@
     "//services/device/public/cpp:device_features",
     "//services/device/public/cpp/power_monitor",
     "//services/device/public/interfaces:constants",
-    "//services/resource_coordinator/public/cpp",
+    "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/interfaces",
     "//services/service_manager/runner/common",
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index ea0b322..24f46080 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -66,7 +66,7 @@
 #include "mojo/public/cpp/system/buffer.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h"
-#include "services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.h"
+#include "services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_factory.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
@@ -488,12 +488,10 @@
     channel_->AddFilter(new ChildMemoryMessageFilter());
 
     if (service_manager_connection_) {
-      memory_instrumentation::MemoryDumpManagerDelegateImpl::Config config(
+      memory_instrumentation::ProcessLocalDumpManagerImpl::Config config(
           GetConnector(), mojom::kBrowserServiceName);
-      auto delegate = base::MakeUnique<
-          memory_instrumentation::MemoryDumpManagerDelegateImpl>(config);
-      base::trace_event::MemoryDumpManager::GetInstance()->Initialize(
-          std::move(delegate));
+      memory_instrumentation::ProcessLocalDumpManagerImpl::CreateInstance(
+          config);
     }
   }
 
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc
index 5ca85c2d..a9d45898 100644
--- a/content/child/resource_dispatcher.cc
+++ b/content/child/resource_dispatcher.cc
@@ -8,6 +8,7 @@
 
 #include <utility>
 
+#include "base/atomic_sequence_num.h"
 #include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/debug/alias.h"
@@ -67,8 +68,8 @@
   // NOTE: The resource_dispatcher_host also needs probably unique
   // request_ids, so they count down from -2 (-1 is a special we're
   // screwed value), while the renderer process counts up.
-  static int next_request_id = 0;
-  return next_request_id++;
+  static base::StaticAtomicSequenceNumber sequence;
+  return sequence.GetNext();  // We start at zero.
 }
 
 void CheckSchemeForReferrerPolicy(const ResourceRequest& request) {
@@ -88,13 +89,12 @@
 
 ResourceDispatcher::ResourceDispatcher(
     IPC::Sender* sender,
-    scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
+    scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner)
     : message_sender_(sender),
       delegate_(NULL),
       io_timestamp_(base::TimeTicks()),
-      main_thread_task_runner_(main_thread_task_runner),
-      weak_factory_(this) {
-}
+      thread_task_runner_(thread_task_runner),
+      weak_factory_(this) {}
 
 ResourceDispatcher::~ResourceDispatcher() {
 }
@@ -401,7 +401,7 @@
   // Always delete the pending_request asyncly so that cancelling the request
   // doesn't delete the request context info while its response is still being
   // handled.
-  main_thread_task_runner_->DeleteSoon(FROM_HERE, it->second.release());
+  thread_task_runner_->DeleteSoon(FROM_HERE, it->second.release());
   pending_requests_.erase(it);
 
   if (release_downloaded_file) {
@@ -470,7 +470,7 @@
 
     FollowPendingRedirect(request_id, request_info);
 
-    main_thread_task_runner_->PostTask(
+    thread_task_runner_->PostTask(
         FROM_HERE, base::Bind(&ResourceDispatcher::FlushDeferredMessages,
                               weak_factory_.GetWeakPtr(), request_id));
   }
@@ -639,7 +639,7 @@
   }
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
-      loading_task_runner ? loading_task_runner : main_thread_task_runner_;
+      loading_task_runner ? loading_task_runner : thread_task_runner_;
 
   if (consumer_handle.is_valid()) {
     pending_requests_[request_id]->url_loader_client =
@@ -655,7 +655,7 @@
 
   if (ipc_type == blink::WebURLRequest::LoadingIPCType::kMojo) {
     scoped_refptr<base::SingleThreadTaskRunner> task_runner =
-        loading_task_runner ? loading_task_runner : main_thread_task_runner_;
+        loading_task_runner ? loading_task_runner : thread_task_runner_;
     std::unique_ptr<URLLoaderClientImpl> client(
         new URLLoaderClientImpl(request_id, this, std::move(task_runner)));
     mojom::URLLoaderAssociatedPtr url_loader;
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h
index 4b20ab3..d6f2c88 100644
--- a/content/child/resource_dispatcher.h
+++ b/content/child/resource_dispatcher.h
@@ -60,7 +60,7 @@
  public:
   ResourceDispatcher(
       IPC::Sender* sender,
-      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
+      scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner);
   ~ResourceDispatcher() override;
 
   // IPC::Listener implementation.
@@ -135,9 +135,9 @@
     io_timestamp_ = io_timestamp;
   }
 
-  void SetMainThreadTaskRunner(
-      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) {
-    main_thread_task_runner_ = main_thread_task_runner;
+  void SetThreadTaskRunner(
+      scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner) {
+    thread_task_runner_ = thread_task_runner;
   }
 
   void SetResourceSchedulingFilter(
@@ -271,7 +271,7 @@
   // IO thread timestamp for ongoing IPC message.
   base::TimeTicks io_timestamp_;
 
-  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
   scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter_;
 
   base::WeakPtrFactory<ResourceDispatcher> weak_factory_;
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index f22e0211..ec86af9 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -339,6 +339,9 @@
   WebRuntimeFeatures::EnableServiceWorkerNavigationPreload(
       base::FeatureList::IsEnabled(features::kServiceWorkerNavigationPreload));
 
+  WebRuntimeFeatures::EnableOffMainThreadFetch(
+      base::FeatureList::IsEnabled(features::kOffMainThreadFetch));
+
   if (base::FeatureList::IsEnabled(features::kGamepadExtensions))
     WebRuntimeFeatures::EnableGamepadExtensions(true);
 
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 10424ed..0f3eab3 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -396,7 +396,7 @@
     "//ppapi/features",
     "//sandbox",
     "//sandbox:sandbox_features",
-    "//services/resource_coordinator/public/interfaces",
+    "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
     "//services/service_manager",
     "//services/service_manager/embedder",
     "//services/service_manager/public/cpp",
@@ -609,6 +609,7 @@
     "url_loader.mojom",
     "url_loader_factory.mojom",
     "video_capture.mojom",
+    "worker_url_loader_factory_provider.mojom",
   ]
 
   import_dirs = [ "//mojo/services" ]
diff --git a/content/common/worker_url_loader_factory_provider.mojom b/content/common/worker_url_loader_factory_provider.mojom
new file mode 100644
index 0000000..6590e4f
--- /dev/null
+++ b/content/common/worker_url_loader_factory_provider.mojom
@@ -0,0 +1,33 @@
+// 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.
+
+module content.mojom;
+
+import "url_loader_factory.mojom";
+
+// A renderer-side interface that is returned by CreateWorkerFetchContext for
+// the browser to notify the renderer process when there's a controller change.
+interface ServiceWorkerWorkerClient {
+  // Called when the ServiceWorkerWorkerClient (which is a dedicated worker or
+  // a shared worker) is controlled by a new service worker.
+  SetControllerServiceWorker(int64 controller_version_id);
+};
+
+// A browser-side interface which provides URLLoaderFactory for worker contexts
+// in the renderer process.
+interface WorkerURLLoaderFactoryProvider {
+  // Called from a dedicated (or shared) worker thread to get the
+  // URLLoaderFactory and register ServiceWorkerWorkerClient of the worker.
+  // SetControllerServiceWorker method of the passed ServiceWorkerWorkerClient
+  // interface will be called when the parent frame and the worker context is
+  // controlled by a service worker. |service_worker_provider_id| is the service
+  // worker provider id of the parent frame.
+  GetURLLoaderFactoryAndRegisterClient(
+      associated URLLoaderFactory& loader,
+      associated ServiceWorkerWorkerClient client,
+      int32 service_worker_provider_id);
+
+  // Called from the service worker thread to get the URLLoaderFactory.
+  GetURLLoaderFactory(associated URLLoaderFactory& loader);
+};
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
index 0a09e02e..2067654 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
@@ -226,7 +226,7 @@
     public void showActionModeOrClearOnFailure() {
         mPendingShowActionMode = false;
 
-        if (!isActionModeSupported()) return;
+        if (!isActionModeSupported() || !mHasSelection) return;
 
         // Just refresh the view if action mode already exists.
         if (isActionModeValid()) {
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 697613f..81ad4d7 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -32,6 +32,7 @@
           "content::mojom::StoragePartitionService",
           "content::mojom::URLLoaderFactory",
           "content::mojom::VideoCaptureHost",
+          "content::mojom::WorkerURLLoaderFactoryProvider",
           "device::mojom::GamepadMonitor",
           "discardable_memory::mojom::DiscardableSharedMemoryManager",
           "media::mojom::ImageCapture",
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 20c365dd..d93fa78 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -353,10 +353,14 @@
     "service_worker/service_worker_context_client.h",
     "service_worker/service_worker_context_message_filter.cc",
     "service_worker/service_worker_context_message_filter.h",
+    "service_worker/service_worker_fetch_context_impl.cc",
+    "service_worker/service_worker_fetch_context_impl.h",
     "service_worker/service_worker_type_converters.cc",
     "service_worker/service_worker_type_converters.h",
     "service_worker/service_worker_type_util.cc",
     "service_worker/service_worker_type_util.h",
+    "service_worker/worker_fetch_context_impl.cc",
+    "service_worker/worker_fetch_context_impl.h",
     "shared_memory_seqlock_reader.cc",
     "shared_memory_seqlock_reader.h",
     "shared_worker/embedded_shared_worker_content_settings_client_proxy.cc",
diff --git a/content/renderer/media_recorder/media_recorder_handler.cc b/content/renderer/media_recorder/media_recorder_handler.cc
index 16b0bb1..da7ebde5 100644
--- a/content/renderer/media_recorder/media_recorder_handler.cc
+++ b/content/renderer/media_recorder/media_recorder_handler.cc
@@ -292,33 +292,19 @@
 
   // TODO(mcasas): Support the case when both video and audio configurations are
   // specified: https://crbug.com/709181.
-  std::string content_type;
-  if (configuration.video_configuration)
-    content_type = configuration.video_configuration->content_type.Ascii();
-  else
-    content_type = configuration.audio_configuration->content_type.Ascii();
-
-  // |content_type| should be of the form "bla;codecs=foo", where "bla" is the
-  // type and "codecs=foo" is the parameter ("foo" is the parameter value), see
-  // RFC 2231 [1]. CanSupportMimeType() operates on type and parameter value.
-  // [1] https://tools.ietf.org/html/rfc2231
-  base::StringTokenizer mime_tokenizer(content_type, ";");
-  blink::WebString web_type;
-  blink::WebString web_codecs;
-  if (mime_tokenizer.GetNext())
-    web_type = blink::WebString::FromASCII(mime_tokenizer.token());
-  if (mime_tokenizer.GetNext()) {
-    const std::string parameters = mime_tokenizer.token();
-    base::StringTokenizer parameter_tokenizer(parameters, "=");
-    if (parameter_tokenizer.GetNext() &&
-        base::ToLowerASCII(parameter_tokenizer.token()) == "codecs" &&
-        parameter_tokenizer.GetNext()) {
-      web_codecs = blink::WebString::FromASCII(parameter_tokenizer.token());
-    }
+  blink::WebString mime_type;
+  blink::WebString codec;
+  if (configuration.video_configuration) {
+    mime_type = configuration.video_configuration->mime_type;
+    codec = configuration.video_configuration->codec;
+  } else {
+    mime_type = configuration.audio_configuration->mime_type;
+    codec = configuration.audio_configuration->codec;
   }
 
-  info->supported = CanSupportMimeType(web_type, web_codecs);
-  DVLOG(1) << "type: " << web_type.Ascii() << ", params:" << web_codecs.Ascii()
+  // See RFC 2231. https://tools.ietf.org/html/rfc2231
+  info->supported = CanSupportMimeType(mime_type, codec);
+  DVLOG(1) << "type: " << mime_type.Ascii() << ", codec:" << codec.Ascii()
            << " is" << (info->supported ? " supported" : " NOT supported");
 
   scoped_callbacks.PassCallbacks()->OnSuccess(std::move(info));
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 5aead0f6..f2a8396 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -16,6 +16,7 @@
 #include "base/debug/asan_invalid_access.h"
 #include "base/debug/crash_logging.h"
 #include "base/debug/dump_without_crashing.h"
+#include "base/feature_list.h"
 #include "base/files/file.h"
 #include "base/i18n/char_iterator.h"
 #include "base/logging.h"
@@ -69,6 +70,7 @@
 #include "content/common/site_isolation_policy.h"
 #include "content/common/swapped_out_messages.h"
 #include "content/common/view_messages.h"
+#include "content/common/worker_url_loader_factory_provider.mojom.h"
 #include "content/public/common/appcache_info.h"
 #include "content/public/common/associated_interface_provider.h"
 #include "content/public/common/bindings_policy.h"
@@ -142,6 +144,7 @@
 #include "content/renderer/renderer_webcolorchooser_impl.h"
 #include "content/renderer/savable_resources.h"
 #include "content/renderer/screen_orientation/screen_orientation_dispatcher.h"
+#include "content/renderer/service_worker/worker_fetch_context_impl.h"
 #include "content/renderer/shared_worker/shared_worker_repository.h"
 #include "content/renderer/shared_worker/websharedworker_proxy.h"
 #include "content/renderer/skia_benchmarking_extension.h"
@@ -179,6 +182,7 @@
 #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
 #include "storage/common/data_element.h"
 #include "third_party/WebKit/public/platform/FilePathConversion.h"
+#include "third_party/WebKit/public/platform/InterfaceProvider.h"
 #include "third_party/WebKit/public/platform/URLConversion.h"
 #include "third_party/WebKit/public/platform/WebCachePolicy.h"
 #include "third_party/WebKit/public/platform/WebData.h"
@@ -3026,6 +3030,31 @@
       this, frame_);
 }
 
+std::unique_ptr<blink::WebWorkerFetchContext>
+RenderFrameImpl::CreateWorkerFetchContext() {
+  DCHECK(base::FeatureList::IsEnabled(features::kOffMainThreadFetch));
+  mojom::WorkerURLLoaderFactoryProviderPtr worker_url_loader_factory_provider;
+  RenderThreadImpl::current()
+      ->blink_platform_impl()
+      ->GetInterfaceProvider()
+      ->GetInterface(mojo::MakeRequest(&worker_url_loader_factory_provider));
+  std::unique_ptr<WorkerFetchContextImpl> worker_fetch_context =
+      base::MakeUnique<WorkerFetchContextImpl>(
+          worker_url_loader_factory_provider.PassInterface());
+  blink::WebServiceWorkerNetworkProvider* web_provider =
+      frame_->DataSource()->GetServiceWorkerNetworkProvider();
+  if (web_provider) {
+    ServiceWorkerNetworkProvider* provider =
+        ServiceWorkerNetworkProvider::FromWebServiceWorkerNetworkProvider(
+            web_provider);
+    worker_fetch_context->set_service_worker_provider_id(
+        provider->provider_id());
+    worker_fetch_context->set_is_controlled_by_service_worker(
+        provider->IsControlledByServiceWorker());
+  }
+  return std::move(worker_fetch_context);
+}
+
 WebExternalPopupMenu* RenderFrameImpl::CreateExternalPopupMenu(
     const WebPopupMenuInfo& popup_menu_info,
     WebExternalPopupMenuClient* popup_menu_client) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index ec8f52a..4678434e 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -501,6 +501,8 @@
       blink::WebApplicationCacheHostClient* client) override;
   blink::WebWorkerContentSettingsClientProxy*
   CreateWorkerContentSettingsClientProxy() override;
+  std::unique_ptr<blink::WebWorkerFetchContext> CreateWorkerFetchContext()
+      override;
   blink::WebExternalPopupMenu* CreateExternalPopupMenu(
       const blink::WebPopupMenuInfo& popup_menu_info,
       blink::WebExternalPopupMenuClient* popup_menu_client) override;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 7a77da1..0969970 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -881,8 +881,6 @@
       base::ThreadPriority::BACKGROUND);
 #endif
 
-  record_purge_suspend_metric_closure_.Reset(base::Bind(
-      &RenderThreadImpl::RecordPurgeAndSuspendMetrics, base::Unretained(this)));
   record_purge_suspend_growth_metric_closure_.Reset(
       base::Bind(&RenderThreadImpl::RecordPurgeAndSuspendMemoryGrowthMetrics,
                  base::Unretained(this)));
@@ -1161,7 +1159,7 @@
   // same queue to ensure tasks are executed in the expected order.
   child_resource_message_filter()->SetMainThreadTaskRunner(
       resource_task_queue2);
-  resource_dispatcher()->SetMainThreadTaskRunner(resource_task_queue2);
+  resource_dispatcher()->SetThreadTaskRunner(resource_task_queue2);
 
   if (!command_line.HasSwitch(switches::kDisableThreadedCompositing))
     InitializeCompositorThread();
@@ -1638,10 +1636,6 @@
   } else {
     renderer_scheduler_->OnRendererForegrounded();
 
-    record_purge_suspend_metric_closure_.Cancel();
-    record_purge_suspend_metric_closure_.Reset(
-        base::Bind(&RenderThreadImpl::RecordPurgeAndSuspendMetrics,
-                   base::Unretained(this)));
     record_purge_suspend_growth_metric_closure_.Cancel();
     record_purge_suspend_growth_metric_closure_.Reset(
         base::Bind(&RenderThreadImpl::RecordPurgeAndSuspendMemoryGrowthMetrics,
@@ -1654,18 +1648,27 @@
   if (!RendererIsHidden())
     return;
 
-  if (base::FeatureList::IsEnabled(features::kPurgeAndSuspend)) {
-    base::MemoryCoordinatorClientRegistry::GetInstance()->PurgeMemory();
-  }
-  // Since purging is not a synchronous task (e.g. v8 GC, oilpan GC, ...),
-  // we need to wait until the task is finished. So wait 15 seconds and
-  // update purge+suspend UMA histogram.
-  // TODO(tasak): use MemoryCoordinator's callback to report purge+suspend
-  // UMA when MemoryCoordinator is available.
-  GetRendererScheduler()->DefaultTaskRunner()->PostDelayedTask(
-      FROM_HERE, record_purge_suspend_metric_closure_.callback(),
-      base::TimeDelta::FromSeconds(15));
+  if (!base::FeatureList::IsEnabled(features::kPurgeAndSuspend))
+    return;
+
+  base::MemoryCoordinatorClientRegistry::GetInstance()->PurgeMemory();
   needs_to_record_first_active_paint_ = true;
+
+  RendererMemoryMetrics memory_metrics;
+  if (!GetRendererMemoryMetrics(&memory_metrics))
+    return;
+
+  purge_and_suspend_memory_metrics_ = memory_metrics;
+  // record how many memory usage increases after purged.
+  GetRendererScheduler()->DefaultTaskRunner()->PostDelayedTask(
+      FROM_HERE, record_purge_suspend_growth_metric_closure_.callback(),
+      base::TimeDelta::FromMinutes(5));
+  GetRendererScheduler()->DefaultTaskRunner()->PostDelayedTask(
+      FROM_HERE, record_purge_suspend_growth_metric_closure_.callback(),
+      base::TimeDelta::FromMinutes(10));
+  GetRendererScheduler()->DefaultTaskRunner()->PostDelayedTask(
+      FROM_HERE, record_purge_suspend_growth_metric_closure_.callback(),
+      base::TimeDelta::FromMinutes(15));
 }
 
 // TODO(tasak): Replace the following GetMallocUsage() with memory-infra
@@ -1762,47 +1765,6 @@
   return true;
 }
 
-// TODO(tasak): Once it is possible to use memory-infra without tracing,
-// we should collect the metrics using memory-infra.
-// TODO(tasak): We should also report a difference between the memory usages
-// before and after purging by using memory-infra.
-void RenderThreadImpl::RecordPurgeAndSuspendMetrics() {
-  // If this renderer is resumed, we should not update UMA.
-  if (!RendererIsHidden())
-    return;
-
-  // TODO(tasak): Compare memory metrics between purge-enabled renderers and
-  // purge-disabled renderers (A/B testing).
-  RendererMemoryMetrics memory_metrics;
-  if (!GetRendererMemoryMetrics(&memory_metrics))
-    return;
-
-  UMA_HISTOGRAM_MEMORY_KB("PurgeAndSuspend.Memory.PartitionAllocKB",
-                          memory_metrics.partition_alloc_kb);
-  UMA_HISTOGRAM_MEMORY_KB("PurgeAndSuspend.Memory.BlinkGCKB",
-                          memory_metrics.blink_gc_kb);
-  UMA_HISTOGRAM_MEMORY_MB("PurgeAndSuspend.Memory.MallocMB",
-                          memory_metrics.malloc_mb);
-  UMA_HISTOGRAM_MEMORY_KB("PurgeAndSuspend.Memory.DiscardableKB",
-                          memory_metrics.discardable_kb);
-  UMA_HISTOGRAM_MEMORY_MB("PurgeAndSuspend.Memory.V8MainThreadIsolateMB",
-                          memory_metrics.v8_main_thread_isolate_mb);
-  UMA_HISTOGRAM_MEMORY_MB("PurgeAndSuspend.Memory.TotalAllocatedMB",
-                          memory_metrics.total_allocated_mb);
-  purge_and_suspend_memory_metrics_ = memory_metrics;
-
-  // record how many memory usage increases after purged.
-  GetRendererScheduler()->DefaultTaskRunner()->PostDelayedTask(
-      FROM_HERE, record_purge_suspend_growth_metric_closure_.callback(),
-      base::TimeDelta::FromMinutes(5));
-  GetRendererScheduler()->DefaultTaskRunner()->PostDelayedTask(
-      FROM_HERE, record_purge_suspend_growth_metric_closure_.callback(),
-      base::TimeDelta::FromMinutes(10));
-  GetRendererScheduler()->DefaultTaskRunner()->PostDelayedTask(
-      FROM_HERE, record_purge_suspend_growth_metric_closure_.callback(),
-      base::TimeDelta::FromMinutes(15));
-}
-
 #define GET_MEMORY_GROWTH(current, previous, allocator) \
   (current.allocator > previous.allocator               \
        ? current.allocator - previous.allocator         \
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 5438b78d..8ca048b 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -580,7 +580,6 @@
   void OnRendererHidden();
   void OnRendererVisible();
 
-  void RecordPurgeAndSuspendMetrics();
   void RecordPurgeAndSuspendMemoryGrowthMetrics() const;
 
   void ReleaseFreeMemory();
@@ -781,7 +780,6 @@
   mojom::RenderFrameMessageFilterAssociatedPtr render_frame_message_filter_;
   mojom::RenderMessageFilterAssociatedPtr render_message_filter_;
 
-  base::CancelableClosure record_purge_suspend_metric_closure_;
   RendererMemoryMetrics purge_and_suspend_memory_metrics_;
   base::CancelableClosure record_purge_suspend_growth_metric_closure_;
   bool needs_to_record_first_active_paint_;
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 096ad12..ca6f42f 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -38,20 +38,25 @@
 #include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
 #include "content/common/service_worker/service_worker_messages.h"
 #include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/worker_url_loader_factory_provider.mojom.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/push_event_payload.h"
 #include "content/public/common/referrer.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/renderer/document_state.h"
 #include "content/renderer/devtools/devtools_agent.h"
 #include "content/renderer/render_thread_impl.h"
+#include "content/renderer/renderer_blink_platform_impl.h"
 #include "content/renderer/service_worker/embedded_worker_devtools_agent.h"
 #include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
+#include "content/renderer/service_worker/service_worker_fetch_context_impl.h"
 #include "content/renderer/service_worker/service_worker_type_converters.h"
 #include "content/renderer/service_worker/service_worker_type_util.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_macros.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_response_headers.h"
+#include "third_party/WebKit/public/platform/InterfaceProvider.h"
 #include "third_party/WebKit/public/platform/URLConversion.h"
 #include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
@@ -1064,6 +1069,7 @@
           MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER,
           true /* is_parent_frame_secure */);
   provider_context_ = provider->context();
+  network_provider_id_ = provider->provider_id();
 
   // Tell the network provider about which version to load.
   provider->SetServiceWorkerVersionId(service_worker_version_id_,
@@ -1073,6 +1079,21 @@
   return new WebServiceWorkerNetworkProviderImpl(std::move(provider));
 }
 
+std::unique_ptr<blink::WebWorkerFetchContext>
+ServiceWorkerContextClient::CreateServiceWorkerFetchContext() {
+  DCHECK(main_thread_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(base::FeatureList::IsEnabled(features::kOffMainThreadFetch));
+  mojom::WorkerURLLoaderFactoryProviderPtr worker_url_loader_factory_provider;
+  RenderThreadImpl::current()
+      ->blink_platform_impl()
+      ->GetInterfaceProvider()
+      ->GetInterface(mojo::MakeRequest(&worker_url_loader_factory_provider));
+
+  // Blink is responsible for deleting the returned object.
+  return base::MakeUnique<ServiceWorkerFetchContextImpl>(
+      worker_url_loader_factory_provider.PassInterface(), network_provider_id_);
+}
+
 blink::WebServiceWorkerProvider*
 ServiceWorkerContextClient::CreateServiceWorkerProvider() {
   DCHECK(main_thread_task_runner_->RunsTasksOnCurrentThread());
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 835f079..a3a63e63 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -61,6 +61,7 @@
 class ServiceWorkerContextClient;
 class ThreadSafeSender;
 class EmbeddedWorkerInstanceClientImpl;
+class WebWorkerFetchContext;
 
 // This class provides access to/from an ServiceWorker's WorkerGlobalScope.
 // Unless otherwise noted, all methods are called on the worker thread.
@@ -197,6 +198,8 @@
   // Called on the main thread.
   blink::WebServiceWorkerNetworkProvider* CreateServiceWorkerNetworkProvider()
       override;
+  std::unique_ptr<blink::WebWorkerFetchContext>
+  CreateServiceWorkerFetchContext() override;
   blink::WebServiceWorkerProvider* CreateServiceWorkerProvider() override;
 
   void PostMessageToClient(const blink::WebString& uuid,
@@ -328,6 +331,7 @@
   const int64_t service_worker_version_id_;
   const GURL service_worker_scope_;
   const GURL script_url_;
+  int network_provider_id_ = kInvalidServiceWorkerProviderId;
   scoped_refptr<ThreadSafeSender> sender_;
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
   scoped_refptr<base::TaskRunner> worker_task_runner_;
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
new file mode 100644
index 0000000..3806edb4
--- /dev/null
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -0,0 +1,49 @@
+// 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.
+
+#include "content/renderer/service_worker/service_worker_fetch_context_impl.h"
+
+#include "content/child/request_extra_data.h"
+#include "content/child/resource_dispatcher.h"
+#include "content/child/web_url_loader_impl.h"
+
+namespace content {
+
+ServiceWorkerFetchContextImpl::ServiceWorkerFetchContextImpl(
+    mojom::WorkerURLLoaderFactoryProviderPtrInfo provider_info,
+    int service_worker_provider_id)
+    : provider_info_(std::move(provider_info)),
+      service_worker_provider_id_(service_worker_provider_id) {}
+
+ServiceWorkerFetchContextImpl::~ServiceWorkerFetchContextImpl() {}
+
+void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread(
+    base::SingleThreadTaskRunner* loading_task_runner) {
+  DCHECK(provider_info_.is_valid());
+  resource_dispatcher_ =
+      base::MakeUnique<ResourceDispatcher>(nullptr, loading_task_runner);
+  provider_.Bind(std::move(provider_info_));
+  provider_->GetURLLoaderFactory(mojo::MakeRequest(&url_loader_factory_));
+}
+
+std::unique_ptr<blink::WebURLLoader>
+ServiceWorkerFetchContextImpl::CreateURLLoader() {
+  return base::MakeUnique<content::WebURLLoaderImpl>(resource_dispatcher_.get(),
+                                                     url_loader_factory_.get());
+}
+
+void ServiceWorkerFetchContextImpl::WillSendRequest(
+    blink::WebURLRequest& request) {
+  RequestExtraData* extra_data = new RequestExtraData();
+  extra_data->set_service_worker_provider_id(service_worker_provider_id_);
+  extra_data->set_originated_from_service_worker(true);
+  extra_data->set_initiated_in_secure_context(true);
+  request.SetExtraData(extra_data);
+}
+
+bool ServiceWorkerFetchContextImpl::IsControlledByServiceWorker() const {
+  return false;
+}
+
+}  // namespace content
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.h b/content/renderer/service_worker/service_worker_fetch_context_impl.h
new file mode 100644
index 0000000..71f6ef4
--- /dev/null
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -0,0 +1,43 @@
+// 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.
+
+#ifndef CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_FETCH_CONTEXT_IMPL_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_FETCH_CONTEXT_IMPL_H_
+
+#include "content/common/worker_url_loader_factory_provider.mojom.h"
+#include "third_party/WebKit/public/platform/WebWorkerFetchContext.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}  // namespace base
+
+namespace content {
+class ResourceDispatcher;
+
+class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext {
+ public:
+  ServiceWorkerFetchContextImpl(
+      mojom::WorkerURLLoaderFactoryProviderPtrInfo provider_info,
+      int service_worker_provider_id);
+  ~ServiceWorkerFetchContextImpl() override;
+
+  // blink::WebWorkerFetchContext implementation:
+  void InitializeOnWorkerThread(base::SingleThreadTaskRunner*) override;
+  std::unique_ptr<blink::WebURLLoader> CreateURLLoader() override;
+  void WillSendRequest(blink::WebURLRequest&) override;
+  bool IsControlledByServiceWorker() const override;
+
+ private:
+  mojom::WorkerURLLoaderFactoryProviderPtrInfo provider_info_;
+  const int service_worker_provider_id_;
+
+  // Initialized on the worker thread when InitializeOnWorkerThread() is called.
+  std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
+  mojom::WorkerURLLoaderFactoryProviderPtr provider_;
+  mojom::URLLoaderFactoryAssociatedPtr url_loader_factory_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_FETCH_CONTEXT_IMPL_H_
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.cc b/content/renderer/service_worker/worker_fetch_context_impl.cc
new file mode 100644
index 0000000..f204642
--- /dev/null
+++ b/content/renderer/service_worker/worker_fetch_context_impl.cc
@@ -0,0 +1,74 @@
+// 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.
+
+#include "content/renderer/service_worker/worker_fetch_context_impl.h"
+
+#include "content/child/request_extra_data.h"
+#include "content/child/resource_dispatcher.h"
+#include "content/child/web_url_loader_impl.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+
+namespace content {
+
+WorkerFetchContextImpl::WorkerFetchContextImpl(
+    mojom::WorkerURLLoaderFactoryProviderPtrInfo provider_info)
+    : provider_info_(std::move(provider_info)) {}
+
+WorkerFetchContextImpl::~WorkerFetchContextImpl() {}
+
+void WorkerFetchContextImpl::InitializeOnWorkerThread(
+    base::SingleThreadTaskRunner* loading_task_runner) {
+  DCHECK(loading_task_runner->RunsTasksOnCurrentThread());
+  DCHECK(!resource_dispatcher_);
+  DCHECK(!binding_);
+  resource_dispatcher_ =
+      base::MakeUnique<ResourceDispatcher>(nullptr, loading_task_runner);
+  binding_ = base::MakeUnique<
+      mojo::AssociatedBinding<mojom::ServiceWorkerWorkerClient>>(this);
+  DCHECK(provider_info_.is_valid());
+  provider_.Bind(std::move(provider_info_));
+  mojom::ServiceWorkerWorkerClientAssociatedPtrInfo ptr_info;
+  binding_->Bind(&ptr_info);
+  provider_->GetURLLoaderFactoryAndRegisterClient(
+      mojo::MakeRequest(&url_loader_factory_), std::move(ptr_info),
+      service_worker_provider_id_);
+}
+
+std::unique_ptr<blink::WebURLLoader> WorkerFetchContextImpl::CreateURLLoader() {
+  return base::MakeUnique<content::WebURLLoaderImpl>(resource_dispatcher_.get(),
+                                                     url_loader_factory_.get());
+}
+
+void WorkerFetchContextImpl::WillSendRequest(blink::WebURLRequest& request) {
+  RequestExtraData* extra_data = new RequestExtraData();
+  extra_data->set_service_worker_provider_id(service_worker_provider_id_);
+  request.SetExtraData(extra_data);
+
+  if (!IsControlledByServiceWorker() &&
+      request.GetServiceWorkerMode() !=
+          blink::WebURLRequest::ServiceWorkerMode::kNone) {
+    request.SetServiceWorkerMode(
+        blink::WebURLRequest::ServiceWorkerMode::kForeign);
+  }
+}
+
+bool WorkerFetchContextImpl::IsControlledByServiceWorker() const {
+  return is_controlled_by_service_worker_ ||
+         (controller_version_id_ != kInvalidServiceWorkerVersionId);
+}
+
+void WorkerFetchContextImpl::set_service_worker_provider_id(int id) {
+  service_worker_provider_id_ = id;
+}
+
+void WorkerFetchContextImpl::set_is_controlled_by_service_worker(bool flag) {
+  is_controlled_by_service_worker_ = flag;
+}
+
+void WorkerFetchContextImpl::SetControllerServiceWorker(
+    int64_t controller_version_id) {
+  controller_version_id_ = controller_version_id;
+}
+
+}  // namespace content
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.h b/content/renderer/service_worker/worker_fetch_context_impl.h
new file mode 100644
index 0000000..62ad5ea
--- /dev/null
+++ b/content/renderer/service_worker/worker_fetch_context_impl.h
@@ -0,0 +1,60 @@
+// 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.
+
+#ifndef CONTENT_RENDERER_SERVICE_WORKER_WORKER_FETCH_CONTEXT_IMPL_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_WORKER_FETCH_CONTEXT_IMPL_H_
+
+#include "content/common/service_worker/service_worker_types.h"
+#include "content/common/worker_url_loader_factory_provider.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "third_party/WebKit/public/platform/WebWorkerFetchContext.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}  // namespace base
+
+namespace content {
+
+class ResourceDispatcher;
+
+class WorkerFetchContextImpl : public blink::WebWorkerFetchContext,
+                               public mojom::ServiceWorkerWorkerClient {
+ public:
+  explicit WorkerFetchContextImpl(
+      mojom::WorkerURLLoaderFactoryProviderPtrInfo provider_info);
+  ~WorkerFetchContextImpl() override;
+
+  // blink::WebWorkerFetchContext implementation:
+  void InitializeOnWorkerThread(base::SingleThreadTaskRunner*) override;
+  std::unique_ptr<blink::WebURLLoader> CreateURLLoader() override;
+  void WillSendRequest(blink::WebURLRequest&) override;
+  bool IsControlledByServiceWorker() const override;
+
+  // mojom::ServiceWorkerWorkerClient implementation:
+  void SetControllerServiceWorker(int64_t controller_version_id) override;
+
+  // Sets the service worker status of the parent frame.
+  void set_service_worker_provider_id(int id);
+  void set_is_controlled_by_service_worker(bool flag);
+
+ private:
+  mojom::WorkerURLLoaderFactoryProviderPtrInfo provider_info_;
+  int service_worker_provider_id_ = kInvalidServiceWorkerProviderId;
+  bool is_controlled_by_service_worker_ = false;
+
+  // Initialized on the worker thread when InitializeOnWorkerThread() is called.
+  std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
+  std::unique_ptr<mojo::AssociatedBinding<mojom::ServiceWorkerWorkerClient>>
+      binding_;
+  mojom::WorkerURLLoaderFactoryProviderPtr provider_;
+  mojom::URLLoaderFactoryAssociatedPtr url_loader_factory_;
+
+  // Updated when mojom::ServiceWorkerWorkerClient::SetControllerServiceWorker()
+  // is called from the browser process via mojo IPC.
+  int controller_version_id_ = kInvalidServiceWorkerVersionId;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_SERVICE_WORKER_WORKER_FETCH_CONTEXT_IMPL_H_
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 064d24b..712b7e7 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -7,6 +7,7 @@
 #include <stdint.h>
 #include <utility>
 
+#include "base/feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/child/appcache/appcache_dispatcher.h"
 #include "content/child/appcache/web_application_cache_host_impl.h"
@@ -18,12 +19,17 @@
 #include "content/child/shared_worker_devtools_agent.h"
 #include "content/child/webmessageportchannel_impl.h"
 #include "content/common/worker_messages.h"
+#include "content/common/worker_url_loader_factory_provider.mojom.h"
 #include "content/public/common/appcache_info.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/origin_util.h"
 #include "content/renderer/devtools/devtools_agent.h"
 #include "content/renderer/render_thread_impl.h"
+#include "content/renderer/renderer_blink_platform_impl.h"
+#include "content/renderer/service_worker/worker_fetch_context_impl.h"
 #include "content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h"
 #include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/InterfaceProvider.h"
 #include "third_party/WebKit/public/platform/URLConversion.h"
 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h"
@@ -252,6 +258,30 @@
   return DevToolsAgent::createMessageLoopWrapper();
 }
 
+std::unique_ptr<blink::WebWorkerFetchContext>
+EmbeddedSharedWorkerStub::CreateWorkerFetchContext(
+    blink::WebServiceWorkerNetworkProvider* web_network_provider) {
+  DCHECK(base::FeatureList::IsEnabled(features::kOffMainThreadFetch));
+  mojom::WorkerURLLoaderFactoryProviderPtr worker_url_loader_factory_provider;
+  RenderThreadImpl::current()
+      ->blink_platform_impl()
+      ->GetInterfaceProvider()
+      ->GetInterface(mojo::MakeRequest(&worker_url_loader_factory_provider));
+  std::unique_ptr<WorkerFetchContextImpl> worker_fetch_context =
+      base::MakeUnique<WorkerFetchContextImpl>(
+          worker_url_loader_factory_provider.PassInterface());
+  if (web_network_provider) {
+    ServiceWorkerNetworkProvider* network_provider =
+        ServiceWorkerNetworkProvider::FromWebServiceWorkerNetworkProvider(
+            web_network_provider);
+    worker_fetch_context->set_service_worker_provider_id(
+        network_provider->provider_id());
+    worker_fetch_context->set_is_controlled_by_service_worker(
+        network_provider->IsControlledByServiceWorker());
+  }
+  return std::move(worker_fetch_context);
+}
+
 void EmbeddedSharedWorkerStub::Shutdown() {
   // WebSharedWorker must be already deleted in the blink side
   // when this is called.
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.h b/content/renderer/shared_worker/embedded_shared_worker_stub.h
index 5554f20..39226b76 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.h
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -81,6 +81,8 @@
                            const blink::WebString& state) override;
   blink::WebDevToolsAgentClient::WebKitClientMessageLoop*
   CreateDevToolsMessageLoop() override;
+  std::unique_ptr<blink::WebWorkerFetchContext> CreateWorkerFetchContext(
+      blink::WebServiceWorkerNetworkProvider*) override;
 
  private:
   ~EmbeddedSharedWorkerStub() override;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index dfa827f..d64ba09 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -636,6 +636,7 @@
     "../browser/media/media_browsertest.cc",
     "../browser/media/media_browsertest.h",
     "../browser/media/media_canplaytype_browsertest.cc",
+    "../browser/media/media_capabilities_browsertest.cc",
     "../browser/media/media_color_browsertest.cc",
     "../browser/media/media_redirect_browsertest.cc",
     "../browser/media/media_source_browsertest.cc",
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index c809245..44d999d80 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -286,6 +286,8 @@
     self.Fail('conformance/canvas/' +
         'framebuffer-bindings-affected-by-to-data-url.html',
         ['win10', ('nvidia', 0x1cb3), 'd3d9'], bug=680754)
+    self.Fail('conformance/limits/gl-max-texture-dimensions.html',
+        ['win10', ('nvidia', 0x1cb3)], bug=715001)
     self.Fail('conformance/ogles/GL/cos/cos_001_to_006.html',
         ['win10', ('nvidia', 0x1cb3), 'd3d9'], bug=680754)
 
@@ -472,6 +474,8 @@
         ['linux', 'nvidia'], bug=672380)
 
     # NVIDIA P400 OpenGL
+    self.Fail('conformance/limits/gl-max-texture-dimensions.html',
+        ['linux', ('nvidia', 0x1cb3)], bug=715001)
     self.Fail('conformance/textures/misc/texture-size.html',
         ['linux', ('nvidia', 0x1cb3), 'opengl'], bug=703779)
     self.Fail('conformance/extensions/webgl-compressed-texture-size-limit.html',
diff --git a/device/u2f/u2f_device.h b/device/u2f/u2f_device.h
index 9537d44b..2a5323d 100644
--- a/device/u2f/u2f_device.h
+++ b/device/u2f/u2f_device.h
@@ -26,7 +26,7 @@
   };
 
   using MessageCallback =
-      base::Callback<void(U2fReturnCode, std::vector<uint8_t>)>;
+      base::Callback<void(U2fReturnCode, const std::vector<uint8_t>&)>;
   using VersionCallback =
       base::Callback<void(bool success, ProtocolVersion version)>;
   using DeviceCallback =
diff --git a/device/u2f/u2f_register.cc b/device/u2f/u2f_register.cc
index 0f43e260..babfe98 100644
--- a/device/u2f/u2f_register.cc
+++ b/device/u2f/u2f_register.cc
@@ -38,7 +38,7 @@
 }
 
 void U2fRegister::OnTryDevice(U2fReturnCode return_code,
-                              std::vector<uint8_t> response_data) {
+                              const std::vector<uint8_t>& response_data) {
   switch (return_code) {
     case U2fReturnCode::SUCCESS:
       state_ = State::COMPLETE;
diff --git a/device/u2f/u2f_register.h b/device/u2f/u2f_register.h
index 466127ed..7b7769e 100644
--- a/device/u2f/u2f_register.h
+++ b/device/u2f/u2f_register.h
@@ -25,7 +25,8 @@
 
  private:
   void TryDevice() override;
-  void OnTryDevice(U2fReturnCode, std::vector<uint8_t>);
+  void OnTryDevice(U2fReturnCode return_code,
+                   const std::vector<uint8_t>& response_data);
 
   std::vector<uint8_t> challenge_hash_;
   std::vector<uint8_t> app_param_;
diff --git a/device/u2f/u2f_register_unittest.cc b/device/u2f/u2f_register_unittest.cc
index 2d0d2d4..6b183da5 100644
--- a/device/u2f/u2f_register_unittest.cc
+++ b/device/u2f/u2f_register_unittest.cc
@@ -38,7 +38,7 @@
   ~TestRegisterCallback() {}
 
   void ReceivedCallback(U2fReturnCode status_code,
-                        std::vector<uint8_t> response) {
+                        const std::vector<uint8_t>& response) {
     response_ = std::make_pair(status_code, response);
     closure_.Run();
   }
diff --git a/device/u2f/u2f_request.h b/device/u2f/u2f_request.h
index 902a2ca..f8d8f3a 100644
--- a/device/u2f/u2f_request.h
+++ b/device/u2f/u2f_request.h
@@ -14,8 +14,9 @@
 namespace device {
 class U2fRequest : HidService::Observer {
  public:
-  using ResponseCallback = base::Callback<void(U2fReturnCode status_code,
-                                               std::vector<uint8_t> response)>;
+  using ResponseCallback =
+      base::Callback<void(U2fReturnCode status_code,
+                          const std::vector<uint8_t>& response)>;
 
   U2fRequest(const ResponseCallback& callback);
   virtual ~U2fRequest();
diff --git a/device/u2f/u2f_request_unittest.cc b/device/u2f/u2f_request_unittest.cc
index 53c2130a..9775d86e 100644
--- a/device/u2f/u2f_request_unittest.cc
+++ b/device/u2f/u2f_request_unittest.cc
@@ -45,7 +45,8 @@
                              base::Unretained(this))) {}
   ~TestResponseCallback() {}
 
-  void ReceivedCallback(U2fReturnCode status, std::vector<uint8_t> data) {
+  void ReceivedCallback(U2fReturnCode status,
+                        const std::vector<uint8_t>& data) {
     closure_.Run();
   }
 
diff --git a/device/u2f/u2f_sign.cc b/device/u2f/u2f_sign.cc
index d537c48..a1f5b7d 100644
--- a/device/u2f/u2f_sign.cc
+++ b/device/u2f/u2f_sign.cc
@@ -52,7 +52,7 @@
 
 void U2fSign::OnTryDevice(std::vector<std::vector<uint8_t>>::const_iterator it,
                           U2fReturnCode return_code,
-                          std::vector<uint8_t> response_data) {
+                          const std::vector<uint8_t>& response_data) {
   switch (return_code) {
     case U2fReturnCode::SUCCESS:
       state_ = State::COMPLETE;
diff --git a/device/u2f/u2f_sign.h b/device/u2f/u2f_sign.h
index e924137..912fc77 100644
--- a/device/u2f/u2f_sign.h
+++ b/device/u2f/u2f_sign.h
@@ -27,9 +27,9 @@
 
  private:
   void TryDevice() override;
-  void OnTryDevice(std::vector<std::vector<uint8_t>>::const_iterator,
-                   U2fReturnCode,
-                   std::vector<uint8_t>);
+  void OnTryDevice(std::vector<std::vector<uint8_t>>::const_iterator it,
+                   U2fReturnCode return_code,
+                   const std::vector<uint8_t>& response_data);
 
   const std::vector<std::vector<uint8_t>> registered_keys_;
   std::vector<uint8_t> challenge_hash_;
diff --git a/device/u2f/u2f_sign_unittest.cc b/device/u2f/u2f_sign_unittest.cc
index 8c846217..95650cad 100644
--- a/device/u2f/u2f_sign_unittest.cc
+++ b/device/u2f/u2f_sign_unittest.cc
@@ -37,7 +37,7 @@
   ~TestSignCallback() {}
 
   void ReceivedCallback(U2fReturnCode status_code,
-                        std::vector<uint8_t> response) {
+                        const std::vector<uint8_t>& response) {
     response_ = std::make_pair(status_code, response);
     closure_.Run();
   }
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc
index b5b60aa..5579586 100644
--- a/gpu/config/gpu_finch_features.cc
+++ b/gpu/config/gpu_finch_features.cc
@@ -9,8 +9,8 @@
 
 // Enable GPU Rasterization by default. This can still be overridden by
 // --force-gpu-rasterization or --disable-gpu-rasterization.
-#if defined(OS_MACOSX)
-// DefaultEnableGpuRasterization has launched on Mac.
+#if defined(OS_MACOSX) || defined(OS_WIN)
+// DefaultEnableGpuRasterization has launched on Mac and Windows.
 const base::Feature kDefaultEnableGpuRasterization{
     "DefaultEnableGpuRasterization", base::FEATURE_ENABLED_BY_DEFAULT};
 #else
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc
index affb8cc3..9b9471c 100644
--- a/media/base/mime_util_internal.cc
+++ b/media/base/mime_util_internal.cc
@@ -415,8 +415,10 @@
   const std::string mime_type_lower_case = base::ToLowerASCII(mime_type);
   MediaFormatMappings::const_iterator it_media_format_map =
       media_format_map_.find(mime_type_lower_case);
-  if (it_media_format_map == media_format_map_.end())
+  if (it_media_format_map == media_format_map_.end()) {
+    DVLOG(3) << __func__ << " Unrecognized mime type: " << mime_type;
     return IsNotSupported;
+  }
 
   if (it_media_format_map->second.empty()) {
     // We get here if the mimetype does not expect a codecs parameter.
diff --git a/media/blink/webmediacapabilitiesclient_impl.cc b/media/blink/webmediacapabilitiesclient_impl.cc
index a407f88..7b9ecbc 100644
--- a/media/blink/webmediacapabilitiesclient_impl.cc
+++ b/media/blink/webmediacapabilitiesclient_impl.cc
@@ -4,7 +4,11 @@
 
 #include "media/blink/webmediacapabilitiesclient_impl.h"
 
+#include "media/base/mime_util.h"
+#include "third_party/WebKit/public/platform/modules/media_capabilities/WebAudioConfiguration.h"
 #include "third_party/WebKit/public/platform/modules/media_capabilities/WebMediaCapabilitiesInfo.h"
+#include "third_party/WebKit/public/platform/modules/media_capabilities/WebMediaConfiguration.h"
+#include "third_party/WebKit/public/platform/modules/media_capabilities/WebVideoConfiguration.h"
 
 namespace media {
 
@@ -15,13 +19,53 @@
 void WebMediaCapabilitiesClientImpl::DecodingInfo(
     const blink::WebMediaConfiguration& configuration,
     std::unique_ptr<blink::WebMediaCapabilitiesQueryCallbacks> callbacks) {
-  // TODO(chcunningham, mlamouri): this is a dummy implementation that returns
-  // true for all the fields.
   std::unique_ptr<blink::WebMediaCapabilitiesInfo> info(
       new blink::WebMediaCapabilitiesInfo());
-  info->supported = true;
-  info->smooth = true;
-  info->power_efficient = true;
+
+  SupportsType audio_support = IsSupported;
+  SupportsType video_support = IsSupported;
+
+  if (configuration.audio_configuration) {
+    const blink::WebAudioConfiguration& audio_config =
+        configuration.audio_configuration.value();
+    std::vector<std::string> codec_vector;
+    SplitCodecsToVector(audio_config.codec.Ascii(), &codec_vector, false);
+
+    // TODO(chcunningham): Update to throw exception pending outcome of
+    // https://github.com/WICG/media-capabilities/issues/32
+    DCHECK_LE(codec_vector.size(), 1U);
+
+    audio_support =
+        IsSupportedMediaFormat(audio_config.mime_type.Ascii(), codec_vector);
+  }
+
+  if (configuration.video_configuration) {
+    const blink::WebVideoConfiguration& video_config =
+        configuration.video_configuration.value();
+    std::vector<std::string> codec_vector;
+    SplitCodecsToVector(video_config.codec.Ascii(), &codec_vector, false);
+
+    // TODO(chcunningham): Update to throw exception pending outcome of
+    // https://github.com/WICG/media-capabilities/issues/32
+    DCHECK_LE(codec_vector.size(), 1U);
+
+    video_support =
+        IsSupportedMediaFormat(video_config.mime_type.Ascii(), codec_vector);
+  }
+
+  // TODO(chcunningham): API should never have to mask uncertainty. Log a metric
+  // for any content type that is "maybe" supported.
+  if (video_support == MayBeSupported)
+    video_support = IsSupported;
+  if (audio_support == MayBeSupported)
+    audio_support = IsSupported;
+
+  info->supported =
+      audio_support == IsSupported && video_support == IsSupported;
+
+  // TODO(chcunningham, mlamouri): real implementation for these.
+  info->smooth = info->power_efficient = info->supported;
+
   callbacks->OnSuccess(std::move(info));
 }
 
diff --git a/media/test/data/decode_capabilities_test.html b/media/test/data/decode_capabilities_test.html
new file mode 100644
index 0000000..6b0191a
--- /dev/null
+++ b/media/test/data/decode_capabilities_test.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<title>Decode Capabilities Test</title>
+<div id="console"></div>
+<script type='text/javascript'>
+  function log(message) {
+    let consoleElement = document.getElementById('console');
+    let entry = document.createElement('div');
+    entry.appendChild(document.createTextNode(message));
+    consoleElement.appendChild(entry);
+    console.log(message);
+  }
+
+  function runTest(configuration) {
+    try {
+      navigator.mediaCapabilities.decodingInfo(configuration)
+        .then((result) => {
+          log('Decoding is '
+              + (result.supported ? '' : 'un') + 'supported');
+
+          document.title = result.supported ? 'SUPPORTED' : 'UNSUPPORTED';
+        })
+        .catch((e) => {
+          log('Promise rejected: ' + e);
+          document.title = "ERROR";
+        });
+
+    } catch (e) {
+      log('Exception:' + e);
+      document.title = "ERROR";
+    }
+  }
+
+  function testVideoDecodeContentType(contentType) {
+    // Clear previous test result from title.
+    document.title = '';
+
+    log("Testing video content type: " + contentType);
+
+    const configuration = {
+      // TODO(chcunningham): Add tests for type: "media-source".
+      type : 'file',
+      video : {
+        contentType : contentType,
+
+        // Any reasonable value will do.
+        width : 640,
+        height : 480,
+        bitrate : 10000,
+        framerate : 30
+      }
+    };
+
+    runTest(configuration);
+  }
+
+  function testAudioDecodeContentType(contentType) {
+    // Clear previous test result from title.
+    document.title = '';
+
+    log("Testing audio content type: " + contentType);
+
+    const configuration = {
+      // TODO(chcunningham): Add tests for type: "media-source".
+      type : 'file',
+      audio : {
+        contentType : contentType
+      }
+    };
+
+    runTest(configuration);
+  }
+</script>
diff --git a/services/resource_coordinator/BUILD.gn b/services/resource_coordinator/BUILD.gn
index bfa2df6..ef9bf45 100644
--- a/services/resource_coordinator/BUILD.gn
+++ b/services/resource_coordinator/BUILD.gn
@@ -14,8 +14,7 @@
   public_deps = [
     "//base",
     "//mojo/public/cpp/bindings",
-    "//services/resource_coordinator/public/cpp",
-    "//services/resource_coordinator/public/interfaces",
+    "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
   ]
 }
 
@@ -24,15 +23,14 @@
 
   sources = [
     "memory/coordinator/coordinator_impl_unittest.cc",
-    "public/cpp/memory/memory_dump_manager_delegate_impl_unittest.cc",
+    "public/cpp/memory/process_local_dump_manager_impl_unittest.cc",
   ]
 
   deps = [
     ":lib",
     "//base",
     "//mojo/public/cpp/bindings",
-    "//services/resource_coordinator/public/cpp",
-    "//services/resource_coordinator/public/interfaces",
+    "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
     "//testing/gtest",
   ]
 }
diff --git a/services/resource_coordinator/memory/coordinator/coordinator_impl.cc b/services/resource_coordinator/memory/coordinator/coordinator_impl.cc
index 3f65716f..4b2f920 100644
--- a/services/resource_coordinator/memory/coordinator/coordinator_impl.cc
+++ b/services/resource_coordinator/memory/coordinator/coordinator_impl.cc
@@ -13,7 +13,7 @@
 #include "base/threading/platform_thread.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/memory_dump_request_args.h"
-#include "services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.h"
+#include "services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h"
 #include "services/resource_coordinator/public/interfaces/memory/constants.mojom.h"
 #include "services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom.h"
 
@@ -34,12 +34,10 @@
     : failed_memory_dump_count_(0),
       initialize_memory_dump_manager_(initialize_memory_dump_manager) {
   if (initialize_memory_dump_manager) {
-    MemoryDumpManagerDelegateImpl::Config config(this);
-    auto delegate = base::MakeUnique<MemoryDumpManagerDelegateImpl>(config);
+    ProcessLocalDumpManagerImpl::CreateInstance(
+        ProcessLocalDumpManagerImpl::Config(this));
     base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id(
         mojom::kServiceTracingProcessId);
-    base::trace_event::MemoryDumpManager::GetInstance()->Initialize(
-        std::move(delegate));
   }
   g_coordinator_impl = this;
 }
diff --git a/services/resource_coordinator/public/cpp/BUILD.gn b/services/resource_coordinator/public/cpp/BUILD.gn
index 47c6d7e..50912f2a 100644
--- a/services/resource_coordinator/public/cpp/BUILD.gn
+++ b/services/resource_coordinator/public/cpp/BUILD.gn
@@ -2,13 +2,15 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("cpp") {
+component("resource_coordinator_cpp") {
   sources = [
     "memory/coordinator.h",
-    "memory/memory_dump_manager_delegate_impl.cc",
-    "memory/memory_dump_manager_delegate_impl.h",
+    "memory/process_local_dump_manager_impl.cc",
+    "memory/process_local_dump_manager_impl.h",
   ]
 
+  defines = [ "SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_IMPLEMENTATION" ]
+
   deps = [
     ":struct_traits",
   ]
@@ -16,9 +18,11 @@
   public_deps = [
     "//base",
     "//mojo/public/cpp/bindings",
-    "//services/resource_coordinator/public/interfaces",
+    "//services/resource_coordinator/public/interfaces:interfaces_internal",
     "//services/service_manager/public/cpp",
   ]
+
+  allow_circular_includes_from = [ "//services/resource_coordinator/public/interfaces:interfaces_internal" ]
 }
 
 source_set("struct_traits") {
@@ -27,8 +31,10 @@
     "memory/memory_instrumentation_struct_traits.h",
   ]
 
+  defines = [ "SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_IMPLEMENTATION" ]
+
   public_deps = [
     "//base",
-    "//services/resource_coordinator/public/interfaces",
+    "//services/resource_coordinator/public/interfaces:interfaces_internal",
   ]
 }
diff --git a/services/resource_coordinator/public/cpp/memory/memory_export.h b/services/resource_coordinator/public/cpp/memory/memory_export.h
new file mode 100644
index 0000000..d674a861
--- /dev/null
+++ b/services/resource_coordinator/public/cpp/memory/memory_export.h
@@ -0,0 +1,32 @@
+// 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.
+
+#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_MEMORY_EXPORT_H_
+#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_MEMORY_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_IMPLEMENTATION)
+#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT \
+  __declspec(dllexport)
+#else
+#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT \
+  __declspec(dllimport)
+#endif  // defined(SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_IMPLEMENTATION)
+#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT \
+  __attribute__((visibility("default")))
+#else
+#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT
+#endif
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT
+#endif
+
+#endif  // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_MEMORY_EXPORT_H_
diff --git a/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.h b/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.h
index 817b667..55d916b9 100644
--- a/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.h
+++ b/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.h
@@ -8,13 +8,15 @@
 #include "base/process/process_handle.h"
 #include "base/trace_event/memory_dump_request_args.h"
 #include "mojo/common/common_custom_types_struct_traits.h"
+#include "services/resource_coordinator/public/cpp/memory/memory_export.h"
 #include "services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom.h"
 
 namespace mojo {
 
 template <>
-struct EnumTraits<memory_instrumentation::mojom::DumpType,
-                  base::trace_event::MemoryDumpType> {
+struct SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT
+    EnumTraits<memory_instrumentation::mojom::DumpType,
+               base::trace_event::MemoryDumpType> {
   static memory_instrumentation::mojom::DumpType ToMojom(
       base::trace_event::MemoryDumpType type);
   static bool FromMojom(memory_instrumentation::mojom::DumpType input,
@@ -22,8 +24,9 @@
 };
 
 template <>
-struct EnumTraits<memory_instrumentation::mojom::LevelOfDetail,
-                  base::trace_event::MemoryDumpLevelOfDetail> {
+struct SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT
+    EnumTraits<memory_instrumentation::mojom::LevelOfDetail,
+               base::trace_event::MemoryDumpLevelOfDetail> {
   static memory_instrumentation::mojom::LevelOfDetail ToMojom(
       base::trace_event::MemoryDumpLevelOfDetail level_of_detail);
   static bool FromMojom(memory_instrumentation::mojom::LevelOfDetail input,
@@ -31,8 +34,9 @@
 };
 
 template <>
-struct StructTraits<memory_instrumentation::mojom::RequestArgsDataView,
-                    base::trace_event::MemoryDumpRequestArgs> {
+struct SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT
+    StructTraits<memory_instrumentation::mojom::RequestArgsDataView,
+                 base::trace_event::MemoryDumpRequestArgs> {
   static uint64_t dump_guid(
       const base::trace_event::MemoryDumpRequestArgs& args) {
     return args.dump_guid;
@@ -50,9 +54,9 @@
 };
 
 template <>
-struct StructTraits<
-    memory_instrumentation::mojom::ChromeMemDumpDataView,
-    base::trace_event::MemoryDumpCallbackResult::ChromeMemDump> {
+struct SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT
+    StructTraits<memory_instrumentation::mojom::ChromeMemDumpDataView,
+                 base::trace_event::MemoryDumpCallbackResult::ChromeMemDump> {
   static uint32_t malloc_total_kb(
       const base::trace_event::MemoryDumpCallbackResult::ChromeMemDump& args) {
     return args.malloc_total_kb;
@@ -75,8 +79,9 @@
 };
 
 template <>
-struct StructTraits<memory_instrumentation::mojom::OSMemDumpDataView,
-                    base::trace_event::MemoryDumpCallbackResult::OSMemDump> {
+struct SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT
+    StructTraits<memory_instrumentation::mojom::OSMemDumpDataView,
+                 base::trace_event::MemoryDumpCallbackResult::OSMemDump> {
   static uint32_t resident_set_kb(
       const base::trace_event::MemoryDumpCallbackResult::OSMemDump& args) {
     return args.resident_set_kb;
@@ -86,7 +91,7 @@
 };
 
 template <>
-struct StructTraits<
+struct SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT StructTraits<
     memory_instrumentation::mojom::MemoryDumpCallbackResultDataView,
     base::trace_event::MemoryDumpCallbackResult> {
   static base::trace_event::MemoryDumpCallbackResult::OSMemDump os_dump(
diff --git a/services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.cc b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.cc
similarity index 64%
rename from services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.cc
rename to services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.cc
index 1129bae..358eadd 100644
--- a/services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.cc
+++ b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.h"
+#include "services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h"
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -16,10 +16,19 @@
 
 namespace memory_instrumentation {
 
-MemoryDumpManagerDelegateImpl::Config::~Config() {}
+ProcessLocalDumpManagerImpl::Config::~Config() {}
 
-MemoryDumpManagerDelegateImpl::MemoryDumpManagerDelegateImpl(
-    const MemoryDumpManagerDelegateImpl::Config& config)
+// static
+void ProcessLocalDumpManagerImpl::CreateInstance(const Config& config) {
+  static ProcessLocalDumpManagerImpl* instance = nullptr;
+  if (!instance) {
+    instance = new ProcessLocalDumpManagerImpl(config);
+  } else {
+    NOTREACHED();
+  }
+}
+
+ProcessLocalDumpManagerImpl::ProcessLocalDumpManagerImpl(const Config& config)
     : binding_(this),
       config_(config),
       task_runner_(nullptr),
@@ -34,21 +43,25 @@
   }
   coordinator_->RegisterProcessLocalDumpManager(
       binding_.CreateInterfacePtrAndBind());
+
+  // Only one process should handle periodic dumping.
+  bool is_coordinator_process = !!config.coordinator();
+  base::trace_event::MemoryDumpManager::GetInstance()->Initialize(
+      base::BindRepeating(&ProcessLocalDumpManagerImpl::RequestGlobalMemoryDump,
+                          base::Unretained(this)),
+      is_coordinator_process);
 }
 
-MemoryDumpManagerDelegateImpl::~MemoryDumpManagerDelegateImpl() {}
+ProcessLocalDumpManagerImpl::~ProcessLocalDumpManagerImpl() {}
 
-bool MemoryDumpManagerDelegateImpl::IsCoordinator() const {
-  return task_runner_ != nullptr;
-}
-
-void MemoryDumpManagerDelegateImpl::RequestProcessMemoryDump(
+void ProcessLocalDumpManagerImpl::RequestProcessMemoryDump(
     const base::trace_event::MemoryDumpRequestArgs& args,
     const RequestProcessMemoryDumpCallback& callback) {
-  MemoryDumpManagerDelegate::CreateProcessDump(args, callback);
+  base::trace_event::MemoryDumpManager::GetInstance()->CreateProcessDump(
+      args, callback);
 }
 
-void MemoryDumpManagerDelegateImpl::RequestGlobalMemoryDump(
+void ProcessLocalDumpManagerImpl::RequestGlobalMemoryDump(
     const base::trace_event::MemoryDumpRequestArgs& args,
     const base::trace_event::GlobalMemoryDumpCallback& callback) {
   // Note: This condition is here to match the old behavior. If the delegate is
@@ -58,7 +71,7 @@
   // process, parallel requests will be cancelled.
   //
   // TODO(chiniforooshan): Unify the child and browser behavior.
-  if (IsCoordinator()) {
+  if (task_runner_) {
     task_runner_->PostTask(
         FROM_HERE,
         base::Bind(&mojom::Coordinator::RequestGlobalMemoryDump,
@@ -75,21 +88,24 @@
     pending_memory_dump_guid_ = args.dump_guid;
   }
   auto callback_proxy =
-      base::Bind(&MemoryDumpManagerDelegateImpl::MemoryDumpCallbackProxy,
+      base::Bind(&ProcessLocalDumpManagerImpl::MemoryDumpCallbackProxy,
                  base::Unretained(this), callback);
   coordinator_->RequestGlobalMemoryDump(args, callback_proxy);
 }
 
-void MemoryDumpManagerDelegateImpl::MemoryDumpCallbackProxy(
+void ProcessLocalDumpManagerImpl::MemoryDumpCallbackProxy(
     const base::trace_event::GlobalMemoryDumpCallback& callback,
     uint64_t dump_guid,
     bool success) {
-  DCHECK_NE(0U, pending_memory_dump_guid_);
-  pending_memory_dump_guid_ = 0;
+  {
+    base::AutoLock lock(pending_memory_dump_guid_lock_);
+    DCHECK_NE(0U, pending_memory_dump_guid_);
+    pending_memory_dump_guid_ = 0;
+  }
   callback.Run(dump_guid, success);
 }
 
-void MemoryDumpManagerDelegateImpl::SetAsNonCoordinatorForTesting() {
+void ProcessLocalDumpManagerImpl::SetAsNonCoordinatorForTesting() {
   task_runner_ = nullptr;
 }
 
diff --git a/services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.h b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h
similarity index 68%
rename from services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.h
rename to services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h
index ccff7191..8cd4f4f7b 100644
--- a/services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.h
+++ b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h
@@ -2,15 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_MEMORY_DUMP_MANAGER_DELEGATE_IMPL_H_
-#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_MEMORY_DUMP_MANAGER_DELEGATE_IMPL_H_
+#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_PROCESS_LOCAL_DUMP_MANAGER_IMPL_H_
+#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_PROCESS_LOCAL_DUMP_MANAGER_IMPL_H_
 
+#include "base/compiler_specific.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/memory_dump_request_args.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/resource_coordinator/public/cpp/memory/coordinator.h"
+#include "services/resource_coordinator/public/cpp/memory/memory_export.h"
 #include "services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -22,13 +24,13 @@
 //
 // This cannot just be implemented by the Coordinator service, because there is
 // no Coordinator service in child processes. So, in a child process, the
-// delegate remotely connects to the Coordinator service. In the browser
-// process, the delegate locally connects to the Coordinator service.
-class MemoryDumpManagerDelegateImpl
-    : public base::trace_event::MemoryDumpManagerDelegate,
-      public mojom::ProcessLocalDumpManager {
+// local dump manager remotely connects to the Coordinator service. In the
+// browser process, it locally connects to the Coordinator service.
+class SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT
+    ProcessLocalDumpManagerImpl
+    : public NON_EXPORTED_BASE(mojom::ProcessLocalDumpManager) {
  public:
-  class Config {
+  class SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT Config {
    public:
     Config(service_manager::Connector* connector,
            const std::string& service_name)
@@ -52,22 +54,23 @@
     bool is_test_config_;
   };
 
-  explicit MemoryDumpManagerDelegateImpl(const Config& config);
-  ~MemoryDumpManagerDelegateImpl() override;
+  static void CreateInstance(const Config& config);
 
-  bool IsCoordinator() const override;
-
-  // The base::trace_event::MemoryDumpManager calls this.
+  // Implements base::trace_event::MemoryDumpManager::RequestGlobalDumpCallback.
+  // NOTE: Use MemoryDumpManager::RequestGlobalDump() to request gobal dump.
   void RequestGlobalMemoryDump(
       const base::trace_event::MemoryDumpRequestArgs& args,
-      const base::trace_event::GlobalMemoryDumpCallback& callback) override;
+      const base::trace_event::GlobalMemoryDumpCallback& callback);
 
   Config config() { return config_; }
   void SetAsNonCoordinatorForTesting();
 
  private:
-  friend std::default_delete<MemoryDumpManagerDelegateImpl>;  // For testing
-  friend class MemoryDumpManagerDelegateImplTest;             // For testing
+  friend std::default_delete<ProcessLocalDumpManagerImpl>;  // For testing
+  friend class ProcessLocalDumpManagerImplTest;             // For testing
+
+  ProcessLocalDumpManagerImpl(const Config& config);
+  ~ProcessLocalDumpManagerImpl() override;
 
   // The ProcessLocalDumpManager interface. The coordinator calls this.
   void RequestProcessMemoryDump(
@@ -86,15 +89,11 @@
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   uint64_t pending_memory_dump_guid_;
 
-  // Prevents racy access to |pending_memory_dump_guid_|.
   base::Lock pending_memory_dump_guid_lock_;
 
-  // Prevents racy access to |initialized_|.
-  base::Lock initialized_lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(MemoryDumpManagerDelegateImpl);
+  DISALLOW_COPY_AND_ASSIGN(ProcessLocalDumpManagerImpl);
 };
 
 }  // namespace memory_instrumentation
 
-#endif  // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_MEMORY_DUMP_MANAGER_DELEGATE_IMPL_H_
+#endif  // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_PROCESS_LOCAL_DUMP_MANAGER_IMPL_H_
diff --git a/services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl_unittest.cc b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl_unittest.cc
similarity index 86%
rename from services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl_unittest.cc
rename to services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl_unittest.cc
index a0fcd2d..4ed7258c 100644
--- a/services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl_unittest.cc
+++ b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "services/resource_coordinator/public/cpp/memory/memory_dump_manager_delegate_impl.h"
+#include "services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/message_loop/message_loop.h"
@@ -41,17 +41,16 @@
   mojo::BindingSet<mojom::Coordinator> bindings_;
 };
 
-class MemoryDumpManagerDelegateImplTest : public testing::Test {
+class ProcessLocalDumpManagerImplTest : public testing::Test {
  public:
   void SetUp() override {
     message_loop_.reset(new base::MessageLoop());
     coordinator_.reset(new MockCoordinator());
     mdm_.reset(new MemoryDumpManager());
     MemoryDumpManager::SetInstanceForTesting(mdm_.get());
-    MemoryDumpManagerDelegateImpl::Config config(coordinator_.get());
-    auto delegate = base::MakeUnique<MemoryDumpManagerDelegateImpl>(config);
-    delegate->SetAsNonCoordinatorForTesting();
-    mdm_->Initialize(std::move(delegate));
+    ProcessLocalDumpManagerImpl::Config config(coordinator_.get());
+    local_manager_impl_.reset(new ProcessLocalDumpManagerImpl(config));
+    local_manager_impl_->SetAsNonCoordinatorForTesting();
 
     // Enable tracing.
     std::string category_filter = "-*,";
@@ -70,6 +69,7 @@
     base::trace_event::TraceLog::GetInstance()->SetDisabled();
     MemoryDumpManager::SetInstanceForTesting(nullptr);
     mdm_.reset();
+    local_manager_impl_.reset();
     coordinator_.reset();
     message_loop_.reset();
   }
@@ -92,7 +92,7 @@
   void SequentiallyRequestGlobalDumps(int num_requests) {
     MemoryDumpManager::GetInstance()->RequestGlobalDump(
         MemoryDumpType::EXPLICITLY_TRIGGERED, MemoryDumpLevelOfDetail::LIGHT,
-        base::Bind(&MemoryDumpManagerDelegateImplTest::OnGlobalMemoryDumpDone,
+        base::Bind(&ProcessLocalDumpManagerImplTest::OnGlobalMemoryDumpDone,
                    base::Unretained(this), num_requests - 1));
   }
 
@@ -104,12 +104,13 @@
   std::unique_ptr<base::MessageLoop> message_loop_;
   std::unique_ptr<MockCoordinator> coordinator_;
   std::unique_ptr<MemoryDumpManager> mdm_;
+  std::unique_ptr<ProcessLocalDumpManagerImpl> local_manager_impl_;
 };
 
 // Makes several global dump requests each after receiving the ACK for the
 // previous one. There should be no throttling and all requests should be
 // forwarded to the coordinator.
-TEST_F(MemoryDumpManagerDelegateImplTest, NonOverlappingMemoryDumpRequests) {
+TEST_F(ProcessLocalDumpManagerImplTest, NonOverlappingMemoryDumpRequests) {
   base::RunLoop run_loop;
   expected_callback_calls_ = 3;
   quit_closure_ = run_loop.QuitClosure();
@@ -121,7 +122,7 @@
 // Makes several global dump requests without waiting for previous requests to
 // finish. Only the first request should make it to the coordinator. The rest
 // should be cancelled.
-TEST_F(MemoryDumpManagerDelegateImplTest, OverlappingMemoryDumpRequests) {
+TEST_F(ProcessLocalDumpManagerImplTest, OverlappingMemoryDumpRequests) {
   base::RunLoop run_loop;
   expected_callback_calls_ = 3;
   quit_closure_ = run_loop.QuitClosure();
diff --git a/services/resource_coordinator/public/interfaces/BUILD.gn b/services/resource_coordinator/public/interfaces/BUILD.gn
index 2fcf102..8560b05 100644
--- a/services/resource_coordinator/public/interfaces/BUILD.gn
+++ b/services/resource_coordinator/public/interfaces/BUILD.gn
@@ -4,7 +4,9 @@
 
 import("//mojo/public/tools/bindings/mojom.gni")
 
-mojom("interfaces") {
+mojom("interfaces_internal") {
+  visibility = [ "//services/resource_coordinator/public/cpp:*" ]
+
   sources = [
     "memory/constants.mojom",
     "memory/memory_instrumentation.mojom",
@@ -14,4 +16,11 @@
   public_deps = [
     "//mojo/common:common_custom_types",
   ]
+
+  export_class_attribute =
+      "SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_EXPORT"
+  export_define =
+      "SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_IMPLEMENTATION=1"
+  export_header =
+      "services/resource_coordinator/public/cpp/memory/memory_export.h"
 }
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 37bd5389..ca49940 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1955,9 +1955,6 @@
 # By about a quarter or less of a pixel.
 crbug.com/421412 [ Mac ] fast/text/international/bdo-bidi-width.html [ Failure ]
 
-crbug.com/417782 virtual/rootlayerscrolls/fast/scrolling/scrollable-area-frame-scrolling-no-overried-inherited-visibility-hidden.html [ Failure ]
-crbug.com/417782 virtual/rootlayerscrolls/fast/scrolling/scrollable-area-frame-scrolling-no-visibility-hidden-child.html [ Failure ]
-crbug.com/417782 virtual/rootlayerscrolls/fast/scrolling/scrollable-area-frame-scrolling-no.html [ Failure ]
 crbug.com/417782 virtual/rootlayerscrolls/fast/scrolling/scrollable-area-frame-zero-size-and-border.html [ Failure ]
 crbug.com/417782 virtual/rootlayerscrolls/fast/scrolling/scrollbar-tickmarks-styled.html [ Failure ]
 crbug.com/417782 virtual/rootlayerscrolls/fast/scrolling/scrollbar-tickmarks-styled-after-onload.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/compositing/squashing/squash-transformed-with-clip-expected.html b/third_party/WebKit/LayoutTests/compositing/squashing/squash-transformed-with-clip-expected.html
new file mode 100644
index 0000000..b4613af
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/squashing/squash-transformed-with-clip-expected.html
@@ -0,0 +1,18 @@
+<style>
+#overlap {
+  width: 10px;
+  height: 100px;
+  background: green;
+}
+#transformed {
+  position: absolute;
+  left: 0;
+  top: 50px;
+  will-change: opacity;
+}
+</style>
+<div id="overlap"></div>
+<div id="transformed">
+  This test succeeds if this text is visible.
+</div>
+This test verifies squashed transformed elements have their ancestor clip and local clip applied in the correct spaces.
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/compositing/squashing/squash-transformed-with-clip.html b/third_party/WebKit/LayoutTests/compositing/squashing/squash-transformed-with-clip.html
new file mode 100644
index 0000000..7af100e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/squashing/squash-transformed-with-clip.html
@@ -0,0 +1,20 @@
+<style>
+#overlap {
+  width: 10px;
+  height: 100px;
+  background: green;
+  will-change: transform;
+}
+#transformed {
+  position: absolute;
+  left: 0;
+  top: 0;
+  overflow: hidden;
+  transform: translate(0, 50px);
+}
+</style>
+<div id="overlap"></div>
+<div id="transformed">
+  This test succeeds if this text is visible.
+</div>
+This test verifies squashed transformed elements have their ancestor clip and local clip applied in the correct spaces.
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/dom/name-validity-usecounter.html b/third_party/WebKit/LayoutTests/fast/dom/name-validity-usecounter.html
new file mode 100644
index 0000000..f529927
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/name-validity-usecounter.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<body>
+<script>
+'use strict';
+
+const kElementNameDOMInvalidHTMLParserValid = 1968;
+const kElementNameDOMValidHTMLParserInvalid = 1969;
+
+test(() => {
+  assert_false(internals.isUseCounted(document, kElementNameDOMInvalidHTMLParserValid),
+               'element name: DOM invalid, HTML valid');
+  assert_false(internals.isUseCounted(document, kElementNameDOMValidHTMLParserInvalid),
+               'element name: DOM valid, HTML invalid');
+  assert_throws('InvalidCharacterError', () => document.createElement('foo"'));
+  assert_true(internals.isUseCounted(document, kElementNameDOMInvalidHTMLParserValid),
+               'element name: DOM invalid, HTML valid');
+  assert_false(internals.isUseCounted(document, kElementNameDOMValidHTMLParserInvalid),
+               'element name: DOM valid, HTML invalid');
+
+  document.createElement(':foo');
+  assert_true(internals.isUseCounted(document, kElementNameDOMValidHTMLParserInvalid),
+              'element name: DOM valid, HTML invalid');
+}, 'name validity failures tickle use counters');
+</script>
+</html>
diff --git a/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.cpp b/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.cpp
index ae58a62b..d34c24b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.cpp
@@ -343,7 +343,7 @@
                                  "CustomElement");
   V0CustomElementProcessingStack::CallbackDeliveryScope delivery_scope;
   Element* element = document->createElementNS(
-      namespace_uri, tag_name,
+      nullptr, namespace_uri, tag_name,
       StringOrDictionary::fromString(maybe_type->IsNull() ? g_null_atom : type),
       exception_state);
   if (element) {
diff --git a/third_party/WebKit/Source/bindings/modules/v8/generated.gni b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
index ca9f4c06..bcc774b4 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/generated.gni
+++ b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
@@ -68,8 +68,6 @@
   "$bindings_modules_v8_output_dir/StringOrStringSequence.h",
   "$bindings_modules_v8_output_dir/StringOrStringSequenceOrConstrainDOMStringParameters.cpp",
   "$bindings_modules_v8_output_dir/StringOrStringSequenceOrConstrainDOMStringParameters.h",
-  "$bindings_modules_v8_output_dir/StringOrStringSequenceOrDOMStringList.cpp",
-  "$bindings_modules_v8_output_dir/StringOrStringSequenceOrDOMStringList.h",
   "$bindings_modules_v8_output_dir/StringOrUnsignedLong.cpp",
   "$bindings_modules_v8_output_dir/StringOrUnsignedLong.h",
   "$bindings_modules_v8_output_dir/UnsignedLongOrUnsignedLongSequence.cpp",
diff --git a/third_party/WebKit/Source/core/dom/BUILD.gn b/third_party/WebKit/Source/core/dom/BUILD.gn
index b159e1d9..5c0bacfb 100644
--- a/third_party/WebKit/Source/core/dom/BUILD.gn
+++ b/third_party/WebKit/Source/core/dom/BUILD.gn
@@ -130,6 +130,8 @@
     "DocumentType.cpp",
     "DocumentType.h",
     "DocumentUserGestureToken.h",
+    "DocumentWriteIntervention.cpp",
+    "DocumentWriteIntervention.h",
     "Element.cpp",
     "Element.h",
     "ElementData.cpp",
diff --git a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
index 17de68f7..e1c747e4 100644
--- a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
+++ b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
@@ -41,6 +41,7 @@
 
 NOINLINE void ClassicPendingScript::CheckState() const {
   // TODO(hiroshige): Turn these CHECK()s into DCHECK() before going to beta.
+  CHECK(!prefinalizer_called_);
   CHECK(GetElement());
   CHECK(GetResource() || !streamer_);
   CHECK(!streamer_ || streamer_->GetResource() == GetResource());
@@ -48,6 +49,7 @@
 
 NOINLINE void ClassicPendingScript::Dispose() {
   PendingScript::Dispose();
+  prefinalizer_called_ = true;
 }
 
 void ClassicPendingScript::DisposeInternal() {
diff --git a/third_party/WebKit/Source/core/dom/ClassicPendingScript.h b/third_party/WebKit/Source/core/dom/ClassicPendingScript.h
index 00b2e441..0405f5b9 100644
--- a/third_party/WebKit/Source/core/dom/ClassicPendingScript.h
+++ b/third_party/WebKit/Source/core/dom/ClassicPendingScript.h
@@ -86,6 +86,12 @@
   bool integrity_failure_;
 
   Member<ScriptStreamer> streamer_;
+
+  // This is a temporary flag to confirm that ClassicPendingScript is not
+  // touched after its refinalizer call and thus https://crbug.com/715309
+  // doesn't break assumptions.
+  // TODO(hiroshige): Check the state in more general way.
+  bool prefinalizer_called_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/DOMImplementation.cpp b/third_party/WebKit/Source/core/dom/DOMImplementation.cpp
index 8aab9bb..54d9e626 100644
--- a/third_party/WebKit/Source/core/dom/DOMImplementation.cpp
+++ b/third_party/WebKit/Source/core/dom/DOMImplementation.cpp
@@ -77,6 +77,7 @@
 }
 
 XMLDocument* DOMImplementation::createDocument(
+    const LocalDOMWindow* window,
     const AtomicString& namespace_uri,
     const AtomicString& qualified_name,
     DocumentType* doctype,
@@ -98,8 +99,8 @@
 
   Node* document_element = nullptr;
   if (!qualified_name.IsEmpty()) {
-    document_element =
-        doc->createElementNS(namespace_uri, qualified_name, exception_state);
+    document_element = doc->createElementNS(window, namespace_uri,
+                                            qualified_name, exception_state);
     if (exception_state.HadException())
       return nullptr;
   }
diff --git a/third_party/WebKit/Source/core/dom/DOMImplementation.h b/third_party/WebKit/Source/core/dom/DOMImplementation.h
index 0fde0fda8..d8534d6 100644
--- a/third_party/WebKit/Source/core/dom/DOMImplementation.h
+++ b/third_party/WebKit/Source/core/dom/DOMImplementation.h
@@ -34,6 +34,7 @@
 class DocumentType;
 class ExceptionState;
 class HTMLDocument;
+class LocalDOMWindow;
 class XMLDocument;
 
 class CORE_EXPORT DOMImplementation final
@@ -54,7 +55,8 @@
                                    const String& public_id,
                                    const String& system_id,
                                    ExceptionState&);
-  XMLDocument* createDocument(const AtomicString& namespace_uri,
+  XMLDocument* createDocument(const LocalDOMWindow*,
+                              const AtomicString& namespace_uri,
                               const AtomicString& qualified_name,
                               DocumentType*,
                               ExceptionState&);
diff --git a/third_party/WebKit/Source/core/dom/DOMImplementation.idl b/third_party/WebKit/Source/core/dom/DOMImplementation.idl
index cd19db5..a7c41a1 100644
--- a/third_party/WebKit/Source/core/dom/DOMImplementation.idl
+++ b/third_party/WebKit/Source/core/dom/DOMImplementation.idl
@@ -24,7 +24,8 @@
     DependentLifetime,
 ] interface DOMImplementation {
     [NewObject, RaisesException] DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
-    [NewObject, RaisesException] XMLDocument createDocument(DOMString? namespaceURI, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
+    // TODO(dominicc): Remove CallWith= when crbug/648179 is fixed.
+    [CallWith=EnteredWindow, NewObject, RaisesException] XMLDocument createDocument(DOMString? namespaceURI, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
     // FIXME: createHTMLDocument should return a Document. crbug.com/238368
     // FIXME: The title argument should not have a default value. crbug.com/335871
     [NewObject] HTMLDocument createHTMLDocument(optional DOMString title = null);
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 69ad410..2d68bef 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -375,6 +375,54 @@
   return true;
 }
 
+// Tests whether |name| is something the HTML parser would accept as a
+// tag name.
+template <typename CharType>
+static inline bool IsValidElementNamePerHTMLParser(const CharType* characters,
+                                                   unsigned length) {
+  CharType c = characters[0] | 0x20;
+  if (!('a' <= c && c < 'z'))
+    return false;
+
+  for (unsigned i = 1; i < length; ++i) {
+    c = characters[i];
+    if (c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == ' ' ||
+        c == '/' || c == '>')
+      return false;
+  }
+
+  return true;
+}
+
+static bool IsValidElementNamePerHTMLParser(const String& name) {
+  unsigned length = name.length();
+  if (!length)
+    return false;
+
+  if (name.Is8Bit()) {
+    const LChar* characters = name.Characters8();
+    return IsValidElementNamePerHTMLParser(characters, length);
+  }
+  const UChar* characters = name.Characters16();
+  return IsValidElementNamePerHTMLParser(characters, length);
+}
+
+// Tests whether |name| is a valid name per DOM spec. Also checks
+// whether the HTML parser would accept this element name and counts
+// cases of mismatches.
+static bool IsValidElementName(const LocalDOMWindow* window,
+                               const String& name) {
+  bool is_valid_dom_name = Document::IsValidName(name);
+  bool is_valid_html_name = IsValidElementNamePerHTMLParser(name);
+  if (UNLIKELY(is_valid_html_name != is_valid_dom_name && window)) {
+    UseCounter::Count(window->GetFrame(),
+                      is_valid_dom_name
+                          ? UseCounter::kElementNameDOMValidHTMLParserInvalid
+                          : UseCounter::kElementNameDOMInvalidHTMLParserValid);
+  }
+  return is_valid_dom_name;
+}
+
 static bool AcceptsEditingFocus(const Element& element) {
   DCHECK(HasEditableStyle(element));
 
@@ -694,9 +742,10 @@
 }
 
 // https://dom.spec.whatwg.org/#dom-document-createelement
-Element* Document::createElement(const AtomicString& name,
+Element* Document::createElement(const LocalDOMWindow* window,
+                                 const AtomicString& name,
                                  ExceptionState& exception_state) {
-  if (!IsValidName(name)) {
+  if (!IsValidElementName(window, name)) {
     exception_state.ThrowDOMException(
         kInvalidCharacterError,
         "The tag name provided ('" + name + "') is not a valid name.");
@@ -746,11 +795,12 @@
 }
 
 // https://dom.spec.whatwg.org/#dom-document-createelement
-Element* Document::createElement(const AtomicString& local_name,
+Element* Document::createElement(const LocalDOMWindow* window,
+                                 const AtomicString& local_name,
                                  const StringOrDictionary& string_or_options,
                                  ExceptionState& exception_state) {
   // 1. If localName does not match Name production, throw InvalidCharacterError
-  if (!IsValidName(local_name)) {
+  if (!IsValidElementName(window, local_name)) {
     exception_state.ThrowDOMException(
         kInvalidCharacterError,
         "The tag name provided ('" + local_name + "') is not a valid name.");
@@ -806,7 +856,7 @@
         *this,
         QualifiedName(g_null_atom, converted_local_name, xhtmlNamespaceURI));
   } else {
-    element = createElement(local_name, exception_state);
+    element = createElement(window, local_name, exception_state);
     if (exception_state.HadException())
       return nullptr;
   }
@@ -846,7 +896,8 @@
   return q_name;
 }
 
-Element* Document::createElementNS(const AtomicString& namespace_uri,
+Element* Document::createElementNS(const LocalDOMWindow* window,
+                                   const AtomicString& namespace_uri,
                                    const AtomicString& qualified_name,
                                    ExceptionState& exception_state) {
   QualifiedName q_name(
@@ -860,7 +911,8 @@
 }
 
 // https://dom.spec.whatwg.org/#internal-createelementns-steps
-Element* Document::createElementNS(const AtomicString& namespace_uri,
+Element* Document::createElementNS(const LocalDOMWindow* window,
+                                   const AtomicString& namespace_uri,
                                    const AtomicString& qualified_name,
                                    const StringOrDictionary& string_or_options,
                                    ExceptionState& exception_state) {
@@ -882,7 +934,7 @@
       AtomicString(GetTypeExtension(this, string_or_options, exception_state));
   const AtomicString& name = should_create_builtin ? is : qualified_name;
 
-  if (!IsValidName(qualified_name)) {
+  if (!IsValidElementName(window, qualified_name)) {
     exception_state.ThrowDOMException(
         kInvalidCharacterError, "The tag name provided ('" + qualified_name +
                                     "') is not a valid name.");
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index c650a95..b5cdaf5 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -317,8 +317,9 @@
 
   Location* location() const;
 
-  Element* createElement(const AtomicString& name,
-                         ExceptionState& = ASSERT_NO_EXCEPTION);
+  Element* createElement(const LocalDOMWindow*,
+                         const AtomicString& name,
+                         ExceptionState&);
   DocumentFragment* createDocumentFragment();
   Text* createTextNode(const String& data);
   Comment* createComment(const String& data);
@@ -332,7 +333,8 @@
                           ExceptionState&,
                           bool should_ignore_namespace_checks = false);
   Node* importNode(Node* imported_node, bool deep, ExceptionState&);
-  Element* createElementNS(const AtomicString& namespace_uri,
+  Element* createElementNS(const LocalDOMWindow*,
+                           const AtomicString& namespace_uri,
                            const AtomicString& qualified_name,
                            ExceptionState&);
   Element* createElement(const QualifiedName&, CreateElementFlags);
@@ -1139,10 +1141,17 @@
 
   TextAutosizer* GetTextAutosizer();
 
-  Element* createElement(const AtomicString& local_name,
+  Element* createElement(
+      const AtomicString& local_name,
+      ExceptionState& exception_state = ASSERT_NO_EXCEPTION) {
+    return createElement(nullptr, local_name, exception_state);
+  }
+  Element* createElement(const LocalDOMWindow*,
+                         const AtomicString& local_name,
                          const StringOrDictionary&,
                          ExceptionState& = ASSERT_NO_EXCEPTION);
-  Element* createElementNS(const AtomicString& namespace_uri,
+  Element* createElementNS(const LocalDOMWindow*,
+                           const AtomicString& namespace_uri,
                            const AtomicString& qualified_name,
                            const StringOrDictionary&,
                            ExceptionState&);
diff --git a/third_party/WebKit/Source/core/dom/Document.idl b/third_party/WebKit/Source/core/dom/Document.idl
index 136ae2c..bc6a55fa 100644
--- a/third_party/WebKit/Source/core/dom/Document.idl
+++ b/third_party/WebKit/Source/core/dom/Document.idl
@@ -55,8 +55,10 @@
     HTMLCollection getElementsByTagNameNS(DOMString? namespaceURI, DOMString localName);
     HTMLCollection getElementsByClassName(DOMString classNames);
 
-    [NewObject, DoNotTestNewObject, CustomElementCallbacks, PerWorldBindings, RaisesException] Element createElement(DOMString localName);
-    [NewObject, DoNotTestNewObject, CustomElementCallbacks, RaisesException] Element createElementNS(DOMString? namespaceURI, DOMString qualifiedName);
+    // TODO(dominicc): Remove CallWith= when crbug/648179 is fixed.
+    [CallWith=EnteredWindow, NewObject, DoNotTestNewObject, CustomElementCallbacks, PerWorldBindings, RaisesException] Element createElement(DOMString localName);
+    // TODO(dominicc): Remove CallWith= when crbug/648179 is fixed.
+    [CallWith=EnteredWindow, NewObject, DoNotTestNewObject, CustomElementCallbacks, RaisesException] Element createElementNS(DOMString? namespaceURI, DOMString qualifiedName);
     [NewObject] DocumentFragment createDocumentFragment();
     [NewObject] Text createTextNode(DOMString data);
     [NewObject, RaisesException] CDATASection createCDATASection(DOMString data);
@@ -176,8 +178,10 @@
     [CallWith=ScriptState, CustomElementCallbacks, RaisesException, MeasureAs=DocumentRegisterElement] CustomElementConstructor registerElement(DOMString type, optional ElementRegistrationOptions options);
     // https://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-instantiate
     // FIXME: The typeExtension arguments should not be nullable.
-    [CustomElementCallbacks, PerWorldBindings, RaisesException] Element createElement(DOMString localName, (DOMString or Dictionary)? options);
-    [CustomElementCallbacks, RaisesException] Element createElementNS(DOMString? namespaceURI, DOMString qualifiedName, (DOMString or Dictionary)? options);
+    // TODO(dominicc): Remove CallWith= when crbug/648179 is fixed.
+    [CallWith=EnteredWindow, CustomElementCallbacks, PerWorldBindings, RaisesException] Element createElement(DOMString localName, (DOMString or Dictionary)? options);
+    // TODO(dominicc): Remove CallWith= when crbug/648179 is fixed.
+    [CallWith=EnteredWindow, CustomElementCallbacks, RaisesException] Element createElementNS(DOMString? namespaceURI, DOMString qualifiedName, (DOMString or Dictionary)? options);
 
     // Page Visibility
     // https://w3c.github.io/page-visibility/#extensions-to-the-document-interface
diff --git a/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.cpp b/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.cpp
new file mode 100644
index 0000000..3ddd87f
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.cpp
@@ -0,0 +1,163 @@
+// 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.
+
+#include "core/dom/DocumentWriteIntervention.h"
+
+#include "core/frame/LocalFrame.h"
+#include "core/frame/LocalFrameClient.h"
+#include "core/frame/Settings.h"
+#include "core/inspector/ConsoleMessage.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/probe/CoreProbes.h"
+#include "platform/network/NetworkStateNotifier.h"
+#include "platform/network/NetworkUtils.h"
+#include "public/platform/WebCachePolicy.h"
+#include "public/platform/WebEffectiveConnectionType.h"
+
+namespace blink {
+
+namespace {
+
+void EmitWarningForDocWriteScripts(const String& url, Document& document) {
+  String message =
+      "A Parser-blocking, cross site (i.e. different eTLD+1) script, " + url +
+      ", is invoked via document.write. The network request for this script "
+      "MAY be blocked by the browser in this or a future page load due to poor "
+      "network connectivity. If blocked in this page load, it will be "
+      "confirmed in a subsequent console message."
+      "See https://www.chromestatus.com/feature/5718547946799104 "
+      "for more details.";
+  document.AddConsoleMessage(
+      ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, message));
+  DVLOG(1) << message.Utf8().data();
+}
+
+bool IsConnectionEffectively2G(WebEffectiveConnectionType effective_type) {
+  switch (effective_type) {
+    case WebEffectiveConnectionType::kTypeSlow2G:
+    case WebEffectiveConnectionType::kType2G:
+      return true;
+    case WebEffectiveConnectionType::kType3G:
+    case WebEffectiveConnectionType::kType4G:
+    case WebEffectiveConnectionType::kTypeUnknown:
+    case WebEffectiveConnectionType::kTypeOffline:
+      return false;
+  }
+  NOTREACHED();
+  return false;
+}
+
+bool ShouldDisallowFetch(Settings* settings,
+                         WebConnectionType connection_type,
+                         WebEffectiveConnectionType effective_connection) {
+  if (settings->GetDisallowFetchForDocWrittenScriptsInMainFrame())
+    return true;
+  if (settings
+          ->GetDisallowFetchForDocWrittenScriptsInMainFrameOnSlowConnections() &&
+      connection_type == kWebConnectionTypeCellular2G)
+    return true;
+  if (settings
+          ->GetDisallowFetchForDocWrittenScriptsInMainFrameIfEffectively2G() &&
+      IsConnectionEffectively2G(effective_connection))
+    return true;
+  return false;
+}
+
+}  // namespace
+
+bool MaybeDisallowFetchForDocWrittenScript(ResourceRequest& request,
+                                           FetchParameters::DeferOption defer,
+                                           Document& document) {
+  // Only scripts inserted via document.write are candidates for having their
+  // fetch disallowed.
+  if (!document.IsInDocumentWrite())
+    return false;
+
+  Settings* settings = document.GetSettings();
+  if (!settings)
+    return false;
+
+  if (!document.GetFrame() || !document.GetFrame()->IsMainFrame())
+    return false;
+
+  // Only block synchronously loaded (parser blocking) scripts.
+  if (defer != FetchParameters::kNoDefer)
+    return false;
+
+  probe::documentWriteFetchScript(&document);
+
+  if (!request.Url().ProtocolIsInHTTPFamily())
+    return false;
+
+  // Avoid blocking same origin scripts, as they may be used to render main
+  // page content, whereas cross-origin scripts inserted via document.write
+  // are likely to be third party content.
+  String request_host = request.Url().Host();
+  String document_host = document.GetSecurityOrigin()->Domain();
+
+  bool same_site = false;
+  if (request_host == document_host)
+    same_site = true;
+
+  // If the hosts didn't match, then see if the domains match. For example, if
+  // a script is served from static.example.com for a document served from
+  // www.example.com, we consider that a first party script and allow it.
+  String request_domain = NetworkUtils::GetDomainAndRegistry(
+      request_host, NetworkUtils::kIncludePrivateRegistries);
+  String document_domain = NetworkUtils::GetDomainAndRegistry(
+      document_host, NetworkUtils::kIncludePrivateRegistries);
+  // getDomainAndRegistry will return the empty string for domains that are
+  // already top-level, such as localhost. Thus we only compare domains if we
+  // get non-empty results back from getDomainAndRegistry.
+  if (!request_domain.IsEmpty() && !document_domain.IsEmpty() &&
+      request_domain == document_domain)
+    same_site = true;
+
+  if (same_site) {
+    // This histogram is introduced to help decide whether we should also check
+    // same scheme while deciding whether or not to block the script as is done
+    // in other cases of "same site" usage. On the other hand we do not want to
+    // block more scripts than necessary.
+    if (request.Url().Protocol() != document.GetSecurityOrigin()->Protocol()) {
+      document.Loader()->DidObserveLoadingBehavior(
+          WebLoadingBehaviorFlag::
+              kWebLoadingBehaviorDocumentWriteBlockDifferentScheme);
+    }
+    return false;
+  }
+
+  EmitWarningForDocWriteScripts(request.Url().GetString(), document);
+  request.SetHTTPHeaderField("Intervention",
+                             "<https://www.chromestatus.com/feature/"
+                             "5718547946799104>; level=\"warning\"");
+
+  // Do not block scripts if it is a page reload. This is to enable pages to
+  // recover if blocking of a script is leading to a page break and the user
+  // reloads the page.
+  const FrameLoadType load_type = document.Loader()->LoadType();
+  if (IsReloadLoadType(load_type)) {
+    // Recording this metric since an increase in number of reloads for pages
+    // where a script was blocked could be indicative of a page break.
+    document.Loader()->DidObserveLoadingBehavior(
+        WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlockReload);
+    return false;
+  }
+
+  // Add the metadata that this page has scripts inserted via document.write
+  // that are eligible for blocking. Note that if there are multiple scripts
+  // the flag will be conveyed to the browser process only once.
+  document.Loader()->DidObserveLoadingBehavior(
+      WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlock);
+
+  if (!ShouldDisallowFetch(
+          settings, GetNetworkStateNotifier().ConnectionType(),
+          document.GetFrame()->Client()->GetEffectiveConnectionType())) {
+    return false;
+  }
+
+  request.SetCachePolicy(WebCachePolicy::kReturnCacheDataDontLoad);
+  return true;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.h b/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.h
new file mode 100644
index 0000000..49e7f459
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.h
@@ -0,0 +1,27 @@
+// 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.
+
+#ifndef DocumentWriteIntervention_h
+#define DocumentWriteIntervention_h
+
+#include "platform/loader/fetch/FetchParameters.h"
+
+namespace blink {
+
+class Document;
+class ResourceRequest;
+
+// Returns true if the fetch should be blocked due to the document.write
+// intervention. In that case, the request's cache policy is set to
+// kReturnCacheDataDontLoad to ensure a network request is not generated.
+// This function may also set an Intervention header, log the intervention in
+// the console, etc.
+// This only affects scripts added via document.write() in the main frame.
+bool MaybeDisallowFetchForDocWrittenScript(ResourceRequest&,
+                                           FetchParameters::DeferOption,
+                                           Document&);
+
+}  // namespace blink
+
+#endif  // DocumentWriteIntervention_h
diff --git a/third_party/WebKit/Source/core/dom/ExceptionCode.h b/third_party/WebKit/Source/core/dom/ExceptionCode.h
index 345779c..6e90967 100644
--- a/third_party/WebKit/Source/core/dom/ExceptionCode.h
+++ b/third_party/WebKit/Source/core/dom/ExceptionCode.h
@@ -64,8 +64,11 @@
   kInvalidNodeTypeError,
   kDataCloneError,
 
-  // These are IDB-specific.
+  // The operation failed for an unknown transient reason (e.g. out of memory).
+  // Note: Rethrowed V8 exception will also have this code.
   kUnknownError,
+
+  // These are IDB-specific.
   kConstraintError,
   kDataError,
   kTransactionInactiveError,
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index d5488e2..fb70a86 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -32,6 +32,7 @@
 #include "core/dom/ClassicScript.h"
 #include "core/dom/Document.h"
 #include "core/dom/DocumentParserTiming.h"
+#include "core/dom/DocumentWriteIntervention.h"
 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h"
 #include "core/dom/Script.h"
 #include "core/dom/ScriptElementBase.h"
@@ -613,12 +614,28 @@
   // "Fetch a classic script given url, settings, ..."
   ResourceRequest resource_request(url);
 
+  FetchParameters::DeferOption defer = FetchParameters::kNoDefer;
+  if (!parser_inserted_ || element_->AsyncAttributeValue() ||
+      element_->DeferAttributeValue())
+    defer = FetchParameters::kLazyLoad;
+
   // [Intervention]
   if (document_write_intervention_ ==
       DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
     resource_request.SetHTTPHeaderField(
         "Intervention",
         "<https://www.chromestatus.com/feature/5718547946799104>");
+    defer = FetchParameters::kIdleLoad;
+  }
+
+  // [Intervention]
+  // For users on slow connections, we want to avoid blocking the parser in
+  // the main frame on script loads inserted via document.write, since it can
+  // add significant delays before page content is displayed on the screen.
+  if (MaybeDisallowFetchForDocWrittenScript(resource_request, defer,
+                                            element_->GetDocument())) {
+    document_write_intervention_ =
+        DocumentWriteIntervention::kDoNotFetchDocWrittenScript;
   }
 
   FetchParameters params(resource_request, element_->InitiatorName());
@@ -642,13 +659,6 @@
 
   // This DeferOption logic is only for classic scripts, as we always set
   // |kLazyLoad| for module scripts in ModuleScriptLoader.
-  FetchParameters::DeferOption defer = FetchParameters::kNoDefer;
-  if (!parser_inserted_ || element_->AsyncAttributeValue() ||
-      element_->DeferAttributeValue())
-    defer = FetchParameters::kLazyLoad;
-  if (document_write_intervention_ ==
-      DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle)
-    defer = FetchParameters::kIdleLoad;
   params.SetDefer(defer);
 
   resource_ = ScriptResource::Fetch(params, fetcher);
@@ -656,14 +666,6 @@
   if (!resource_)
     return false;
 
-  // [Intervention]
-  if (created_during_document_write_ &&
-      resource_->GetResourceRequest().GetCachePolicy() ==
-          WebCachePolicy::kReturnCacheDataDontLoad) {
-    document_write_intervention_ =
-        DocumentWriteIntervention::kDoNotFetchDocWrittenScript;
-  }
-
   return true;
 }
 
diff --git a/third_party/WebKit/Source/core/dom/TreeScopeTest.cpp b/third_party/WebKit/Source/core/dom/TreeScopeTest.cpp
index 7bf29e4..9b9c1206 100644
--- a/third_party/WebKit/Source/core/dom/TreeScopeTest.cpp
+++ b/third_party/WebKit/Source/core/dom/TreeScopeTest.cpp
@@ -16,7 +16,8 @@
   Document* document = Document::Create();
   EXPECT_EQ(document, document->CommonAncestorTreeScope(*document));
 
-  Element* html = document->createElement("html", StringOrDictionary());
+  Element* html =
+      document->createElement(nullptr, "html", StringOrDictionary());
   document->AppendChild(html);
   ShadowRoot* shadow_root =
       html->CreateShadowRootInternal(ShadowRootType::V0, ASSERT_NO_EXCEPTION);
@@ -29,7 +30,8 @@
   // shadowRoot
 
   Document* document = Document::Create();
-  Element* html = document->createElement("html", StringOrDictionary());
+  Element* html =
+      document->createElement(nullptr, "html", StringOrDictionary());
   document->AppendChild(html);
   ShadowRoot* shadow_root =
       html->CreateShadowRootInternal(ShadowRootType::V0, ASSERT_NO_EXCEPTION);
@@ -44,11 +46,14 @@
   //  A      B
 
   Document* document = Document::Create();
-  Element* html = document->createElement("html", StringOrDictionary());
+  Element* html =
+      document->createElement(nullptr, "html", StringOrDictionary());
   document->AppendChild(html);
-  Element* head = document->createElement("head", StringOrDictionary());
+  Element* head =
+      document->createElement(nullptr, "head", StringOrDictionary());
   html->AppendChild(head);
-  Element* body = document->createElement("body", StringOrDictionary());
+  Element* body =
+      document->createElement(nullptr, "body", StringOrDictionary());
   html->AppendChild(body);
 
   ShadowRoot* shadow_root_a =
@@ -68,11 +73,14 @@
   // A
 
   Document* document = Document::Create();
-  Element* html = document->createElement("html", StringOrDictionary());
+  Element* html =
+      document->createElement(nullptr, "html", StringOrDictionary());
   document->AppendChild(html);
-  Element* head = document->createElement("head", StringOrDictionary());
+  Element* head =
+      document->createElement(nullptr, "head", StringOrDictionary());
   html->AppendChild(head);
-  Element* body = document->createElement("body", StringOrDictionary());
+  Element* body =
+      document->createElement(nullptr, "body", StringOrDictionary());
   html->AppendChild(body);
 
   ShadowRoot* shadow_root_y =
@@ -80,7 +88,8 @@
   ShadowRoot* shadow_root_b =
       body->CreateShadowRootInternal(ShadowRootType::V0, ASSERT_NO_EXCEPTION);
 
-  Element* div_in_y = document->createElement("div", StringOrDictionary());
+  Element* div_in_y =
+      document->createElement(nullptr, "div", StringOrDictionary());
   shadow_root_y->AppendChild(div_in_y);
   ShadowRoot* shadow_root_a = div_in_y->CreateShadowRootInternal(
       ShadowRootType::V0, ASSERT_NO_EXCEPTION);
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementTest.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElementTest.cpp
index a708592..dc7f3e3 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementTest.cpp
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementTest.cpp
@@ -189,13 +189,13 @@
     EXPECT_EQ(data.state, element->GetCustomElementState()) << data.name;
     EXPECT_EQ(data.v0state, element->GetV0CustomElementState()) << data.name;
 
-    element = document.createElementNS(HTMLNames::xhtmlNamespaceURI, data.name,
-                                       ASSERT_NO_EXCEPTION);
+    element = document.createElementNS(nullptr, HTMLNames::xhtmlNamespaceURI,
+                                       data.name, ASSERT_NO_EXCEPTION);
     EXPECT_EQ(data.state, element->GetCustomElementState()) << data.name;
     EXPECT_EQ(data.v0state, element->GetV0CustomElementState()) << data.name;
 
-    element = document.createElementNS(SVGNames::svgNamespaceURI, data.name,
-                                       ASSERT_NO_EXCEPTION);
+    element = document.createElementNS(nullptr, SVGNames::svgNamespaceURI,
+                                       data.name, ASSERT_NO_EXCEPTION);
     EXPECT_EQ(CustomElementState::kUncustomized,
               element->GetCustomElementState())
         << data.name;
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementTestHelpers.h b/third_party/WebKit/Source/core/dom/custom/CustomElementTestHelpers.h
index f710de0..04ef280 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementTestHelpers.h
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementTestHelpers.h
@@ -123,8 +123,8 @@
     if (!document)
       document = HTMLDocument::Create();
     NonThrowableExceptionState no_exceptions;
-    Element* element =
-        document->createElementNS(namespace_uri_, local_name_, no_exceptions);
+    Element* element = document->createElementNS(nullptr, namespace_uri_,
+                                                 local_name_, no_exceptions);
     for (const auto& attribute : attributes_)
       element->setAttribute(attribute.first, attribute.second);
     return element;
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementUpgradeSorterTest.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElementUpgradeSorterTest.cpp
index 4118020..d79cf30 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementUpgradeSorterTest.cpp
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementUpgradeSorterTest.cpp
@@ -30,7 +30,7 @@
   Element* CreateElementWithId(const char* local_name, const char* id) {
     NonThrowableExceptionState no_exceptions;
     Element* element = GetDocument()->createElement(
-        local_name, StringOrDictionary(), no_exceptions);
+        nullptr, local_name, StringOrDictionary(), no_exceptions);
     element->setAttribute(HTMLNames::idAttr, id);
     return element;
   }
@@ -55,8 +55,8 @@
 
 TEST_F(CustomElementUpgradeSorterTest, inOtherDocument_notInSet) {
   NonThrowableExceptionState no_exceptions;
-  Element* element =
-      GetDocument()->createElement("a-a", StringOrDictionary(), no_exceptions);
+  Element* element = GetDocument()->createElement(
+      nullptr, "a-a", StringOrDictionary(), no_exceptions);
 
   Document* other_document = HTMLDocument::Create();
   other_document->AppendChild(element);
@@ -74,8 +74,8 @@
 
 TEST_F(CustomElementUpgradeSorterTest, oneCandidate) {
   NonThrowableExceptionState no_exceptions;
-  Element* element =
-      GetDocument()->createElement("a-a", StringOrDictionary(), no_exceptions);
+  Element* element = GetDocument()->createElement(
+      nullptr, "a-a", StringOrDictionary(), no_exceptions);
   GetDocument()->documentElement()->AppendChild(element);
 
   CustomElementUpgradeSorter sorter;
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index 6f3db2e..51eabe3b 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -4110,8 +4110,6 @@
   if (!ScrollbarsSuppressed())
     pending_scroll_delta_ += scroll_delta;
 
-  if (ScrollTypeClearsFragmentAnchor(scroll_type))
-    ClearFragmentAnchor();
   UpdateLayersAndCompositingAfterScrollIfNeeded();
 
   Document* document = frame_->GetDocument();
@@ -4145,8 +4143,10 @@
       document_loader->GetInitialScrollState().was_scrolled_by_user = true;
   }
 
-  if (scroll_type != kAnchoringScroll && scroll_type != kClampingScroll)
+  if (IsExplicitScrollType(scroll_type)) {
+    ClearFragmentAnchor();
     ClearScrollAnchor();
+  }
 }
 
 void FrameView::DidChangeScrollOffset() {
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 635004d..7ed3ec6e 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1578,6 +1578,8 @@
     kGamepadButtons = 1965,
     kVibrateWithoutUserGesture = 1966,
     kDispatchMouseEventOnDisabledFormControl = 1967,
+    kElementNameDOMInvalidHTMLParserValid = 1968,
+    kElementNameDOMValidHTMLParserInvalid = 1969,
 
     // Add new features immediately above this line. Don't change assigned
     // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp b/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp
index 71c4353..939bbc1 100644
--- a/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp
+++ b/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp
@@ -5,6 +5,7 @@
 #include "core/html/parser/PreloadRequest.h"
 
 #include "core/dom/Document.h"
+#include "core/dom/DocumentWriteIntervention.h"
 #include "core/loader/DocumentLoader.h"
 #include "platform/CrossOriginAttributeValue.h"
 #include "platform/loader/fetch/FetchInitiatorInfo.h"
@@ -47,6 +48,9 @@
   resource_request.SetRequestContext(
       ResourceFetcher::DetermineRequestContext(resource_type_, false));
 
+  if (resource_type_ == Resource::kScript)
+    MaybeDisallowFetchForDocWrittenScript(resource_request, defer_, *document);
+
   FetchParameters params(resource_request, initiator_info);
 
   if (resource_type_ == Resource::kImportResource) {
diff --git a/third_party/WebKit/Source/core/loader/BUILD.gn b/third_party/WebKit/Source/core/loader/BUILD.gn
index c5ec0ea2..01821207 100644
--- a/third_party/WebKit/Source/core/loader/BUILD.gn
+++ b/third_party/WebKit/Source/core/loader/BUILD.gn
@@ -65,6 +65,8 @@
     "ThreadableLoaderClient.h",
     "ThreadableLoadingContext.cpp",
     "ThreadableLoadingContext.h",
+    "WorkerFetchContext.cpp",
+    "WorkerFetchContext.h",
     "WorkerThreadableLoader.cpp",
     "WorkerThreadableLoader.h",
     "WorkletScriptLoader.cpp",
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index d0011ef..2fb04743 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -76,11 +76,10 @@
 #include "platform/loader/fetch/ResourceTimingInfo.h"
 #include "platform/loader/fetch/UniqueIdentifier.h"
 #include "platform/mhtml/MHTMLArchive.h"
-#include "platform/network/NetworkStateNotifier.h"
-#include "platform/network/NetworkUtils.h"
 #include "platform/scheduler/renderer/web_view_scheduler.h"
 #include "platform/weborigin/SchemeRegistry.h"
 #include "platform/wtf/Vector.h"
+#include "public/platform/Platform.h"
 #include "public/platform/WebCachePolicy.h"
 #include "public/platform/WebInsecureRequestPolicy.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h"
@@ -89,133 +88,6 @@
 
 namespace {
 
-void EmitWarningForDocWriteScripts(const String& url, Document& document) {
-  String message =
-      "A Parser-blocking, cross site (i.e. different eTLD+1) script, " + url +
-      ", is invoked via document.write. The network request for this script "
-      "MAY be blocked by the browser in this or a future page load due to poor "
-      "network connectivity. If blocked in this page load, it will be "
-      "confirmed in a subsequent console message."
-      "See https://www.chromestatus.com/feature/5718547946799104 "
-      "for more details.";
-  document.AddConsoleMessage(
-      ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, message));
-  WTFLogAlways("%s", message.Utf8().data());
-}
-
-bool IsConnectionEffectively2G(WebEffectiveConnectionType effective_type) {
-  switch (effective_type) {
-    case WebEffectiveConnectionType::kTypeSlow2G:
-    case WebEffectiveConnectionType::kType2G:
-      return true;
-    case WebEffectiveConnectionType::kType3G:
-    case WebEffectiveConnectionType::kType4G:
-    case WebEffectiveConnectionType::kTypeUnknown:
-    case WebEffectiveConnectionType::kTypeOffline:
-      return false;
-  }
-  NOTREACHED();
-  return false;
-}
-
-bool ShouldDisallowFetchForMainFrameScript(ResourceRequest& request,
-                                           FetchParameters::DeferOption defer,
-                                           Document& document) {
-  // Only scripts inserted via document.write are candidates for having their
-  // fetch disallowed.
-  if (!document.IsInDocumentWrite())
-    return false;
-
-  if (!document.GetSettings())
-    return false;
-
-  if (!document.GetFrame())
-    return false;
-
-  // Only block synchronously loaded (parser blocking) scripts.
-  if (defer != FetchParameters::kNoDefer)
-    return false;
-
-  probe::documentWriteFetchScript(&document);
-
-  if (!request.Url().ProtocolIsInHTTPFamily())
-    return false;
-
-  // Avoid blocking same origin scripts, as they may be used to render main
-  // page content, whereas cross-origin scripts inserted via document.write
-  // are likely to be third party content.
-  String request_host = request.Url().Host();
-  String document_host = document.GetSecurityOrigin()->Domain();
-
-  bool same_site = false;
-  if (request_host == document_host)
-    same_site = true;
-
-  // If the hosts didn't match, then see if the domains match. For example, if
-  // a script is served from static.example.com for a document served from
-  // www.example.com, we consider that a first party script and allow it.
-  String request_domain = NetworkUtils::GetDomainAndRegistry(
-      request_host, NetworkUtils::kIncludePrivateRegistries);
-  String document_domain = NetworkUtils::GetDomainAndRegistry(
-      document_host, NetworkUtils::kIncludePrivateRegistries);
-  // getDomainAndRegistry will return the empty string for domains that are
-  // already top-level, such as localhost. Thus we only compare domains if we
-  // get non-empty results back from getDomainAndRegistry.
-  if (!request_domain.IsEmpty() && !document_domain.IsEmpty() &&
-      request_domain == document_domain)
-    same_site = true;
-
-  if (same_site) {
-    // This histogram is introduced to help decide whether we should also check
-    // same scheme while deciding whether or not to block the script as is done
-    // in other cases of "same site" usage. On the other hand we do not want to
-    // block more scripts than necessary.
-    if (request.Url().Protocol() != document.GetSecurityOrigin()->Protocol()) {
-      document.Loader()->DidObserveLoadingBehavior(
-          WebLoadingBehaviorFlag::
-              kWebLoadingBehaviorDocumentWriteBlockDifferentScheme);
-    }
-    return false;
-  }
-
-  EmitWarningForDocWriteScripts(request.Url().GetString(), document);
-  request.SetHTTPHeaderField("Intervention",
-                             "<https://www.chromestatus.com/feature/"
-                             "5718547946799104>; level=\"warning\"");
-
-  // Do not block scripts if it is a page reload. This is to enable pages to
-  // recover if blocking of a script is leading to a page break and the user
-  // reloads the page.
-  const FrameLoadType load_type = document.Loader()->LoadType();
-  if (IsReloadLoadType(load_type)) {
-    // Recording this metric since an increase in number of reloads for pages
-    // where a script was blocked could be indicative of a page break.
-    document.Loader()->DidObserveLoadingBehavior(
-        WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlockReload);
-    return false;
-  }
-
-  // Add the metadata that this page has scripts inserted via document.write
-  // that are eligible for blocking. Note that if there are multiple scripts
-  // the flag will be conveyed to the browser process only once.
-  document.Loader()->DidObserveLoadingBehavior(
-      WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlock);
-
-  const bool is2g = GetNetworkStateNotifier().ConnectionType() ==
-                    kWebConnectionTypeCellular2G;
-  WebEffectiveConnectionType effective_connection =
-      document.GetFrame()->Client()->GetEffectiveConnectionType();
-
-  return document.GetSettings()
-             ->GetDisallowFetchForDocWrittenScriptsInMainFrame() ||
-         (document.GetSettings()
-              ->GetDisallowFetchForDocWrittenScriptsInMainFrameOnSlowConnections() &&
-          is2g) ||
-         (document.GetSettings()
-              ->GetDisallowFetchForDocWrittenScriptsInMainFrameIfEffectively2G() &&
-          IsConnectionEffectively2G(effective_connection));
-}
-
 enum class RequestMethod { kIsPost, kIsNotPost };
 enum class RequestType { kIsConditional, kIsNotConditional };
 enum class ResourceType { kIsMainResource, kIsNotMainResource };
@@ -356,7 +228,7 @@
 }
 
 WebCachePolicy FrameFetchContext::ResourceRequestCachePolicy(
-    ResourceRequest& request,
+    const ResourceRequest& request,
     Resource::Type type,
     FetchParameters::DeferOption defer) const {
   DCHECK(GetFrame());
@@ -379,15 +251,6 @@
                                         ResourceType::kIsMainResource);
   }
 
-  // For users on slow connections, we want to avoid blocking the parser in
-  // the main frame on script loads inserted via document.write, since it can
-  // add significant delays before page content is displayed on the screen.
-  // TODO(toyoshim): Move following logic that rewrites ResourceRequest to
-  // somewhere that should be relevant to the script resource handling.
-  if (type == Resource::kScript && IsMainFrame() && GetDocument() &&
-      ShouldDisallowFetchForMainFrameScript(request, defer, *GetDocument()))
-    return WebCachePolicy::kReturnCacheDataDontLoad;
-
   const WebCachePolicy cache_policy = DetermineFrameWebCachePolicy(
       GetFrame(), ResourceType::kIsNotMainResource);
 
@@ -903,6 +766,10 @@
                                                url, reporting_policy);
 }
 
+std::unique_ptr<WebURLLoader> FrameFetchContext::CreateURLLoader() {
+  return Platform::Current()->CreateURLLoader();
+}
+
 DEFINE_TRACE(FrameFetchContext) {
   visitor->Trace(document_loader_);
   BaseFetchContext::Trace(visitor);
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
index 9f81a50..805a36a 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -71,7 +71,7 @@
   void AddAdditionalRequestHeaders(ResourceRequest&,
                                    FetchResourceType) override;
   WebCachePolicy ResourceRequestCachePolicy(
-      ResourceRequest&,
+      const ResourceRequest&,
       Resource::Type,
       FetchParameters::DeferOption) const override;
   void DispatchDidChangeResourcePriority(unsigned long identifier,
@@ -152,6 +152,8 @@
 
   RefPtr<WebTaskRunner> LoadingTaskRunner() const override;
 
+  std::unique_ptr<WebURLLoader> CreateURLLoader() override;
+
   DECLARE_VIRTUAL_TRACE();
 
  private:
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
new file mode 100644
index 0000000..a1ca5f3
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -0,0 +1,103 @@
+// 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.
+
+#include "core/loader/WorkerFetchContext.h"
+
+#include "core/workers/WorkerClients.h"
+#include "core/workers/WorkerGlobalScope.h"
+#include "platform/Supplementable.h"
+#include "platform/WebTaskRunner.h"
+#include "platform/exported/WrappedResourceRequest.h"
+#include "platform/scheduler/child/web_scheduler.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebThread.h"
+#include "public/platform/WebWorkerFetchContext.h"
+
+namespace blink {
+
+namespace {
+
+// WorkerFetchContextHolder is used to pass the WebWorkerFetchContext from the
+// main thread to the worker thread by attaching to the WorkerClients as a
+// Supplement.
+class WorkerFetchContextHolder final
+    : public GarbageCollectedFinalized<WorkerFetchContextHolder>,
+      public Supplement<WorkerClients> {
+  USING_GARBAGE_COLLECTED_MIXIN(WorkerFetchContextHolder);
+
+ public:
+  static WorkerFetchContextHolder* From(WorkerClients& clients) {
+    return static_cast<WorkerFetchContextHolder*>(
+        Supplement<WorkerClients>::From(clients, SupplementName()));
+  }
+  static const char* SupplementName() { return "WorkerFetchContextHolder"; }
+
+  explicit WorkerFetchContextHolder(
+      std::unique_ptr<WebWorkerFetchContext> web_context)
+      : web_context_(std::move(web_context)) {}
+  virtual ~WorkerFetchContextHolder() {}
+
+  std::unique_ptr<WebWorkerFetchContext> TakeContext() {
+    return std::move(web_context_);
+  }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() { Supplement<WorkerClients>::Trace(visitor); }
+
+ private:
+  std::unique_ptr<WebWorkerFetchContext> web_context_;
+};
+
+}  // namespace
+
+WorkerFetchContext::~WorkerFetchContext() {}
+
+WorkerFetchContext* WorkerFetchContext::Create(
+    WorkerGlobalScope& worker_global_scope) {
+  DCHECK(worker_global_scope.IsContextThread());
+  WorkerClients* worker_clients = worker_global_scope.Clients();
+  DCHECK(worker_clients);
+  WorkerFetchContextHolder* holder =
+      static_cast<WorkerFetchContextHolder*>(Supplement<WorkerClients>::From(
+          *worker_clients, WorkerFetchContextHolder::SupplementName()));
+  if (!holder)
+    return nullptr;
+  std::unique_ptr<WebWorkerFetchContext> web_context = holder->TakeContext();
+  DCHECK(web_context);
+  return new WorkerFetchContext(std::move(web_context));
+}
+
+WorkerFetchContext::WorkerFetchContext(
+    std::unique_ptr<WebWorkerFetchContext> web_context)
+    : web_context_(std::move(web_context)) {
+  web_context_->InitializeOnWorkerThread(Platform::Current()
+                                             ->CurrentThread()
+                                             ->Scheduler()
+                                             ->LoadingTaskRunner()
+                                             ->ToSingleThreadTaskRunner());
+}
+
+std::unique_ptr<WebURLLoader> WorkerFetchContext::CreateURLLoader() {
+  return web_context_->CreateURLLoader();
+}
+
+bool WorkerFetchContext::IsControlledByServiceWorker() const {
+  return web_context_->IsControlledByServiceWorker();
+}
+
+void WorkerFetchContext::PrepareRequest(ResourceRequest& request,
+                                        RedirectType) {
+  WrappedResourceRequest webreq(request);
+  web_context_->WillSendRequest(webreq);
+}
+
+void ProvideWorkerFetchContextToWorker(
+    WorkerClients* clients,
+    std::unique_ptr<WebWorkerFetchContext> web_context) {
+  DCHECK(clients);
+  WorkerFetchContextHolder::ProvideTo(
+      *clients, WorkerFetchContextHolder::SupplementName(),
+      new WorkerFetchContextHolder(std::move(web_context)));
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
new file mode 100644
index 0000000..4a98706
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
@@ -0,0 +1,47 @@
+// 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.
+
+#ifndef WorkerFetchContext_h
+#define WorkerFetchContext_h
+
+#include <memory>
+#include "core/CoreExport.h"
+#include "platform/loader/fetch/FetchContext.h"
+#include "platform/wtf/Forward.h"
+
+namespace blink {
+
+class WorkerClients;
+class WebURLLoader;
+class WebWorkerFetchContext;
+class WorkerGlobalScope;
+
+CORE_EXPORT void ProvideWorkerFetchContextToWorker(
+    WorkerClients*,
+    std::unique_ptr<WebWorkerFetchContext>);
+
+// The WorkerFetchContext is a FetchContext for workers (dedicated, shared and
+// service workers). This class is used only when off-main-thread-fetch is
+// enabled, and is still under development.
+// TODO(horo): Implement all methods of FetchContext. crbug.com/443374
+class WorkerFetchContext final : public FetchContext {
+ public:
+  static WorkerFetchContext* Create(WorkerGlobalScope&);
+  virtual ~WorkerFetchContext();
+
+  // FetchContext implementation:
+  // TODO(horo): Implement more methods.
+  std::unique_ptr<WebURLLoader> CreateURLLoader() override;
+  void PrepareRequest(ResourceRequest&, RedirectType) override;
+  bool IsControlledByServiceWorker() const override;
+
+ private:
+  explicit WorkerFetchContext(std::unique_ptr<WebWorkerFetchContext>);
+
+  std::unique_ptr<WebWorkerFetchContext> web_context_;
+};
+
+}  // namespace blink
+
+#endif  // WorkerFetchContext_h
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
index 018270e..1f9148f 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -224,21 +224,25 @@
   // LayoutTests/compositing/content-changed-chicken-egg.html
   DisableCompositingQueryAsserts disabler;
 
-  if (change_type == kCanvasChanged)
-    Compositor()->SetNeedsCompositingUpdate(
-        kCompositingUpdateAfterCompositingInputChange);
+  if (Compositor()) {
+    if (change_type == kCanvasChanged) {
+      Compositor()->SetNeedsCompositingUpdate(
+          kCompositingUpdateAfterCompositingInputChange);
+    }
 
-  if (change_type == kCanvasContextChanged) {
-    Compositor()->SetNeedsCompositingUpdate(
-        kCompositingUpdateAfterCompositingInputChange);
+    if (change_type == kCanvasContextChanged) {
+      Compositor()->SetNeedsCompositingUpdate(
+          kCompositingUpdateAfterCompositingInputChange);
 
-    // Although we're missing test coverage, we need to call
-    // GraphicsLayer::setContentsToPlatformLayer with the new platform
-    // layer for this canvas.
-    // See http://crbug.com/349195
-    if (HasCompositedLayerMapping())
-      GetCompositedLayerMapping()->SetNeedsGraphicsLayerUpdate(
-          kGraphicsLayerUpdateSubtree);
+      // Although we're missing test coverage, we need to call
+      // GraphicsLayer::setContentsToPlatformLayer with the new platform
+      // layer for this canvas.
+      // See http://crbug.com/349195
+      if (HasCompositedLayerMapping()) {
+        GetCompositedLayerMapping()->SetNeedsGraphicsLayerUpdate(
+            kGraphicsLayerUpdateSubtree);
+      }
+    }
   }
 
   if (CompositedLayerMapping* composited_layer_mapping =
@@ -385,7 +389,9 @@
         *transform, box->Size(), ComputedStyle::kIncludeTransformOrigin,
         ComputedStyle::kIncludeMotionPath,
         ComputedStyle::kIncludeIndependentTransformProperties);
-    MakeMatrixRenderable(*transform, Compositor()->HasAcceleratedCompositing());
+    MakeMatrixRenderable(
+        *transform,
+        Compositor() ? Compositor()->HasAcceleratedCompositing() : false);
   }
 }
 
@@ -1031,8 +1037,10 @@
        current = current->Parent())
     current->child_needs_compositing_inputs_update_ = true;
 
-  Compositor()->SetNeedsCompositingUpdate(
-      kCompositingUpdateAfterCompositingInputChange);
+  if (Compositor()) {
+    Compositor()->SetNeedsCompositingUpdate(
+        kCompositingUpdateAfterCompositingInputChange);
+  }
 }
 
 void PaintLayer::UpdateAncestorDependentCompositingInputs(
@@ -1259,9 +1267,11 @@
 
   SetNeedsCompositingInputsUpdate();
 
-  if (!child->StackingNode()->IsStacked() &&
-      !GetLayoutObject().DocumentBeingDestroyed())
-    Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
+  if (Compositor()) {
+    if (!child->StackingNode()->IsStacked() &&
+        !GetLayoutObject().DocumentBeingDestroyed())
+      Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
+  }
 
   if (child->StackingNode()->IsStacked() || child->FirstChild()) {
     // Dirty the z-order list in which we are contained. The
@@ -1293,9 +1303,11 @@
   if (last_ == old_child)
     last_ = old_child->PreviousSibling();
 
-  if (!old_child->StackingNode()->IsStacked() &&
-      !GetLayoutObject().DocumentBeingDestroyed())
-    Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
+  if (Compositor()) {
+    if (!old_child->StackingNode()->IsStacked() &&
+        !GetLayoutObject().DocumentBeingDestroyed())
+      Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
+  }
 
   if (old_child->StackingNode()->IsStacked() || old_child->FirstChild()) {
     // Dirty the z-order list in which we are contained.  When called via the
@@ -2960,7 +2972,8 @@
     const ComputedStyle* old_style) {
   CompositingReasons old_potential_compositing_reasons_from_style =
       PotentialCompositingReasonsFromStyle();
-  Compositor()->UpdatePotentialCompositingReasonsFromStyle(this);
+  if (Compositor())
+    Compositor()->UpdatePotentialCompositingReasonsFromStyle(this);
 
   // This function implements an optimization for transforms and opacity.
   // A common pattern is for a touchmove handler to update the transform
@@ -3014,8 +3027,10 @@
   // not possibly have changed.
   rare_data_->composited_layer_mapping->SetNeedsGraphicsLayerUpdate(
       kGraphicsLayerUpdateLocal);
-  Compositor()->SetNeedsCompositingUpdate(
-      kCompositingUpdateAfterGeometryChange);
+  if (Compositor()) {
+    Compositor()->SetNeedsCompositingUpdate(
+        kCompositingUpdateAfterGeometryChange);
+  }
 
   if (scrollable_area_)
     scrollable_area_->UpdateAfterStyleChange(old_style);
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
index 2d0b917..7817508e 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -764,7 +764,17 @@
 
   ClipRect ancestor_background_clip_rect;
   if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
-    if (parent_layer) {
+    if (painting_info.root_layer == &paint_layer_) {
+      // This works around a bug in squashed-layer painting.
+      // Squashed layers paint into a backing in its compositing container's
+      // space, but painting_info.root_layer points to the squashed layer
+      // itself, thus PaintLayerClipper would return a clip rect in the
+      // squashed layer's local space, instead of the backing's space.
+      // Fortunately, CompositedLayerMapping::DoPaintTask already applied
+      // appropriate ancestor clip for us, we can simply skip it.
+      DCHECK_EQ(paint_layer_.GetCompositingState(), kPaintsIntoGroupedBacking);
+      ancestor_background_clip_rect.SetRect(FloatClipRect());
+    } else if (parent_layer) {
       // Calculate the clip rectangle that the ancestors establish.
       ClipRectsContext clip_rects_context(
           painting_info.root_layer,
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index 39eac7dd..deb91d4 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -471,13 +471,11 @@
     frame_view->DidChangeScrollOffset();
   }
 
-  if (ScrollTypeClearsFragmentAnchor(scroll_type))
+  if (IsExplicitScrollType(scroll_type)) {
     frame_view->ClearFragmentAnchor();
-
-  // Clear the scroll anchor, unless it is the reason for this scroll.
-  if (RuntimeEnabledFeatures::scrollAnchoringEnabled() &&
-      scroll_type != kAnchoringScroll && scroll_type != kClampingScroll)
-    GetScrollAnchor()->Clear();
+    if (RuntimeEnabledFeatures::scrollAnchoringEnabled())
+      GetScrollAnchor()->Clear();
+  }
 }
 
 IntSize PaintLayerScrollableArea::ScrollOffsetInt() const {
@@ -632,6 +630,21 @@
   if (Box().IsIntrinsicallyScrollable(orientation))
     return true;
 
+  if (Box().IsLayoutView()) {
+    if (LocalFrame* frame = Box().GetFrame()) {
+      if (FrameView* frame_view = frame->View()) {
+        ScrollbarMode h_mode;
+        ScrollbarMode v_mode;
+        frame_view->CalculateScrollbarModes(h_mode, v_mode);
+        if (orientation == kHorizontalScrollbar &&
+            h_mode == kScrollbarAlwaysOff)
+          return false;
+        if (orientation == kVerticalScrollbar && v_mode == kScrollbarAlwaysOff)
+          return false;
+      }
+    }
+  }
+
   EOverflow overflow_style = (orientation == kHorizontalScrollbar)
                                  ? Box().Style()->OverflowX()
                                  : Box().Style()->OverflowY();
@@ -1242,8 +1255,12 @@
         frame_view->CalculateScrollbarModes(h_mode, v_mode);
         if (h_mode == kScrollbarAlwaysOn)
           needs_horizontal_scrollbar = true;
+        else if (h_mode == kScrollbarAlwaysOff)
+          needs_horizontal_scrollbar = false;
         if (v_mode == kScrollbarAlwaysOn)
           needs_vertical_scrollbar = true;
+        else if (v_mode == kScrollbarAlwaysOff)
+          needs_vertical_scrollbar = false;
       }
     }
   }
@@ -1718,6 +1735,13 @@
 
   bool is_visible_to_hit_test = Box().Style()->VisibleToHitTesting();
   bool did_scroll_overflow = scrolls_overflow_;
+  if (Box().IsLayoutView()) {
+    ScrollbarMode h_mode;
+    ScrollbarMode v_mode;
+    frame_view->CalculateScrollbarModes(h_mode, v_mode);
+    if (h_mode == kScrollbarAlwaysOff && v_mode == kScrollbarAlwaysOff)
+      has_overflow = false;
+  }
   scrolls_overflow_ = has_overflow && is_visible_to_hit_test;
   if (did_scroll_overflow == ScrollsOverflow())
     return;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
index 106cd21..2693110 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
@@ -515,7 +515,7 @@
   EXPECT_TRUE(paint_layer->NeedsCompositedScrolling());
 
   // Add clip to scroller.
-  scroller->setAttribute("class", "clip", ASSERT_NO_EXCEPTION);
+  scroller->setAttribute(HTMLNames::classAttr, "clip");
   GetDocument().View()->UpdateAllLifecyclePhases();
   paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
   ASSERT_TRUE(paint_layer);
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index 109f612..6864f7d5 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -114,10 +114,10 @@
 
 ALWAYS_INLINE ComputedStyle::ComputedStyle()
     : ComputedStyleBase(), RefCounted<ComputedStyle>() {
-  box_.Init();
-  visual_.Init();
-  background_.Init();
-  surround_.Init();
+  box_data_.Init();
+  visual_data_.Init();
+  background_data_.Init();
+  surround_data_.Init();
   rare_non_inherited_data_.Init();
   rare_non_inherited_data_.Access()->deprecated_flexible_box_.Init();
   rare_non_inherited_data_.Access()->flexible_box_.Init();
@@ -137,10 +137,10 @@
 ALWAYS_INLINE ComputedStyle::ComputedStyle(const ComputedStyle& o)
     : ComputedStyleBase(o),
       RefCounted<ComputedStyle>(),
-      box_(o.box_),
-      visual_(o.visual_),
-      background_(o.background_),
-      surround_(o.surround_),
+      box_data_(o.box_data_),
+      visual_data_(o.visual_data_),
+      background_data_(o.background_data_),
+      surround_data_(o.surround_data_),
       rare_non_inherited_data_(o.rare_non_inherited_data_),
       rare_inherited_data_(o.rare_inherited_data_),
       style_inherited_data_(o.style_inherited_data_),
@@ -333,10 +333,10 @@
 
 void ComputedStyle::CopyNonInheritedFromCached(const ComputedStyle& other) {
   ComputedStyleBase::CopyNonInheritedFromCached(other);
-  box_ = other.box_;
-  visual_ = other.visual_;
-  background_ = other.background_;
-  surround_ = other.surround_;
+  box_data_ = other.box_data_;
+  visual_data_ = other.visual_data_;
+  background_data_ = other.background_data_;
+  surround_data_ = other.surround_data_;
   rare_non_inherited_data_ = other.rare_non_inherited_data_;
 
   // The flags are copied one-by-one because they contain
@@ -482,9 +482,10 @@
              other.OriginalDisplay() &&  // Not generated in ComputedStyleBase
          VerticalAlign() == other.VerticalAlign() &&  // Not generated in
                                                       // ComputedStyleBase
-         box_ == other.box_ &&
-         visual_ == other.visual_ && background_ == other.background_ &&
-         surround_ == other.surround_ &&
+         box_data_ == other.box_data_ &&
+         visual_data_ == other.visual_data_ &&
+         background_data_ == other.background_data_ &&
+         surround_data_ == other.surround_data_ &&
          rare_non_inherited_data_ == other.rare_non_inherited_data_ &&
          svg_style_->NonInheritedEqual(*other.svg_style_);
 }
@@ -578,17 +579,17 @@
   if (GetPosition() != other.GetPosition())
     return true;
 
-  if (box_.Get() != other.box_.Get()) {
-    if (box_->Width() != other.box_->Width() ||
-        box_->MinWidth() != other.box_->MinWidth() ||
-        box_->MaxWidth() != other.box_->MaxWidth() ||
-        box_->Height() != other.box_->Height() ||
-        box_->MinHeight() != other.box_->MinHeight() ||
-        box_->MaxHeight() != other.box_->MaxHeight())
+  if (box_data_.Get() != other.box_data_.Get()) {
+    if (box_data_->Width() != other.box_data_->Width() ||
+        box_data_->MinWidth() != other.box_data_->MinWidth() ||
+        box_data_->MaxWidth() != other.box_data_->MaxWidth() ||
+        box_data_->Height() != other.box_data_->Height() ||
+        box_data_->MinHeight() != other.box_data_->MinHeight() ||
+        box_data_->MaxHeight() != other.box_data_->MaxHeight())
       return true;
   }
 
-  if (surround_.Get() != other.surround_.Get()) {
+  if (surround_data_.Get() != other.surround_data_.Get()) {
     if (!MarginEqual(other) || !OffsetEqual(other) || !PaddingEqual(other))
       return true;
   }
@@ -608,7 +609,7 @@
   // - or the layoutObject knows how to exactly invalidate paints caused by the
   //   layout change instead of forced full paint invalidation.
 
-  if (surround_.Get() != other.surround_.Get()) {
+  if (surround_data_.Get() != other.surround_data_.Get()) {
     // If our border widths change, then we need to layout. Other changes to
     // borders only necessitate a paint invalidation.
     if (BorderLeftWidth() != other.BorderLeftWidth() ||
@@ -839,19 +840,19 @@
 }
 
 bool ComputedStyle::DiffNeedsFullLayout(const ComputedStyle& other) const {
-  if (box_.Get() != other.box_.Get()) {
-    if (box_->Width() != other.box_->Width() ||
-        box_->MinWidth() != other.box_->MinWidth() ||
-        box_->MaxWidth() != other.box_->MaxWidth() ||
-        box_->Height() != other.box_->Height() ||
-        box_->MinHeight() != other.box_->MinHeight() ||
-        box_->MaxHeight() != other.box_->MaxHeight())
+  if (box_data_.Get() != other.box_data_.Get()) {
+    if (box_data_->Width() != other.box_data_->Width() ||
+        box_data_->MinWidth() != other.box_data_->MinWidth() ||
+        box_data_->MaxWidth() != other.box_data_->MaxWidth() ||
+        box_data_->Height() != other.box_data_->Height() ||
+        box_data_->MinHeight() != other.box_data_->MinHeight() ||
+        box_data_->MaxHeight() != other.box_data_->MaxHeight())
       return true;
 
-    if (box_->VerticalAlign() != other.box_->VerticalAlign())
+    if (box_data_->VerticalAlign() != other.box_data_->VerticalAlign())
       return true;
 
-    if (box_->BoxSizing() != other.box_->BoxSizing())
+    if (box_data_->BoxSizing() != other.box_data_->BoxSizing())
       return true;
   }
 
@@ -905,7 +906,7 @@
       PrintColorAdjust() != other.PrintColorAdjust() ||
       InsideLink() != other.InsideLink() ||
       !Border().VisuallyEqual(other.Border()) ||
-      *background_ != *other.background_)
+      *background_data_ != *other.background_data_)
     return true;
 
   if (rare_inherited_data_.Get() != other.rare_inherited_data_.Get()) {
@@ -1011,7 +1012,7 @@
 void ComputedStyle::UpdatePropertySpecificDifferences(
     const ComputedStyle& other,
     StyleDifference& diff) const {
-  if (box_->ZIndex() != other.box_->ZIndex() ||
+  if (box_data_->ZIndex() != other.box_data_->ZIndex() ||
       IsStackingContext() != other.IsStackingContext())
     diff.SetZIndexChanged();
 
@@ -1060,7 +1061,7 @@
         style_inherited_data_->visited_link_color !=
             other.style_inherited_data_->visited_link_color ||
         HasSimpleUnderlineInternal() != other.HasSimpleUnderlineInternal() ||
-        visual_->text_decoration != other.visual_->text_decoration) {
+        visual_data_->text_decoration != other.visual_data_->text_decoration) {
       diff.SetTextDecorationOrColorChanged();
     } else if (rare_non_inherited_data_.Get() !=
                    other.rare_non_inherited_data_.Get() &&
@@ -1102,11 +1103,11 @@
     }
   }
 
-  bool has_clip = HasOutOfFlowPosition() && !visual_->has_auto_clip;
+  bool has_clip = HasOutOfFlowPosition() && !visual_data_->has_auto_clip;
   bool other_has_clip =
-      other.HasOutOfFlowPosition() && !other.visual_->has_auto_clip;
+      other.HasOutOfFlowPosition() && !other.visual_data_->has_auto_clip;
   if (has_clip != other_has_clip ||
-      (has_clip && visual_->clip != other.visual_->clip))
+      (has_clip && visual_data_->clip != other.visual_data_->clip))
     diff.SetCSSClipChanged();
 }
 
@@ -2392,31 +2393,31 @@
 void ComputedStyle::SetBorderImageSource(StyleImage* image) {
   if (Border().image_.GetImage() == image)
     return;
-  surround_.Access()->border_.image_.SetImage(image);
+  surround_data_.Access()->border_.image_.SetImage(image);
 }
 
 void ComputedStyle::SetBorderImageSlices(const LengthBox& slices) {
   if (Border().image_.ImageSlices() == slices)
     return;
-  surround_.Access()->border_.image_.SetImageSlices(slices);
+  surround_data_.Access()->border_.image_.SetImageSlices(slices);
 }
 
 void ComputedStyle::SetBorderImageSlicesFill(bool fill) {
   if (Border().image_.Fill() == fill)
     return;
-  surround_.Access()->border_.image_.SetFill(fill);
+  surround_data_.Access()->border_.image_.SetFill(fill);
 }
 
 void ComputedStyle::SetBorderImageWidth(const BorderImageLengthBox& slices) {
   if (Border().image_.BorderSlices() == slices)
     return;
-  surround_.Access()->border_.image_.SetBorderSlices(slices);
+  surround_data_.Access()->border_.image_.SetBorderSlices(slices);
 }
 
 void ComputedStyle::SetBorderImageOutset(const BorderImageLengthBox& outset) {
   if (Border().image_.Outset() == outset)
     return;
-  surround_.Access()->border_.image_.SetOutset(outset);
+  surround_data_.Access()->border_.image_.SetOutset(outset);
 }
 
 bool ComputedStyle::BorderObscuresBackground() const {
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index fd24d447c..ab15aeba 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -185,10 +185,10 @@
 
  protected:
   // non-inherited attributes
-  DataRef<StyleBoxData> box_;
-  DataRef<StyleVisualData> visual_;
-  DataRef<StyleBackgroundData> background_;
-  DataRef<StyleSurroundData> surround_;
+  DataRef<StyleBoxData> box_data_;
+  DataRef<StyleVisualData> visual_data_;
+  DataRef<StyleBackgroundData> background_data_;
+  DataRef<StyleSurroundData> surround_data_;
   DataRef<StyleRareNonInheritedData> rare_non_inherited_data_;
 
   // inherited attributes
@@ -419,55 +419,55 @@
   // background-color
   static Color InitialBackgroundColor() { return Color::kTransparent; }
   void SetBackgroundColor(const StyleColor& v) {
-    SET_VAR(background_, color_, v);
+    SET_VAR(background_data_, color_, v);
   }
 
   // background-image
   bool HasBackgroundImage() const {
-    return background_->Background().HasImage();
+    return background_data_->Background().HasImage();
   }
   bool HasFixedBackgroundImage() const {
-    return background_->Background().HasFixedImage();
+    return background_data_->Background().HasFixedImage();
   }
   bool HasEntirelyFixedBackground() const;
 
   // background-clip
   EFillBox BackgroundClip() const {
-    return static_cast<EFillBox>(background_->Background().Clip());
+    return static_cast<EFillBox>(background_data_->Background().Clip());
   }
 
   // Border properties.
   // -webkit-border-image
   static NinePieceImage InitialNinePieceImage() { return NinePieceImage(); }
   const NinePieceImage& BorderImage() const {
-    return surround_->border_.GetImage();
+    return surround_data_->border_.GetImage();
   }
   void SetBorderImage(const NinePieceImage& b) {
-    SET_VAR(surround_, border_.image_, b);
+    SET_VAR(surround_data_, border_.image_, b);
   }
 
   // border-image-slice
   const LengthBox& BorderImageSlices() const {
-    return surround_->border_.GetImage().ImageSlices();
+    return surround_data_->border_.GetImage().ImageSlices();
   }
   void SetBorderImageSlices(const LengthBox&);
 
   // border-image-source
   static StyleImage* InitialBorderImageSource() { return 0; }
   StyleImage* BorderImageSource() const {
-    return surround_->border_.GetImage().GetImage();
+    return surround_data_->border_.GetImage().GetImage();
   }
   void SetBorderImageSource(StyleImage*);
 
   // border-image-width
   const BorderImageLengthBox& BorderImageWidth() const {
-    return surround_->border_.GetImage().BorderSlices();
+    return surround_data_->border_.GetImage().BorderSlices();
   }
   void SetBorderImageWidth(const BorderImageLengthBox&);
 
   // border-image-outset
   const BorderImageLengthBox& BorderImageOutset() const {
-    return surround_->border_.GetImage().Outset();
+    return surround_data_->border_.GetImage().Outset();
   }
   void SetBorderImageOutset(const BorderImageLengthBox&);
 
@@ -475,31 +475,35 @@
   static float InitialBorderWidth() { return 3; }
 
   // border-top-width
-  float BorderTopWidth() const { return surround_->border_.BorderTopWidth(); }
+  float BorderTopWidth() const {
+    return surround_data_->border_.BorderTopWidth();
+  }
   void SetBorderTopWidth(float v) {
-    SET_BORDER_WIDTH(surround_, border_.top_, v);
+    SET_BORDER_WIDTH(surround_data_, border_.top_, v);
   }
 
   // border-bottom-width
   float BorderBottomWidth() const {
-    return surround_->border_.BorderBottomWidth();
+    return surround_data_->border_.BorderBottomWidth();
   }
   void SetBorderBottomWidth(float v) {
-    SET_BORDER_WIDTH(surround_, border_.bottom_, v);
+    SET_BORDER_WIDTH(surround_data_, border_.bottom_, v);
   }
 
   // border-left-width
-  float BorderLeftWidth() const { return surround_->border_.BorderLeftWidth(); }
+  float BorderLeftWidth() const {
+    return surround_data_->border_.BorderLeftWidth();
+  }
   void SetBorderLeftWidth(float v) {
-    SET_BORDER_WIDTH(surround_, border_.left_, v);
+    SET_BORDER_WIDTH(surround_data_, border_.left_, v);
   }
 
   // border-right-width
   float BorderRightWidth() const {
-    return surround_->border_.BorderRightWidth();
+    return surround_data_->border_.BorderRightWidth();
   }
   void SetBorderRightWidth(float v) {
-    SET_BORDER_WIDTH(surround_, border_.right_, v);
+    SET_BORDER_WIDTH(surround_data_, border_.right_, v);
   }
 
   // Border style properties.
@@ -507,55 +511,55 @@
 
   // border-top-style
   EBorderStyle BorderTopStyle() const {
-    return surround_->border_.Top().Style();
+    return surround_data_->border_.Top().Style();
   }
   void SetBorderTopStyle(EBorderStyle v) {
-    SET_VAR(surround_, border_.top_.style_, v);
+    SET_VAR(surround_data_, border_.top_.style_, v);
   }
 
   // border-right-style
   EBorderStyle BorderRightStyle() const {
-    return surround_->border_.Right().Style();
+    return surround_data_->border_.Right().Style();
   }
   void SetBorderRightStyle(EBorderStyle v) {
-    SET_VAR(surround_, border_.right_.style_, v);
+    SET_VAR(surround_data_, border_.right_.style_, v);
   }
 
   // border-left-style
   EBorderStyle BorderLeftStyle() const {
-    return surround_->border_.Left().Style();
+    return surround_data_->border_.Left().Style();
   }
   void SetBorderLeftStyle(EBorderStyle v) {
-    SET_VAR(surround_, border_.left_.style_, v);
+    SET_VAR(surround_data_, border_.left_.style_, v);
   }
 
   // border-bottom-style
   EBorderStyle BorderBottomStyle() const {
-    return surround_->border_.Bottom().Style();
+    return surround_data_->border_.Bottom().Style();
   }
   void SetBorderBottomStyle(EBorderStyle v) {
-    SET_VAR(surround_, border_.bottom_.style_, v);
+    SET_VAR(surround_data_, border_.bottom_.style_, v);
   }
 
   // Border color properties.
   // border-left-color
   void SetBorderLeftColor(const StyleColor& v) {
-    SET_BORDERVALUE_COLOR(surround_, border_.left_, v);
+    SET_BORDERVALUE_COLOR(surround_data_, border_.left_, v);
   }
 
   // border-right-color
   void SetBorderRightColor(const StyleColor& v) {
-    SET_BORDERVALUE_COLOR(surround_, border_.right_, v);
+    SET_BORDERVALUE_COLOR(surround_data_, border_.right_, v);
   }
 
   // border-top-color
   void SetBorderTopColor(const StyleColor& v) {
-    SET_BORDERVALUE_COLOR(surround_, border_.top_, v);
+    SET_BORDERVALUE_COLOR(surround_data_, border_.top_, v);
   }
 
   // border-bottom-color
   void SetBorderBottomColor(const StyleColor& v) {
-    SET_BORDERVALUE_COLOR(surround_, border_.bottom_, v);
+    SET_BORDERVALUE_COLOR(surround_data_, border_.bottom_, v);
   }
 
   // Border radius properties.
@@ -565,56 +569,56 @@
 
   // border-top-left-radius (aka -webkit-border-top-left-radius)
   const LengthSize& BorderTopLeftRadius() const {
-    return surround_->border_.TopLeft();
+    return surround_data_->border_.TopLeft();
   }
   void SetBorderTopLeftRadius(const LengthSize& s) {
-    SET_VAR(surround_, border_.top_left_, s);
+    SET_VAR(surround_data_, border_.top_left_, s);
   }
 
   // border-top-right-radius (aka -webkit-border-top-right-radius)
   const LengthSize& BorderTopRightRadius() const {
-    return surround_->border_.TopRight();
+    return surround_data_->border_.TopRight();
   }
   void SetBorderTopRightRadius(const LengthSize& s) {
-    SET_VAR(surround_, border_.top_right_, s);
+    SET_VAR(surround_data_, border_.top_right_, s);
   }
 
   // border-bottom-left-radius (aka -webkit-border-bottom-left-radius)
   const LengthSize& BorderBottomLeftRadius() const {
-    return surround_->border_.BottomLeft();
+    return surround_data_->border_.BottomLeft();
   }
   void SetBorderBottomLeftRadius(const LengthSize& s) {
-    SET_VAR(surround_, border_.bottom_left_, s);
+    SET_VAR(surround_data_, border_.bottom_left_, s);
   }
 
   // border-bottom-right-radius (aka -webkit-border-bottom-right-radius)
   const LengthSize& BorderBottomRightRadius() const {
-    return surround_->border_.BottomRight();
+    return surround_data_->border_.BottomRight();
   }
   void SetBorderBottomRightRadius(const LengthSize& s) {
-    SET_VAR(surround_, border_.bottom_right_, s);
+    SET_VAR(surround_data_, border_.bottom_right_, s);
   }
 
   // Offset properties.
   // left
   static Length InitialLeft() { return Length(); }
-  const Length& Left() const { return surround_->left_; }
-  void SetLeft(const Length& v) { SET_VAR(surround_, left_, v); }
+  const Length& Left() const { return surround_data_->left_; }
+  void SetLeft(const Length& v) { SET_VAR(surround_data_, left_, v); }
 
   // right
   static Length InitialRight() { return Length(); }
-  const Length& Right() const { return surround_->right_; }
-  void SetRight(const Length& v) { SET_VAR(surround_, right_, v); }
+  const Length& Right() const { return surround_data_->right_; }
+  void SetRight(const Length& v) { SET_VAR(surround_data_, right_, v); }
 
   // top
   static Length InitialTop() { return Length(); }
-  const Length& Top() const { return surround_->top_; }
-  void SetTop(const Length& v) { SET_VAR(surround_, top_, v); }
+  const Length& Top() const { return surround_data_->top_; }
+  void SetTop(const Length& v) { SET_VAR(surround_data_, top_, v); }
 
   // bottom
   static Length InitialBottom() { return Length(); }
-  const Length& Bottom() const { return surround_->bottom_; }
-  void SetBottom(const Length& v) { SET_VAR(surround_, bottom_, v); }
+  const Length& Bottom() const { return surround_data_->bottom_; }
+  void SetBottom(const Length& v) { SET_VAR(surround_data_, bottom_, v); }
 
   // box-shadow (aka -webkit-box-shadow)
   static ShadowList* InitialBoxShadow() { return 0; }
@@ -625,22 +629,22 @@
 
   // box-sizing (aka -webkit-box-sizing)
   static EBoxSizing InitialBoxSizing() { return EBoxSizing::kContentBox; }
-  EBoxSizing BoxSizing() const { return box_->BoxSizing(); }
+  EBoxSizing BoxSizing() const { return box_data_->BoxSizing(); }
   void SetBoxSizing(EBoxSizing s) {
-    SET_VAR(box_, box_sizing_, static_cast<unsigned>(s));
+    SET_VAR(box_data_, box_sizing_, static_cast<unsigned>(s));
   }
 
   // clip
   static LengthBox InitialClip() { return LengthBox(); }
-  const LengthBox& Clip() const { return visual_->clip; }
+  const LengthBox& Clip() const { return visual_data_->clip; }
   void SetClip(const LengthBox& box) {
-    SET_VAR(visual_, has_auto_clip, false);
-    SET_VAR(visual_, clip, box);
+    SET_VAR(visual_data_, has_auto_clip, false);
+    SET_VAR(visual_data_, clip, box);
   }
-  bool HasAutoClip() const { return visual_->has_auto_clip; }
+  bool HasAutoClip() const { return visual_data_->has_auto_clip; }
   void SetHasAutoClip() {
-    SET_VAR(visual_, has_auto_clip, true);
-    SET_VAR(visual_, clip, ComputedStyle::InitialClip());
+    SET_VAR(visual_data_, has_auto_clip, true);
+    SET_VAR(visual_data_, clip, ComputedStyle::InitialClip());
   }
 
   // Column properties.
@@ -837,10 +841,10 @@
     return kBoxDecorationBreakSlice;
   }
   EBoxDecorationBreak BoxDecorationBreak() const {
-    return box_->BoxDecorationBreak();
+    return box_data_->BoxDecorationBreak();
   }
   void SetBoxDecorationBreak(EBoxDecorationBreak b) {
-    SET_VAR(box_, box_decoration_break_, b);
+    SET_VAR(box_data_, box_decoration_break_, b);
   }
 
   // -webkit-box-lines
@@ -1037,28 +1041,28 @@
   static Length InitialMinSize() { return Length(); }
 
   // width
-  const Length& Width() const { return box_->Width(); }
-  void SetWidth(const Length& v) { SET_VAR(box_, width_, v); }
+  const Length& Width() const { return box_data_->Width(); }
+  void SetWidth(const Length& v) { SET_VAR(box_data_, width_, v); }
 
   // height
-  const Length& Height() const { return box_->Height(); }
-  void SetHeight(const Length& v) { SET_VAR(box_, height_, v); }
+  const Length& Height() const { return box_data_->Height(); }
+  void SetHeight(const Length& v) { SET_VAR(box_data_, height_, v); }
 
   // max-width
-  const Length& MaxWidth() const { return box_->MaxWidth(); }
-  void SetMaxWidth(const Length& v) { SET_VAR(box_, max_width_, v); }
+  const Length& MaxWidth() const { return box_data_->MaxWidth(); }
+  void SetMaxWidth(const Length& v) { SET_VAR(box_data_, max_width_, v); }
 
   // max-height
-  const Length& MaxHeight() const { return box_->MaxHeight(); }
-  void SetMaxHeight(const Length& v) { SET_VAR(box_, max_height_, v); }
+  const Length& MaxHeight() const { return box_data_->MaxHeight(); }
+  void SetMaxHeight(const Length& v) { SET_VAR(box_data_, max_height_, v); }
 
   // min-width
-  const Length& MinWidth() const { return box_->MinWidth(); }
-  void SetMinWidth(const Length& v) { SET_VAR(box_, min_width_, v); }
+  const Length& MinWidth() const { return box_data_->MinWidth(); }
+  void SetMinWidth(const Length& v) { SET_VAR(box_data_, min_width_, v); }
 
   // min-height
-  const Length& MinHeight() const { return box_->MinHeight(); }
-  void SetMinHeight(const Length& v) { SET_VAR(box_, min_height_, v); }
+  const Length& MinHeight() const { return box_data_->MinHeight(); }
+  void SetMinHeight(const Length& v) { SET_VAR(box_data_, min_height_, v); }
 
   // image-orientation
   static RespectImageOrientationEnum InitialRespectImageOrientation() {
@@ -1094,25 +1098,31 @@
 
   // margin-top
   static Length InitialMarginTop() { return Length(kFixed); }
-  const Length& MarginTop() const { return surround_->margin_top_; }
-  void SetMarginTop(const Length& v) { SET_VAR(surround_, margin_top_, v); }
+  const Length& MarginTop() const { return surround_data_->margin_top_; }
+  void SetMarginTop(const Length& v) {
+    SET_VAR(surround_data_, margin_top_, v);
+  }
 
   // margin-bottom
   static Length InitialMarginBottom() { return Length(kFixed); }
-  const Length& MarginBottom() const { return surround_->margin_bottom_; }
+  const Length& MarginBottom() const { return surround_data_->margin_bottom_; }
   void SetMarginBottom(const Length& v) {
-    SET_VAR(surround_, margin_bottom_, v);
+    SET_VAR(surround_data_, margin_bottom_, v);
   }
 
   // margin-left
   static Length InitialMarginLeft() { return Length(kFixed); }
-  const Length& MarginLeft() const { return surround_->margin_left_; }
-  void SetMarginLeft(const Length& v) { SET_VAR(surround_, margin_left_, v); }
+  const Length& MarginLeft() const { return surround_data_->margin_left_; }
+  void SetMarginLeft(const Length& v) {
+    SET_VAR(surround_data_, margin_left_, v);
+  }
 
   // margin-right
   static Length InitialMarginRight() { return Length(kFixed); }
-  const Length& MarginRight() const { return surround_->margin_right_; }
-  void SetMarginRight(const Length& v) { SET_VAR(surround_, margin_right_, v); }
+  const Length& MarginRight() const { return surround_data_->margin_right_; }
+  void SetMarginRight(const Length& v) {
+    SET_VAR(surround_data_, margin_right_, v);
+  }
 
   // -webkit-margin-before-collapse (aka -webkit-margin-top-collapse)
   static EMarginCollapse InitialMarginBeforeCollapse() {
@@ -1296,27 +1306,33 @@
 
   // padding-bottom
   static Length InitialPaddingBottom() { return Length(kFixed); }
-  const Length& PaddingBottom() const { return surround_->padding_bottom_; }
+  const Length& PaddingBottom() const {
+    return surround_data_->padding_bottom_;
+  }
   void SetPaddingBottom(const Length& v) {
-    SET_VAR(surround_, padding_bottom_, v);
+    SET_VAR(surround_data_, padding_bottom_, v);
   }
 
   // padding-left
   static Length InitialPaddingLeft() { return Length(kFixed); }
-  const Length& PaddingLeft() const { return surround_->padding_left_; }
-  void SetPaddingLeft(const Length& v) { SET_VAR(surround_, padding_left_, v); }
+  const Length& PaddingLeft() const { return surround_data_->padding_left_; }
+  void SetPaddingLeft(const Length& v) {
+    SET_VAR(surround_data_, padding_left_, v);
+  }
 
   // padding-right
   static Length InitialPaddingRight() { return Length(kFixed); }
-  const Length& PaddingRight() const { return surround_->padding_right_; }
+  const Length& PaddingRight() const { return surround_data_->padding_right_; }
   void SetPaddingRight(const Length& v) {
-    SET_VAR(surround_, padding_right_, v);
+    SET_VAR(surround_data_, padding_right_, v);
   }
 
   // padding-top
   static Length InitialPaddingTop() { return Length(kFixed); }
-  const Length& PaddingTop() const { return surround_->padding_top_; }
-  void SetPaddingTop(const Length& v) { SET_VAR(surround_, padding_top_, v); }
+  const Length& PaddingTop() const { return surround_data_->padding_top_; }
+  void SetPaddingTop(const Length& v) {
+    SET_VAR(surround_data_, padding_top_, v);
+  }
 
   // perspective (aka -webkit-perspective)
   static float InitialPerspective() { return 0; }
@@ -1566,10 +1582,10 @@
   // text-decoration-line
   static TextDecoration InitialTextDecoration() { return kTextDecorationNone; }
   TextDecoration GetTextDecoration() const {
-    return static_cast<TextDecoration>(visual_->text_decoration);
+    return static_cast<TextDecoration>(visual_data_->text_decoration);
   }
   void SetTextDecoration(TextDecoration v) {
-    SET_VAR(visual_, text_decoration, v);
+    SET_VAR(visual_data_, text_decoration, v);
   }
 
   // text-decoration-color
@@ -1636,11 +1652,13 @@
     return EVerticalAlign::kBaseline;
   }
   EVerticalAlign VerticalAlign() const { return VerticalAlignInternal(); }
-  const Length& GetVerticalAlignLength() const { return box_->VerticalAlign(); }
+  const Length& GetVerticalAlignLength() const {
+    return box_data_->VerticalAlign();
+  }
   void SetVerticalAlign(EVerticalAlign v) { SetVerticalAlignInternal(v); }
   void SetVerticalAlignLength(const Length& length) {
     SetVerticalAlignInternal(EVerticalAlign::kLength);
-    SET_VAR(box_, vertical_align_, length);
+    SET_VAR(box_data_, vertical_align_, length);
   }
 
   // will-change
@@ -1671,20 +1689,20 @@
   }
 
   // z-index
-  int ZIndex() const { return box_->ZIndex(); }
-  bool HasAutoZIndex() const { return box_->HasAutoZIndex(); }
+  int ZIndex() const { return box_data_->ZIndex(); }
+  bool HasAutoZIndex() const { return box_data_->HasAutoZIndex(); }
   void SetZIndex(int v) {
-    SET_VAR(box_, has_auto_z_index_, false);
-    SET_VAR(box_, z_index_, v);
+    SET_VAR(box_data_, has_auto_z_index_, false);
+    SET_VAR(box_data_, z_index_, v);
   }
   void SetHasAutoZIndex() {
-    SET_VAR(box_, has_auto_z_index_, true);
-    SET_VAR(box_, z_index_, 0);
+    SET_VAR(box_data_, has_auto_z_index_, true);
+    SET_VAR(box_data_, z_index_, 0);
   }
 
   // zoom
   static float InitialZoom() { return 1.0f; }
-  float Zoom() const { return visual_->zoom_; }
+  float Zoom() const { return visual_data_->zoom_; }
   float EffectiveZoom() const { return rare_inherited_data_->effective_zoom_; }
   bool SetZoom(float);
   bool SetEffectiveZoom(float);
@@ -2800,17 +2818,17 @@
   }
   void SetLogicalWidth(const Length& v) {
     if (IsHorizontalWritingMode()) {
-      SET_VAR(box_, width_, v);
+      SET_VAR(box_data_, width_, v);
     } else {
-      SET_VAR(box_, height_, v);
+      SET_VAR(box_data_, height_, v);
     }
   }
 
   void SetLogicalHeight(const Length& v) {
     if (IsHorizontalWritingMode()) {
-      SET_VAR(box_, height_, v);
+      SET_VAR(box_data_, height_, v);
     } else {
-      SET_VAR(box_, width_, v);
+      SET_VAR(box_data_, width_, v);
     }
   }
   const Length& LogicalMaxWidth() const {
@@ -2898,16 +2916,16 @@
            !PaddingTop().IsZero() || !PaddingBottom().IsZero();
   }
   void ResetPadding() {
-    SET_VAR(surround_, padding_top_, kFixed);
-    SET_VAR(surround_, padding_bottom_, kFixed);
-    SET_VAR(surround_, padding_left_, kFixed);
-    SET_VAR(surround_, padding_right_, kFixed);
+    SET_VAR(surround_data_, padding_top_, kFixed);
+    SET_VAR(surround_data_, padding_bottom_, kFixed);
+    SET_VAR(surround_data_, padding_left_, kFixed);
+    SET_VAR(surround_data_, padding_right_, kFixed);
   }
   void SetPadding(const LengthBox& b) {
-    SET_VAR(surround_, padding_top_, b.top_);
-    SET_VAR(surround_, padding_bottom_, b.bottom_);
-    SET_VAR(surround_, padding_left_, b.left_);
-    SET_VAR(surround_, padding_right_, b.right_);
+    SET_VAR(surround_data_, padding_top_, b.top_);
+    SET_VAR(surround_data_, padding_bottom_, b.bottom_);
+    SET_VAR(surround_data_, padding_left_, b.left_);
+    SET_VAR(surround_data_, padding_right_, b.right_);
   }
   bool PaddingEqual(const ComputedStyle& other) const {
     return PaddingTop() == other.PaddingTop() &&
@@ -2931,12 +2949,16 @@
   bool BorderImageSlicesFill() const { return Border().GetImage().Fill(); }
 
   void SetBorderImageSlicesFill(bool);
-  const BorderData& Border() const { return surround_->border_; }
-  const BorderValue& BorderLeft() const { return surround_->border_.Left(); }
-  const BorderValue& BorderRight() const { return surround_->border_.Right(); }
-  const BorderValue& BorderTop() const { return surround_->border_.Top(); }
+  const BorderData& Border() const { return surround_data_->border_; }
+  const BorderValue& BorderLeft() const {
+    return surround_data_->border_.Left();
+  }
+  const BorderValue& BorderRight() const {
+    return surround_data_->border_.Right();
+  }
+  const BorderValue& BorderTop() const { return surround_data_->border_.Top(); }
   const BorderValue& BorderBottom() const {
-    return surround_->border_.Bottom();
+    return surround_data_->border_.Bottom();
   }
   const BorderValue& BorderBefore() const;
   const BorderValue& BorderAfter() const;
@@ -2968,26 +2990,32 @@
     ResetBorderBottomLeftRadius();
     ResetBorderBottomRightRadius();
   }
-  void ResetBorderTop() { SET_VAR(surround_, border_.top_, BorderValue()); }
-  void ResetBorderRight() { SET_VAR(surround_, border_.right_, BorderValue()); }
-  void ResetBorderBottom() {
-    SET_VAR(surround_, border_.bottom_, BorderValue());
+  void ResetBorderTop() {
+    SET_VAR(surround_data_, border_.top_, BorderValue());
   }
-  void ResetBorderLeft() { SET_VAR(surround_, border_.left_, BorderValue()); }
+  void ResetBorderRight() {
+    SET_VAR(surround_data_, border_.right_, BorderValue());
+  }
+  void ResetBorderBottom() {
+    SET_VAR(surround_data_, border_.bottom_, BorderValue());
+  }
+  void ResetBorderLeft() {
+    SET_VAR(surround_data_, border_.left_, BorderValue());
+  }
   void ResetBorderImage() {
-    SET_VAR(surround_, border_.image_, NinePieceImage());
+    SET_VAR(surround_data_, border_.image_, NinePieceImage());
   }
   void ResetBorderTopLeftRadius() {
-    SET_VAR(surround_, border_.top_left_, InitialBorderRadius());
+    SET_VAR(surround_data_, border_.top_left_, InitialBorderRadius());
   }
   void ResetBorderTopRightRadius() {
-    SET_VAR(surround_, border_.top_right_, InitialBorderRadius());
+    SET_VAR(surround_data_, border_.top_right_, InitialBorderRadius());
   }
   void ResetBorderBottomLeftRadius() {
-    SET_VAR(surround_, border_.bottom_left_, InitialBorderRadius());
+    SET_VAR(surround_data_, border_.bottom_left_, InitialBorderRadius());
   }
   void ResetBorderBottomRightRadius() {
-    SET_VAR(surround_, border_.bottom_right_, InitialBorderRadius());
+    SET_VAR(surround_data_, border_.bottom_right_, InitialBorderRadius());
   }
 
   void SetBorderRadius(const LengthSize& s) {
@@ -3066,10 +3094,10 @@
   }
 
   // Clip utility functions.
-  const Length& ClipLeft() const { return visual_->clip.Left(); }
-  const Length& ClipRight() const { return visual_->clip.Right(); }
-  const Length& ClipTop() const { return visual_->clip.Top(); }
-  const Length& ClipBottom() const { return visual_->clip.Bottom(); }
+  const Length& ClipLeft() const { return visual_data_->clip.Left(); }
+  const Length& ClipRight() const { return visual_data_->clip.Right(); }
+  const Length& ClipTop() const { return visual_data_->clip.Top(); }
+  const Length& ClipBottom() const { return visual_data_->clip.Bottom(); }
 
   // Offset utility functions.
   // Accessors for positioned object edges that take into account writing mode.
@@ -3249,7 +3277,7 @@
     kExcludeIndependentTransformProperties
   };
   void ApplyTransform(TransformationMatrix&,
-                      const LayoutSize& border_box_size,
+                      const LayoutSize& border_box_data_size,
                       ApplyTransformOrigin,
                       ApplyMotionPath,
                       ApplyIndependentTransformProperties) const;
@@ -3419,10 +3447,10 @@
 
   // Background utility functions.
   FillLayer& AccessBackgroundLayers() {
-    return background_.Access()->background_;
+    return background_data_.Access()->background_;
   }
   const FillLayer& BackgroundLayers() const {
-    return background_->Background();
+    return background_data_->Background();
   }
   void AdjustBackgroundLayers() {
     if (BackgroundLayers().Next()) {
@@ -3546,18 +3574,18 @@
   // Color accessors are all private to make sure callers use
   // VisitedDependentColor instead to access them.
   StyleColor BorderLeftColor() const {
-    return surround_->border_.Left().GetColor();
+    return surround_data_->border_.Left().GetColor();
   }
   StyleColor BorderRightColor() const {
-    return surround_->border_.Right().GetColor();
+    return surround_data_->border_.Right().GetColor();
   }
   StyleColor BorderTopColor() const {
-    return surround_->border_.Top().GetColor();
+    return surround_data_->border_.Top().GetColor();
   }
   StyleColor BorderBottomColor() const {
-    return surround_->border_.Bottom().GetColor();
+    return surround_data_->border_.Bottom().GetColor();
   }
-  StyleColor BackgroundColor() const { return background_->GetColor(); }
+  StyleColor BackgroundColor() const { return background_data_->GetColor(); }
   StyleAutoColor CaretColor() const {
     return rare_inherited_data_->CaretColor();
   }
@@ -3694,9 +3722,9 @@
 }
 
 inline bool ComputedStyle::SetZoom(float f) {
-  if (compareEqual(visual_->zoom_, f))
+  if (compareEqual(visual_data_->zoom_, f))
     return false;
-  visual_.Access()->zoom_ = f;
+  visual_data_.Access()->zoom_ = f;
   SetEffectiveZoom(EffectiveZoom() * Zoom());
   return true;
 }
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index 7a9c20fd..a4ee138 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -40,6 +40,7 @@
 #include "core/inspector/ConsoleMessage.h"
 #include "core/inspector/ConsoleMessageStorage.h"
 #include "core/inspector/WorkerThreadDebugger.h"
+#include "core/loader/WorkerFetchContext.h"
 #include "core/loader/WorkerThreadableLoader.h"
 #include "core/probe/CoreProbes.h"
 #include "core/workers/WorkerClients.h"
@@ -51,6 +52,7 @@
 #include "core/workers/WorkerThread.h"
 #include "platform/CrossThreadFunctional.h"
 #include "platform/InstanceCounters.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/loader/fetch/MemoryCache.h"
 #include "platform/network/ContentSecurityPolicyParsers.h"
 #include "platform/scheduler/child/web_scheduler.h"
@@ -300,6 +302,14 @@
   return const_cast<WorkerGlobalScope*>(this);
 }
 
+WorkerFetchContext* WorkerGlobalScope::GetFetchContext() {
+  DCHECK(RuntimeEnabledFeatures::offMainThreadFetchEnabled());
+  if (fetch_context_)
+    return fetch_context_;
+  fetch_context_ = WorkerFetchContext::Create(*this);
+  return fetch_context_;
+}
+
 WorkerGlobalScope::WorkerGlobalScope(
     const KURL& url,
     const String& user_agent,
@@ -375,6 +385,7 @@
   visitor->Trace(timers_);
   visitor->Trace(event_listeners_);
   visitor->Trace(pending_error_events_);
+  visitor->Trace(fetch_context_);
   ExecutionContext::Trace(visitor);
   EventTargetWithInlineData::Trace(visitor);
   SecurityContext::Trace(visitor);
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
index 4abdcf3..ec165161 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
@@ -51,6 +51,7 @@
 class ExceptionState;
 class V8AbstractEventListener;
 class WorkerClients;
+class WorkerFetchContext;
 class WorkerLocation;
 class WorkerNavigator;
 class WorkerThread;
@@ -153,6 +154,9 @@
 
   WorkerClients* Clients() const { return worker_clients_.Get(); }
 
+  // Available only when off-main-thread-fetch is enabled.
+  WorkerFetchContext* GetFetchContext();
+
   DECLARE_VIRTUAL_TRACE();
 
  protected:
@@ -208,6 +212,8 @@
 
   HeapHashMap<int, Member<ErrorEvent>> pending_error_events_;
   int last_pending_error_event_id_;
+
+  Member<WorkerFetchContext> fetch_context_;
 };
 
 DEFINE_TYPE_CASTS(WorkerGlobalScope,
diff --git a/third_party/WebKit/Source/devtools/front_end/inline_editor/SwatchPopoverHelper.js b/third_party/WebKit/Source/devtools/front_end/inline_editor/SwatchPopoverHelper.js
index 8c6c9d34..69adaad15 100644
--- a/third_party/WebKit/Source/devtools/front_end/inline_editor/SwatchPopoverHelper.js
+++ b/third_party/WebKit/Source/devtools/front_end/inline_editor/SwatchPopoverHelper.js
@@ -9,7 +9,6 @@
     super();
     this._popover = new UI.GlassPane();
     this._popover.registerRequiredCSS('inline_editor/swatchPopover.css');
-    this._popover.setBlockPointerEvents(false);
     this._popover.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
     this._popover.setMarginBehavior(UI.GlassPane.MarginBehavior.Arrow);
     this._popover.element.addEventListener('mousedown', e => e.consume(), false);
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js b/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js
index 5541156..f517e65 100644
--- a/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js
@@ -479,8 +479,8 @@
   constructor(anchor) {
     this._anchorElement = anchor;
     this._glassPane = new UI.GlassPane();
-    this._glassPane.setBlockPointerEvents(false);
-    this._glassPane.setMarginBehavior(UI.GlassPane.MarginBehavior.NoMargin);
+    this._glassPane.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.PierceContents);
+    this._glassPane.setMarginBehavior(UI.GlassPane.MarginBehavior.Arrow);
     this._glassPane.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
     this._element =
         UI.createShadowRootWithCoreStyles(this._glassPane.contentElement, 'perf_ui/timelineOverviewInfo.css')
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/timelineOverviewInfo.css b/third_party/WebKit/Source/devtools/front_end/perf_ui/timelineOverviewInfo.css
index 0799e94..bce02d4 100644
--- a/third_party/WebKit/Source/devtools/front_end/perf_ui/timelineOverviewInfo.css
+++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/timelineOverviewInfo.css
@@ -8,7 +8,6 @@
     display: flex;
     background: white;
     box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 2px 4px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0, 0, 0, 0.1);
-    pointer-events: none;
 }
 
 .overview-info .frame .time {
@@ -19,5 +18,3 @@
     max-width: 400px;
     max-height: 500px;
 }
-
-
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
index dc07c7f3..3590d65 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -249,14 +249,14 @@
     var children = this._root.children();
     var maxSelfTime = 0;
     var maxTotalTime = 0;
+    var totalUsedTime = this._root.totalTime - this._root.selfTime;
     for (var child of children.values()) {
       maxSelfTime = Math.max(maxSelfTime, child.selfTime);
       maxTotalTime = Math.max(maxTotalTime, child.totalTime);
     }
     for (var child of children.values()) {
       // Exclude the idle time off the total calculation.
-      var gridNode =
-          new Timeline.TimelineTreeView.TreeGridNode(child, this._root.totalTime, maxSelfTime, maxTotalTime, this);
+      var gridNode = new Timeline.TimelineTreeView.TreeGridNode(child, totalUsedTime, maxSelfTime, maxTotalTime, this);
       this._dataGrid.insertChild(gridNode);
     }
     this._sortingChanged();
@@ -854,6 +854,7 @@
         return null;
     }
   }
+
   /**
    * @override
    * @param {!UI.ContextMenu} contextMenu
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
index 1567c91..3a8ec1a4 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -1046,14 +1046,13 @@
    */
   static _buildRangeStatsCacheIfNeeded(model) {
     var tasks = model.mainThreadTasks();
-    var filter = Timeline.TimelineUIUtils._filterForStats();
-    var firstTask = tasks.find(filter);
-    if (!firstTask || firstTask[Timeline.TimelineUIUtils._categoryBreakdownCacheSymbol])
+    if (tasks.length && tasks[0][Timeline.TimelineUIUtils._categoryBreakdownCacheSymbol])
       return;
     var aggregatedStats = {};
     var ownTimes = [];
     TimelineModel.TimelineModel.forEachEvent(
-        model.mainThreadEvents(), onStartEvent, onEndEvent, undefined, undefined, undefined, filter);
+        model.mainThreadEvents(), onStartEvent, onEndEvent, undefined, undefined, undefined,
+        Timeline.TimelineUIUtils._filterForStats());
 
     /**
      * @param {!SDK.TracingModel.Event} e
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
index 620d574..eb908dc 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -590,8 +590,8 @@
 }
 
 .timeline-tree-view .data-grid .selected .background-bar {
-    background-color: rgba(255, 255, 255, 0.25);
-    border-bottom-color: rgba(255, 255, 255, 0.5);
+    background-color: rgba(255, 255, 255, 0.3);
+    border-bottom-color: rgba(255, 255, 255, 0.9);
 }
 
 .timeline-tree-view .timeline-details-view-body .full-widget-dimmed-banner {
@@ -670,4 +670,4 @@
 
 .timeline-landing-warning span[is=ui-icon] {
     margin: -8px;
-}
\ No newline at end of file
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineProfileTree.js b/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineProfileTree.js
index c08f3965..edb01a9 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineProfileTree.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineProfileTree.js
@@ -250,6 +250,8 @@
    */
   _grouppedTopNodes() {
     var flatNodes = super.children();
+    for (var node of flatNodes.values())
+      this.selfTime -= node.totalTime;
     if (!this._eventGroupIdCallback)
       return flatNodes;
     var groupNodes = new Map();
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js b/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js
index b905558..aa64dee 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js
@@ -35,7 +35,7 @@
     this.contentElement.tabIndex = 0;
     this.contentElement.addEventListener('focus', () => this.widget().focus(), false);
     this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this), false);
-    this.setBlockPointerEvents(true);
+    this.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane);
     this.setSetOutsideClickCallback(event => {
       this.hide();
       event.consume(true);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js b/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
index d94c4433f..f508cf6 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
@@ -12,7 +12,8 @@
     this.element.shadowRoot.appendChild(this._arrowElement);
 
     this.registerRequiredCSS('ui/glassPane.css');
-    this.element.classList.add('no-pointer-events');
+    this.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.PierceGlassPane);
+
     this._onMouseDownBound = this._onMouseDown.bind(this);
     /** @type {?function(!Event)} */
     this._onClickOutsideCallback = null;
@@ -51,10 +52,13 @@
   }
 
   /**
-   * @param {boolean} blockPointerEvents
+   * @param {!UI.GlassPane.PointerEventsBehavior} pointerEventsBehavior
    */
-  setBlockPointerEvents(blockPointerEvents) {
-    this.element.classList.toggle('no-pointer-events', !blockPointerEvents);
+  setPointerEventsBehavior(pointerEventsBehavior) {
+    this.element.classList.toggle(
+        'no-pointer-events', pointerEventsBehavior !== UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane);
+    this.contentElement.classList.toggle(
+        'no-pointer-events', pointerEventsBehavior === UI.GlassPane.PointerEventsBehavior.PierceContents);
   }
 
   /**
@@ -364,9 +368,14 @@
   }
 };
 
-/**
- * @enum {symbol}
- */
+/** @enum {symbol} */
+UI.GlassPane.PointerEventsBehavior = {
+  BlockedByGlassPane: Symbol('BlockedByGlassPane'),
+  PierceGlassPane: Symbol('PierceGlassPane'),
+  PierceContents: Symbol('PierceContents')
+};
+
+/** @enum {symbol} */
 UI.GlassPane.AnchorBehavior = {
   PreferTop: Symbol('PreferTop'),
   PreferBottom: Symbol('PreferBottom'),
@@ -374,18 +383,14 @@
   PreferRight: Symbol('PreferRight'),
 };
 
-/**
- * @enum {symbol}
- */
+/** @enum {symbol} */
 UI.GlassPane.SizeBehavior = {
   SetExactSize: Symbol('SetExactSize'),
   SetExactWidthMaxHeight: Symbol('SetExactWidthMaxHeight'),
   MeasureContent: Symbol('MeasureContent')
 };
 
-/**
- * @enum {symbol}
- */
+/** @enum {symbol} */
 UI.GlassPane.MarginBehavior = {
   Arrow: Symbol('Arrow'),
   DefaultMargin: Symbol('DefaultMargin'),
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Popover.js b/third_party/WebKit/Source/devtools/front_end/ui/Popover.js
index 6c4790a..6dd7e1ac 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Popover.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Popover.js
@@ -203,7 +203,6 @@
     var popover = new UI.GlassPane();
     popover.registerRequiredCSS('ui/popover.css');
     popover.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
-    popover.setBlockPointerEvents(false);
     popover.setMarginBehavior(UI.GlassPane.MarginBehavior.Arrow);
     var request = this._scheduledRequest;
     request.show.call(null, popover).then(success => {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js
index 6af13cd..cffeefa 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js
@@ -49,7 +49,9 @@
     this._document = document;
 
     this._glassPane = new UI.GlassPane();
-    this._glassPane.setBlockPointerEvents(!this._parentMenu);
+    this._glassPane.setPointerEventsBehavior(
+        this._parentMenu ? UI.GlassPane.PointerEventsBehavior.PierceGlassPane :
+                           UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane);
     this._glassPane.registerRequiredCSS('ui/softContextMenu.css');
     this._glassPane.setContentAnchorBox(anchorBox);
     this._glassPane.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
index 8f36b24..c8deeec 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
@@ -124,7 +124,7 @@
       document.documentElement.addEventListener('mouseup', mouseUp, false);
 
       var optionsGlassPane = new UI.GlassPane();
-      optionsGlassPane.setBlockPointerEvents(true);
+      optionsGlassPane.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane);
       optionsGlassPane.show(document);
       var optionsBar = new UI.Toolbar('fill', optionsGlassPane.contentElement);
       optionsBar._contentElement.classList.add('floating');
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
index 7f114a2..d2d83168 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -96,7 +96,7 @@
     this._glassPaneInUse = true;
     if (!UI.DragHandler._glassPaneUsageCount++) {
       UI.DragHandler._glassPane = new UI.GlassPane();
-      UI.DragHandler._glassPane.setBlockPointerEvents(true);
+      UI.DragHandler._glassPane.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane);
       UI.DragHandler._glassPane.show(UI.DragHandler._documentForMouseOut);
     }
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/glassPane.css b/third_party/WebKit/Source/devtools/front_end/ui/glassPane.css
index 31a72a8..1a170f4 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/glassPane.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/glassPane.css
@@ -30,6 +30,10 @@
     flex: none;
 }
 
+.no-pointer-events {
+    pointer-events: none;
+}
+
 .arrow-top {
     margin-top: -19px;
     margin-left: -9px;
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothError.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothError.cpp
index cefc92b7..79b368b 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothError.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothError.cpp
@@ -31,7 +31,7 @@
     case BluetoothOperation::kDescriptorsRetrieval:
       operation_string = "retrieve descriptors";
       break;
-    case BluetoothOperation::GATT:
+    case BluetoothOperation::kGATT:
       operation_string = "perform GATT operations";
       break;
   }
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothError.h b/third_party/WebKit/Source/modules/bluetooth/BluetoothError.h
index c07a614..1c5806c 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothError.h
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothError.h
@@ -12,12 +12,11 @@
 namespace blink {
 
 // Used when generating DOMExceptions specific to each operation.
-// TODO(crbug.com/684445): Add DescriptorsRetrieval.
 enum class BluetoothOperation {
   kServicesRetrieval,
   kCharacteristicsRetrieval,
   kDescriptorsRetrieval,
-  GATT,
+  kGATT,
 };
 
 // These error codes requires detailed error messages.
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
index fd7cca8..cb108ad8 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
@@ -94,7 +94,7 @@
   // If the device is disconnected, reject.
   if (!GetGatt()->RemoveFromActiveAlgorithms(resolver)) {
     resolver->Reject(
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
     return;
   }
 
@@ -115,7 +115,7 @@
   if (!GetGatt()->connected()) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
   }
 
   if (!GetGatt()->device()->IsValidCharacteristic(
@@ -150,7 +150,7 @@
   // If the device is disconnected, reject.
   if (!GetGatt()->RemoveFromActiveAlgorithms(resolver)) {
     resolver->Reject(
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
     return;
   }
 
@@ -168,7 +168,7 @@
   if (!GetGatt()->connected()) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
   }
 
   if (!GetGatt()->device()->IsValidCharacteristic(
@@ -217,7 +217,7 @@
   // If the device is disconnected, reject.
   if (!GetGatt()->RemoveFromActiveAlgorithms(resolver)) {
     resolver->Reject(
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
     return;
   }
 
@@ -233,7 +233,7 @@
   if (!GetGatt()->connected()) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
   }
 
   if (!GetGatt()->device()->IsValidCharacteristic(
@@ -266,7 +266,7 @@
   if (!GetGatt()->connected()) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
   }
 
   if (!GetGatt()->device()->IsValidCharacteristic(
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp
index a955399..0fda52c 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp
@@ -39,7 +39,7 @@
   // If the device is disconnected, reject.
   if (!GetGatt()->RemoveFromActiveAlgorithms(resolver)) {
     resolver->Reject(
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
     return;
   }
 
@@ -59,7 +59,7 @@
   if (!GetGatt()->connected()) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
   }
 
   if (!GetGatt()->device()->IsValidDescriptor(descriptor_->instance_id)) {
@@ -91,7 +91,7 @@
   // disconnected so we reject.
   if (!GetGatt()->RemoveFromActiveAlgorithms(resolver)) {
     resolver->Reject(
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
     return;
   }
 
@@ -109,7 +109,7 @@
   if (!GetGatt()->connected()) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
-        BluetoothError::CreateNotConnectedException(BluetoothOperation::GATT));
+        BluetoothError::CreateNotConnectedException(BluetoothOperation::kGATT));
   }
 
   if (!GetGatt()->device()->IsValidDescriptor(descriptor_->instance_id)) {
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp
index 092bc16..90620e1e 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp
@@ -350,7 +350,7 @@
 
 IDBTransaction* IDBDatabase::transaction(
     ScriptState* script_state,
-    const StringOrStringSequenceOrDOMStringList& store_names,
+    const StringOrStringSequence& store_names,
     const String& mode_string,
     ExceptionState& exception_state) {
   IDB_TRACE("IDBDatabase::transaction");
@@ -362,10 +362,6 @@
   } else if (store_names.isStringSequence()) {
     for (const String& name : store_names.getAsStringSequence())
       scope.insert(name);
-  } else if (store_names.isDOMStringList()) {
-    const Vector<String>& list = *store_names.getAsDOMStringList();
-    for (const String& name : list)
-      scope.insert(name);
   } else {
     NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h
index c0d0f28..ddda700 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h
@@ -28,7 +28,7 @@
 
 #include "bindings/core/v8/ActiveScriptWrappable.h"
 #include "bindings/core/v8/ScriptState.h"
-#include "bindings/modules/v8/StringOrStringSequenceOrDOMStringList.h"
+#include "bindings/modules/v8/StringOrStringSequence.h"
 #include "core/dom/ContextLifecycleObserver.h"
 #include "core/dom/DOMStringList.h"
 #include "modules/EventModules.h"
@@ -101,11 +101,10 @@
     return createObjectStore(name, IDBKeyPath(options.keyPath()),
                              options.autoIncrement(), exception_state);
   }
-  IDBTransaction* transaction(
-      ScriptState*,
-      const StringOrStringSequenceOrDOMStringList& store_names,
-      const String& mode,
-      ExceptionState&);
+  IDBTransaction* transaction(ScriptState*,
+                              const StringOrStringSequence& store_names,
+                              const String& mode,
+                              ExceptionState&);
   void deleteObjectStore(const String& name, ExceptionState&);
   void close();
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.idl b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.idl
index 3febcf1..b678506 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.idl
@@ -35,7 +35,7 @@
     readonly attribute unsigned long long version;
     readonly attribute DOMStringList objectStoreNames;
 
-    [NewObject, CallWith=ScriptState, RaisesException] IDBTransaction transaction((DOMString or sequence<DOMString> or DOMStringList) storeNames,
+    [NewObject, CallWith=ScriptState, RaisesException] IDBTransaction transaction((DOMString or sequence<DOMString>) storeNames,
                                                                                   optional IDBTransactionMode mode = "readonly");
     void close();
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
index dfa93b0..6b6d197 100644
--- a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
@@ -319,7 +319,7 @@
     const String& object_store_name,
     const String& mode = IndexedDBNames::readonly) {
   DummyExceptionStateForTesting exception_state;
-  StringOrStringSequenceOrDOMStringList scope;
+  StringOrStringSequence scope;
   scope.setString(object_store_name);
   IDBTransaction* idb_transaction =
       idb_database->transaction(script_state, scope, mode, exception_state);
diff --git a/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp b/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
index 0ec5372..812d9b2 100644
--- a/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
+++ b/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
@@ -13,6 +13,7 @@
 #include "modules/media_capabilities/MediaConfiguration.h"
 #include "modules/media_capabilities/MediaDecodingConfiguration.h"
 #include "modules/media_capabilities/MediaEncodingConfiguration.h"
+#include "platform/network/ParsedContentType.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebMediaRecorderHandler.h"
 #include "public/platform/modules/media_capabilities/WebMediaCapabilitiesClient.h"
@@ -29,7 +30,15 @@
 
   // |contentType| is mandatory.
   DCHECK(configuration.hasContentType());
-  web_configuration.content_type = configuration.contentType();
+  ParsedContentType parsed_content_type(configuration.contentType(),
+                                        ParsedContentType::Mode::kStrict);
+
+  // TODO(chcunningham): Throw TypeError for invalid input.
+  // DCHECK(parsed_content_type.IsValid());
+
+  DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
+  web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII();
+  web_configuration.codec = parsed_content_type.ParameterValueForName(codecs);
 
   // |channels| is optional and will be set to a null WebString if not present.
   web_configuration.channels = configuration.hasChannels()
@@ -51,7 +60,15 @@
 
   // All the properties are mandatory.
   DCHECK(configuration.hasContentType());
-  web_configuration.content_type = configuration.contentType();
+  ParsedContentType parsed_content_type(configuration.contentType(),
+                                        ParsedContentType::Mode::kStrict);
+
+  // TODO(chcunningham): Throw TypeError for invalid input.
+  // DCHECK(parsed_content_type.IsValid());
+
+  DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
+  web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII();
+  web_configuration.codec = parsed_content_type.ParameterValueForName(codecs);
 
   DCHECK(configuration.hasWidth());
   web_configuration.width = configuration.width();
diff --git a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
index 437ecae..98791a53f 100644
--- a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
+++ b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
@@ -116,19 +116,13 @@
   uint8_t* pixel_data_ptr = nullptr;
   WTF::CheckedNumeric<int> allocation_size = 0;
 
-  sk_sp<SkImage> sk_image = image->ImageForCurrentFrame();
-  // Use |skImage|'s pixels if it has direct access to them.
-  if (sk_image->peekPixels(&pixmap)) {
+  // makeNonTextureImage() will make a raster copy of ImageForCurrentFrame() if
+  // needed, otherwise returning the original SkImage.
+  const sk_sp<SkImage> sk_image =
+      image->ImageForCurrentFrame()->makeNonTextureImage();
+  if (sk_image && sk_image->peekPixels(&pixmap)) {
     pixel_data_ptr = static_cast<uint8_t*>(pixmap.writable_addr());
     allocation_size = pixmap.getSafeSize();
-  } else if (image_source.isImageBitmap()) {
-    ImageBitmap* image_bitmap = image_source.getAsImageBitmap();
-    pixel_data = image_bitmap->CopyBitmapData(image_bitmap->IsPremultiplied()
-                                                  ? kPremultiplyAlpha
-                                                  : kDontPremultiplyAlpha,
-                                              kN32ColorType);
-    pixel_data_ptr = pixel_data->Data();
-    allocation_size = image_bitmap->Size().Area() * 4 /* bytes per pixel */;
   } else {
     // TODO(mcasas): retrieve the pixels from elsewhere.
     NOTREACHED();
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
index 865352c..4d1c5ec 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -681,6 +681,9 @@
       status: "stable",
     },
     {
+      name: "OffMainThreadFetch",
+    },
+    {
       name: "OnDeviceChange",
       status: "stable",
     },
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.cpp b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.cpp
index c612edb..5c5707b4 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.cpp
@@ -58,7 +58,7 @@
                                                FetchResourceType) {}
 
 WebCachePolicy FetchContext::ResourceRequestCachePolicy(
-    ResourceRequest&,
+    const ResourceRequest&,
     Resource::Type,
     FetchParameters::DeferOption defer) const {
   return WebCachePolicy::kUseProtocolCachePolicy;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
index 6fbe7a9c..b598b762 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
@@ -42,6 +42,7 @@
 #include "platform/weborigin/SecurityViolationReportingPolicy.h"
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/Noncopyable.h"
+#include "public/platform/WebURLLoader.h"
 
 namespace blink {
 
@@ -85,7 +86,7 @@
   // a const reference as a header needs to be added for doc.write blocking
   // intervention.
   virtual WebCachePolicy ResourceRequestCachePolicy(
-      ResourceRequest&,
+      const ResourceRequest&,
       Resource::Type,
       FetchParameters::DeferOption) const;
 
@@ -214,6 +215,8 @@
     return platform_probe_sink_;
   }
 
+  virtual std::unique_ptr<WebURLLoader> CreateURLLoader() { return nullptr; }
+
  protected:
   FetchContext();
 
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollTypes.h b/third_party/WebKit/Source/platform/scroll/ScrollTypes.h
index 139f88b..8971c625 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollTypes.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollTypes.h
@@ -79,7 +79,9 @@
   kAnchoringScroll
 };
 
-inline bool ScrollTypeClearsFragmentAnchor(ScrollType scroll_type) {
+// An explicit scroll is one that was requested by the user or the webpage.
+// An implicit scroll is a side effect of a layout change.
+inline bool IsExplicitScrollType(ScrollType scroll_type) {
   return scroll_type == kUserScroll || scroll_type == kProgrammaticScroll ||
          scroll_type == kCompositorScroll;
 }
diff --git a/third_party/WebKit/Source/web/DedicatedWorkerMessagingProxyProviderImpl.cpp b/third_party/WebKit/Source/web/DedicatedWorkerMessagingProxyProviderImpl.cpp
index 47817c44..d5612a24 100644
--- a/third_party/WebKit/Source/web/DedicatedWorkerMessagingProxyProviderImpl.cpp
+++ b/third_party/WebKit/Source/web/DedicatedWorkerMessagingProxyProviderImpl.cpp
@@ -31,13 +31,17 @@
 #include "web/DedicatedWorkerMessagingProxyProviderImpl.h"
 
 #include "core/dom/Document.h"
+#include "core/loader/WorkerFetchContext.h"
 #include "core/workers/DedicatedWorkerMessagingProxy.h"
 #include "core/workers/Worker.h"
 #include "core/workers/WorkerClients.h"
 #include "core/workers/WorkerContentSettingsClient.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/wtf/PtrUtil.h"
+#include "public/platform/Platform.h"
 #include "public/platform/WebContentSettingsClient.h"
 #include "public/platform/WebString.h"
+#include "public/platform/WebWorkerFetchContext.h"
 #include "public/web/WebFrameClient.h"
 #include "public/web/WebWorkerContentSettingsClientProxy.h"
 #include "web/IndexedDBClientImpl.h"
@@ -67,6 +71,15 @@
         worker_clients,
         WTF::WrapUnique(
             web_frame->Client()->CreateWorkerContentSettingsClientProxy()));
+    if (RuntimeEnabledFeatures::offMainThreadFetchEnabled()) {
+      std::unique_ptr<WebWorkerFetchContext> web_worker_fetch_context =
+          web_frame->Client()->CreateWorkerFetchContext();
+      DCHECK(web_worker_fetch_context);
+      // TODO(horo): Set more information about the context (ex:
+      // DataSaverEnabled) to |web_worker_fetch_context|.
+      ProvideWorkerFetchContextToWorker(worker_clients,
+                                        std::move(web_worker_fetch_context));
+    }
     // FIXME: call provideServiceWorkerContainerClientToWorker here when we
     // support ServiceWorker in dedicated workers (http://crbug.com/371690)
     return new DedicatedWorkerMessagingProxy(worker, worker_clients);
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
index 1b4d6eb2..897aa72 100644
--- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
@@ -39,6 +39,7 @@
 #include "core/inspector/ConsoleMessage.h"
 #include "core/loader/FrameLoadRequest.h"
 #include "core/loader/ThreadableLoadingContext.h"
+#include "core/loader/WorkerFetchContext.h"
 #include "core/probe/CoreProbes.h"
 #include "core/workers/ParentFrameTaskRunners.h"
 #include "core/workers/WorkerClients.h"
@@ -51,6 +52,7 @@
 #include "modules/serviceworkers/ServiceWorkerContainerClient.h"
 #include "modules/serviceworkers/ServiceWorkerThread.h"
 #include "platform/Histogram.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/SharedBuffer.h"
 #include "platform/heap/Handle.h"
 #include "platform/loader/fetch/SubstituteData.h"
@@ -62,6 +64,7 @@
 #include "platform/wtf/PtrUtil.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebURLRequest.h"
+#include "public/platform/WebWorkerFetchContext.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerProvider.h"
 #include "public/web/WebConsoleMessage.h"
@@ -419,6 +422,17 @@
       worker_clients,
       WTF::WrapUnique(worker_context_client_->CreateServiceWorkerProvider()));
 
+  if (RuntimeEnabledFeatures::offMainThreadFetchEnabled()) {
+    std::unique_ptr<WebWorkerFetchContext> web_worker_fetch_context =
+
+        worker_context_client_->CreateServiceWorkerFetchContext();
+    DCHECK(web_worker_fetch_context);
+    // TODO(horo): Set more information about the context (ex: DataSaverEnabled)
+    // to |web_worker_fetch_context|.
+    ProvideWorkerFetchContextToWorker(worker_clients,
+                                      std::move(web_worker_fetch_context));
+  }
+
   // We need to set the CSP to both the shadow page's document and the
   // ServiceWorkerGlobalScope.
   document->InitContentSecurityPolicy(
diff --git a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp
index ff366f0..3ee95df 100644
--- a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp
+++ b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp
@@ -202,6 +202,10 @@
   RuntimeEnabledFeatures::setNetworkInformationEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableOffMainThreadFetch(bool enable) {
+  RuntimeEnabledFeatures::setOffMainThreadFetchEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnableOnDeviceChange(bool enable) {
   RuntimeEnabledFeatures::setOnDeviceChangeEnabled(enable);
 }
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
index df1c8555..02e2ad20 100644
--- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
@@ -38,6 +38,7 @@
 #include "core/loader/FrameLoadRequest.h"
 #include "core/loader/FrameLoader.h"
 #include "core/loader/ThreadableLoadingContext.h"
+#include "core/loader/WorkerFetchContext.h"
 #include "core/probe/CoreProbes.h"
 #include "core/workers/ParentFrameTaskRunners.h"
 #include "core/workers/SharedWorkerGlobalScope.h"
@@ -50,6 +51,7 @@
 #include "core/workers/WorkerScriptLoader.h"
 #include "core/workers/WorkerThreadStartupData.h"
 #include "platform/CrossThreadFunctional.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/heap/Handle.h"
 #include "platform/heap/Persistent.h"
 #include "platform/loader/fetch/ResourceResponse.h"
@@ -63,6 +65,7 @@
 #include "public/platform/WebString.h"
 #include "public/platform/WebURL.h"
 #include "public/platform/WebURLRequest.h"
+#include "public/platform/WebWorkerFetchContext.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h"
 #include "public/web/WebDevToolsAgent.h"
 #include "public/web/WebFrame.h"
@@ -327,6 +330,20 @@
           web_security_origin)));
   ProvideIndexedDBClientToWorker(worker_clients,
                                  IndexedDBClientImpl::Create(*worker_clients));
+
+  if (RuntimeEnabledFeatures::offMainThreadFetchEnabled()) {
+    std::unique_ptr<WebWorkerFetchContext> web_worker_fetch_context =
+        client_->CreateWorkerFetchContext(
+            WebLocalFrameImpl::FromFrame(main_frame_->GetFrame())
+                ->DataSource()
+                ->GetServiceWorkerNetworkProvider());
+    DCHECK(web_worker_fetch_context);
+    // TODO(horo): Set more information about the context (ex: DataSaverEnabled)
+    // to |web_worker_fetch_context|.
+    ProvideWorkerFetchContextToWorker(worker_clients,
+                                      std::move(web_worker_fetch_context));
+  }
+
   ContentSecurityPolicy* content_security_policy =
       main_script_loader_->ReleaseContentSecurityPolicy();
   WorkerThreadStartMode start_mode =
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index 172531f6..742bd7bd 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -342,6 +342,7 @@
     "platform/WebVector.h",
     "platform/WebViewScheduler.h",
     "platform/WebViewportStyle.h",
+    "platform/WebWorkerFetchContext.h",
     "platform/callback/WebClosure.h",
     "platform/linux/WebFallbackFont.h",
     "platform/linux/WebFontRenderStyle.h",
diff --git a/third_party/WebKit/public/platform/WebWorkerFetchContext.h b/third_party/WebKit/public/platform/WebWorkerFetchContext.h
new file mode 100644
index 0000000..d453fde
--- /dev/null
+++ b/third_party/WebKit/public/platform/WebWorkerFetchContext.h
@@ -0,0 +1,43 @@
+// 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.
+
+#ifndef WebWorkerFetchContext_h
+#define WebWorkerFetchContext_h
+
+namespace base {
+class SingleThreadTaskRunner;
+}  // namespace base
+
+namespace blink {
+
+class WebURLLoader;
+class WebURLRequest;
+
+// WebWorkerFetchContext is a per-worker object created on the main thread,
+// passed to a worker (dedicated, shared and service worker) and initialized on
+// the worker thread by InitializeOnWorkerThread(). It contains information
+// about the resource fetching context (ex: service worker provider id), and is
+// used to create a new WebURLLoader instance in the worker thread.
+class WebWorkerFetchContext {
+ public:
+  virtual ~WebWorkerFetchContext() {}
+
+  virtual void InitializeOnWorkerThread(base::SingleThreadTaskRunner*) = 0;
+
+  // Returns a new WebURLLoader instance which is associated with the worker
+  // thread.
+  virtual std::unique_ptr<WebURLLoader> CreateURLLoader() = 0;
+
+  // Called when a request is about to be sent out to modify the request to
+  // handle the request correctly in the loading stack later. (Example: service
+  // worker)
+  virtual void WillSendRequest(WebURLRequest&) = 0;
+
+  // Whether the fetch context is controlled by a service worker.
+  virtual bool IsControlledByServiceWorker() const = 0;
+};
+
+}  // namespace blink
+
+#endif  // WebWorkerFetchContext_h
diff --git a/third_party/WebKit/public/platform/modules/media_capabilities/WebAudioConfiguration.h b/third_party/WebKit/public/platform/modules/media_capabilities/WebAudioConfiguration.h
index 12959b3..cae7da40 100644
--- a/third_party/WebKit/public/platform/modules/media_capabilities/WebAudioConfiguration.h
+++ b/third_party/WebKit/public/platform/modules/media_capabilities/WebAudioConfiguration.h
@@ -14,7 +14,8 @@
 // It is created by Blink and passed to consumers that can assume that all
 // required fields are properly set.
 struct WebAudioConfiguration {
-  WebString content_type;
+  WebString mime_type;
+  WebString codec;
 
   // `channels` is Optional too but it will be reflected with `isNull()`.
   WebString channels;
diff --git a/third_party/WebKit/public/platform/modules/media_capabilities/WebVideoConfiguration.h b/third_party/WebKit/public/platform/modules/media_capabilities/WebVideoConfiguration.h
index a65ed26..5b1d1501 100644
--- a/third_party/WebKit/public/platform/modules/media_capabilities/WebVideoConfiguration.h
+++ b/third_party/WebKit/public/platform/modules/media_capabilities/WebVideoConfiguration.h
@@ -13,7 +13,8 @@
 // It is created by Blink and passed to consumers that can assume that all
 // required fields are properly set.
 struct WebVideoConfiguration {
-  WebString content_type;
+  WebString mime_type;
+  WebString codec;
   unsigned width;
   unsigned height;
   unsigned bitrate;
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h
index 7e9100da..0f1458a 100644
--- a/third_party/WebKit/public/web/WebFrameClient.h
+++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -65,6 +65,7 @@
 #include "public/platform/WebStorageQuotaType.h"
 #include "public/platform/WebURLError.h"
 #include "public/platform/WebURLRequest.h"
+#include "public/platform/WebWorkerFetchContext.h"
 #include "v8/include/v8.h"
 
 namespace blink {
@@ -146,6 +147,13 @@
     return 0;
   }
 
+  // Returns a new WebWorkerFetchContext for a dedicated worker. Ownership of
+  // the returned object is transferred to the caller. This is used only when
+  // off-main-thread-fetch is enabled.
+  virtual std::unique_ptr<WebWorkerFetchContext> CreateWorkerFetchContext() {
+    return nullptr;
+  }
+
   // Create a new WebPopupMenu. In the "createExternalPopupMenu" form, the
   // client is responsible for rendering the contents of the popup menu.
   virtual WebExternalPopupMenu* CreateExternalPopupMenu(
diff --git a/third_party/WebKit/public/web/WebRuntimeFeatures.h b/third_party/WebKit/public/web/WebRuntimeFeatures.h
index 07b76a3..2144839a 100644
--- a/third_party/WebKit/public/web/WebRuntimeFeatures.h
+++ b/third_party/WebKit/public/web/WebRuntimeFeatures.h
@@ -98,6 +98,7 @@
   BLINK_EXPORT static void EnableNotificationConstructor(bool);
   BLINK_EXPORT static void EnableNotificationContentImage(bool);
   BLINK_EXPORT static void EnableNotifications(bool);
+  BLINK_EXPORT static void EnableOffMainThreadFetch(bool);
   BLINK_EXPORT static void EnableOnDeviceChange(bool);
   BLINK_EXPORT static void EnableOrientationEvent(bool);
   BLINK_EXPORT static void EnableOverlayScrollbars(bool);
diff --git a/third_party/WebKit/public/web/WebSharedWorkerClient.h b/third_party/WebKit/public/web/WebSharedWorkerClient.h
index 46f8cf1d1..93ac90f 100644
--- a/third_party/WebKit/public/web/WebSharedWorkerClient.h
+++ b/third_party/WebKit/public/web/WebSharedWorkerClient.h
@@ -32,6 +32,7 @@
 #define WebSharedWorkerClient_h
 
 #include "public/platform/WebMessagePortChannel.h"
+#include "public/platform/WebWorkerFetchContext.h"
 #include "public/web/WebDevToolsAgentClient.h"
 
 namespace blink {
@@ -93,6 +94,14 @@
   CreateDevToolsMessageLoop() {
     return nullptr;
   }
+
+  // Returns a new WebWorkerFetchContext for the shared worker. Ownership of the
+  // returned object is transferred to the caller. This is used only when
+  // off-main-thread-fetch is enabled.
+  virtual std::unique_ptr<WebWorkerFetchContext> CreateWorkerFetchContext(
+      WebServiceWorkerNetworkProvider*) {
+    return nullptr;
+  }
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
index 63062cf..90bc12b 100644
--- a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
+++ b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
@@ -35,6 +35,7 @@
 
 #include "public/platform/WebMessagePortChannel.h"
 #include "public/platform/WebURL.h"
+#include "public/platform/WebWorkerFetchContext.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerClientsClaimCallbacks.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerClientsInfo.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerEventResult.h"
@@ -244,6 +245,14 @@
     return nullptr;
   }
 
+  // Creates a WebWorkerFetchContext for a service worker. Ownership of the
+  // returned object is transferred to the caller. This is called on the main
+  // thread. This is used only when off-main-thread-fetch is enabled.
+  virtual std::unique_ptr<blink::WebWorkerFetchContext>
+  CreateServiceWorkerFetchContext() {
+    return nullptr;
+  }
+
   // Ownership of the returned object is transferred to the caller.
   // This is called on the main thread.
   virtual WebServiceWorkerProvider* CreateServiceWorkerProvider() {
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index d19d7b15..4dc3617 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -56287,6 +56287,9 @@
 </histogram>
 
 <histogram name="PurgeAndSuspend.Memory.BlinkGCKB" units="KB">
+  <obsolete>
+    Deprecated April 2017.
+  </obsolete>
   <owner>tasak@google.com</owner>
   <summary>
     The memory usage of the BlinkGC allocator after a background renderer is
@@ -56295,6 +56298,9 @@
 </histogram>
 
 <histogram name="PurgeAndSuspend.Memory.DiscardableKB" units="KB">
+  <obsolete>
+    Deprecated April 2017.
+  </obsolete>
   <owner>tasak@google.com</owner>
   <summary>
     The memory usage of the discardable memory after a background renderer is
@@ -56303,6 +56309,9 @@
 </histogram>
 
 <histogram name="PurgeAndSuspend.Memory.MallocMB" units="MB">
+  <obsolete>
+    Deprecated April 2017.
+  </obsolete>
   <owner>tasak@google.com</owner>
   <summary>
     The memory usage of the malloc after a background renderer is purged and
@@ -56311,6 +56320,9 @@
 </histogram>
 
 <histogram name="PurgeAndSuspend.Memory.PartitionAllocKB" units="KB">
+  <obsolete>
+    Deprecated April 2017.
+  </obsolete>
   <owner>tasak@google.com</owner>
   <summary>
     The memory usage of PartitionAlloc after a background renderer is purged and
@@ -56319,6 +56331,9 @@
 </histogram>
 
 <histogram name="PurgeAndSuspend.Memory.TotalAllocatedMB" units="MB">
+  <obsolete>
+    Deprecated April 2017.
+  </obsolete>
   <owner>tasak@google.com</owner>
   <summary>
     The sum of the memory usages of PartitionAlloc, malloc, discardable memory,
@@ -56328,6 +56343,9 @@
 </histogram>
 
 <histogram name="PurgeAndSuspend.Memory.V8MainThreadIsolateMB" units="MB">
+  <obsolete>
+    Deprecated April 2017.
+  </obsolete>
   <owner>tasak@google.com</owner>
   <summary>
     The memory usage of mainThreadIsolate() after a backgrounded renderer is
@@ -89702,6 +89720,14 @@
   <int value="16" label="Conflicting Module"/>
   <int value="17" label="Critical Notification (Upgrade Installed)"/>
   <int value="18" label="IME Warning (Activation)"/>
+  <int value="19" label="Toolbar Actions Bar"/>
+  <int value="20" label="Global Error"/>
+  <int value="21" label="Extension Install"/>
+  <int value="22" label="Extension Uninstall"/>
+  <int value="23" label="Extension Installed (Sideloaded)"/>
+  <int value="24" label="Payment Request"/>
+  <int value="25" label="Save Card"/>
+  <int value="26" label="Card Unmask"/>
 </enum>
 
 <enum name="DifferentPrimaryAccounts" type="int">
@@ -97301,6 +97327,8 @@
   <int value="1965" label="GamepadButtons"/>
   <int value="1966" label="VibrateWithoutUserGesture"/>
   <int value="1967" label="DispatchMouseEventOnDisabledFormControl"/>
+  <int value="1968" label="ElementNameDOMInvalidHTMLParserValid"/>
+  <int value="1969" label="ElementNameDOMValidHTMLParserInvalid"/>
 </enum>
 
 <enum name="FetchRequestMode" type="int">