diff --git a/DEPS b/DEPS
index abdf99f..41dd62a 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '64735758443e0a81a2f8a67338a5203fd725c2f3',
+  'v8_revision': 'f9b1cd343df071f543f07539513692367af25b06',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -88,7 +88,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling NaCl
   # and whatever else without interference from each other.
-  'nacl_revision': 'f88070127d32714df2714d94c9494fce951993d8',
+  'nacl_revision': '015356a98e4430dff9ce7e80ce9d2a62b04c2c4e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # 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': '28f796f29c9e269f992fbb1550b0e384a227f602',
+  'catapult_revision': 'd4f2d777c7aa4d9454a74afe92ff17e13da62380',
   # 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/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index d36e22d..28410322 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -143,6 +143,7 @@
     WebContents* guest_contents = LoadPdfGetGuestContents(url);
     ASSERT_TRUE(guest_contents);
     std::string test_util_js;
+    std::string mock_interactions_js;
 
     {
       base::ThreadRestrictions::ScopedAllowIO allow_io;
@@ -152,6 +153,15 @@
       base::FilePath test_util_path = test_data_dir.AppendASCII("test_util.js");
       ASSERT_TRUE(base::ReadFileToString(test_util_path, &test_util_js));
 
+      base::FilePath source_root_dir;
+      PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir);
+      base::FilePath mock_interactions_path = source_root_dir.Append(
+          FILE_PATH_LITERAL("third_party/polymer/v1_0/components-chromium/"
+                            "iron-test-helpers/mock-interactions.js"));
+      ASSERT_TRUE(base::ReadFileToString(mock_interactions_path,
+                                         &mock_interactions_js));
+      test_util_js.append(mock_interactions_js);
+
       base::FilePath test_file_path = test_data_dir.AppendASCII(filename);
       std::string test_js;
       ASSERT_TRUE(base::ReadFileToString(test_file_path, &test_js));
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 4523ef28..29840ec 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1697,6 +1697,7 @@
       "//third_party/accessibility-audit/axs_testing.js",
       "//third_party/chaijs/chai.js",
       "//third_party/mocha/mocha.js",
+      "//third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js",
       "//third_party/pyftpdlib/",
       "//third_party/pywebsocket/",
       "//third_party/simplejson/",
diff --git a/chrome/test/data/pdf/basic_test.js b/chrome/test/data/pdf/basic_test.js
index fc541f6..bde0be10 100644
--- a/chrome/test/data/pdf/basic_test.js
+++ b/chrome/test/data/pdf/basic_test.js
@@ -123,6 +123,4 @@
   }
 ];
 
-importTestHelpers().then(function() {
-  chrome.test.runTests(tests);
-});
+chrome.test.runTests(tests);
diff --git a/chrome/test/data/pdf/material_elements_test.js b/chrome/test/data/pdf/material_elements_test.js
index 082e960..bad24228 100644
--- a/chrome/test/data/pdf/material_elements_test.js
+++ b/chrome/test/data/pdf/material_elements_test.js
@@ -195,6 +195,4 @@
   }
 ];
 
-importTestHelpers().then(function() {
-  chrome.test.runTests(tests);
-});
+chrome.test.runTests(tests);
diff --git a/chrome/test/data/pdf/page_change_test.js b/chrome/test/data/pdf/page_change_test.js
index 85395d6..8c27397 100644
--- a/chrome/test/data/pdf/page_change_test.js
+++ b/chrome/test/data/pdf/page_change_test.js
@@ -69,6 +69,4 @@
   }
 ];
 
-importTestHelpers().then(function() {
-  chrome.test.runTests(tests);
-});
+chrome.test.runTests(tests);
diff --git a/chrome/test/data/pdf/test_util.js b/chrome/test/data/pdf/test_util.js
index 7fff3fa3..9efead4 100644
--- a/chrome/test/data/pdf/test_util.js
+++ b/chrome/test/data/pdf/test_util.js
@@ -104,27 +104,3 @@
     this.pageDimensions = [];
   };
 }
-
-function importHTML(src) {
-  var link = document.createElement('link');
-  var promise = new Promise(function(resolve, reject) {
-    link.onload = resolve;
-    link.onerror = reject;
-  });
-  link.rel = 'import';
-  link.href = src;
-  document.head.appendChild(link);
-  return promise;
-}
-
-/**
- * Import iron-test-helpers into the test document.
- * @example
- *   importTestHelpers().then(function() {
- *     chrome.test.runTests(...);
- *   })
- */
-function importTestHelpers() {
-  return importHTML('chrome://resources/polymer/v1_0/iron-test-helpers/' +
-      'iron-test-helpers.html');
-}
diff --git a/chrome/test/data/pdf/toolbar_manager_test.js b/chrome/test/data/pdf/toolbar_manager_test.js
index 041101c..ecd74ab 100644
--- a/chrome/test/data/pdf/toolbar_manager_test.js
+++ b/chrome/test/data/pdf/toolbar_manager_test.js
@@ -194,6 +194,4 @@
   }
 ];
 
-importTestHelpers().then(function() {
-  chrome.test.runTests(tests);
-});
+chrome.test.runTests(tests);
diff --git a/components/feature_engagement_tracker/internal/init_aware_model.cc b/components/feature_engagement_tracker/internal/init_aware_model.cc
index a5ab190..c514a70 100644
--- a/components/feature_engagement_tracker/internal/init_aware_model.cc
+++ b/components/feature_engagement_tracker/internal/init_aware_model.cc
@@ -9,7 +9,9 @@
 namespace feature_engagement_tracker {
 
 InitAwareModel::InitAwareModel(std::unique_ptr<Model> model)
-    : model_(std::move(model)), weak_ptr_factory_(this) {
+    : model_(std::move(model)),
+      initialization_complete_(false),
+      weak_ptr_factory_(this) {
   DCHECK(model_);
 }
 
@@ -37,19 +39,27 @@
     return;
   }
 
+  if (initialization_complete_)
+    return;
+
   queued_events_.push_back(std::tie(event_name, current_day));
 }
 
 void InitAwareModel::OnInitializeComplete(
     const OnModelInitializationFinished& callback,
     bool success) {
+  initialization_complete_ = true;
   if (success) {
     for (auto& event : queued_events_)
       model_->IncrementEvent(std::get<0>(event), std::get<1>(event));
-    queued_events_.clear();
   }
+  queued_events_.clear();
 
   callback.Run(success);
 }
 
+size_t InitAwareModel::GetQueuedEventCountForTesting() {
+  return queued_events_.size();
+}
+
 }  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/internal/init_aware_model.h b/components/feature_engagement_tracker/internal/init_aware_model.h
index 72a76d1..89b0e45 100644
--- a/components/feature_engagement_tracker/internal/init_aware_model.h
+++ b/components/feature_engagement_tracker/internal/init_aware_model.h
@@ -30,6 +30,8 @@
   void IncrementEvent(const std::string& event_name,
                       uint32_t current_day) override;
 
+  size_t GetQueuedEventCountForTesting();
+
  private:
   void OnInitializeComplete(const OnModelInitializationFinished& callback,
                             bool success);
@@ -37,6 +39,11 @@
   std::unique_ptr<Model> model_;
   std::vector<std::tuple<std::string, uint32_t>> queued_events_;
 
+  // Whether the initialization has completed. This will be set to true once
+  // the underlying model has been initialized, regardless of whether the
+  // result was a success or not.
+  bool initialization_complete_;
+
   base::WeakPtrFactory<InitAwareModel> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(InitAwareModel);
diff --git a/components/feature_engagement_tracker/internal/init_aware_model_unittest.cc b/components/feature_engagement_tracker/internal/init_aware_model_unittest.cc
index 6345257..00f3894 100644
--- a/components/feature_engagement_tracker/internal/init_aware_model_unittest.cc
+++ b/components/feature_engagement_tracker/internal/init_aware_model_unittest.cc
@@ -98,6 +98,7 @@
 
   model_->IncrementEvent("foo", 0U);
   model_->IncrementEvent("bar", 1U);
+  EXPECT_EQ(0U, model_->GetQueuedEventCountForTesting());
 }
 
 TEST_F(InitAwareModelTest, QueuedIncrementEvent) {
@@ -130,6 +131,40 @@
   EXPECT_CALL(*mocked_model_, IsReady()).WillRepeatedly(Return(true));
   EXPECT_CALL(*mocked_model_, IncrementEvent("qux", 3U)).Times(1);
   model_->IncrementEvent("qux", 3U);
+  EXPECT_EQ(0U, model_->GetQueuedEventCountForTesting());
+}
+
+TEST_F(InitAwareModelTest, QueuedIncrementEventWithUnsuccessfulInit) {
+  {
+    EXPECT_CALL(*mocked_model_, IsReady()).WillRepeatedly(Return(false));
+    EXPECT_CALL(*mocked_model_, IncrementEvent(_, _)).Times(0);
+
+    model_->IncrementEvent("foo", 0U);
+    model_->IncrementEvent("bar", 1U);
+  }
+
+  Model::OnModelInitializationFinished callback;
+  EXPECT_CALL(*mocked_model_, Initialize(_, 2U))
+      .WillOnce(SaveArg<0>(&callback));
+  model_->Initialize(load_callback_, 2U);
+
+  {
+    Sequence sequence;
+    EXPECT_CALL(*mocked_model_, IncrementEvent("foo", 0U))
+        .Times(0)
+        .InSequence(sequence);
+    EXPECT_CALL(*mocked_model_, IncrementEvent("bar", 1U))
+        .Times(0)
+        .InSequence(sequence);
+
+    callback.Run(false);
+    EXPECT_FALSE(load_success_.value());
+    EXPECT_EQ(0U, model_->GetQueuedEventCountForTesting());
+  }
+
+  EXPECT_CALL(*mocked_model_, IncrementEvent("qux", 3U)).Times(0);
+  model_->IncrementEvent("qux", 3U);
+  EXPECT_EQ(0U, model_->GetQueuedEventCountForTesting());
 }
 
 }  // namespace feature_engagement_tracker
diff --git a/components/security_interstitials_strings.grdp b/components/security_interstitials_strings.grdp
index 6e54c197..8d44d5d 100644
--- a/components/security_interstitials_strings.grdp
+++ b/components/security_interstitials_strings.grdp
@@ -62,10 +62,20 @@
 
   <!-- SSL error page: Superfish-specific -->
   <message name="IDS_SSL_SUPERFISH_HEADING" desc="The large heading at the top of the Superfish-specific SSL interstitial.">
-    Software on your computer is stopping Chrome from connecting to the web
+    Software on your computer is stopping Chrome from safely connecting to the web
   </message>
   <message name="IDS_SSL_SUPERFISH_PRIMARY_PARAGRAPH" desc="The primary explanatory paragraph for the Superfish-specific SSL interstitial.">
-    Follow these steps to remove the software and its associated certificate. You'll need administrator privileges. <ph name="BEGIN_LEARN_MORE_LINK">&lt;a href="#" id="learn-more-link"&gt;</ph>Learn more<ph name="END_LEARN_MORE_LINK">&lt;/a&gt;</ph>
+    <ph name="BEGIN_PARAGRAPH">&lt;p&gt;</ph>Follow these steps to temporarily disable the software so you can get on the web. You'll need administrator privileges.<ph name="END_PARAGRAPH">&lt;/p&gt;</ph>
+
+    <ph name="BEGIN_LIST">&lt;ol&gt;</ph>
+    <ph name="LIST_ITEM">&lt;li&gt;</ph>Click <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>Start<ph name="END_BOLD">&lt;/strong&gt;</ph>, then search for and select <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>"View local services"<ph name="END_BOLD">&lt;/strong&gt;</ph>
+    <ph name="LIST_ITEM">&lt;li&gt;</ph>Select <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>VisualDiscovery<ph name="END_BOLD">&lt;/strong&gt;</ph>
+    <ph name="LIST_ITEM">&lt;li&gt;</ph>Under <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>Startup type<ph name="END_BOLD">&lt;/strong&gt;</ph>, select <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>Disabled<ph name="END_BOLD">&lt;/strong&gt;</ph>
+    <ph name="LIST_ITEM">&lt;li&gt;</ph>Under <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>Service status<ph name="END_BOLD">&lt;/strong&gt;</ph>, click <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>Stop<ph name="END_BOLD">&lt;/strong&gt;</ph>
+    <ph name="LIST_ITEM">&lt;li&gt;</ph>Click <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>Apply<ph name="END_BOLD">&lt;/strong&gt;</ph>, then click <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>OK<ph name="END_BOLD">&lt;/strong&gt;</ph>
+    <ph name="LIST_ITEM">&lt;li&gt;</ph>Visit the <ph name="BEGIN_LEARN_MORE_LINK">&lt;a href="#" id="learn-more-link"&gt;</ph>Chrome help center<ph name="END_LEARN_MORE_LINK">&lt;/a&gt;</ph> to learn how to permanently remove the software from your computer
+    <ph name="END_LIST">&lt;/ol&gt;</ph>
+
   </message>
 
   <!-- SSL error page: overridable -->
diff --git a/content/browser/power_monitor_browsertest.cc b/content/browser/power_monitor_browsertest.cc
index 83791f3..e7e09fae 100644
--- a/content/browser/power_monitor_browsertest.cc
+++ b/content/browser/power_monitor_browsertest.cc
@@ -5,8 +5,12 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/utility_process_host.h"
+#include "content/public/browser/utility_process_host_client.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test_utils.h"
@@ -37,6 +41,14 @@
   run_loop.Run();
 }
 
+void StartUtilityProcessOnIOThread(mojom::PowerMonitorTestRequest request) {
+  UtilityProcessHost* host = UtilityProcessHost::Create(nullptr, nullptr);
+  host->SetName(base::ASCIIToUTF16("TestProcess"));
+  EXPECT_TRUE(host->Start());
+
+  BindInterface(host, std::move(request));
+}
+
 class MockPowerMonitorMessageBroadcaster : public device::mojom::PowerMonitor {
  public:
   MockPowerMonitorMessageBroadcaster() = default;
@@ -86,15 +98,38 @@
   void BindPowerMonitor(const service_manager::BindSourceInfo& source_info,
                         const std::string& interface_name,
                         mojo::ScopedMessagePipeHandle handle) {
-    if (source_info.identity.name() == mojom::kRendererServiceName)
+    if (source_info.identity.name() == mojom::kRendererServiceName) {
       ++request_count_from_renderer_;
 
+      DCHECK(renderer_bound_closure_);
+      std::move(renderer_bound_closure_).Run();
+    } else if (source_info.identity.name() == mojom::kUtilityServiceName) {
+      ++request_count_from_utility_;
+
+      DCHECK(utility_bound_closure_);
+      std::move(utility_bound_closure_).Run();
+    }
+
     power_monitor_message_broadcaster_.Bind(
         device::mojom::PowerMonitorRequest(std::move(handle)));
   }
 
  protected:
+  void StartUtilityProcess(mojom::PowerMonitorTestPtr* power_monitor_test,
+                           base::Closure utility_bound_closure) {
+    utility_bound_closure_ = utility_bound_closure;
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&StartUtilityProcessOnIOThread,
+                       mojo::MakeRequest(power_monitor_test)));
+  }
+
+  void set_renderer_bound_closure(base::Closure closure) {
+    renderer_bound_closure_ = closure;
+  }
+
   int request_count_from_renderer() { return request_count_from_renderer_; }
+  int request_count_from_utility() { return request_count_from_utility_; }
 
   void SimulatePowerStateChange(bool on_battery_power) {
     power_monitor_message_broadcaster_.OnPowerStateChange(on_battery_power);
@@ -102,15 +137,21 @@
 
  private:
   int request_count_from_renderer_ = 0;
+  int request_count_from_utility_ = 0;
+  base::OnceClosure renderer_bound_closure_;
+  base::OnceClosure utility_bound_closure_;
 
   MockPowerMonitorMessageBroadcaster power_monitor_message_broadcaster_;
 
   DISALLOW_COPY_AND_ASSIGN(PowerMonitorTest);
 };
 
-IN_PROC_BROWSER_TEST_F(PowerMonitorTest, RequestOnceFromOneRendererProcess) {
+IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestRendererProcess) {
   ASSERT_EQ(0, request_count_from_renderer());
+  base::RunLoop run_loop;
+  set_renderer_bound_closure(run_loop.QuitClosure());
   ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(".", "simple_page.html")));
+  run_loop.Run();
   EXPECT_EQ(1, request_count_from_renderer());
 
   mojom::PowerMonitorTestPtr power_monitor_renderer;
@@ -127,6 +168,24 @@
   VerifyPowerStateInChildProcess(power_monitor_renderer.get(), false);
 }
 
+IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestUtilityProcess) {
+  mojom::PowerMonitorTestPtr power_monitor_utility;
+
+  ASSERT_EQ(0, request_count_from_utility());
+  base::RunLoop run_loop;
+  StartUtilityProcess(&power_monitor_utility, run_loop.QuitClosure());
+  run_loop.Run();
+  EXPECT_EQ(1, request_count_from_utility());
+
+  SimulatePowerStateChange(true);
+  // Verify utility process on_battery_power changed to true.
+  VerifyPowerStateInChildProcess(power_monitor_utility.get(), true);
+
+  SimulatePowerStateChange(false);
+  // Verify utility process on_battery_power changed to false.
+  VerifyPowerStateInChildProcess(power_monitor_utility.get(), false);
+}
+
 }  //  namespace
 
 }  //  namespace content
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 25bed8c1..21fb08f3 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -160,6 +160,8 @@
     "common/layout_test/layout_test_switches.cc",
     "common/layout_test/layout_test_switches.h",
     "common/leak_detection_result.h",
+    "common/power_monitor_test_impl.cc",
+    "common/power_monitor_test_impl.h",
     "common/shell_content_client.cc",
     "common/shell_content_client.h",
     "common/shell_messages.cc",
diff --git a/content/shell/browser/content_shell_utility_manifest_overlay.json b/content/shell/browser/content_shell_utility_manifest_overlay.json
index abb81bdc..5ca52ab 100644
--- a/content/shell/browser/content_shell_utility_manifest_overlay.json
+++ b/content/shell/browser/content_shell_utility_manifest_overlay.json
@@ -4,6 +4,7 @@
     "service_manager:connector": {
       "provides": {
         "browser": [
+          "content::mojom::PowerMonitorTest",
           "content::mojom::TestService"
         ]
       }
diff --git a/content/shell/common/power_monitor_test_impl.cc b/content/shell/common/power_monitor_test_impl.cc
new file mode 100644
index 0000000..37cc850
--- /dev/null
+++ b/content/shell/common/power_monitor_test_impl.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/shell/common/power_monitor_test_impl.h"
+
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+// static
+void PowerMonitorTestImpl::MakeStrongBinding(
+    std::unique_ptr<PowerMonitorTestImpl> instance,
+    const service_manager::BindSourceInfo& source_info,
+    mojom::PowerMonitorTestRequest request) {
+  mojo::MakeStrongBinding(std::move(instance), std::move(request));
+}
+
+PowerMonitorTestImpl::PowerMonitorTestImpl() {
+  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+  if (power_monitor)
+    power_monitor->AddObserver(this);
+}
+
+PowerMonitorTestImpl::~PowerMonitorTestImpl() {
+  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+  if (power_monitor)
+    power_monitor->RemoveObserver(this);
+}
+
+void PowerMonitorTestImpl::QueryNextState(QueryNextStateCallback callback) {
+  // Do not allow overlapping call.
+  DCHECK(callback_.is_null());
+  callback_ = std::move(callback);
+
+  if (need_to_report_)
+    ReportState();
+}
+
+void PowerMonitorTestImpl::OnPowerStateChange(bool on_battery_power) {
+  on_battery_power_ = on_battery_power;
+  need_to_report_ = true;
+
+  if (!callback_.is_null())
+    ReportState();
+}
+
+void PowerMonitorTestImpl::ReportState() {
+  std::move(callback_).Run(on_battery_power_);
+  need_to_report_ = false;
+}
+
+}  // namespace content
diff --git a/content/shell/common/power_monitor_test_impl.h b/content/shell/common/power_monitor_test_impl.h
new file mode 100644
index 0000000..0f1bf233
--- /dev/null
+++ b/content/shell/common/power_monitor_test_impl.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SHELL_COMMON_POWER_MONITOR_TEST_IMPL_H_
+#define CONTENT_SHELL_COMMON_POWER_MONITOR_TEST_IMPL_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/power_monitor/power_monitor.h"
+#include "content/shell/common/power_monitor_test.mojom.h"
+
+namespace service_manager {
+struct BindSourceInfo;
+}
+
+namespace content {
+
+class PowerMonitorTestImpl : public base::PowerObserver,
+                             public mojom::PowerMonitorTest {
+ public:
+  static void MakeStrongBinding(
+      std::unique_ptr<PowerMonitorTestImpl> instance,
+      const service_manager::BindSourceInfo& source_info,
+      mojom::PowerMonitorTestRequest request);
+
+  PowerMonitorTestImpl();
+  ~PowerMonitorTestImpl() override;
+
+ private:
+  // mojom::PowerMonitorTest:
+  void QueryNextState(QueryNextStateCallback callback) override;
+
+  // base::PowerObserver:
+  void OnPowerStateChange(bool on_battery_power) override;
+  void OnSuspend() override {}
+  void OnResume() override {}
+
+  void ReportState();
+
+  QueryNextStateCallback callback_;
+  bool on_battery_power_ = false;
+  bool need_to_report_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(PowerMonitorTestImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_SHELL_COMMON_POWER_MONITOR_TEST_IMPL_H_
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc
index e78755d..e30a413 100644
--- a/content/shell/renderer/shell_content_renderer_client.cc
+++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -10,18 +10,16 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/power_monitor/power_monitor.h"
 #include "components/cdm/renderer/external_clear_key_key_system_properties.h"
 #include "components/web_cache/renderer/web_cache_impl.h"
 #include "content/public/child/child_thread.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/simple_connection_filter.h"
 #include "content/public/test/test_service.mojom.h"
-#include "content/shell/common/power_monitor_test.mojom.h"
+#include "content/shell/common/power_monitor_test_impl.h"
 #include "content/shell/common/shell_switches.h"
 #include "content/shell/renderer/shell_render_view_observer.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "ppapi/features/features.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
@@ -98,61 +96,6 @@
   new TestServiceImpl(std::move(request));
 }
 
-class PowerMonitorTestImpl : public base::PowerObserver,
-                             public mojom::PowerMonitorTest {
- public:
-  static void MakeStrongBinding(
-      std::unique_ptr<PowerMonitorTestImpl> instance,
-      const service_manager::BindSourceInfo& source_info,
-      mojom::PowerMonitorTestRequest request) {
-    mojo::MakeStrongBinding(std::move(instance), std::move(request));
-  }
-
-  PowerMonitorTestImpl() {
-    base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
-    if (power_monitor)
-      power_monitor->AddObserver(this);
-  }
-  ~PowerMonitorTestImpl() override {
-    base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
-    if (power_monitor)
-      power_monitor->RemoveObserver(this);
-  }
-
- private:
-  // mojom::PowerMonitorTest:
-  void QueryNextState(QueryNextStateCallback callback) override {
-    // Do not allow overlapping call.
-    DCHECK(callback_.is_null());
-    callback_ = std::move(callback);
-
-    if (need_to_report_)
-      ReportState();
-  }
-
-  // base::PowerObserver:
-  void OnPowerStateChange(bool on_battery_power) override {
-    on_battery_power_ = on_battery_power;
-    need_to_report_ = true;
-
-    if (!callback_.is_null())
-      ReportState();
-  }
-  void OnSuspend() override {}
-  void OnResume() override {}
-
-  void ReportState() {
-    std::move(callback_).Run(on_battery_power_);
-    need_to_report_ = false;
-  }
-
-  QueryNextStateCallback callback_;
-  bool on_battery_power_ = false;
-  bool need_to_report_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(PowerMonitorTestImpl);
-};
-
 }  // namespace
 
 ShellContentRendererClient::ShellContentRendererClient() {}
diff --git a/content/shell/utility/shell_content_utility_client.cc b/content/shell/utility/shell_content_utility_client.cc
index 47a78608..cb94f8e 100644
--- a/content/shell/utility/shell_content_utility_client.cc
+++ b/content/shell/utility/shell_content_utility_client.cc
@@ -17,6 +17,7 @@
 #include "content/public/test/test_host_resolver.h"
 #include "content/public/test/test_service.h"
 #include "content/public/test/test_service.mojom.h"
+#include "content/shell/common/power_monitor_test_impl.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/public/cpp/system/buffer.h"
 #include "net/base/net_errors.h"
@@ -118,6 +119,10 @@
   auto registry = base::MakeUnique<service_manager::BinderRegistry>();
   registry->AddInterface(base::Bind(&TestServiceImpl::Create),
                          base::ThreadTaskRunnerHandle::Get());
+  registry->AddInterface<mojom::PowerMonitorTest>(
+      base::Bind(&PowerMonitorTestImpl::MakeStrongBinding,
+                 base::Passed(base::MakeUnique<PowerMonitorTestImpl>())),
+      base::ThreadTaskRunnerHandle::Get());
   content::ChildThread::Get()
       ->GetServiceManagerConnection()
       ->AddConnectionFilter(
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 5ba9e5b..5d63802f 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -629,6 +629,7 @@
     "//testing/gtest",
     "//third_party/ocmock",
     "//ui/base:test_support",
+    "//ui/gfx:test_support",
   ]
 
   sources = [
diff --git a/ios/web/public/test/fakes/test_web_state.h b/ios/web/public/test/fakes/test_web_state.h
index d98f99e5..90931b7 100644
--- a/ios/web/public/test/fakes/test_web_state.h
+++ b/ios/web/public/test/fakes/test_web_state.h
@@ -76,6 +76,8 @@
   void RemovePolicyDecider(WebStatePolicyDecider* decider) override {}
   WebStateInterfaceProvider* GetWebStateInterfaceProvider() override;
   bool HasOpener() const override;
+  void TakeSnapshot(const SnapshotCallback& callback,
+                    CGSize target_size) const override;
   base::WeakPtr<WebState> AsWeakPtr() override;
 
   // Setters for test data.
diff --git a/ios/web/public/test/fakes/test_web_state.mm b/ios/web/public/test/fakes/test_web_state.mm
index 9c268874..97b631d 100644
--- a/ios/web/public/test/fakes/test_web_state.mm
+++ b/ios/web/public/test/fakes/test_web_state.mm
@@ -6,9 +6,12 @@
 
 #include <stdint.h>
 
+#include "base/bind.h"
 #include "base/callback.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #import "ios/web/public/web_state/ui/crw_content_view.h"
 #include "ios/web/public/web_state/web_state_observer.h"
+#include "ui/gfx/image/image.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -230,6 +233,12 @@
   return false;
 }
 
+void TestWebState::TakeSnapshot(const SnapshotCallback& callback,
+                                CGSize target_size) const {
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::Bind(callback, gfx::Image()));
+}
+
 base::WeakPtr<WebState> TestWebState::AsWeakPtr() {
   NOTREACHED();
   return base::WeakPtr<WebState>();
diff --git a/ios/web/public/web_state/web_state.h b/ios/web/public/web_state/web_state.h
index 6974f523..8335bb8 100644
--- a/ios/web/public/web_state/web_state.h
+++ b/ios/web/public/web_state/web_state.h
@@ -35,6 +35,10 @@
 class Value;
 }
 
+namespace gfx {
+class Image;
+}
+
 namespace web {
 
 class BrowserState;
@@ -248,6 +252,14 @@
   // CreateParams::created_with_opener for more details.
   virtual bool HasOpener() const = 0;
 
+  // Callback used to handle snapshots. The parameter is the snapshot image.
+  typedef base::Callback<void(const gfx::Image&)> SnapshotCallback;
+
+  // Takes a snapshot of this WebState with |target_size|. |callback| is
+  // asynchronously invoked after performing the snapshot.
+  virtual void TakeSnapshot(const SnapshotCallback& callback,
+                            CGSize target_size) const = 0;
+
  protected:
   friend class WebStateObserver;
   friend class WebStatePolicyDecider;
diff --git a/ios/web/web_state/web_state_impl.h b/ios/web/web_state/web_state_impl.h
index 916f62f..fbdb248b 100644
--- a/ios/web/web_state/web_state_impl.h
+++ b/ios/web/web_state/web_state_impl.h
@@ -208,6 +208,8 @@
   id<CRWWebViewProxy> GetWebViewProxy() const override;
   WebStateInterfaceProvider* GetWebStateInterfaceProvider() override;
   bool HasOpener() const override;
+  void TakeSnapshot(const SnapshotCallback& callback,
+                    CGSize target_size) const override;
   base::WeakPtr<WebState> AsWeakPtr() override;
 
   // Adds |interstitial|'s view to the web controller's content view.
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index d973508..d918d55 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -7,10 +7,12 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #import "ios/web/interstitials/web_interstitial_impl.h"
 #import "ios/web/navigation/crw_session_controller.h"
 #import "ios/web/navigation/legacy_navigation_manager_impl.h"
@@ -38,6 +40,7 @@
 #include "ios/web/webui/web_ui_ios_controller_factory_registry.h"
 #include "ios/web/webui/web_ui_ios_impl.h"
 #include "net/http/http_response_headers.h"
+#include "ui/gfx/image/image.h"
 
 namespace web {
 
@@ -672,6 +675,23 @@
   return created_with_opener_;
 }
 
+void WebStateImpl::TakeSnapshot(const SnapshotCallback& callback,
+                                CGSize target_size) const {
+  UIView* view = [web_controller_ view];
+  UIImage* snapshot = nil;
+  if (view && !CGRectIsEmpty(view.bounds)) {
+    CGFloat scaled_height =
+        view.bounds.size.height * target_size.width / view.bounds.size.width;
+    CGRect scaled_rect = CGRectMake(0, 0, target_size.width, scaled_height);
+    UIGraphicsBeginImageContextWithOptions(target_size, YES, 0);
+    [view drawViewHierarchyInRect:scaled_rect afterScreenUpdates:NO];
+    snapshot = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+  }
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::Bind(callback, gfx::Image(snapshot)));
+}
+
 void WebStateImpl::OnNavigationStarted(web::NavigationContext* context) {
   for (auto& observer : observers_)
     observer.DidStartNavigation(context);
diff --git a/ios/web/web_state/web_state_unittest.mm b/ios/web/web_state/web_state_unittest.mm
index 35c165c2..76b37f8 100644
--- a/ios/web/web_state/web_state_unittest.mm
+++ b/ios/web/web_state/web_state_unittest.mm
@@ -4,11 +4,16 @@
 
 #import "ios/web/public/web_state/web_state.h"
 
+#import <UIKit/UIKit.h>
+
 #include "base/mac/bind_objc_block.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/ios/wait_util.h"
 #include "base/values.h"
 #import "ios/web/public/navigation_manager.h"
 #import "ios/web/public/test/web_test_with_web_state.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_unittest_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -112,4 +117,37 @@
   ASSERT_FALSE(navigation_manager->GetLastCommittedItem());
 }
 
+// Tests that the snapshot method returns an image of a rendered html page.
+TEST_F(WebStateTest, Snapshot) {
+  LoadHtml(
+      "<html><div style='background-color:#FF0000; width:50%; "
+      "height:100%;'></div></html>");
+  __block bool snapshot_complete = false;
+  [[[UIApplication sharedApplication] keyWindow]
+      addSubview:web_state()->GetView()];
+  // The subview is added but not immediately painted, so a small delay is
+  // necessary.
+  base::test::ios::SpinRunLoopWithMinDelay(base::TimeDelta::FromSecondsD(0.1));
+  CGSize target_size = CGSizeMake(100.0f, 100.0f);
+  web_state()->TakeSnapshot(
+      base::BindBlockArc(^(const gfx::Image& snapshot) {
+        ASSERT_FALSE(snapshot.IsEmpty());
+        EXPECT_EQ(snapshot.Width(), target_size.width);
+        EXPECT_EQ(snapshot.Height(), target_size.height);
+        // Test a pixel on the left (red) side.
+        gfx::test::CheckColors(gfx::test::GetPlatformImageColor(
+                                   gfx::test::ToPlatformType(snapshot), 45, 50),
+                               SK_ColorRED);
+        // Test a pixel on the right (white) side.
+        gfx::test::CheckColors(gfx::test::GetPlatformImageColor(
+                                   gfx::test::ToPlatformType(snapshot), 55, 50),
+                               SK_ColorWHITE);
+        snapshot_complete = true;
+      }),
+      target_size);
+  WaitForCondition(^{
+    return snapshot_complete;
+  });
+}
+
 }  // namespace web
diff --git a/net/data/ssl/certificate_transparency/log_list.json b/net/data/ssl/certificate_transparency/log_list.json
index 6ea5b39..6a29f47 100644
--- a/net/data/ssl/certificate_transparency/log_list.json
+++ b/net/data/ssl/certificate_transparency/log_list.json
@@ -178,6 +178,26 @@
     8
    ],
    "dns_api_endpoint": "startcom1.ct.googleapis.com"
+  },
+  {
+   "description": "Comodo 'Sabre' CT log",
+   "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8m/SiQ8/xfiHHqtls9m7FyOMBg4JVZY9CgiixXGz0akvKD6DEL8S0ERmFe9U4ZiA0M4kbT5nmuk3I85Sk4bagA==",
+   "url": "sabre.ct.comodo.com/",
+   "maximum_merge_delay": 86400,
+   "operated_by": [
+    9
+   ],
+   "dns_api_endpoint": "comodo-sabre.ct.googleapis.com"
+  },
+  {
+   "description": "Comodo 'Mammoth' CT log",
+   "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7+R9dC4VFbbpuyOL+yy14ceAmEf7QGlo/EmtYU6DRzwat43f/3swtLr/L8ugFOOt1YU/RFmMjGCL17ixv66MZw==",
+   "url": "mammoth.ct.comodo.com/",
+   "maximum_merge_delay": 86400,
+   "operated_by": [
+    9
+   ],
+   "dns_api_endpoint": "comodo-mammoth.ct.googleapis.com"
   }
  ],
  "operators": [
@@ -216,6 +236,10 @@
   {
    "name": "StartSSL",
    "id": 8
+  },
+  {
+   "name": "Comodo",
+   "id": 9
   }
  ]
 }
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index c94914c4..88a4e52 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -312,6 +312,7 @@
       backend_factory_(std::move(backend_factory)),
       building_backend_(false),
       bypass_lock_for_test_(false),
+      bypass_lock_after_headers_for_test_(false),
       fail_conditionalization_for_test_(false),
       mode_(NORMAL),
       network_layer_(std::move(network_layer)),
@@ -465,6 +466,8 @@
       new HttpCache::Transaction(priority, this);
    if (bypass_lock_for_test_)
     transaction->BypassLockForTest();
+   if (bypass_lock_after_headers_for_test_)
+     transaction->BypassLockAfterHeadersForTest();
    if (fail_conditionalization_for_test_)
      transaction->FailConditionalizationForTest();
 
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 91214c1..e420c72 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -193,7 +193,14 @@
 
   // Causes all transactions created after this point to simulate lock timeout
   // and effectively bypass the cache lock whenever there is lock contention.
-  void SimulateCacheLockTimeout() { bypass_lock_for_test_ = true; }
+  void SimulateCacheLockTimeoutForTesting() { bypass_lock_for_test_ = true; }
+
+  // Causes all transactions created after this point to simulate lock timeout
+  // and effectively bypass the cache lock whenever there is lock contention
+  // after the transaction has completed its headers phase.
+  void SimulateCacheLockTimeoutAfterHeadersForTesting() {
+    bypass_lock_after_headers_for_test_ = true;
+  }
 
   // Causes all transactions created after this point to generate a failure
   // when attempting to conditionalize a network request.
@@ -513,6 +520,7 @@
   std::unique_ptr<BackendFactory> backend_factory_;
   bool building_backend_;
   bool bypass_lock_for_test_;
+  bool bypass_lock_after_headers_for_test_;
   bool fail_conditionalization_for_test_;
 
   Mode mode_;
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 29d040c8..6be3d87 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -168,6 +168,7 @@
       vary_mismatch_(false),
       couldnt_conditionalize_request_(false),
       bypass_lock_for_test_(false),
+      bypass_lock_after_headers_for_test_(false),
       fail_conditionalization_for_test_(false),
       io_buf_len_(0),
       read_offset_(0),
@@ -853,7 +854,7 @@
         rv = DoCacheReadMetadataComplete(rv);
         break;
       case STATE_HEADERS_PHASE_CANNOT_PROCEED:
-        rv = DoHeadersPhaseCannotProceed();
+        rv = DoHeadersPhaseCannotProceed(rv);
         break;
       case STATE_FINISH_HEADERS:
         rv = DoFinishHeaders(rv);
@@ -923,6 +924,10 @@
                                     result);
   cache_pending_ = false;
 
+  // Reset mode_ that might get set in this function. This is done because this
+  // function can be invoked multiple times for a transaction.
+  mode_ = NONE;
+
   if (!ShouldPassThrough()) {
     cache_key_ = cache_->GenerateCacheKey(request_);
 
@@ -1131,42 +1136,48 @@
   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_) {
-      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 &&
-          new_entry_->writer->range_requested_) {
-        // Quickly timeout and bypass the cache if we're a range request and
-        // we're blocked by the reader/writer lock. Doing so eliminates a long
-        // running issue, http://crbug.com/31014, where two of the same media
-        // resources could not be played back simultaneously due to one locking
-        // the cache entry until the entire video was downloaded.
-        //
-        // Bypassing the cache is not ideal, as we are now ignoring the cache
-        // entirely for all range requests to a resource beyond the first. This
-        // is however a much more succinct solution than the alternatives, which
-        // would require somewhat significant changes to the http caching logic.
-        //
-        // Allow some timeout slack for the entry addition to complete in case
-        // the writer lock is imminently released; we want to avoid skipping
-        // the cache if at all possible. See http://crbug.com/408765
-        timeout_milliseconds = 25;
-      }
-      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE,
-          base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout,
-                     weak_factory_.GetWeakPtr(), entry_lock_waiting_since_),
-          TimeDelta::FromMilliseconds(timeout_milliseconds));
-    }
-  }
+  if (rv == ERR_IO_PENDING)
+    AddCacheLockTimeoutHandler(new_entry_);
   return rv;
 }
 
+void HttpCache::Transaction::AddCacheLockTimeoutHandler(ActiveEntry* entry) {
+  DCHECK(next_state_ == STATE_ADD_TO_ENTRY_COMPLETE ||
+         next_state_ == STATE_FINISH_HEADERS_COMPLETE);
+  if ((bypass_lock_for_test_ && next_state_ == STATE_ADD_TO_ENTRY_COMPLETE) ||
+      (bypass_lock_after_headers_for_test_ &&
+       next_state_ == STATE_FINISH_HEADERS_COMPLETE)) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::Bind(&HttpCache::Transaction::OnCacheLockTimeout,
+                   weak_factory_.GetWeakPtr(), entry_lock_waiting_since_));
+  } else {
+    int timeout_milliseconds = 20 * 1000;
+    if (partial_ && entry->writer && entry->writer->range_requested_) {
+      // Quickly timeout and bypass the cache if we're a range request and
+      // we're blocked by the reader/writer lock. Doing so eliminates a long
+      // running issue, http://crbug.com/31014, where two of the same media
+      // resources could not be played back simultaneously due to one locking
+      // the cache entry until the entire video was downloaded.
+      //
+      // Bypassing the cache is not ideal, as we are now ignoring the cache
+      // entirely for all range requests to a resource beyond the first. This
+      // is however a much more succinct solution than the alternatives, which
+      // would require somewhat significant changes to the http caching logic.
+      //
+      // Allow some timeout slack for the entry addition to complete in case
+      // the writer lock is imminently released; we want to avoid skipping
+      // the cache if at all possible. See http://crbug.com/408765
+      timeout_milliseconds = 25;
+    }
+    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&HttpCache::Transaction::OnCacheLockTimeout,
+                   weak_factory_.GetWeakPtr(), entry_lock_waiting_since_),
+        TimeDelta::FromMilliseconds(timeout_milliseconds));
+  }
+}
+
 int HttpCache::Transaction::DoAddToEntryComplete(int result) {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoAddToEntryComplete");
   net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY,
@@ -1817,7 +1828,7 @@
   return OK;
 }
 
-int HttpCache::Transaction::DoHeadersPhaseCannotProceed() {
+int HttpCache::Transaction::DoHeadersPhaseCannotProceed(int result) {
   // If its the Start state machine and it cannot proceed due to a cache
   // failure, restart this transaction.
   DCHECK(!reading_);
@@ -1831,6 +1842,10 @@
 
   entry_ = nullptr;
 
+  // Bypass the cache for timeout scenario.
+  if (result == ERR_CACHE_LOCK_TIMEOUT)
+    effective_load_flags_ |= LOAD_DISABLE_CACHE;
+
   TransitionToState(STATE_GET_BACKEND);
   return OK;
 }
@@ -1854,13 +1869,20 @@
   // If the transaction needs to wait because another transaction is still
   // writing the response body, it will return ERR_IO_PENDING now and the
   // io_callback_ will be invoked when the wait is done.
-  return cache_->DoneWithResponseHeaders(entry_, this, partial_ != nullptr);
+  int rv = cache_->DoneWithResponseHeaders(entry_, this, partial_ != nullptr);
+  if (rv == ERR_IO_PENDING) {
+    DCHECK(entry_lock_waiting_since_.is_null());
+    entry_lock_waiting_since_ = TimeTicks::Now();
+    AddCacheLockTimeoutHandler(entry_);
+  }
+  return rv;
 }
 
 int HttpCache::Transaction::DoFinishHeadersComplete(int rv) {
-  if (rv == ERR_CACHE_RACE) {
+  entry_lock_waiting_since_ = TimeTicks();
+  if (rv == ERR_CACHE_RACE || rv == ERR_CACHE_LOCK_TIMEOUT) {
     TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
-    return OK;
+    return rv;
   }
 
   TransitionToState(STATE_NONE);
@@ -2805,16 +2827,20 @@
   return ERR_CACHE_READ_FAILURE;
 }
 
-void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) {
+void HttpCache::Transaction::OnCacheLockTimeout(base::TimeTicks start_time) {
   if (entry_lock_waiting_since_ != start_time)
     return;
 
-  DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE);
+  DCHECK(next_state_ == STATE_ADD_TO_ENTRY_COMPLETE ||
+         next_state_ == STATE_FINISH_HEADERS_COMPLETE);
 
   if (!cache_)
     return;
 
-  cache_->RemovePendingTransaction(this);
+  if (next_state_ == STATE_ADD_TO_ENTRY_COMPLETE)
+    cache_->RemovePendingTransaction(this);
+  else
+    cache_->DoneWithEntry(entry_, this, false, partial_ != nullptr);
   OnIOComplete(ERR_CACHE_LOCK_TIMEOUT);
 }
 
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index eac49c2..dec02f1 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -128,6 +128,10 @@
     bypass_lock_for_test_ = true;
   }
 
+  void BypassLockAfterHeadersForTest() {
+    bypass_lock_after_headers_for_test_ = true;
+  }
+
   // Generates a failure when attempting to conditionalize a network request.
   void FailConditionalizationForTest() {
     fail_conditionalization_for_test_ = true;
@@ -191,14 +195,6 @@
     bool initialized;
   };
 
-  // A snapshot of pieces of the transaction before entering the state machine
-  // so that the state can be restored when restarting the state machine.
-  struct RestartInfo {
-    Mode mode = NONE;
-    HttpResponseInfo::CacheEntryStatus cache_entry_status =
-        HttpResponseInfo::CacheEntryStatus::ENTRY_UNDEFINED;
-  };
-
   enum State {
     STATE_UNSET,
 
@@ -312,7 +308,7 @@
   int DoPartialHeadersReceived();
   int DoCacheReadMetadata();
   int DoCacheReadMetadataComplete(int result);
-  int DoHeadersPhaseCannotProceed();
+  int DoHeadersPhaseCannotProceed(int result);
   int DoFinishHeaders(int result);
   int DoFinishHeadersComplete(int result);
   int DoNetworkRead();
@@ -324,6 +320,10 @@
   int DoCacheWriteTruncatedResponse();
   int DoCacheWriteTruncatedResponseComplete(int result);
 
+  // Adds time out handling while waiting to be added to entry or after headers
+  // phase is complete.
+  void AddCacheLockTimeoutHandler(ActiveEntry* entry);
+
   // Sets request_ and fields derived from it.
   void SetRequest(const NetLogWithSource& net_log);
 
@@ -413,7 +413,7 @@
   int OnCacheReadError(int result, bool restart);
 
   // Called when the cache lock timeout fires.
-  void OnAddToEntryTimeout(base::TimeTicks start_time);
+  void OnCacheLockTimeout(base::TimeTicks start_time);
 
   // Deletes the current partial cache entry (sparse), and optionally removes
   // the control object (partial_).
@@ -505,6 +505,8 @@
   bool vary_mismatch_;  // The request doesn't match the stored vary data.
   bool couldnt_conditionalize_request_;
   bool bypass_lock_for_test_;  // A test is exercising the cache lock.
+  bool bypass_lock_after_headers_for_test_;  // A test is exercising the cache
+                                             // lock.
   bool fail_conditionalization_for_test_;  // Fail ConditionalizeRequest.
   scoped_refptr<IOBuffer> read_buf_;
   int io_buf_len_;
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index 869708f..b01427a7 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -1576,6 +1576,92 @@
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 }
 
+// Tests parallel validation on range requests can be successfully restarted
+// when there is a cache lock timeout.
+TEST(HttpCache, RangeGET_ParallelValidationCacheLockTimeout) {
+  MockHttpCache cache;
+
+  ScopedMockTransaction transaction(kRangeGET_TransactionOK);
+
+  std::vector<std::unique_ptr<Context>> context_list;
+  const int kNumTransactions = 2;
+
+  for (int i = 0; i < kNumTransactions; ++i) {
+    context_list.push_back(base::MakeUnique<Context>());
+  }
+
+  // Let 1st transaction complete headers phase for ranges 40-49.
+  std::string first_read;
+  MockHttpRequest request1(transaction);
+  {
+    auto& c = context_list[0];
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+    EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
+
+    c->result =
+        c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
+    base::RunLoop().RunUntilIdle();
+
+    // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
+    // true.
+    const int kBufferSize = 5;
+    scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
+    ReleaseBufferCompletionCallback cb(buffer.get());
+    c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
+    EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
+
+    std::string data_read(buffer->data(), kBufferSize);
+    first_read = data_read;
+
+    EXPECT_EQ(LOAD_STATE_READING_RESPONSE, c->trans->GetLoadState());
+  }
+
+  cache.SimulateCacheLockTimeoutAfterHeaders();
+
+  // 2nd transaction requests ranges 30-39.
+  transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
+  MockHttpRequest request2(transaction);
+  {
+    auto& c = context_list[1];
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+    EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
+
+    c->result =
+        c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
+    base::RunLoop().RunUntilIdle();
+
+    EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
+  }
+
+  EXPECT_TRUE(cache.IsWriterPresent(kRangeGET_TransactionOK.url));
+  EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(kRangeGET_TransactionOK.url));
+
+  EXPECT_EQ(3, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+  for (int i = 0; i < kNumTransactions; ++i) {
+    auto& c = context_list[i];
+    if (c->result == ERR_IO_PENDING)
+      c->result = c->callback.WaitForResult();
+
+    if (i == 0) {
+      ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
+                                        transaction);
+      continue;
+    }
+
+    transaction.data = "rg: 30-39 ";
+    ReadAndVerifyTransaction(c->trans.get(), transaction);
+  }
+
+  EXPECT_EQ(3, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+}
+
 // Tests parallel validation on range requests with overlapping ranges.
 TEST(HttpCache, RangeGET_ParallelValidationOverlappingRanges) {
   MockHttpCache cache;
@@ -1939,6 +2025,53 @@
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 }
 
+// Tests that a transaction which is in validated queue can timeout and start
+// reading from the network without writing to the cache.
+TEST(HttpCache, SimpleGET_ParallelValidationValidatedTimeout) {
+  MockHttpCache cache;
+
+  MockHttpRequest request(kSimpleGET_Transaction);
+
+  std::vector<std::unique_ptr<Context>> context_list;
+  const int kNumTransactions = 2;
+
+  for (int i = 0; i < kNumTransactions; ++i) {
+    context_list.push_back(base::MakeUnique<Context>());
+    auto& c = context_list[i];
+
+    if (i == 1)
+      cache.SimulateCacheLockTimeoutAfterHeaders();
+
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+
+    c->result =
+        c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
+  }
+
+  // Allow all requests to move from the Create queue to the active entry.
+  base::RunLoop().RunUntilIdle();
+
+  // The first request should be a writer at this point, and the subsequent
+  // requests should have completed validation, timed out and restarted.
+
+  EXPECT_EQ(2, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
+  EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+
+  // Complete the rest of the transactions.
+  for (auto& context : context_list) {
+    ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
+  }
+
+  EXPECT_EQ(2, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+}
+
 // Tests that a transaction which is in readers can be destroyed without
 // any impact to other transactions.
 TEST(HttpCache, SimpleGET_ParallelValidationCancelReader) {
diff --git a/net/http/mock_http_cache.cc b/net/http/mock_http_cache.cc
index e676122..5363d3af 100644
--- a/net/http/mock_http_cache.cc
+++ b/net/http/mock_http_cache.cc
@@ -586,7 +586,11 @@
 }
 
 void MockHttpCache::SimulateCacheLockTimeout() {
-  http_cache_.SimulateCacheLockTimeout();
+  http_cache_.SimulateCacheLockTimeoutForTesting();
+}
+
+void MockHttpCache::SimulateCacheLockTimeoutAfterHeaders() {
+  http_cache_.SimulateCacheLockTimeoutAfterHeadersForTesting();
 }
 
 void MockHttpCache::FailConditionalizations() {
diff --git a/net/http/mock_http_cache.h b/net/http/mock_http_cache.h
index 7718f351..ca07304 100644
--- a/net/http/mock_http_cache.h
+++ b/net/http/mock_http_cache.h
@@ -207,6 +207,9 @@
   // Wrapper to simulate cache lock timeout for new transactions.
   void SimulateCacheLockTimeout();
 
+  // Wrapper to simulate cache lock timeout for new transactions.
+  void SimulateCacheLockTimeoutAfterHeaders();
+
   // Wrapper to fail request conditionalization for new transactions.
   void FailConditionalizations();
 
diff --git a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
index c0178ca..3255631 100644
--- a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
@@ -359,6 +359,8 @@
     : WebRemoteFrameBase(scope),
       frame_client_(RemoteFrameClientImpl::Create(this)),
       client_(client),
-      self_keep_alive_(this) {}
+      self_keep_alive_(this) {
+  DCHECK(client);
+}
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 435cc451..c1757a9 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -8835,23 +8835,12 @@
 class SwapMainFrameWhenTitleChangesWebFrameClient
     : public FrameTestHelpers::TestWebFrameClient {
  public:
-  SwapMainFrameWhenTitleChangesWebFrameClient() : remote_frame_(nullptr) {}
-
-  ~SwapMainFrameWhenTitleChangesWebFrameClient() override {
-    if (remote_frame_)
-      remote_frame_->Close();
-  }
+  SwapMainFrameWhenTitleChangesWebFrameClient() {}
 
   void DidReceiveTitle(const WebString&, WebTextDirection) override {
-    if (!Frame()->Parent()) {
-      remote_frame_ =
-          WebRemoteFrame::Create(WebTreeScopeType::kDocument, nullptr);
-      Frame()->Swap(remote_frame_);
-    }
+    if (!Frame()->Parent())
+      Frame()->Swap(FrameTestHelpers::CreateRemote());
   }
-
- private:
-  WebRemoteFrame* remote_frame_;
 };
 
 }  // anonymous namespace
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils.py
index a862bd57..7547119 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils.py
@@ -28,11 +28,12 @@
 _log = logging.getLogger(__name__)
 
 
-def _default_handlers(stream, logging_level):
+def _default_handlers(stream, logging_level, include_time):
     """Return a list of the default logging handlers to use.
 
     Args:
       stream: See the configure_logging() docstring.
+      include_time: See the configure_logging() docstring.
     """
     # Create the filter.
     def should_log(record):
@@ -46,10 +47,15 @@
 
     # Create the handler.
     handler = logging.StreamHandler(stream)
-    if logging_level == logging.DEBUG:
-        formatter = logging.Formatter('%(name)s: [%(levelname)s] %(message)s')
+    if include_time:
+        prefix = '%(asctime)s - '
     else:
-        formatter = logging.Formatter('%(message)s')
+        prefix = ''
+
+    if logging_level == logging.DEBUG:
+        formatter = logging.Formatter(prefix + '%(name)s: [%(levelname)s] %(message)s')
+    else:
+        formatter = logging.Formatter(prefix + '%(message)s')
 
     handler.setFormatter(formatter)
     handler.addFilter(logging_filter)
@@ -58,7 +64,7 @@
 
 
 def configure_logging(logging_level=None, logger=None, stream=None,
-                      handlers=None):
+                      handlers=None, include_time=True):
     """Configure logging for standard purposes.
 
     Returns:
@@ -80,6 +86,9 @@
       handlers: A list of logging.Handler instances to add to the logger
                 being configured.  If this parameter is provided, then the
                 stream parameter is not used.
+      include_time: Include time information at the start of every log message.
+                    Useful for understanding how much time has passed between
+                    subsequent log messages.
     """
     # If the stream does not define an "encoding" data attribute, the
     # logging module can throw an error like the following:
@@ -96,7 +105,7 @@
     if stream is None:
         stream = sys.stderr
     if handlers is None:
-        handlers = _default_handlers(stream, logging_level)
+        handlers = _default_handlers(stream, logging_level, include_time)
 
     logger.setLevel(logging_level)
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils_unittest.py
index 28ca6732..a5d471d 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils_unittest.py
@@ -47,7 +47,7 @@
         logger.propagate = False
 
         logging_level = self._logging_level()
-        self._handlers = configure_logging(logging_level=logging_level, logger=logger, stream=log_stream)
+        self._handlers = configure_logging(logging_level=logging_level, logger=logger, stream=log_stream, include_time=False)
         self._log = logger
         self._log_stream = log_stream
 
diff --git a/third_party/WebKit/public/web/WebRemoteFrame.h b/third_party/WebKit/public/web/WebRemoteFrame.h
index 5c23c51..9b40f3c 100644
--- a/third_party/WebKit/public/web/WebRemoteFrame.h
+++ b/third_party/WebKit/public/web/WebRemoteFrame.h
@@ -24,15 +24,19 @@
 
 class WebRemoteFrame : public WebFrame {
  public:
+  // Factory methods for creating a WebRemoteFrame. The WebRemoteFrameClient
+  // argument must be non-null for all creation methods.
   BLINK_EXPORT static WebRemoteFrame* Create(WebTreeScopeType,
                                              WebRemoteFrameClient*,
                                              WebFrame* opener = nullptr);
 
-  // Functions for the embedder replicate the frame tree between processes.
+  // Specialized factory methods to allow the embedder to replicate the frame
+  // tree between processes.
   // TODO(dcheng): The embedder currently does not replicate local frames in
-  // insertion order, so the local child version takes a previous sibling to
+  // insertion order, so the local child version takes |previous_sibling| to
   // ensure that it is inserted into the correct location in the list of
-  // children.
+  // children. If |previous_sibling| is null, the child is inserted at the
+  // beginning.
   virtual WebLocalFrame* CreateLocalChild(WebTreeScopeType,
                                           const WebString& name,
                                           WebSandboxFlags,