diff --git a/DEPS b/DEPS
index 09ff1ec..026d04b 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '4ef01482025e2e629e35458aa214436d3b4138e8',
+  'skia_revision': 'ce425510a07632f14b7b779ec3864f719cb4326b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'e43ea3f67b99e1c715c7ab2e02864612ea64f8a9',
+  'v8_revision': '691effc377ebae3e8a2c2391913befeda0619d52',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -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': '5bcd9a32232e8cd5df918104eb131be76f833701',
+  'pdfium_revision': '3ae3033bff2582029984f91f40f4a8b748a30c96',
   # 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.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'f76a7183f0bf2130ff891b857208421e7f00dbd6',
+  'catapult_revision': 'f410d46fe0f63a221c8099698bb798a245f2a9c0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/android_webview/glue/BUILD.gn b/android_webview/glue/BUILD.gn
index ab52954..25fb8b4a 100644
--- a/android_webview/glue/BUILD.gn
+++ b/android_webview/glue/BUILD.gn
@@ -78,5 +78,6 @@
     "java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java",
     "java/src/com/android/webview/chromium/WebViewDatabaseAdapter.java",
     "java/src/com/android/webview/chromium/WebViewDelegateFactory.java",
+    "java/src/com/android/webview/chromium/reflection/WebViewConfig.java",
   ]
 }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/reflection/WebViewConfig.java b/android_webview/glue/java/src/com/android/webview/chromium/reflection/WebViewConfig.java
new file mode 100644
index 0000000..f2445237
--- /dev/null
+++ b/android_webview/glue/java/src/com/android/webview/chromium/reflection/WebViewConfig.java
@@ -0,0 +1,22 @@
+// 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 com.android.webview.chromium.reflection;
+
+import org.chromium.android_webview.AwContentsStatics;
+import org.chromium.base.annotations.UsedByReflection;
+
+/**
+ * Entry points for reflection into Android WebView internals for static configuration.
+ *
+ * Methods in this class may be removed, but they should not be changed in any incompatible way.
+ * Methods should be removed when we no longer wish to expose the functionality.
+ */
+@UsedByReflection("")
+public class WebViewConfig {
+    @UsedByReflection("")
+    public static void disableSafeBrowsing() {
+        AwContentsStatics.setSafeBrowsingEnabled(false);
+    }
+}
diff --git a/base/BUILD.gn b/base/BUILD.gn
index fd1fe2c..48243ce 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1196,7 +1196,6 @@
       "process/internal_linux.cc",
       "process/memory_linux.cc",
       "process/process_handle_linux.cc",
-      "process/process_info_linux.cc",
       "process/process_iterator_linux.cc",
       "process/process_metrics_linux.cc",
       "sys_info_linux.cc",
@@ -2055,7 +2054,6 @@
     "process/memory_unittest.cc",
     "process/memory_unittest_mac.h",
     "process/memory_unittest_mac.mm",
-    "process/process_info_unittest.cc",
     "process/process_metrics_unittest.cc",
     "process/process_metrics_unittest_ios.cc",
     "process/process_unittest.cc",
diff --git a/base/OWNERS b/base/OWNERS
index 0e7d010..28043c42 100644
--- a/base/OWNERS
+++ b/base/OWNERS
@@ -36,11 +36,6 @@
 per-file feature_list*=asvitkine@chromium.org
 per-file feature_list*=isherman@chromium.org
 
-# For bot infrastructure:
-per-file *.isolate=maruel@chromium.org
-per-file *.isolate=tandrii@chromium.org
-per-file *.isolate=vadimsh@chromium.org
-
 # For TCMalloc tests:
 per-file security_unittest.cc=jln@chromium.org
 
diff --git a/base/process/process_info_linux.cc b/base/process/process_info_linux.cc
index 2f22748..7cec8f4e 100644
--- a/base/process/process_info_linux.cc
+++ b/base/process/process_info_linux.cc
@@ -17,12 +17,10 @@
 const Time CurrentProcessInfo::CreationTime() {
   int64_t start_ticks =
       internal::ReadProcSelfStatsAndGetFieldAsInt64(internal::VM_STARTTIME);
-  if (!start_ticks)
-    return Time();
+  DCHECK(start_ticks);
   TimeDelta start_offset = internal::ClockTicksToTimeDelta(start_ticks);
   Time boot_time = internal::GetBootTime();
-  if (boot_time.is_null())
-    return Time();
+  DCHECK(!boot_time.is_null());
   return Time(boot_time + start_offset);
 }
 
diff --git a/base/process/process_info_unittest.cc b/base/process/process_info_unittest.cc
deleted file mode 100644
index a757774..0000000
--- a/base/process/process_info_unittest.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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 "base/process/process_info.h"
-
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-#if !defined(OS_IOS)
-TEST(ProcessInfoTest, CreationTime) {
-  Time creation_time = CurrentProcessInfo::CreationTime();
-  ASSERT_FALSE(creation_time.is_null());
-}
-#endif  // !defined(OS_IOS)
-
-}  // namespace base
diff --git a/base/synchronization/waitable_event.h b/base/synchronization/waitable_event.h
index 761965f0..e8caffe 100644
--- a/base/synchronization/waitable_event.h
+++ b/base/synchronization/waitable_event.h
@@ -112,6 +112,9 @@
   // You MUST NOT delete any of the WaitableEvent objects while this wait is
   // happening, however WaitMany's return "happens after" the |Signal| call
   // that caused it has completed, like |Wait|.
+  //
+  // If more than one WaitableEvent is signaled to unblock WaitMany, the lowest
+  // index among them is returned.
   static size_t WaitMany(WaitableEvent** waitables, size_t count);
 
   // For asynchronous waiting, see WaitableEventWatcher
diff --git a/base/synchronization/waitable_event_posix.cc b/base/synchronization/waitable_event_posix.cc
index 5dfff46..846fa067 100644
--- a/base/synchronization/waitable_event_posix.cc
+++ b/base/synchronization/waitable_event_posix.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 
 #include <algorithm>
+#include <limits>
 #include <vector>
 
 #include "base/debug/activity_tracker.h"
@@ -266,12 +267,10 @@
   SyncWaiter sw;
 
   const size_t r = EnqueueMany(&waitables[0], count, &sw);
-  if (r) {
+  if (r < count) {
     // One of the events is already signaled. The SyncWaiter has not been
-    // enqueued anywhere. EnqueueMany returns the count of remaining waitables
-    // when the signaled one was seen, so the index of the signaled event is
-    // @count - @r.
-    return waitables[count - r].second;
+    // enqueued anywhere.
+    return waitables[r].second;
   }
 
   // At this point, we hold the locks on all the WaitableEvents and we have
@@ -319,38 +318,50 @@
 }
 
 // -----------------------------------------------------------------------------
-// If return value == 0:
+// If return value == count:
 //   The locks of the WaitableEvents have been taken in order and the Waiter has
 //   been enqueued in the wait-list of each. None of the WaitableEvents are
 //   currently signaled
 // else:
 //   None of the WaitableEvent locks are held. The Waiter has not been enqueued
-//   in any of them and the return value is the index of the first WaitableEvent
-//   which was signaled, from the end of the array.
+//   in any of them and the return value is the index of the WaitableEvent which
+//   was signaled with the lowest input index from the original WaitMany call.
 // -----------------------------------------------------------------------------
 // static
-size_t WaitableEvent::EnqueueMany
-    (std::pair<WaitableEvent*, size_t>* waitables,
-     size_t count, Waiter* waiter) {
-  if (!count)
-    return 0;
-
-  waitables[0].first->kernel_->lock_.Acquire();
-    if (waitables[0].first->kernel_->signaled_) {
-      if (!waitables[0].first->kernel_->manual_reset_)
-        waitables[0].first->kernel_->signaled_ = false;
-      waitables[0].first->kernel_->lock_.Release();
-      return count;
+size_t WaitableEvent::EnqueueMany(std::pair<WaitableEvent*, size_t>* waitables,
+                                  size_t count,
+                                  Waiter* waiter) {
+  size_t winner = count;
+  size_t winner_index = count;
+  for (size_t i = 0; i < count; ++i) {
+    auto& kernel = waitables[i].first->kernel_;
+    kernel->lock_.Acquire();
+    if (kernel->signaled_ && waitables[i].second < winner) {
+      winner = waitables[i].second;
+      winner_index = i;
     }
+  }
 
-    const size_t r = EnqueueMany(waitables + 1, count - 1, waiter);
-    if (r) {
-      waitables[0].first->kernel_->lock_.Release();
-    } else {
-      waitables[0].first->Enqueue(waiter);
+  // No events signaled. All locks acquired. Enqueue the Waiter on all of them
+  // and return.
+  if (winner == count) {
+    for (size_t i = 0; i < count; ++i)
+      waitables[i].first->Enqueue(waiter);
+    return count;
+  }
+
+  // Unlock in reverse order and possibly clear the chosen winner's signal
+  // before returning its index.
+  for (auto* w = waitables + count - 1; w >= waitables; --w) {
+    auto& kernel = w->first->kernel_;
+    if (w->second == winner) {
+      if (!kernel->manual_reset_)
+        kernel->signaled_ = false;
     }
+    kernel->lock_.Release();
+  }
 
-    return r;
+  return winner_index;
 }
 
 // -----------------------------------------------------------------------------
diff --git a/base/synchronization/waitable_event_unittest.cc b/base/synchronization/waitable_event_unittest.cc
index c0e280aa..3aa1af16 100644
--- a/base/synchronization/waitable_event_unittest.cc
+++ b/base/synchronization/waitable_event_unittest.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include <algorithm>
+
 #include "base/compiler_specific.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
@@ -78,6 +80,42 @@
     delete ev[i];
 }
 
+TEST(WaitableEventTest, WaitManyLeftToRight) {
+  WaitableEvent* ev[5];
+  for (size_t i = 0; i < 5; ++i) {
+    ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
+                              WaitableEvent::InitialState::NOT_SIGNALED);
+  }
+
+  // Test for consistent left-to-right return behavior across all permutations
+  // of the input array. This is to verify that only the indices -- and not
+  // the WaitableEvents' addresses -- are relevant in determining who wins when
+  // multiple events are signaled.
+
+  std::sort(ev, ev + 5);
+  do {
+    ev[0]->Signal();
+    ev[1]->Signal();
+    EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
+
+    ev[2]->Signal();
+    EXPECT_EQ(1u, WaitableEvent::WaitMany(ev, 5));
+    EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
+
+    ev[3]->Signal();
+    ev[4]->Signal();
+    ev[0]->Signal();
+    EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
+    EXPECT_EQ(3u, WaitableEvent::WaitMany(ev, 5));
+    ev[2]->Signal();
+    EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
+    EXPECT_EQ(4u, WaitableEvent::WaitMany(ev, 5));
+  } while (std::next_permutation(ev, ev + 5));
+
+  for (size_t i = 0; i < 5; ++i)
+    delete ev[i];
+}
+
 class WaitableEventSignaler : public PlatformThread::Delegate {
  public:
   WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
diff --git a/base/sys_info.h b/base/sys_info.h
index ecaa731..18bdaf0 100644
--- a/base/sys_info.h
+++ b/base/sys_info.h
@@ -80,8 +80,6 @@
   static std::string OperatingSystemVersion();
 
   // Retrieves detailed numeric values for the OS version.
-  // TODO(port): Implement a Linux version of this method and enable the
-  // corresponding unit test.
   // DON'T USE THIS ON THE MAC OR WINDOWS to determine the current OS release
   // for OS version-specific feature checks and workarounds. If you must use
   // an OS version check instead of a feature check, use the base::mac::IsOS*
diff --git a/base/sys_info_posix.cc b/base/sys_info_posix.cc
index f480055cc..c4c07d0 100644
--- a/base/sys_info_posix.cc
+++ b/base/sys_info_posix.cc
@@ -183,6 +183,30 @@
 }
 #endif
 
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+// static
+void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
+                                            int32_t* minor_version,
+                                            int32_t* bugfix_version) {
+  struct utsname info;
+  if (uname(&info) < 0) {
+    NOTREACHED();
+    *major_version = 0;
+    *minor_version = 0;
+    *bugfix_version = 0;
+    return;
+  }
+  int num_read = sscanf(info.release, "%d.%d.%d", major_version, minor_version,
+                        bugfix_version);
+  if (num_read < 1)
+    *major_version = 0;
+  if (num_read < 2)
+    *minor_version = 0;
+  if (num_read < 3)
+    *bugfix_version = 0;
+}
+#endif
+
 // static
 std::string SysInfo::OperatingSystemArchitecture() {
   struct utsname info;
diff --git a/base/sys_info_unittest.cc b/base/sys_info_unittest.cc
index e80884b9..94b5a84 100644
--- a/base/sys_info_unittest.cc
+++ b/base/sys_info_unittest.cc
@@ -71,7 +71,7 @@
   EXPECT_GT(SysInfo::AmountOfTotalDiskSpace(tmp_path), 0) << tmp_path.value();
 }
 
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
 TEST_F(SysInfoTest, OperatingSystemVersionNumbers) {
   int32_t os_major_version = -1;
   int32_t os_minor_version = -1;
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index 4c03aeb..6dddb94 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -19,7 +19,6 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/singleton.h"
 #include "base/message_loop/message_loop.h"
-#include "base/process/process_info.h"
 #include "base/process/process_metrics.h"
 #include "base/stl_util.h"
 #include "base/strings/string_split.h"
@@ -1501,16 +1500,6 @@
                             process_name_);
   }
 
-#if !defined(OS_NACL) && !defined(OS_IOS)
-  Time process_creation_time = CurrentProcessInfo::CreationTime();
-  if (!process_creation_time.is_null()) {
-    TimeDelta process_uptime = Time::Now() - process_creation_time;
-    InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
-                            current_thread_id, "process_uptime_seconds",
-                            "uptime", process_uptime.InSeconds());
-  }
-#endif  // !defined(OS_NACL) && !defined(OS_IOS)
-
   if (!process_labels_.empty()) {
     std::vector<std::string> labels;
     for (const auto& it : process_labels_)
diff --git a/breakpad/OWNERS b/breakpad/OWNERS
index c88bdbe2..0e8489a 100644
--- a/breakpad/OWNERS
+++ b/breakpad/OWNERS
@@ -1,8 +1,4 @@
 mark@chromium.org
 thestig@chromium.org
 
-per-file *.isolate=maruel@chromium.org
-per-file *.isolate=tandrii@chromium.org
-per-file *.isolate=vadimsh@chromium.org
-
 # TEAM: google-breakpad-dev@googlegroups.com
diff --git a/cc/OWNERS b/cc/OWNERS
index cbba2c2b..5a30b139 100644
--- a/cc/OWNERS
+++ b/cc/OWNERS
@@ -57,9 +57,5 @@
 # nduca@chromium.org
 # mithro@mithis.com / tansell@chromium.org
 
-per-file *.isolate=maruel@chromium.org
-per-file *.isolate=tandrii@chromium.org
-per-file *.isolate=vadimsh@chromium.org
-
 # TEAM: graphics-dev@chromium.org
 # COMPONENT: Internals>Compositing
diff --git a/cc/paint/paint_canvas.h b/cc/paint/paint_canvas.h
index 733273d..cd00cdc6 100644
--- a/cc/paint/paint_canvas.h
+++ b/cc/paint/paint_canvas.h
@@ -34,7 +34,6 @@
   virtual void flush() = 0;
 
   virtual SkISize getBaseLayerSize() const = 0;
-  virtual bool peekPixels(SkPixmap* pixmap) = 0;
   virtual bool readPixels(const SkImageInfo& dest_info,
                           void* dest_pixels,
                           size_t dest_row_bytes,
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc
index 41ff72367..0421d89 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -23,6 +23,7 @@
                                  const SkSurfaceProps& props)
     : canvas_(new SkCanvas(bitmap, props)), owned_(canvas_) {}
 
+SkiaPaintCanvas::SkiaPaintCanvas(SkiaPaintCanvas&& other) = default;
 SkiaPaintCanvas::~SkiaPaintCanvas() = default;
 
 SkMetaData& SkiaPaintCanvas::getMetaData() {
@@ -41,10 +42,6 @@
   return canvas_->getBaseLayerSize();
 }
 
-bool SkiaPaintCanvas::peekPixels(SkPixmap* pixmap) {
-  return canvas_->peekPixels(pixmap);
-}
-
 bool SkiaPaintCanvas::readPixels(const SkImageInfo& dest_info,
                                  void* dest_pixels,
                                  size_t dest_row_bytes,
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h
index 0a0974b..979efdf 100644
--- a/cc/paint/skia_paint_canvas.h
+++ b/cc/paint/skia_paint_canvas.h
@@ -28,15 +28,17 @@
   explicit SkiaPaintCanvas(SkCanvas* canvas);
   explicit SkiaPaintCanvas(const SkBitmap& bitmap);
   explicit SkiaPaintCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
+  explicit SkiaPaintCanvas(SkiaPaintCanvas&& other);
   ~SkiaPaintCanvas() override;
 
+  SkiaPaintCanvas& operator=(SkiaPaintCanvas&& other) = default;
+
   SkMetaData& getMetaData() override;
   SkImageInfo imageInfo() const override;
 
   void flush() override;
 
   SkISize getBaseLayerSize() const override;
-  bool peekPixels(SkPixmap* pixmap) override;
   bool readPixels(const SkImageInfo& dest_info,
                   void* dest_pixels,
                   size_t dest_row_bytes,
@@ -163,6 +165,8 @@
  private:
   SkCanvas* canvas_;
   std::unique_ptr<SkCanvas> owned_;
+
+  DISALLOW_COPY_AND_ASSIGN(SkiaPaintCanvas);
 };
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 4ef536f..26884a55 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1521,11 +1521,9 @@
 
 bool LayerTreeImpl::DistributeRootScrollOffset(
     const gfx::ScrollOffset& root_offset) {
-  if (!InnerViewportScrollLayer())
+  if (!InnerViewportScrollLayer() || !OuterViewportScrollLayer())
     return false;
 
-  DCHECK(OuterViewportScrollLayer());
-
   // If we get here, we have both inner/outer viewports, and need to distribute
   // the scroll offset between them.
   gfx::ScrollOffset inner_viewport_offset =
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml
index 89936ce..9e598e4 100644
--- a/chrome/android/java/res/values-v17/styles.xml
+++ b/chrome/android/java/res/values-v17/styles.xml
@@ -431,14 +431,6 @@
         <item name="android:textSize">14sp</item>
     </style>
 
-    <!-- Signin promo dialog-->
-    <style name="SigninPromoDialog" parent="FullscreenWhite">
-        <item name="android:windowFrame">@null</item>
-        <item name="android:windowIsFloating">true</item>
-        <item name="android:windowContentOverlay">@null</item>
-        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
-    </style>
-
     <!-- Contextual Search styles -->
     <style name="ContextualSearchTextViewLayout">
         <item name="android:layout_width">match_parent</item>
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index 241c4ae..c310353e 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -27,7 +27,8 @@
     <color name="google_grey_600">#757575</color>
     <color name="google_grey_700">#616161</color>
     <color name="toolbar_shadow_color">#1d000000</color>
-    <color name="semi_opaque_white">#80ffffff</color>
+    <color name="white_alpha_50">#80ffffff</color>
+    <color name="black_alpha_40">#66000000</color>
     <color name="toolbar_light_tint">#A3000000</color>
     <color name="light_grey">#ccc</color>
     <color name="modal_dialog_scrim_color">#7f000000</color>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
index c8aeceb8..467f1a61 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
@@ -247,12 +247,6 @@
         startMarginAnimation(false);
         startYOffsetAnimation(false);
         finishScrollStacks();
-
-        // TODO(twellington): Add a proper tab selection animation rather than disabling the current
-        //                    animation.
-        if (FeatureUtilities.isChromeHomeEnabled()) {
-            onUpdateAnimation(System.currentTimeMillis(), true);
-        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
index e72367c3..b10b915 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
@@ -1956,7 +1956,7 @@
             if (tab.getId() == tabId) {
                 tab.setDiscardAmount(getDiscardRange());
                 tab.setDying(false);
-                tab.getLayoutTab().setMaxContentHeight(mLayout.getHeightMinusBrowserControls());
+                tab.getLayoutTab().setMaxContentHeight(getMaxTabHeight());
             }
         }
 
@@ -2269,6 +2269,16 @@
     }
 
     /**
+     * @return The maximum height of a layout tab in the tab switcher.
+     */
+    public float getMaxTabHeight() {
+        if (FeatureUtilities.isChromeHomeEnabled() && mCurrentMode == Orientation.PORTRAIT) {
+            return mLayout.getHeight();
+        }
+        return mLayout.getHeightMinusBrowserControls();
+    }
+
+    /**
      * Computes the scale of the tab based on its discard status.
      *
      * @param amount    The discard amount.
@@ -2302,19 +2312,18 @@
         mDiscardDirection = getDefaultDiscardDirection();
         setWarpState(true, false);
         final float opaqueTopPadding = mBorderTopPadding - mBorderTransparentTop;
-        mAnimationFactory = StackAnimation.createAnimationFactory(mLayout.getWidth(),
+        mAnimationFactory = StackAnimation.createAnimationFactory(this, mLayout.getWidth(),
                 mLayout.getHeight(), mLayout.getHeightMinusBrowserControls(), mBorderTopPadding,
                 opaqueTopPadding, mBorderLeftPadding, mCurrentMode);
         float dpToPx = mLayout.getContext().getResources().getDisplayMetrics().density;
         mViewAnimationFactory = new StackViewAnimation(dpToPx, mLayout.getWidth());
         if (mStackTabs == null) return;
         float width = mLayout.getWidth();
-        float height = mLayout.getHeightMinusBrowserControls();
         for (int i = 0; i < mStackTabs.length; i++) {
             LayoutTab tab = mStackTabs[i].getLayoutTab();
             if (tab == null) continue;
             tab.setMaxContentWidth(width);
-            tab.setMaxContentHeight(height);
+            tab.setMaxContentHeight(getMaxTabHeight());
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java
index 9c923c69..acae0fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java
@@ -80,10 +80,12 @@
     protected final float mBorderTopHeight;
     protected final float mBorderTopOpaqueHeight;
     protected final float mBorderLeftWidth;
+    protected final Stack mStack;
 
     /**
      * Protected constructor.
      *
+     * @param stack                       The stack using the animations provided by this class.
      * @param width                       The width of the layout in dp.
      * @param height                      The height of the layout in dp.
      * @param heightMinusBrowserControls  The height of the layout minus the browser controls in dp.
@@ -91,9 +93,10 @@
      * @param borderFramePaddingTopOpaque The opaque top padding of the border frame in dp.
      * @param borderFramePaddingLeft      The left padding of the border frame in dp.
      */
-    protected StackAnimation(float width, float height, float heightMinusBrowserControls,
-            float borderFramePaddingTop, float borderFramePaddingTopOpaque,
-            float borderFramePaddingLeft) {
+    protected StackAnimation(Stack stack, float width, float height,
+            float heightMinusBrowserControls, float borderFramePaddingTop,
+            float borderFramePaddingTopOpaque, float borderFramePaddingLeft) {
+        mStack = stack;
         mWidth = width;
         mHeight = height;
         mHeightMinusBrowserControls = heightMinusBrowserControls;
@@ -107,6 +110,7 @@
      * The factory method that creates the particular factory method based on the orientation
      * parameter.
      *
+     * @param stack                       The stack of tabs being animated.
      * @param width                       The width of the layout in dp.
      * @param height                      The height of the layout in dp.
      * @param heightMinusBrowserControls  The height of the layout minus the browser controls in dp.
@@ -117,19 +121,21 @@
      *                                    appropriate {@link StackAnimation}.
      * @return                            The TabSwitcherAnimationFactory instance.
      */
-    public static StackAnimation createAnimationFactory(float width, float height,
+    public static StackAnimation createAnimationFactory(Stack stack, float width, float height,
             float heightMinusBrowserControls, float borderFramePaddingTop,
             float borderFramePaddingTopOpaque, float borderFramePaddingLeft, int orientation) {
         StackAnimation factory = null;
         switch (orientation) {
             case Orientation.LANDSCAPE:
-                factory = new StackAnimationLandscape(width, height, heightMinusBrowserControls,
-                        borderFramePaddingTop, borderFramePaddingTopOpaque, borderFramePaddingLeft);
+                factory = new StackAnimationLandscape(stack, width, height,
+                        heightMinusBrowserControls, borderFramePaddingTop,
+                        borderFramePaddingTopOpaque, borderFramePaddingLeft);
                 break;
             case Orientation.PORTRAIT:
             default:
-                factory = new StackAnimationPortrait(width, height, heightMinusBrowserControls,
-                        borderFramePaddingTop, borderFramePaddingTopOpaque, borderFramePaddingLeft);
+                factory = new StackAnimationPortrait(stack, width, height,
+                        heightMinusBrowserControls, borderFramePaddingTop,
+                        borderFramePaddingTopOpaque, borderFramePaddingLeft);
                 break;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape.java
index 5beb7cf..5b37de3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape.java
@@ -21,6 +21,7 @@
 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation;
 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable;
 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
+import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.MathUtils;
 import org.chromium.ui.base.LocalizationUtils;
 
@@ -28,10 +29,10 @@
     /**
      * Only Constructor.
      */
-    public StackAnimationLandscape(float width, float height, float heightMinusBrowserControls,
-            float borderFramePaddingTop, float borderFramePaddingTopOpaque,
-            float borderFramePaddingLeft) {
-        super(width, height, heightMinusBrowserControls, borderFramePaddingTop,
+    public StackAnimationLandscape(Stack stack, float width, float height,
+            float heightMinusBrowserControls, float borderFramePaddingTop,
+            float borderFramePaddingTopOpaque, float borderFramePaddingLeft) {
+        super(stack, width, height, heightMinusBrowserControls, borderFramePaddingTop,
                 borderFramePaddingTopOpaque, borderFramePaddingLeft);
     }
 
@@ -54,7 +55,7 @@
 
             addAnimation(set, tab.getLayoutTab(), MAX_CONTENT_HEIGHT,
                     tab.getLayoutTab().getUnclampedOriginalContentHeight(),
-                    mHeightMinusBrowserControls, ENTER_STACK_ANIMATION_DURATION, 0);
+                    mStack.getMaxTabHeight(), ENTER_STACK_ANIMATION_DURATION, 0);
             if (i < focusIndex) {
                 addAnimation(set, tab, SCROLL_OFFSET, initialScrollOffset, scrollOffset,
                         ENTER_STACK_ANIMATION_DURATION, 0);
@@ -128,8 +129,11 @@
                         set, tab, SCALE, tab.getScale(), 1.0f, TAB_FOCUSED_ANIMATION_DURATION, 0);
                 addAnimation(set, tab, X_IN_STACK_INFLUENCE, tab.getXInStackInfluence(), 0.0f,
                         TAB_FOCUSED_ANIMATION_DURATION, 0);
+                int tabYInfluenceDuration = FeatureUtilities.isChromeHomeEnabled()
+                        ? TAB_FOCUSED_ANIMATION_DURATION
+                        : TAB_FOCUSED_Y_STACK_DURATION;
                 addAnimation(set, tab, Y_IN_STACK_INFLUENCE, tab.getYInStackInfluence(), 0.0f,
-                        TAB_FOCUSED_Y_STACK_DURATION, 0);
+                        tabYInfluenceDuration, 0);
 
                 addAnimation(set, tab.getLayoutTab(), MAX_CONTENT_HEIGHT,
                         tab.getLayoutTab().getMaxContentHeight(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationPortrait.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationPortrait.java
index 652db9b..ae454ab 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationPortrait.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationPortrait.java
@@ -20,6 +20,7 @@
 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation;
 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable;
 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
+import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.MathUtils;
 import org.chromium.ui.base.LocalizationUtils;
 
@@ -27,10 +28,10 @@
     /**
      * Only Constructor.
      */
-    public StackAnimationPortrait(float width, float height, float heightMinusBrowserControls,
-            float borderFramePaddingTop, float borderFramePaddingTopOpaque,
-            float borderFramePaddingLeft) {
-        super(width, height, heightMinusBrowserControls, borderFramePaddingTop,
+    public StackAnimationPortrait(Stack stack, float width, float height,
+            float heightMinusBrowserControls, float borderFramePaddingTop,
+            float borderFramePaddingTopOpaque, float borderFramePaddingLeft) {
+        super(stack, width, height, heightMinusBrowserControls, borderFramePaddingTop,
                 borderFramePaddingTopOpaque, borderFramePaddingLeft);
     }
 
@@ -62,11 +63,11 @@
             float scrollOffset = StackTab.screenToScroll(i * spacing, warpSize);
 
             if (i < focusIndex) {
-                tab.getLayoutTab().setMaxContentHeight(mHeightMinusBrowserControls);
+                tab.getLayoutTab().setMaxContentHeight(mStack.getMaxTabHeight());
                 addAnimation(set, tab, SCROLL_OFFSET, initialScrollOffset, scrollOffset,
                         ENTER_STACK_ANIMATION_DURATION, 0);
             } else if (i > focusIndex) {
-                tab.getLayoutTab().setMaxContentHeight(mHeightMinusBrowserControls);
+                tab.getLayoutTab().setMaxContentHeight(mStack.getMaxTabHeight());
                 tab.setScrollOffset(scrollOffset + trailingScrollOffset);
                 addAnimation(
                         set, tab, Y_IN_STACK_OFFSET, mHeight, 0, ENTER_STACK_ANIMATION_DURATION, 0);
@@ -75,7 +76,7 @@
 
                 addAnimation(set, tab.getLayoutTab(), MAX_CONTENT_HEIGHT,
                         tab.getLayoutTab().getUnclampedOriginalContentHeight(),
-                        mHeightMinusBrowserControls, ENTER_STACK_ANIMATION_DURATION,
+                        mStack.getMaxTabHeight(), ENTER_STACK_ANIMATION_DURATION,
                         ENTER_STACK_RESIZE_DELAY);
                 addAnimation(set, tab, Y_IN_STACK_INFLUENCE, 0.0f, 1.0f,
                         ENTER_STACK_BORDER_ALPHA_DURATION, 0);
@@ -136,8 +137,11 @@
                         TAB_FOCUSED_ANIMATION_DURATION, 0);
                 addAnimation(
                         set, tab, SCALE, tab.getScale(), 1.0f, TAB_FOCUSED_ANIMATION_DURATION, 0);
+                int tabYInfluenceDuration = FeatureUtilities.isChromeHomeEnabled()
+                        ? TAB_FOCUSED_ANIMATION_DURATION
+                        : TAB_FOCUSED_Y_STACK_DURATION;
                 addAnimation(set, tab, Y_IN_STACK_INFLUENCE, tab.getYInStackInfluence(), 0.0f,
-                        TAB_FOCUSED_Y_STACK_DURATION, 0);
+                        tabYInfluenceDuration, 0);
                 addAnimation(set, tab.getLayoutTab(), MAX_CONTENT_HEIGHT,
                         tab.getLayoutTab().getMaxContentHeight(),
                         tab.getLayoutTab().getUnclampedOriginalContentHeight(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
index e09cf97..9acd716 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
@@ -411,6 +411,8 @@
         boolean handled = CustomTabActivity.handleInActiveContentIfNeeded(getIntent());
         if (handled) return;
 
+        maybePrefetchDnsInBackground();
+
         // Create and fire a launch intent.
         startActivity(createCustomTabActivityIntent(
                 this, getIntent(), !isCustomTabIntent(getIntent()) && mIsHerbIntent));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
index 28a392fc..caf50c4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
@@ -95,11 +95,11 @@
         super(context, attrs);
 
         int defaultHandleColor =
-                ApiCompatibilityUtils.getColor(getResources(), R.color.google_grey_500);
+                ApiCompatibilityUtils.getColor(getResources(), R.color.black_alpha_40);
         mHandleDark = generateHandleBitmap(defaultHandleColor);
 
         int lightHandleColor =
-                ApiCompatibilityUtils.getColor(getResources(), R.color.semi_opaque_white);
+                ApiCompatibilityUtils.getColor(getResources(), R.color.white_alpha_50);
         mHandleLight = generateHandleBitmap(lightHandleColor);
     }
 
@@ -201,10 +201,11 @@
     protected void updateVisualsForToolbarState() {
         super.updateVisualsForToolbarState();
 
-        // The handle should not show in tab switcher mode.
-        mToolbarHandleView.setVisibility(
-                mTabSwitcherState != ToolbarPhone.STATIC_TAB ? View.INVISIBLE : View.VISIBLE);
-        mToolbarHandleView.setImageBitmap(mUseLightToolbarDrawables ? mHandleLight : mHandleDark);
+        // The tab switcher's background color should not affect the toolbar handle; it should only
+        // switch color based on the static tab's theme color. This is done so fade in/out looks
+        // correct.
+        boolean isLight = ColorUtils.shouldUseLightForegroundOnBackground(getTabThemeColor());
+        mToolbarHandleView.setImageBitmap(isLight ? mHandleLight : mHandleDark);
     }
 
     @Override
@@ -252,6 +253,7 @@
         mNewTabButton.setAlpha(progress);
 
         mLocationBar.setAlpha(1f - progress);
+        mToolbarHandleView.setAlpha(1f - progress);
 
         int tabSwitcherThemeColor = getToolbarColorForVisualState(VisualState.TAB_SWITCHER_NORMAL);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
index 03934b7..e6f19e12 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -59,6 +59,7 @@
 import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.ColorUtils;
+import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.MathUtils;
 import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.animation.CancelAwareAnimatorListener;
@@ -706,7 +707,7 @@
 
                 // Perform the fade logic before super.dispatchDraw(canvas) so that we can properly
                 // set the values before the draw happens.
-                if (!mAnimateNormalToolbar) {
+                if (!mAnimateNormalToolbar || FeatureUtilities.isChromeHomeEnabled()) {
                     drawTabSwitcherFadeAnimation(
                             tabSwitcherAnimationFinished, mTabSwitcherModePercent);
                 }
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 6505600..d706b49 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -1663,29 +1663,11 @@
   PostProfileInit();
 
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
-  // Show the First Run UI if this is the first time Chrome has been run on
-  // this computer, or we're being compelled to do so by a command line flag.
-  // Note that this be done _after_ the PrefService is initialized and all
-  // preferences are registered, since some of the code that the importer
-  // touches reads preferences.
+  // Execute first run specific code after the PrefService has been initialized
+  // and preferences have been registered since some of the import code depends
+  // on preferences.
   if (first_run::IsChromeFirstRun()) {
-    // By default Auto Import is performed on first run.
-    bool auto_import = true;
-
-#if defined(OS_WIN)
-    // Auto Import might be disabled via a field trial.  However, this field
-    // trial is not intended to affect enterprise users.
-    auto_import =
-        base::win::IsEnterpriseManaged() ||
-        !base::FeatureList::IsEnabled(features::kDisableFirstRunAutoImportWin);
-#endif  // defined(OS_WIN)
-
-    if (auto_import) {
-      first_run::AutoImport(profile_, master_prefs_->homepage_defined,
-                            master_prefs_->do_import_items,
-                            master_prefs_->dont_import_items,
-                            master_prefs_->import_bookmarks_path);
-    }
+    first_run::AutoImport(profile_, master_prefs_->import_bookmarks_path);
 
     // Note: this can pop the first run consent dialog on linux.
     first_run::DoPostImportTasks(profile_,
diff --git a/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc b/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc
index a2451440..e0be4c8 100644
--- a/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc
+++ b/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc
@@ -10,6 +10,7 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/ssl/ssl_error_handler.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -82,11 +83,12 @@
   DVLOG(1) << "Component ready, version " << version.GetString() << " in "
            << install_dir.value();
 
-  if (!content::BrowserThread::PostBlockingPoolTask(
-          FROM_HERE,
-          base::Bind(&LoadProtoFromDisk, GetInstalledPath(install_dir)))) {
-    NOTREACHED();
-  }
+  base::PostTaskWithTraits(
+      FROM_HERE,
+      base::TaskTraits()
+          .WithPriority(base::TaskPriority::BACKGROUND)
+          .MayBlock(),
+      base::Bind(&LoadProtoFromDisk, GetInstalledPath(install_dir)));
 }
 
 // Called during startup and installation before ComponentReady().
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index bab5ac73..53a9677c 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/extensions/convert_web_app.h"
 #include "chrome/browser/extensions/extension_assets_manager.h"
 #include "chrome/browser/extensions/extension_error_reporter.h"
+#include "chrome/browser/extensions/extension_install_checker.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/install_tracker.h"
 #include "chrome/browser/extensions/install_tracker_factory.h"
@@ -108,7 +109,8 @@
 CrxInstaller::CrxInstaller(base::WeakPtr<ExtensionService> service_weak,
                            std::unique_ptr<ExtensionInstallPrompt> client,
                            const WebstoreInstaller::Approval* approval)
-    : install_directory_(service_weak->install_directory()),
+    : profile_(service_weak->profile()),
+      install_directory_(service_weak->install_directory()),
       install_source_(Manifest::INTERNAL),
       approved_(false),
       hash_check_failed_(false),
@@ -130,8 +132,7 @@
       did_handle_successfully_(true),
       error_on_unsupported_requirements_(false),
       update_from_settings_page_(false),
-      install_flags_(kInstallFlagNone),
-      install_checker_(service_weak->profile()) {
+      install_flags_(kInstallFlagNone) {
   installer_task_runner_ = service_weak->GetFileTaskRunner();
   if (!approval)
     return;
@@ -355,7 +356,7 @@
     }
   }
 
-  if (install_checker_.extension()->is_app()) {
+  if (extension_->is_app()) {
     // If the app was downloaded, apps_require_extension_mime_type_
     // will be set.  In this case, check that it was served with the
     // right mime type.  Make an exception for file URLs, which come
@@ -388,7 +389,7 @@
       pattern.SetHost(download_url_.host());
       pattern.SetMatchSubdomains(true);
 
-      URLPatternSet patterns = install_checker_.extension()->web_extent();
+      URLPatternSet patterns = extension_->web_extent();
       for (URLPatternSet::const_iterator i = patterns.begin();
            i != patterns.end(); ++i) {
         if (!pattern.MatchesHost(i->host())) {
@@ -431,7 +432,7 @@
                             install_cause(),
                             extension_misc::NUM_INSTALL_CAUSES);
 
-  install_checker_.set_extension(extension);
+  extension_ = extension;
   temp_dir_ = temp_dir;
   if (!install_icon.empty())
     install_icon_.reset(new SkBitmap(install_icon));
@@ -510,11 +511,12 @@
   // Run the policy, requirements and blacklist checks in parallel. Skip the
   // checks if the extension is a bookmark app.
   if (extension()->from_bookmark()) {
-    CrxInstaller::OnInstallChecksComplete(0);
+    ConfirmInstall();
   } else {
-    install_checker_.Start(
-        ExtensionInstallChecker::CHECK_ALL,
-        false /* fail fast */,
+    install_checker_ = base::MakeUnique<ExtensionInstallChecker>(
+        profile_, extension_, ExtensionInstallChecker::CHECK_ALL,
+        false /* fail fast */);
+    install_checker_->Start(
         base::Bind(&CrxInstaller::OnInstallChecksComplete, this));
   }
 }
@@ -525,24 +527,24 @@
     return;
 
   // Check for requirement errors.
-  if (!install_checker_.requirement_errors().empty()) {
+  if (!install_checker_->requirement_errors().empty()) {
     if (error_on_unsupported_requirements_) {
       ReportFailureFromUIThread(
           CrxInstallError(CrxInstallError::ERROR_DECLINED,
                           base::UTF8ToUTF16(base::JoinString(
-                              install_checker_.requirement_errors(), " "))));
+                              install_checker_->requirement_errors(), " "))));
       return;
     }
     install_flags_ |= kInstallFlagHasRequirementErrors;
   }
 
   // Check the blacklist state.
-  if (install_checker_.blacklist_state() == BLACKLISTED_MALWARE) {
+  if (install_checker_->blacklist_state() == BLACKLISTED_MALWARE) {
     install_flags_ |= kInstallFlagIsBlacklistedForMalware;
   }
 
-  if ((install_checker_.blacklist_state() == BLACKLISTED_MALWARE ||
-       install_checker_.blacklist_state() == BLACKLISTED_UNKNOWN) &&
+  if ((install_checker_->blacklist_state() == BLACKLISTED_MALWARE ||
+       install_checker_->blacklist_state() == BLACKLISTED_UNKNOWN) &&
       !allow_silent_install_) {
     // User tried to install a blacklisted extension. Show an error and
     // refuse to install it.
@@ -561,7 +563,7 @@
   // deal with it.
 
   // Check for policy errors.
-  if (!install_checker_.policy_error().empty()) {
+  if (!install_checker_->policy_error().empty()) {
     // We don't want to show the error infobar for installs from the WebStore,
     // because the WebStore already shows an error dialog itself.
     // Note: |client_| can be NULL in unit_tests!
@@ -569,7 +571,7 @@
       client_->install_ui()->SetSkipPostInstallUI(true);
     ReportFailureFromUIThread(
         CrxInstallError(CrxInstallError::ERROR_DECLINED,
-                        base::UTF8ToUTF16(install_checker_.policy_error())));
+                        base::UTF8ToUTF16(install_checker_->policy_error())));
     return;
   }
 
@@ -582,7 +584,7 @@
   if (!service || service->browser_terminating())
     return;
 
-  if (KioskModeInfo::IsKioskOnly(install_checker_.extension().get())) {
+  if (KioskModeInfo::IsKioskOnly(extension())) {
     bool in_kiosk_mode = false;
 #if defined(OS_CHROMEOS)
     user_manager::UserManager* user_manager = user_manager::UserManager::Get();
@@ -721,13 +723,10 @@
   // with base::string16
   std::string extension_id = extension()->id();
   std::string error;
-  install_checker_.set_extension(
-      file_util::LoadExtension(
-          version_dir,
-          install_source_,
-          // Note: modified by UpdateCreationFlagsAndCompleteInstall.
-          creation_flags_,
-          &error).get());
+  extension_ = file_util::LoadExtension(
+      version_dir, install_source_,
+      // Note: modified by UpdateCreationFlagsAndCompleteInstall.
+      creation_flags_, &error);
 
   if (extension()) {
     ReportSuccessFromFileThread();
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h
index 7d7168f..e16d57c 100644
--- a/chrome/browser/extensions/crx_installer.h
+++ b/chrome/browser/extensions/crx_installer.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_
 #define CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -14,7 +15,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/version.h"
-#include "chrome/browser/extensions/extension_install_checker.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/webstore_installer.h"
@@ -36,6 +36,7 @@
 
 namespace extensions {
 class CrxInstallError;
+class ExtensionInstallChecker;
 class ExtensionUpdaterTest;
 
 // This class installs a crx file into a profile.
@@ -200,9 +201,9 @@
 
   bool did_handle_successfully() const { return did_handle_successfully_; }
 
-  Profile* profile() { return install_checker_.profile(); }
+  Profile* profile() { return profile_; }
 
-  const Extension* extension() { return install_checker_.extension().get(); }
+  const Extension* extension() { return extension_.get(); }
 
   // The currently installed version of the extension, for updates. Will be
   // invalid if this isn't an update.
@@ -211,7 +212,6 @@
  private:
   friend class ::ExtensionServiceTest;
   friend class ExtensionUpdaterTest;
-  friend class ExtensionCrxInstallerTest;
 
   CrxInstaller(base::WeakPtr<ExtensionService> service_weak,
                std::unique_ptr<ExtensionInstallPrompt> client,
@@ -288,6 +288,12 @@
       install_flags_ &= ~flag;
   }
 
+  // The Profile the extension is being installed in.
+  Profile* profile_;
+
+  // The extension being installed.
+  scoped_refptr<const Extension> extension_;
+
   // The file we're installing.
   base::FilePath source_file_;
 
@@ -438,7 +444,7 @@
   int install_flags_;
 
   // Performs requirements, policy and blacklist checks on the extension.
-  ExtensionInstallChecker install_checker_;
+  std::unique_ptr<ExtensionInstallChecker> install_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(CrxInstaller);
 };
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index 36098b8..af7b9e43 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -284,16 +284,6 @@
         CreateWebAppInfo(kAppTitle, kAppDescription, kAppUrl, 64));
     EXPECT_TRUE(WaitForCrxInstallerDone());
     ASSERT_TRUE(crx_installer->extension());
-    ASSERT_FALSE(HasRequirementErrors(crx_installer.get()));
-    ASSERT_FALSE(HasPolicyErrors(crx_installer.get()));
-  }
-
-  bool HasRequirementErrors(CrxInstaller* crx_installer) {
-    return !crx_installer->install_checker_.requirement_errors().empty();
-  }
-
-  bool HasPolicyErrors(CrxInstaller* crx_installer) {
-    return !crx_installer->install_checker_.policy_error().empty();
   }
 };
 
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index 55eecc6..ca87820 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -263,7 +263,8 @@
     return observer_->WaitForExtensionCrash(extension_id);
   }
 
-  // Wait for the crx installer to be done. Returns true if it really is done.
+  // Wait for the crx installer to be done. Returns true if it has finished
+  // successfully.
   bool WaitForCrxInstallerDone() {
     return observer_->WaitForCrxInstallerDone();
   }
diff --git a/chrome/browser/extensions/extension_install_checker.cc b/chrome/browser/extensions/extension_install_checker.cc
index 313225df..d027389d 100644
--- a/chrome/browser/extensions/extension_install_checker.cc
+++ b/chrome/browser/extensions/extension_install_checker.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/extensions/extension_install_checker.h"
 
+#include "base/callback_helpers.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/blacklist.h"
 #include "chrome/browser/extensions/chrome_requirements_checker.h"
@@ -14,55 +15,56 @@
 
 namespace extensions {
 
-ExtensionInstallChecker::ExtensionInstallChecker(Profile* profile)
+ExtensionInstallChecker::ExtensionInstallChecker(
+    Profile* profile,
+    scoped_refptr<const Extension> extension,
+    int enabled_checks,
+    bool fail_fast)
     : profile_(profile),
+      extension_(extension),
       blacklist_state_(NOT_BLACKLISTED),
       policy_allows_load_(true),
-      current_sequence_number_(0),
+      enabled_checks_(enabled_checks),
       running_checks_(0),
-      fail_fast_(false),
-      weak_ptr_factory_(this) {
-}
+      fail_fast_(fail_fast),
+      weak_ptr_factory_(this) {}
 
 ExtensionInstallChecker::~ExtensionInstallChecker() {
 }
 
-void ExtensionInstallChecker::Start(int enabled_checks,
-                                    bool fail_fast,
-                                    const Callback& callback) {
+void ExtensionInstallChecker::Start(const Callback& callback) {
   // Profile is null in tests.
   if (profile_) {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    // TODO(michaelpg): change NOTREACHED to [D]CHECK here and below.
     if (!extension_.get()) {
       NOTREACHED();
       return;
     }
   }
 
-  if (is_running() || !enabled_checks || callback.is_null()) {
+  if (is_running() || !enabled_checks_ || callback.is_null()) {
     NOTREACHED();
     return;
   }
 
-  running_checks_ = enabled_checks;
-  fail_fast_ = fail_fast;
+  running_checks_ = enabled_checks_;
   callback_ = callback;
-  ResetResults();
 
   // Execute the management policy check first as it is synchronous.
-  if (enabled_checks & CHECK_MANAGEMENT_POLICY) {
+  if (enabled_checks_ & CHECK_MANAGEMENT_POLICY) {
     CheckManagementPolicy();
     if (!is_running())
       return;
   }
 
-  if (enabled_checks & CHECK_REQUIREMENTS) {
+  if (enabled_checks_ & CHECK_REQUIREMENTS) {
     CheckRequirements();
     if (!is_running())
       return;
   }
 
-  if (enabled_checks & CHECK_BLACKLIST)
+  if (enabled_checks_ & CHECK_BLACKLIST)
     CheckBlacklistState();
 }
 
@@ -89,21 +91,15 @@
 void ExtensionInstallChecker::CheckRequirements() {
   DCHECK(extension_.get());
 
-  if (!requirements_checker_.get())
-    requirements_checker_.reset(new ChromeRequirementsChecker());
+  requirements_checker_ = base::MakeUnique<ChromeRequirementsChecker>();
   requirements_checker_->Check(
-      extension_,
-      base::Bind(&ExtensionInstallChecker::OnRequirementsCheckDone,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 current_sequence_number_));
+      extension_, base::Bind(&ExtensionInstallChecker::OnRequirementsCheckDone,
+                             weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ExtensionInstallChecker::OnRequirementsCheckDone(
-    int sequence_number,
     const std::vector<std::string>& errors) {
-  // Some pending results may arrive after fail fast.
-  if (sequence_number != current_sequence_number_)
-    return;
+  DCHECK(is_running());
 
   requirement_errors_ = errors;
 
@@ -118,15 +114,11 @@
   blacklist->IsBlacklisted(
       extension_->id(),
       base::Bind(&ExtensionInstallChecker::OnBlacklistStateCheckDone,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 current_sequence_number_));
+                 weak_ptr_factory_.GetWeakPtr()));
 }
 
-void ExtensionInstallChecker::OnBlacklistStateCheckDone(int sequence_number,
-                                                        BlacklistState state) {
-  // Some pending results may arrive after fail fast.
-  if (sequence_number != current_sequence_number_)
-    return;
+void ExtensionInstallChecker::OnBlacklistStateCheckDone(BlacklistState state) {
+  DCHECK(is_running());
 
   blacklist_state_ = state;
 
@@ -134,13 +126,6 @@
   MaybeInvokeCallback();
 }
 
-void ExtensionInstallChecker::ResetResults() {
-  requirement_errors_.clear();
-  blacklist_state_ = NOT_BLACKLISTED;
-  policy_allows_load_ = true;
-  policy_error_.clear();
-}
-
 void ExtensionInstallChecker::MaybeInvokeCallback() {
   if (callback_.is_null())
     return;
@@ -160,14 +145,7 @@
     // If we are failing fast, discard any pending results.
     weak_ptr_factory_.InvalidateWeakPtrs();
     running_checks_ = 0;
-    ++current_sequence_number_;
-
-    Callback callback_copy = callback_;
-    callback_.Reset();
-
-    // This instance may be owned by the callback recipient and deleted here,
-    // so reset |callback_| first and invoke a copy of the callback.
-    callback_copy.Run(failed_mask);
+    base::ResetAndReturn(&callback_).Run(failed_mask);
   }
 }
 
diff --git a/chrome/browser/extensions/extension_install_checker.h b/chrome/browser/extensions/extension_install_checker.h
index b73255b..9bafea51 100644
--- a/chrome/browser/extensions/extension_install_checker.h
+++ b/chrome/browser/extensions/extension_install_checker.h
@@ -22,8 +22,8 @@
 
 class RequirementsChecker;
 
-// Performs common checks for an extension. Extensions that violate these checks
-// would be disabled or not even installed.
+// Performs common checks for validating whether an extension may be installed.
+// This class should be Start()-ed at most once.
 class ExtensionInstallChecker {
  public:
   // Called when checks are complete. The returned value is a bitmask of
@@ -42,25 +42,20 @@
     CHECK_ALL = (1 << 3) - 1
   };
 
-  explicit ExtensionInstallChecker(Profile* profile);
+  // |enabled_checks| is a bitmask of CheckTypes to run.
+  // If |fail_fast| is true, the callback to Start() will be invoked once any
+  // check fails. Otherwise it will be invoked when all checks have completed.
+  ExtensionInstallChecker(Profile* profile,
+                          scoped_refptr<const Extension> extension,
+                          int enabled_checks,
+                          bool fail_fast);
   virtual ~ExtensionInstallChecker();
 
-  // Start a set of checks. |enabled_checks| is a bitmask of CheckTypes to run.
-  // If |fail_fast| is true, the callback will be invoked once any check fails.
-  // Otherwise it will be invoked when all checks have completed. |callback|
-  // will only be called once.
+  // Starts the set of checks. |callback| will only be called once.
   // This function must be called on the UI thread. The callback also occurs on
   // the UI thread. Checks may run asynchronously in parallel.
-  // If checks are currently running, the caller must wait for the callback to
-  // be invoked before starting another set of checks.
-  void Start(int enabled_checks, bool fail_fast, const Callback& callback);
-
-  Profile* profile() const { return profile_; }
-
-  const scoped_refptr<const Extension>& extension() { return extension_; }
-  void set_extension(const scoped_refptr<const Extension>& extension) {
-    extension_ = extension;
-  }
+  // This function should be invoked at most once.
+  void Start(const Callback& callback);
 
   // Returns true if any checks are currently running.
   bool is_running() const { return running_checks_ != 0; }
@@ -84,14 +79,10 @@
   void OnManagementPolicyCheckDone(bool allows_load, const std::string& error);
 
   virtual void CheckRequirements();
-  void OnRequirementsCheckDone(int sequence_number,
-                               const std::vector<std::string>& errors);
+  void OnRequirementsCheckDone(const std::vector<std::string>& errors);
 
   virtual void CheckBlacklistState();
-  void OnBlacklistStateCheckDone(int sequence_number, BlacklistState state);
-
-  virtual void ResetResults();
-  int current_sequence_number() const { return current_sequence_number_; }
+  void OnBlacklistStateCheckDone(BlacklistState state);
 
  private:
   void MaybeInvokeCallback();
@@ -114,10 +105,11 @@
   bool policy_allows_load_;
   std::string policy_error_;
 
-  // The sequence number of the currently running checks.
-  int current_sequence_number_;
+  // Bitmask of enabled checks.
+  int enabled_checks_;
 
   // Bitmask of currently running checks.
+  // TODO(michaelpg): Consolidate this with enabled_checks_.
   int running_checks_;
 
   // If true, the callback is invoked when the first check fails.
diff --git a/chrome/browser/extensions/extension_install_checker_unittest.cc b/chrome/browser/extensions/extension_install_checker_unittest.cc
index f70d9dd..fb6b9e6 100644
--- a/chrome/browser/extensions/extension_install_checker_unittest.cc
+++ b/chrome/browser/extensions/extension_install_checker_unittest.cc
@@ -18,10 +18,6 @@
 const char kDummyRequirementsError[] = "Requirements error";
 const char kDummyPolicyError[] = "Cannot install extension";
 
-const char kDummyPolicyError2[] = "Another policy error";
-const char kDummyRequirementsError2[] = "Another requirements error";
-const BlacklistState kBlacklistState2 = BLACKLISTED_SECURITY_VULNERABILITY;
-
 }  // namespace
 
 // Stubs most of the checks since we are interested in validating the logic in
@@ -29,8 +25,8 @@
 // checks.
 class ExtensionInstallCheckerForTest : public ExtensionInstallChecker {
  public:
-  ExtensionInstallCheckerForTest()
-      : ExtensionInstallChecker(NULL),
+  ExtensionInstallCheckerForTest(int enabled_checks, bool fail_fast)
+      : ExtensionInstallChecker(nullptr, nullptr, enabled_checks, fail_fast),
         requirements_check_called_(false),
         blacklist_check_called_(false),
         policy_check_called_(false),
@@ -50,21 +46,25 @@
   bool blacklist_check_called() const { return blacklist_check_called_; }
   bool policy_check_called() const { return policy_check_called_; }
 
-  void MockCheckRequirements(int sequence_number) {
+  void MockCheckRequirements() {
+    if (!is_running())
+      return;
     std::vector<std::string> errors;
     if (!requirements_error_.empty())
       errors.push_back(requirements_error_);
-    OnRequirementsCheckDone(sequence_number, errors);
+    OnRequirementsCheckDone(errors);
   }
 
-  void MockCheckBlacklistState(int sequence_number) {
-    OnBlacklistStateCheckDone(sequence_number, blacklist_state_);
+  void MockCheckBlacklistState() {
+    if (!is_running())
+      return;
+    OnBlacklistStateCheckDone(blacklist_state_);
   }
 
  protected:
   void CheckRequirements() override {
     requirements_check_called_ = true;
-    MockCheckRequirements(current_sequence_number());
+    MockCheckRequirements();
   }
 
   void CheckManagementPolicy() override {
@@ -75,15 +75,7 @@
 
   void CheckBlacklistState() override {
     blacklist_check_called_ = true;
-    MockCheckBlacklistState(current_sequence_number());
-  }
-
-  void ResetResults() override {
-    ExtensionInstallChecker::ResetResults();
-
-    requirements_check_called_ = false;
-    blacklist_check_called_ = false;
-    policy_check_called_ = false;
+    MockCheckBlacklistState();
   }
 
   bool requirements_check_called_;
@@ -99,6 +91,10 @@
 // This class implements asynchronous mocks of the requirements and blacklist
 // checks.
 class ExtensionInstallCheckerAsync : public ExtensionInstallCheckerForTest {
+ public:
+  ExtensionInstallCheckerAsync(int enabled_checks, bool fail_fast)
+      : ExtensionInstallCheckerForTest(enabled_checks, fail_fast) {}
+
  protected:
   void CheckRequirements() override {
     requirements_check_called_ = true;
@@ -106,7 +102,7 @@
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::Bind(&ExtensionInstallCheckerForTest::MockCheckRequirements,
-                   base::Unretained(this), current_sequence_number()));
+                   base::Unretained(this)));
   }
 
   void CheckBlacklistState() override {
@@ -115,7 +111,7 @@
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::Bind(&ExtensionInstallCheckerForTest::MockCheckBlacklistState,
-                   base::Unretained(this), current_sequence_number()));
+                   base::Unretained(this)));
   }
 };
 
@@ -148,40 +144,6 @@
   ExtensionInstallCheckerTest() {}
   ~ExtensionInstallCheckerTest() override {}
 
-  void RunSecondInvocation(ExtensionInstallCheckerForTest* checker,
-                           int checks_failed) {
-    EXPECT_GT(checks_failed, 0);
-    EXPECT_FALSE(checker->is_running());
-    ValidateExpectedCalls(ExtensionInstallChecker::CHECK_ALL, *checker);
-
-    // Set up different return values.
-    checker->set_blacklist_state(kBlacklistState2);
-    checker->set_policy_check_error(kDummyPolicyError2);
-    checker->set_requirements_error(kDummyRequirementsError2);
-
-    // Run the install checker again and ensure the second set of return values
-    // is received.
-    checker->Start(
-        ExtensionInstallChecker::CHECK_ALL,
-        false /* fail fast */,
-        base::Bind(&ExtensionInstallCheckerTest::ValidateSecondInvocation,
-                   base::Unretained(this),
-                   checker));
-  }
-
-  void ValidateSecondInvocation(ExtensionInstallCheckerForTest* checker,
-                                int checks_failed) {
-    EXPECT_FALSE(checker->is_running());
-    EXPECT_EQ(ExtensionInstallChecker::CHECK_REQUIREMENTS |
-                  ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY,
-              checks_failed);
-    ValidateExpectedCalls(ExtensionInstallChecker::CHECK_ALL, *checker);
-
-    EXPECT_EQ(kBlacklistState2, checker->blacklist_state());
-    ExpectPolicyError(kDummyPolicyError2, *checker);
-    ExpectRequirementsError(kDummyRequirementsError2, *checker);
-  }
-
  protected:
   void SetAllErrors(ExtensionInstallCheckerForTest* checker) {
     checker->set_blacklist_state(kBlacklistStateError);
@@ -242,14 +204,10 @@
   }
 
   void RunChecker(ExtensionInstallCheckerForTest* checker,
-                  bool fail_fast,
-                  int checks_to_run,
                   int expected_checks_run,
                   int expected_result) {
     CheckObserver observer;
-    checker->Start(checks_to_run,
-                   fail_fast,
-                   base::Bind(&CheckObserver::OnChecksComplete,
+    checker->Start(base::Bind(&CheckObserver::OnChecksComplete,
                               base::Unretained(&observer)));
     observer.Wait();
 
@@ -261,8 +219,6 @@
 
   void DoRunAllChecksPass(ExtensionInstallCheckerForTest* checker) {
     RunChecker(checker,
-               false /* fail fast */,
-               ExtensionInstallChecker::CHECK_ALL,
                ExtensionInstallChecker::CHECK_ALL,
                0);
 
@@ -274,8 +230,6 @@
   void DoRunAllChecksFail(ExtensionInstallCheckerForTest* checker) {
     SetAllErrors(checker);
     RunChecker(checker,
-               false /* fail fast */,
-               ExtensionInstallChecker::CHECK_ALL,
                ExtensionInstallChecker::CHECK_ALL,
                ExtensionInstallChecker::CHECK_ALL);
 
@@ -284,35 +238,34 @@
     ExpectBlacklistError(*checker);
   }
 
-  void DoRunSubsetOfChecks(ExtensionInstallCheckerForTest* checker) {
-    // Test check set 1.
-    int tests_to_run = ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY |
-                       ExtensionInstallChecker::CHECK_REQUIREMENTS;
-    SetAllErrors(checker);
-    RunChecker(checker, false, tests_to_run, tests_to_run, tests_to_run);
+  void DoRunSubsetOfChecks(int checks_to_run) {
+    ExtensionInstallCheckerForTest sync_checker(checks_to_run,
+                                                /*fail_fast=*/false);
+    ExtensionInstallCheckerAsync async_checker(checks_to_run,
+                                               /*fail_fast=*/false);
+    ExtensionInstallCheckerForTest* checkers[] = {
+        &sync_checker, &async_checker,
+    };
 
-    ExpectRequirementsError(*checker);
-    ExpectPolicyError(*checker);
-    ExpectBlacklistPass(*checker);
+    for (auto* checker : checkers) {
+      SetAllErrors(checker);
+      RunChecker(checker, checks_to_run, checks_to_run);
 
-    // Test check set 2.
-    tests_to_run = ExtensionInstallChecker::CHECK_BLACKLIST |
-                   ExtensionInstallChecker::CHECK_REQUIREMENTS;
-    SetAllErrors(checker);
-    RunChecker(checker, false, tests_to_run, tests_to_run, tests_to_run);
+      if (checks_to_run & ExtensionInstallChecker::CHECK_REQUIREMENTS)
+        ExpectRequirementsError(*checker);
+      else
+        ExpectRequirementsPass(*checker);
 
-    ExpectRequirementsError(*checker);
-    ExpectPolicyPass(*checker);
-    ExpectBlacklistError(*checker);
+      if (checks_to_run & ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY)
+        ExpectPolicyError(*checker);
+      else
+        ExpectPolicyPass(*checker);
 
-    // Test a single check.
-    tests_to_run = ExtensionInstallChecker::CHECK_BLACKLIST;
-    SetAllErrors(checker);
-    RunChecker(checker, false, tests_to_run, tests_to_run, tests_to_run);
-
-    ExpectRequirementsPass(*checker);
-    ExpectPolicyPass(*checker);
-    ExpectBlacklistError(*checker);
+      if (checks_to_run & ExtensionInstallChecker::CHECK_BLACKLIST)
+        ExpectBlacklistError(*checker);
+      else
+        ExpectBlacklistPass(*checker);
+    }
   }
 
  private:
@@ -320,108 +273,66 @@
   base::MessageLoop message_loop;
 };
 
-class ExtensionInstallCheckerMultipleInvocationTest
-    : public ExtensionInstallCheckerTest {
- public:
-  ExtensionInstallCheckerMultipleInvocationTest() : callback_count_(0) {}
-  ~ExtensionInstallCheckerMultipleInvocationTest() override {}
-
-  void RunSecondInvocation(ExtensionInstallCheckerForTest* checker,
-                           int checks_failed) {
-    ASSERT_EQ(0, callback_count_);
-    ++callback_count_;
-    EXPECT_FALSE(checker->is_running());
-    EXPECT_GT(checks_failed, 0);
-    ValidateExpectedCalls(ExtensionInstallChecker::CHECK_ALL, *checker);
-
-    // Set up different return values.
-    checker->set_blacklist_state(kBlacklistState2);
-    checker->set_policy_check_error(kDummyPolicyError2);
-    checker->set_requirements_error(kDummyRequirementsError2);
-
-    // Run the install checker again and ensure the second set of return values
-    // is received.
-    checker->Start(ExtensionInstallChecker::CHECK_ALL,
-                   false /* fail fast */,
-                   base::Bind(&ExtensionInstallCheckerMultipleInvocationTest::
-                                  ValidateSecondInvocation,
-                              base::Unretained(this),
-                              checker));
-  }
-
-  void ValidateSecondInvocation(ExtensionInstallCheckerForTest* checker,
-                                int checks_failed) {
-    ASSERT_EQ(1, callback_count_);
-    EXPECT_FALSE(checker->is_running());
-    EXPECT_EQ(ExtensionInstallChecker::CHECK_REQUIREMENTS |
-                  ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY,
-              checks_failed);
-    ValidateExpectedCalls(ExtensionInstallChecker::CHECK_ALL, *checker);
-
-    EXPECT_EQ(kBlacklistState2, checker->blacklist_state());
-    ExpectPolicyError(kDummyPolicyError2, *checker);
-    ExpectRequirementsError(kDummyRequirementsError2, *checker);
-  }
-
- private:
-  int callback_count_;
-};
-
 // Test the case where all tests pass.
 TEST_F(ExtensionInstallCheckerTest, AllSucceeded) {
-  ExtensionInstallCheckerForTest sync_checker;
+  ExtensionInstallCheckerForTest sync_checker(
+      ExtensionInstallChecker::CHECK_ALL, /*fail_fast=*/false);
   DoRunAllChecksPass(&sync_checker);
 
-  ExtensionInstallCheckerAsync async_checker;
+  ExtensionInstallCheckerAsync async_checker(ExtensionInstallChecker::CHECK_ALL,
+                                             /*fail_fast=*/false);
   DoRunAllChecksPass(&async_checker);
 }
 
 // Test the case where all tests fail.
 TEST_F(ExtensionInstallCheckerTest, AllFailed) {
-  ExtensionInstallCheckerForTest sync_checker;
+  ExtensionInstallCheckerForTest sync_checker(
+      ExtensionInstallChecker::CHECK_ALL, /*fail_fast=*/false);
   DoRunAllChecksFail(&sync_checker);
 
-  ExtensionInstallCheckerAsync async_checker;
+  ExtensionInstallCheckerAsync async_checker(ExtensionInstallChecker::CHECK_ALL,
+                                             /*fail_fast=*/false);
   DoRunAllChecksFail(&async_checker);
 }
 
 // Test running only a subset of tests.
 TEST_F(ExtensionInstallCheckerTest, RunSubsetOfChecks) {
-  ExtensionInstallCheckerForTest sync_checker;
-  ExtensionInstallCheckerAsync async_checker;
-  DoRunSubsetOfChecks(&sync_checker);
-  DoRunSubsetOfChecks(&async_checker);
+  DoRunSubsetOfChecks(ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY |
+                      ExtensionInstallChecker::CHECK_REQUIREMENTS);
+  DoRunSubsetOfChecks(ExtensionInstallChecker::CHECK_BLACKLIST |
+                      ExtensionInstallChecker::CHECK_REQUIREMENTS);
+  DoRunSubsetOfChecks(ExtensionInstallChecker::CHECK_BLACKLIST);
 }
 
 // Test fail fast with synchronous callbacks.
 TEST_F(ExtensionInstallCheckerTest, FailFastSync) {
   // This test assumes some internal knowledge of the implementation - that
   // the policy check runs first.
-  ExtensionInstallCheckerForTest checker;
-  SetAllErrors(&checker);
-  RunChecker(&checker,
-             true /* fail fast */,
-             ExtensionInstallChecker::CHECK_ALL,
-             ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY,
-             ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY);
+  {
+    ExtensionInstallCheckerForTest checker(ExtensionInstallChecker::CHECK_ALL,
+                                           /*fail_fast=*/true);
+    SetAllErrors(&checker);
+    RunChecker(&checker, ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY,
+               ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY);
 
-  ExpectRequirementsPass(checker);
-  ExpectPolicyError(checker);
-  ExpectBlacklistPass(checker);
+    ExpectRequirementsPass(checker);
+    ExpectPolicyError(checker);
+    ExpectBlacklistPass(checker);
+  }
 
-  // This test assumes some internal knowledge of the implementation - that
-  // the requirements check runs before the blacklist check.
-  SetAllErrors(&checker);
-  RunChecker(&checker,
-             true /* fail fast */,
-             ExtensionInstallChecker::CHECK_REQUIREMENTS |
-                 ExtensionInstallChecker::CHECK_BLACKLIST,
-             ExtensionInstallChecker::CHECK_REQUIREMENTS,
-             ExtensionInstallChecker::CHECK_REQUIREMENTS);
+  {
+    ExtensionInstallCheckerForTest checker(
+        ExtensionInstallChecker::CHECK_REQUIREMENTS |
+            ExtensionInstallChecker::CHECK_BLACKLIST,
+        /*fail_fast=*/true);
+    SetAllErrors(&checker);
+    RunChecker(&checker, ExtensionInstallChecker::CHECK_REQUIREMENTS,
+               ExtensionInstallChecker::CHECK_REQUIREMENTS);
 
-  ExpectRequirementsError(checker);
-  ExpectPolicyPass(checker);
-  ExpectBlacklistPass(checker);
+    ExpectRequirementsError(checker);
+    ExpectPolicyPass(checker);
+    ExpectBlacklistPass(checker);
+  }
 }
 
 // Test fail fast with asynchronous callbacks.
@@ -430,7 +341,9 @@
   // the requirements check runs before the blacklist check. Both checks should
   // be called, but the requirements check callback arrives first and the
   // blacklist result will be discarded.
-  ExtensionInstallCheckerAsync checker;
+  ExtensionInstallCheckerAsync checker(ExtensionInstallChecker::CHECK_ALL,
+                                       /*fail_fast=*/true);
+
   SetAllErrors(&checker);
 
   // The policy check is synchronous and needs to pass for the other tests to
@@ -438,8 +351,6 @@
   checker.set_policy_check_error(std::string());
 
   RunChecker(&checker,
-             true /* fail fast */,
-             ExtensionInstallChecker::CHECK_ALL,
              ExtensionInstallChecker::CHECK_ALL,
              ExtensionInstallChecker::CHECK_REQUIREMENTS);
 
@@ -448,41 +359,4 @@
   ExpectBlacklistPass(checker);
 }
 
-// Test multiple invocations of the install checker. Wait for all checks to
-// complete.
-TEST_F(ExtensionInstallCheckerMultipleInvocationTest, CompleteAll) {
-  ExtensionInstallCheckerAsync checker;
-  SetAllErrors(&checker);
-
-  // Start the second check as soon as the callback of the first run is invoked.
-  checker.Start(
-      ExtensionInstallChecker::CHECK_ALL,
-      false /* fail fast */,
-      base::Bind(
-          &ExtensionInstallCheckerMultipleInvocationTest::RunSecondInvocation,
-          base::Unretained(this),
-          &checker));
-  base::RunLoop().RunUntilIdle();
-}
-
-// Test multiple invocations of the install checker and fail fast.
-TEST_F(ExtensionInstallCheckerMultipleInvocationTest, FailFast) {
-  ExtensionInstallCheckerAsync checker;
-  SetAllErrors(&checker);
-
-  // The policy check is synchronous and needs to pass for the other tests to
-  // run.
-  checker.set_policy_check_error(std::string());
-
-  // Start the second check as soon as the callback of the first run is invoked.
-  checker.Start(
-      ExtensionInstallChecker::CHECK_ALL,
-      true /* fail fast */,
-      base::Bind(
-          &ExtensionInstallCheckerMultipleInvocationTest::RunSecondInvocation,
-          base::Unretained(this),
-          &checker));
-  base::RunLoop().RunUntilIdle();
-}
-
 }  // namespace extensions
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index c3b026a..689f719a 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -2888,16 +2888,10 @@
   EXPECT_TRUE(service()->IsExtensionEnabled(theme_crx));
 }
 
-#if defined(OS_CHROMEOS)
-// Always fails on ChromeOS: http://crbug.com/79737
-#define MAYBE_UpdatePendingExternalCrx DISABLED_UpdatePendingExternalCrx
-#else
-#define MAYBE_UpdatePendingExternalCrx UpdatePendingExternalCrx
-#endif
 // Test updating a pending CRX as if the source is an external extension
 // with an update URL.  In this case we don't know if the CRX is a theme
 // or not.
-TEST_F(ExtensionServiceTest, MAYBE_UpdatePendingExternalCrx) {
+TEST_F(ExtensionServiceTest, UpdatePendingExternalCrx) {
   InitializeEmptyExtensionService();
   EXPECT_TRUE(service()->pending_extension_manager()->AddFromExternalUpdateUrl(
       theme_crx,
diff --git a/chrome/browser/extensions/unpacked_installer.cc b/chrome/browser/extensions/unpacked_installer.cc
index 02e59d90..148113f3 100644
--- a/chrome/browser/extensions/unpacked_installer.cc
+++ b/chrome/browser/extensions/unpacked_installer.cc
@@ -7,9 +7,11 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/files/file_util.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/extensions/extension_error_reporter.h"
+#include "chrome/browser/extensions/extension_install_checker.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
 #include "chrome/browser/extensions/extension_management.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -110,10 +112,10 @@
 
 UnpackedInstaller::UnpackedInstaller(ExtensionService* extension_service)
     : service_weak_(extension_service->AsWeakPtr()),
+      profile_(extension_service->profile()),
       prompt_for_plugins_(true),
       require_modern_manifest_version_(true),
-      be_noisy_on_failure_(true),
-      install_checker_(extension_service->profile()) {
+      be_noisy_on_failure_(true) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
@@ -149,9 +151,8 @@
   }
 
   std::string error;
-  install_checker_.set_extension(
-      file_util::LoadExtension(
-          extension_path_, Manifest::COMMAND_LINE, GetFlags(), &error).get());
+  extension_ = file_util::LoadExtension(extension_path_, Manifest::COMMAND_LINE,
+                                        GetFlags(), &error);
 
   if (!extension() ||
       !extension_l10n_util::ValidateExtensionLocales(
@@ -195,8 +196,7 @@
       PluginInfo::HasPlugins(extension()) &&
       !disabled_extensions.Contains(extension()->id())) {
     SimpleExtensionLoadPrompt* prompt = new SimpleExtensionLoadPrompt(
-        extension(),
-        install_checker_.profile(),
+        extension(), profile_,
         base::Bind(&UnpackedInstaller::StartInstallChecks, this));
     prompt->ShowPrompt();
     return;
@@ -241,24 +241,26 @@
     }
   }
 
-  install_checker_.Start(
+  install_checker_ = base::MakeUnique<ExtensionInstallChecker>(
+      profile_, extension_,
       ExtensionInstallChecker::CHECK_REQUIREMENTS |
           ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY,
-      true /* fail fast */,
+      true /* fail fast */);
+  install_checker_->Start(
       base::Bind(&UnpackedInstaller::OnInstallChecksComplete, this));
 }
 
 void UnpackedInstaller::OnInstallChecksComplete(int failed_checks) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  if (!install_checker_.policy_error().empty()) {
-    ReportExtensionLoadError(install_checker_.policy_error());
+  if (!install_checker_->policy_error().empty()) {
+    ReportExtensionLoadError(install_checker_->policy_error());
     return;
   }
 
-  if (!install_checker_.requirement_errors().empty()) {
+  if (!install_checker_->requirement_errors().empty()) {
     ReportExtensionLoadError(
-        base::JoinString(install_checker_.requirement_errors(), " "));
+        base::JoinString(install_checker_->requirement_errors(), " "));
     return;
   }
 
@@ -329,9 +331,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   std::string error;
-  install_checker_.set_extension(
-      file_util::LoadExtension(
-          extension_path_, Manifest::UNPACKED, flags, &error).get());
+  extension_ = file_util::LoadExtension(extension_path_, Manifest::UNPACKED,
+                                        flags, &error);
 
   if (!extension() ||
       !extension_l10n_util::ValidateExtensionLocales(
diff --git a/chrome/browser/extensions/unpacked_installer.h b/chrome/browser/extensions/unpacked_installer.h
index c0416a2..e145bef 100644
--- a/chrome/browser/extensions/unpacked_installer.h
+++ b/chrome/browser/extensions/unpacked_installer.h
@@ -14,13 +14,14 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/extensions/extension_install_checker.h"
 
 class ExtensionService;
+class Profile;
 
 namespace extensions {
 
 class Extension;
+class ExtensionInstallChecker;
 
 // Installs and loads an unpacked extension. Because internal state needs to be
 // held about the instalation process, only one call to Load*() should be made
@@ -117,15 +118,21 @@
   // Helper to get the Extension::CreateFlags for the installing extension.
   int GetFlags();
 
-  const Extension* extension() { return install_checker_.extension().get(); }
+  const Extension* extension() { return extension_.get(); }
 
   // The service we will report results back to.
   base::WeakPtr<ExtensionService> service_weak_;
 
+  // The Profile the extension is being installed in.
+  Profile* profile_;
+
   // The pathname of the directory to load from, which is an absolute path
   // after GetAbsolutePath has been called.
   base::FilePath extension_path_;
 
+  // The extension being installed.
+  scoped_refptr<const Extension> extension_;
+
   // If true and the extension contains plugins, we prompt the user before
   // loading.
   bool prompt_for_plugins_;
@@ -139,7 +146,7 @@
 
   // Checks management policies and requirements before the extension can be
   // installed.
-  ExtensionInstallChecker install_checker_;
+  std::unique_ptr<ExtensionInstallChecker> install_checker_;
 
   CompletionCallback callback_;
 
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index 06cbc5c..8f66c1ad 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -55,6 +55,7 @@
 #include "chrome/installer/util/master_preferences.h"
 #include "chrome/installer/util/master_preferences_constants.h"
 #include "chrome/installer/util/util_constants.h"
+#include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/signin/core/browser/signin_manager.h"
@@ -198,56 +199,6 @@
   }
 }
 
-// Sets the |items| bitfield according to whether the import data specified by
-// |import_type| should be be auto imported or not.
-void SetImportItem(PrefService* user_prefs,
-                   const char* pref_path,
-                   int import_items,
-                   int dont_import_items,
-                   importer::ImportItem import_type,
-                   int* items) {
-  // Work out whether an item is to be imported according to what is specified
-  // in master preferences.
-  bool should_import = false;
-  bool master_pref_set =
-      ((import_items | dont_import_items) & import_type) != 0;
-  bool master_pref = ((import_items & ~dont_import_items) & import_type) != 0;
-
-  if (import_type == importer::HISTORY ||
-      (import_type != importer::FAVORITES &&
-       first_run::internal::IsOrganicFirstRun())) {
-    // History is always imported unless turned off in master_preferences.
-    // Search engines and home page are imported in organic builds only
-    // unless turned off in master_preferences.
-    should_import = !master_pref_set || master_pref;
-  } else {
-    // Bookmarks are never imported, unless turned on in master_preferences.
-    // Search engine and home page import behaviour is similar in non organic
-    // builds.
-    should_import = master_pref_set && master_pref;
-  }
-
-  // If an import policy is set, import items according to policy. If no master
-  // preference is set, but a corresponding recommended policy is set, import
-  // item according to recommended policy. If both a master preference and a
-  // recommended policy is set, the master preference wins. If neither
-  // recommended nor managed policies are set, import item according to what we
-  // worked out above.
-  if (master_pref_set)
-    user_prefs->SetBoolean(pref_path, should_import);
-
-  if (!user_prefs->FindPreference(pref_path)->IsDefaultValue()) {
-    if (user_prefs->GetBoolean(pref_path))
-      *items |= import_type;
-  } else {
-    // no policy (recommended or managed) is set
-    if (should_import)
-      *items |= import_type;
-  }
-
-  user_prefs->ClearPref(pref_path);
-}
-
 // Launches the import, via |importer_host|, from |source_profile| into
 // |target_profile| for the items specified in the |items_to_import| bitfield.
 // This may be done in a separate process depending on the platform, but it will
@@ -298,19 +249,16 @@
 // Imports settings from the first profile in |importer_list|.
 void ImportSettings(Profile* profile,
                     std::unique_ptr<ImporterList> importer_list,
-                    int items_to_import) {
+                    uint16_t items_to_import) {
+  DCHECK(items_to_import);
   const importer::SourceProfile& source_profile =
       importer_list->GetSourceProfileAt(0);
-  // If no items to import then skip entirely.
-  if (!items_to_import)
-    return;
 
   // Ensure that importers aren't requested to import items that they do not
   // support. If there is no overlap, skip.
   items_to_import &= source_profile.services_supported;
-  if (items_to_import) {
+  if (items_to_import)
     ImportFromSourceProfile(source_profile, profile, items_to_import);
-  }
 
   g_auto_import_state |= first_run::AUTO_IMPORT_PROFILE_IMPORTED;
 }
@@ -495,57 +443,16 @@
   ConvertStringVectorToGURLVector(
       install_prefs.GetFirstRunTabs(), &out_prefs->new_tabs);
 
-  bool value = false;
-  if (install_prefs.GetBool(
-          installer::master_preferences::kDistroImportSearchPref, &value)) {
-    if (value) {
-      out_prefs->do_import_items |= importer::SEARCH_ENGINES;
-    } else {
-      out_prefs->dont_import_items |= importer::SEARCH_ENGINES;
-    }
-  }
-
   // If we're suppressing the first-run bubble, set that preference now.
   // Otherwise, wait until the user has completed first run to set it, so the
   // user is guaranteed to see the bubble iff they have completed the first run
   // process.
+  bool value = false;
   if (install_prefs.GetBool(
           installer::master_preferences::kDistroSuppressFirstRunBubble,
-          &value) && value)
+          &value) &&
+      value) {
     SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SUPPRESS);
-
-  if (install_prefs.GetBool(
-          installer::master_preferences::kDistroImportHistoryPref,
-          &value)) {
-    if (value) {
-      out_prefs->do_import_items |= importer::HISTORY;
-    } else {
-      out_prefs->dont_import_items |= importer::HISTORY;
-    }
-  }
-
-  std::string not_used;
-  out_prefs->homepage_defined = install_prefs.GetString(
-      prefs::kHomePage, &not_used);
-
-  if (install_prefs.GetBool(
-          installer::master_preferences::kDistroImportHomePagePref,
-          &value)) {
-    if (value) {
-      out_prefs->do_import_items |= importer::HOME_PAGE;
-    } else {
-      out_prefs->dont_import_items |= importer::HOME_PAGE;
-    }
-  }
-
-  // Bookmarks are never imported unless specifically turned on.
-  if (install_prefs.GetBool(
-          installer::master_preferences::kDistroImportBookmarksPref,
-          &value)) {
-    if (value)
-      out_prefs->do_import_items |= importer::FAVORITES;
-    else
-      out_prefs->dont_import_items |= importer::FAVORITES;
   }
 
   if (install_prefs.GetBool(
@@ -616,15 +523,19 @@
 
 }  // namespace internal
 
-MasterPrefs::MasterPrefs()
-    : homepage_defined(false),
-      do_import_items(0),
-      dont_import_items(0),
-      make_chrome_default_for_user(false),
-      suppress_first_run_default_browser_prompt(false),
-      welcome_page_on_os_upgrade_enabled(true) {}
+MasterPrefs::MasterPrefs() = default;
 
-MasterPrefs::~MasterPrefs() {}
+MasterPrefs::~MasterPrefs() = default;
+
+void RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterBooleanPref(prefs::kImportAutofillFormData, false);
+  registry->RegisterBooleanPref(prefs::kImportBookmarks, false);
+  registry->RegisterBooleanPref(prefs::kImportHistory, false);
+  registry->RegisterBooleanPref(prefs::kImportHomepage, false);
+  registry->RegisterBooleanPref(prefs::kImportSavedPasswords, false);
+  registry->RegisterBooleanPref(prefs::kImportSearchEngine, false);
+}
 
 bool IsChromeFirstRun() {
   if (g_first_run == internal::FIRST_RUN_UNKNOWN) {
@@ -756,84 +667,56 @@
 
 void AutoImport(
     Profile* profile,
-    bool homepage_defined,
-    int import_items,
-    int dont_import_items,
     const std::string& import_bookmarks_path) {
-  base::FilePath local_state_path;
-  PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
-  bool local_state_file_exists = base::PathExists(local_state_path);
-
-  // It may be possible to do the if block below asynchronously. In which case,
-  // get rid of this RunLoop. http://crbug.com/366116.
-  base::RunLoop run_loop;
-  std::unique_ptr<ImporterList> importer_list(new ImporterList());
-  importer_list->DetectSourceProfiles(
-      g_browser_process->GetApplicationLocale(),
-      false,  // include_interactive_profiles?
-      run_loop.QuitClosure());
-  run_loop.Run();
-
-  // Do import if there is an available profile for us to import.
-  if (importer_list->count() > 0) {
-    if (internal::IsOrganicFirstRun()) {
-      // Home page is imported in organic builds only unless turned off or
-      // defined in master_preferences.
-      if (homepage_defined) {
-        dont_import_items |= importer::HOME_PAGE;
-        if (import_items & importer::HOME_PAGE)
-          import_items &= ~importer::HOME_PAGE;
-      }
-      // Search engines are not imported automatically in organic builds if the
-      // user already has a user preferences directory.
-      if (local_state_file_exists) {
-        dont_import_items |= importer::SEARCH_ENGINES;
-        if (import_items & importer::SEARCH_ENGINES)
-          import_items &= ~importer::SEARCH_ENGINES;
-      }
-    }
-
-    PrefService* user_prefs = profile->GetPrefs();
-    int items = 0;
-
-    SetImportItem(user_prefs,
-                  prefs::kImportHistory,
-                  import_items,
-                  dont_import_items,
-                  importer::HISTORY,
-                  &items);
-    SetImportItem(user_prefs,
-                  prefs::kImportHomepage,
-                  import_items,
-                  dont_import_items,
-                  importer::HOME_PAGE,
-                  &items);
-    SetImportItem(user_prefs,
-                  prefs::kImportSearchEngine,
-                  import_items,
-                  dont_import_items,
-                  importer::SEARCH_ENGINES,
-                  &items);
-    SetImportItem(user_prefs,
-                  prefs::kImportBookmarks,
-                  import_items,
-                  dont_import_items,
-                  importer::FAVORITES,
-                  &items);
-
-    importer::LogImporterUseToMetrics(
-        "AutoImport", importer_list->GetSourceProfileAt(0).importer_type);
-
-    ImportSettings(profile, std::move(importer_list), items);
-  }
-
-  if (!import_bookmarks_path.empty()) {
-    ImportFromFile(profile, import_bookmarks_path);
-  }
-
-  content::RecordAction(UserMetricsAction("FirstRunDef_Accept"));
-
   g_auto_import_state |= AUTO_IMPORT_CALLED;
+
+  // Use |profile|'s PrefService to determine what to import. It will reflect in
+  // order:
+  //  1) Policies.
+  //  2) Master preferences (used to initialize user prefs in
+  //     ProcessMasterPreferences()).
+  //  3) Recommended policies.
+  //  4) Registered default.
+  PrefService* prefs = profile->GetPrefs();
+  uint16_t items_to_import = 0;
+  static constexpr struct {
+    const char* pref_path;
+    importer::ImportItem bit;
+  } kImportItems[] = {
+      {prefs::kImportAutofillFormData, importer::AUTOFILL_FORM_DATA},
+      {prefs::kImportBookmarks, importer::FAVORITES},
+      {prefs::kImportHistory, importer::HISTORY},
+      {prefs::kImportHomepage, importer::HOME_PAGE},
+      {prefs::kImportSavedPasswords, importer::PASSWORDS},
+      {prefs::kImportSearchEngine, importer::SEARCH_ENGINES},
+  };
+
+  for (const auto& import_item : kImportItems) {
+    if (prefs->GetBoolean(import_item.pref_path))
+      items_to_import |= import_item.bit;
+  }
+
+  if (items_to_import) {
+    // It may be possible to do the if block below asynchronously. In which
+    // case, get rid of this RunLoop. http://crbug.com/366116.
+    base::RunLoop run_loop;
+    auto importer_list = base::MakeUnique<ImporterList>();
+    importer_list->DetectSourceProfiles(
+        g_browser_process->GetApplicationLocale(),
+        false,  // include_interactive_profiles?
+        run_loop.QuitClosure());
+    run_loop.Run();
+
+    if (importer_list->count() > 0) {
+      importer::LogImporterUseToMetrics(
+          "AutoImport", importer_list->GetSourceProfileAt(0).importer_type);
+
+      ImportSettings(profile, std::move(importer_list), items_to_import);
+    }
+  }
+
+  if (!import_bookmarks_path.empty())
+    ImportFromFile(profile, import_bookmarks_path);
 }
 
 void DoPostImportTasks(Profile* profile, bool make_chrome_default_for_user) {
diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h
index 725dade..93f4484 100644
--- a/chrome/browser/first_run/first_run.h
+++ b/chrome/browser/first_run/first_run.h
@@ -24,6 +24,10 @@
 class WebContents;
 }
 
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
 // This namespace contains the chrome first-run installation actions needed to
 // fully test the custom installer. It also contains the opposite actions to
 // execute during uninstall. When the first run UI is ready we won't
@@ -71,12 +75,9 @@
   // remove items from here which are being stored temporarily only to be later
   // dumped into local_state. Also see related TODO in chrome_browser_main.cc.
 
-  bool homepage_defined;
-  int do_import_items;
-  int dont_import_items;
-  bool make_chrome_default_for_user;
-  bool suppress_first_run_default_browser_prompt;
-  bool welcome_page_on_os_upgrade_enabled;
+  bool make_chrome_default_for_user = false;
+  bool suppress_first_run_default_browser_prompt = false;
+  bool welcome_page_on_os_upgrade_enabled = true;
   std::vector<GURL> new_tabs;
   std::vector<GURL> bookmarks;
   std::string import_bookmarks_path;
@@ -86,6 +87,9 @@
   std::string suppress_default_browser_prompt_for_version;
 };
 
+void RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry);
+
 // Returns true if Chrome should behave as if this is the first time Chrome is
 // run for this user.
 bool IsChromeFirstRun();
@@ -151,13 +155,10 @@
 // Log a metric for the "FirstRun.SearchEngineBubble" histogram.
 void LogFirstRunMetric(FirstRunBubbleMetric metric);
 
-// Automatically import history and home page (and search engine, if
-// ShouldShowSearchEngineDialog is true). Also imports bookmarks from file if
+// Automatically imports items requested by |profile|'s configuration (sum of
+// policies and master prefs). Also imports bookmarks from file if
 // |import_bookmarks_path| is not empty.
 void AutoImport(Profile* profile,
-                bool homepage_defined,
-                int import_items,
-                int dont_import_items,
                 const std::string& import_bookmarks_path);
 
 // Does remaining first run tasks. This can pop the first run consent dialog on
diff --git a/chrome/browser/first_run/first_run_browsertest.cc b/chrome/browser/first_run/first_run_browsertest.cc
index 90250a4..321d37a 100644
--- a/chrome/browser/first_run/first_run_browsertest.cc
+++ b/chrome/browser/first_run/first_run_browsertest.cc
@@ -176,8 +176,32 @@
 #else
 #define MAYBE_ImportDefault ImportDefault
 #endif
+// No items are imported by default.
 IN_PROC_BROWSER_TEST_F(FirstRunMasterPrefsImportDefault, MAYBE_ImportDefault) {
   int auto_import_state = first_run::auto_import_state();
+  EXPECT_EQ(MaskExpectedImportState(first_run::AUTO_IMPORT_CALLED),
+            auto_import_state);
+}
+
+extern const char kImportAll[] =
+    "{\n"
+    "  \"distribution\": {\n"
+    "    \"import_bookmarks\": true,\n"
+    "    \"import_history\": true,\n"
+    "    \"import_home_page\": true,\n"
+    "    \"import_search_engine\": true\n"
+    "  }\n"
+    "}\n";
+typedef FirstRunMasterPrefsBrowserTestT<kImportAll>
+    FirstRunMasterPrefsImportAll;
+// http://crbug.com/314221
+#if defined(OS_MACOSX) || (defined(GOOGLE_CHROME_BUILD) && defined(OS_LINUX))
+#define MAYBE_ImportAll DISABLED_ImportAll
+#else
+#define MAYBE_ImportAll ImportAll
+#endif
+IN_PROC_BROWSER_TEST_F(FirstRunMasterPrefsImportAll, MAYBE_ImportAll) {
+  int auto_import_state = first_run::auto_import_state();
   EXPECT_EQ(MaskExpectedImportState(first_run::AUTO_IMPORT_CALLED |
                                     first_run::AUTO_IMPORT_PROFILE_IMPORTED),
             auto_import_state);
@@ -204,7 +228,6 @@
   int auto_import_state = first_run::auto_import_state();
   EXPECT_EQ(
       MaskExpectedImportState(first_run::AUTO_IMPORT_CALLED |
-                              first_run::AUTO_IMPORT_PROFILE_IMPORTED |
                               first_run::AUTO_IMPORT_BOOKMARKS_FILE_IMPORTED),
       auto_import_state);
 }
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index 5719a73..c9f6e1c 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -1599,33 +1599,24 @@
 
 // Test that if a form gets autofilled, then it gets autofilled on re-creation
 // as well.
-// TODO(vabr): This is flaky everywhere. http://crbug.com/442704
 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
-                       DISABLED_ReCreatedFormsGetFilled) {
-  NavigateToFile("/password/dynamic_password_form.html");
+                       ReCreatedFormsGetFilled) {
+  // At first let us save a credential to the password store.
+  scoped_refptr<password_manager::TestPasswordStore> password_store =
+      static_cast<password_manager::TestPasswordStore*>(
+          PasswordStoreFactory::GetForProfile(
+              browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS)
+              .get());
+  autofill::PasswordForm signin_form;
+  signin_form.signon_realm = embedded_test_server()->base_url().spec();
+  signin_form.origin = embedded_test_server()->base_url();
+  signin_form.action = embedded_test_server()->base_url();
+  signin_form.username_value = base::ASCIIToUTF16("temp");
+  signin_form.password_value = base::ASCIIToUTF16("random");
+  password_store->AddLogin(signin_form);
 
-  // Fill in the credentials, and make sure they are saved.
-  NavigationObserver form_submit_observer(WebContents());
-  std::unique_ptr<BubbleObserver> prompt_observer(
-      new BubbleObserver(WebContents()));
-  std::string create_fill_and_submit =
-      "document.getElementById('create_form_button').click();"
-      "window.setTimeout(function() {"
-      "  var form = document.getElementById('dynamic_form_id');"
-      "  form.username.value = 'temp';"
-      "  form.password.value = 'random';"
-      "  form.submit();"
-      "}, 0)";
-  ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_fill_and_submit));
-  form_submit_observer.Wait();
-  EXPECT_TRUE(prompt_observer->IsShowingSavePrompt());
-  prompt_observer->AcceptSavePrompt();
-
-  // Reload the original page to have the saved credentials autofilled.
-  NavigationObserver reload_observer(WebContents());
   NavigateToFile("/password/dynamic_password_form.html");
-  reload_observer.Wait();
-  std::string create_form =
+  const std::string create_form =
       "document.getElementById('create_form_button').click();";
   ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_form));
   // Wait until the username is filled, to make sure autofill kicked in.
@@ -1633,7 +1624,7 @@
 
   // Now the form gets deleted and created again. It should get autofilled
   // again.
-  std::string delete_form =
+  const std::string delete_form =
       "var form = document.getElementById('dynamic_form_id');"
       "form.parentNode.removeChild(form);";
   ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), delete_form));
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index ec501abe..e4e93d66 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
+#include "base/strings/pattern.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -71,12 +72,13 @@
 const int kDefaultKeyModifier = blink::WebInputEvent::ControlKey;
 #endif
 
-// Using ASSERT_TRUE deliberately instead of ASSERT_EQ or ASSERT_STREQ
-// in order to print a more readable message if the strings differ.
-#define ASSERT_MULTILINE_STREQ(expected, actual) \
-    ASSERT_TRUE(expected == actual) \
-        << "Expected:\n" << expected \
-        << "\n\nActual:\n" << actual
+// Check if the |actual| string matches the string or the string pattern in
+// |pattern| and print a readable message if it does not match.
+#define ASSERT_MULTILINE_STR_MATCHES(pattern, actual) \
+  ASSERT_TRUE(base::MatchPattern(actual, pattern))    \
+      << "Expected match pattern:\n"                  \
+      << pattern << "\n\nActual:\n"                   \
+      << actual
 
 bool GetGuestCallback(WebContents** guest_out, WebContents* guest) {
   EXPECT_FALSE(*guest_out);
@@ -594,8 +596,7 @@
     ax_tree_dump += ui::ToString(node.role);
 
     std::string name = node.GetStringAttribute(ui::AX_ATTR_NAME);
-    base::ReplaceChars(name, "\r", "\\r", &name);
-    base::ReplaceChars(name, "\n", "\\n", &name);
+    base::ReplaceChars(name, "\r\n", "", &name);
     if (!name.empty())
       ax_tree_dump += " '" + name + "'";
     ax_tree_dump += "\n";
@@ -606,38 +607,41 @@
   return ax_tree_dump;
 }
 
-static const char kExpectedPDFAXTree[] =
+// This is a pattern with a few wildcards due to a PDF bug where the
+// fi ligature is not parsed correctly on some systems.
+// http://crbug.com/701427
+
+static const char kExpectedPDFAXTreePattern[] =
     "embeddedObject\n"
     "  group\n"
     "    region 'Page 1'\n"
     "      paragraph\n"
-    "        staticText '1 First Section\\r\\n'\n"
+    "        staticText '1 First Section'\n"
     "          inlineTextBox '1 '\n"
-    "          inlineTextBox 'First Section\\r\\n'\n"
+    "          inlineTextBox 'First Section'\n"
     "      paragraph\n"
-    "        staticText 'This is the first section.\\r\\n1'\n"
-    "          inlineTextBox 'This is the first section.\\r\\n'\n"
+    "        staticText 'This is the *rst section.1'\n"
+    "          inlineTextBox 'This is the *rst section.'\n"
     "          inlineTextBox '1'\n"
     "    region 'Page 2'\n"
     "      paragraph\n"
-    "        staticText '1.1 First Subsection\\r\\n'\n"
+    "        staticText '1.1 First Subsection'\n"
     "          inlineTextBox '1.1 '\n"
-    "          inlineTextBox 'First Subsection\\r\\n'\n"
+    "          inlineTextBox 'First Subsection'\n"
     "      paragraph\n"
-    "        staticText 'This is the first subsection.\\r\\n2'\n"
-    "          inlineTextBox 'This is the first subsection.\\r\\n'\n"
+    "        staticText 'This is the *rst subsection.2'\n"
+    "          inlineTextBox 'This is the *rst subsection.'\n"
     "          inlineTextBox '2'\n"
     "    region 'Page 3'\n"
     "      paragraph\n"
-    "        staticText '2 Second Section\\r\\n'\n"
+    "        staticText '2 Second Section'\n"
     "          inlineTextBox '2 '\n"
-    "          inlineTextBox 'Second Section\\r\\n'\n"
+    "          inlineTextBox 'Second Section'\n"
     "      paragraph\n"
     "        staticText '3'\n"
     "          inlineTextBox '3'\n";
 
-// https://crbug.com/701427
-IN_PROC_BROWSER_TEST_F(PDFExtensionTest, DISABLED_PdfAccessibility) {
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibility) {
   content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
 
   GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-bookmarks.pdf"));
@@ -648,7 +652,8 @@
                                                 "1 First Section\r\n");
   ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents);
   std::string ax_tree_dump = DumpPdfAccessibilityTree(ax_tree);
-  ASSERT_MULTILINE_STREQ(kExpectedPDFAXTree, ax_tree_dump);
+
+  ASSERT_MULTILINE_STR_MATCHES(kExpectedPDFAXTreePattern, ax_tree_dump);
 }
 
 #if defined(GOOGLE_CHROME_BUILD)
@@ -666,8 +671,7 @@
 }
 #endif
 
-// https://crbug.com/701427
-IN_PROC_BROWSER_TEST_F(PDFExtensionTest, DISABLED_PdfAccessibilityEnableLater) {
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibilityEnableLater) {
   // In this test, load the PDF file first, with accessibility off.
   GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-bookmarks.pdf"));
   WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url);
@@ -680,7 +684,7 @@
                                                 "1 First Section\r\n");
   ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents);
   std::string ax_tree_dump = DumpPdfAccessibilityTree(ax_tree);
-  ASSERT_MULTILINE_STREQ(kExpectedPDFAXTree, ax_tree_dump);
+  ASSERT_MULTILINE_STR_MATCHES(kExpectedPDFAXTreePattern, ax_tree_dump);
 }
 
 bool RetrieveGuestContents(WebContents** out_guest_contents,
@@ -689,8 +693,7 @@
   return true;
 }
 
-// https://crbug.com/701427
-IN_PROC_BROWSER_TEST_F(PDFExtensionTest, DISABLED_PdfAccessibilityInIframe) {
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibilityInIframe) {
   content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
   GURL test_iframe_url(embedded_test_server()->GetURL("/pdf/test-iframe.html"));
   ui_test_utils::NavigateToURL(browser(), test_iframe_url);
@@ -708,11 +711,10 @@
 
   ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents);
   std::string ax_tree_dump = DumpPdfAccessibilityTree(ax_tree);
-  ASSERT_MULTILINE_STREQ(kExpectedPDFAXTree, ax_tree_dump);
+  ASSERT_MULTILINE_STR_MATCHES(kExpectedPDFAXTreePattern, ax_tree_dump);
 }
 
-// https://crbug.com/701427
-IN_PROC_BROWSER_TEST_F(PDFExtensionTest, DISABLED_PdfAccessibilityInOOPIF) {
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibilityInOOPIF) {
   content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
   GURL test_iframe_url(embedded_test_server()->GetURL(
       "/pdf/test-cross-site-iframe.html"));
@@ -731,7 +733,7 @@
 
   ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents);
   std::string ax_tree_dump = DumpPdfAccessibilityTree(ax_tree);
-  ASSERT_MULTILINE_STREQ(kExpectedPDFAXTree, ax_tree_dump);
+  ASSERT_MULTILINE_STR_MATCHES(kExpectedPDFAXTreePattern, ax_tree_dump);
 }
 
 #if defined(GOOGLE_CHROME_BUILD)
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 4a6504d..c376de4 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -583,6 +583,7 @@
 
 #if !defined(OS_ANDROID)
   browser_sync::ForeignSessionHandler::RegisterProfilePrefs(registry);
+  first_run::RegisterProfilePrefs(registry);
   gcm::GCMChannelStatusSyncer::RegisterProfilePrefs(registry);
   gcm::RegisterProfilePrefs(registry);
   StartupBrowserCreator::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/resources/chromeos/about_os_credits.html b/chrome/browser/resources/chromeos/about_os_credits.html
index 5e7caabf..f03cc8a 100644
--- a/chrome/browser/resources/chromeos/about_os_credits.html
+++ b/chrome/browser/resources/chromeos/about_os_credits.html
@@ -6,8 +6,8 @@
 <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
 <style>
 body {
-  background-color:white;
-  max-width:1020px;
+  background-color: white;
+  max-width: 1020px;
 }
 </style>
 </head>
@@ -17,8 +17,9 @@
   <a href="http://dev.chromium.org/chromium-os/licensing-for-chromiumos-package-owners">Licensing for Chromium OS Package Owners</a></p>
 <p>
 If you need to change styles, fonts, layout, etc of <a href="chrome://os_credits">chrome://os_credits</a> page,
-edit <a href="https://chromium.googlesource.com/chromiumos/chromite/+/master/licensing/about_credits.tmpl">chromite/licensing/about_credits.tmpl</a>. 
+edit <a href="https://chromium.googlesource.com/chromiumos/chromite/+/master/licensing/about_credits.tmpl">chromite/licensing/about_credits.tmpl</a>.
 The template is used to generate
 a device-dependent about_os_credits.html when a CrOS image is built.</p>
 </body>
+<script src="keyboard/keyboard_utils.js"></script>
 </html>
diff --git a/chrome/browser/resources/chromeos/demo_app/OWNERS b/chrome/browser/resources/chromeos/demo_app/OWNERS
new file mode 100644
index 0000000..7642048
--- /dev/null
+++ b/chrome/browser/resources/chromeos/demo_app/OWNERS
@@ -0,0 +1,2 @@
+hirono@chromium.org
+oka@chromium.org
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html
index a166666..206c4b05 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -27,6 +27,12 @@
 <dom-module id="settings-basic-page">
   <template>
     <style include="settings-page-styles">
+      :host([is-subpage-animating]) {
+        /* Prevent an unwanted horizontal scrollbar when transitioning back from
+         * a sub-page. */
+        overflow: hidden;
+      }
+
       #advancedToggle {
         --paper-button: {
           text-transform: none;
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js
index fa0b6848..ae0fc19b 100644
--- a/chrome/browser/resources/settings/route.js
+++ b/chrome/browser/resources/settings/route.js
@@ -369,6 +369,11 @@
    *     parameter during navigation. Defaults to false.
    */
   var navigateTo = function(route, opt_dynamicParameters, opt_removeSearch) {
+    // The ADVANCED route only serves as a parent of subpages, and should not
+    // be possible to navigate to it directly.
+    if (route == settings.Route.ADVANCED)
+      route = settings.Route.BASIC;
+
     var params = opt_dynamicParameters || new URLSearchParams();
     var removeSearch = !!opt_removeSearch;
 
diff --git a/chrome/browser/resources/settings/settings_page/main_page_behavior.js b/chrome/browser/resources/settings/settings_page/main_page_behavior.js
index 6e7fe98..600499e7 100644
--- a/chrome/browser/resources/settings/settings_page/main_page_behavior.js
+++ b/chrome/browser/resources/settings/settings_page/main_page_behavior.js
@@ -11,6 +11,16 @@
 var MainPageBehaviorImpl = {
   properties: {
     /**
+     * Help CSS to alter style during the horizontal swipe animation.
+     * Note that this is unrelated to the |currentAnimation_| (which refers to
+     * the vertical exapand animation).
+     */
+    isSubpageAnimating: {
+      reflectToAttribute: true,
+      type: Boolean,
+    },
+
+    /**
      * Whether a search operation is in progress or previous search results are
      * being displayed.
      * @private {boolean}
@@ -25,6 +35,10 @@
   /** @type {?HTMLElement} The scrolling container. */
   scroller: null,
 
+  listeners: {
+    'neon-animation-finish': 'onNeonAnimationFinish_'
+  },
+
   /** @override */
   attached: function() {
     if (this.domHost && this.domHost.parentNode.tagName == 'PAPER-HEADER-PANEL')
@@ -34,6 +48,17 @@
   },
 
   /**
+   * Remove the is-animating attribute once the animation is complete.
+   * This may catch animations finishing more often than needed, which is not
+   * known to cause any issues (e.g. when animating from a shallower page to a
+   * deeper page; or when transitioning to the main page).
+   * @private
+   */
+  onNeonAnimationFinish_: function() {
+    this.isSubpageAnimating = false;
+  },
+
+  /**
    * @param {!settings.Route} newRoute
    * @param {settings.Route} oldRoute
    */
@@ -57,6 +82,9 @@
         !settings.lastRouteChangeWasPopstate() || oldRouteWasSection ||
         oldRoute == settings.Route.BASIC;
 
+    if (oldRoute && (oldRoute.isSubpage() || newRoute.isSubpage()))
+      this.isSubpageAnimating = true;
+
     // For previously uncreated pages (including on first load), allow the page
     // to render before scrolling to or expanding the section.
     if (!oldRoute || this.scrollHeight == 0)
@@ -120,6 +148,7 @@
         // Need to exclude routes that correspond to 'non-sectioned' children of
         // ADVANCED, otherwise tryTransitionToSection_ will recurse endlessly.
         !currentRoute.isNavigableDialog) {
+      assert(currentRoute.section);
       promise = this.$$('#advancedPageTemplate').get();
     }
 
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.css b/chrome/browser/resources/vr_shell/vr_shell_ui.css
index 3693cf9..8b1f5b7 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui.css
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui.css
@@ -86,16 +86,16 @@
 }
 
 .round-button {
-  background-color: #eee;
+  background-color: #fbfbfb;
   background-position: center;
   background-repeat: no-repeat;
-  background-size: contain;
-  border-radius: 10%;
-  height: 96px;
+  background-size: 70px;
+  border-radius: 6px;
+  height: 112px;
   margin: auto auto;
   opacity: 0.8;
-  transition: opacity 150ms ease-in-out;
-  width: 96px;
+  transition: opacity 50ms ease-in-out;
+  width: 112px;
 }
 
 .button-caption {
@@ -105,7 +105,7 @@
   opacity: 0;
   overflow: hidden;
   text-align: center;
-  transition: opacity 150ms ease-in-out;
+  transition: opacity 50ms ease-in-out;
   white-space: nowrap;
 }
 
@@ -129,7 +129,7 @@
 }
 
 .disabled-button {
-  background-color: #aaa;
+  background-color: #bbb;
 }
 
 #back-button,
@@ -149,13 +149,21 @@
 }
 
 #reload-ui-button {
+  --rotX: -0.2;
+  --rotY: 0;
+  --rotZ: 0;
+  --scale: 1;
+  --tranX: 0;
+  --tranY: -0.7;
+  --tranZ: -0.4;
+  background-color: rgba(255,255,255,0.25);
   color: white;
   font-size: 24px;
   padding: 12px;
 }
 
 #reload-ui-button:hover {
-  background-color: pink;
+  background-color: turquoise;
 }
 
 #content-interceptor {
@@ -204,25 +212,26 @@
 }
 
 #url-indicator-container {
+  --scale: 1.2;
   --tranX: 0;
-  --tranY: -0.65;
-  --tranZ: -1.2;
+  --tranY: -0.75;
+  --tranZ: -1.8;
 }
 
 #url-indicator-border {
-  --fadeTimeMs: 500;
-  --fadeYOffset: -0.1;
+  --fadeTimeMs: 200;
+  --fadeYOffset: -0.05;
   --opacity: 0.9;
   --statusBarColor: rgb(66, 133, 244);
   background-color: #ececec;
-  border-radius: 200px;
+  border-radius: 6px;
   padding: 6px;
 }
 
 #url-indicator {
   align-items: center;
   background-color: #ececec;
-  border-radius: 200px;
+  border-radius: 6px;
   box-sizing: border-box;
   display: flex;
   height: 104px;
@@ -275,14 +284,10 @@
 }
 
 #omnibox-ui-element {
-  --tranX: 0;
-  --tranY: -0.1;
-  --tranZ: -1.0;
   background-color: transparent;
   box-sizing: border-box;
-  font-family: arial;
   font-size: 16px;
-  width: 400px;
+  width: 368px;
 }
 
 #suggestions {
@@ -310,19 +315,23 @@
 
 #omnibox-url-element {
   background-color: white;
-  border: 1px solid grey;
+  border-radius: 6px;
   box-sizing: border-box;
   display: flex;
   flex-direction: row-reverse; /* Right-justify for convienence. */
+  height: 64px;
   margin-top: 2px;
-  padding: 5px;
+  padding: 8px;
+  transition: background-color 50ms ease-in-out;
 }
 
 #omnibox-input-field {
+  background-color: transparent;
   border: none;
-  font-size: 16px;
+  font-size: 27px;
   outline: none; /* Do not show an outline when focused. */
   overflow: hidden;
+  text-align: center;
   white-space: nowrap;
   width: 100%;
 }
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.js b/chrome/browser/resources/vr_shell/vr_shell_ui.js
index f01ace1..b7d3a8d33 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui.js
@@ -16,9 +16,9 @@
   // This value should match the one in VrShellImpl.java
   /** @const */ var UI_DPR = 1.2;
 
-  function getStyleFloat(style, property) {
+  function getStyleFloat(style, property, defaultValue) {
     let value = parseFloat(style.getPropertyValue(property));
-    return isNaN(value) ? 0 : value;
+    return isNaN(value) ? defaultValue : value;
   }
 
   function getStyleString(style, property) {
@@ -28,16 +28,17 @@
 
   class ContentQuad {
     constructor() {
-      /** @const */ this.SCREEN_HEIGHT = 1.6;
-      /** @const */ this.SCREEN_RATIO = 16 / 9;
+      /** @const */ this.SCREEN_HEIGHT = 1.375;
+      /** @const */ this.SCREEN_RATIO = 9.6 / 6.4;
+      /** @const */ this.BROWSING_SCREEN_ELEVATION = -0.15;
       /** @const */ this.BROWSING_SCREEN_DISTANCE = 2.0;
       /** @const */ this.FULLSCREEN_DISTANCE = 3.0;
       /** @const */ this.CSS_WIDTH_PIXELS = 960.0;
       /** @const */ this.CSS_HEIGHT_PIXELS = 640.0;
       /** @const */ this.DPR = 1.2;
       /** @const */ this.MENU_MODE_SCREEN_DISTANCE = 2.0;
-      /** @const */ this.MENU_MODE_SCREEN_HEIGHT = 0.8;
-      /** @const */ this.MENU_MODE_SCREEN_ELEVATION = 0.2;
+      /** @const */ this.MENU_MODE_SCREEN_HEIGHT = 0.48;
+      /** @const */ this.MENU_MODE_SCREEN_ELEVATION = -0.125;
       /** @const */ this.BACKGROUND_DISTANCE_MULTIPLIER = 1.414;
       /** @const */ this.DOM_INTERCEPTOR_SELECTOR = '#content-interceptor';
       /** @const */ this.DOM_INTERCEPTOR_ELEVATION = 0.01;
@@ -50,7 +51,8 @@
       element.setVisible(false);
       element.setSize(
           this.SCREEN_HEIGHT * this.SCREEN_RATIO, this.SCREEN_HEIGHT);
-      element.setTranslation(0, 0, -this.BROWSING_SCREEN_DISTANCE);
+      element.setTranslation(
+          0, this.BROWSING_SCREEN_ELEVATION, -this.BROWSING_SCREEN_DISTANCE);
       this.elementId = ui.addElement(element);
 
       // Place an invisible (fill none) but hittable plane behind the content
@@ -113,7 +115,7 @@
 
     updateState() {
       // Defaults content quad parameters.
-      let y = 0;
+      let y = this.BROWSING_SCREEN_ELEVATION;
       let distance = this.BROWSING_SCREEN_DISTANCE;
       let height = this.SCREEN_HEIGHT;
 
@@ -167,13 +169,30 @@
       this.sizeY = pixelHeight / 1000;
       element.setSize(this.sizeX, this.sizeY);
 
-      // Pull additional custom properties from CSS.
+      // Parse element CSS properties.
       let style = window.getComputedStyle(domElement);
-      this.translationX = getStyleFloat(style, '--tranX');
-      this.translationY = getStyleFloat(style, '--tranY');
-      this.translationZ = getStyleFloat(style, '--tranZ');
-      element.setTranslation(
-          this.translationX, this.translationY, this.translationZ);
+
+      this.translationX = getStyleFloat(style, '--tranX', 0);
+      this.translationY = getStyleFloat(style, '--tranY', 0);
+      this.translationZ = getStyleFloat(style, '--tranZ', 0);
+      if (this.translationX != 0 || this.translationY != 0 ||
+          this.translationZ != 0) {
+        element.setTranslation(
+            this.translationX, this.translationY, this.translationZ);
+      }
+
+      this.scale = getStyleFloat(style, '--scale', 1);
+      if (this.scale != 1) {
+        element.setScale(this.scale, this.scale, this.scale);
+      }
+
+      this.rotationX = getStyleFloat(style, '--rotX', 0);
+      this.rotationY = getStyleFloat(style, '--rotY', 0);
+      this.rotationZ = getStyleFloat(style, '--rotZ', 0);
+      if (this.rotationX != 0 || this.rotationY != 0 || this.rotationZ != 0) {
+        element.setRotation(
+            this.rotationX, this.rotationY, this.rotationZ, 2 * Math.PI);
+      }
 
       this.id = ui.addElement(element);
       this.domElement = domElement;
@@ -384,9 +403,9 @@
         ],
       ];
 
-      /** @const */ var BUTTON_Y = -0.27;
-      /** @const */ var BUTTON_Z = -1;
-      /** @const */ var BUTTON_SPACING = 0.11;
+      /** @const */ var BUTTON_Y = -0.53;
+      /** @const */ var BUTTON_Z = -2;
+      /** @const */ var BUTTON_SPACING = 0.14;
 
       let controls = new api.UiElement(0, 0, 0, 0);
       controls.setVisible(false);
@@ -441,9 +460,6 @@
 
       let update = new api.UiElementUpdate();
       update.setVisible(false);
-      update.setSize(0.25, 0.1);
-      update.setTranslation(0, -1.0, -1.0);
-      update.setRotation(1, 0, 0, -0.8);
       ui.updateElement(this.uiElement.id, update);
     }
 
@@ -566,9 +582,9 @@
       let style = window.getComputedStyle(border);
       this.statusBarColor = getStyleString(style, '--statusBarColor');
       this.backgroundColor = style.backgroundColor;
-      this.fadeTimeMs = getStyleFloat(style, '--fadeTimeMs');
-      this.fadeYOffset = getStyleFloat(style, '--fadeYOffset');
-      this.opacity = getStyleFloat(style, '--opacity');
+      this.fadeTimeMs = getStyleFloat(style, '--fadeTimeMs', 0);
+      this.fadeYOffset = getStyleFloat(style, '--fadeYOffset', 0);
+      this.opacity = getStyleFloat(style, '--opacity', 1);
     }
 
     getSecurityIconElementId(level) {
@@ -711,7 +727,7 @@
     constructor() {
       /** @const */ this.SCENE_GROUND_SIZE = 25.0;
       /** @const */ this.SCENE_HEIGHT = 4.0;
-      /** @const */ this.GRIDLINE_COUNT = 10;
+      /** @const */ this.GRIDLINE_COUNT = 40;
       /** @const */ this.HORIZON_COLOR = {r: 0.57, g: 0.57, b: 0.57, a: 1.0};
       /** @const */ this.CENTER_COLOR = {r: 0.48, g: 0.48, b: 0.48, a: 1.0};
       /** @const */ this.FULLSCREEN_BACKGROUND_COLOR =
@@ -734,7 +750,7 @@
       ceilingPlane.setSize(this.SCENE_GROUND_SIZE, this.SCENE_GROUND_SIZE);
       ceilingPlane.setFill(
           new api.OpaqueGradient(this.HORIZON_COLOR, this.CENTER_COLOR));
-      ceilingPlane.setTranslation(0, this.SCENE_HEIGHT / 2, 0);
+      ceilingPlane.setTranslation(0, this.SCENE_HEIGHT * 2, 0);
       ceilingPlane.setRotation(1.0, 0.0, 0.0, Math.PI / 2);
       ceilingPlane.setDrawPhase(0);
       this.ceilingPlaneId = ui.addElement(ceilingPlane);
@@ -808,6 +824,10 @@
 
   class Omnibox {
     constructor() {
+      /** @const */ this.ELEVATION = -0.7;
+      /** @const */ this.DISTANCE = -1.99;
+      /** @const */ this.SCALE = -this.DISTANCE;
+
       this.enabled = false;
 
       let root = document.querySelector('#omnibox-ui-element');
@@ -817,6 +837,8 @@
       // Initially invisible.
       let update = new api.UiElementUpdate();
       update.setVisible(false);
+      update.setTranslation(0, this.ELEVATION, this.DISTANCE);
+      update.setScale(this.SCALE, this.SCALE, this.SCALE);
       ui.updateElement(this.domUiElement.id, update);
 
       // Field-clearing button.
@@ -923,8 +945,8 @@
       /** @const */ var DOM_NEW_TAB_BUTTON_SELECTOR = '#new-tab';
       /** @const */ var DOM_NEW_INCOGNITO_TAB_BUTTON_SELECTOR =
           '#new-incognito-tab';
-      /** @const */ var TAB_CONTAINER_Y_OFFSET = 0.4;
-      /** @const */ var TAB_CONTAINER_Z_OFFSET = -1;
+      /** @const */ var TAB_CONTAINER_Y_OFFSET = 0.3;
+      /** @const */ var TAB_CONTAINER_Z_OFFSET = -2;
 
       this.domTabs = {};
       this.contentQuadId = contentQuadId;
@@ -1050,7 +1072,7 @@
     constructor(contentQuadId) {
       /** @const */ this.SCALE = 1.4;
       /** @const */ this.ANGLE_UP = Math.PI / 8;
-      /** @const */ this.Y_OFFSET = -0.9;
+      /** @const */ this.Y_OFFSET = -1.0;
       /** @const */ this.Z_OFFSET = -1.8;
 
       this.element = new DomUiElement('#vkb');
diff --git a/chrome/browser/thumbnails/content_analysis_unittest.cc b/chrome/browser/thumbnails/content_analysis_unittest.cc
index 325615e..6d44d14 100644
--- a/chrome/browser/thumbnails/content_analysis_unittest.cc
+++ b/chrome/browser/thumbnails/content_analysis_unittest.cc
@@ -88,7 +88,7 @@
   canvas.FillRect(gfx::Rect(0, 0, 800, 600), SkColorSetRGB(10, 10, 10));
   canvas.FillRect(gfx::Rect(400, 300, 1, 1), SkColorSetRGB(255, 255, 255));
 
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
 
   SkBitmap reduced_color;
   reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(),
@@ -131,7 +131,7 @@
   canvas.FillRect(gfx::Rect(0, 0, 800, 600), SkColorSetRGB(0, 0, 0));
   canvas.DrawRect(draw_rect, SkColorSetRGB(255, 255, 255));
 
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
 
   SkBitmap reduced_color;
   reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(),
@@ -169,7 +169,7 @@
   canvas.FillRect(image_rect, SkColorSetRGB(0, 0, 0));
   canvas.DrawRect(draw_rect, SkColorSetRGB(255, 255, 255));
 
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
   SkBitmap reduced_color;
   reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(),
                                                 source.height()));
@@ -232,7 +232,7 @@
   canvas.DrawRect(gfx::Rect(300, 250, 99, 100), SkColorSetRGB(255, 255, 255));
   canvas.DrawRect(gfx::Rect(401, 250, 99, 100), SkColorSetRGB(255, 255, 255));
 
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
   SkBitmap reduced_color;
   reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(),
                                                 source.height()));
@@ -554,7 +554,7 @@
   std::fill_n(columns.begin() + 300, 100, true);
   std::fill_n(columns.begin() + 500, 100, true);
 
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
   SkBitmap result = ComputeDecimatedImage(source, rows, columns);
   EXPECT_FALSE(result.empty());
   EXPECT_EQ(300, result.width());
@@ -666,7 +666,7 @@
     canvas.DrawRect(pict_rect, SkColorSetRGB(0, 0, 0));
   }
 
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
 
   SkBitmap result = CreateRetargetedThumbnailImage(
       source, gfx::Size(424, 264), 2.5);
diff --git a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc b/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc
index ef13e40..7fff79c 100644
--- a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc
+++ b/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc
@@ -140,7 +140,7 @@
 
   // The image consists of vertical non-overlapping stripes 150 pixels wide.
   canvas.FillRect(gfx::Rect(200, 200, 800, 400), SkColorSetRGB(255, 255, 255));
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
 
   ConsumerCallbackCatcher catcher;
   const gfx::Size thumbnail_size(432, 284);
diff --git a/chrome/browser/thumbnails/simple_thumbnail_crop_unittest.cc b/chrome/browser/thumbnails/simple_thumbnail_crop_unittest.cc
index 535553c..e321e58 100644
--- a/chrome/browser/thumbnails/simple_thumbnail_crop_unittest.cc
+++ b/chrome/browser/thumbnails/simple_thumbnail_crop_unittest.cc
@@ -24,7 +24,7 @@
 TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_TallerThanWide) {
   // The input bitmap is vertically long.
   gfx::Canvas canvas(gfx::Size(40, 90), 1.0f, true);
-  SkBitmap bitmap = canvas.ToBitmap();
+  SkBitmap bitmap = canvas.GetBitmap();
 
   // The desired size is square.
   thumbnails::ClipResult clip_result = thumbnails::CLIP_RESULT_NOT_CLIPPED;
@@ -40,7 +40,7 @@
 TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_WiderThanTall) {
   // The input bitmap is horizontally long.
   gfx::Canvas canvas(gfx::Size(70, 40), 1.0f, true);
-  SkBitmap bitmap = canvas.ToBitmap();
+  SkBitmap bitmap = canvas.GetBitmap();
 
   // The desired size is square.
   thumbnails::ClipResult clip_result = thumbnails::CLIP_RESULT_NOT_CLIPPED;
@@ -56,7 +56,7 @@
 TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_TooWiderThanTall) {
   // The input bitmap is horizontally very long.
   gfx::Canvas canvas(gfx::Size(90, 40), 1.0f, true);
-  SkBitmap bitmap = canvas.ToBitmap();
+  SkBitmap bitmap = canvas.GetBitmap();
 
   // The desired size is square.
   thumbnails::ClipResult clip_result = thumbnails::CLIP_RESULT_NOT_CLIPPED;
@@ -72,7 +72,7 @@
 TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_NotClipped) {
   // The input bitmap is square.
   gfx::Canvas canvas(gfx::Size(40, 40), 1.0f, true);
-  SkBitmap bitmap = canvas.ToBitmap();
+  SkBitmap bitmap = canvas.GetBitmap();
 
   // The desired size is square.
   thumbnails::ClipResult clip_result = thumbnails::CLIP_RESULT_NOT_CLIPPED;
@@ -88,7 +88,7 @@
 TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_NonSquareOutput) {
   // The input bitmap is square.
   gfx::Canvas canvas(gfx::Size(40, 40), 1.0f, true);
-  SkBitmap bitmap = canvas.ToBitmap();
+  SkBitmap bitmap = canvas.GetBitmap();
 
   // The desired size is horizontally long.
   thumbnails::ClipResult clip_result = thumbnails::CLIP_RESULT_NOT_CLIPPED;
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc
index c01a8466..554d1cc 100644
--- a/chrome/browser/ui/browser_ui_prefs.cc
+++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -71,12 +71,6 @@
   registry->RegisterDictionaryPref(prefs::kBrowserWindowPlacement);
   registry->RegisterDictionaryPref(prefs::kBrowserWindowPlacementPopup);
   registry->RegisterDictionaryPref(prefs::kAppWindowPlacement);
-  registry->RegisterBooleanPref(prefs::kImportAutofillFormData, true);
-  registry->RegisterBooleanPref(prefs::kImportBookmarks, true);
-  registry->RegisterBooleanPref(prefs::kImportHistory, true);
-  registry->RegisterBooleanPref(prefs::kImportHomepage, true);
-  registry->RegisterBooleanPref(prefs::kImportSavedPasswords, true);
-  registry->RegisterBooleanPref(prefs::kImportSearchEngine, true);
   registry->RegisterBooleanPref(
       prefs::kEnableDoNotTrack,
       false,
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler.cc b/chrome/browser/ui/webui/settings/profile_info_handler.cc
index 6d38d2b..d577cd5 100644
--- a/chrome/browser/ui/webui/settings/profile_info_handler.cc
+++ b/chrome/browser/ui/webui/settings/profile_info_handler.cc
@@ -214,8 +214,9 @@
     name = base::UTF16ToUTF8(entry->GetName());
 
     if (entry->IsUsingGAIAPicture() && entry->GetGAIAPicture()) {
-      gfx::Image icon =
-          profiles::GetAvatarIconForWebUI(entry->GetAvatarIcon(), true);
+      constexpr int kAvatarIconSize = 40;
+      gfx::Image icon = profiles::GetSizedAvatarIcon(
+          entry->GetAvatarIcon(), true, kAvatarIconSize, kAvatarIconSize);
       icon_url = webui::GetBitmapDataUrl(icon.AsBitmap());
     } else {
       icon_url = profiles::GetDefaultAvatarIconUrl(entry->GetAvatarIconIndex());
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 786a279..cf12a9f 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -96,10 +96,6 @@
 // user promoting Chrome for iOS.
 const base::Feature kDesktopIOSPromotion{"DesktopIOSPromotion",
                                          base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Disables the AutoImport feature on first run. See crbug.com/555550
-const base::Feature kDisableFirstRunAutoImportWin{
-    "DisableFirstRunAutoImport", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
 // Experiment to display a toggle allowing users to opt-out of persisting a
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index f44f462..24dbb6c 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -62,7 +62,6 @@
 
 #if defined(OS_WIN)
 extern const base::Feature kDesktopIOSPromotion;
-extern const base::Feature kDisableFirstRunAutoImportWin;
 #endif  // defined(OS_WIN)
 
 extern const base::Feature kDisplayPersistenceToggleInPermissionPrompts;
diff --git a/chrome/common/trace_event_args_whitelist.cc b/chrome/common/trace_event_args_whitelist.cc
index 740852f4..3b021a24 100644
--- a/chrome/common/trace_event_args_whitelist.cc
+++ b/chrome/common/trace_event_args_whitelist.cc
@@ -24,7 +24,6 @@
 const WhitelistEntry kEventArgsWhitelist[] = {
     {"__metadata", "thread_name", nullptr},
     {"__metadata", "process_name", nullptr},
-    {"__metadata", "process_runtime_sec", nullptr},
     {"ipc", "SyncChannel::Send", nullptr},
     {"toplevel", "*", nullptr},
     {"latencyInfo", "*", kInputLatencyAllowedArgs},
diff --git a/chrome/installer/util/master_preferences.cc b/chrome/installer/util/master_preferences.cc
index fa01417..223aa32 100644
--- a/chrome/installer/util/master_preferences.cc
+++ b/chrome/installer/util/master_preferences.cc
@@ -226,6 +226,29 @@
         installer::master_preferences::kDoNotCreateQuickLaunchShortcut, true);
   }
 
+  // Deprecated boolean import master preferences now mapped to their duplicates
+  // in prefs::.
+  static constexpr char kDistroImportHistoryPref[] = "import_history";
+  static constexpr char kDistroImportHomePagePref[] = "import_home_page";
+  static constexpr char kDistroImportSearchPref[] = "import_search_engine";
+  static constexpr char kDistroImportBookmarksPref[] = "import_bookmarks";
+
+  static constexpr struct {
+    const char* old_distro_pref_path;
+    const char* modern_pref_path;
+  } kLegacyDistroImportPrefMappings[] = {
+      {kDistroImportBookmarksPref, prefs::kImportBookmarks},
+      {kDistroImportHistoryPref, prefs::kImportHistory},
+      {kDistroImportHomePagePref, prefs::kImportHomepage},
+      {kDistroImportSearchPref, prefs::kImportSearchEngine},
+  };
+
+  for (const auto& mapping : kLegacyDistroImportPrefMappings) {
+    bool value = false;
+    if (GetBool(mapping.old_distro_pref_path, &value))
+      master_dictionary_->SetBoolean(mapping.modern_pref_path, value);
+  }
+
 #if BUILDFLAG(ENABLE_RLZ)
   // Map the RLZ ping delay shipped in the distribution dictionary into real
   // prefs.
diff --git a/chrome/installer/util/master_preferences.h b/chrome/installer/util/master_preferences.h
index 61582943..1eadf29 100644
--- a/chrome/installer/util/master_preferences.h
+++ b/chrome/installer/util/master_preferences.h
@@ -39,11 +39,7 @@
 //   "distribution": {
 //      "create_all_shortcuts": true,
 //      "do_not_launch_chrome": false,
-//      "import_bookmarks": false,
 //      "import_bookmarks_from_file": "c:\\path",
-//      "import_history": false,
-//      "import_home_page": false,
-//      "import_search_engine": true,
 //      "make_chrome_default": false,
 //      "make_chrome_default_for_user": true,
 //      "ping_delay": 40,
@@ -65,7 +61,13 @@
 //      "https://igoogle.com"
 //   ],
 //   "homepage": "http://example.org",
-//   "homepage_is_newtabpage": false
+//   "homepage_is_newtabpage": false,
+//   "import_autofill_form_data": false,
+//   "import_bookmarks": false,
+//   "import_history": false,
+//   "import_home_page": false,
+//   "import_saved_passwords": false,
+//   "import_search_engine": false
 // }
 //
 // A reserved "distribution" entry in the file is used to group related
diff --git a/chrome/installer/util/master_preferences_constants.cc b/chrome/installer/util/master_preferences_constants.cc
index 2a1aeed..81aeae0 100644
--- a/chrome/installer/util/master_preferences_constants.cc
+++ b/chrome/installer/util/master_preferences_constants.cc
@@ -8,12 +8,8 @@
 namespace master_preferences {
   const char kDisableLogging[] = "disable_logging";
   const char kDistroDict[] = "distribution";
-  const char kDistroImportBookmarksPref[] = "import_bookmarks";
   const char kDistroImportBookmarksFromFilePref[] =
       "import_bookmarks_from_file";
-  const char kDistroImportHistoryPref[] = "import_history";
-  const char kDistroImportHomePagePref[] = "import_home_page";
-  const char kDistroImportSearchPref[] = "import_search_engine";
   const char kDistroSuppressDefaultBrowserPromptPref[] =
       "suppress_default_browser_prompt_for_version";
   const char kDistroSuppressFirstRunBubble[] = "suppress_first_run_bubble";
diff --git a/chrome/installer/util/master_preferences_constants.h b/chrome/installer/util/master_preferences_constants.h
index c37b732..1ac32af 100644
--- a/chrome/installer/util/master_preferences_constants.h
+++ b/chrome/installer/util/master_preferences_constants.h
@@ -19,17 +19,9 @@
 extern const char kDisableLogging[];
 // Name of the dictionary that holds the distribution values.
 extern const char kDistroDict[];
-// Boolean pref that triggers silent import of the default browser bookmarks.
-extern const char kDistroImportBookmarksPref[];
 // String pref that triggers silent import of bookmarks from the html file at
 // given path.
 extern const char kDistroImportBookmarksFromFilePref[];
-// Boolean pref that triggers silent import of the default browser history.
-extern const char kDistroImportHistoryPref[];
-// Boolean pref that triggers silent import of the default browser homepage.
-extern const char kDistroImportHomePagePref[];
-// Boolean pref that triggers silent import of the default search engine.
-extern const char kDistroImportSearchPref[];
 // String of Chrome version for which the "set as default browser" infobar will
 // never be shown.
 extern const char kDistroSuppressDefaultBrowserPromptPref[];
diff --git a/chrome/installer/util/master_preferences_unittest.cc b/chrome/installer/util/master_preferences_unittest.cc
index e91b8b9..0b53d91 100644
--- a/chrome/installer/util/master_preferences_unittest.cc
+++ b/chrome/installer/util/master_preferences_unittest.cc
@@ -75,11 +75,7 @@
       "{ \n"
       "  \"distribution\": { \n"
       "     \"show_welcome_page\": true,\n"
-      "     \"import_search_engine\": true,\n"
-      "     \"import_history\": true,\n"
-      "     \"import_bookmarks\": true,\n"
       "     \"import_bookmarks_from_file\": \"c:\\\\foo\",\n"
-      "     \"import_home_page\": true,\n"
       "     \"welcome_page_on_os_upgrade_enabled\": true,\n"
       "     \"do_not_create_any_shortcuts\": true,\n"
       "     \"do_not_create_desktop_shortcut\": true,\n"
@@ -93,7 +89,7 @@
       "     \"require_eula\": true\n"
       "  },\n"
       "  \"blah\": {\n"
-      "     \"import_history\": false\n"
+      "     \"show_welcome_page\": false\n"
       "  }\n"
       "} \n";
 
@@ -103,10 +99,6 @@
   EXPECT_TRUE(prefs.read_from_file());
 
   const char* const expected_true[] = {
-      installer::master_preferences::kDistroImportSearchPref,
-      installer::master_preferences::kDistroImportHistoryPref,
-      installer::master_preferences::kDistroImportBookmarksPref,
-      installer::master_preferences::kDistroImportHomePagePref,
       installer::master_preferences::kDistroWelcomePageOnOSUpgradeEnabled,
       installer::master_preferences::kDoNotCreateAnyShortcuts,
       installer::master_preferences::kDoNotCreateDesktopShortcut,
@@ -135,16 +127,14 @@
 
 TEST_F(MasterPreferencesTest, ParseMissingDistroParams) {
   const char text[] =
-    "{ \n"
-    "  \"distribution\": { \n"
-    "     \"import_search_engine\": true,\n"
-    "     \"import_bookmarks\": false,\n"
-    "     \"import_bookmarks_from_file\": \"\",\n"
-    "     \"do_not_create_desktop_shortcut\": true,\n"
-    "     \"do_not_create_quick_launch_shortcut\": true,\n"
-    "     \"do_not_launch_chrome\": true\n"
-    "  }\n"
-    "} \n";
+      "{ \n"
+      "  \"distribution\": { \n"
+      "     \"import_bookmarks_from_file\": \"\",\n"
+      "     \"do_not_create_desktop_shortcut\": true,\n"
+      "     \"do_not_create_quick_launch_shortcut\": true,\n"
+      "     \"do_not_launch_chrome\": false\n"
+      "  }\n"
+      "} \n";
 
   EXPECT_TRUE(base::WriteFile(prefs_file(), text,
                               static_cast<int>(strlen(text))));
@@ -152,11 +142,9 @@
   EXPECT_TRUE(prefs.read_from_file());
 
   ExpectedBooleans expected_bool[] = {
-    { installer::master_preferences::kDistroImportSearchPref, true },
-    { installer::master_preferences::kDistroImportBookmarksPref, false },
-    { installer::master_preferences::kDoNotCreateDesktopShortcut, true },
-    { installer::master_preferences::kDoNotCreateQuickLaunchShortcut, true },
-    { installer::master_preferences::kDoNotLaunchChrome, true },
+      {installer::master_preferences::kDoNotCreateDesktopShortcut, true},
+      {installer::master_preferences::kDoNotCreateQuickLaunchShortcut, true},
+      {installer::master_preferences::kDoNotLaunchChrome, false},
   };
 
   bool value = false;
@@ -166,7 +154,6 @@
   }
 
   const char* const missing_bools[] = {
-    installer::master_preferences::kDistroImportHomePagePref,
     installer::master_preferences::kDistroWelcomePageOnOSUpgradeEnabled,
     installer::master_preferences::kDoNotRegisterForUpdateLaunch,
     installer::master_preferences::kMakeChromeDefault,
@@ -318,6 +305,10 @@
       "{"
       "  \"distribution\": {"
       "     \"create_all_shortcuts\": false,\n"
+      "     \"import_bookmarks\": true,\n"
+      "     \"import_history\": true,\n"
+      "     \"import_home_page\": true,\n"
+      "     \"import_search_engine\": true,\n"
       "     \"ping_delay\": 40\n"
       "  }"
       "}";
@@ -340,6 +331,20 @@
   EXPECT_TRUE(do_not_create_quick_launch_shortcut);
   EXPECT_FALSE(do_not_create_taskbar_shortcut);
 
+  bool actual_value = false;
+  EXPECT_TRUE(prefs.master_dictionary().GetBoolean(prefs::kImportBookmarks,
+                                                   &actual_value));
+  EXPECT_TRUE(actual_value);
+  EXPECT_TRUE(prefs.master_dictionary().GetBoolean(prefs::kImportHistory,
+                                                   &actual_value));
+  EXPECT_TRUE(actual_value);
+  EXPECT_TRUE(prefs.master_dictionary().GetBoolean(prefs::kImportHomepage,
+                                                   &actual_value));
+  EXPECT_TRUE(actual_value);
+  EXPECT_TRUE(prefs.master_dictionary().GetBoolean(prefs::kImportSearchEngine,
+                                                   &actual_value));
+  EXPECT_TRUE(actual_value);
+
 #if BUILDFLAG(ENABLE_RLZ)
   int rlz_ping_delay = 0;
   EXPECT_TRUE(prefs.master_dictionary().GetInteger(prefs::kRlzPingDelaySeconds,
diff --git a/chrome/test/data/webui/settings/route_tests.js b/chrome/test/data/webui/settings/route_tests.js
index 7344683e..ab0c682 100644
--- a/chrome/test/data/webui/settings/route_tests.js
+++ b/chrome/test/data/webui/settings/route_tests.js
@@ -106,7 +106,7 @@
     return testNavigateBackUsesHistory(
         settings.Route.ADVANCED,
         settings.Route.PEOPLE,
-        settings.Route.ADVANCED);
+        settings.Route.BASIC);
   });
 
   test('navigate back to sibling route', function() {
@@ -144,6 +144,11 @@
     assertEquals('', settings.getQueryParameters().toString());
   });
 
+  test('navigateTo ADVANCED forwards to BASIC', function() {
+    settings.navigateTo(settings.Route.ADVANCED);
+    assertEquals(settings.Route.BASIC, settings.getCurrentRoute());
+  });
+
   test('popstate flag works', function() {
     settings.navigateTo(settings.Route.BASIC);
     assertFalse(settings.lastRouteChangeWasPopstate());
diff --git a/components/OWNERS b/components/OWNERS
index 1dbc3891..5e5ca55 100644
--- a/components/OWNERS
+++ b/components/OWNERS
@@ -11,8 +11,6 @@
 per-file crash_strings.grdp=file://components/crash/OWNERS
 per-file dom_distiller_strings.grdp=file://components/dom_distiller/OWNERS
 per-file error_page_strings.grdp=file://components/error_page/OWNERS
-per-file nacl_helper_nonsfi_unittests.isolate=file://components/nacl/OWNERS
-per-file nacl_loader_unittests.isolate=file://components/nacl/OWNERS
 per-file ntp_snippets_strings.grdp=file://components/ntp_snippets/OWNERS
 per-file omnibox_strings.grdp=file://components/omnibox/OWNERS
 per-file password_manager_strings.grdp=file://components/password_manager/OWNERS
@@ -31,9 +29,6 @@
 per-file translate_strings.grdp=file://components/translate/OWNERS
 per-file undo_strings.grdp=file://components/undo/OWNERS
 per-file web_contents_delegate_android_strings.grdp=file://components/web_contents_delegate_android/OWNERS
-per-file *.isolate=maruel@chromium.org
-per-file *.isolate=tandrii@chromium.org
-per-file *.isolate=vadimsh@chromium.org
 
 # These are for the common case of adding or removing tests. If you're making
 # structural changes, please get a review from one of the overall components
diff --git a/components/offline_items_collection/core/offline_content_aggregator.cc b/components/offline_items_collection/core/offline_content_aggregator.cc
index b856247..acbfd5a 100644
--- a/components/offline_items_collection/core/offline_content_aggregator.cc
+++ b/components/offline_items_collection/core/offline_content_aggregator.cc
@@ -39,19 +39,28 @@
   // Validate that this is the first OfflineContentProvider registered that is
   // associated with |name_space|.
   DCHECK(providers_.find(name_space) == providers_.end());
-  DCHECK(pending_actions_.find(provider) == pending_actions_.end());
+
+  // Only set up the connection to the provider if the provider isn't associated
+  // with any other namespace.
+  if (!MapContainsValue(providers_, provider))
+    provider->AddObserver(this);
 
   providers_[name_space] = provider;
-  provider->AddObserver(this);
 }
 
 void OfflineContentAggregator::UnregisterProvider(
     const std::string& name_space) {
-  auto it = providers_.find(name_space);
+  auto provider_it = providers_.find(name_space);
 
-  it->second->RemoveObserver(this);
-  pending_actions_.erase(it->second);
-  providers_.erase(it);
+  OfflineContentProvider* provider = provider_it->second;
+  providers_.erase(provider_it);
+
+  // Only clean up the connection to the provider if the provider isn't
+  // associated with any other namespace.
+  if (!MapContainsValue(providers_, provider)) {
+    provider->RemoveObserver(this);
+    pending_actions_.erase(provider);
+  }
 }
 
 bool OfflineContentAggregator::AreItemsAvailable() {
@@ -119,12 +128,17 @@
 
 OfflineContentProvider::OfflineItemList
 OfflineContentAggregator::GetAllItems() {
+  // Create a set of unique providers to iterate over.
+  std::set<OfflineContentProvider*> providers;
+  for (auto provider_it : providers_)
+    providers.insert(provider_it.second);
+
   OfflineItemList items;
-  for (auto& it : providers_) {
-    if (!it.second->AreItemsAvailable())
+  for (auto* provider : providers) {
+    if (!provider->AreItemsAvailable())
       continue;
 
-    OfflineItemList provider_items = it.second->GetAllItems();
+    OfflineItemList provider_items = provider->GetAllItems();
     items.insert(items.end(), provider_items.begin(), provider_items.end());
   }
 
diff --git a/components/offline_items_collection/core/offline_content_aggregator.h b/components/offline_items_collection/core/offline_content_aggregator.h
index 6271d9e..0349708 100644
--- a/components/offline_items_collection/core/offline_content_aggregator.h
+++ b/components/offline_items_collection/core/offline_content_aggregator.h
@@ -57,6 +57,17 @@
   // |name_space|.  UI actions taken on OfflineItems with |name_space| will be
   // routed to |provider|.  |provider| is expected to only expose OfflineItems
   // with |name_space| set.
+  // It is okay to register the same provider with multiple unique namespaces.
+  // The class will work as expected with a few caveats.  These are fixable if
+  // they are necessary for proper operation.  Contact dtrainor@ if changes to
+  // this behavior is needed.
+  //   1. Unregistering the first namespace won't remove any pending actions
+  //      that are queued for this provider.  That means the provider might
+  //      still get actions for the removed namespace once it is done
+  //      initializing itself.  This case must be handled by the individual
+  //      provider for now.
+  //   2. The provider needs to handle calls to GetAllItems properly (not return
+  //      any items for a namespace that it didn't register).
   void RegisterProvider(const std::string& name_space,
                         OfflineContentProvider* provider);
 
diff --git a/components/offline_items_collection/core/offline_content_aggregator_unittest.cc b/components/offline_items_collection/core/offline_content_aggregator_unittest.cc
index 0ed47057..3619340 100644
--- a/components/offline_items_collection/core/offline_content_aggregator_unittest.cc
+++ b/components/offline_items_collection/core/offline_content_aggregator_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
 
+#include <map>
+
 #include "base/memory/ptr_util.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -14,11 +16,41 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using testing::_;
+using testing::ContainerEq;
 using testing::Return;
 
 namespace offline_items_collection {
 namespace {
 
+struct CompareOfflineItemsById {
+  bool operator()(const OfflineItem& a, const OfflineItem& b) const {
+    return a.id < b.id;
+  }
+};
+
+// A custom comparator that makes sure two vectors contain the same elements.
+// TODO(dtrainor): Look into building a better matcher that works with gmock.
+template <typename T>
+bool VectorContentsEq(const std::vector<T>& list1,
+                      const std::vector<T>& list2) {
+  if (list1.size() != list2.size())
+    return false;
+
+  std::map<T, int, CompareOfflineItemsById> occurance_counts;
+  for (auto it = list1.begin(); it != list1.end(); it++)
+    occurance_counts[*it]++;
+
+  for (auto it = list2.begin(); it != list2.end(); it++)
+    occurance_counts[*it]--;
+
+  for (auto it = occurance_counts.begin(); it != occurance_counts.end(); it++) {
+    if (it->second != 0)
+      return false;
+  }
+
+  return true;
+}
+
 // Helper class that automatically unregisters itself from the aggregator in the
 // case that someone calls OpenItem on it.
 class OpenItemRemovalOfflineContentProvider
@@ -141,12 +173,13 @@
   EXPECT_CALL(provider2, GetAllItems()).WillRepeatedly(Return(items2));
 
   provider1.NotifyOnItemsAvailable();
-  EXPECT_EQ(items1, aggregator_.GetAllItems());
+  EXPECT_TRUE(VectorContentsEq(items1, aggregator_.GetAllItems()));
 
   OfflineContentProvider::OfflineItemList combined_items(items1);
   combined_items.insert(combined_items.end(), items2.begin(), items2.end());
   provider2.NotifyOnItemsAvailable();
-  EXPECT_EQ(combined_items, aggregator_.GetAllItems());
+
+  EXPECT_TRUE(VectorContentsEq(combined_items, aggregator_.GetAllItems()));
 }
 
 TEST_F(OfflineContentAggregatorTest, QueryingItemFromRemovedProvider) {
@@ -404,5 +437,41 @@
   provider1.NotifyOnItemsAvailable();
 }
 
+TEST_F(OfflineContentAggregatorTest, SameProviderWithMultipleNamespaces) {
+  MockOfflineContentProvider provider;
+  ScopedMockOfflineContentProvider::ScopedMockObserver observer(&aggregator_);
+
+  ContentId id1("1", "A");
+  ContentId id2("2", "B");
+  OfflineItem item1(id1);
+  OfflineItem item2(id2);
+  OfflineContentProvider::OfflineItemList items;
+  items.push_back(item1);
+  items.push_back(item2);
+
+  aggregator_.RegisterProvider("1", &provider);
+  aggregator_.RegisterProvider("2", &provider);
+  EXPECT_TRUE(provider.HasObserver(&aggregator_));
+
+  EXPECT_CALL(provider, GetAllItems()).WillRepeatedly(Return(items));
+  EXPECT_CALL(provider, GetItemById(id1)).WillRepeatedly(Return(&item1));
+  EXPECT_CALL(provider, GetItemById(id2)).WillRepeatedly(Return(&item2));
+
+  EXPECT_CALL(observer, OnItemsAvailable(&aggregator_)).Times(1);
+  provider.NotifyOnItemsAvailable();
+
+  EXPECT_TRUE(VectorContentsEq(items, aggregator_.GetAllItems()));
+  EXPECT_EQ(&item1, aggregator_.GetItemById(id1));
+  EXPECT_EQ(&item2, aggregator_.GetItemById(id2));
+
+  aggregator_.UnregisterProvider("1");
+  EXPECT_TRUE(provider.HasObserver(&aggregator_));
+  EXPECT_EQ(nullptr, aggregator_.GetItemById(id1));
+  EXPECT_EQ(&item2, aggregator_.GetItemById(id2));
+
+  aggregator_.UnregisterProvider("2");
+  EXPECT_FALSE(provider.HasObserver(&aggregator_));
+}
+
 }  // namespace
 }  // namespace offline_items_collection
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index 371d02a..e1b3201 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -52,8 +52,8 @@
     "form_saver.h",
     "form_saver_impl.cc",
     "form_saver_impl.h",
-    "http_password_migrator.cc",
-    "http_password_migrator.h",
+    "http_password_store_migrator.cc",
+    "http_password_store_migrator.h",
     "import/csv_reader.cc",
     "import/csv_reader.h",
     "import/password_csv_reader.cc",
@@ -280,7 +280,7 @@
     "facet_manager_unittest.cc",
     "form_fetcher_impl_unittest.cc",
     "form_saver_impl_unittest.cc",
-    "http_password_migrator_unittest.cc",
+    "http_password_store_migrator_unittest.cc",
     "import/csv_reader_unittest.cc",
     "import/password_csv_reader_unittest.cc",
     "import/password_importer_unittest.cc",
diff --git a/components/password_manager/core/browser/credential_manager_pending_request_task.cc b/components/password_manager/core/browser/credential_manager_pending_request_task.cc
index c82cabf..6600bd4 100644
--- a/components/password_manager/core/browser/credential_manager_pending_request_task.cc
+++ b/components/password_manager/core/browser/credential_manager_pending_request_task.cc
@@ -133,7 +133,7 @@
     std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
   if (results.empty()) {
     // Try to migrate the HTTP passwords and process them later.
-    http_migrator_ = base::MakeUnique<HttpPasswordMigrator>(
+    http_migrator_ = base::MakeUnique<HttpPasswordStoreMigrator>(
         origin_, delegate_->client(), this);
     return;
   }
diff --git a/components/password_manager/core/browser/credential_manager_pending_request_task.h b/components/password_manager/core/browser/credential_manager_pending_request_task.h
index 289a820e..a444a72 100644
--- a/components/password_manager/core/browser/credential_manager_pending_request_task.h
+++ b/components/password_manager/core/browser/credential_manager_pending_request_task.h
@@ -12,7 +12,7 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
-#include "components/password_manager/core/browser/http_password_migrator.h"
+#include "components/password_manager/core/browser/http_password_store_migrator.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
 #include "url/gurl.h"
@@ -55,7 +55,7 @@
 // Retrieves credentials from the PasswordStore.
 class CredentialManagerPendingRequestTask
     : public PasswordStoreConsumer,
-      public HttpPasswordMigrator::Consumer {
+      public HttpPasswordStoreMigrator::Consumer {
  public:
   CredentialManagerPendingRequestTask(
       CredentialManagerPendingRequestTaskDelegate* delegate,
@@ -73,7 +73,7 @@
       std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
 
  private:
-  // HttpPasswordMigrator::Consumer:
+  // HttpPasswordStoreMigrator::Consumer:
   void ProcessMigratedForms(
       std::vector<std::unique_ptr<autofill::PasswordForm>> forms) override;
 
@@ -87,7 +87,7 @@
   const bool include_passwords_;
   std::set<std::string> federations_;
 
-  std::unique_ptr<HttpPasswordMigrator> http_migrator_;
+  std::unique_ptr<HttpPasswordStoreMigrator> http_migrator_;
 
   DISALLOW_COPY_AND_ASSIGN(CredentialManagerPendingRequestTask);
 };
diff --git a/components/password_manager/core/browser/form_fetcher_impl.cc b/components/password_manager/core/browser/form_fetcher_impl.cc
index c4f922c..b73501a 100644
--- a/components/password_manager/core/browser/form_fetcher_impl.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -128,8 +128,8 @@
 
   if (should_migrate_http_passwords_ && results.empty() &&
       form_digest_.origin.SchemeIs(url::kHttpsScheme)) {
-    http_migrator_ = base::MakeUnique<HttpPasswordMigrator>(form_digest_.origin,
-                                                            client_, this);
+    http_migrator_ = base::MakeUnique<HttpPasswordStoreMigrator>(
+        form_digest_.origin, client_, this);
     return;
   }
 
diff --git a/components/password_manager/core/browser/form_fetcher_impl.h b/components/password_manager/core/browser/form_fetcher_impl.h
index a9a1e7ac..af6ba69 100644
--- a/components/password_manager/core/browser/form_fetcher_impl.h
+++ b/components/password_manager/core/browser/form_fetcher_impl.h
@@ -11,7 +11,7 @@
 
 #include "base/macros.h"
 #include "components/password_manager/core/browser/form_fetcher.h"
-#include "components/password_manager/core/browser/http_password_migrator.h"
+#include "components/password_manager/core/browser/http_password_store_migrator.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
 
@@ -23,7 +23,7 @@
 // with a particular origin.
 class FormFetcherImpl : public FormFetcher,
                         public PasswordStoreConsumer,
-                        public HttpPasswordMigrator::Consumer {
+                        public HttpPasswordStoreMigrator::Consumer {
  public:
   // |form_digest| describes what credentials need to be retrieved and
   // |client| serves the PasswordStore, the logging information etc.
@@ -48,7 +48,7 @@
       std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
   void OnGetSiteStatistics(std::vector<InteractionsStats> stats) override;
 
-  // HttpPasswordMigrator::Consumer:
+  // HttpPasswordStoreMigrator::Consumer:
   void ProcessMigratedForms(
       std::vector<std::unique_ptr<autofill::PasswordForm>> forms) override;
 
@@ -96,7 +96,7 @@
   const bool should_migrate_http_passwords_;
 
   // Does the actual migration.
-  std::unique_ptr<HttpPasswordMigrator> http_migrator_;
+  std::unique_ptr<HttpPasswordStoreMigrator> http_migrator_;
 
   DISALLOW_COPY_AND_ASSIGN(FormFetcherImpl);
 };
diff --git a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
index 310c7baf..e3e2806 100644
--- a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
@@ -477,7 +477,7 @@
   EXPECT_CALL(*mock_store_, AddLogin(https_form));
   EXPECT_CALL(consumer_,
               ProcessMatches(UnorderedElementsAre(Pointee(https_form)), 0u));
-  static_cast<HttpPasswordMigrator*>(migrator_ptr.get())
+  static_cast<HttpPasswordStoreMigrator*>(migrator_ptr.get())
       ->OnGetPasswordStoreResults(MakeResults({http_form}));
   EXPECT_THAT(form_fetcher_->GetFederatedMatches(), IsEmpty());
 
@@ -548,7 +548,7 @@
 
   // Now perform the actual migration.
   EXPECT_CALL(*mock_store_, AddLogin(https_form));
-  static_cast<HttpPasswordMigrator*>(migrator_ptr.get())
+  static_cast<HttpPasswordStoreMigrator*>(migrator_ptr.get())
       ->OnGetPasswordStoreResults(MakeResults({http_form}));
   EXPECT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
 }
diff --git a/components/password_manager/core/browser/http_password_migrator.cc b/components/password_manager/core/browser/http_password_store_migrator.cc
similarity index 85%
rename from components/password_manager/core/browser/http_password_migrator.cc
rename to components/password_manager/core/browser/http_password_store_migrator.cc
index 1bfb65e6..db243cb 100644
--- a/components/password_manager/core/browser/http_password_migrator.cc
+++ b/components/password_manager/core/browser/http_password_store_migrator.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 "components/password_manager/core/browser/http_password_migrator.h"
+#include "components/password_manager/core/browser/http_password_store_migrator.h"
 
 #include "base/memory/weak_ptr.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
@@ -21,16 +21,17 @@
     const base::WeakPtr<PasswordStoreConsumer>& migrator,
     bool is_hsts) {
   if (migrator) {
-    static_cast<HttpPasswordMigrator*>(migrator.get())
+    static_cast<HttpPasswordStoreMigrator*>(migrator.get())
         ->OnHSTSQueryResult(is_hsts);
   }
 }
 
 }  // namespace
 
-HttpPasswordMigrator::HttpPasswordMigrator(const GURL& https_origin,
-                                           const PasswordManagerClient* client,
-                                           Consumer* consumer)
+HttpPasswordStoreMigrator::HttpPasswordStoreMigrator(
+    const GURL& https_origin,
+    const PasswordManagerClient* client,
+    Consumer* consumer)
     : client_(client), consumer_(consumer) {
   DCHECK(client_);
   DCHECK(https_origin.is_valid());
@@ -41,14 +42,15 @@
   GURL http_origin = https_origin.ReplaceComponents(rep);
   PasswordStore::FormDigest form(autofill::PasswordForm::SCHEME_HTML,
                                  http_origin.GetOrigin().spec(), http_origin);
+  http_origin_domain_ = http_origin.GetOrigin();
   client_->GetPasswordStore()->GetLogins(form, this);
   client_->PostHSTSQueryForHost(
       https_origin, base::Bind(&OnHSTSQueryResultHelper, GetWeakPtr()));
 }
 
-HttpPasswordMigrator::~HttpPasswordMigrator() = default;
+HttpPasswordStoreMigrator::~HttpPasswordStoreMigrator() = default;
 
-void HttpPasswordMigrator::OnGetPasswordStoreResults(
+void HttpPasswordStoreMigrator::OnGetPasswordStoreResults(
     std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
   DCHECK(thread_checker_.CalledOnValidThread());
   results_ = std::move(results);
@@ -58,16 +60,19 @@
     ProcessPasswordStoreResults();
 }
 
-void HttpPasswordMigrator::OnHSTSQueryResult(bool is_hsts) {
+void HttpPasswordStoreMigrator::OnHSTSQueryResult(bool is_hsts) {
   DCHECK(thread_checker_.CalledOnValidThread());
   mode_ = is_hsts ? MigrationMode::MOVE : MigrationMode::COPY;
   got_hsts_query_result_ = true;
 
+  if (is_hsts)
+    client_->GetPasswordStore()->RemoveSiteStats(http_origin_domain_);
+
   if (got_password_store_results_)
     ProcessPasswordStoreResults();
 }
 
-void HttpPasswordMigrator::ProcessPasswordStoreResults() {
+void HttpPasswordStoreMigrator::ProcessPasswordStoreResults() {
   // Android and PSL matches are ignored.
   results_.erase(
       std::remove_if(results_.begin(), results_.end(),
diff --git a/components/password_manager/core/browser/http_password_migrator.h b/components/password_manager/core/browser/http_password_store_migrator.h
similarity index 75%
rename from components/password_manager/core/browser/http_password_migrator.h
rename to components/password_manager/core/browser/http_password_store_migrator.h
index 4f71156..47a378c 100644
--- a/components/password_manager/core/browser/http_password_migrator.h
+++ b/components/password_manager/core/browser/http_password_store_migrator.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HTTP_PASSWORD_MIGRATOR_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HTTP_PASSWORD_MIGRATOR_H_
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HTTP_PASSWORD_STORE_MIGRATOR_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HTTP_PASSWORD_STORE_MIGRATOR_H_
 
 #include <memory>
 #include <vector>
@@ -11,13 +11,12 @@
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
+#include "url/gurl.h"
 
 namespace autofill {
 struct PasswordForm;
 }
 
-class GURL;
-
 namespace password_manager {
 
 class PasswordManagerClient;
@@ -28,9 +27,12 @@
 // HTTP password is considered obsolete and will be replaced by an HTTPS
 // version. If HSTS is not enabled, some parts of the site might still be served
 // via HTTP, which is why the password is copied in this case.
-class HttpPasswordMigrator : public PasswordStoreConsumer {
+// Furthermore, if a site has migrated to HTTPS and HSTS is enabled, the
+// corresponding HTTP site statistics are cleared as well, since they are
+// obsolete.
+class HttpPasswordStoreMigrator : public PasswordStoreConsumer {
  public:
-  // API to be implemented by an embedder of HttpPasswordMigrator.
+  // API to be implemented by an embedder of HttpPasswordStoreMigrator.
   class Consumer {
    public:
     virtual ~Consumer() = default;
@@ -42,10 +44,10 @@
   };
 
   // |https_origin| should specify a valid HTTPS URL.
-  HttpPasswordMigrator(const GURL& https_origin,
-                       const PasswordManagerClient* client,
-                       Consumer* consumer);
-  ~HttpPasswordMigrator() override;
+  HttpPasswordStoreMigrator(const GURL& https_origin,
+                            const PasswordManagerClient* client,
+                            Consumer* consumer);
+  ~HttpPasswordStoreMigrator() override;
 
   // PasswordStoreConsumer:
   void OnGetPasswordStoreResults(
@@ -73,11 +75,12 @@
   bool got_password_store_results_ = false;
   MigrationMode mode_;
   std::vector<std::unique_ptr<autofill::PasswordForm>> results_;
+  GURL http_origin_domain_;
   base::ThreadChecker thread_checker_;
 
-  DISALLOW_COPY_AND_ASSIGN(HttpPasswordMigrator);
+  DISALLOW_COPY_AND_ASSIGN(HttpPasswordStoreMigrator);
 };
 
 }  // namespace password_manager
 
-#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HTTP_PASSWORD_MIGRATOR_H_
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HTTP_PASSWORD_STORE_MIGRATOR_H_
diff --git a/components/password_manager/core/browser/http_password_migrator_unittest.cc b/components/password_manager/core/browser/http_password_store_migrator_unittest.cc
similarity index 62%
rename from components/password_manager/core/browser/http_password_migrator_unittest.cc
rename to components/password_manager/core/browser/http_password_store_migrator_unittest.cc
index 084daa7..6aa5d2b 100644
--- a/components/password_manager/core/browser/http_password_migrator_unittest.cc
+++ b/components/password_manager/core/browser/http_password_store_migrator_unittest.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/password_manager/core/browser/http_password_migrator.h"
+#include "components/password_manager/core/browser/http_password_store_migrator.h"
 
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/password_manager/core/browser/mock_password_store.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
@@ -17,8 +18,10 @@
 
 using autofill::PasswordForm;
 using testing::ElementsAre;
+using testing::Invoke;
 using testing::Pointee;
 using testing::SaveArg;
+using testing::Unused;
 using testing::_;
 
 constexpr char kTestHttpsURL[] = "https://example.org/";
@@ -60,7 +63,7 @@
   return form;
 }
 
-class MockConsumer : public HttpPasswordMigrator::Consumer {
+class MockConsumer : public HttpPasswordStoreMigrator::Consumer {
  public:
   MOCK_METHOD1(ProcessForms,
                void(const std::vector<autofill::PasswordForm*>& forms));
@@ -92,13 +95,15 @@
 
 }  // namespace
 
-class HttpPasswordMigratorTest : public testing::Test {
+class HttpPasswordStoreMigratorTest : public testing::Test {
  public:
-  HttpPasswordMigratorTest()
+  HttpPasswordStoreMigratorTest()
       : mock_store_(new testing::StrictMock<MockPasswordStore>),
         client_(mock_store_.get()) {}
 
-  ~HttpPasswordMigratorTest() override { mock_store_->ShutdownOnUIThread(); }
+  ~HttpPasswordStoreMigratorTest() override {
+    mock_store_->ShutdownOnUIThread();
+  }
 
   MockConsumer& consumer() { return consumer_; }
   MockPasswordStore& store() { return *mock_store_; }
@@ -107,6 +112,7 @@
  protected:
   void TestEmptyStore(bool is_hsts);
   void TestFullStore(bool is_hsts);
+  void TestMigratorDeletionByConsumer(bool is_hsts);
 
  private:
   base::MessageLoop message_loop_;  // Used by mock_store_.
@@ -114,33 +120,45 @@
   scoped_refptr<MockPasswordStore> mock_store_;
   MockPasswordManagerClient client_;
 
-  DISALLOW_COPY_AND_ASSIGN(HttpPasswordMigratorTest);
+  DISALLOW_COPY_AND_ASSIGN(HttpPasswordStoreMigratorTest);
 };
 
-void HttpPasswordMigratorTest::TestEmptyStore(bool is_hsts) {
+void HttpPasswordStoreMigratorTest::TestEmptyStore(bool is_hsts) {
   PasswordStore::FormDigest form(autofill::PasswordForm::SCHEME_HTML,
                                  kTestHttpURL, GURL(kTestHttpURL));
   EXPECT_CALL(store(), GetLogins(form, _));
   PasswordManagerClient::HSTSCallback callback;
   EXPECT_CALL(client(), PostHSTSQueryForHost(GURL(kTestHttpsURL), _))
       .WillOnce(SaveArg<1>(&callback));
-  HttpPasswordMigrator migrator(GURL(kTestHttpsURL), &client(), &consumer());
+  HttpPasswordStoreMigrator migrator(GURL(kTestHttpsURL), &client(),
+                                     &consumer());
   callback.Run(is_hsts);
+  // We expect a potential call to |RemoveSiteStatsImpl| which is a async task
+  // posted from |PasswordStore::RemoveSiteStats|. Hence the following lines are
+  // necessary to ensure |RemoveSiteStatsImpl| gets called when expected.
+  EXPECT_CALL(store(), RemoveSiteStatsImpl(GURL(kTestHttpURL))).Times(is_hsts);
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_CALL(consumer(), ProcessForms(std::vector<autofill::PasswordForm*>()));
   migrator.OnGetPasswordStoreResults(
       std::vector<std::unique_ptr<autofill::PasswordForm>>());
 }
 
-void HttpPasswordMigratorTest::TestFullStore(bool is_hsts) {
+void HttpPasswordStoreMigratorTest::TestFullStore(bool is_hsts) {
   PasswordStore::FormDigest form_digest(autofill::PasswordForm::SCHEME_HTML,
                                         kTestHttpURL, GURL(kTestHttpURL));
   EXPECT_CALL(store(), GetLogins(form_digest, _));
   PasswordManagerClient::HSTSCallback callback;
   EXPECT_CALL(client(), PostHSTSQueryForHost(GURL(kTestHttpsURL), _))
       .WillOnce(SaveArg<1>(&callback));
-  HttpPasswordMigrator migrator(GURL(kTestHttpsURL), &client(), &consumer());
+  HttpPasswordStoreMigrator migrator(GURL(kTestHttpsURL), &client(),
+                                     &consumer());
   callback.Run(is_hsts);
+  // We expect a potential call to |RemoveSiteStatsImpl| which is a async task
+  // posted from |PasswordStore::RemoveSiteStats|. Hence the following lines are
+  // necessary to ensure |RemoveSiteStatsImpl| gets called when expected.
+  EXPECT_CALL(store(), RemoveSiteStatsImpl(GURL(kTestHttpURL))).Times(is_hsts);
+  base::RunLoop().RunUntilIdle();
 
   PasswordForm form = CreateTestForm();
   PasswordForm psl_form = CreateTestPSLForm();
@@ -159,20 +177,57 @@
   migrator.OnGetPasswordStoreResults(std::move(results));
 }
 
-TEST_F(HttpPasswordMigratorTest, EmptyStoreWithHSTS) {
+// This test checks whether the migration successfully completes even if the
+// migrator gets explicitly deleted by its consumer. This test will crash if
+// this is not the case.
+void HttpPasswordStoreMigratorTest::TestMigratorDeletionByConsumer(
+    bool is_hsts) {
+  // Setup expectations on store and client.
+  EXPECT_CALL(store(), GetLogins(_, _));
+  PasswordManagerClient::HSTSCallback callback;
+  EXPECT_CALL(client(), PostHSTSQueryForHost(GURL(kTestHttpsURL), _))
+      .WillOnce(SaveArg<1>(&callback));
+
+  // Construct the migrator, call |OnGetPasswordStoreResults| explicitly and
+  // manually delete it.
+  auto migrator = base::MakeUnique<HttpPasswordStoreMigrator>(
+      GURL(kTestHttpsURL), &client(), &consumer());
+  migrator->OnGetPasswordStoreResults(
+      std::vector<std::unique_ptr<autofill::PasswordForm>>());
+  EXPECT_CALL(consumer(), ProcessForms(_)).WillOnce(Invoke([&migrator](Unused) {
+    migrator.reset();
+  }));
+
+  callback.Run(is_hsts);
+  // We expect a potential call to |RemoveSiteStatsImpl| which is a async task
+  // posted from |PasswordStore::RemoveSiteStats|. Hence the following lines are
+  // necessary to ensure |RemoveSiteStatsImpl| gets called when expected.
+  EXPECT_CALL(store(), RemoveSiteStatsImpl(GURL(kTestHttpURL))).Times(is_hsts);
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(HttpPasswordStoreMigratorTest, EmptyStoreWithHSTS) {
   TestEmptyStore(true);
 }
 
-TEST_F(HttpPasswordMigratorTest, EmptyStoreWithoutHSTS) {
+TEST_F(HttpPasswordStoreMigratorTest, EmptyStoreWithoutHSTS) {
   TestEmptyStore(false);
 }
 
-TEST_F(HttpPasswordMigratorTest, FullStoreWithHSTS) {
+TEST_F(HttpPasswordStoreMigratorTest, FullStoreWithHSTS) {
   TestFullStore(true);
 }
 
-TEST_F(HttpPasswordMigratorTest, FullStoreWithoutHSTS) {
+TEST_F(HttpPasswordStoreMigratorTest, FullStoreWithoutHSTS) {
   TestFullStore(false);
 }
 
+TEST_F(HttpPasswordStoreMigratorTest, MigratorDeletionByConsumerWithHSTS) {
+  TestMigratorDeletionByConsumer(true);
+}
+
+TEST_F(HttpPasswordStoreMigratorTest, MigratorDeletionByConsumerWithoutHSTS) {
+  TestMigratorDeletionByConsumer(false);
+}
+
 }  // namespace password_manager
diff --git a/components/wallpaper/wallpaper_color_calculator_unittest.cc b/components/wallpaper/wallpaper_color_calculator_unittest.cc
index 398d0fa..31268f7 100644
--- a/components/wallpaper/wallpaper_color_calculator_unittest.cc
+++ b/components/wallpaper/wallpaper_color_calculator_unittest.cc
@@ -82,7 +82,7 @@
   canvas.FillRect(gfx::Rect(kImageSize), kGray);
   canvas.FillRect(gfx::Rect(0, 1, 300, 1), kVibrantGreen);
 
-  image_ = gfx::ImageSkia::CreateFrom1xBitmap(canvas.ToBitmap());
+  image_ = gfx::ImageSkia::CreateFrom1xBitmap(canvas.GetBitmap());
 
   calculator_ = base::MakeUnique<WallpaperColorCalculator>(
       image_, color_utils::LumaRange::NORMAL,
diff --git a/content/OWNERS b/content/OWNERS
index 4e1c8d0..41531f0 100644
--- a/content/OWNERS
+++ b/content/OWNERS
@@ -22,8 +22,4 @@
 per-file *.sb=set noparent
 per-file *.sb=rsesek@chromium.org
 
-per-file *.isolate=maruel@chromium.org
-per-file *.isolate=tandrii@chromium.org
-per-file *.isolate=vadimsh@chromium.org
-
 # COMPONENT: Internals>Core
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc
index 1fb1130..9202ef8 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/debug/crash_logging.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -1018,8 +1019,12 @@
 
     // If no host is found, the navigation has been cancelled in the meantime.
     // Just return as the navigation will be stopped in the renderer as well.
-    if (provider_host == nullptr)
+    if (provider_host == nullptr) {
+      // TODO(clamy): remove this Dump when the root cause for crbug.com/703972
+      // has been found.
+      base::debug::DumpWithoutCrashing();
       return;
+    }
     DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_WINDOW, info.type);
     provider_host->CompleteNavigationInitialized(render_process_id_,
                                                  info.route_id, this);
diff --git a/content/renderer/media/webmediaplayer_ms_compositor.cc b/content/renderer/media/webmediaplayer_ms_compositor.cc
index c0097d7..763b183 100644
--- a/content/renderer/media/webmediaplayer_ms_compositor.cc
+++ b/content/renderer/media/webmediaplayer_ms_compositor.cc
@@ -48,25 +48,27 @@
         media::PIXEL_FORMAT_I420, frame->coded_size(), frame->visible_rect(),
         frame->natural_size(), frame->timestamp());
 
-    sk_sp<cc::PaintSurface> surface = cc::PaintSurface::MakeRasterN32Premul(
-        frame->visible_rect().width(), frame->visible_rect().height());
-
     ui::ContextProviderCommandBuffer* const provider =
         RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
-    if (surface && provider) {
-      DCHECK(provider->ContextGL());
-      video_renderer->Copy(
-          frame.get(), surface->getCanvas(),
-          media::Context3D(provider->ContextGL(), provider->GrContext()));
-    } else {
+    if (!provider) {
       // Return a black frame (yuv = {0, 0x80, 0x80}).
       return media::VideoFrame::CreateColorFrame(
           frame->visible_rect().size(), 0u, 0x80, 0x80, frame->timestamp());
     }
 
+    SkBitmap bitmap;
+    bitmap.allocPixels(SkImageInfo::MakeN32Premul(
+        frame->visible_rect().width(), frame->visible_rect().height()));
+    cc::SkiaPaintCanvas paint_canvas(bitmap);
+
+    DCHECK(provider->ContextGL());
+    video_renderer->Copy(
+        frame.get(), &paint_canvas,
+        media::Context3D(provider->ContextGL(), provider->GrContext()));
+
     SkPixmap pixmap;
-    const bool result = surface->getCanvas()->peekPixels(&pixmap);
-    DCHECK(result) << "Error trying to access PaintSurface's pixels";
+    const bool result = bitmap.peekPixels(&pixmap);
+    DCHECK(result) << "Error trying to access SkBitmap's pixels";
 
     const uint32 source_pixel_format =
         (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
index 77b5241..edde298 100644
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
+++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
@@ -101,27 +101,30 @@
            frame->format() == media::PIXEL_FORMAT_UYVY ||
            frame->format() == media::PIXEL_FORMAT_NV12);
     ScopedWaitableEvent event(waiter);
-    sk_sp<cc::PaintSurface> surface = cc::PaintSurface::MakeRasterN32Premul(
-        frame->visible_rect().width(), frame->visible_rect().height());
 
-    if (!surface || !provider_) {
+    if (!provider_) {
       // Return a black frame (yuv = {0, 0x80, 0x80}).
       *new_frame = media::VideoFrame::CreateColorFrame(
           frame->visible_rect().size(), 0u, 0x80, 0x80, frame->timestamp());
       return;
     }
 
+    SkBitmap bitmap;
+    bitmap.allocPixels(SkImageInfo::MakeN32Premul(
+        frame->visible_rect().width(), frame->visible_rect().height()));
+    cc::SkiaPaintCanvas paint_canvas(bitmap);
+
     *new_frame = media::VideoFrame::CreateFrame(
         media::PIXEL_FORMAT_I420, frame->coded_size(), frame->visible_rect(),
         frame->natural_size(), frame->timestamp());
     DCHECK(provider_->ContextGL());
     canvas_video_renderer_->Copy(
-        frame.get(), surface->getCanvas(),
+        frame.get(), &paint_canvas,
         media::Context3D(provider_->ContextGL(), provider_->GrContext()));
 
     SkPixmap pixmap;
-    const bool result = surface->getCanvas()->peekPixels(&pixmap);
-    DCHECK(result) << "Error trying to access PaintSurface's pixels";
+    const bool result = bitmap.peekPixels(&pixmap);
+    DCHECK(result) << "Error trying to access SkBitmap's pixels";
     const uint32 source_pixel_format =
         (kN32_SkColorType == kRGBA_8888_SkColorType) ? cricket::FOURCC_ABGR
                                                      : cricket::FOURCC_ARGB;
diff --git a/content/renderer/mus/renderer_window_tree_client.cc b/content/renderer/mus/renderer_window_tree_client.cc
index 6940056..8cb2e657 100644
--- a/content/renderer/mus/renderer_window_tree_client.cc
+++ b/content/renderer/mus/renderer_window_tree_client.cc
@@ -119,6 +119,13 @@
 void RendererWindowTreeClient::OnCaptureChanged(ui::Id new_capture_window_id,
                                                 ui::Id old_capture_window_id) {}
 
+void RendererWindowTreeClient::OnFrameSinkIdAllocated(
+    ui::Id window_id,
+    const cc::FrameSinkId& frame_sink_id) {
+  // TODO(fsamuel): OOPIF's |frame_sink_id| is ready. The OOPIF can now be
+  // embedded by the parent.
+}
+
 void RendererWindowTreeClient::OnTopLevelCreated(
     uint32_t change_id,
     ui::mojom::WindowDataPtr data,
diff --git a/content/renderer/mus/renderer_window_tree_client.h b/content/renderer/mus/renderer_window_tree_client.h
index 3241ca48..982e6acf 100644
--- a/content/renderer/mus/renderer_window_tree_client.h
+++ b/content/renderer/mus/renderer_window_tree_client.h
@@ -74,6 +74,8 @@
   void OnUnembed(ui::Id window_id) override;
   void OnCaptureChanged(ui::Id new_capture_window_id,
                         ui::Id old_capture_window_id) override;
+  void OnFrameSinkIdAllocated(ui::Id window_id,
+                              const cc::FrameSinkId& frame_sink_id) override;
   void OnTopLevelCreated(uint32_t change_id,
                          ui::mojom::WindowDataPtr data,
                          int64_t display_id,
diff --git a/content/renderer/pepper/plugin_instance_throttler_impl_unittest.cc b/content/renderer/pepper/plugin_instance_throttler_impl_unittest.cc
index 01763945..d5c2e3b 100644
--- a/content/renderer/pepper/plugin_instance_throttler_impl_unittest.cc
+++ b/content/renderer/pepper/plugin_instance_throttler_impl_unittest.cc
@@ -105,7 +105,7 @@
   gfx::Canvas canvas(gfx::Size(20, 10), 1.0f, true);
   canvas.FillRect(gfx::Rect(20, 10), SK_ColorBLACK);
   canvas.FillRect(gfx::Rect(10, 10), SK_ColorWHITE);
-  SkBitmap interesting_bitmap = canvas.ToBitmap();
+  SkBitmap interesting_bitmap = canvas.GetBitmap();
 
   // Don't throttle for a boring frame.
   throttler()->OnImageFlush(boring_bitmap);
diff --git a/extensions/browser/api/runtime/runtime_apitest.cc b/extensions/browser/api/runtime/runtime_apitest.cc
index 422251a..1bb7850 100644
--- a/extensions/browser/api/runtime/runtime_apitest.cc
+++ b/extensions/browser/api/runtime/runtime_apitest.cc
@@ -80,7 +80,8 @@
 }
 
 // Tests chrome.runtime.reload
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeRuntimeReload) {
+// This test is flaky: crbug.com/366181
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_ChromeRuntimeReload) {
   ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
   const char kManifest[] =
       "{"
diff --git a/extensions/test/extension_test_notification_observer.cc b/extensions/test/extension_test_notification_observer.cc
index 0e4d75d0c..7d6db807 100644
--- a/extensions/test/extension_test_notification_observer.cc
+++ b/extensions/test/extension_test_notification_observer.cc
@@ -127,7 +127,8 @@
 bool ExtensionTestNotificationObserver::WaitForCrxInstallerDone() {
   int before = crx_installers_done_observed_;
   WaitForNotification(NOTIFICATION_CRX_INSTALLER_DONE);
-  return crx_installers_done_observed_ == before + 1;
+  return crx_installers_done_observed_ == before + 1 &&
+         !last_loaded_extension_id_.empty();
 }
 
 void ExtensionTestNotificationObserver::Watch(
diff --git a/extensions/test/extension_test_notification_observer.h b/extensions/test/extension_test_notification_observer.h
index 655084e..418d567a 100644
--- a/extensions/test/extension_test_notification_observer.h
+++ b/extensions/test/extension_test_notification_observer.h
@@ -46,7 +46,8 @@
   // crashed.
   bool WaitForExtensionCrash(const std::string& extension_id);
 
-  // Wait for the crx installer to be done. Returns true if it really is done.
+  // Wait for the crx installer to be done. Returns true if it has finished
+  // successfully.
   bool WaitForCrxInstallerDone();
 
   // Watch for the given event type from the given source.
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index d3836079..479b2d6 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -6703,7 +6703,7 @@
   typedef cmds::%(func_name)s::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
       c.%(last_arg_name)s_shm_id, c.%(last_arg_name)s_shm_offset,
-      &buffer_size);
+      sizeof(Result), &buffer_size);
   %(last_arg_type)s %(last_arg_name)s = result ? result->GetData() : NULL;
   if (%(last_arg_name)s == NULL) {
     return error::kOutOfBounds;
diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc
index b879f95..a561056 100644
--- a/gpu/command_buffer/service/common_decoder.cc
+++ b/gpu/command_buffer/service/common_decoder.cc
@@ -143,10 +143,11 @@
 
 void* CommonDecoder::GetAddressAndSize(unsigned int shm_id,
                                        unsigned int data_offset,
+                                       unsigned int minimum_size,
                                        unsigned int* data_size) {
   CHECK(engine_);
   scoped_refptr<gpu::Buffer> buffer = engine_->GetSharedMemoryBuffer(shm_id);
-  if (!buffer.get())
+  if (!buffer.get() || buffer->GetRemainingSize(data_offset) < minimum_size)
     return NULL;
   return buffer->GetDataAddressAndSize(data_offset, data_size);
 }
diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h
index 5b41775b..3c23d53 100644
--- a/gpu/command_buffer/service/common_decoder.h
+++ b/gpu/command_buffer/service/common_decoder.h
@@ -152,13 +152,16 @@
 
   void* GetAddressAndSize(unsigned int shm_id,
                           unsigned int offset,
+                          unsigned int minimum_size,
                           unsigned int* size);
 
   template <typename T>
   T GetSharedMemoryAndSizeAs(unsigned int shm_id,
                              unsigned int offset,
+                             unsigned int minimum_size,
                              unsigned int* size) {
-    return static_cast<T>(GetAddressAndSize(shm_id, offset, size));
+    return static_cast<T>(
+        GetAddressAndSize(shm_id, offset, minimum_size, size));
   }
 
   unsigned int GetSharedMemorySize(unsigned int shm_id, unsigned int offset);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
index 156a071..3e08b52 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
@@ -226,7 +226,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetActiveUniformBlockiv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -440,7 +440,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetInternalformativ::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -649,7 +649,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetUniformfv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLfloat* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -678,7 +678,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetUniformiv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -707,7 +707,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetUniformuiv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLuint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -808,7 +808,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetVertexAttribPointerv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.pointer_shm_id, c.pointer_shm_offset, &buffer_size);
+      c.pointer_shm_id, c.pointer_shm_offset, sizeof(Result), &buffer_size);
   GLuint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -857,7 +857,7 @@
   unsigned int buffer_size = 0;
   if (c.pixels_shm_id != 0) {
     pixels = GetSharedMemoryAndSizeAs<uint8_t*>(
-        c.pixels_shm_id, c.pixels_shm_offset, &buffer_size);
+        c.pixels_shm_id, c.pixels_shm_offset, 0, &buffer_size);
     if (!pixels) {
       return error::kOutOfBounds;
     }
@@ -946,7 +946,7 @@
 
   if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
     pixels = GetSharedMemoryAndSizeAs<uint8_t*>(
-        pixels_shm_id, pixels_shm_offset, &buffer_size);
+        pixels_shm_id, pixels_shm_offset, 0, &buffer_size);
     if (!pixels) {
       return error::kOutOfBounds;
     }
@@ -984,7 +984,7 @@
 
   if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
     pixels = GetSharedMemoryAndSizeAs<uint8_t*>(
-        pixels_shm_id, pixels_shm_offset, &buffer_size);
+        pixels_shm_id, pixels_shm_offset, 0, &buffer_size);
     if (!pixels) {
       return error::kOutOfBounds;
     }
@@ -1021,7 +1021,7 @@
 
   if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
     pixels = GetSharedMemoryAndSizeAs<uint8_t*>(
-        pixels_shm_id, pixels_shm_offset, &buffer_size);
+        pixels_shm_id, pixels_shm_offset, 0, &buffer_size);
     if (!pixels) {
       return error::kOutOfBounds;
     }
@@ -1060,7 +1060,7 @@
 
   if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
     pixels = GetSharedMemoryAndSizeAs<uint8_t*>(
-        pixels_shm_id, pixels_shm_offset, &buffer_size);
+        pixels_shm_id, pixels_shm_offset, 0, &buffer_size);
     if (!pixels) {
       return error::kOutOfBounds;
     }
@@ -1897,7 +1897,7 @@
     if (coords_shm_id != 0 || coords_shm_offset != 0) {
       unsigned int memory_size = 0;
       coords = GetSharedMemoryAndSizeAs<const GLvoid*>(
-          coords_shm_id, coords_shm_offset, &memory_size);
+          coords_shm_id, coords_shm_offset, 0, &memory_size);
       coords_bufsize = static_cast<GLsizei>(memory_size);
     }
 
@@ -2068,7 +2068,7 @@
     if (paths_shm_id != 0 || paths_shm_offset != 0) {
       unsigned int memory_size = 0;
       paths = GetSharedMemoryAndSizeAs<const GLvoid*>(
-          paths_shm_id, paths_shm_offset, &memory_size);
+          paths_shm_id, paths_shm_offset, 0, &memory_size);
       paths_bufsize = static_cast<GLsizei>(memory_size);
     }
 
@@ -2085,7 +2085,8 @@
   if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) {
     unsigned int memory_size = 0;
     transform_values = GetSharedMemoryAndSizeAs<const GLfloat*>(
-        c.transformValues_shm_id, c.transformValues_shm_offset, &memory_size);
+        c.transformValues_shm_id, c.transformValues_shm_offset, 0,
+        &memory_size);
     transform_values_bufsize = static_cast<GLsizei>(memory_size);
   }
   if (!transform_values) {
@@ -2120,7 +2121,7 @@
     if (paths_shm_id != 0 || paths_shm_offset != 0) {
       unsigned int memory_size = 0;
       paths = GetSharedMemoryAndSizeAs<const GLvoid*>(
-          paths_shm_id, paths_shm_offset, &memory_size);
+          paths_shm_id, paths_shm_offset, 0, &memory_size);
       paths_bufsize = static_cast<GLsizei>(memory_size);
     }
 
@@ -2137,7 +2138,8 @@
   if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) {
     unsigned int memory_size = 0;
     transform_values = GetSharedMemoryAndSizeAs<const GLfloat*>(
-        c.transformValues_shm_id, c.transformValues_shm_offset, &memory_size);
+        c.transformValues_shm_id, c.transformValues_shm_offset, 0,
+        &memory_size);
     transform_values_bufsize = static_cast<GLsizei>(memory_size);
   }
   if (!transform_values) {
@@ -2170,7 +2172,7 @@
     if (paths_shm_id != 0 || paths_shm_offset != 0) {
       unsigned int memory_size = 0;
       paths = GetSharedMemoryAndSizeAs<const GLvoid*>(
-          paths_shm_id, paths_shm_offset, &memory_size);
+          paths_shm_id, paths_shm_offset, 0, &memory_size);
       paths_bufsize = static_cast<GLsizei>(memory_size);
     }
 
@@ -2186,7 +2188,8 @@
   if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) {
     unsigned int memory_size = 0;
     transform_values = GetSharedMemoryAndSizeAs<const GLfloat*>(
-        c.transformValues_shm_id, c.transformValues_shm_offset, &memory_size);
+        c.transformValues_shm_id, c.transformValues_shm_offset, 0,
+        &memory_size);
     transform_values_bufsize = static_cast<GLsizei>(memory_size);
   }
   if (!transform_values) {
@@ -2221,7 +2224,7 @@
     if (paths_shm_id != 0 || paths_shm_offset != 0) {
       unsigned int memory_size = 0;
       paths = GetSharedMemoryAndSizeAs<const GLvoid*>(
-          paths_shm_id, paths_shm_offset, &memory_size);
+          paths_shm_id, paths_shm_offset, 0, &memory_size);
       paths_bufsize = static_cast<GLsizei>(memory_size);
     }
 
@@ -2237,7 +2240,8 @@
   if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) {
     unsigned int memory_size = 0;
     transform_values = GetSharedMemoryAndSizeAs<const GLfloat*>(
-        c.transformValues_shm_id, c.transformValues_shm_offset, &memory_size);
+        c.transformValues_shm_id, c.transformValues_shm_offset, 0,
+        &memory_size);
     transform_values_bufsize = static_cast<GLsizei>(memory_size);
   }
   if (!transform_values) {
@@ -2271,7 +2275,7 @@
     if (paths_shm_id != 0 || paths_shm_offset != 0) {
       unsigned int memory_size = 0;
       paths = GetSharedMemoryAndSizeAs<const GLvoid*>(
-          paths_shm_id, paths_shm_offset, &memory_size);
+          paths_shm_id, paths_shm_offset, 0, &memory_size);
       paths_bufsize = static_cast<GLsizei>(memory_size);
     }
 
@@ -2289,7 +2293,8 @@
   if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) {
     unsigned int memory_size = 0;
     transform_values = GetSharedMemoryAndSizeAs<const GLfloat*>(
-        c.transformValues_shm_id, c.transformValues_shm_offset, &memory_size);
+        c.transformValues_shm_id, c.transformValues_shm_offset, 0,
+        &memory_size);
     transform_values_bufsize = static_cast<GLsizei>(memory_size);
   }
   if (!transform_values) {
@@ -2324,7 +2329,7 @@
     if (paths_shm_id != 0 || paths_shm_offset != 0) {
       unsigned int memory_size = 0;
       paths = GetSharedMemoryAndSizeAs<const GLvoid*>(
-          paths_shm_id, paths_shm_offset, &memory_size);
+          paths_shm_id, paths_shm_offset, 0, &memory_size);
       paths_bufsize = static_cast<GLsizei>(memory_size);
     }
 
@@ -2342,7 +2347,8 @@
   if (c.transformValues_shm_id != 0 || c.transformValues_shm_offset != 0) {
     unsigned int memory_size = 0;
     transform_values = GetSharedMemoryAndSizeAs<const GLfloat*>(
-        c.transformValues_shm_id, c.transformValues_shm_offset, &memory_size);
+        c.transformValues_shm_id, c.transformValues_shm_offset, 0,
+        &memory_size);
     transform_values_bufsize = static_cast<GLsizei>(memory_size);
   }
   if (!transform_values) {
@@ -2403,7 +2409,7 @@
   if (c.coeffs_shm_id != 0 || c.coeffs_shm_offset != 0) {
     unsigned int memory_size = 0;
     coeffs = GetSharedMemoryAndSizeAs<const GLfloat*>(
-        c.coeffs_shm_id, c.coeffs_shm_offset, &memory_size);
+        c.coeffs_shm_id, c.coeffs_shm_offset, 0, &memory_size);
     coeffs_bufsize = static_cast<GLsizei>(memory_size);
   }
   if (!coeffs) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
index bc19ef16..d4eb37e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
@@ -1079,7 +1079,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetBooleanv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLboolean* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1109,7 +1109,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetBufferParameteri64v::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint64* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1139,7 +1139,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetBufferParameteriv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1186,7 +1186,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetFloatv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLfloat* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1219,7 +1219,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetFramebufferAttachmentParameteriv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1248,7 +1248,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetInteger64v::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint64* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1277,7 +1277,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetIntegeri_v::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.data_shm_id, c.data_shm_offset, &buffer_size);
+      c.data_shm_id, c.data_shm_offset, sizeof(Result), &buffer_size);
   GLint* data = result ? result->GetData() : NULL;
   if (data == NULL) {
     return error::kOutOfBounds;
@@ -1306,7 +1306,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetInteger64i_v::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.data_shm_id, c.data_shm_offset, &buffer_size);
+      c.data_shm_id, c.data_shm_offset, sizeof(Result), &buffer_size);
   GLint64* data = result ? result->GetData() : NULL;
   if (data == NULL) {
     return error::kOutOfBounds;
@@ -1334,7 +1334,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetIntegerv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1363,7 +1363,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetProgramiv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1393,7 +1393,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetRenderbufferParameteriv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1424,7 +1424,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetSamplerParameterfv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLfloat* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1455,7 +1455,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetSamplerParameteriv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1485,7 +1485,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetShaderiv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1514,7 +1514,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetSynciv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.values_shm_id, c.values_shm_offset, &buffer_size);
+      c.values_shm_id, c.values_shm_offset, sizeof(Result), &buffer_size);
   GLint* values = result ? result->GetData() : NULL;
   if (values == NULL) {
     return error::kOutOfBounds;
@@ -1543,7 +1543,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetTexParameterfv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLfloat* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1573,7 +1573,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetTexParameteriv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1603,7 +1603,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetVertexAttribfv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLfloat* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1633,7 +1633,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetVertexAttribiv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1663,7 +1663,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetVertexAttribIiv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
@@ -1693,7 +1693,7 @@
   unsigned int buffer_size = 0;
   typedef cmds::GetVertexAttribIuiv::Result Result;
   Result* result = GetSharedMemoryAndSizeAs<Result*>(
-      c.params_shm_id, c.params_shm_offset, &buffer_size);
+      c.params_shm_id, c.params_shm_offset, sizeof(Result), &buffer_size);
   GLuint* params = result ? result->GetData() : NULL;
   if (params == NULL) {
     return error::kOutOfBounds;
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index 87111b4..557b228 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -190,12 +190,12 @@
   }
 
   void ResetDecoder() {
+    decoder_->Destroy(true);
+    decoder_.reset();
     if (recreate_context_) {
       context_->ReleaseCurrent(nullptr);
       context_ = nullptr;
     }
-    decoder_->Destroy(true);
-    decoder_.reset();
     command_buffer_.reset();
   }
 
diff --git a/media/OWNERS b/media/OWNERS
index ceeec91..50e4f034 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -20,8 +20,4 @@
 wolenetz@chromium.org
 xhwang@chromium.org
 
-per-file *.isolate=maruel@chromium.org
-per-file *.isolate=tandrii@chromium.org
-per-file *.isolate=vadimsh@chromium.org
-
 # COMPONENT: Internals>Media
diff --git a/net/OWNERS b/net/OWNERS
index 589e980b..904fb38 100644
--- a/net/OWNERS
+++ b/net/OWNERS
@@ -17,10 +17,6 @@
 xunjieli@chromium.org
 zhongyi@chromium.org
 
-per-file *.isolate=maruel@chromium.org
-per-file *.isolate=tandrii@chromium.org
-per-file *.isolate=vadimsh@chromium.org
-
 per-file BUILD.gn=bengr@chromium.org
 per-file net.gyp*=bengr@chromium.org
 
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index af348737..5f870c6 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -13,6 +13,7 @@
 #include <algorithm>
 #include <string>
 
+#include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/compiler_specific.h"
@@ -190,6 +191,7 @@
       total_received_bytes_(0),
       total_sent_bytes_(0),
       websocket_handshake_stream_base_create_helper_(NULL),
+      in_do_loop_(false),
       weak_factory_(this) {
   TRACE_EVENT0("io", "HttpCacheTransaction::Transaction");
   static_assert(HttpCache::Transaction::kNumValidationHeaders ==
@@ -714,11 +716,14 @@
 int HttpCache::Transaction::DoLoop(int result) {
   DCHECK_NE(STATE_UNSET, next_state_);
   DCHECK_NE(STATE_NONE, next_state_);
+  DCHECK(!in_do_loop_);
 
   int rv = result;
   do {
     State state = next_state_;
     next_state_ = STATE_UNSET;
+    base::AutoReset<bool> scoped_in_do_loop(&in_do_loop_, true);
+
     switch (state) {
       case STATE_GET_BACKEND:
         DCHECK_EQ(OK, rv);
@@ -898,7 +903,7 @@
 
 int HttpCache::Transaction::DoGetBackend() {
   cache_pending_ = true;
-  next_state_ = STATE_GET_BACKEND_COMPLETE;
+  TransitionToState(STATE_GET_BACKEND_COMPLETE);
   net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_GET_BACKEND);
   return cache_->GetBackendForTransaction(this);
 }
@@ -916,7 +921,7 @@
     if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
       if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
         // The client has asked for nonsense.
-        next_state_ = STATE_NONE;
+        TransitionToState(STATE_NONE);
         return ERR_CACHE_MISS;
       }
       mode_ = READ;
@@ -955,7 +960,7 @@
   // If must use cache, then we must fail.  This can happen for back/forward
   // navigations to a page generated via a form post.
   if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_CACHE_MISS;
   }
 
@@ -964,9 +969,9 @@
       partial_->RestoreHeaders(&custom_request_->extra_headers);
       partial_.reset();
     }
-    next_state_ = STATE_SEND_REQUEST;
+    TransitionToState(STATE_SEND_REQUEST);
   } else {
-    next_state_ = STATE_INIT_ENTRY;
+    TransitionToState(STATE_INIT_ENTRY);
   }
 
   // This is only set if we have something to do with the response.
@@ -980,23 +985,23 @@
   DCHECK(!new_entry_);
 
   if (!cache_.get()) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_UNEXPECTED;
   }
 
   if (mode_ == WRITE) {
-    next_state_ = STATE_DOOM_ENTRY;
+    TransitionToState(STATE_DOOM_ENTRY);
     return OK;
   }
 
-  next_state_ = STATE_OPEN_ENTRY;
+  TransitionToState(STATE_OPEN_ENTRY);
   return OK;
 }
 
 int HttpCache::Transaction::DoOpenEntry() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoOpenEntry");
   DCHECK(!new_entry_);
-  next_state_ = STATE_OPEN_ENTRY_COMPLETE;
+  TransitionToState(STATE_OPEN_ENTRY_COMPLETE);
   cache_pending_ = true;
   net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_OPEN_ENTRY);
   first_cache_access_since_ = TimeTicks::Now();
@@ -1012,12 +1017,12 @@
                                     result);
   cache_pending_ = false;
   if (result == OK) {
-    next_state_ = STATE_ADD_TO_ENTRY;
+    TransitionToState(STATE_ADD_TO_ENTRY);
     return OK;
   }
 
   if (result == ERR_CACHE_RACE) {
-    next_state_ = STATE_INIT_ENTRY;
+    TransitionToState(STATE_INIT_ENTRY);
     return OK;
   }
 
@@ -1025,31 +1030,31 @@
       (request_->method == "HEAD" && mode_ == READ_WRITE)) {
     DCHECK(mode_ == READ_WRITE || mode_ == WRITE || request_->method == "HEAD");
     mode_ = NONE;
-    next_state_ = STATE_SEND_REQUEST;
+    TransitionToState(STATE_SEND_REQUEST);
     return OK;
   }
 
   if (mode_ == READ_WRITE) {
     mode_ = WRITE;
-    next_state_ = STATE_CREATE_ENTRY;
+    TransitionToState(STATE_CREATE_ENTRY);
     return OK;
   }
   if (mode_ == UPDATE) {
     // There is no cache entry to update; proceed without caching.
     mode_ = NONE;
-    next_state_ = STATE_SEND_REQUEST;
+    TransitionToState(STATE_SEND_REQUEST);
     return OK;
   }
 
   // The entry does not exist, and we are not permitted to create a new entry,
   // so we must fail.
-  next_state_ = STATE_NONE;
+  TransitionToState(STATE_NONE);
   return ERR_CACHE_MISS;
 }
 
 int HttpCache::Transaction::DoDoomEntry() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoDoomEntry");
-  next_state_ = STATE_DOOM_ENTRY_COMPLETE;
+  TransitionToState(STATE_DOOM_ENTRY_COMPLETE);
   cache_pending_ = true;
   if (first_cache_access_since_.is_null())
     first_cache_access_since_ = TimeTicks::Now();
@@ -1061,17 +1066,16 @@
   TRACE_EVENT0("io", "HttpCacheTransaction::DoDoomEntryComplete");
   net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_DOOM_ENTRY,
                                     result);
-  next_state_ = STATE_CREATE_ENTRY;
   cache_pending_ = false;
-  if (result == ERR_CACHE_RACE)
-    next_state_ = STATE_INIT_ENTRY;
+  TransitionToState(result == ERR_CACHE_RACE ? STATE_INIT_ENTRY
+                                             : STATE_CREATE_ENTRY);
   return OK;
 }
 
 int HttpCache::Transaction::DoCreateEntry() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCreateEntry");
   DCHECK(!new_entry_);
-  next_state_ = STATE_CREATE_ENTRY_COMPLETE;
+  TransitionToState(STATE_CREATE_ENTRY_COMPLETE);
   cache_pending_ = true;
   net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_CREATE_ENTRY);
   return cache_->CreateEntry(cache_key_, &new_entry_, this);
@@ -1087,11 +1091,11 @@
   cache_pending_ = false;
   switch (result) {
     case OK:
-      next_state_ = STATE_ADD_TO_ENTRY;
+      TransitionToState(STATE_ADD_TO_ENTRY);
       break;
 
     case ERR_CACHE_RACE:
-      next_state_ = STATE_INIT_ENTRY;
+      TransitionToState(STATE_INIT_ENTRY);
       break;
 
     default:
@@ -1103,7 +1107,7 @@
       mode_ = NONE;
       if (partial_)
         partial_->RestoreHeaders(&custom_request_->extra_headers);
-      next_state_ = STATE_SEND_REQUEST;
+      TransitionToState(STATE_SEND_REQUEST);
   }
   return OK;
 }
@@ -1112,14 +1116,17 @@
   TRACE_EVENT0("io", "HttpCacheTransaction::DoAddToEntry");
   DCHECK(new_entry_);
   cache_pending_ = true;
-  next_state_ = STATE_ADD_TO_ENTRY_COMPLETE;
+  TransitionToState(STATE_ADD_TO_ENTRY_COMPLETE);
   net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY);
   DCHECK(entry_lock_waiting_since_.is_null());
   entry_lock_waiting_since_ = TimeTicks::Now();
   int rv = cache_->AddTransactionToEntry(new_entry_, this);
   if (rv == ERR_IO_PENDING) {
     if (bypass_lock_for_test_) {
-      OnAddToEntryTimeout(entry_lock_waiting_since_);
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE,
+          base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout,
+                     weak_factory_.GetWeakPtr(), entry_lock_waiting_since_));
     } else {
       int timeout_milliseconds = 20 * 1000;
       if (partial_ && new_entry_->writer &&
@@ -1169,19 +1176,19 @@
   new_entry_ = NULL;
 
   if (result == ERR_CACHE_RACE) {
-    next_state_ = STATE_INIT_ENTRY;
+    TransitionToState(STATE_INIT_ENTRY);
     return OK;
   }
 
   if (result == ERR_CACHE_LOCK_TIMEOUT) {
     if (mode_ == READ) {
-      next_state_ = STATE_NONE;
+      TransitionToState(STATE_NONE);
       return ERR_CACHE_MISS;
     }
 
     // The cache is busy, bypass it for this transaction.
     mode_ = NONE;
-    next_state_ = STATE_SEND_REQUEST;
+    TransitionToState(STATE_SEND_REQUEST);
     if (partial_) {
       partial_->RestoreHeaders(&custom_request_->extra_headers);
       partial_.reset();
@@ -1194,18 +1201,18 @@
   // TODO(jkarlin): We should either handle the case or DCHECK.
   if (result != OK) {
     NOTREACHED();
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return result;
   }
 
   if (mode_ == WRITE) {
     if (partial_)
       partial_->RestoreHeaders(&custom_request_->extra_headers);
-    next_state_ = STATE_SEND_REQUEST;
+    TransitionToState(STATE_SEND_REQUEST);
   } else {
     // We have to read the headers from the cached entry.
     DCHECK(mode_ & READ_META);
-    next_state_ = STATE_CACHE_READ_RESPONSE;
+    TransitionToState(STATE_CACHE_READ_RESPONSE);
   }
   return OK;
 }
@@ -1213,7 +1220,7 @@
 int HttpCache::Transaction::DoCacheReadResponse() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadResponse");
   DCHECK(entry_);
-  next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE;
+  TransitionToState(STATE_CACHE_READ_RESPONSE_COMPLETE);
 
   io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex);
   read_buf_ = new IOBuffer(io_buf_len_);
@@ -1254,7 +1261,7 @@
     // will fall back to the network after the timeout.
     DCHECK(!partial_);
     mode_ = NONE;
-    next_state_ = STATE_SEND_REQUEST;
+    TransitionToState(STATE_SEND_REQUEST);
     return OK;
   }
 
@@ -1263,11 +1270,11 @@
     // Either this is the first use of an entry since it was prefetched XOR
     // this is a prefetch. The value of response.unused_since_prefetch is
     // valid for this transaction but the bit needs to be flipped in storage.
-    next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH;
+    TransitionToState(STATE_TOGGLE_UNUSED_SINCE_PREFETCH);
     return OK;
   }
 
-  next_state_ = STATE_CACHE_DISPATCH_VALIDATION;
+  TransitionToState(STATE_CACHE_DISPATCH_VALIDATION);
   return OK;
 }
 
@@ -1280,7 +1287,7 @@
   // transaction then metadata will be written to cache twice. If prefetching
   // becomes more common, consider combining the writes.
 
-  next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE;
+  TransitionToState(STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE);
   return WriteResponseInfoToEntry(false);
 }
 
@@ -1291,7 +1298,7 @@
       "HttpCacheTransaction::DoCacheToggleUnusedSincePrefetchComplete");
   // Restore the original value for this transaction.
   response_.unused_since_prefetch = !response_.unused_since_prefetch;
-  next_state_ = STATE_CACHE_DISPATCH_VALIDATION;
+  TransitionToState(STATE_CACHE_DISPATCH_VALIDATION);
   return OnWriteResponseInfoToEntryComplete(result);
 }
 
@@ -1330,14 +1337,14 @@
 }
 
 int HttpCache::Transaction::DoCacheQueryData() {
-  next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE;
+  TransitionToState(STATE_CACHE_QUERY_DATA_COMPLETE);
   return entry_->disk_entry->ReadyForSparseIO(io_callback_);
 }
 
 int HttpCache::Transaction::DoCacheQueryDataComplete(int result) {
   DCHECK_EQ(OK, result);
   if (!cache_.get()) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_UNEXPECTED;
   }
 
@@ -1347,11 +1354,11 @@
 // We may end up here multiple times for a given request.
 int HttpCache::Transaction::DoStartPartialCacheValidation() {
   if (mode_ == NONE) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return OK;
   }
 
-  next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION;
+  TransitionToState(STATE_COMPLETE_PARTIAL_CACHE_VALIDATION);
   return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_);
 }
 
@@ -1364,12 +1371,12 @@
       cache_->DoneReadingFromEntry(entry_, this);
       entry_ = NULL;
     }
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return result;
   }
 
   if (result < 0) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return result;
   }
 
@@ -1377,7 +1384,7 @@
                                    &custom_request_->extra_headers);
 
   if (reading_ && partial_->IsCurrentRangeCached()) {
-    next_state_ = STATE_CACHE_READ_DATA;
+    TransitionToState(STATE_CACHE_READ_DATA);
     return OK;
   }
 
@@ -1395,7 +1402,7 @@
   int rv =
       cache_->network_layer_->CreateTransaction(priority_, &network_trans_);
   if (rv != OK) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return rv;
   }
   network_trans_->SetBeforeNetworkStartCallback(before_network_start_callback_);
@@ -1409,7 +1416,7 @@
     network_trans_->SetWebSocketHandshakeStreamCreateHelper(
         websocket_handshake_stream_base_create_helper_);
 
-  next_state_ = STATE_SEND_REQUEST_COMPLETE;
+  TransitionToState(STATE_SEND_REQUEST_COMPLETE);
   rv = network_trans_->Start(request_, io_callback_, net_log_);
   return rv;
 }
@@ -1417,7 +1424,7 @@
 int HttpCache::Transaction::DoSendRequestComplete(int result) {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoSendRequestComplete");
   if (!cache_.get()) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_UNEXPECTED;
   }
 
@@ -1427,7 +1434,7 @@
     mode_ = WRITE;
 
   if (result == OK) {
-    next_state_ = STATE_SUCCESSFUL_SEND_REQUEST;
+    TransitionToState(STATE_SUCCESSFUL_SEND_REQUEST);
     return OK;
   }
 
@@ -1448,7 +1455,7 @@
     DoneWritingToEntry(true);
   }
 
-  next_state_ = STATE_NONE;
+  TransitionToState(STATE_NONE);
   return result;
 }
 
@@ -1462,7 +1469,7 @@
       new_response->headers->response_code() == 407) {
     SetAuthResponse(*new_response);
     if (!reading_) {
-      next_state_ = STATE_NONE;
+      TransitionToState(STATE_NONE);
       return OK;
     }
 
@@ -1471,7 +1478,7 @@
     // this URL moments ago.
     if (IsReadyToRestartForAuth()) {
       DCHECK(!response_.auth_challenge.get());
-      next_state_ = STATE_SEND_REQUEST_COMPLETE;
+      TransitionToState(STATE_SEND_REQUEST_COMPLETE);
       // In theory we should check to see if there are new cookies, but there
       // is no way to do that from here.
       return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_);
@@ -1487,7 +1494,7 @@
     mode_ = NONE;
     partial_.reset();
     ResetNetworkTransaction();
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_CACHE_AUTH_FAILURE_AFTER_READ;
   }
 
@@ -1502,7 +1509,7 @@
     SetResponse(HttpResponseInfo());
     ResetNetworkTransaction();
     new_response_ = NULL;
-    next_state_ = STATE_SEND_REQUEST;
+    TransitionToState(STATE_SEND_REQUEST);
     return OK;
   }
 
@@ -1543,7 +1550,7 @@
       (request_->method == "GET" || request_->method == "POST")) {
     // If there is an active entry it may be destroyed with this transaction.
     SetResponse(*new_response_);
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return OK;
   }
 
@@ -1551,21 +1558,20 @@
   if (mode_ == READ_WRITE || mode_ == UPDATE) {
     if (new_response->headers->response_code() == 304 || handling_206_) {
       UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED);
-      next_state_ = STATE_UPDATE_CACHED_RESPONSE;
+      TransitionToState(STATE_UPDATE_CACHED_RESPONSE);
       return OK;
     }
     UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED);
     mode_ = WRITE;
   }
 
-  next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
+  TransitionToState(STATE_OVERWRITE_CACHED_RESPONSE);
   return OK;
 }
 
 // We received 304 or 206 and we want to update the cached response headers.
 int HttpCache::Transaction::DoUpdateCachedResponse() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoUpdateCachedResponse");
-  next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
   int rv = OK;
   // Update the cached response based on the headers and properties of
   // new_response_.
@@ -1590,28 +1596,32 @@
       int ret = cache_->DoomEntry(cache_key_, NULL);
       DCHECK_EQ(OK, ret);
     }
+    TransitionToState(STATE_UPDATE_CACHED_RESPONSE_COMPLETE);
   } else {
     // If we are already reading, we already updated the headers for this
     // request; doing it again will change Content-Length.
     if (!reading_) {
-      next_state_ = STATE_CACHE_WRITE_UPDATED_RESPONSE;
+      TransitionToState(STATE_CACHE_WRITE_UPDATED_RESPONSE);
       rv = OK;
+    } else {
+      TransitionToState(STATE_UPDATE_CACHED_RESPONSE_COMPLETE);
     }
   }
+
   return rv;
 }
 
 int HttpCache::Transaction::DoCacheWriteUpdatedResponse() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteUpdatedResponse");
 
-  next_state_ = STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE;
+  TransitionToState(STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE);
   return WriteResponseInfoToEntry(false);
 }
 
 int HttpCache::Transaction::DoCacheWriteUpdatedResponseComplete(int result) {
   TRACE_EVENT0("io",
                "HttpCacheTransaction::DoCacheWriteUpdatedResponseComplete");
-  next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
+  TransitionToState(STATE_UPDATE_CACHED_RESPONSE_COMPLETE);
   return OnWriteResponseInfoToEntryComplete(result);
 }
 
@@ -1640,18 +1650,18 @@
     // the first part to the user.
     ResetNetworkTransaction();
     new_response_ = NULL;
-    next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
+    TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
     partial_->SetRangeToStartDownload();
     return OK;
   }
-  next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
+  TransitionToState(STATE_OVERWRITE_CACHED_RESPONSE);
   return OK;
 }
 
 int HttpCache::Transaction::DoOverwriteCachedResponse() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoOverwriteCachedResponse");
   if (mode_ & READ) {
-    next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
+    TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
     return OK;
   }
 
@@ -1666,7 +1676,7 @@
     DoneWritingToEntry(false);
     mode_ = NONE;
     new_response_ = NULL;
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return OK;
   }
 
@@ -1676,29 +1686,29 @@
     DoneWritingToEntry(false);
     if (partial_)
       partial_->FixResponseHeaders(response_.headers.get(), true);
-    next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
+    TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
     return OK;
   }
 
-  next_state_ = STATE_CACHE_WRITE_RESPONSE;
+  TransitionToState(STATE_CACHE_WRITE_RESPONSE);
   return OK;
 }
 
 int HttpCache::Transaction::DoCacheWriteResponse() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse");
-  next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
+  TransitionToState(STATE_CACHE_WRITE_RESPONSE_COMPLETE);
   return WriteResponseInfoToEntry(truncated_);
 }
 
 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete");
-  next_state_ = STATE_TRUNCATE_CACHED_DATA;
+  TransitionToState(STATE_TRUNCATE_CACHED_DATA);
   return OnWriteResponseInfoToEntryComplete(result);
 }
 
 int HttpCache::Transaction::DoTruncateCachedData() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData");
-  next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
+  TransitionToState(STATE_TRUNCATE_CACHED_DATA_COMPLETE);
   if (!entry_)
     return OK;
   if (net_log_.IsCapturing())
@@ -1716,13 +1726,13 @@
     }
   }
 
-  next_state_ = STATE_TRUNCATE_CACHED_METADATA;
+  TransitionToState(STATE_TRUNCATE_CACHED_METADATA);
   return OK;
 }
 
 int HttpCache::Transaction::DoTruncateCachedMetadata() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedMetadata");
-  next_state_ = STATE_TRUNCATE_CACHED_METADATA_COMPLETE;
+  TransitionToState(STATE_TRUNCATE_CACHED_METADATA_COMPLETE);
   if (!entry_)
     return OK;
 
@@ -1740,7 +1750,7 @@
     }
   }
 
-  next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
+  TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
   return OK;
 }
 
@@ -1749,25 +1759,25 @@
 
   if (!partial_) {
     if (entry_ && entry_->disk_entry->GetDataSize(kMetadataIndex))
-      next_state_ = STATE_CACHE_READ_METADATA;
+      TransitionToState(STATE_CACHE_READ_METADATA);
     else
-      next_state_ = STATE_NONE;
+      TransitionToState(STATE_NONE);
     return OK;
   }
 
   if (reading_) {
     if (network_trans_.get()) {
-      next_state_ = STATE_NETWORK_READ;
+      TransitionToState(STATE_NETWORK_READ);
     } else {
-      next_state_ = STATE_CACHE_READ_DATA;
+      TransitionToState(STATE_CACHE_READ_DATA);
     }
   } else if (mode_ != NONE) {
     // We are about to return the headers for a byte-range request to the user,
     // so let's fix them.
     partial_->FixResponseHeaders(response_.headers.get(), true);
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
   } else {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
   }
   return OK;
 }
@@ -1776,7 +1786,7 @@
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadMetadata");
   DCHECK(entry_);
   DCHECK(!response_.metadata.get());
-  next_state_ = STATE_CACHE_READ_METADATA_COMPLETE;
+  TransitionToState(STATE_CACHE_READ_METADATA_COMPLETE);
 
   response_.metadata =
       new IOBufferWithSize(entry_->disk_entry->GetDataSize(kMetadataIndex));
@@ -1794,13 +1804,13 @@
                                     result);
   if (result != response_.metadata->size())
     return OnCacheReadError(result, false);
-  next_state_ = STATE_NONE;
+  TransitionToState(STATE_NONE);
   return OK;
 }
 
 int HttpCache::Transaction::DoNetworkRead() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead");
-  next_state_ = STATE_NETWORK_READ_COMPLETE;
+  TransitionToState(STATE_NETWORK_READ_COMPLETE);
   return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
 }
 
@@ -1809,18 +1819,18 @@
   DCHECK(mode_ & WRITE || mode_ == NONE);
 
   if (!cache_.get()) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_UNEXPECTED;
   }
 
   // If there is an error or we aren't saving the data, we are done; just wait
   // until the destructor runs to see if we can keep the data.
   if (mode_ == NONE || result < 0) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return result;
   }
 
-  next_state_ = STATE_CACHE_WRITE_DATA;
+  TransitionToState(STATE_CACHE_WRITE_DATA);
   return result;
 }
 
@@ -1828,12 +1838,12 @@
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData");
 
   if (request_->method == "HEAD") {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return 0;
   }
 
   DCHECK(entry_);
-  next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
+  TransitionToState(STATE_CACHE_READ_DATA_COMPLETE);
 
   if (net_log_.IsCapturing())
     net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_DATA);
@@ -1855,7 +1865,7 @@
   }
 
   if (!cache_.get()) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_UNEXPECTED;
   }
 
@@ -1876,13 +1886,13 @@
     return OnCacheReadError(result, false);
   }
 
-  next_state_ = STATE_NONE;
+  TransitionToState(STATE_NONE);
   return result;
 }
 
 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteData");
-  next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
+  TransitionToState(STATE_CACHE_WRITE_DATA_COMPLETE);
   write_len_ = num_bytes;
   if (entry_) {
     if (net_log_.IsCapturing())
@@ -1906,7 +1916,7 @@
     }
   }
   if (!cache_.get()) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_UNEXPECTED;
   }
 
@@ -1941,20 +1951,20 @@
     }
   }
 
-  next_state_ = STATE_NONE;
+  TransitionToState(STATE_NONE);
   return result;
 }
 
 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
-  next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE;
+  TransitionToState(STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE);
   return WriteResponseInfoToEntry(true);
 }
 
 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
 
-  next_state_ = STATE_NONE;
+  TransitionToState(STATE_NONE);
   return OnWriteResponseInfoToEntryComplete(result);
 }
 
@@ -2091,18 +2101,18 @@
   // TODO(jkarlin): Either handle this case or DCHECK.
   if (response_.headers->response_code() == 206 || partial_) {
     NOTREACHED();
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_CACHE_MISS;
   }
 
   // We don't have the whole resource.
   if (truncated_) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_CACHE_MISS;
   }
 
   if (RequiresValidation() != VALIDATION_NONE) {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
     return ERR_CACHE_MISS;
   }
 
@@ -2110,9 +2120,9 @@
     FixHeadersForHead();
 
   if (entry_->disk_entry->GetDataSize(kMetadataIndex))
-    next_state_ = STATE_CACHE_READ_METADATA;
+    TransitionToState(STATE_CACHE_READ_METADATA);
   else
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
 
   return OK;
 }
@@ -2138,7 +2148,7 @@
       return SetupEntryForRead();
 
     // Bail out!
-    next_state_ = STATE_SEND_REQUEST;
+    TransitionToState(STATE_SEND_REQUEST);
     mode_ = NONE;
     return OK;
   }
@@ -2176,7 +2186,7 @@
 
       DCHECK_NE(206, response_.headers->response_code());
     }
-    next_state_ = STATE_SEND_REQUEST;
+    TransitionToState(STATE_SEND_REQUEST);
   }
   return OK;
 }
@@ -2203,7 +2213,7 @@
     }
   }
 
-  next_state_ = STATE_CACHE_QUERY_DATA;
+  TransitionToState(STATE_CACHE_QUERY_DATA);
   return OK;
 }
 
@@ -2224,7 +2234,7 @@
     invalid_range_ = true;
   }
 
-  next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
+  TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
   return OK;
 }
 
@@ -2267,7 +2277,7 @@
                             type,
                             EXTERNALLY_CONDITIONALIZED_MAX);
 
-  next_state_ = STATE_SEND_REQUEST;
+  TransitionToState(STATE_SEND_REQUEST);
   return OK;
 }
 
@@ -2619,7 +2629,7 @@
     if (truncated_ || is_sparse_ || !invalid_range_) {
       // We are going to return the saved response headers to the caller, so
       // we may need to adjust them first.
-      next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
+      TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
       return OK;
     } else {
       partial_.reset();
@@ -2632,9 +2642,9 @@
     FixHeadersForHead();
 
   if (entry_->disk_entry->GetDataSize(kMetadataIndex))
-    next_state_ = STATE_CACHE_READ_METADATA;
+    TransitionToState(STATE_CACHE_READ_METADATA);
   else
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
   return OK;
 }
 
@@ -2740,11 +2750,11 @@
     entry_ = NULL;
     is_sparse_ = false;
     partial_.reset();
-    next_state_ = STATE_GET_BACKEND;
+    TransitionToState(STATE_GET_BACKEND);
     return OK;
   }
 
-  next_state_ = STATE_NONE;
+  TransitionToState(STATE_NONE);
   return ERR_CACHE_READ_FAILURE;
 }
 
@@ -2779,9 +2789,9 @@
   if (result == 0) {
     // We need to move on to the next range.
     ResetNetworkTransaction();
-    next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
+    TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
   } else {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
   }
   return result;
 }
@@ -2791,11 +2801,11 @@
 
   if (result == 0 && mode_ == READ_WRITE) {
     // We need to move on to the next range.
-    next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
+    TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
   } else if (result < 0) {
     return OnCacheReadError(result, false);
   } else {
-    next_state_ = STATE_NONE;
+    TransitionToState(STATE_NONE);
   }
   return result;
 }
@@ -2808,7 +2818,7 @@
   // to Doom the entry again).
   mode_ = WRITE;
   ResetPartialState(!range_requested_);
-  next_state_ = STATE_CREATE_ENTRY;
+  TransitionToState(STATE_CREATE_ENTRY);
   return OK;
 }
 
@@ -3073,4 +3083,11 @@
   DoLoop(result);
 }
 
+void HttpCache::Transaction::TransitionToState(State state) {
+  // Ensure that the state is only set once per Do* state.
+  DCHECK(in_do_loop_);
+  DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state;
+  next_state_ = state;
+}
+
 }  // namespace net
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 0998695..a8fca542 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -434,6 +434,10 @@
   // Called to signal completion of asynchronous IO.
   void OnIOComplete(int result);
 
+  // When in a DoLoop, use this to set the next state as it verifies that the
+  // state isn't set twice.
+  void TransitionToState(State state);
+
   State next_state_;
   const HttpRequestInfo* request_;
   RequestPriority priority_;
@@ -508,6 +512,9 @@
   BeforeNetworkStartCallback before_network_start_callback_;
   BeforeHeadersSentCallback before_headers_sent_callback_;
 
+  // True if the Transaction is currently processing the DoLoop.
+  bool in_do_loop_;
+
   base::WeakPtrFactory<Transaction> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(Transaction);
diff --git a/services/service_manager/runner/host/service_process_launcher.cc b/services/service_manager/runner/host/service_process_launcher.cc
index 3b92bf6..52077bb 100644
--- a/services/service_manager/runner/host/service_process_launcher.cc
+++ b/services/service_manager/runner/host/service_process_launcher.cc
@@ -189,10 +189,17 @@
   }
 
   if (child_process_.IsValid()) {
-    DVLOG(0) << "Launched child process pid=" << child_process_.Pid()
-             << ", instance=" << target_.instance()
-             << ", name=" << target_.name()
-             << ", user_id=" << target_.user_id();
+#if defined(OS_CHROMEOS)
+    // Always log instead of DVLOG because knowing which pid maps to which
+    // service is vital for interpreting crashes after-the-fact and Chrome OS
+    // devices generally run release builds, even in development.
+    VLOG(0)
+#else
+    DVLOG(0)
+#endif
+        << "Launched child process pid=" << child_process_.Pid()
+        << ", instance=" << target_.instance() << ", name=" << target_.name()
+        << ", user_id=" << target_.user_id();
 
     if (mojo_ipc_channel_.get()) {
       mojo_ipc_channel_->ChildProcessLaunched();
diff --git a/services/ui/public/interfaces/window_tree.mojom b/services/ui/public/interfaces/window_tree.mojom
index e38b7f0..13de19f 100644
--- a/services/ui/public/interfaces/window_tree.mojom
+++ b/services/ui/public/interfaces/window_tree.mojom
@@ -339,6 +339,11 @@
   // change.
   OnCaptureChanged(uint32 new_capture, uint32 old_capture);
 
+  // This is called on the owner of a window when it embeds a client in it,
+  // which includes the window manager creating a new window at the request of
+  // another client.
+  OnFrameSinkIdAllocated(uint32 window, cc.mojom.FrameSinkId frame_sink_id);
+
   // Called in response to NewTopLevelWindow() successfully completing.
   // |parent_drawn| is true if the parent of the window is drawn, see
   // OnDrawnStateChanged() for details. |display_id| identifies the display this
diff --git a/services/ui/ws/test_change_tracker.cc b/services/ui/ws/test_change_tracker.cc
index 06f9344..e52a2da1 100644
--- a/services/ui/ws/test_change_tracker.cc
+++ b/services/ui/ws/test_change_tracker.cc
@@ -54,6 +54,11 @@
                                 WindowIdToString(change.window_id).c_str(),
                                 WindowIdToString(change.window_id2).c_str());
 
+    case CHANGE_TYPE_FRAME_SINK_ID_ALLOCATED:
+      return base::StringPrintf("OnFrameSinkIdAllocated window=%s %s",
+                                WindowIdToString(change.window_id).c_str(),
+                                change.frame_sink_id.ToString().c_str());
+
     case CHANGE_TYPE_NODE_ADD_TRANSIENT_WINDOW:
       return base::StringPrintf("AddTransientWindow parent = %s child = %s",
                                 WindowIdToString(change.window_id).c_str(),
@@ -304,6 +309,16 @@
   AddChange(change);
 }
 
+void TestChangeTracker::OnFrameSinkIdAllocated(
+    Id window_id,
+    const cc::FrameSinkId& frame_sink_id) {
+  Change change;
+  change.type = CHANGE_TYPE_FRAME_SINK_ID_ALLOCATED;
+  change.window_id = window_id;
+  change.frame_sink_id = frame_sink_id;
+  AddChange(change);
+}
+
 void TestChangeTracker::OnWindowHierarchyChanged(
     Id window_id,
     Id old_parent_id,
diff --git a/services/ui/ws/test_change_tracker.h b/services/ui/ws/test_change_tracker.h
index 84c978e8..d736fe67 100644
--- a/services/ui/ws/test_change_tracker.h
+++ b/services/ui/ws/test_change_tracker.h
@@ -22,6 +22,7 @@
 
 enum ChangeType {
   CHANGE_TYPE_CAPTURE_CHANGED,
+  CHANGE_TYPE_FRAME_SINK_ID_ALLOCATED,
   CHANGE_TYPE_EMBED,
   CHANGE_TYPE_EMBEDDED_APP_DISCONNECTED,
   CHANGE_TYPE_UNEMBED,
@@ -148,6 +149,8 @@
   void OnEmbeddedAppDisconnected(Id window_id);
   void OnUnembed(Id window_id);
   void OnCaptureChanged(Id new_capture_window_id, Id old_capture_window_id);
+  void OnFrameSinkIdAllocated(Id window_id,
+                              const cc::FrameSinkId& frame_sink_id);
   void OnTransientWindowAdded(Id window_id, Id transient_window_id);
   void OnTransientWindowRemoved(Id window_id, Id transient_window_id);
   void OnWindowBoundsChanged(
diff --git a/services/ui/ws/test_utils.cc b/services/ui/ws/test_utils.cc
index 61d1932..48c2ae8 100644
--- a/services/ui/ws/test_utils.cc
+++ b/services/ui/ws/test_utils.cc
@@ -290,6 +290,12 @@
   tracker_.OnCaptureChanged(new_capture_window_id, old_capture_window_id);
 }
 
+void TestWindowTreeClient::OnFrameSinkIdAllocated(
+    Id window_id,
+    const cc::FrameSinkId& frame_sink_id) {
+  tracker_.OnFrameSinkIdAllocated(window_id, frame_sink_id);
+}
+
 void TestWindowTreeClient::OnTopLevelCreated(
     uint32_t change_id,
     mojom::WindowDataPtr data,
diff --git a/services/ui/ws/test_utils.h b/services/ui/ws/test_utils.h
index 3f68927..df4488d 100644
--- a/services/ui/ws/test_utils.h
+++ b/services/ui/ws/test_utils.h
@@ -404,6 +404,8 @@
   void OnUnembed(Id window_id) override;
   void OnCaptureChanged(Id new_capture_window_id,
                         Id old_capture_window_id) override;
+  void OnFrameSinkIdAllocated(Id window_id,
+                              const cc::FrameSinkId& frame_sink_id) override;
   void OnTopLevelCreated(uint32_t change_id,
                          mojom::WindowDataPtr data,
                          int64_t display_id,
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc
index df00978b..c6651fe 100644
--- a/services/ui/ws/window_tree.cc
+++ b/services/ui/ws/window_tree.cc
@@ -470,17 +470,18 @@
 }
 
 bool WindowTree::Embed(const ClientWindowId& window_id,
-                       mojom::WindowTreeClientPtr client,
+                       mojom::WindowTreeClientPtr window_tree_client,
                        uint32_t flags) {
-  if (!client || !CanEmbed(window_id))
+  if (!window_tree_client || !CanEmbed(window_id))
     return false;
   ServerWindow* window = GetWindowByClientId(window_id);
   PrepareForEmbed(window);
   // When embedding we don't know the user id of where the TreeClient came
   // from. Use an invalid id, which limits what the client is able to do.
-  window_server_->EmbedAtWindow(window, InvalidUserId(), std::move(client),
-                                flags,
+  window_server_->EmbedAtWindow(window, InvalidUserId(),
+                                std::move(window_tree_client), flags,
                                 base::WrapUnique(new DefaultAccessPolicy));
+  client()->OnFrameSinkIdAllocated(window_id.id, window->frame_sink_id());
   return true;
 }
 
@@ -2075,6 +2076,10 @@
     window_server_->WindowManagerSentBogusMessage();
     window = nullptr;
   }
+  if (window) {
+    client()->OnFrameSinkIdAllocated(transport_window_id,
+                                     window->frame_sink_id());
+  }
   window_server_->WindowManagerCreatedTopLevelWindow(this, change_id, window);
 }
 
diff --git a/services/ui/ws/window_tree.h b/services/ui/ws/window_tree.h
index 4a03b18..756c155 100644
--- a/services/ui/ws/window_tree.h
+++ b/services/ui/ws/window_tree.h
@@ -180,7 +180,7 @@
   bool SetWindowOpacity(const ClientWindowId& window_id, float opacity);
   bool SetFocus(const ClientWindowId& window_id);
   bool Embed(const ClientWindowId& window_id,
-             mojom::WindowTreeClientPtr client,
+             mojom::WindowTreeClientPtr window_tree_client,
              uint32_t flags);
   void DispatchInputEvent(ServerWindow* target, const ui::Event& event);
 
diff --git a/services/ui/ws/window_tree_client_unittest.cc b/services/ui/ws/window_tree_client_unittest.cc
index eb2425f..cdfe5ce 100644
--- a/services/ui/ws/window_tree_client_unittest.cc
+++ b/services/ui/ws/window_tree_client_unittest.cc
@@ -298,6 +298,8 @@
                         Id old_capture_window_id) override {
     tracker()->OnCaptureChanged(new_capture_window_id, old_capture_window_id);
   }
+  void OnFrameSinkIdAllocated(Id window_id,
+                              const cc::FrameSinkId& frame_sink_id) override {}
   void OnTopLevelCreated(uint32_t change_id,
                          mojom::WindowDataPtr data,
                          int64_t display_id,
diff --git a/services/ui/ws/window_tree_unittest.cc b/services/ui/ws/window_tree_unittest.cc
index be17bc3..df3860e 100644
--- a/services/ui/ws/window_tree_unittest.cc
+++ b/services/ui/ws/window_tree_unittest.cc
@@ -664,6 +664,34 @@
             ChangesToDescription1(*wm_client()->tracker()->changes())[0]);
 }
 
+// Establish client, call Embed() in WM, make sure to get FrameSinkId.
+TEST_F(WindowTreeTest, Embed) {
+  const ClientWindowId embed_window_id = BuildClientWindowId(wm_tree(), 1);
+  EXPECT_TRUE(
+      wm_tree()->NewWindow(embed_window_id, ServerWindow::Properties()));
+  ServerWindow* embed_window = wm_tree()->GetWindowByClientId(embed_window_id);
+  ASSERT_TRUE(embed_window);
+  const ClientWindowId wm_root_id = FirstRootId(wm_tree());
+  EXPECT_TRUE(wm_tree()->AddWindow(wm_root_id, embed_window_id));
+  ServerWindow* wm_root = FirstRoot(wm_tree());
+  ASSERT_TRUE(wm_root);
+  mojom::WindowTreeClientPtr client;
+  mojom::WindowTreeClientRequest client_request(&client);
+  wm_client()->Bind(std::move(client_request));
+  const uint32_t embed_flags = 0;
+  wm_tree()->Embed(embed_window_id, std::move(client), embed_flags);
+  ASSERT_EQ(1u, wm_client()->tracker()->changes()->size())
+      << SingleChangeToDescription(*wm_client()->tracker()->changes());
+  // The window manager should be told about the FrameSinkId of the embedded
+  // window.
+  EXPECT_EQ(
+      base::StringPrintf(
+          "OnFrameSinkIdAllocated window=%s %s",
+          WindowIdToString(WindowIdFromTransportId(embed_window_id.id)).c_str(),
+          embed_window->frame_sink_id().ToString().c_str()),
+      SingleChangeToDescription(*wm_client()->tracker()->changes()));
+}
+
 // Establish client, call NewTopLevelWindow(), make sure get id, and make
 // sure client paused.
 TEST_F(WindowTreeTest, NewTopLevelWindow) {
@@ -700,9 +728,20 @@
   child_binding->client()->tracker()->changes()->clear();
   static_cast<mojom::WindowManagerClient*>(wm_tree())
       ->OnWmCreatedTopLevelWindow(wm_change_id, embed_window_id2.id);
-  EXPECT_FALSE(child_binding->is_paused());
+
   ServerWindow* embed_window = wm_tree()->GetWindowByClientId(embed_window_id2);
   ASSERT_TRUE(embed_window);
+  ASSERT_EQ(1u, wm_client()->tracker()->changes()->size())
+      << SingleChangeToDescription(*wm_client()->tracker()->changes());
+  // The window manager should be told about the FrameSinkId of the embedded
+  // window.
+  EXPECT_EQ(base::StringPrintf(
+                "OnFrameSinkIdAllocated window=%s %s",
+                WindowIdToString(WindowIdFromTransportId(embed_window_id2.id))
+                    .c_str(),
+                embed_window->frame_sink_id().ToString().c_str()),
+            SingleChangeToDescription(*wm_client()->tracker()->changes()));
+  EXPECT_FALSE(child_binding->is_paused());
   // TODO(fsamuel): Currently the FrameSinkId maps directly to the server's
   // window ID. This is likely bad from a security perspective and should be
   // fixed.
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 356de3d1..e1974de 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -556,21 +556,6 @@
             ]
         }
     ],
-    "DisableFirstRunAutoImport": [
-        {
-            "platforms": [
-                "win"
-            ],
-            "experiments": [
-                {
-                    "name": "AutoImportDisabled",
-                    "enable_features": [
-                        "DisableFirstRunAutoImport"
-                    ]
-                }
-            ]
-        }
-    ],
     "DisallowFetchForDocWrittenScriptsInMainFrame": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index a0c3ee5c..4c3e22f 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -125,9 +125,6 @@
 # A real bug with a Skia assert
 crbug.com/671048 virtual/color_space/fast/canvas/color-space/display_linear-rgb.html [ Pass Failure Crash ]
 
-crbug.com/683339 paint/invalidation/paged-with-overflowing-block-rl.html [ Failure ]
-crbug.com/683339 virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl.html [ Failure ]
-
 crbug.com/701800 [ Win7 ] virtual/disable-spinvalidation/compositing/perpendicular-layer-sorting.html [ Pass Failure ]
 
 crbug.com/702006 paint/invalidation/compositing/scrolling-neg-z-index-descendants-should-cause-repaint.html [ Failure ]
@@ -815,8 +812,6 @@
 crbug.com/520188 [ Win ] http/tests/local/fileapi/file-last-modified-after-delete.html [ Failure Pass ]
 crbug.com/520188 [ Win ] virtual/mojo-loading/http/tests/local/fileapi/file-last-modified-after-delete.html [ Failure Pass ]
 crbug.com/520611 [ Debug ] fast/filesystem/workers/file-writer-events-shared-worker.html [ Failure Pass ]
-crbug.com/520613 http/tests/cache/freshness-header.html [ Failure Pass ]
-crbug.com/520613 virtual/mojo-loading/http/tests/cache/freshness-header.html [ Failure Pass ]
 crbug.com/520194 http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overridesexpires.html [ Failure Pass ]
 crbug.com/520194 virtual/mojo-loading/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overridesexpires.html [ Failure Pass ]
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/cache/freshness-header.html b/third_party/WebKit/LayoutTests/http/tests/cache/freshness-header.html
deleted file mode 100644
index f0332d0..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/cache/freshness-header.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<script src="/js-test-resources/js-test.js"></script>
-<script>
-description("Resource-Freshness header is sent when a revalidation request is initiated by the Blink memory cache within the stale-while-revalidate window.");
-
-var resourceFreshnessHeader;
-function report(value) {
-  resourceFreshnessHeader = value;
-}
-
-window.jsTestIsAsync = true;
-
-window.onload = function () {
-    // We set the timeout to 500 msec here because we expect age=1 in the
-    // ResourceFreshness header if the age is [0.5, 1.5) seconds.
-    setTimeout(
-        function() {
-            var script = document.createElement("script");
-            script.src = "resources/stale-while-revalidate.php";
-            script.onload = function() {
-                shouldBeEqualToString(
-                    'resourceFreshnessHeader',
-                    'max-age=0,stale-while-revalidate=1,age=1');
-                finishJSTest();
-            };
-            document.body.appendChild(script);
-        },
-        500);
-};
-</script>
-<script src="resources/stale-while-revalidate.php"></script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/cache/resources/stale-while-revalidate.php b/third_party/WebKit/LayoutTests/http/tests/cache/resources/stale-while-revalidate.php
deleted file mode 100644
index cb7fd72..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/cache/resources/stale-while-revalidate.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-$last_modified = gmdate(DATE_RFC1123, time() - 1);
-
-header('Cache-Control: private, max-age=0, stale-while-revalidate=1');
-header('Last-Modified: ' . $last_modified);
-header('Content-Type: application/javascript');
-echo('report("' . $_SERVER['HTTP_RESOURCE_FRESHNESS'] . '");');
-?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js
index 219cfb2..4072611 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js
@@ -81,7 +81,7 @@
 InspectorTest.dumpApplicationCacheTree = function()
 {
     InspectorTest.addResult("Dumping application cache tree:");
-    var applicationCacheTreeElement = UI.panels.resources.applicationCacheListTreeElement;
+    var applicationCacheTreeElement = UI.panels.resources._sidebar.applicationCacheListTreeElement;
     if (!applicationCacheTreeElement.childCount()) {
         InspectorTest.addResult("    (empty)");
         return;
@@ -127,7 +127,7 @@
 InspectorTest.dumpApplicationCacheModel = function()
 {
     InspectorTest.addResult("Dumping application cache model:");
-    var model = UI.panels.resources._applicationCacheModel;
+    var model = UI.panels.resources._sidebar._applicationCacheModel;
 
     var frameIds = [];
     for (var frameId in model._manifestURLsByFrame)
@@ -154,8 +154,8 @@
 
 InspectorTest.waitForFrameManifestURLAndStatus = function(frameId, manifestURL, status, callback)
 {
-    var frameManifestStatus = UI.panels.resources._applicationCacheModel.frameManifestStatus(frameId);
-    var frameManifestURL = UI.panels.resources._applicationCacheModel.frameManifestURL(frameId);
+    var frameManifestStatus = UI.panels.resources._sidebar._applicationCacheModel.frameManifestStatus(frameId);
+    var frameManifestURL = UI.panels.resources._sidebar._applicationCacheModel.frameManifestURL(frameId);
     if (frameManifestStatus === status && frameManifestURL.indexOf(manifestURL) !== -1) {
         callback();
         return;
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/cache-storage/cache-storage-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/cache-storage/cache-storage-test.js
index 1f6c7cb3..46fd8ae 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/cache-storage/cache-storage-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/cache-storage/cache-storage-test.js
@@ -7,9 +7,9 @@
 
 InspectorTest.dumpCacheTree = function()
 {
-    UI.panels.resources.cacheStorageListTreeElement.expand();
+    UI.panels.resources._sidebar.cacheStorageListTreeElement.expand();
     InspectorTest.addResult("Dumping CacheStorage tree:");
-    var cachesTreeElement = UI.panels.resources.cacheStorageListTreeElement;
+    var cachesTreeElement = UI.panels.resources._sidebar.cacheStorageListTreeElement;
     var promise = new Promise(function(resolve, reject) {
         InspectorTest.addSnifferPromise(SDK.ServiceWorkerCacheModel.prototype, "_updateCacheNames").then(crawlCacheTree).catch(reject);
 
@@ -65,20 +65,20 @@
             }
         }
     });
-    UI.panels.resources.cacheStorageListTreeElement._refreshCaches();
+    UI.panels.resources._sidebar.cacheStorageListTreeElement._refreshCaches();
     return promise;
 }
 
 // If optionalEntry is not specified, then the whole cache is deleted.
 InspectorTest.deleteCacheFromInspector = function(cacheName, optionalEntry)
 {
-    UI.panels.resources.cacheStorageListTreeElement.expand();
+    UI.panels.resources._sidebar.cacheStorageListTreeElement.expand();
     if (optionalEntry) {
         InspectorTest.addResult("Deleting CacheStorage entry " + optionalEntry + " in cache " + cacheName);
     } else {
         InspectorTest.addResult("Deleting CacheStorage cache " + cacheName);
     }
-    var cachesTreeElement = UI.panels.resources.cacheStorageListTreeElement;
+    var cachesTreeElement = UI.panels.resources._sidebar.cacheStorageListTreeElement;
     var promise = new Promise(function(resolve, reject) {
         InspectorTest.addSnifferPromise(SDK.ServiceWorkerCacheModel.prototype, "_updateCacheNames")
             .then(function() {
@@ -124,7 +124,7 @@
                 reject("Error: Could not find CacheStorage cache " + cacheName);
             }).catch(reject);
     });
-    UI.panels.resources.cacheStorageListTreeElement._refreshCaches();
+    UI.panels.resources._sidebar.cacheStorageListTreeElement._refreshCaches();
     return promise;
 }
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js
index 9a85f61..9547f4a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js
@@ -4,7 +4,7 @@
 InspectorTest.dumpIndexedDBTree = function()
 {
     InspectorTest.addResult("Dumping IndexedDB tree:");
-    var indexedDBTreeElement = UI.panels.resources.indexedDBListTreeElement;
+    var indexedDBTreeElement = UI.panels.resources._sidebar.indexedDBListTreeElement;
     if (!indexedDBTreeElement.childCount()) {
         InspectorTest.addResult("    (empty)");
         return;
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/resources-panel.html b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/resources-panel.html
index 4c28029..f5dd2bdc 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/resources-panel.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/resources-panel.html
@@ -70,7 +70,7 @@
     UI.viewManager.showView("resources");
 
     InspectorTest.addResult("Expanded IndexedDB tree element.");
-    UI.panels.resources.indexedDBListTreeElement.expand();
+    UI.panels.resources._sidebar.indexedDBListTreeElement.expand();
     InspectorTest.dumpIndexedDBTree();
     InspectorTest.addResult("Created database.");
     createDatabase(databaseCreated);
@@ -79,7 +79,7 @@
     {
         indexedDBModel = InspectorTest.indexedDBModel();
         indexedDBModel.addEventListener(Resources.IndexedDBModel.Events.DatabaseLoaded, databaseLoaded);
-        UI.panels.resources.indexedDBListTreeElement.refreshIndexedDB();
+        UI.panels.resources._sidebar.indexedDBListTreeElement.refreshIndexedDB();
     }
 
     function databaseLoaded()
@@ -106,14 +106,14 @@
 
     function databaseDeleted()
     {
-        UI.panels.resources.indexedDBListTreeElement.refreshIndexedDB();
+        UI.panels.resources._sidebar.indexedDBListTreeElement.refreshIndexedDB();
         InspectorTest.addSniffer(Resources.IndexedDBModel.prototype, "_updateOriginDatabaseNames", databaseNamesLoadedAfterDeleting, false);
     }
 
     function databaseNamesLoadedAfterDeleting()
     {
         InspectorTest.dumpIndexedDBTree();
-        UI.panels.resources.indexedDBListTreeElement.collapse();
+        UI.panels.resources._sidebar.indexedDBListTreeElement.collapse();
         InspectorTest.completeTest();
     }
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/resource-tree/resource-tree-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/resource-tree/resource-tree-test.js
index 31659ff..7382307c 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/resource-tree/resource-tree-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/resource-tree/resource-tree-test.js
@@ -64,7 +64,7 @@
             dump(children[i], prefix + "    ");
     }
 
-    dump(UI.panels.resources._resourcesSection._treeElement, "");
+    dump(UI.panels.resources._sidebar._resourcesSection._treeElement, "");
     if (!InspectorTest._testSourceNavigator) {
         InspectorTest._testSourceNavigator = new Sources.SourcesNavigatorView();
         InspectorTest._testSourceNavigator.show(UI.inspectorView.element);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-force-update-on-page-load.html b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-force-update-on-page-load.html
index ac59b8e..102e0f3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-force-update-on-page-load.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-force-update-on-page-load.html
@@ -90,7 +90,7 @@
             InspectorTest.deleteServiceWorkerRegistration(scope);
             InspectorTest.completeTest();
         });
-    UI.panels.resources.serviceWorkersTreeElement.select();
+    UI.panels.resources._sidebar.serviceWorkersTreeElement.select();
     InspectorTest.registerServiceWorker(scriptURL, scope);
 }
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-view.html b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-view.html
index 8f4aec5b..a553528b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-view.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-view.html
@@ -42,7 +42,7 @@
     }
 
     InspectorTest.addResult("Select ServiceWorkers tree element.");
-    UI.panels.resources.serviceWorkersTreeElement.select();
+    UI.panels.resources._sidebar.serviceWorkersTreeElement.select();
     InspectorTest.addResult("Register ServiceWorker for scope1");
     InspectorTest.registerServiceWorker(scriptURL, scope1);
 }
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/resolve-alien-node.html b/third_party/WebKit/LayoutTests/inspector/elements/resolve-alien-node.html
index c33ff51d8..daee268c 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/resolve-alien-node.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/resolve-alien-node.html
@@ -10,7 +10,7 @@
     function step1(error, result, exceptionDetails)
     {
         var spanWrapper = InspectorTest.runtimeModel.createRemoteObject(result);
-        InspectorTest.domModel.pushObjectAsNodeToFrontend(spanWrapper, step2);
+        InspectorTest.domModel.pushObjectAsNodeToFrontend(spanWrapper).then(step2);
     }
 
     function step2(node)
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html
index 78c6d05..45532d9 100644
--- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html
+++ b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html
@@ -92,7 +92,7 @@
         }
         InspectorTest.recordNetwork();
         InspectorTest.addSniffer(UI.panels.sources, "showUILocation", showUILocationHook, true);
-        InspectorTest.addSniffer(UI.panels.resources, "showResource", showResourceHook, true);
+        InspectorTest.addSniffer(UI.panels.resources._sidebar, "showResource", showResourceHook, true);
         InspectorTest.addSniffer(UI.panels.network, "revealAndHighlightRequest", showRequestHook, true);
 
         function showUILocationHook(uiLocation)
diff --git a/third_party/WebKit/LayoutTests/inspector/reveal-objects.html b/third_party/WebKit/LayoutTests/inspector/reveal-objects.html
index 5437ac9..7f2480dc 100644
--- a/third_party/WebKit/LayoutTests/inspector/reveal-objects.html
+++ b/third_party/WebKit/LayoutTests/inspector/reveal-objects.html
@@ -99,7 +99,7 @@
     {
         InspectorTest.addSniffer(Elements.ElementsPanel.prototype, "revealAndSelectNode", nodeRevealed, true);
         InspectorTest.addSniffer(Sources.SourcesPanel.prototype, "showUILocation", uiLocationRevealed, true);
-        InspectorTest.addSniffer(Resources.ResourcesPanel.prototype, "showResource", resourceRevealed, true);
+        InspectorTest.addSniffer(Resources.ApplicationPanelSidebar.prototype, "showResource", resourceRevealed, true);
         InspectorTest.addSniffer(Network.NetworkPanel.prototype, "revealAndHighlightRequest", revealed, true);
     }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/source-frame.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/source-frame.html
index 2b0d545..7767684 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/source-frame.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/source-frame.html
@@ -60,7 +60,7 @@
             function visit(resource)
             {
                 if (resource.url.indexOf("debugger-test.js") !== -1) {
-                    UI.panels.resources.showResource(resource, 1);
+                    UI.panels.resources._sidebar.showResource(resource, 1);
                     return true;
                 }
             }
diff --git a/third_party/WebKit/LayoutTests/inspector/storage-panel-dom-storage-update.html b/third_party/WebKit/LayoutTests/inspector/storage-panel-dom-storage-update.html
index d92f55b..88661bc 100644
--- a/third_party/WebKit/LayoutTests/inspector/storage-panel-dom-storage-update.html
+++ b/third_party/WebKit/LayoutTests/inspector/storage-panel-dom-storage-update.html
@@ -66,7 +66,7 @@
 
             InspectorTest.assertTrue(!!storage, "Local storage not found.");
 
-            UI.panels.resources._showDOMStorage(storage);
+            UI.panels.resources.showDOMStorage(storage);
             view = UI.panels.resources._domStorageView;
             InspectorTest.addSniffer(view, "_showDOMStorageItems", viewUpdated);
         },
diff --git a/third_party/WebKit/LayoutTests/inspector/storage-panel-dom-storage.html b/third_party/WebKit/LayoutTests/inspector/storage-panel-dom-storage.html
index 3500e71..503eb707 100644
--- a/third_party/WebKit/LayoutTests/inspector/storage-panel-dom-storage.html
+++ b/third_party/WebKit/LayoutTests/inspector/storage-panel-dom-storage.html
@@ -46,7 +46,7 @@
             InspectorTest.completeTest();
             return;
         }
-        UI.panels.resources._showDOMStorage(storage);
+        UI.panels.resources.showDOMStorage(storage);
         InspectorTest.addResult("Did show: " + name(storage));
         InspectorTest.deprecatedRunAfterPendingDispatches(function() {
             InspectorTest.addResult(name(storage) + " content: ");
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/paged-with-overflowing-block-rl-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/paged-with-overflowing-block-rl-expected.png
index f60842a..be9624a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/paged-with-overflowing-block-rl-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/paged-with-overflowing-block-rl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png
new file mode 100644
index 0000000..be9624a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/paged-with-overflowing-block-rl-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/paged-with-overflowing-block-rl-expected.png
index e30876e..a0553a3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/paged-with-overflowing-block-rl-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/paged-with-overflowing-block-rl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png
new file mode 100644
index 0000000..a0553a3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/paged-with-overflowing-block-rl-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/paged-with-overflowing-block-rl-expected.png
index 53fd21f0..857d8c6 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/paged-with-overflowing-block-rl-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/paged-with-overflowing-block-rl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png
new file mode 100644
index 0000000..857d8c6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/paged-with-overflowing-block-rl-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/paged-with-overflowing-block-rl-expected.png
index ccd6acf6..1381b793 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/paged-with-overflowing-block-rl-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/paged-with-overflowing-block-rl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png
new file mode 100644
index 0000000..1381b793
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/paged-with-overflowing-block-rl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html b/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html
index acfd67b..8e3a8232 100644
--- a/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html
+++ b/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html
@@ -6,105 +6,149 @@
 
 <html>
 <head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script> 
 <script src="../resources/audit-util.js"></script>
-<script src="../resources/audio-testing.js"></script>
+<script src="../resources/audit.js"></script>
 
 </head>
 <body>
 
 <script>
+let audit = Audit.createTaskRunner();
 
-window.onload = init;
+let sampleRate = 44100.0;
+let numberOfNotes = 60;  // play over a 5 octave range
+let noteDuration = 0.025;
+let noteSpacing =
+    noteDuration + 0.005;  // leave 5ms of silence between each "note"
+let lengthInSeconds = numberOfNotes * noteSpacing;
 
-var sampleRate = 44100.0;
-var numberOfNotes = 60; // play over a 5 octave range
-var noteDuration = 0.025;
-var noteSpacing = noteDuration + 0.005; // leave 5ms of silence between each "note"
-var lengthInSeconds = numberOfNotes * noteSpacing;
-
-var context = 0;
-var buffer = 0;
+let context = 0;
+let expectedAudio;
 
 function createTestBuffer(frequency, sampleRate) {
-    // Create a buffer containing two periods at this frequency.
-    // The 1st half is a pure sine wave period scaled by a linear ramp from 0 -> 1.
-    // The 2nd half of the buffer corresponds exactly to one pure sine wave period.
-    var onePeriodDuration = 1 / frequency;
-    var sampleFrameLength = 2 * onePeriodDuration * sampleRate;
+  // Create a buffer containing two periods at this frequency.
+  // The 1st half is a pure sine wave period scaled by a linear ramp from 0 ->
+  // 1. The 2nd half of the buffer corresponds exactly to one pure sine wave
+  // period.
+  let onePeriodDuration = 1 / frequency;
+  let sampleFrameLength = 2 * onePeriodDuration * sampleRate;
 
-    var audioBuffer = context.createBuffer(1, sampleFrameLength, sampleRate);
+  let audioBuffer = context.createBuffer(1, sampleFrameLength, sampleRate);
 
-    var n = audioBuffer.length;
-    var channelData = audioBuffer.getChannelData(0);
+  let n = audioBuffer.length;
+  let channelData = audioBuffer.getChannelData(0);
 
-    for (var i = 0; i < n; ++i) {
-        var sample = Math.sin(frequency * 2.0*Math.PI * i / sampleRate);
+  for (let i = 0; i < n; ++i) {
+    let sample = Math.sin(frequency * 2.0 * Math.PI * i / sampleRate);
 
-        // Linear ramp from 0 -> 1 for the first period.
-        // Stay at 1 for the 2nd period.
-        var scale = i < n / 2 ? i / (n / 2) : 1;
-        sample *= scale;
+    // Linear ramp from 0 -> 1 for the first period.
+    // Stay at 1 for the 2nd period.
+    let scale = i < n / 2 ? i / (n / 2) : 1;
+    sample *= scale;
 
-        channelData[i] = sample;
-    }
+    channelData[i] = sample;
+  }
 
-    return audioBuffer;
+  return audioBuffer;
 }
 
-function playNote(time, duration, playbackRate) {
-    var source = context.createBufferSource();
-    source.buffer = buffer;
-    source.playbackRate.value = playbackRate;
+function playNote(buffer, time, duration, playbackRate) {
+  let source = context.createBufferSource();
+  source.buffer = buffer;
+  source.playbackRate.value = playbackRate;
 
-    var gainNode = context.createGain();
-    source.connect(gainNode);
-    gainNode.connect(context.destination);
+  let gainNode = context.createGain();
+  source.connect(gainNode);
+  gainNode.connect(context.destination);
 
-    // Loop the 2nd half of the buffer.
-    // We should be able to hear any problems as glitches if the looping incorrectly indexes to
-    // anywhere outside of the desired loop-points, since only the 2nd half is a perfect sine-wave cycle,
-    // while the 1st half of the buffer contains a linear ramp of a sine-wave cycle.
-    source.loop = true;
-    source.loopStart = 0.5 * buffer.duration;
-    source.loopEnd = buffer.duration;
+  // Loop the 2nd half of the buffer.
+  // We should be able to hear any problems as glitches if the looping
+  // incorrectly indexes to anywhere outside of the desired loop-points, since
+  // only the 2nd half is a perfect sine-wave cycle, while the 1st half of the
+  // buffer contains a linear ramp of a sine-wave cycle.
+  source.loop = true;
+  source.loopStart = 0.5 * buffer.duration;
+  source.loopEnd = buffer.duration;
 
-    // Play for the given duration.
-    source.start(time);
-    source.stop(time + duration);
+  // Play for the given duration.
+  source.start(time);
+  source.stop(time + duration);
 
-    // Apply a quick linear fade-out to avoid a click at the end of the note.
-    gainNode.gain.value = 1;
-    gainNode.gain.setValueAtTime(1, time + duration - 0.005);
-    gainNode.gain.linearRampToValueAtTime(0, time + duration);
+  // Apply a quick linear fade-out to avoid a click at the end of the note.
+  gainNode.gain.value = 1;
+  gainNode.gain.setValueAtTime(1, time + duration - 0.005);
+  gainNode.gain.linearRampToValueAtTime(0, time + duration);
 }
 
-function init() {
-    if (!window.testRunner)
-        return;
+audit.define(
+    {label: 'initialize', description: 'Set up context and expected results'},
+    (task, should) => {
+      // Create offline audio context.
+      should(
+          () => {context = new OfflineAudioContext(
+                     2, sampleRate * lengthInSeconds, sampleRate)},
+          'Creating context for testing')
+          .notThrow();
 
-    // Create offline audio context.
-    context = new OfflineAudioContext(2, sampleRate * lengthInSeconds, sampleRate);
+      should(
+          Audit.loadFileFromUrl('audiobuffersource-loop-points-expected.wav')
+              .then(arrayBuffer => {
+                context.decodeAudioData(arrayBuffer).then(audioBuffer => {
+                  expectedAudio = audioBuffer;
+                });
+              }),
+          'Fetching expected audio')
+          .beResolved()
+          .then(() => task.done());
+    });
 
-    // Create the test buffer.
-    // We'll loop this with the loop-points set for the 2nd half of this buffer.
-    buffer = createTestBuffer(440.0, sampleRate);
+audit.define(
+    {
+      label: 'test',
+      description: 'Test loop points and compare with expected results'
+    },
+    (task, should) => {
+      // Create the test buffer.
+      // We'll loop this with the loop-points set for the 2nd half of this
+      // buffer.
+      let buffer = createTestBuffer(440.0, sampleRate);
 
-    // Play all the notes as a chromatic scale.
-    for (var i = 0; i < numberOfNotes; ++i) {
-        var time = i * noteSpacing;
-        var semitone = i - numberOfNotes/2; // start three octaves down
+      // Play all the notes as a chromatic scale.
+      for (let i = 0; i < numberOfNotes; ++i) {
+        let time = i * noteSpacing;
+        // start three octaves down
+        let semitone = i - numberOfNotes / 2;
 
         // Convert from semitone to rate.
-        var playbackRate = Math.pow(2, semitone / 12);
+        let playbackRate = Math.pow(2, semitone / 12);
 
-        playNote(time, noteDuration, playbackRate);
-    }
+        playNote(buffer, time, noteDuration, playbackRate);
+      }
 
-    context.oncomplete = finishAudioTest;
-    context.startRendering();
+      context.startRendering()
+          .then(renderedAudio => {
+            // Compute a threshold based on the maximum error, |maxUlp|, in ULP.
+            // This is experimentally determined. Assuming that the reference
+            // file is a 16-bit wav file, the max values in the wave file
+            // are +/- 32768.
+            let maxUlp = 0.9999;
+            let threshold = maxUlp / 32768;
 
-    testRunner.waitUntilDone();
-}
+            for (let k = 0; k < renderedAudio.numberOfChannels; ++k) {
+              should(
+                  renderedAudio.getChannelData(k),
+                  'Rendered audio for channel ' + k)
+                  .beCloseToArray(
+                      expectedAudio.getChannelData(k),
+                      {absoluteThreshold: threshold});
+            }
+          })
+          .then(() => task.done());
+    });
+
+audit.run();
 
 </script>
 
diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-multi-channels.html b/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-multi-channels.html
index 8fed30e..4139d36 100644
--- a/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-multi-channels.html
+++ b/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-multi-channels.html
@@ -6,38 +6,72 @@
 
 <html>
 <head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script> 
 <script src="../resources/audit-util.js"></script>
-<script src="../resources/audio-testing.js"></script>
-<script type="text/javascript" src="../resources/mix-testing.js"></script>
+<script src="../resources/audit.js"></script>
+<script src="../resources/mix-testing.js"></script>
 </head>
 <body>
 
 <script>
+let audit = Audit.createTaskRunner();
+let context;
+let expectedAudio;
+      
+audit.define('initialize', (task, should) => {
+  // Create offline audio context
+  let sampleRate = 44100.0;
+  should(() => {
+    context =
+        new OfflineAudioContext(6, sampleRate * toneLengthSeconds, sampleRate);
+  }, 'Creating context for testing').notThrow();
+  should(
+      Audit.loadFileFromUrl('audiobuffersource-multi-channels-expected.wav')
+          .then(arrayBuffer => {
+            context.decodeAudioData(arrayBuffer).then(audioBuffer => {
+              expectedAudio = audioBuffer;
+            });
+          }),
+      'Fetching expected audio')
+      .beResolved()
+      .then(() => task.done());
 
-function runTest() {
-    if (!window.testRunner)
-        return;
+});
 
-    testRunner.waitUntilDone();
+audit.define(
+    {label: 'test', description: 'AudioBufferSource with 5.1 buffer'},
+    (task, should) => {
+      let toneBuffer = createToneBuffer(context, 440, toneLengthSeconds, 6);
 
-    window.jsTestAsync = true;
+      let source = context.createBufferSource();
+      source.buffer = toneBuffer;
 
-    // Create offline audio context
-    var sampleRate = 44100.0;
-    var context = new OfflineAudioContext(6, sampleRate * toneLengthSeconds, sampleRate);
-    var toneBuffer = createToneBuffer(context, 440, toneLengthSeconds, 6); 
+      source.connect(context.destination);
+      source.start(0);
 
-    var source = context.createBufferSource();
-    source.buffer = toneBuffer;
+      context.startRendering()
+          .then(renderedAudio => {
+            // Compute a threshold based on the maximum error, |maxUlp|, in ULP.
+            // This is experimentally determined. Assuming that the reference
+            // file is a 16-bit wav file, the max values in the wave file
+            // are +/- 32768.
+            let maxUlp = 1;
+            let threshold = maxUlp / 32768;
 
-    source.connect(context.destination);
-    source.start(0);
+            for (let k = 0; k < renderedAudio.numberOfChannels; ++k) {
+              should(
+                  renderedAudio.getChannelData(k),
+                  'Rendered audio for channel ' + k)
+                  .beCloseToArray(
+                      expectedAudio.getChannelData(k),
+                      {absoluteThreshold: threshold});
+            }
+          })
+          .then(() => task.done());
+    });
 
-    context.oncomplete = finishAudioTest;
-    context.startRendering();
-}
-
-runTest();
+audit.run();
 </script>
 
 </body>
diff --git a/third_party/WebKit/Source/core/layout/compositing/GraphicsLayerUpdater.cpp b/third_party/WebKit/Source/core/layout/compositing/GraphicsLayerUpdater.cpp
index ebe6007f..66172b83 100644
--- a/third_party/WebKit/Source/core/layout/compositing/GraphicsLayerUpdater.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/GraphicsLayerUpdater.cpp
@@ -57,6 +57,10 @@
     if (layer.stackingNode()->isStacked())
       return m_compositingStackingContext;
 
+    // TODO(wangxianzhu, chrishtr): This is incorrect if m_compositingAncestor
+    // is inline and there is any non-layer floating object between layer and
+    // m_compositingAncestor. Should use the logic in PaintLayer::
+    // containingLayer().
     if (layer.layoutObject().isFloatingWithNonContainingBlockParent())
       return layer.enclosingLayerWithCompositedLayerMapping(ExcludeSelf);
 
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
index abd609c8f6..4bf93ca 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -870,8 +870,10 @@
     *skippedAncestor = false;
 
   LayoutObject& layoutObject = this->layoutObject();
-  if (layoutObject.isColumnSpanAll() ||
-      layoutObject.isFloatingWithNonContainingBlockParent()) {
+  // Column span need to find the containing layer through its containing block.
+  // TODO(wangxianzhu): This can be combined with the loop handing possible
+  // floating objects.
+  if (layoutObject.isColumnSpanAll()) {
     Optional<LayoutObject::AncestorSkipInfo> skipInfo;
     if (skippedAncestor)
       skipInfo.emplace(&ancestor->layoutObject());
@@ -899,7 +901,28 @@
     return curr;
   }
 
-  return parent();
+  // If the parent layer is not a block, there might be floating objects
+  // between this layer (included) and parent layer which need to escape the
+  // inline parent to find the actual containing layer through the containing
+  // block chain.
+  if (!parent() || parent()->layoutObject().isLayoutBlock())
+    return parent();
+
+  // This is a universal approach to find containing layer, but is slower than
+  // the earlier code.
+  Optional<LayoutObject::AncestorSkipInfo> skipInfo;
+  if (skippedAncestor)
+    skipInfo.emplace(&ancestor->layoutObject());
+  auto* object = &layoutObject;
+  while (auto* container =
+             object->container(skippedAncestor ? &*skipInfo : nullptr)) {
+    if (skippedAncestor && skipInfo->ancestorSkipped())
+      *skippedAncestor = true;
+    if (container->hasLayer())
+      return toLayoutBoxModelObject(container)->layer();
+    object = container;
+  }
+  return nullptr;
 }
 
 PaintLayer* PaintLayer::enclosingTransformedAncestor() const {
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
index aa63b15..8165be0 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -76,10 +76,7 @@
 
     const EffectPaintPropertyNode* effect =
         layoutObject.paintProperties()->effect();
-    const TransformPaintPropertyNode* transform =
-        layoutObject.paintProperties()->transform();
-    if ((effect && effect->requiresCompositingForAnimation()) ||
-        (transform && transform->requiresCompositingForAnimation())) {
+    if (effect && effect->requiresCompositingForAnimation()) {
       return false;
     }
   }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
index 4a245c4..258912a 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
@@ -157,7 +157,7 @@
   FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest,
                            DoPaintWithEffectAnimationZeroOpacity);
   FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest,
-                           DoPaintWithTransformAnimationZeroOpacity);
+                           DoNotPaintWithTransformAnimationZeroOpacity);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
index 69ea1ba..23abda1 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
@@ -1083,7 +1083,7 @@
       PaintLayerPainter(*targetLayer).paintedOutputInvisible(paintingInfo));
 }
 
-TEST_P(PaintLayerPainterTest, DoPaintWithTransformAnimationZeroOpacity) {
+TEST_P(PaintLayerPainterTest, DoNotPaintWithTransformAnimationZeroOpacity) {
   setBodyInnerHTML(
       "<style> "
       "div#target { "
@@ -1101,8 +1101,13 @@
       toLayoutBox(getLayoutObjectByElementId("target"))->layer();
   PaintLayerPaintingInfo paintingInfo(nullptr, LayoutRect(),
                                       GlobalPaintNormalPhase, LayoutSize());
-  EXPECT_FALSE(
-      PaintLayerPainter(*targetLayer).paintedOutputInvisible(paintingInfo));
+  if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
+    EXPECT_TRUE(
+        PaintLayerPainter(*targetLayer).paintedOutputInvisible(paintingInfo));
+  } else {
+    EXPECT_FALSE(
+        PaintLayerPainter(*targetLayer).paintedOutputInvisible(paintingInfo));
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
index d5b41edc..2f55f10b 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
@@ -649,6 +649,94 @@
                                        document().layoutView()->layer()));
 }
 
+TEST_P(PaintLayerTest, FloatLayerUnderFloatUnderInlineLayer) {
+  setBodyInnerHTML(
+      "<style>body {margin: 0}</style>"
+      "<span id='span' style='position: relative; top: 100px; left: 100px'>"
+      "  <div style='float: left; margin: 33px'>"
+      "    <div id='floating'"
+      "        style='float: left; position: relative; top: 50px; left: 50px'>"
+      "    </div>"
+      "  </div>"
+      "</span>");
+
+  PaintLayer* floating =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("floating"))->layer();
+  PaintLayer* span =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("span"))->layer();
+
+  EXPECT_EQ(span, floating->parent());
+  EXPECT_EQ(span->parent(), floating->containingLayer());
+
+  EXPECT_EQ(LayoutPoint(83, 83), floating->location());
+  EXPECT_EQ(LayoutPoint(100, 100), span->location());
+  EXPECT_EQ(LayoutPoint(-17, -17), floating->visualOffsetFromAncestor(span));
+  EXPECT_EQ(LayoutPoint(83, 83), floating->visualOffsetFromAncestor(
+                                     document().layoutView()->layer()));
+}
+
+TEST_P(PaintLayerTest, FloatLayerUnderFloatLayerUnderInlineLayer) {
+  setBodyInnerHTML(
+      "<style>body {margin: 0}</style>"
+      "<span id='span' style='position: relative; top: 100px; left: 100px'>"
+      "  <div id='floatingParent'"
+      "      style='float: left; position: relative; margin: 33px'>"
+      "    <div id='floating'"
+      "        style='float: left; position: relative; top: 50px; left: 50px'>"
+      "    </div>"
+      "  </div>"
+      "</span>");
+
+  PaintLayer* floating =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("floating"))->layer();
+  PaintLayer* floatingParent =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("floatingParent"))
+          ->layer();
+  PaintLayer* span =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("span"))->layer();
+
+  EXPECT_EQ(floatingParent, floating->parent());
+  EXPECT_EQ(floatingParent, floating->containingLayer());
+  EXPECT_EQ(span, floatingParent->parent());
+  EXPECT_EQ(span->parent(), floatingParent->containingLayer());
+
+  EXPECT_EQ(LayoutPoint(50, 50), floating->location());
+  EXPECT_EQ(LayoutPoint(33, 33), floatingParent->location());
+  EXPECT_EQ(LayoutPoint(100, 100), span->location());
+  EXPECT_EQ(LayoutPoint(-17, -17), floating->visualOffsetFromAncestor(span));
+  EXPECT_EQ(LayoutPoint(-67, -67),
+            floatingParent->visualOffsetFromAncestor(span));
+  EXPECT_EQ(LayoutPoint(83, 83), floating->visualOffsetFromAncestor(
+                                     document().layoutView()->layer()));
+}
+
+TEST_P(PaintLayerTest, LayerUnderFloatUnderInlineLayer) {
+  setBodyInnerHTML(
+      "<style>body {margin: 0}</style>"
+      "<span id='span' style='position: relative; top: 100px; left: 100px'>"
+      "  <div style='float: left; margin: 33px'>"
+      "    <div>"
+      "      <div id='child' style='position: relative; top: 50px; left: 50px'>"
+      "      </div>"
+      "    </div>"
+      "  </div>"
+      "</span>");
+
+  PaintLayer* child =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("child"))->layer();
+  PaintLayer* span =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("span"))->layer();
+
+  EXPECT_EQ(span, child->parent());
+  EXPECT_EQ(span->parent(), child->containingLayer());
+
+  EXPECT_EQ(LayoutPoint(83, 83), child->location());
+  EXPECT_EQ(LayoutPoint(100, 100), span->location());
+  EXPECT_EQ(LayoutPoint(-17, -17), child->visualOffsetFromAncestor(span));
+  EXPECT_EQ(LayoutPoint(83, 83),
+            child->visualOffsetFromAncestor(document().layoutView()->layer()));
+}
+
 TEST_P(PaintLayerTest, CompositingContainerFloatingIframe) {
   enableCompositing();
   setBodyInnerHTML(
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index 849a8bec..c0de0209 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -406,6 +406,7 @@
   "front_end/quick_open/module.json",
   "front_end/resources/ApplicationCacheModel.js",
   "front_end/resources/ApplicationCacheItemsView.js",
+  "front_end/resources/ApplicationPanelSidebar.js",
   "front_end/resources/appManifestView.css",
   "front_end/resources/AppManifestView.js",
   "front_end/resources/clearStorageView.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/audits/AuditExtensionCategory.js b/third_party/WebKit/Source/devtools/front_end/audits/AuditExtensionCategory.js
index e6e54d2..e3c8e54 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits/AuditExtensionCategory.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits/AuditExtensionCategory.js
@@ -209,22 +209,27 @@
    */
   node: function(expression, evaluateOptions) {
     var parentElement = createElement('div');
-    this.evaluate(expression, evaluateOptions, onEvaluate);
+    this.evaluate(expression, evaluateOptions, async remoteObject => {
+      await append(remoteObject);
+      remoteObject.release();
+    });
+    return parentElement;
 
     /**
      * @param {!SDK.RemoteObject} remoteObject
      */
-    function onEvaluate(remoteObject) {
-      Common.Renderer.renderPromise(remoteObject).then(appendRenderer).then(remoteObject.release.bind(remoteObject));
-
-      /**
-       * @param {!Element} element
-       */
-      function appendRenderer(element) {
-        parentElement.appendChild(element);
-      }
+    async function append(remoteObject) {
+      if (!remoteObject.isNode())
+        return;
+      var domModel = SDK.DOMModel.fromTarget(remoteObject.runtimeModel().target());
+      if (!domModel)
+        return;
+      var node = await domModel.pushObjectAsNodeToFrontend(remoteObject);
+      if (!node)
+        return;
+      var element = await Common.Renderer.renderPromise(/** @type {!SDK.DOMNode} */ (node));
+      parentElement.appendChild(element);
     }
-    return parentElement;
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
index 9d89be4e..233338b4 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -483,10 +483,12 @@
       case 'promise':
       case 'proxy':
       case 'set':
+      case 'weakmap':
+      case 'weakset':
         element = this._formatParameterAsObject(output, includePreview);
         break;
       case 'node':
-        element = this._formatParameterAsNode(output);
+        element = output.isNode() ? this._formatParameterAsNode(output) : this._formatParameterAsObject(output, false);
         break;
       case 'string':
         element = this._formatParameterAsString(output);
@@ -598,29 +600,27 @@
   }
 
   /**
-   * @param {!SDK.RemoteObject} object
+   * @param {!SDK.RemoteObject} remoteObject
    * @return {!Element}
    */
-  _formatParameterAsNode(object) {
+  _formatParameterAsNode(remoteObject) {
     var result = createElement('span');
-    Common.Renderer.renderPromise(object).then(appendRenderer.bind(this), failedToRender.bind(this));
+
+    var domModel = SDK.DOMModel.fromTarget(remoteObject.runtimeModel().target());
+    if (!domModel)
+      return result;
+    domModel.pushObjectAsNodeToFrontend(remoteObject).then(node => {
+      if (!node) {
+        result.appendChild(this._formatParameterAsObject(remoteObject, false));
+        return;
+      }
+      Common.Renderer.renderPromise(node).then(rendererElement => {
+        result.appendChild(rendererElement);
+        this._formattedParameterAsNodeForTest();
+      });
+    });
+
     return result;
-
-    /**
-     * @param {!Element} rendererElement
-     * @this {Console.ConsoleViewMessage}
-     */
-    function appendRenderer(rendererElement) {
-      result.appendChild(rendererElement);
-      this._formattedParameterAsNodeForTest();
-    }
-
-    /**
-     * @this {Console.ConsoleViewMessage}
-     */
-    function failedToRender() {
-      result.appendChild(this._formatParameterAsObject(object, false));
-    }
   }
 
   _formattedParameterAsNodeForTest() {
diff --git a/third_party/WebKit/Source/devtools/front_end/cookie_table/CookiesTable.js b/third_party/WebKit/Source/devtools/front_end/cookie_table/CookiesTable.js
index 4bb51710..adf3439 100644
--- a/third_party/WebKit/Source/devtools/front_end/cookie_table/CookiesTable.js
+++ b/third_party/WebKit/Source/devtools/front_end/cookie_table/CookiesTable.js
@@ -161,10 +161,13 @@
 
   /**
    * @param {{current: ?SDK.Cookie, neighbor: ?SDK.Cookie}} selectionCookies
-   * @param {!Array<!SDK.Cookie>} cookies
+   * @param {?Array<!SDK.Cookie>} cookies
    * @return {?SDK.Cookie}
    */
   _findSelectedCookie(selectionCookies, cookies) {
+    if (!cookies)
+      return null;
+
     var current = selectionCookies.current;
     var foundCurrent = cookies.find(cookie => this._isSameCookie(cookie, current));
     if (foundCurrent)
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
index fb51c77..619cf46 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
@@ -41,6 +41,10 @@
 
     if (!isEnterKey(event))
       return;
+    if (this._prompt.acceptAutoComplete()) {
+      event.consume(true);
+      return;
+    }
     var node = UI.context.flavor(SDK.DOMNode);
     if (!node)
       return;
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
index b095335..c5acf146 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -1017,7 +1017,7 @@
       } else if (node instanceof SDK.RemoteObject) {
         var domModel = SDK.DOMModel.fromTarget(/** @type {!SDK.RemoteObject} */ (node).runtimeModel().target());
         if (domModel)
-          domModel.pushObjectAsNodeToFrontend(node, onNodeResolved);
+          domModel.pushObjectAsNodeToFrontend(node).then(onNodeResolved);
         else
           reject(new Error('Could not resolve a node to reveal.'));
       } else {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
index 3fe0a40..7a3040d 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -1583,19 +1583,13 @@
      * @param {function(!Error)} reject
      */
     function renderPromise(resolve, reject) {
-      if (object instanceof SDK.DOMNode) {
+      if (object instanceof SDK.DOMNode)
         onNodeResolved(/** @type {!SDK.DOMNode} */ (object));
-      } else if (object instanceof SDK.DeferredDOMNode) {
+      else if (object instanceof SDK.DeferredDOMNode)
         (/** @type {!SDK.DeferredDOMNode} */ (object)).resolve(onNodeResolved);
-      } else if (object instanceof SDK.RemoteObject) {
-        var domModel = SDK.DOMModel.fromTarget((/** @type {!SDK.RemoteObject} */ (object)).runtimeModel().target());
-        if (domModel)
-          domModel.pushObjectAsNodeToFrontend(object, onNodeResolved);
-        else
-          reject(new Error('No dom model for given JS object target found.'));
-      } else {
+      else
         reject(new Error('Can\'t reveal not a node.'));
-      }
+
 
       /**
        * @param {?SDK.DOMNode} node
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/module.json b/third_party/WebKit/Source/devtools/front_end/elements/module.json
index 4993b21..11b7c4d 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/elements/module.json
@@ -21,7 +21,7 @@
             "type": "@Common.Renderer",
             "contextTypes": [
                 "SDK.DOMNode",
-                "SDK.RemoteObject"
+                "SDK.DeferredDOMNode"
             ],
             "className": "Elements.ElementsTreeOutline.Renderer"
         },
diff --git a/third_party/WebKit/Source/devtools/front_end/host/Platform.js b/third_party/WebKit/Source/devtools/front_end/host/Platform.js
index 387d989..1317d42 100644
--- a/third_party/WebKit/Source/devtools/front_end/host/Platform.js
+++ b/third_party/WebKit/Source/devtools/front_end/host/Platform.js
@@ -71,7 +71,7 @@
     return Host._fontFamily;
   switch (Host.platform()) {
     case 'linux':
-      Host._fontFamily = 'Ubuntu, Arial, sans-serif';
+      Host._fontFamily = 'Roboto, Ubuntu, Arial, sans-serif';
       break;
     case 'mac':
       Host._fontFamily = '\'Lucida Grande\', sans-serif';
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js
new file mode 100644
index 0000000..4836c57
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js
@@ -0,0 +1,1654 @@
+/*
+ * Copyright (C) 2007, 2008, 2010 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ * Copyright (C) 2013 Samsung Electronics. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * @implements {SDK.TargetManager.Observer}
+ * @unrestricted
+ */
+Resources.ApplicationPanelSidebar = class extends UI.VBox {
+  /**
+   * @param {!Resources.ResourcesPanel} panel
+   */
+  constructor(panel) {
+    super();
+
+    this._panel = panel;
+
+    this._sidebarTree = new UI.TreeOutlineInShadow();
+    this._sidebarTree.element.classList.add('resources-sidebar');
+    this._sidebarTree.registerRequiredCSS('resources/resourcesSidebar.css');
+    this._sidebarTree.element.classList.add('filter-all');
+    this.contentElement.appendChild(this._sidebarTree.element);
+
+    this._applicationTreeElement = this._addSidebarSection(Common.UIString('Application'));
+    this._manifestTreeElement = new Resources.AppManifestTreeElement(panel);
+    this._applicationTreeElement.appendChild(this._manifestTreeElement);
+    this.serviceWorkersTreeElement = new Resources.ServiceWorkersTreeElement(panel);
+    this._applicationTreeElement.appendChild(this.serviceWorkersTreeElement);
+    var clearStorageTreeElement = new Resources.ClearStorageTreeElement(panel);
+    this._applicationTreeElement.appendChild(clearStorageTreeElement);
+
+    var storageTreeElement = this._addSidebarSection(Common.UIString('Storage'));
+    this.localStorageListTreeElement =
+        new Resources.StorageCategoryTreeElement(panel, Common.UIString('Local Storage'), 'LocalStorage');
+    var localStorageIcon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
+    this.localStorageListTreeElement.setLeadingIcons([localStorageIcon]);
+
+    storageTreeElement.appendChild(this.localStorageListTreeElement);
+    this.sessionStorageListTreeElement =
+        new Resources.StorageCategoryTreeElement(panel, Common.UIString('Session Storage'), 'SessionStorage');
+    var sessionStorageIcon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
+    this.sessionStorageListTreeElement.setLeadingIcons([sessionStorageIcon]);
+
+    storageTreeElement.appendChild(this.sessionStorageListTreeElement);
+    this.indexedDBListTreeElement = new Resources.IndexedDBTreeElement(panel);
+    storageTreeElement.appendChild(this.indexedDBListTreeElement);
+    this.databasesListTreeElement =
+        new Resources.StorageCategoryTreeElement(panel, Common.UIString('Web SQL'), 'Databases');
+    var databaseIcon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
+    this.databasesListTreeElement.setLeadingIcons([databaseIcon]);
+
+    storageTreeElement.appendChild(this.databasesListTreeElement);
+    this.cookieListTreeElement = new Resources.StorageCategoryTreeElement(panel, Common.UIString('Cookies'), 'Cookies');
+    var cookieIcon = UI.Icon.create('mediumicon-cookie', 'resource-tree-item');
+    this.cookieListTreeElement.setLeadingIcons([cookieIcon]);
+    storageTreeElement.appendChild(this.cookieListTreeElement);
+
+    var cacheTreeElement = this._addSidebarSection(Common.UIString('Cache'));
+    this.cacheStorageListTreeElement = new Resources.ServiceWorkerCacheTreeElement(panel);
+    cacheTreeElement.appendChild(this.cacheStorageListTreeElement);
+    this.applicationCacheListTreeElement =
+        new Resources.StorageCategoryTreeElement(panel, Common.UIString('Application Cache'), 'ApplicationCache');
+    var applicationCacheIcon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
+    this.applicationCacheListTreeElement.setLeadingIcons([applicationCacheIcon]);
+
+    cacheTreeElement.appendChild(this.applicationCacheListTreeElement);
+
+    this._resourcesSection = new Resources.ResourcesSection(panel, this._addSidebarSection(Common.UIString('Frames')));
+
+    /** @type {!Map.<!Resources.Database, !Object.<string, !Resources.DatabaseTableView>>} */
+    this._databaseTableViews = new Map();
+    /** @type {!Map.<!Resources.Database, !Resources.DatabaseQueryView>} */
+    this._databaseQueryViews = new Map();
+    /** @type {!Map.<!Resources.Database, !Resources.DatabaseTreeElement>} */
+    this._databaseTreeElements = new Map();
+    /** @type {!Map.<!Resources.DOMStorage, !Resources.DOMStorageTreeElement>} */
+    this._domStorageTreeElements = new Map();
+    /** @type {!Object.<string, boolean>} */
+    this._domains = {};
+
+    this._sidebarTree.contentElement.addEventListener('mousemove', this._onmousemove.bind(this), false);
+    this._sidebarTree.contentElement.addEventListener('mouseleave', this._onmouseleave.bind(this), false);
+
+    SDK.targetManager.observeTargets(this);
+    SDK.targetManager.addModelListener(
+        SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.FrameNavigated, this._frameNavigated, this);
+  }
+
+  /**
+   * @param {string} title
+   * @return {!UI.TreeElement}
+   */
+  _addSidebarSection(title) {
+    var treeElement = new UI.TreeElement(title, true);
+    treeElement.listItemElement.classList.add('storage-group-list-item');
+    treeElement.setCollapsible(false);
+    treeElement.selectable = false;
+    this._sidebarTree.appendChild(treeElement);
+    return treeElement;
+  }
+
+  /**
+   * @override
+   * @param {!SDK.Target} target
+   */
+  targetAdded(target) {
+    if (this._target)
+      return;
+    this._target = target;
+    this._databaseModel = Resources.DatabaseModel.fromTarget(target);
+
+    this._databaseModel.on(Resources.DatabaseModel.DatabaseAddedEvent, this._databaseAdded, this);
+    this._databaseModel.on(Resources.DatabaseModel.DatabasesRemovedEvent, this._resetWebSQL, this);
+
+    var resourceTreeModel = SDK.ResourceTreeModel.fromTarget(target);
+    if (!resourceTreeModel)
+      return;
+
+    if (resourceTreeModel.cachedResourcesLoaded())
+      this._initialize();
+
+    resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this._initialize, this);
+    resourceTreeModel.addEventListener(
+        SDK.ResourceTreeModel.Events.WillLoadCachedResources, this._resetWithFrames, this);
+  }
+
+  /**
+   * @override
+   * @param {!SDK.Target} target
+   */
+  targetRemoved(target) {
+    if (target !== this._target)
+      return;
+    delete this._target;
+
+    var resourceTreeModel = SDK.ResourceTreeModel.fromTarget(target);
+    if (resourceTreeModel) {
+      resourceTreeModel.removeEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this._initialize, this);
+      resourceTreeModel.removeEventListener(
+          SDK.ResourceTreeModel.Events.WillLoadCachedResources, this._resetWithFrames, this);
+    }
+    this._databaseModel.off(Resources.DatabaseModel.DatabaseAddedEvent, this._databaseAdded, this);
+    this._databaseModel.off(Resources.DatabaseModel.DatabasesRemovedEvent, this._resetWebSQL, this);
+
+    this._resetWithFrames();
+  }
+
+  /**
+   * @override
+   */
+  focus() {
+    this._sidebarTree.focus();
+  }
+
+  _initialize() {
+    for (var frame of SDK.ResourceTreeModel.frames())
+      this._addCookieDocument(frame);
+    this._databaseModel.enable();
+
+    var indexedDBModel = Resources.IndexedDBModel.fromTarget(this._target);
+    if (indexedDBModel)
+      indexedDBModel.enable();
+
+    var cacheStorageModel = SDK.ServiceWorkerCacheModel.fromTarget(this._target);
+    if (cacheStorageModel)
+      cacheStorageModel.enable();
+    var resourceTreeModel = SDK.ResourceTreeModel.fromTarget(this._target);
+    if (resourceTreeModel)
+      this._populateApplicationCacheTree(resourceTreeModel);
+    var domStorageModel = Resources.DOMStorageModel.fromTarget(this._target);
+    if (domStorageModel)
+      this._populateDOMStorageTree(domStorageModel);
+    this.indexedDBListTreeElement._initialize();
+    var serviceWorkerCacheModel = SDK.ServiceWorkerCacheModel.fromTarget(this._target);
+    this.cacheStorageListTreeElement._initialize(serviceWorkerCacheModel);
+    this._initDefaultSelection();
+  }
+
+  _initDefaultSelection() {
+    var itemURL = this._panel.lastSelectedItemURL();
+    if (itemURL) {
+      var rootElement = this._sidebarTree.rootElement();
+      for (var treeElement = rootElement.firstChild(); treeElement;
+           treeElement = treeElement.traverseNextTreeElement(false, rootElement, true)) {
+        if (treeElement.itemURL === itemURL) {
+          treeElement.revealAndSelect(true);
+          return;
+        }
+      }
+    }
+    this._manifestTreeElement.select();
+  }
+
+  _resetWithFrames() {
+    this._resourcesSection.reset();
+    this._reset();
+  }
+
+  _resetWebSQL() {
+    var queryViews = this._databaseQueryViews.valuesArray();
+    for (var i = 0; i < queryViews.length; ++i) {
+      queryViews[i].removeEventListener(
+          Resources.DatabaseQueryView.Events.SchemaUpdated, this._updateDatabaseTables, this);
+    }
+    this._databaseTableViews.clear();
+    this._databaseQueryViews.clear();
+    this._databaseTreeElements.clear();
+    this.databasesListTreeElement.removeChildren();
+    this.databasesListTreeElement.setExpandable(false);
+  }
+
+  _resetDOMStorage() {
+    this._domStorageTreeElements.clear();
+    this.localStorageListTreeElement.removeChildren();
+    this.sessionStorageListTreeElement.removeChildren();
+  }
+
+  _resetCookies() {
+    this.cookieListTreeElement.removeChildren();
+  }
+
+  _resetCacheStorage() {
+    this.cacheStorageListTreeElement.removeChildren();
+    this.cacheStorageListTreeElement.setExpandable(false);
+  }
+
+  _resetAppCache() {
+    for (var frameId of Object.keys(this._applicationCacheFrameElements))
+      this._applicationCacheFrameManifestRemoved({data: frameId});
+    this.applicationCacheListTreeElement.setExpandable(false);
+  }
+
+  _reset() {
+    this._domains = {};
+    this._resetWebSQL();
+    this._resetDOMStorage();
+    this._resetCookies();
+    this._resetCacheStorage();
+    // No need to this._resetAppCache.
+
+    this._panel.resetView();
+
+    if (this._sidebarTree.selectedTreeElement)
+      this._sidebarTree.selectedTreeElement.deselect();
+  }
+
+  _frameNavigated(event) {
+    var frame = event.data;
+
+    if (!frame.parentFrame)
+      this._reset();
+
+    var applicationCacheFrameTreeElement = this._applicationCacheFrameElements[frame.id];
+    if (applicationCacheFrameTreeElement)
+      applicationCacheFrameTreeElement.frameNavigated(frame);
+    this._addCookieDocument(frame);
+  }
+
+  /**
+   * @param {!Resources.DatabaseModel.DatabaseAddedEvent} event
+   */
+  _databaseAdded(event) {
+    var databaseTreeElement = new Resources.DatabaseTreeElement(this, event.database);
+    this._databaseTreeElements.set(event.database, databaseTreeElement);
+    this.databasesListTreeElement.appendChild(databaseTreeElement);
+  }
+
+  /**
+   * @param {!SDK.ResourceTreeFrame} frame
+   */
+  _addCookieDocument(frame) {
+    var parsedURL = frame.url.asParsedURL();
+    if (!parsedURL || (parsedURL.scheme !== 'http' && parsedURL.scheme !== 'https' && parsedURL.scheme !== 'file'))
+      return;
+
+    var domain = parsedURL.securityOrigin();
+    if (!this._domains[domain]) {
+      this._domains[domain] = true;
+      var cookieDomainTreeElement = new Resources.CookieTreeElement(this._panel, frame, domain);
+      this.cookieListTreeElement.appendChild(cookieDomainTreeElement);
+    }
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _domStorageAdded(event) {
+    var domStorage = /** @type {!Resources.DOMStorage} */ (event.data);
+    this._addDOMStorage(domStorage);
+  }
+
+  /**
+   * @param {!Resources.DOMStorage} domStorage
+   */
+  _addDOMStorage(domStorage) {
+    console.assert(!this._domStorageTreeElements.get(domStorage));
+
+    var domStorageTreeElement = new Resources.DOMStorageTreeElement(this._panel, domStorage);
+    this._domStorageTreeElements.set(domStorage, domStorageTreeElement);
+    if (domStorage.isLocalStorage)
+      this.localStorageListTreeElement.appendChild(domStorageTreeElement);
+    else
+      this.sessionStorageListTreeElement.appendChild(domStorageTreeElement);
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _domStorageRemoved(event) {
+    var domStorage = /** @type {!Resources.DOMStorage} */ (event.data);
+    this._removeDOMStorage(domStorage);
+  }
+
+  /**
+   * @param {!Resources.DOMStorage} domStorage
+   */
+  _removeDOMStorage(domStorage) {
+    var treeElement = this._domStorageTreeElements.get(domStorage);
+    if (!treeElement)
+      return;
+    var wasSelected = treeElement.selected;
+    var parentListTreeElement = treeElement.parent;
+    parentListTreeElement.removeChild(treeElement);
+    if (wasSelected)
+      parentListTreeElement.select();
+    this._domStorageTreeElements.remove(domStorage);
+  }
+
+  /**
+   * @param {!Resources.Database} database
+   */
+  selectDatabase(database) {
+    if (database) {
+      this._showDatabase(database);
+      this._databaseTreeElements.get(database).select();
+    }
+  }
+
+  /**
+   * @param {!SDK.Resource} resource
+   * @param {number=} line
+   * @param {number=} column
+   * @return {boolean}
+   */
+  showResource(resource, line, column) {
+    var resourceTreeElement = Resources.FrameResourceTreeElement.forResource(resource);
+    if (resourceTreeElement)
+      resourceTreeElement.revealAndSelect(true);
+
+    if (typeof line === 'number') {
+      var resourceSourceFrame = this._resourceSourceFrameViewForResource(resource);
+      if (resourceSourceFrame)
+        resourceSourceFrame.revealPosition(line, column, true);
+    }
+    return true;
+  }
+
+  /**
+   * @param {!SDK.Resource} resource
+   * @return {?SourceFrame.ResourceSourceFrame}
+   */
+  _resourceSourceFrameViewForResource(resource) {
+    var resourceView = Resources.FrameResourceTreeElement.resourceViewForResource(resource);
+    if (resourceView && resourceView instanceof SourceFrame.ResourceSourceFrame)
+      return /** @type {!SourceFrame.ResourceSourceFrame} */ (resourceView);
+    return null;
+  }
+
+  /**
+   * @param {!Resources.Database} database
+   * @param {string=} tableName
+   */
+  _showDatabase(database, tableName) {
+    if (!database)
+      return;
+
+    var view;
+    if (tableName) {
+      var tableViews = this._databaseTableViews.get(database);
+      if (!tableViews) {
+        tableViews = /** @type {!Object.<string, !Resources.DatabaseTableView>} */ ({});
+        this._databaseTableViews.set(database, tableViews);
+      }
+      view = tableViews[tableName];
+      if (!view) {
+        view = new Resources.DatabaseTableView(database, tableName);
+        tableViews[tableName] = view;
+      }
+    } else {
+      view = this._databaseQueryViews.get(database);
+      if (!view) {
+        view = new Resources.DatabaseQueryView(database);
+        this._databaseQueryViews.set(database, view);
+        view.addEventListener(Resources.DatabaseQueryView.Events.SchemaUpdated, this._updateDatabaseTables, this);
+      }
+    }
+
+    this._innerShowView(view);
+  }
+
+  _showApplicationCache(frameId) {
+    if (!this._applicationCacheViews[frameId]) {
+      this._applicationCacheViews[frameId] =
+          new Resources.ApplicationCacheItemsView(this._applicationCacheModel, frameId);
+    }
+
+    this._innerShowView(this._applicationCacheViews[frameId]);
+  }
+
+  /**
+   *  @param {!UI.Widget} view
+   */
+  showFileSystem(view) {
+    this._innerShowView(view);
+  }
+
+  _innerShowView(view) {
+    this._panel.showView(view);
+  }
+
+  _updateDatabaseTables(event) {
+    var database = event.data;
+
+    if (!database)
+      return;
+
+    var databasesTreeElement = this._databaseTreeElements.get(database);
+    if (!databasesTreeElement)
+      return;
+
+    databasesTreeElement.invalidateChildren();
+    var tableViews = this._databaseTableViews.get(database);
+
+    if (!tableViews)
+      return;
+
+    var tableNamesHash = {};
+    var panel = this._panel;
+    function tableNamesCallback(tableNames) {
+      var tableNamesLength = tableNames.length;
+      for (var i = 0; i < tableNamesLength; ++i)
+        tableNamesHash[tableNames[i]] = true;
+
+      for (var tableName in tableViews) {
+        if (!(tableName in tableNamesHash)) {
+          if (panel.visibleView === tableViews[tableName])
+            panel.showView(null);
+          delete tableViews[tableName];
+        }
+      }
+    }
+    database.getTableNames(tableNamesCallback);
+  }
+
+  /**
+   * @param {!Resources.DOMStorageModel} domStorageModel
+   */
+  _populateDOMStorageTree(domStorageModel) {
+    domStorageModel.enable();
+    domStorageModel.storages().forEach(this._addDOMStorage.bind(this));
+    domStorageModel.addEventListener(Resources.DOMStorageModel.Events.DOMStorageAdded, this._domStorageAdded, this);
+    domStorageModel.addEventListener(Resources.DOMStorageModel.Events.DOMStorageRemoved, this._domStorageRemoved, this);
+  }
+
+  /**
+   * @param {!SDK.ResourceTreeModel} resourceTreeModel
+   */
+  _populateApplicationCacheTree(resourceTreeModel) {
+    this._applicationCacheModel = Resources.ApplicationCacheModel.fromTarget(this._target);
+
+    this._applicationCacheViews = {};
+    this._applicationCacheFrameElements = {};
+    this._applicationCacheManifestElements = {};
+
+    this._applicationCacheModel.addEventListener(
+        Resources.ApplicationCacheModel.Events.FrameManifestAdded, this._applicationCacheFrameManifestAdded, this);
+    this._applicationCacheModel.addEventListener(
+        Resources.ApplicationCacheModel.Events.FrameManifestRemoved, this._applicationCacheFrameManifestRemoved, this);
+    this._applicationCacheModel.addEventListener(
+        Resources.ApplicationCacheModel.Events.FrameManifestsReset, this._resetAppCache, this);
+
+    this._applicationCacheModel.addEventListener(
+        Resources.ApplicationCacheModel.Events.FrameManifestStatusUpdated,
+        this._applicationCacheFrameManifestStatusChanged, this);
+    this._applicationCacheModel.addEventListener(
+        Resources.ApplicationCacheModel.Events.NetworkStateChanged, this._applicationCacheNetworkStateChanged, this);
+  }
+
+  _applicationCacheFrameManifestAdded(event) {
+    var frameId = event.data;
+    var manifestURL = this._applicationCacheModel.frameManifestURL(frameId);
+
+    var manifestTreeElement = this._applicationCacheManifestElements[manifestURL];
+    if (!manifestTreeElement) {
+      manifestTreeElement = new Resources.ApplicationCacheManifestTreeElement(this._panel, manifestURL);
+      this.applicationCacheListTreeElement.appendChild(manifestTreeElement);
+      this._applicationCacheManifestElements[manifestURL] = manifestTreeElement;
+    }
+
+    var model = SDK.ResourceTreeModel.fromTarget(this._target);
+    var frameTreeElement = new Resources.ApplicationCacheFrameTreeElement(this, model.frameForId(frameId), manifestURL);
+    manifestTreeElement.appendChild(frameTreeElement);
+    manifestTreeElement.expand();
+    this._applicationCacheFrameElements[frameId] = frameTreeElement;
+  }
+
+  _applicationCacheFrameManifestRemoved(event) {
+    var frameId = event.data;
+    var frameTreeElement = this._applicationCacheFrameElements[frameId];
+    if (!frameTreeElement)
+      return;
+
+    var manifestURL = frameTreeElement.manifestURL;
+    delete this._applicationCacheFrameElements[frameId];
+    delete this._applicationCacheViews[frameId];
+    frameTreeElement.parent.removeChild(frameTreeElement);
+
+    var manifestTreeElement = this._applicationCacheManifestElements[manifestURL];
+    if (manifestTreeElement.childCount())
+      return;
+
+    delete this._applicationCacheManifestElements[manifestURL];
+    manifestTreeElement.parent.removeChild(manifestTreeElement);
+  }
+
+  _applicationCacheFrameManifestStatusChanged(event) {
+    var frameId = event.data;
+    var status = this._applicationCacheModel.frameManifestStatus(frameId);
+
+    if (this._applicationCacheViews[frameId])
+      this._applicationCacheViews[frameId].updateStatus(status);
+  }
+
+  _applicationCacheNetworkStateChanged(event) {
+    var isNowOnline = event.data;
+
+    for (var manifestURL in this._applicationCacheViews)
+      this._applicationCacheViews[manifestURL].updateNetworkState(isNowOnline);
+  }
+
+  showView(view) {
+    if (view)
+      this.showResource(view.resource);
+  }
+
+  _onmousemove(event) {
+    var nodeUnderMouse = event.target;
+    if (!nodeUnderMouse)
+      return;
+
+    var listNode = nodeUnderMouse.enclosingNodeOrSelfWithNodeName('li');
+    if (!listNode)
+      return;
+
+    var element = listNode.treeElement;
+    if (this._previousHoveredElement === element)
+      return;
+
+    if (this._previousHoveredElement) {
+      this._previousHoveredElement.hovered = false;
+      delete this._previousHoveredElement;
+    }
+
+    if (element instanceof Resources.FrameTreeElement) {
+      this._previousHoveredElement = element;
+      element.hovered = true;
+    }
+  }
+
+  _onmouseleave(event) {
+    if (this._previousHoveredElement) {
+      this._previousHoveredElement.hovered = false;
+      delete this._previousHoveredElement;
+    }
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.BaseStorageTreeElement = class extends UI.TreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   * @param {string} title
+   * @param {boolean} expandable
+   */
+  constructor(storagePanel, title, expandable) {
+    super(title, expandable);
+    this._storagePanel = storagePanel;
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    if (!selectedByUser)
+      return false;
+    var itemURL = this.itemURL;
+    if (itemURL)
+      this._storagePanel.setLastSelectedItemURL(itemURL);
+    return false;
+  }
+
+  /**
+   * @protected
+   * @param {?UI.Widget} view
+   */
+  showView(view) {
+    this._storagePanel.showView(view);
+  }
+};
+
+Resources.StorageCategoryTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   * @param {string} categoryName
+   * @param {string} settingsKey
+   */
+  constructor(storagePanel, categoryName, settingsKey) {
+    super(storagePanel, categoryName, false);
+    this._expandedSetting =
+        Common.settings.createSetting('resources' + settingsKey + 'Expanded', settingsKey === 'Frames');
+    this._categoryName = categoryName;
+  }
+
+
+  get itemURL() {
+    return 'category://' + this._categoryName;
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    this._storagePanel.showCategoryView(this._categoryName);
+    return false;
+  }
+
+  /**
+   * @override
+   */
+  onattach() {
+    super.onattach();
+    if (this._expandedSetting.get())
+      this.expand();
+  }
+
+  /**
+   * @override
+   */
+  onexpand() {
+    this._expandedSetting.set(true);
+  }
+
+  /**
+   * @override
+   */
+  oncollapse() {
+    this._expandedSetting.set(false);
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.DatabaseTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ApplicationPanelSidebar} sidebar
+   * @param {!Resources.Database} database
+   */
+  constructor(sidebar, database) {
+    super(sidebar._panel, database.name, true);
+    this._sidebar = sidebar;
+    this._database = database;
+
+    var icon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  get itemURL() {
+    return 'database://' + encodeURI(this._database.name);
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    this._sidebar._showDatabase(this._database);
+    return false;
+  }
+
+  /**
+   * @override
+   */
+  onexpand() {
+    this._updateChildren();
+  }
+
+  _updateChildren() {
+    this.removeChildren();
+
+    /**
+     * @param {!Array.<string>} tableNames
+     * @this {Resources.DatabaseTreeElement}
+     */
+    function tableNamesCallback(tableNames) {
+      var tableNamesLength = tableNames.length;
+      for (var i = 0; i < tableNamesLength; ++i)
+        this.appendChild(new Resources.DatabaseTableTreeElement(this._storagePanel, this._database, tableNames[i]));
+    }
+    this._database.getTableNames(tableNamesCallback.bind(this));
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.DatabaseTableTreeElement = class extends Resources.BaseStorageTreeElement {
+  constructor(sidebar, database, tableName) {
+    super(sidebar._panel, tableName, false);
+    this._sidebar = sidebar;
+    this._database = database;
+    this._tableName = tableName;
+    var icon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  get itemURL() {
+    return 'database://' + encodeURI(this._database.name) + '/' + encodeURI(this._tableName);
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    this._sidebar._showDatabase(this._database, this._tableName);
+    return false;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.ServiceWorkerCacheTreeElement = class extends Resources.StorageCategoryTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   */
+  constructor(storagePanel) {
+    super(storagePanel, Common.UIString('Cache Storage'), 'CacheStorage');
+    var icon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+    /** @type {?SDK.ServiceWorkerCacheModel} */
+    this._swCacheModel = null;
+  }
+
+  /**
+   * @param {?SDK.ServiceWorkerCacheModel} model
+   */
+  _initialize(model) {
+    /** @type {!Array.<!Resources.SWCacheTreeElement>} */
+    this._swCacheTreeElements = [];
+    this._swCacheModel = model;
+    if (model) {
+      for (var cache of model.caches())
+        this._addCache(model, cache);
+    }
+    SDK.targetManager.addModelListener(
+        SDK.ServiceWorkerCacheModel, SDK.ServiceWorkerCacheModel.Events.CacheAdded, this._cacheAdded, this);
+    SDK.targetManager.addModelListener(
+        SDK.ServiceWorkerCacheModel, SDK.ServiceWorkerCacheModel.Events.CacheRemoved, this._cacheRemoved, this);
+  }
+
+  /**
+   * @override
+   */
+  onattach() {
+    super.onattach();
+    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
+  }
+
+  _handleContextMenuEvent(event) {
+    var contextMenu = new UI.ContextMenu(event);
+    contextMenu.appendItem(Common.UIString('Refresh Caches'), this._refreshCaches.bind(this));
+    contextMenu.show();
+  }
+
+  _refreshCaches() {
+    if (this._swCacheModel)
+      this._swCacheModel.refreshCacheNames();
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _cacheAdded(event) {
+    var cache = /** @type {!SDK.ServiceWorkerCacheModel.Cache} */ (event.data.cache);
+    var model = /** @type {!SDK.ServiceWorkerCacheModel} */ (event.data.model);
+    this._addCache(model, cache);
+  }
+
+  /**
+   * @param {!SDK.ServiceWorkerCacheModel} model
+   * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+   */
+  _addCache(model, cache) {
+    var swCacheTreeElement = new Resources.SWCacheTreeElement(this._storagePanel, model, cache);
+    this._swCacheTreeElements.push(swCacheTreeElement);
+    this.appendChild(swCacheTreeElement);
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _cacheRemoved(event) {
+    var cache = /** @type {!SDK.ServiceWorkerCacheModel.Cache} */ (event.data.cache);
+    var model = /** @type {!SDK.ServiceWorkerCacheModel} */ (event.data.model);
+
+    var swCacheTreeElement = this._cacheTreeElement(model, cache);
+    if (!swCacheTreeElement)
+      return;
+
+    swCacheTreeElement.clear();
+    this.removeChild(swCacheTreeElement);
+    this._swCacheTreeElements.remove(swCacheTreeElement);
+  }
+
+  /**
+   * @param {!SDK.ServiceWorkerCacheModel} model
+   * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+   * @return {?Resources.SWCacheTreeElement}
+   */
+  _cacheTreeElement(model, cache) {
+    var index = -1;
+    for (var i = 0; i < this._swCacheTreeElements.length; ++i) {
+      if (this._swCacheTreeElements[i]._cache.equals(cache) && this._swCacheTreeElements[i]._model === model) {
+        index = i;
+        break;
+      }
+    }
+    if (index !== -1)
+      return this._swCacheTreeElements[i];
+    return null;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.SWCacheTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   * @param {!SDK.ServiceWorkerCacheModel} model
+   * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+   */
+  constructor(storagePanel, model, cache) {
+    super(storagePanel, cache.cacheName + ' - ' + cache.securityOrigin, false);
+    this._model = model;
+    this._cache = cache;
+    var icon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  get itemURL() {
+    // I don't think this will work at all.
+    return 'cache://' + this._cache.cacheId;
+  }
+
+  /**
+   * @override
+   */
+  onattach() {
+    super.onattach();
+    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
+  }
+
+  _handleContextMenuEvent(event) {
+    var contextMenu = new UI.ContextMenu(event);
+    contextMenu.appendItem(Common.UIString('Delete'), this._clearCache.bind(this));
+    contextMenu.show();
+  }
+
+  _clearCache() {
+    this._model.deleteCache(this._cache);
+  }
+
+  /**
+   * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+   */
+  update(cache) {
+    this._cache = cache;
+    if (this._view)
+      this._view.update(cache);
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    if (!this._view)
+      this._view = new Resources.ServiceWorkerCacheView(this._model, this._cache);
+
+    this.showView(this._view);
+    return false;
+  }
+
+  clear() {
+    if (this._view)
+      this._view.clear();
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.ServiceWorkersTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   */
+  constructor(storagePanel) {
+    super(storagePanel, Common.UIString('Service Workers'), false);
+    var icon = UI.Icon.create('mediumicon-service-worker', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  /**
+   * @return {string}
+   */
+  get itemURL() {
+    return 'service-workers://';
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    if (!this._view)
+      this._view = new Resources.ServiceWorkersView();
+    this.showView(this._view);
+    return false;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.AppManifestTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   */
+  constructor(storagePanel) {
+    super(storagePanel, Common.UIString('Manifest'), false);
+    var icon = UI.Icon.create('mediumicon-manifest', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  /**
+   * @return {string}
+   */
+  get itemURL() {
+    return 'manifest://';
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    if (!this._view)
+      this._view = new Resources.AppManifestView();
+    this.showView(this._view);
+    return false;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.ClearStorageTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   */
+  constructor(storagePanel) {
+    super(storagePanel, Common.UIString('Clear storage'), false);
+    var icon = UI.Icon.create('mediumicon-clear-storage', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  /**
+   * @return {string}
+   */
+  get itemURL() {
+    return 'clear-storage://';
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    if (!this._view)
+      this._view = new Resources.ClearStorageView();
+    this.showView(this._view);
+    return false;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.IndexedDBTreeElement = class extends Resources.StorageCategoryTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   */
+  constructor(storagePanel) {
+    super(storagePanel, Common.UIString('IndexedDB'), 'IndexedDB');
+    var icon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  _initialize() {
+    SDK.targetManager.addModelListener(
+        Resources.IndexedDBModel, Resources.IndexedDBModel.Events.DatabaseAdded, this._indexedDBAdded, this);
+    SDK.targetManager.addModelListener(
+        Resources.IndexedDBModel, Resources.IndexedDBModel.Events.DatabaseRemoved, this._indexedDBRemoved, this);
+    SDK.targetManager.addModelListener(
+        Resources.IndexedDBModel, Resources.IndexedDBModel.Events.DatabaseLoaded, this._indexedDBLoaded, this);
+    /** @type {!Array.<!Resources.IDBDatabaseTreeElement>} */
+    this._idbDatabaseTreeElements = [];
+
+    var targets = SDK.targetManager.targets(SDK.Target.Capability.Browser);
+    for (var i = 0; i < targets.length; ++i) {
+      var indexedDBModel = Resources.IndexedDBModel.fromTarget(targets[i]);
+      var databases = indexedDBModel.databases();
+      for (var j = 0; j < databases.length; ++j)
+        this._addIndexedDB(indexedDBModel, databases[j]);
+    }
+  }
+
+  /**
+   * @override
+   */
+  onattach() {
+    super.onattach();
+    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
+  }
+
+  _handleContextMenuEvent(event) {
+    var contextMenu = new UI.ContextMenu(event);
+    contextMenu.appendItem(Common.UIString('Refresh IndexedDB'), this.refreshIndexedDB.bind(this));
+    contextMenu.show();
+  }
+
+  refreshIndexedDB() {
+    var targets = SDK.targetManager.targets(SDK.Target.Capability.Browser);
+    for (var i = 0; i < targets.length; ++i)
+      Resources.IndexedDBModel.fromTarget(targets[i]).refreshDatabaseNames();
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _indexedDBAdded(event) {
+    var databaseId = /** @type {!Resources.IndexedDBModel.DatabaseId} */ (event.data.databaseId);
+    var model = /** @type {!Resources.IndexedDBModel} */ (event.data.model);
+    this._addIndexedDB(model, databaseId);
+  }
+
+  /**
+   * @param {!Resources.IndexedDBModel} model
+   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
+   */
+  _addIndexedDB(model, databaseId) {
+    var idbDatabaseTreeElement = new Resources.IDBDatabaseTreeElement(this._storagePanel, model, databaseId);
+    this._idbDatabaseTreeElements.push(idbDatabaseTreeElement);
+    this.appendChild(idbDatabaseTreeElement);
+    model.refreshDatabase(databaseId);
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _indexedDBRemoved(event) {
+    var databaseId = /** @type {!Resources.IndexedDBModel.DatabaseId} */ (event.data.databaseId);
+    var model = /** @type {!Resources.IndexedDBModel} */ (event.data.model);
+
+    var idbDatabaseTreeElement = this._idbDatabaseTreeElement(model, databaseId);
+    if (!idbDatabaseTreeElement)
+      return;
+
+    idbDatabaseTreeElement.clear();
+    this.removeChild(idbDatabaseTreeElement);
+    this._idbDatabaseTreeElements.remove(idbDatabaseTreeElement);
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _indexedDBLoaded(event) {
+    var database = /** @type {!Resources.IndexedDBModel.Database} */ (event.data.database);
+    var model = /** @type {!Resources.IndexedDBModel} */ (event.data.model);
+
+    var idbDatabaseTreeElement = this._idbDatabaseTreeElement(model, database.databaseId);
+    if (!idbDatabaseTreeElement)
+      return;
+
+    idbDatabaseTreeElement.update(database);
+  }
+
+  /**
+   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
+   * @param {!Resources.IndexedDBModel} model
+   * @return {?Resources.IDBDatabaseTreeElement}
+   */
+  _idbDatabaseTreeElement(model, databaseId) {
+    var index = -1;
+    for (var i = 0; i < this._idbDatabaseTreeElements.length; ++i) {
+      if (this._idbDatabaseTreeElements[i]._databaseId.equals(databaseId) &&
+          this._idbDatabaseTreeElements[i]._model === model) {
+        index = i;
+        break;
+      }
+    }
+    if (index !== -1)
+      return this._idbDatabaseTreeElements[i];
+    return null;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.IDBDatabaseTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   * @param {!Resources.IndexedDBModel} model
+   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
+   */
+  constructor(storagePanel, model, databaseId) {
+    super(storagePanel, databaseId.name + ' - ' + databaseId.securityOrigin, false);
+    this._model = model;
+    this._databaseId = databaseId;
+    this._idbObjectStoreTreeElements = {};
+    var icon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  get itemURL() {
+    return 'indexedDB://' + this._databaseId.securityOrigin + '/' + this._databaseId.name;
+  }
+
+  /**
+   * @override
+   */
+  onattach() {
+    super.onattach();
+    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
+  }
+
+  _handleContextMenuEvent(event) {
+    var contextMenu = new UI.ContextMenu(event);
+    contextMenu.appendItem(Common.UIString('Refresh IndexedDB'), this._refreshIndexedDB.bind(this));
+    contextMenu.show();
+  }
+
+  _refreshIndexedDB() {
+    this._model.refreshDatabaseNames();
+  }
+
+  /**
+   * @param {!Resources.IndexedDBModel.Database} database
+   */
+  update(database) {
+    this._database = database;
+    var objectStoreNames = {};
+    for (var objectStoreName in this._database.objectStores) {
+      var objectStore = this._database.objectStores[objectStoreName];
+      objectStoreNames[objectStore.name] = true;
+      if (!this._idbObjectStoreTreeElements[objectStore.name]) {
+        var idbObjectStoreTreeElement =
+            new Resources.IDBObjectStoreTreeElement(this._storagePanel, this._model, this._databaseId, objectStore);
+        this._idbObjectStoreTreeElements[objectStore.name] = idbObjectStoreTreeElement;
+        this.appendChild(idbObjectStoreTreeElement);
+      }
+      this._idbObjectStoreTreeElements[objectStore.name].update(objectStore);
+    }
+    for (var objectStoreName in this._idbObjectStoreTreeElements) {
+      if (!objectStoreNames[objectStoreName])
+        this._objectStoreRemoved(objectStoreName);
+    }
+
+    if (this._view)
+      this._view.update(database);
+
+    this._updateTooltip();
+  }
+
+  _updateTooltip() {
+    this.tooltip = Common.UIString('Version') + ': ' + this._database.version;
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    if (!this._view)
+      this._view = new Resources.IDBDatabaseView(this._model, this._database);
+
+    this.showView(this._view);
+    return false;
+  }
+
+  /**
+   * @param {string} objectStoreName
+   */
+  _objectStoreRemoved(objectStoreName) {
+    var objectStoreTreeElement = this._idbObjectStoreTreeElements[objectStoreName];
+    objectStoreTreeElement.clear();
+    this.removeChild(objectStoreTreeElement);
+    delete this._idbObjectStoreTreeElements[objectStoreName];
+  }
+
+  clear() {
+    for (var objectStoreName in this._idbObjectStoreTreeElements)
+      this._objectStoreRemoved(objectStoreName);
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.IDBObjectStoreTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   * @param {!Resources.IndexedDBModel} model
+   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
+   * @param {!Resources.IndexedDBModel.ObjectStore} objectStore
+   */
+  constructor(storagePanel, model, databaseId, objectStore) {
+    super(storagePanel, objectStore.name, false);
+    this._model = model;
+    this._databaseId = databaseId;
+    this._idbIndexTreeElements = {};
+    var icon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  get itemURL() {
+    return 'indexedDB://' + this._databaseId.securityOrigin + '/' + this._databaseId.name + '/' +
+        this._objectStore.name;
+  }
+
+  /**
+   * @override
+   */
+  onattach() {
+    super.onattach();
+    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
+  }
+
+  _handleContextMenuEvent(event) {
+    var contextMenu = new UI.ContextMenu(event);
+    contextMenu.appendItem(Common.UIString('Clear'), this._clearObjectStore.bind(this));
+    contextMenu.show();
+  }
+
+  _clearObjectStore() {
+    /**
+     * @this {Resources.IDBObjectStoreTreeElement}
+     */
+    function callback() {
+      this.update(this._objectStore);
+    }
+    this._model.clearObjectStore(this._databaseId, this._objectStore.name, callback.bind(this));
+  }
+
+  /**
+   * @param {!Resources.IndexedDBModel.ObjectStore} objectStore
+   */
+  update(objectStore) {
+    this._objectStore = objectStore;
+
+    var indexNames = {};
+    for (var indexName in this._objectStore.indexes) {
+      var index = this._objectStore.indexes[indexName];
+      indexNames[index.name] = true;
+      if (!this._idbIndexTreeElements[index.name]) {
+        var idbIndexTreeElement = new Resources.IDBIndexTreeElement(
+            this._storagePanel, this._model, this._databaseId, this._objectStore, index);
+        this._idbIndexTreeElements[index.name] = idbIndexTreeElement;
+        this.appendChild(idbIndexTreeElement);
+      }
+      this._idbIndexTreeElements[index.name].update(index);
+    }
+    for (var indexName in this._idbIndexTreeElements) {
+      if (!indexNames[indexName])
+        this._indexRemoved(indexName);
+    }
+    for (var indexName in this._idbIndexTreeElements) {
+      if (!indexNames[indexName]) {
+        this.removeChild(this._idbIndexTreeElements[indexName]);
+        delete this._idbIndexTreeElements[indexName];
+      }
+    }
+
+    if (this.childCount())
+      this.expand();
+
+    if (this._view)
+      this._view.update(this._objectStore);
+
+    this._updateTooltip();
+  }
+
+  _updateTooltip() {
+    var keyPathString = this._objectStore.keyPathString;
+    var tooltipString = keyPathString !== null ? (Common.UIString('Key path: ') + keyPathString) : '';
+    if (this._objectStore.autoIncrement)
+      tooltipString += '\n' + Common.UIString('autoIncrement');
+    this.tooltip = tooltipString;
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    if (!this._view)
+      this._view = new Resources.IDBDataView(this._model, this._databaseId, this._objectStore, null);
+
+    this.showView(this._view);
+    return false;
+  }
+
+  /**
+   * @param {string} indexName
+   */
+  _indexRemoved(indexName) {
+    var indexTreeElement = this._idbIndexTreeElements[indexName];
+    indexTreeElement.clear();
+    this.removeChild(indexTreeElement);
+    delete this._idbIndexTreeElements[indexName];
+  }
+
+  clear() {
+    for (var indexName in this._idbIndexTreeElements)
+      this._indexRemoved(indexName);
+    if (this._view)
+      this._view.clear();
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.IDBIndexTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   * @param {!Resources.IndexedDBModel} model
+   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
+   * @param {!Resources.IndexedDBModel.ObjectStore} objectStore
+   * @param {!Resources.IndexedDBModel.Index} index
+   */
+  constructor(storagePanel, model, databaseId, objectStore, index) {
+    super(storagePanel, index.name, false);
+    this._model = model;
+    this._databaseId = databaseId;
+    this._objectStore = objectStore;
+    this._index = index;
+  }
+
+  get itemURL() {
+    return 'indexedDB://' + this._databaseId.securityOrigin + '/' + this._databaseId.name + '/' +
+        this._objectStore.name + '/' + this._index.name;
+  }
+
+  /**
+   * @param {!Resources.IndexedDBModel.Index} index
+   */
+  update(index) {
+    this._index = index;
+
+    if (this._view)
+      this._view.update(this._index);
+
+    this._updateTooltip();
+  }
+
+  _updateTooltip() {
+    var tooltipLines = [];
+    var keyPathString = this._index.keyPathString;
+    tooltipLines.push(Common.UIString('Key path: ') + keyPathString);
+    if (this._index.unique)
+      tooltipLines.push(Common.UIString('unique'));
+    if (this._index.multiEntry)
+      tooltipLines.push(Common.UIString('multiEntry'));
+    this.tooltip = tooltipLines.join('\n');
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    if (!this._view)
+      this._view = new Resources.IDBDataView(this._model, this._databaseId, this._objectStore, this._index);
+
+    this.showView(this._view);
+    return false;
+  }
+
+  clear() {
+    if (this._view)
+      this._view.clear();
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.DOMStorageTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   * @param {!Resources.DOMStorage} domStorage
+   */
+  constructor(storagePanel, domStorage) {
+    super(storagePanel, domStorage.securityOrigin ? domStorage.securityOrigin : Common.UIString('Local Files'), false);
+    this._domStorage = domStorage;
+    var icon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  get itemURL() {
+    return 'storage://' + this._domStorage.securityOrigin + '/' +
+        (this._domStorage.isLocalStorage ? 'local' : 'session');
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    this._storagePanel.showDOMStorage(this._domStorage);
+    return false;
+  }
+
+  /**
+   * @override
+   */
+  onattach() {
+    super.onattach();
+    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
+  }
+
+  _handleContextMenuEvent(event) {
+    var contextMenu = new UI.ContextMenu(event);
+    contextMenu.appendItem(Common.UIString('Clear'), () => this._domStorage.clear());
+    contextMenu.show();
+  }
+};
+
+Resources.CookieTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ResourcesPanel} storagePanel
+   * @param {!SDK.ResourceTreeFrame} frame
+   * @param {string} cookieDomain
+   */
+  constructor(storagePanel, frame, cookieDomain) {
+    super(storagePanel, cookieDomain ? cookieDomain : Common.UIString('Local Files'), false);
+    this._target = frame.target();
+    this._cookieDomain = cookieDomain;
+    var icon = UI.Icon.create('mediumicon-cookie', 'resource-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  get itemURL() {
+    return 'cookies://' + this._cookieDomain;
+  }
+
+  /**
+   * @override
+   */
+  onattach() {
+    super.onattach();
+    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
+  }
+
+  /**
+   * @param {!Event} event
+   */
+  _handleContextMenuEvent(event) {
+    var contextMenu = new UI.ContextMenu(event);
+    contextMenu.appendItem(
+        Common.UIString('Clear'), () => this._storagePanel.clearCookies(this._target, this._cookieDomain));
+    contextMenu.show();
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    this._storagePanel.showCookies(this._target, this._cookieDomain);
+    return false;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.ApplicationCacheManifestTreeElement = class extends Resources.BaseStorageTreeElement {
+  constructor(storagePanel, manifestURL) {
+    var title = new Common.ParsedURL(manifestURL).displayName;
+    super(storagePanel, title, false);
+    this.tooltip = manifestURL;
+    this._manifestURL = manifestURL;
+  }
+
+  get itemURL() {
+    return 'appcache://' + this._manifestURL;
+  }
+
+  get manifestURL() {
+    return this._manifestURL;
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    this._storagePanel.showCategoryView(this._manifestURL);
+    return false;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.ApplicationCacheFrameTreeElement = class extends Resources.BaseStorageTreeElement {
+  /**
+   * @param {!Resources.ApplicationPanelSidebar} sidebar
+   * @param {!SDK.ResourceTreeFrame} frame
+   * @param {string} manifestURL
+   */
+  constructor(sidebar, frame, manifestURL) {
+    super(sidebar._panel, '', false);
+    this._sidebar = sidebar;
+    this._frameId = frame.id;
+    this._manifestURL = manifestURL;
+    this._refreshTitles(frame);
+
+    var icon = UI.Icon.create('largeicon-navigator-folder', 'navigator-tree-item');
+    icon.classList.add('navigator-folder-tree-item');
+    this.setLeadingIcons([icon]);
+  }
+
+  get itemURL() {
+    return 'appcache://' + this._manifestURL + '/' + encodeURI(this.titleAsText());
+  }
+
+  get frameId() {
+    return this._frameId;
+  }
+
+  get manifestURL() {
+    return this._manifestURL;
+  }
+
+  /**
+   * @param {!SDK.ResourceTreeFrame} frame
+   */
+  _refreshTitles(frame) {
+    this.title = frame.displayName();
+  }
+
+  /**
+   * @param {!SDK.ResourceTreeFrame} frame
+   */
+  frameNavigated(frame) {
+    this._refreshTitles(frame);
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  onselect(selectedByUser) {
+    super.onselect(selectedByUser);
+    this._sidebar._showApplicationCache(this._frameId);
+    return false;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+Resources.StorageCategoryView = class extends UI.VBox {
+  constructor() {
+    super();
+
+    this.element.classList.add('storage-view');
+    this._emptyWidget = new UI.EmptyWidget('');
+    this._emptyWidget.show(this.element);
+  }
+
+  setText(text) {
+    this._emptyWidget.text = text;
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js b/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js
index 090a26b..7170f9a 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js
@@ -6,13 +6,9 @@
  * @unrestricted
  */
 Resources.ClearStorageView = class extends UI.VBox {
-  /**
-   * @param {!Resources.ResourcesPanel} resourcesPanel
-   */
-  constructor(resourcesPanel) {
+  constructor() {
     super(true);
 
-    this._resourcesPanel = resourcesPanel;
     this._reportView = new UI.ReportView(Common.UIString('Clear storage'));
     this._reportView.registerRequiredCSS('resources/clearStorageView.css');
     this._reportView.element.classList.add('clear-storage-header');
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/CookieItemsView.js b/third_party/WebKit/Source/devtools/front_end/resources/CookieItemsView.js
index e910a7e..7a67c816 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/CookieItemsView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/CookieItemsView.js
@@ -29,17 +29,15 @@
 
 Resources.CookieItemsView = class extends Resources.StorageItemsView {
   /**
-   * @param {!Resources.CookieTreeElement} treeElement
    * @param {!SDK.CookieModel} model
    * @param {string} cookieDomain
    */
-  constructor(treeElement, model, cookieDomain) {
+  constructor(model, cookieDomain) {
     super(Common.UIString('Cookies'), 'cookiesPanel');
 
     this.element.classList.add('storage-view');
 
     this._model = model;
-    this._treeElement = treeElement;
     this._cookieDomain = cookieDomain;
 
     this._totalSize = 0;
@@ -89,7 +87,9 @@
 
     if (!this._cookiesTable) {
       this._cookiesTable = new CookieTable.CookiesTable(
-          this._saveCookie.bind(this), this.refreshItems.bind(this), () => this.setCanDeleteSelected(true),
+          this._saveCookie.bind(this),
+          this.refreshItems.bind(this),
+          () => this.setCanDeleteSelected(!!this._cookiesTable.selectedCookie()),
           this._deleteCookie.bind(this));
     }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js
index 22298440..e47760e0 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js
@@ -1,122 +1,36 @@
-/*
- * Copyright (C) 2007, 2008, 2010 Apple Inc.  All rights reserved.
- * Copyright (C) 2009 Joseph Pecoraro
- * Copyright (C) 2013 Samsung Electronics. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/**
- * @implements {SDK.TargetManager.Observer}
- * @unrestricted
- */
+// 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.
+
 Resources.ResourcesPanel = class extends UI.PanelWithSidebar {
   constructor() {
     super('resources');
     this.registerRequiredCSS('resources/resourcesPanel.css');
 
-    this._resourcesLastSelectedItemSetting = Common.settings.createSetting('resourcesLastSelectedItem', {});
+    this._resourcesLastSelectedItemSetting = Common.settings.createSetting('resourcesLastSelectedItem', '');
 
-    this._sidebarTree = new UI.TreeOutlineInShadow();
-    this._sidebarTree.element.classList.add('resources-sidebar');
-    this._sidebarTree.registerRequiredCSS('resources/resourcesSidebar.css');
-    this._sidebarTree.element.classList.add('filter-all');
-    this.panelSidebarElement().appendChild(this._sidebarTree.element);
+    /** @type {?UI.Widget} */
+    this.visibleView = null;
 
-    this._applicationTreeElement = this._addSidebarSection(Common.UIString('Application'));
-    this._manifestTreeElement = new Resources.AppManifestTreeElement(this);
-    this._applicationTreeElement.appendChild(this._manifestTreeElement);
-    this.serviceWorkersTreeElement = new Resources.ServiceWorkersTreeElement(this);
-    this._applicationTreeElement.appendChild(this.serviceWorkersTreeElement);
-    var clearStorageTreeElement = new Resources.ClearStorageTreeElement(this);
-    this._applicationTreeElement.appendChild(clearStorageTreeElement);
-
-    var storageTreeElement = this._addSidebarSection(Common.UIString('Storage'));
-    this.localStorageListTreeElement =
-        new Resources.StorageCategoryTreeElement(this, Common.UIString('Local Storage'), 'LocalStorage');
-    var localStorageIcon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
-    this.localStorageListTreeElement.setLeadingIcons([localStorageIcon]);
-
-    storageTreeElement.appendChild(this.localStorageListTreeElement);
-    this.sessionStorageListTreeElement =
-        new Resources.StorageCategoryTreeElement(this, Common.UIString('Session Storage'), 'SessionStorage');
-    var sessionStorageIcon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
-    this.sessionStorageListTreeElement.setLeadingIcons([sessionStorageIcon]);
-
-    storageTreeElement.appendChild(this.sessionStorageListTreeElement);
-    this.indexedDBListTreeElement = new Resources.IndexedDBTreeElement(this);
-    storageTreeElement.appendChild(this.indexedDBListTreeElement);
-    this.databasesListTreeElement =
-        new Resources.StorageCategoryTreeElement(this, Common.UIString('Web SQL'), 'Databases');
-    var databaseIcon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
-    this.databasesListTreeElement.setLeadingIcons([databaseIcon]);
-
-    storageTreeElement.appendChild(this.databasesListTreeElement);
-    this.cookieListTreeElement = new Resources.StorageCategoryTreeElement(this, Common.UIString('Cookies'), 'Cookies');
-    var cookieIcon = UI.Icon.create('mediumicon-cookie', 'resource-tree-item');
-    this.cookieListTreeElement.setLeadingIcons([cookieIcon]);
-    storageTreeElement.appendChild(this.cookieListTreeElement);
-
-    var cacheTreeElement = this._addSidebarSection(Common.UIString('Cache'));
-    this.cacheStorageListTreeElement = new Resources.ServiceWorkerCacheTreeElement(this);
-    cacheTreeElement.appendChild(this.cacheStorageListTreeElement);
-    this.applicationCacheListTreeElement =
-        new Resources.StorageCategoryTreeElement(this, Common.UIString('Application Cache'), 'ApplicationCache');
-    var applicationCacheIcon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
-    this.applicationCacheListTreeElement.setLeadingIcons([applicationCacheIcon]);
-
-    cacheTreeElement.appendChild(this.applicationCacheListTreeElement);
-
-    this._resourcesSection = new Resources.ResourcesSection(this, this._addSidebarSection(Common.UIString('Frames')));
+    /** @type {?Resources.StorageCategoryView} */
+    this._categoryView = null;
 
     var mainContainer = new UI.VBox();
     this.storageViews = mainContainer.element.createChild('div', 'vbox flex-auto');
     this._storageViewToolbar = new UI.Toolbar('resources-toolbar', mainContainer.element);
     this.splitWidget().setMainWidget(mainContainer);
 
-    /** @type {!Map.<!Resources.Database, !Object.<string, !Resources.DatabaseTableView>>} */
-    this._databaseTableViews = new Map();
-    /** @type {!Map.<!Resources.Database, !Resources.DatabaseQueryView>} */
-    this._databaseQueryViews = new Map();
-    /** @type {!Map.<!Resources.Database, !Resources.DatabaseTreeElement>} */
-    this._databaseTreeElements = new Map();
-    /** @type {!Map.<!Resources.DOMStorage, !Resources.DOMStorageTreeElement>} */
-    this._domStorageTreeElements = new Map();
-    /** @type {!Object.<string, boolean>} */
-    this._domains = {};
-
     /** @type {?Resources.DOMStorageItemsView} */
     this._domStorageView = null;
+
     /** @type {?Resources.CookieItemsView} */
     this._cookieView = null;
 
-    this.panelSidebarElement().addEventListener('mousemove', this._onmousemove.bind(this), false);
-    this.panelSidebarElement().addEventListener('mouseleave', this._onmouseleave.bind(this), false);
+    /** @type {?UI.EmptyWidget} */
+    this._emptyWidget = null;
 
-    SDK.targetManager.observeTargets(this);
-    SDK.targetManager.addModelListener(
-        SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.FrameNavigated, this._frameNavigated, this);
+    this._sidebar = new Resources.ApplicationPanelSidebar(this);
+    this._sidebar.show(this.panelSidebarElement());
   }
 
   /**
@@ -127,421 +41,52 @@
   }
 
   /**
-   * @param {string} title
-   * @return {!UI.TreeElement}
+   * @param {!UI.Widget} view
+   * @return {boolean}
    */
-  _addSidebarSection(title) {
-    var treeElement = new UI.TreeElement(title, true);
-    treeElement.listItemElement.classList.add('storage-group-list-item');
-    treeElement.setCollapsible(false);
-    treeElement.selectable = false;
-    this._sidebarTree.appendChild(treeElement);
-    return treeElement;
-  }
-
-  /**
-   * @override
-   * @param {!SDK.Target} target
-   */
-  targetAdded(target) {
-    if (this._target)
-      return;
-    this._target = target;
-    this._databaseModel = Resources.DatabaseModel.fromTarget(target);
-
-    this._databaseModel.on(Resources.DatabaseModel.DatabaseAddedEvent, this._databaseAdded, this);
-    this._databaseModel.on(Resources.DatabaseModel.DatabasesRemovedEvent, this._resetWebSQL, this);
-
-    var resourceTreeModel = SDK.ResourceTreeModel.fromTarget(target);
-    if (!resourceTreeModel)
-      return;
-
-    if (resourceTreeModel.cachedResourcesLoaded())
-      this._initialize();
-
-    resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this._initialize, this);
-    resourceTreeModel.addEventListener(
-        SDK.ResourceTreeModel.Events.WillLoadCachedResources, this._resetWithFrames, this);
-  }
-
-  /**
-   * @override
-   * @param {!SDK.Target} target
-   */
-  targetRemoved(target) {
-    if (target !== this._target)
-      return;
-    delete this._target;
-
-    var resourceTreeModel = SDK.ResourceTreeModel.fromTarget(target);
-    if (resourceTreeModel) {
-      resourceTreeModel.removeEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this._initialize, this);
-      resourceTreeModel.removeEventListener(
-          SDK.ResourceTreeModel.Events.WillLoadCachedResources, this._resetWithFrames, this);
-    }
-    this._databaseModel.off(Resources.DatabaseModel.DatabaseAddedEvent, this._databaseAdded, this);
-    this._databaseModel.off(Resources.DatabaseModel.DatabasesRemovedEvent, this._resetWebSQL, this);
-
-    this._resetWithFrames();
+  static _shouldCloseOnReset(view) {
+    var viewClassesToClose = [
+      SourceFrame.ResourceSourceFrame, SourceFrame.ImageView, SourceFrame.FontView, Resources.StorageItemsView,
+      Resources.DatabaseQueryView, Resources.DatabaseTableView
+    ];
+    return viewClassesToClose.some(type => view instanceof type);
   }
 
   /**
    * @override
    */
   focus() {
-    this._sidebarTree.focus();
-  }
-
-  _initialize() {
-    for (var frame of SDK.ResourceTreeModel.frames())
-      this._addCookieDocument(frame);
-    this._databaseModel.enable();
-
-    var indexedDBModel = Resources.IndexedDBModel.fromTarget(this._target);
-    if (indexedDBModel)
-      indexedDBModel.enable();
-
-    var cacheStorageModel = SDK.ServiceWorkerCacheModel.fromTarget(this._target);
-    if (cacheStorageModel)
-      cacheStorageModel.enable();
-    var resourceTreeModel = SDK.ResourceTreeModel.fromTarget(this._target);
-    if (resourceTreeModel)
-      this._populateApplicationCacheTree(resourceTreeModel);
-    var domStorageModel = Resources.DOMStorageModel.fromTarget(this._target);
-    if (domStorageModel)
-      this._populateDOMStorageTree(domStorageModel);
-    this.indexedDBListTreeElement._initialize();
-    this.cacheStorageListTreeElement._initialize();
-    this._initDefaultSelection();
-  }
-
-  _initDefaultSelection() {
-    var itemURL = this._resourcesLastSelectedItemSetting.get();
-    if (itemURL) {
-      var rootElement = this._sidebarTree.rootElement();
-      for (var treeElement = rootElement.firstChild(); treeElement;
-           treeElement = treeElement.traverseNextTreeElement(false, rootElement, true)) {
-        if (treeElement.itemURL === itemURL) {
-          treeElement.revealAndSelect(true);
-          return;
-        }
-      }
-    }
-    this._manifestTreeElement.select();
-  }
-
-  _resetWithFrames() {
-    this._resourcesSection.reset();
-    this._reset();
-  }
-
-  _resetWebSQL() {
-    if (this.visibleView instanceof Resources.DatabaseQueryView ||
-        this.visibleView instanceof Resources.DatabaseTableView) {
-      this.visibleView.detach();
-      delete this.visibleView;
-    }
-
-    var queryViews = this._databaseQueryViews.valuesArray();
-    for (var i = 0; i < queryViews.length; ++i) {
-      queryViews[i].removeEventListener(
-          Resources.DatabaseQueryView.Events.SchemaUpdated, this._updateDatabaseTables, this);
-    }
-    this._databaseTableViews.clear();
-    this._databaseQueryViews.clear();
-    this._databaseTreeElements.clear();
-    this.databasesListTreeElement.removeChildren();
-    this.databasesListTreeElement.setExpandable(false);
-  }
-
-  _resetDOMStorage() {
-    if (this.visibleView === this._domStorageView) {
-      this.visibleView.detach();
-      delete this.visibleView;
-    }
-
-    this._domStorageTreeElements.clear();
-    this.localStorageListTreeElement.removeChildren();
-    this.sessionStorageListTreeElement.removeChildren();
-  }
-
-  _resetCookies() {
-    if (this.visibleView instanceof Resources.CookieItemsView) {
-      this.visibleView.detach();
-      delete this.visibleView;
-    }
-    this.cookieListTreeElement.removeChildren();
-  }
-
-  _resetCacheStorage() {
-    if (this.visibleView instanceof Resources.ServiceWorkerCacheView) {
-      this.visibleView.detach();
-      delete this.visibleView;
-    }
-    this.cacheStorageListTreeElement.removeChildren();
-    this.cacheStorageListTreeElement.setExpandable(false);
-  }
-
-  _resetAppCache() {
-    for (var frameId of Object.keys(this._applicationCacheFrameElements))
-      this._applicationCacheFrameManifestRemoved({data: frameId});
-    this.applicationCacheListTreeElement.setExpandable(false);
-  }
-
-  _reset() {
-    this._domains = {};
-    this._resetWebSQL();
-    this._resetDOMStorage();
-    this._resetCookies();
-    this._resetCacheStorage();
-    // No need to this._resetAppCache.
-
-    if ((this.visibleView instanceof SourceFrame.ResourceSourceFrame) ||
-        (this.visibleView instanceof SourceFrame.ImageView) || (this.visibleView instanceof SourceFrame.FontView)) {
-      this.visibleView.detach();
-      delete this.visibleView;
-    }
-
-    this._storageViewToolbar.removeToolbarItems();
-
-    if (this._sidebarTree.selectedTreeElement)
-      this._sidebarTree.selectedTreeElement.deselect();
-  }
-
-  _frameNavigated(event) {
-    var frame = event.data;
-
-    if (!frame.parentFrame)
-      this._reset();
-
-    var applicationCacheFrameTreeElement = this._applicationCacheFrameElements[frame.id];
-    if (applicationCacheFrameTreeElement)
-      applicationCacheFrameTreeElement.frameNavigated(frame);
-    this._addCookieDocument(frame);
+    this._sidebar.focus();
   }
 
   /**
-   * @param {!Resources.DatabaseModel.DatabaseAddedEvent} event
+   * @return {string}
    */
-  _databaseAdded(event) {
-    var databaseTreeElement = new Resources.DatabaseTreeElement(this, event.database);
-    this._databaseTreeElements.set(event.database, databaseTreeElement);
-    this.databasesListTreeElement.appendChild(databaseTreeElement);
+  lastSelectedItemURL() {
+    return this._resourcesLastSelectedItemSetting.get();
+  }
+
+  setLastSelectedItemURL(url) {
+    this._resourcesLastSelectedItemSetting.set(url);
+  }
+
+  resetView() {
+    if (this.visibleView && Resources.ResourcesPanel._shouldCloseOnReset(this.visibleView))
+      this.showView(null);
   }
 
   /**
-   * @param {!SDK.ResourceTreeFrame} frame
+   * @param {?UI.Widget} view
    */
-  _addCookieDocument(frame) {
-    var parsedURL = frame.url.asParsedURL();
-    if (!parsedURL || (parsedURL.scheme !== 'http' && parsedURL.scheme !== 'https' && parsedURL.scheme !== 'file'))
-      return;
-
-    var domain = parsedURL.securityOrigin();
-    if (!this._domains[domain]) {
-      this._domains[domain] = true;
-      var cookieDomainTreeElement = new Resources.CookieTreeElement(this, frame, domain);
-      this.cookieListTreeElement.appendChild(cookieDomainTreeElement);
-    }
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _domStorageAdded(event) {
-    var domStorage = /** @type {!Resources.DOMStorage} */ (event.data);
-    this._addDOMStorage(domStorage);
-  }
-
-  /**
-   * @param {!Resources.DOMStorage} domStorage
-   */
-  _addDOMStorage(domStorage) {
-    console.assert(!this._domStorageTreeElements.get(domStorage));
-
-    var domStorageTreeElement = new Resources.DOMStorageTreeElement(this, domStorage);
-    this._domStorageTreeElements.set(domStorage, domStorageTreeElement);
-    if (domStorage.isLocalStorage)
-      this.localStorageListTreeElement.appendChild(domStorageTreeElement);
-    else
-      this.sessionStorageListTreeElement.appendChild(domStorageTreeElement);
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _domStorageRemoved(event) {
-    var domStorage = /** @type {!Resources.DOMStorage} */ (event.data);
-    this._removeDOMStorage(domStorage);
-  }
-
-  /**
-   * @param {!Resources.DOMStorage} domStorage
-   */
-  _removeDOMStorage(domStorage) {
-    var treeElement = this._domStorageTreeElements.get(domStorage);
-    if (!treeElement)
-      return;
-    var wasSelected = treeElement.selected;
-    var parentListTreeElement = treeElement.parent;
-    parentListTreeElement.removeChild(treeElement);
-    if (wasSelected)
-      parentListTreeElement.select();
-    this._domStorageTreeElements.remove(domStorage);
-  }
-
-  /**
-   * @param {!Resources.Database} database
-   */
-  selectDatabase(database) {
-    if (database) {
-      this._showDatabase(database);
-      this._databaseTreeElements.get(database).select();
-    }
-  }
-
-  /**
-   * @param {!Resources.DOMStorage} domStorage
-   */
-  selectDOMStorage(domStorage) {
-    if (domStorage) {
-      this._showDOMStorage(domStorage);
-      this._domStorageTreeElements.get(domStorage).select();
-    }
-  }
-
-  /**
-   * @param {!SDK.Resource} resource
-   * @param {number=} line
-   * @param {number=} column
-   * @return {boolean}
-   */
-  showResource(resource, line, column) {
-    var resourceTreeElement = Resources.FrameResourceTreeElement.forResource(resource);
-    if (resourceTreeElement)
-      resourceTreeElement.revealAndSelect(true);
-
-    if (typeof line === 'number') {
-      var resourceSourceFrame = this._resourceSourceFrameViewForResource(resource);
-      if (resourceSourceFrame)
-        resourceSourceFrame.revealPosition(line, column, true);
-    }
-    return true;
-  }
-
-  /**
-   * @param {!SDK.Resource} resource
-   * @return {?SourceFrame.ResourceSourceFrame}
-   */
-  _resourceSourceFrameViewForResource(resource) {
-    var resourceView = Resources.FrameResourceTreeElement.resourceViewForResource(resource);
-    if (resourceView && resourceView instanceof SourceFrame.ResourceSourceFrame)
-      return /** @type {!SourceFrame.ResourceSourceFrame} */ (resourceView);
-    return null;
-  }
-
-  /**
-   * @param {!Resources.Database} database
-   * @param {string=} tableName
-   */
-  _showDatabase(database, tableName) {
-    if (!database)
-      return;
-
-    var view;
-    if (tableName) {
-      var tableViews = this._databaseTableViews.get(database);
-      if (!tableViews) {
-        tableViews = /** @type {!Object.<string, !Resources.DatabaseTableView>} */ ({});
-        this._databaseTableViews.set(database, tableViews);
-      }
-      view = tableViews[tableName];
-      if (!view) {
-        view = new Resources.DatabaseTableView(database, tableName);
-        tableViews[tableName] = view;
-      }
-    } else {
-      view = this._databaseQueryViews.get(database);
-      if (!view) {
-        view = new Resources.DatabaseQueryView(database);
-        this._databaseQueryViews.set(database, view);
-        view.addEventListener(Resources.DatabaseQueryView.Events.SchemaUpdated, this._updateDatabaseTables, this);
-      }
-    }
-
-    this._innerShowView(view);
-  }
-
-  /**
-   * @param {!Resources.DOMStorage} domStorage
-   */
-  _showDOMStorage(domStorage) {
-    if (!domStorage)
-      return;
-
-    if (!this._domStorageView)
-      this._domStorageView = new Resources.DOMStorageItemsView(domStorage);
-    else
-      this._domStorageView.setStorage(domStorage);
-    this._innerShowView(this._domStorageView);
-  }
-
-  /**
-   * @param {!Resources.CookieTreeElement} treeElement
-   * @param {string} cookieDomain
-   * @param {!SDK.Target} cookieFrameTarget
-   */
-  showCookies(treeElement, cookieDomain, cookieFrameTarget) {
-    var model = SDK.CookieModel.fromTarget(cookieFrameTarget);
-    if (!this._cookieView)
-      this._cookieView = new Resources.CookieItemsView(treeElement, model, cookieDomain);
-    else
-      this._cookieView.setCookiesDomain(model, cookieDomain);
-    this._innerShowView(this._cookieView);
-  }
-
-  /**
-   * @param {!SDK.Target} target
-   * @param {string} cookieDomain
-   */
-  _clearCookies(target, cookieDomain) {
-    SDK.CookieModel.fromTarget(target).clear(cookieDomain, () => {
-      if (this._cookieView)
-        this._cookieView.refreshItems();
-    });
-  }
-
-  showApplicationCache(frameId) {
-    if (!this._applicationCacheViews[frameId]) {
-      this._applicationCacheViews[frameId] =
-          new Resources.ApplicationCacheItemsView(this._applicationCacheModel, frameId);
-    }
-
-    this._innerShowView(this._applicationCacheViews[frameId]);
-  }
-
-  /**
-   *  @param {!UI.Widget} view
-   */
-  showFileSystem(view) {
-    this._innerShowView(view);
-  }
-
-  showCategoryView(categoryName) {
-    if (!this._categoryView)
-      this._categoryView = new Resources.StorageCategoryView();
-    this._categoryView.setText(categoryName);
-    this._innerShowView(this._categoryView);
-  }
-
-  _innerShowView(view) {
+  showView(view) {
     if (this.visibleView === view)
       return;
 
     if (this.visibleView)
       this.visibleView.detach();
 
-    view.show(this.storageViews);
+    if (view)
+      view.show(this.storageViews);
     this.visibleView = view;
 
     this._storageViewToolbar.removeToolbarItems();
@@ -551,172 +96,68 @@
     this._storageViewToolbar.element.classList.toggle('hidden', !toolbarItems.length);
   }
 
-  closeVisibleView() {
-    if (!this.visibleView)
-      return;
-    this.visibleView.detach();
-    delete this.visibleView;
-  }
-
-  _updateDatabaseTables(event) {
-    var database = event.data;
-
-    if (!database)
-      return;
-
-    var databasesTreeElement = this._databaseTreeElements.get(database);
-    if (!databasesTreeElement)
-      return;
-
-    databasesTreeElement.invalidateChildren();
-    var tableViews = this._databaseTableViews.get(database);
-
-    if (!tableViews)
-      return;
-
-    var tableNamesHash = {};
-    var self = this;
-    function tableNamesCallback(tableNames) {
-      var tableNamesLength = tableNames.length;
-      for (var i = 0; i < tableNamesLength; ++i)
-        tableNamesHash[tableNames[i]] = true;
-
-      for (var tableName in tableViews) {
-        if (!(tableName in tableNamesHash)) {
-          if (self.visibleView === tableViews[tableName])
-            self.closeVisibleView();
-          delete tableViews[tableName];
-        }
-      }
-    }
-    database.getTableNames(tableNamesCallback);
+  /**
+   * @param {string} categoryName
+   */
+  showCategoryView(categoryName) {
+    if (!this._categoryView)
+      this._categoryView = new Resources.StorageCategoryView();
+    this._categoryView.setText(categoryName);
+    this.showView(this._categoryView);
   }
 
   /**
-   * @param {!Resources.DOMStorageModel} domStorageModel
+   * @param {!Resources.DOMStorage} domStorage
    */
-  _populateDOMStorageTree(domStorageModel) {
-    domStorageModel.enable();
-    domStorageModel.storages().forEach(this._addDOMStorage.bind(this));
-    domStorageModel.addEventListener(Resources.DOMStorageModel.Events.DOMStorageAdded, this._domStorageAdded, this);
-    domStorageModel.addEventListener(Resources.DOMStorageModel.Events.DOMStorageRemoved, this._domStorageRemoved, this);
+  showDOMStorage(domStorage) {
+    if (!domStorage)
+      return;
+
+    if (!this._domStorageView)
+      this._domStorageView = new Resources.DOMStorageItemsView(domStorage);
+    else
+      this._domStorageView.setStorage(domStorage);
+    this.showView(this._domStorageView);
   }
 
   /**
-   * @param {!SDK.ResourceTreeModel} resourceTreeModel
+   * @param {!SDK.Target} cookieFrameTarget
+   * @param {string} cookieDomain
    */
-  _populateApplicationCacheTree(resourceTreeModel) {
-    this._applicationCacheModel = Resources.ApplicationCacheModel.fromTarget(this._target);
-
-    this._applicationCacheViews = {};
-    this._applicationCacheFrameElements = {};
-    this._applicationCacheManifestElements = {};
-
-    this._applicationCacheModel.addEventListener(
-        Resources.ApplicationCacheModel.Events.FrameManifestAdded, this._applicationCacheFrameManifestAdded, this);
-    this._applicationCacheModel.addEventListener(
-        Resources.ApplicationCacheModel.Events.FrameManifestRemoved, this._applicationCacheFrameManifestRemoved, this);
-    this._applicationCacheModel.addEventListener(
-        Resources.ApplicationCacheModel.Events.FrameManifestsReset, this._resetAppCache, this);
-
-    this._applicationCacheModel.addEventListener(
-        Resources.ApplicationCacheModel.Events.FrameManifestStatusUpdated,
-        this._applicationCacheFrameManifestStatusChanged, this);
-    this._applicationCacheModel.addEventListener(
-        Resources.ApplicationCacheModel.Events.NetworkStateChanged, this._applicationCacheNetworkStateChanged, this);
+  showCookies(cookieFrameTarget, cookieDomain) {
+    var model = SDK.CookieModel.fromTarget(cookieFrameTarget);
+    if (!this._cookieView)
+      this._cookieView = new Resources.CookieItemsView(model, cookieDomain);
+    else
+      this._cookieView.setCookiesDomain(model, cookieDomain);
+    this.showView(this._cookieView);
   }
 
-  _applicationCacheFrameManifestAdded(event) {
-    var frameId = event.data;
-    var manifestURL = this._applicationCacheModel.frameManifestURL(frameId);
-
-    var manifestTreeElement = this._applicationCacheManifestElements[manifestURL];
-    if (!manifestTreeElement) {
-      manifestTreeElement = new Resources.ApplicationCacheManifestTreeElement(this, manifestURL);
-      this.applicationCacheListTreeElement.appendChild(manifestTreeElement);
-      this._applicationCacheManifestElements[manifestURL] = manifestTreeElement;
-    }
-
-    var frameTreeElement = new Resources.ApplicationCacheFrameTreeElement(this, frameId, manifestURL);
-    manifestTreeElement.appendChild(frameTreeElement);
-    manifestTreeElement.expand();
-    this._applicationCacheFrameElements[frameId] = frameTreeElement;
+  /**
+   * @param {string} text
+   */
+  showEmptyWidget(text) {
+    if (!this._emptyWidget)
+      this._emptyWidget = new UI.EmptyWidget(text);
+    else
+      this._emptyWidget.text = text;
+    this.showView(this._emptyWidget);
   }
 
-  _applicationCacheFrameManifestRemoved(event) {
-    var frameId = event.data;
-    var frameTreeElement = this._applicationCacheFrameElements[frameId];
-    if (!frameTreeElement)
-      return;
-
-    var manifestURL = frameTreeElement.manifestURL;
-    delete this._applicationCacheFrameElements[frameId];
-    delete this._applicationCacheViews[frameId];
-    frameTreeElement.parent.removeChild(frameTreeElement);
-
-    var manifestTreeElement = this._applicationCacheManifestElements[manifestURL];
-    if (manifestTreeElement.childCount())
-      return;
-
-    delete this._applicationCacheManifestElements[manifestURL];
-    manifestTreeElement.parent.removeChild(manifestTreeElement);
-  }
-
-  _applicationCacheFrameManifestStatusChanged(event) {
-    var frameId = event.data;
-    var status = this._applicationCacheModel.frameManifestStatus(frameId);
-
-    if (this._applicationCacheViews[frameId])
-      this._applicationCacheViews[frameId].updateStatus(status);
-  }
-
-  _applicationCacheNetworkStateChanged(event) {
-    var isNowOnline = event.data;
-
-    for (var manifestURL in this._applicationCacheViews)
-      this._applicationCacheViews[manifestURL].updateNetworkState(isNowOnline);
-  }
-
-  showView(view) {
-    if (view)
-      this.showResource(view.resource);
-  }
-
-  _onmousemove(event) {
-    var nodeUnderMouse = event.target;
-    if (!nodeUnderMouse)
-      return;
-
-    var listNode = nodeUnderMouse.enclosingNodeOrSelfWithNodeName('li');
-    if (!listNode)
-      return;
-
-    var element = listNode.treeElement;
-    if (this._previousHoveredElement === element)
-      return;
-
-    if (this._previousHoveredElement) {
-      this._previousHoveredElement.hovered = false;
-      delete this._previousHoveredElement;
-    }
-
-    if (element instanceof Resources.FrameTreeElement) {
-      this._previousHoveredElement = element;
-      element.hovered = true;
-    }
-  }
-
-  _onmouseleave(event) {
-    if (this._previousHoveredElement) {
-      this._previousHoveredElement.hovered = false;
-      delete this._previousHoveredElement;
-    }
+  /**
+   * @param {!SDK.Target} target
+   * @param {string} cookieDomain
+   */
+  clearCookies(target, cookieDomain) {
+    SDK.CookieModel.fromTarget(target).clear(cookieDomain, () => {
+      if (this._cookieView)
+        this._cookieView.refreshItems();
+    });
   }
 };
 
 /**
  * @implements {Common.Revealer}
- * @unrestricted
  */
 Resources.ResourcesPanel.ResourceRevealer = class {
   /**
@@ -727,1063 +168,7 @@
   reveal(resource) {
     if (!(resource instanceof SDK.Resource))
       return Promise.reject(new Error('Internal error: not a resource'));
-    var panel = Resources.ResourcesPanel._instance();
+    var panel = Resources.ResourcesPanel._instance()._sidebar;
     return UI.viewManager.showView('resources').then(panel.showResource.bind(panel, resource));
   }
 };
-
-/**
- * @unrestricted
- */
-Resources.BaseStorageTreeElement = class extends UI.TreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   * @param {string} title
-   * @param {boolean} expandable
-   */
-  constructor(storagePanel, title, expandable) {
-    super(title, expandable);
-    this._storagePanel = storagePanel;
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    if (!selectedByUser)
-      return false;
-    var itemURL = this.itemURL;
-    if (itemURL)
-      this._storagePanel._resourcesLastSelectedItemSetting.set(itemURL);
-    return false;
-  }
-
-  /**
-   * @protected
-   * @param {?UI.Widget} view
-   */
-  showView(view) {
-    if (!view) {
-      this._storagePanel.visibleView.detach();
-      return;
-    }
-    this._storagePanel._innerShowView(view);
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.StorageCategoryTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   * @param {string} categoryName
-   * @param {string} settingsKey
-   */
-  constructor(storagePanel, categoryName, settingsKey) {
-    super(storagePanel, categoryName, false);
-    this._expandedSetting =
-        Common.settings.createSetting('resources' + settingsKey + 'Expanded', settingsKey === 'Frames');
-    this._categoryName = categoryName;
-  }
-
-  /**
-   * @return {!SDK.Target}
-   */
-  target() {
-    return this._storagePanel._target;
-  }
-
-  get itemURL() {
-    return 'category://' + this._categoryName;
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    this._storagePanel.showCategoryView(this._categoryName);
-    return false;
-  }
-
-  /**
-   * @override
-   */
-  onattach() {
-    super.onattach();
-    if (this._expandedSetting.get())
-      this.expand();
-  }
-
-  /**
-   * @override
-   */
-  onexpand() {
-    this._expandedSetting.set(true);
-  }
-
-  /**
-   * @override
-   */
-  oncollapse() {
-    this._expandedSetting.set(false);
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.DatabaseTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   * @param {!Resources.Database} database
-   */
-  constructor(storagePanel, database) {
-    super(storagePanel, database.name, true);
-    this._database = database;
-
-    var icon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  get itemURL() {
-    return 'database://' + encodeURI(this._database.name);
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    this._storagePanel._showDatabase(this._database);
-    return false;
-  }
-
-  /**
-   * @override
-   */
-  onexpand() {
-    this._updateChildren();
-  }
-
-  _updateChildren() {
-    this.removeChildren();
-
-    /**
-     * @param {!Array.<string>} tableNames
-     * @this {Resources.DatabaseTreeElement}
-     */
-    function tableNamesCallback(tableNames) {
-      var tableNamesLength = tableNames.length;
-      for (var i = 0; i < tableNamesLength; ++i)
-        this.appendChild(new Resources.DatabaseTableTreeElement(this._storagePanel, this._database, tableNames[i]));
-    }
-    this._database.getTableNames(tableNamesCallback.bind(this));
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.DatabaseTableTreeElement = class extends Resources.BaseStorageTreeElement {
-  constructor(storagePanel, database, tableName) {
-    super(storagePanel, tableName, false);
-    this._database = database;
-    this._tableName = tableName;
-    var icon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  get itemURL() {
-    return 'database://' + encodeURI(this._database.name) + '/' + encodeURI(this._tableName);
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    this._storagePanel._showDatabase(this._database, this._tableName);
-    return false;
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.ServiceWorkerCacheTreeElement = class extends Resources.StorageCategoryTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   */
-  constructor(storagePanel) {
-    super(storagePanel, Common.UIString('Cache Storage'), 'CacheStorage');
-    var icon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  _initialize() {
-    /** @type {!Array.<!Resources.SWCacheTreeElement>} */
-    this._swCacheTreeElements = [];
-    var target = this._storagePanel._target;
-    var model = target && SDK.ServiceWorkerCacheModel.fromTarget(target);
-    if (model) {
-      for (var cache of model.caches())
-        this._addCache(model, cache);
-    }
-    SDK.targetManager.addModelListener(
-        SDK.ServiceWorkerCacheModel, SDK.ServiceWorkerCacheModel.Events.CacheAdded, this._cacheAdded, this);
-    SDK.targetManager.addModelListener(
-        SDK.ServiceWorkerCacheModel, SDK.ServiceWorkerCacheModel.Events.CacheRemoved, this._cacheRemoved, this);
-  }
-
-  /**
-   * @override
-   */
-  onattach() {
-    super.onattach();
-    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
-  }
-
-  _handleContextMenuEvent(event) {
-    var contextMenu = new UI.ContextMenu(event);
-    contextMenu.appendItem(Common.UIString('Refresh Caches'), this._refreshCaches.bind(this));
-    contextMenu.show();
-  }
-
-  _refreshCaches() {
-    var target = this._storagePanel._target;
-    if (target) {
-      var model = SDK.ServiceWorkerCacheModel.fromTarget(target);
-      if (!model)
-        return;
-      model.refreshCacheNames();
-    }
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _cacheAdded(event) {
-    var cache = /** @type {!SDK.ServiceWorkerCacheModel.Cache} */ (event.data.cache);
-    var model = /** @type {!SDK.ServiceWorkerCacheModel} */ (event.data.model);
-    this._addCache(model, cache);
-  }
-
-  /**
-   * @param {!SDK.ServiceWorkerCacheModel} model
-   * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
-   */
-  _addCache(model, cache) {
-    var swCacheTreeElement = new Resources.SWCacheTreeElement(this._storagePanel, model, cache);
-    this._swCacheTreeElements.push(swCacheTreeElement);
-    this.appendChild(swCacheTreeElement);
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _cacheRemoved(event) {
-    var cache = /** @type {!SDK.ServiceWorkerCacheModel.Cache} */ (event.data.cache);
-    var model = /** @type {!SDK.ServiceWorkerCacheModel} */ (event.data.model);
-
-    var swCacheTreeElement = this._cacheTreeElement(model, cache);
-    if (!swCacheTreeElement)
-      return;
-
-    swCacheTreeElement.clear();
-    this.removeChild(swCacheTreeElement);
-    this._swCacheTreeElements.remove(swCacheTreeElement);
-  }
-
-  /**
-   * @param {!SDK.ServiceWorkerCacheModel} model
-   * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
-   * @return {?Resources.SWCacheTreeElement}
-   */
-  _cacheTreeElement(model, cache) {
-    var index = -1;
-    for (var i = 0; i < this._swCacheTreeElements.length; ++i) {
-      if (this._swCacheTreeElements[i]._cache.equals(cache) && this._swCacheTreeElements[i]._model === model) {
-        index = i;
-        break;
-      }
-    }
-    if (index !== -1)
-      return this._swCacheTreeElements[i];
-    return null;
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.SWCacheTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   * @param {!SDK.ServiceWorkerCacheModel} model
-   * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
-   */
-  constructor(storagePanel, model, cache) {
-    super(storagePanel, cache.cacheName + ' - ' + cache.securityOrigin, false);
-    this._model = model;
-    this._cache = cache;
-    var icon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  get itemURL() {
-    // I don't think this will work at all.
-    return 'cache://' + this._cache.cacheId;
-  }
-
-  /**
-   * @override
-   */
-  onattach() {
-    super.onattach();
-    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
-  }
-
-  _handleContextMenuEvent(event) {
-    var contextMenu = new UI.ContextMenu(event);
-    contextMenu.appendItem(Common.UIString('Delete'), this._clearCache.bind(this));
-    contextMenu.show();
-  }
-
-  _clearCache() {
-    this._model.deleteCache(this._cache);
-  }
-
-  /**
-   * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
-   */
-  update(cache) {
-    this._cache = cache;
-    if (this._view)
-      this._view.update(cache);
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    if (!this._view)
-      this._view = new Resources.ServiceWorkerCacheView(this._model, this._cache);
-
-    this.showView(this._view);
-    return false;
-  }
-
-  clear() {
-    if (this._view)
-      this._view.clear();
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.ServiceWorkersTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   */
-  constructor(storagePanel) {
-    super(storagePanel, Common.UIString('Service Workers'), false);
-    var icon = UI.Icon.create('mediumicon-service-worker', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  /**
-   * @return {string}
-   */
-  get itemURL() {
-    return 'service-workers://';
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    if (!this._view)
-      this._view = new Resources.ServiceWorkersView();
-    this.showView(this._view);
-    return false;
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.AppManifestTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   */
-  constructor(storagePanel) {
-    super(storagePanel, Common.UIString('Manifest'), false);
-    var icon = UI.Icon.create('mediumicon-manifest', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  /**
-   * @return {string}
-   */
-  get itemURL() {
-    return 'manifest://';
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    if (!this._view)
-      this._view = new Resources.AppManifestView();
-    this.showView(this._view);
-    return false;
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.ClearStorageTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   */
-  constructor(storagePanel) {
-    super(storagePanel, Common.UIString('Clear storage'), false);
-    var icon = UI.Icon.create('mediumicon-clear-storage', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  /**
-   * @return {string}
-   */
-  get itemURL() {
-    return 'clear-storage://';
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    if (!this._view)
-      this._view = new Resources.ClearStorageView(this._storagePanel);
-    this.showView(this._view);
-    return false;
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.IndexedDBTreeElement = class extends Resources.StorageCategoryTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   */
-  constructor(storagePanel) {
-    super(storagePanel, Common.UIString('IndexedDB'), 'IndexedDB');
-    var icon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  _initialize() {
-    SDK.targetManager.addModelListener(
-        Resources.IndexedDBModel, Resources.IndexedDBModel.Events.DatabaseAdded, this._indexedDBAdded, this);
-    SDK.targetManager.addModelListener(
-        Resources.IndexedDBModel, Resources.IndexedDBModel.Events.DatabaseRemoved, this._indexedDBRemoved, this);
-    SDK.targetManager.addModelListener(
-        Resources.IndexedDBModel, Resources.IndexedDBModel.Events.DatabaseLoaded, this._indexedDBLoaded, this);
-    /** @type {!Array.<!Resources.IDBDatabaseTreeElement>} */
-    this._idbDatabaseTreeElements = [];
-
-    var targets = SDK.targetManager.targets(SDK.Target.Capability.Browser);
-    for (var i = 0; i < targets.length; ++i) {
-      var indexedDBModel = Resources.IndexedDBModel.fromTarget(targets[i]);
-      var databases = indexedDBModel.databases();
-      for (var j = 0; j < databases.length; ++j)
-        this._addIndexedDB(indexedDBModel, databases[j]);
-    }
-  }
-
-  /**
-   * @override
-   */
-  onattach() {
-    super.onattach();
-    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
-  }
-
-  _handleContextMenuEvent(event) {
-    var contextMenu = new UI.ContextMenu(event);
-    contextMenu.appendItem(Common.UIString('Refresh IndexedDB'), this.refreshIndexedDB.bind(this));
-    contextMenu.show();
-  }
-
-  refreshIndexedDB() {
-    var targets = SDK.targetManager.targets(SDK.Target.Capability.Browser);
-    for (var i = 0; i < targets.length; ++i)
-      Resources.IndexedDBModel.fromTarget(targets[i]).refreshDatabaseNames();
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _indexedDBAdded(event) {
-    var databaseId = /** @type {!Resources.IndexedDBModel.DatabaseId} */ (event.data.databaseId);
-    var model = /** @type {!Resources.IndexedDBModel} */ (event.data.model);
-    this._addIndexedDB(model, databaseId);
-  }
-
-  /**
-   * @param {!Resources.IndexedDBModel} model
-   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
-   */
-  _addIndexedDB(model, databaseId) {
-    var idbDatabaseTreeElement = new Resources.IDBDatabaseTreeElement(this._storagePanel, model, databaseId);
-    this._idbDatabaseTreeElements.push(idbDatabaseTreeElement);
-    this.appendChild(idbDatabaseTreeElement);
-    model.refreshDatabase(databaseId);
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _indexedDBRemoved(event) {
-    var databaseId = /** @type {!Resources.IndexedDBModel.DatabaseId} */ (event.data.databaseId);
-    var model = /** @type {!Resources.IndexedDBModel} */ (event.data.model);
-
-    var idbDatabaseTreeElement = this._idbDatabaseTreeElement(model, databaseId);
-    if (!idbDatabaseTreeElement)
-      return;
-
-    idbDatabaseTreeElement.clear();
-    this.removeChild(idbDatabaseTreeElement);
-    this._idbDatabaseTreeElements.remove(idbDatabaseTreeElement);
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _indexedDBLoaded(event) {
-    var database = /** @type {!Resources.IndexedDBModel.Database} */ (event.data.database);
-    var model = /** @type {!Resources.IndexedDBModel} */ (event.data.model);
-
-    var idbDatabaseTreeElement = this._idbDatabaseTreeElement(model, database.databaseId);
-    if (!idbDatabaseTreeElement)
-      return;
-
-    idbDatabaseTreeElement.update(database);
-  }
-
-  /**
-   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
-   * @param {!Resources.IndexedDBModel} model
-   * @return {?Resources.IDBDatabaseTreeElement}
-   */
-  _idbDatabaseTreeElement(model, databaseId) {
-    var index = -1;
-    for (var i = 0; i < this._idbDatabaseTreeElements.length; ++i) {
-      if (this._idbDatabaseTreeElements[i]._databaseId.equals(databaseId) &&
-          this._idbDatabaseTreeElements[i]._model === model) {
-        index = i;
-        break;
-      }
-    }
-    if (index !== -1)
-      return this._idbDatabaseTreeElements[i];
-    return null;
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.IDBDatabaseTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   * @param {!Resources.IndexedDBModel} model
-   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
-   */
-  constructor(storagePanel, model, databaseId) {
-    super(storagePanel, databaseId.name + ' - ' + databaseId.securityOrigin, false);
-    this._model = model;
-    this._databaseId = databaseId;
-    this._idbObjectStoreTreeElements = {};
-    var icon = UI.Icon.create('mediumicon-database', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  get itemURL() {
-    return 'indexedDB://' + this._databaseId.securityOrigin + '/' + this._databaseId.name;
-  }
-
-  /**
-   * @override
-   */
-  onattach() {
-    super.onattach();
-    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
-  }
-
-  _handleContextMenuEvent(event) {
-    var contextMenu = new UI.ContextMenu(event);
-    contextMenu.appendItem(Common.UIString('Refresh IndexedDB'), this._refreshIndexedDB.bind(this));
-    contextMenu.show();
-  }
-
-  _refreshIndexedDB() {
-    this._model.refreshDatabaseNames();
-  }
-
-  /**
-   * @param {!Resources.IndexedDBModel.Database} database
-   */
-  update(database) {
-    this._database = database;
-    var objectStoreNames = {};
-    for (var objectStoreName in this._database.objectStores) {
-      var objectStore = this._database.objectStores[objectStoreName];
-      objectStoreNames[objectStore.name] = true;
-      if (!this._idbObjectStoreTreeElements[objectStore.name]) {
-        var idbObjectStoreTreeElement =
-            new Resources.IDBObjectStoreTreeElement(this._storagePanel, this._model, this._databaseId, objectStore);
-        this._idbObjectStoreTreeElements[objectStore.name] = idbObjectStoreTreeElement;
-        this.appendChild(idbObjectStoreTreeElement);
-      }
-      this._idbObjectStoreTreeElements[objectStore.name].update(objectStore);
-    }
-    for (var objectStoreName in this._idbObjectStoreTreeElements) {
-      if (!objectStoreNames[objectStoreName])
-        this._objectStoreRemoved(objectStoreName);
-    }
-
-    if (this._view)
-      this._view.update(database);
-
-    this._updateTooltip();
-  }
-
-  _updateTooltip() {
-    this.tooltip = Common.UIString('Version') + ': ' + this._database.version;
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    if (!this._view)
-      this._view = new Resources.IDBDatabaseView(this._model, this._database);
-
-    this.showView(this._view);
-    return false;
-  }
-
-  /**
-   * @param {string} objectStoreName
-   */
-  _objectStoreRemoved(objectStoreName) {
-    var objectStoreTreeElement = this._idbObjectStoreTreeElements[objectStoreName];
-    objectStoreTreeElement.clear();
-    this.removeChild(objectStoreTreeElement);
-    delete this._idbObjectStoreTreeElements[objectStoreName];
-  }
-
-  clear() {
-    for (var objectStoreName in this._idbObjectStoreTreeElements)
-      this._objectStoreRemoved(objectStoreName);
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.IDBObjectStoreTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   * @param {!Resources.IndexedDBModel} model
-   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
-   * @param {!Resources.IndexedDBModel.ObjectStore} objectStore
-   */
-  constructor(storagePanel, model, databaseId, objectStore) {
-    super(storagePanel, objectStore.name, false);
-    this._model = model;
-    this._databaseId = databaseId;
-    this._idbIndexTreeElements = {};
-    var icon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  get itemURL() {
-    return 'indexedDB://' + this._databaseId.securityOrigin + '/' + this._databaseId.name + '/' +
-        this._objectStore.name;
-  }
-
-  /**
-   * @override
-   */
-  onattach() {
-    super.onattach();
-    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
-  }
-
-  _handleContextMenuEvent(event) {
-    var contextMenu = new UI.ContextMenu(event);
-    contextMenu.appendItem(Common.UIString('Clear'), this._clearObjectStore.bind(this));
-    contextMenu.show();
-  }
-
-  _clearObjectStore() {
-    /**
-     * @this {Resources.IDBObjectStoreTreeElement}
-     */
-    function callback() {
-      this.update(this._objectStore);
-    }
-    this._model.clearObjectStore(this._databaseId, this._objectStore.name, callback.bind(this));
-  }
-
-  /**
-   * @param {!Resources.IndexedDBModel.ObjectStore} objectStore
-   */
-  update(objectStore) {
-    this._objectStore = objectStore;
-
-    var indexNames = {};
-    for (var indexName in this._objectStore.indexes) {
-      var index = this._objectStore.indexes[indexName];
-      indexNames[index.name] = true;
-      if (!this._idbIndexTreeElements[index.name]) {
-        var idbIndexTreeElement = new Resources.IDBIndexTreeElement(
-            this._storagePanel, this._model, this._databaseId, this._objectStore, index);
-        this._idbIndexTreeElements[index.name] = idbIndexTreeElement;
-        this.appendChild(idbIndexTreeElement);
-      }
-      this._idbIndexTreeElements[index.name].update(index);
-    }
-    for (var indexName in this._idbIndexTreeElements) {
-      if (!indexNames[indexName])
-        this._indexRemoved(indexName);
-    }
-    for (var indexName in this._idbIndexTreeElements) {
-      if (!indexNames[indexName]) {
-        this.removeChild(this._idbIndexTreeElements[indexName]);
-        delete this._idbIndexTreeElements[indexName];
-      }
-    }
-
-    if (this.childCount())
-      this.expand();
-
-    if (this._view)
-      this._view.update(this._objectStore);
-
-    this._updateTooltip();
-  }
-
-  _updateTooltip() {
-    var keyPathString = this._objectStore.keyPathString;
-    var tooltipString = keyPathString !== null ? (Common.UIString('Key path: ') + keyPathString) : '';
-    if (this._objectStore.autoIncrement)
-      tooltipString += '\n' + Common.UIString('autoIncrement');
-    this.tooltip = tooltipString;
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    if (!this._view)
-      this._view = new Resources.IDBDataView(this._model, this._databaseId, this._objectStore, null);
-
-    this.showView(this._view);
-    return false;
-  }
-
-  /**
-   * @param {string} indexName
-   */
-  _indexRemoved(indexName) {
-    var indexTreeElement = this._idbIndexTreeElements[indexName];
-    indexTreeElement.clear();
-    this.removeChild(indexTreeElement);
-    delete this._idbIndexTreeElements[indexName];
-  }
-
-  clear() {
-    for (var indexName in this._idbIndexTreeElements)
-      this._indexRemoved(indexName);
-    if (this._view)
-      this._view.clear();
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.IDBIndexTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   * @param {!Resources.IndexedDBModel} model
-   * @param {!Resources.IndexedDBModel.DatabaseId} databaseId
-   * @param {!Resources.IndexedDBModel.ObjectStore} objectStore
-   * @param {!Resources.IndexedDBModel.Index} index
-   */
-  constructor(storagePanel, model, databaseId, objectStore, index) {
-    super(storagePanel, index.name, false);
-    this._model = model;
-    this._databaseId = databaseId;
-    this._objectStore = objectStore;
-    this._index = index;
-  }
-
-  get itemURL() {
-    return 'indexedDB://' + this._databaseId.securityOrigin + '/' + this._databaseId.name + '/' +
-        this._objectStore.name + '/' + this._index.name;
-  }
-
-  /**
-   * @param {!Resources.IndexedDBModel.Index} index
-   */
-  update(index) {
-    this._index = index;
-
-    if (this._view)
-      this._view.update(this._index);
-
-    this._updateTooltip();
-  }
-
-  _updateTooltip() {
-    var tooltipLines = [];
-    var keyPathString = this._index.keyPathString;
-    tooltipLines.push(Common.UIString('Key path: ') + keyPathString);
-    if (this._index.unique)
-      tooltipLines.push(Common.UIString('unique'));
-    if (this._index.multiEntry)
-      tooltipLines.push(Common.UIString('multiEntry'));
-    this.tooltip = tooltipLines.join('\n');
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    if (!this._view)
-      this._view = new Resources.IDBDataView(this._model, this._databaseId, this._objectStore, this._index);
-
-    this.showView(this._view);
-    return false;
-  }
-
-  clear() {
-    if (this._view)
-      this._view.clear();
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.DOMStorageTreeElement = class extends Resources.BaseStorageTreeElement {
-  constructor(storagePanel, domStorage) {
-    super(storagePanel, domStorage.securityOrigin ? domStorage.securityOrigin : Common.UIString('Local Files'), false);
-    this._domStorage = domStorage;
-    var icon = UI.Icon.create('mediumicon-table', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  get itemURL() {
-    return 'storage://' + this._domStorage.securityOrigin + '/' +
-        (this._domStorage.isLocalStorage ? 'local' : 'session');
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    this._storagePanel._showDOMStorage(this._domStorage);
-    return false;
-  }
-
-  /**
-   * @override
-   */
-  onattach() {
-    super.onattach();
-    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
-  }
-
-  _handleContextMenuEvent(event) {
-    var contextMenu = new UI.ContextMenu(event);
-    contextMenu.appendItem(Common.UIString('Clear'), () => this._domStorage.clear());
-    contextMenu.show();
-  }
-};
-
-Resources.CookieTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   * @param {!SDK.ResourceTreeFrame} frame
-   * @param {string} cookieDomain
-   */
-  constructor(storagePanel, frame, cookieDomain) {
-    super(storagePanel, cookieDomain ? cookieDomain : Common.UIString('Local Files'), false);
-    this._target = frame.target();
-    this._cookieDomain = cookieDomain;
-    var icon = UI.Icon.create('mediumicon-cookie', 'resource-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  get itemURL() {
-    return 'cookies://' + this._cookieDomain;
-  }
-
-  /**
-   * @override
-   */
-  onattach() {
-    super.onattach();
-    this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
-  }
-
-  /**
-   * @param {!Event} event
-   */
-  _handleContextMenuEvent(event) {
-    var contextMenu = new UI.ContextMenu(event);
-    contextMenu.appendItem(
-        Common.UIString('Clear'), () => this._storagePanel._clearCookies(this._target, this._cookieDomain));
-    contextMenu.show();
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    this._storagePanel.showCookies(this, this._cookieDomain, this._target);
-    return false;
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.ApplicationCacheManifestTreeElement = class extends Resources.BaseStorageTreeElement {
-  constructor(storagePanel, manifestURL) {
-    var title = new Common.ParsedURL(manifestURL).displayName;
-    super(storagePanel, title, false);
-    this.tooltip = manifestURL;
-    this._manifestURL = manifestURL;
-  }
-
-  get itemURL() {
-    return 'appcache://' + this._manifestURL;
-  }
-
-  get manifestURL() {
-    return this._manifestURL;
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    this._storagePanel.showCategoryView(this._manifestURL);
-    return false;
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.ApplicationCacheFrameTreeElement = class extends Resources.BaseStorageTreeElement {
-  /**
-   * @param {!Resources.ResourcesPanel} storagePanel
-   * @param {!Protocol.Page.FrameId} frameId
-   * @param {string} manifestURL
-   */
-  constructor(storagePanel, frameId, manifestURL) {
-    super(storagePanel, '', false);
-    this._frameId = frameId;
-    this._manifestURL = manifestURL;
-    this._refreshTitles();
-
-    var icon = UI.Icon.create('largeicon-navigator-folder', 'navigator-tree-item');
-    icon.classList.add('navigator-folder-tree-item');
-    this.setLeadingIcons([icon]);
-  }
-
-  get itemURL() {
-    return 'appcache://' + this._manifestURL + '/' + encodeURI(this.titleAsText());
-  }
-
-  get frameId() {
-    return this._frameId;
-  }
-
-  get manifestURL() {
-    return this._manifestURL;
-  }
-
-  _refreshTitles() {
-    var resourceTreeModel = SDK.ResourceTreeModel.fromTarget(this._storagePanel._target);
-    var frame = resourceTreeModel.frameForId(this._frameId);
-    this.title = frame.displayName();
-  }
-
-  frameNavigated() {
-    this._refreshTitles();
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  onselect(selectedByUser) {
-    super.onselect(selectedByUser);
-    this._storagePanel.showApplicationCache(this._frameId);
-    return false;
-  }
-};
-
-/**
- * @unrestricted
- */
-Resources.StorageCategoryView = class extends UI.VBox {
-  constructor() {
-    super();
-
-    this.element.classList.add('storage-view');
-    this._emptyWidget = new UI.EmptyWidget('');
-    this._emptyWidget.show(this.element);
-  }
-
-  setText(text) {
-    this._emptyWidget.text = text;
-  }
-};
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/module.json b/third_party/WebKit/Source/devtools/front_end/resources/module.json
index 6531547e..99e22449 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/resources/module.json
@@ -40,6 +40,7 @@
         "IndexedDBModel.js",
         "IndexedDBViews.js",
         "ResourcesPanel.js",
+        "ApplicationPanelSidebar.js",
         "ResourcesSection.js",
         "ServiceWorkerCacheViews.js",
         "ServiceWorkersView.js"
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
index b6d4378f..3ff7d632 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
@@ -1847,13 +1847,15 @@
 
   /**
    * @param {!SDK.RemoteObject} object
-   * @param {function(?SDK.DOMNode)} callback
+   * @return {!Promise<?SDK.DOMNode>}
    */
-  pushObjectAsNodeToFrontend(object, callback) {
-    if (object.isNode())
-      this.pushNodeToFrontend(/** @type {string} */ (object.objectId), callback);
-    else
-      callback(null);
+  pushObjectAsNodeToFrontend(object) {
+    return new Promise(fulfill => {
+      if (object.isNode())
+        this.pushNodeToFrontend(/** @type {string} */ (object.objectId), fulfill);
+      else
+        fulfill(null);
+    });
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
index 6dbd6449..2e65110 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
@@ -84,19 +84,6 @@
   }
 
   /**
-   * @param {!Protocol.Runtime.ObjectPreview} preview
-   * @return {number}
-   */
-  static mapOrSetEntriesCount(preview) {
-    if (preview.subtype !== 'map' && preview.subtype !== 'set')
-      return 0;
-    var matches = preview.description.match(SDK.RemoteObject._descriptionLengthParenRegex);
-    if (!matches)
-      return 0;
-    return parseInt(matches[1], 10);
-  }
-
-  /**
    * @param {!Protocol.Runtime.RemoteObject|!SDK.RemoteObject|number|string|boolean|undefined|null} object
    * @return {!Protocol.Runtime.CallArgument}
    */
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
index 06160f5..6ea5c477 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
@@ -490,7 +490,7 @@
     this._queryRange = new Common.TextRange(
         0, beforeRange.toString().length, 0, beforeRange.toString().length + fullWordRange.toString().length);
 
-    var shouldSelect = !this._disableDefaultSuggestionForEmptyInput || this.text();
+    var shouldSelect = !this._disableDefaultSuggestionForEmptyInput || !!this.text();
     if (this._suggestBox) {
       this._suggestBox.updateSuggestions(
           this._boxForAnchorAtStart(selection, fullWordRange), completions, shouldSelect, !this._isCaretAtEndOfPrompt(),
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/inspectorStyle.css b/third_party/WebKit/Source/devtools/front_end/ui/inspectorStyle.css
index 0d55955..681f319c 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/inspectorStyle.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/inspectorStyle.css
@@ -48,7 +48,7 @@
 
 .platform-linux {
     color: rgb(48, 57, 66);
-    font-family: Ubuntu, Arial, sans-serif;
+    font-family: Roboto, Ubuntu, Arial, sans-serif;
 }
 
 .platform-mac {
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
index 5a8c0c66..cb81f55 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -524,10 +524,6 @@
   return blink::freshnessLifetime(response(), m_responseTimestamp);
 }
 
-double Resource::stalenessLifetime() const {
-  return response().cacheControlStaleWhileRevalidate();
-}
-
 static bool canUseResponse(const ResourceResponse& response,
                            double responseTimestamp) {
   if (response.isNull())
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.h b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
index cbd4c0f7..0ff68ed 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
@@ -282,7 +282,6 @@
 
   double currentAge() const;
   double freshnessLifetime() const;
-  double stalenessLifetime() const;
 
   bool isAlive() const { return m_isAlive; }
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index f7fcd772..596adba 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -699,16 +699,6 @@
   if (!eTag.isEmpty())
     revalidatingRequest.setHTTPHeaderField(HTTPNames::If_None_Match, eTag);
 
-  double stalenessLifetime = resource->stalenessLifetime();
-  if (std::isfinite(stalenessLifetime) && stalenessLifetime > 0) {
-    revalidatingRequest.setHTTPHeaderField(
-        HTTPNames::Resource_Freshness,
-        AtomicString(String::format(
-            "max-age=%.0lf,stale-while-revalidate=%.0lf,age=%.0lf",
-            resource->freshnessLifetime(), stalenessLifetime,
-            resource->currentAge())));
-  }
-
   resource->setRevalidatingRequest(revalidatingRequest);
 }
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
index ffeb3fd..951732d 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
@@ -453,15 +453,6 @@
   return m_cacheControlHeader.maxAge;
 }
 
-double ResourceResponse::cacheControlStaleWhileRevalidate() const {
-  if (!m_cacheControlHeader.parsed) {
-    m_cacheControlHeader =
-        parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeader),
-                                    m_httpHeaderFields.get(pragmaHeader));
-  }
-  return m_cacheControlHeader.staleWhileRevalidate;
-}
-
 static double parseDateValueInHeader(const HTTPHeaderMap& headers,
                                      const AtomicString& headerName) {
   const AtomicString& headerValue = headers.get(headerName);
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
index f6ccce6f..f2cc0373 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
@@ -197,7 +197,6 @@
   bool cacheControlContainsMustRevalidate() const;
   bool hasCacheValidatorFields() const;
   double cacheControlMaxAge() const;
-  double cacheControlStaleWhileRevalidate() const;
   double date() const;
   double age() const;
   double expires() const;
diff --git a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
index e0928aa..d94093a 100644
--- a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
+++ b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
@@ -700,14 +700,11 @@
   CacheControlHeader cacheControlHeader;
   cacheControlHeader.parsed = true;
   cacheControlHeader.maxAge = std::numeric_limits<double>::quiet_NaN();
-  cacheControlHeader.staleWhileRevalidate =
-      std::numeric_limits<double>::quiet_NaN();
 
   static const char noCacheDirective[] = "no-cache";
   static const char noStoreDirective[] = "no-store";
   static const char mustRevalidateDirective[] = "must-revalidate";
   static const char maxAgeDirective[] = "max-age";
-  static const char staleWhileRevalidateDirective[] = "stale-while-revalidate";
 
   if (!cacheControlValue.isEmpty()) {
     Vector<std::pair<String, String>> directives;
@@ -734,17 +731,6 @@
         double maxAge = directives[i].second.toDouble(&ok);
         if (ok)
           cacheControlHeader.maxAge = maxAge;
-      } else if (equalIgnoringCase(directives[i].first,
-                                   staleWhileRevalidateDirective)) {
-        if (!std::isnan(cacheControlHeader.staleWhileRevalidate)) {
-          // First stale-while-revalidate directive wins if there are multiple
-          // ones.
-          continue;
-        }
-        bool ok;
-        double staleWhileRevalidate = directives[i].second.toDouble(&ok);
-        if (ok)
-          cacheControlHeader.staleWhileRevalidate = staleWhileRevalidate;
       }
     }
   }
diff --git a/third_party/WebKit/Source/platform/network/HTTPParsers.h b/third_party/WebKit/Source/platform/network/HTTPParsers.h
index f6b2b5f..a2094bf 100644
--- a/third_party/WebKit/Source/platform/network/HTTPParsers.h
+++ b/third_party/WebKit/Source/platform/network/HTTPParsers.h
@@ -79,15 +79,13 @@
   bool containsNoStore : 1;
   bool containsMustRevalidate : 1;
   double maxAge;
-  double staleWhileRevalidate;
 
   CacheControlHeader()
       : parsed(false),
         containsNoCache(false),
         containsNoStore(false),
         containsMustRevalidate(false),
-        maxAge(0.0),
-        staleWhileRevalidate(0.0) {}
+        maxAge(0.0) {}
 };
 
 PLATFORM_EXPORT ContentDispositionType getContentDispositionType(const String&);
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner.py
index 56f7982..295d5f1 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner.py
@@ -275,6 +275,8 @@
             test_input.should_run_pixel_test = True
         else:
             test_input.should_run_pixel_test = self._port.should_run_as_pixel_test(test_input)
+        test_input.should_run_pixel_test_first = (
+            self._port.should_run_pixel_test_first(test_input))
 
     def _run_test(self, test_input, shard_name):
         self._batch_count += 1
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
index a79ed87..1804e07 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
@@ -70,6 +70,7 @@
         self._worker_name = worker_name
         self._test_name = test_input.test_name
         self._should_run_pixel_test = test_input.should_run_pixel_test
+        self._should_run_pixel_test_first = test_input.should_run_pixel_test_first
         self._reference_files = test_input.reference_files
         self._should_add_missing_baselines = test_input.should_add_missing_baselines
         self._stop_when_done = stop_when_done
@@ -283,11 +284,27 @@
         is_testharness_test, testharness_failures = self._compare_testharness_test(driver_output, expected_driver_output)
         if is_testharness_test:
             failures.extend(testharness_failures)
+
+        compare_functions = []
+        compare_image_fn = (self._compare_image, (expected_driver_output, driver_output))
+        compare_txt_fn = (self._compare_text, (expected_driver_output.text, driver_output.text))
+        compare_audio_fn = (self._compare_audio, (expected_driver_output.audio, driver_output.audio))
+
+        if self._should_run_pixel_test_first:
+            if driver_output.image_hash and self._should_run_pixel_test:
+                compare_functions.append(compare_image_fn)
+            elif not is_testharness_test:
+                compare_functions.append(compare_txt_fn)
         else:
-            failures.extend(self._compare_text(expected_driver_output.text, driver_output.text))
-        failures.extend(self._compare_audio(expected_driver_output.audio, driver_output.audio))
-        if self._should_run_pixel_test:
-            failures.extend(self._compare_image(expected_driver_output, driver_output))
+            if not is_testharness_test:
+                compare_functions.append(compare_txt_fn)
+            if self._should_run_pixel_test:
+                compare_functions.append(compare_image_fn)
+        compare_functions.append(compare_audio_fn)
+
+        for func, args in compare_functions:
+            failures.extend(func(*args))
+
         has_repaint_overlay = (repaint_overlay.result_contains_repaint_rects(expected_driver_output.text) or
                                repaint_overlay.result_contains_repaint_rects(driver_output.text))
         return TestResult(self._test_name, failures, driver_output.test_time, driver_output.has_stderr(),
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
index f6ee2901..503421b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -1569,6 +1569,10 @@
             return False
         return True
 
+    def should_run_pixel_test_first(self, test_input):
+        return any(test_input.test_name.startswith(
+            directory) for directory in self._options.image_first_tests)
+
     def _convert_path(self, path):
         """Handles filename conversion for subprocess command line args."""
         # See note above in diff_image() for why we need this.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
index d4f23c9..f999f5c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -235,6 +235,15 @@
                 dest='smoke',
                 action='store_false',
                 help='Do not run just the SmokeTests'),
+            optparse.make_option(
+                '--image-first-tests',
+                action='append',
+                default=[],
+                dest='image_first_tests',
+                help=('A directory (or test) where the test result will only be compared with the '
+                      'image baseline if an image baseline is available, and fall back to comparison '
+                      'with the text baseline when image baselines are missing. Specify multiple times '
+                      'to add multiple directories/tests.')),
         ]))
 
     option_group_definitions.append(
diff --git a/tools/json_schema_compiler/js_externs_generator_test.py b/tools/json_schema_compiler/js_externs_generator_test.py
index 88c2a09f..fe7ab688d 100755
--- a/tools/json_schema_compiler/js_externs_generator_test.py
+++ b/tools/json_schema_compiler/js_externs_generator_test.py
@@ -63,6 +63,8 @@
 
   callback BazGreekCallback = void(Baz baz, Greek greek);
 
+  callback OptionalParamCallback = void(optional Qux qux);
+
   interface Functions {
     // Does something exciting! And what's more, this is a multiline function
     // comment! It goes onto multiple lines!
@@ -75,6 +77,8 @@
     static void bazGreek(optional BazGreekCallback callback);
 
     [deprecated="Use a new method."] static DOMString returnString();
+
+    static void optionalParam(optional OptionalParamCallback callback);
   };
 
   interface Events {
@@ -205,6 +209,12 @@
 chrome.fakeApi.returnString = function() {};
 
 /**
+ * @param {function(!chrome.fakeApi.Qux|undefined):void=} callback
+ * @see https://developer.chrome.com/extensions/fakeApi#method-optionalParam
+ */
+chrome.fakeApi.optionalParam = function(callback) {};
+
+/**
  * Fired when we realize it's a trap!
  * @type {!ChromeEvent}
  * @see https://developer.chrome.com/extensions/fakeApi#event-onTrapDetected
diff --git a/tools/json_schema_compiler/js_util.py b/tools/json_schema_compiler/js_util.py
index e563b88..064b40b 100644
--- a/tools/json_schema_compiler/js_util.py
+++ b/tools/json_schema_compiler/js_util.py
@@ -119,6 +119,8 @@
     c.Append('function(')
     for i, param in enumerate(function.params):
       c.Concat(self._TypeToJsType(namespace_name, param.type_), new_line=False)
+      if param.optional:
+        c.Append('|undefined', new_line=False)
       if i is not len(function.params) - 1:
         c.Append(', ', new_line=False, strip_right=False)
     c.Append('):', new_line=False)
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 7db750c3..887eb9b 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -4460,6 +4460,7 @@
 <action name="FirstRunDef_Accept">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
+  <obsolete>Deprecated 02/2017.</obsolete>
 </action>
 
 <action name="Flash.JavaScriptUsed" not_user_triggered="true">
diff --git a/ui/OWNERS b/ui/OWNERS
index 79875b5..7eb8966a 100644
--- a/ui/OWNERS
+++ b/ui/OWNERS
@@ -6,10 +6,6 @@
 avi@chromium.org
 ccameron@chromium.org
 
-per-file *.isolate=maruel@chromium.org
-per-file *.isolate=tandrii@chromium.org
-per-file *.isolate=vadimsh@chromium.org
-
 # If you're doing structural changes get a review from one of the OWNERS.
 per-file *.gyp*=*
 per-file BUILD.gn=*
diff --git a/ui/aura/mus/window_port_mus.cc b/ui/aura/mus/window_port_mus.cc
index 2d50370..1ad03c8 100644
--- a/ui/aura/mus/window_port_mus.cc
+++ b/ui/aura/mus/window_port_mus.cc
@@ -271,8 +271,16 @@
 void WindowPortMus::SetFrameSinkIdFromServer(
     const cc::FrameSinkId& frame_sink_id) {
   frame_sink_id_ = frame_sink_id;
-  if (!pending_compositor_frame_sink_request_.is_null())
+  if (!pending_compositor_frame_sink_request_.is_null()) {
+    // TOP_LEVEL_IN_WM, and EMBED_IN_OWNER windows should not be requesting
+    // CompositorFrameSinks.
+    DCHECK_NE(WindowMusType::TOP_LEVEL_IN_WM, window_mus_type());
+    DCHECK_NE(WindowMusType::EMBED_IN_OWNER, window_mus_type());
     base::ResetAndReturn(&pending_compositor_frame_sink_request_).Run();
+  }
+  // TODO(fsamuel): If the window type is TOP_LEVEL_IN_WM or EMBED_IN_OWNER then
+  // we should check if we have a cc::LocalSurfaeId ready as well. If we do,
+  // then we are ready to embed.
 }
 
 void WindowPortMus::SetSurfaceInfoFromServer(
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 8cc1db0..5037dab 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -920,6 +920,16 @@
   capture_synchronizer_->SetCaptureFromServer(new_capture_window);
 }
 
+void WindowTreeClient::OnFrameSinkIdAllocated(
+    Id window_id,
+    const cc::FrameSinkId& frame_sink_id) {
+  WindowMus* window = GetWindowByServerId(window_id);
+  if (!window)
+    return;
+
+  window->SetFrameSinkIdFromServer(frame_sink_id);
+}
+
 void WindowTreeClient::OnTopLevelCreated(uint32_t change_id,
                                          ui::mojom::WindowDataPtr data,
                                          int64_t display_id,
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h
index 8c9c8098..130d90c 100644
--- a/ui/aura/mus/window_tree_client.h
+++ b/ui/aura/mus/window_tree_client.h
@@ -319,6 +319,8 @@
   void OnUnembed(Id window_id) override;
   void OnCaptureChanged(Id new_capture_window_id,
                         Id old_capture_window_id) override;
+  void OnFrameSinkIdAllocated(Id window_id,
+                              const cc::FrameSinkId& frame_sink_id) override;
   void OnTopLevelCreated(uint32_t change_id,
                          ui::mojom::WindowDataPtr data,
                          int64_t display_id,
diff --git a/ui/base/OWNERS b/ui/base/OWNERS
index b6ad79f1..498d1734 100644
--- a/ui/base/OWNERS
+++ b/ui/base/OWNERS
@@ -1,7 +1,3 @@
-per-file *.isolate=maruel@chromium.org
-per-file *.isolate=tandrii@chromium.org
-per-file *.isolate=vadimsh@chromium.org
-
 per-file template_expressions*=dschuyler@chromium.org
 
 # If you're doing structural changes get a review from one of the ui/OWNERS.
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc
index 60f0077..cef5c86 100644
--- a/ui/gfx/canvas.cc
+++ b/ui/gfx/canvas.cc
@@ -29,25 +29,10 @@
 
 namespace gfx {
 
-namespace {
-
-sk_sp<cc::PaintSurface> CreateSurface(const Size& size, bool is_opaque) {
-  // SkSurface cannot be zero-sized, but clients of Canvas sometimes request
-  // that (and then later resize).
-  int width = std::max(size.width(), 1);
-  int height = std::max(size.height(), 1);
-  SkAlphaType alpha = is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
-  SkImageInfo info = SkImageInfo::MakeN32(width, height, alpha);
-  return cc::PaintSurface::MakeRaster(info);
-}
-
-}  // namespace
-
 Canvas::Canvas(const Size& size, float image_scale, bool is_opaque)
     : image_scale_(image_scale) {
   Size pixel_size = ScaleToCeiledSize(size, image_scale);
-  surface_ = CreateSurface(pixel_size, is_opaque);
-  canvas_ = surface_->getCanvas();
+  canvas_ = CreateOwnedCanvas(pixel_size, is_opaque);
 
 #if !defined(USE_CAIRO)
   // skia::PlatformCanvas instances are initialized to 0 by Cairo, but
@@ -61,9 +46,7 @@
 }
 
 Canvas::Canvas()
-    : image_scale_(1.f),
-      surface_(CreateSurface({0, 0}, false)),
-      canvas_(surface_->getCanvas()) {}
+    : image_scale_(1.f), canvas_(CreateOwnedCanvas({0, 0}, false)) {}
 
 Canvas::Canvas(cc::PaintCanvas* canvas, float image_scale)
     : image_scale_(image_scale), canvas_(canvas) {
@@ -78,8 +61,7 @@
                                    bool is_opaque) {
   image_scale_ = image_scale;
   Size pixel_size = ScaleToFlooredSize(size, image_scale);
-  surface_ = CreateSurface(pixel_size, is_opaque);
-  canvas_ = surface_->getCanvas();
+  canvas_ = CreateOwnedCanvas(pixel_size, is_opaque);
 
   SkScalar scale_scalar = SkFloatToScalar(image_scale);
   canvas_->scale(scale_scalar, scale_scalar);
@@ -558,10 +540,16 @@
   canvas_->concat(transform.matrix());
 }
 
-SkBitmap Canvas::ToBitmap() {
-  SkBitmap bitmap;
-  bitmap.setInfo(canvas_->imageInfo());
-  canvas_->readPixels(&bitmap, 0, 0);
+SkBitmap Canvas::GetBitmap() const {
+  DCHECK(bitmap_);
+  SkBitmap bitmap = bitmap_.value();
+  // When the bitmap is copied, it shares the underlying pixelref, but doesn't
+  // initialize pixels unless they are locked. Hence, ensure that the returned
+  // bitmap keeps the pixelref alive by locking it. Note that the dtor of
+  // SkBitmap will unlock the pixelrefs, so this won't leak. Also note that
+  // moving SkBitmap retains the same lock as the source, so the caller
+  // will receive a locked-pixels bitmap.
+  bitmap.lockPixels();
   return bitmap;
 }
 
@@ -619,4 +607,21 @@
   canvas_->drawRect(dest_rect, flags);
 }
 
+cc::PaintCanvas* Canvas::CreateOwnedCanvas(const Size& size, bool is_opaque) {
+  // SkBitmap cannot be zero-sized, but clients of Canvas sometimes request
+  // that (and then later resize).
+  int width = std::max(size.width(), 1);
+  int height = std::max(size.height(), 1);
+  SkAlphaType alpha = is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+  SkImageInfo info = SkImageInfo::MakeN32(width, height, alpha);
+
+  bitmap_.emplace();
+  bitmap_->allocPixels(info);
+  // Ensure that the bitmap is zeroed, since the code expects that.
+  memset(bitmap_->getPixels(), 0, bitmap_->getSafeSize());
+
+  owned_canvas_ = cc::SkiaPaintCanvas(bitmap_.value());
+  return &owned_canvas_.value();
+}
+
 }  // namespace gfx
diff --git a/ui/gfx/canvas.h b/ui/gfx/canvas.h
index 4fcb4bc..27c9751 100644
--- a/ui/gfx/canvas.h
+++ b/ui/gfx/canvas.h
@@ -11,10 +11,11 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/strings/string16.h"
 #include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_flags.h"
-#include "cc/paint/paint_surface.h"
+#include "cc/paint/skia_paint_canvas.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/text_constants.h"
@@ -471,7 +472,8 @@
                        const Rect& display_rect,
                        int flags);
 
-  SkBitmap ToBitmap();
+  // Note that writing to this bitmap will modify pixels stored in this canvas.
+  SkBitmap GetBitmap() const;
 
   // TODO(enne): rename sk_canvas members and interface.
   cc::PaintCanvas* sk_canvas() { return canvas_; }
@@ -496,6 +498,7 @@
                           bool filter,
                           const cc::PaintFlags& flags,
                           bool remove_image_scale);
+  cc::PaintCanvas* CreateOwnedCanvas(const Size& size, bool is_opaque);
 
   // The device scale factor at which drawing on this canvas occurs.
   // An additional scale can be applied via Canvas::Scale(). However,
@@ -503,10 +506,11 @@
   float image_scale_;
 
   // canvas_ is our active canvas object. Sometimes we are also the owner,
-  // in which case surface_ will be set. Other times we are just
-  // borrowing someone else's canvas, in which case canvas_ will point there
-  // but surface_ will be null.
-  sk_sp<cc::PaintSurface> surface_;
+  // in which case bitmap_ and owned_canvas_ will be set. Other times we are
+  // just borrowing someone else's canvas, in which case canvas_ will point
+  // there but bitmap_ and owned_canvas_ will not exist.
+  base::Optional<SkBitmap> bitmap_;
+  base::Optional<cc::SkiaPaintCanvas> owned_canvas_;
   cc::PaintCanvas* canvas_;
 
   DISALLOW_COPY_AND_ASSIGN(Canvas);
diff --git a/ui/gfx/canvas_paint_mac.mm b/ui/gfx/canvas_paint_mac.mm
index ab7dda21..6123d915 100644
--- a/ui/gfx/canvas_paint_mac.mm
+++ b/ui/gfx/canvas_paint_mac.mm
@@ -23,20 +23,11 @@
 
 CanvasSkiaPaint::~CanvasSkiaPaint() {
   if (!is_empty()) {
-    cc::PaintCanvas* canvas = sk_canvas();
-    canvas->restoreToCount(1);
+    sk_canvas()->restoreToCount(1);
 
     // Blit the dirty rect to the current context.
-    SkPixmap pixmap;
-    // TODO(enne): make this class record directly into a bitmap and
-    // remove this peekPixels call.
-    bool success = canvas->peekPixels(&pixmap);
-    DCHECK(success);
-    SkBitmap bitmap;
-    success = bitmap.installPixels(pixmap);
-    DCHECK(success);
     CGImageRef image = SkCreateCGImageRefWithColorspace(
-        bitmap, base::mac::GetSystemColorSpace());
+        GetBitmap(), base::mac::GetSystemColorSpace());
     CGRect dest_rect = NSRectToCGRect(rectangle_);
 
     CGContextRef destination_context =
diff --git a/ui/gfx/color_analysis_unittest.cc b/ui/gfx/color_analysis_unittest.cc
index 929d01d..32444db 100644
--- a/ui/gfx/color_analysis_unittest.cc
+++ b/ui/gfx/color_analysis_unittest.cc
@@ -345,7 +345,7 @@
   canvas.FillRect(gfx::Rect(150, 0, 50, 200), SkColorSetRGB(0, 100, 100));
   canvas.FillRect(gfx::Rect(200, 0, 50, 200), SkColorSetRGB(0, 0, 100));
 
-  gfx::Matrix3F covariance = ComputeColorCovariance(canvas.ToBitmap());
+  gfx::Matrix3F covariance = ComputeColorCovariance(canvas.GetBitmap());
 
   gfx::Matrix3F expected_covariance = gfx::Matrix3F::Zeros();
   expected_covariance.set(2400, 400, -1600,
@@ -402,7 +402,7 @@
   // The image consists of vertical non-overlapping stripes 150 pixels wide.
   canvas.FillRect(gfx::Rect(0, 0, 150, 200), SkColorSetRGB(0, 0, 0));
   canvas.FillRect(gfx::Rect(150, 0, 150, 200), SkColorSetRGB(255, 255, 255));
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
   SkBitmap result;
   result.allocPixels(SkImageInfo::MakeA8(300, 200));
 
@@ -439,7 +439,7 @@
   canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(100, 0, 0));
   canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(0, 255, 0));
   canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(0, 0, 128));
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
   SkBitmap result;
   result.allocPixels(SkImageInfo::MakeA8(300, 200));
 
@@ -481,7 +481,7 @@
   canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(10, 10, 10));
   canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(100, 100, 100));
   canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(255, 255, 255));
-  SkBitmap source = canvas.ToBitmap();
+  SkBitmap source = canvas.GetBitmap();
   SkBitmap result;
   result.allocPixels(SkImageInfo::MakeA8(300, 200));
 
@@ -514,7 +514,7 @@
   // close to black.
   gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true);
   canvas.FillRect(gfx::Rect(0, 0, 300, 200), SkColorSetRGB(10, 10, 10));
-  SkBitmap bitmap = canvas.ToBitmap();
+  SkBitmap bitmap = canvas.GetBitmap();
 
   // All expectations start at SK_ColorTRANSPARENT (i.e. 0).
   SkColor expectations[arraysize(color_profiles)] = {};
@@ -527,7 +527,7 @@
   // Add a green that could hit a couple values.
   const SkColor kVibrantGreen = SkColorSetRGB(25, 200, 25);
   canvas.FillRect(gfx::Rect(0, 1, 300, 1), kVibrantGreen);
-  bitmap = canvas.ToBitmap();
+  bitmap = canvas.GetBitmap();
   expectations[0] = kVibrantGreen;
   expectations[1] = kVibrantGreen;
   for (size_t i = 0; i < arraysize(color_profiles); ++i) {
@@ -539,7 +539,7 @@
   // Add a stripe of a dark, muted green (saturation .33, luma .29).
   const SkColor kDarkGreen = SkColorSetRGB(50, 100, 50);
   canvas.FillRect(gfx::Rect(0, 2, 300, 1), kDarkGreen);
-  bitmap = canvas.ToBitmap();
+  bitmap = canvas.GetBitmap();
   expectations[3] = kDarkGreen;
   for (size_t i = 0; i < arraysize(color_profiles); ++i) {
     EXPECT_EQ(expectations[i],
@@ -551,7 +551,7 @@
   // normal vibrant, but is out of range for other color profiles.
   const SkColor kPureGreen = SkColorSetRGB(0, 255, 0);
   canvas.FillRect(gfx::Rect(0, 3, 300, 1), kPureGreen);
-  bitmap = canvas.ToBitmap();
+  bitmap = canvas.GetBitmap();
   expectations[1] = kPureGreen;
   for (size_t i = 0; i < arraysize(color_profiles); ++i) {
     EXPECT_EQ(expectations[i],
diff --git a/ui/gfx/color_utils_unittest.cc b/ui/gfx/color_utils_unittest.cc
index 3870dd3..fcba64c0 100644
--- a/ui/gfx/color_utils_unittest.cc
+++ b/ui/gfx/color_utils_unittest.cc
@@ -128,7 +128,7 @@
   // Fill all pixels in black.
   canvas.FillRect(gfx::Rect(kSize), SK_ColorBLACK);
 
-  SkBitmap bitmap = canvas.ToBitmap();
+  SkBitmap bitmap = canvas.GetBitmap();
   // The thumbnail should deserve the highest boring score.
   EXPECT_DOUBLE_EQ(1.0, CalculateBoringScore(bitmap));
 }
@@ -143,7 +143,7 @@
   canvas.FillRect(gfx::Rect(0, 0, kSize.width() / 2, kSize.height()),
                   SK_ColorWHITE);
 
-  SkBitmap bitmap = canvas.ToBitmap();
+  SkBitmap bitmap = canvas.GetBitmap();
   ASSERT_EQ(kSize.width(), bitmap.width());
   ASSERT_EQ(kSize.height(), bitmap.height());
   // The thumbnail should be less boring because two colors are used.
diff --git a/ui/gfx/nine_image_painter_unittest.cc b/ui/gfx/nine_image_painter_unittest.cc
index 954f97a..1cf8506 100644
--- a/ui/gfx/nine_image_painter_unittest.cc
+++ b/ui/gfx/nine_image_painter_unittest.cc
@@ -85,7 +85,7 @@
   gfx::Rect bounds(0, 0, 50, 50);
   painter.Paint(&canvas, bounds);
 
-  SkBitmap result = canvas.ToBitmap();
+  SkBitmap result = canvas.GetBitmap();
 
   gfx::Vector2d paint_offset =
       gfx::ToFlooredVector2d(gfx::ScaleVector2d(offset, image_scale));
@@ -116,7 +116,7 @@
   gfx::Rect bounds(1, 1, 1, 1);
   painter.Paint(&canvas, bounds);
 
-  SkBitmap result = canvas.ToBitmap();
+  SkBitmap result = canvas.GetBitmap();
 
   EXPECT_EQ(SK_ColorGREEN, result.getColor(1, 1));
 
@@ -146,7 +146,7 @@
   gfx::Rect bounds(1, 1, 10, 10);
   painter.Paint(&canvas, bounds);
 
-  SkBitmap result = canvas.ToBitmap();
+  SkBitmap result = canvas.GetBitmap();
 
   SkIRect green_rect = SkIRect::MakeLTRB(2, 2, 10, 10);
   for (int y = 1; y < 10; y++) {
@@ -182,7 +182,7 @@
   gfx::Rect bounds(0, 0, 50, 50);
   painter.Paint(&canvas, bounds);
 
-  SkBitmap result = canvas.ToBitmap();
+  SkBitmap result = canvas.GetBitmap();
 
   gfx::Vector2d paint_offset =
       gfx::ToFlooredVector2d(gfx::ScaleVector2d(offset, image_scale));
@@ -211,7 +211,7 @@
   gfx::Rect bounds(0, 0, 50, 50);
   painter.Paint(&canvas, bounds);
 
-  SkBitmap result = canvas.ToBitmap();
+  SkBitmap result = canvas.GetBitmap();
 
   // The painting space is 50x50 and the scale of -1,-1 means an offset of 50,50
   // would put the output in the top left corner. Since the offset is 70,60 it
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index ca8677a..dfd21118 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -3798,15 +3798,17 @@
   const Size kCanvasSize(300, 50);
   const int kTestSize = 10;
 
-  sk_sp<cc::PaintSurface> surface = cc::PaintSurface::MakeRasterN32Premul(
-      kCanvasSize.width(), kCanvasSize.height());
-  Canvas canvas(surface->getCanvas(), 1.0f);
+  SkBitmap bitmap;
+  bitmap.allocPixels(
+      SkImageInfo::MakeN32Premul(kCanvasSize.width(), kCanvasSize.height()));
+  cc::SkiaPaintCanvas paint_canvas(bitmap);
+  Canvas canvas(&paint_canvas, 1.0f);
   RenderText* render_text = GetRenderText();
   render_text->SetHorizontalAlignment(ALIGN_LEFT);
   render_text->SetColor(SK_ColorBLACK);
 
   for (auto* string : kTestStrings) {
-    surface->getCanvas()->clear(SK_ColorWHITE);
+    paint_canvas.clear(SK_ColorWHITE);
     render_text->SetText(WideToUTF16(string));
     const Size string_size = render_text->GetStringSize();
     render_text->ApplyBaselineStyle(SUPERSCRIPT, Range(1, 2));
@@ -3822,9 +3824,7 @@
 
     render_text->Draw(&canvas);
     ASSERT_LT(string_size.width() + kTestSize, kCanvasSize.width());
-    SkPixmap pixmap;
-    surface->getCanvas()->peekPixels(&pixmap);
-    const uint32_t* buffer = static_cast<const uint32_t*>(pixmap.addr());
+    const uint32_t* buffer = static_cast<const uint32_t*>(bitmap.getPixels());
     ASSERT_NE(nullptr, buffer);
     TestRectangleBuffer rect_buffer(string, buffer, kCanvasSize.width(),
                                     kCanvasSize.height());
@@ -3891,15 +3891,17 @@
   const Size kCanvasSize(300, 50);
   const int kTestSize = 10;
 
-  sk_sp<cc::PaintSurface> surface = cc::PaintSurface::MakeRasterN32Premul(
-      kCanvasSize.width(), kCanvasSize.height());
-  Canvas canvas(surface->getCanvas(), 1.0f);
+  SkBitmap bitmap;
+  bitmap.allocPixels(
+      SkImageInfo::MakeN32Premul(kCanvasSize.width(), kCanvasSize.height()));
+  cc::SkiaPaintCanvas paint_canvas(bitmap);
+  Canvas canvas(&paint_canvas, 1.0f);
   RenderText* render_text = GetRenderText();
   render_text->SetHorizontalAlignment(ALIGN_LEFT);
   render_text->SetColor(SK_ColorBLACK);
 
   for (auto* string : kTestStrings) {
-    surface->getCanvas()->clear(SK_ColorWHITE);
+    paint_canvas.clear(SK_ColorWHITE);
     render_text->SetText(WideToUTF16(string));
     const Size string_size = render_text->GetStringSize();
     int fake_width = string_size.width() / 2;
@@ -3909,9 +3911,7 @@
     render_text->set_clip_to_display_rect(true);
     render_text->Draw(&canvas);
     ASSERT_LT(string_size.width() + kTestSize, kCanvasSize.width());
-    SkPixmap pixmap;
-    surface->getCanvas()->peekPixels(&pixmap);
-    const uint32_t* buffer = static_cast<const uint32_t*>(pixmap.addr());
+    const uint32_t* buffer = static_cast<const uint32_t*>(bitmap.getPixels());
     ASSERT_NE(nullptr, buffer);
     TestRectangleBuffer rect_buffer(string, buffer, kCanvasSize.width(),
                                     kCanvasSize.height());