diff --git a/DEPS b/DEPS
index 9964530..dc2c855 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': '1ad4dcaa827c515f4e55370f2988db00c3d5f7ae',
+  'v8_revision': 'ee5db9409665e270a377c2c3be7d3b017830cfc2',
   # 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.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundScheduler.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundScheduler.java
index 28e9661..eef945b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundScheduler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundScheduler.java
@@ -7,6 +7,8 @@
 import android.content.Context;
 import android.os.Bundle;
 
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GoogleApiAvailability;
 import com.google.android.gms.gcm.GcmNetworkManager;
 import com.google.android.gms.gcm.OneoffTask;
 import com.google.android.gms.gcm.Task;
@@ -45,7 +47,8 @@
      */
     public static void unschedule(Context context) {
         // Get the GCM Network Scheduler.
-        GcmNetworkManager gcmNetworkManager = GcmNetworkManager.getInstance(context);
+        GcmNetworkManager gcmNetworkManager = getGcmNetworkManager(context);
+        if (gcmNetworkManager == null) return;
         gcmNetworkManager.cancelTask(OfflinePageUtils.TASK_TAG, ChromeBackgroundService.class);
     }
 
@@ -56,7 +59,8 @@
     private static void schedule(Context context, TriggerConditions triggerConditions,
             long delayStartSecs, boolean overwrite) {
         // Get the GCM Network Scheduler.
-        GcmNetworkManager gcmNetworkManager = GcmNetworkManager.getInstance(context);
+        GcmNetworkManager gcmNetworkManager = getGcmNetworkManager(context);
+        if (gcmNetworkManager == null) return;
 
         Bundle taskExtras = new Bundle();
         TaskExtrasPacker.packTimeInBundle(taskExtras);
@@ -77,6 +81,14 @@
         gcmNetworkManager.schedule(task);
     }
 
+    private static GcmNetworkManager getGcmNetworkManager(Context context) {
+        if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
+                == ConnectionResult.SUCCESS) {
+            return GcmNetworkManager.getInstance(context);
+        }
+        return null;
+    }
+
     /**
      * Get the latest power conditions from the android APIs.
      */
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 97f9a63c..3b2a603 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1565,6 +1565,7 @@
   "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java",
   "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsUnitTest.java",
   "junit/src/org/chromium/chrome/browser/offlinepages/ShadowGcmNetworkManager.java",
+  "junit/src/org/chromium/chrome/browser/offlinepages/ShadowGoogleApiAvailability.java",
   "junit/src/org/chromium/chrome/browser/offlinepages/StubBackgroundSchedulerProcessor.java",
   "junit/src/org/chromium/chrome/browser/offlinepages/TaskExtrasPackerTest.java",
   "junit/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridgeTest.java",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java
index 21e214a..d09cfd91 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java
@@ -46,9 +46,8 @@
  * Unit tests for BackgroundOfflinerTask.
  */
 @RunWith(OfflinePageTestRunner.class)
-@Config(manifest = Config.NONE,
-        application = BaseChromiumApplication.class,
-        shadows = { ShadowGcmNetworkManager.class })
+@Config(manifest = Config.NONE, application = BaseChromiumApplication.class,
+        shadows = {ShadowGcmNetworkManager.class, ShadowGoogleApiAvailability.class})
 public class BackgroundOfflinerTaskTest {
     private static final boolean REQUIRE_POWER = true;
     private static final boolean REQUIRE_UNMETERED = true;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundSchedulerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundSchedulerTest.java
index 0e22add..2f583a1 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundSchedulerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundSchedulerTest.java
@@ -28,9 +28,8 @@
  * Unit tests for BackgroundScheduler.
  */
 @RunWith(OfflinePageTestRunner.class)
-@Config(manifest = Config.NONE,
-        application = BaseChromiumApplication.class,
-        shadows = {ShadowGcmNetworkManager.class})
+@Config(manifest = Config.NONE, application = BaseChromiumApplication.class,
+        shadows = {ShadowGcmNetworkManager.class, ShadowGoogleApiAvailability.class})
 public class BackgroundSchedulerTest {
     private Context mContext;
     private TriggerConditions mConditions1 = new TriggerConditions(
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java
index bf13eb1..177b962 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java
@@ -4,10 +4,11 @@
 
 package org.chromium.chrome.browser.offlinepages;
 
-import org.chromium.testing.local.LocalRobolectricTestRunner;
 import org.junit.runners.model.InitializationError;
 import org.robolectric.internal.bytecode.InstrumentationConfiguration;
 
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
 /**
  * Custom Robolectric test runner that instruments the com.google.android.gms.gcm package
  * so Shadows of those classes can be created.
@@ -24,6 +25,7 @@
     @Override
     public InstrumentationConfiguration createClassLoaderConfig() {
         InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder();
+        builder.addInstrumentedPackage("com.google.android.gms.common");
         builder.addInstrumentedPackage("com.google.android.gms.gcm");
         return builder.build();
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/ShadowGoogleApiAvailability.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/ShadowGoogleApiAvailability.java
new file mode 100644
index 0000000..bb8bbb1
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/ShadowGoogleApiAvailability.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 org.chromium.chrome.browser.offlinepages;
+
+import android.content.Context;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GoogleApiAvailability;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+/** Custom shadow for the OS's GoogleApiAvailability. */
+@Implements(GoogleApiAvailability.class)
+public class ShadowGoogleApiAvailability {
+    @Implementation
+    public int isGooglePlayServicesAvailable(Context context) {
+        return ConnectionResult.SUCCESS;
+    }
+}
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index 7297916..7452c2d 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -1828,8 +1828,9 @@
   observing_autofill_client->Wait();
 }
 
+// Flaky on official builds (?): https://crbug.com/693717
 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
-                       ShowFormNotSecureOnUsernameField) {
+                       DISABLED_ShowFormNotSecureOnUsernameField) {
   password_manager::ContentPasswordManagerDriverFactory* driver_factory =
       password_manager::ContentPasswordManagerDriverFactory::FromWebContents(
           WebContents());
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
index ca73d98..b313f02 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -53,7 +53,6 @@
       state_prior_to_tab_fullscreen_(STATE_INVALID),
       tab_fullscreen_(false),
       toggled_into_fullscreen_(false),
-      reentrant_window_state_change_call_check_(false),
       is_privileged_fullscreen_for_testing_(false),
       ptr_factory_(this) {
 }
@@ -249,7 +248,6 @@
 }
 
 void FullscreenController::WindowFullscreenStateChanged() {
-  reentrant_window_state_change_call_check_ = true;
   ExclusiveAccessContext* const exclusive_access_context =
       exclusive_access_manager()->context();
   bool exiting_fullscreen = !exclusive_access_context->IsFullscreen();
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.h b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
index 58ce24b..1edfeac 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.h
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
@@ -189,10 +189,6 @@
   // True if this controller has toggled into tab OR browser fullscreen.
   bool toggled_into_fullscreen_;
 
-  // Used to verify that calls we expect to reenter by calling
-  // WindowFullscreenStateChanged do so.
-  bool reentrant_window_state_change_call_check_;
-
   // Used in testing to confirm proper behavior for specific, privileged
   // fullscreen cases.
   bool is_privileged_fullscreen_for_testing_;
diff --git a/chromeos/cert_loader.cc b/chromeos/cert_loader.cc
index 5532300..4e4131ba 100644
--- a/chromeos/cert_loader.cc
+++ b/chromeos/cert_loader.cc
@@ -174,7 +174,7 @@
     observer.OnCertificatesLoaded(*cert_list_, initial_load);
 }
 
-void CertLoader::OnCertDBChanged(const net::X509Certificate* cert) {
+void CertLoader::OnCertDBChanged() {
   VLOG(1) << "OnCertDBChanged";
   LoadCertificates();
 }
diff --git a/chromeos/cert_loader.h b/chromeos/cert_loader.h
index 0a65e76e..7243c6d 100644
--- a/chromeos/cert_loader.h
+++ b/chromeos/cert_loader.h
@@ -104,7 +104,7 @@
   void NotifyCertificatesLoaded(bool initial_load);
 
   // net::CertDatabase::Observer
-  void OnCertDBChanged(const net::X509Certificate* cert) override;
+  void OnCertDBChanged() override;
 
   base::ObserverList<Observer> observers_;
 
diff --git a/chromeos/cert_loader_unittest.cc b/chromeos/cert_loader_unittest.cc
index d2ccb40..c42722b6 100644
--- a/chromeos/cert_loader_unittest.cc
+++ b/chromeos/cert_loader_unittest.cc
@@ -46,7 +46,7 @@
   ~TestNSSCertDatabase() override {}
 
   void NotifyOfCertAdded(const net::X509Certificate* cert) {
-    NSSCertDatabaseChromeOS::NotifyObserversCertDBChanged(nullptr);
+    NSSCertDatabaseChromeOS::NotifyObserversCertDBChanged();
   }
 };
 
diff --git a/components/translate/core/browser/proto/translate_ranker_model.proto b/components/translate/core/browser/proto/translate_ranker_model.proto
index 4ac58b4d..567470b 100644
--- a/components/translate/core/browser/proto/translate_ranker_model.proto
+++ b/components/translate/core/browser/proto/translate_ranker_model.proto
@@ -11,6 +11,7 @@
 package chrome_intelligence;
 
 // Defines a Chrome Ranker Translate model.
+// Next tag: 12
 message TranslateRankerModel {
   // A number that identifies the version of this model.
   optional uint32 version = 1;
@@ -18,9 +19,15 @@
   // Defines the weights and bias of a Logistic Regression Model.
   message LogisticRegressionModel {
     optional float bias = 1;
+
     optional float accept_ratio_weight = 2;
     optional float decline_ratio_weight = 3;
     optional float ignore_ratio_weight = 4;
+
+    optional float accept_count_weight = 9;
+    optional float decline_count_weight = 10;
+    optional float ignore_count_weight = 11;
+
     // One-hot features are encoded in the form of a map. These maps
     // each contain an element 'UNKNOWN' to use in case the key is not
     // found in the map.
diff --git a/components/translate/core/browser/translate_ranker.cc b/components/translate/core/browser/translate_ranker.cc
index fe2a214..1341652 100644
--- a/components/translate/core/browser/translate_ranker.cc
+++ b/components/translate/core/browser/translate_ranker.cc
@@ -136,7 +136,6 @@
   }
 
   DCHECK(model_->has_logistic_regression_model());
-
   SCOPED_UMA_HISTOGRAM_TIMER("Translate.Ranker.Timer.ShouldOfferTranslation");
 
   // TODO(rogerm): Remove ScopedTracker below once crbug.com/646711 is closed.
@@ -147,31 +146,17 @@
   const std::string& app_locale =
       TranslateDownloadManager::GetInstance()->application_locale();
   const std::string& country = translate_prefs.GetCountry();
-  double accept_count = translate_prefs.GetTranslationAcceptedCount(src_lang);
-  double denied_count = translate_prefs.GetTranslationDeniedCount(src_lang);
-  double ignored_count =
-      model_->logistic_regression_model().has_ignore_ratio_weight()
-          ? translate_prefs.GetTranslationIgnoredCount(src_lang)
-          : 0.0;
-  double total_count = accept_count + denied_count + ignored_count;
-  double accept_ratio =
-      (total_count == 0.0) ? 0.0 : (accept_count / total_count);
-  double decline_ratio =
-      (total_count == 0.0) ? 0.0 : (denied_count / total_count);
-  double ignore_ratio =
-      (total_count == 0.0) ? 0.0 : (ignored_count / total_count);
+  int accept_count = translate_prefs.GetTranslationAcceptedCount(src_lang);
+  int decline_count = translate_prefs.GetTranslationDeniedCount(src_lang);
+  int ignore_count = translate_prefs.GetTranslationIgnoredCount(src_lang);
   DVLOG(3) << "TranslateRanker: features=["
            << "src_lang='" << src_lang << "', dst_lang='" << dst_lang
            << "', country='" << country << "', locale='" << app_locale
            << ", accept_count=" << accept_count
-           << ", denied_count=" << denied_count
-           << ", ignored_count=" << ignored_count
-           << ", total_count=" << total_count
-           << ", accept_ratio=" << accept_ratio
-           << ", decline_ratio=" << decline_ratio
-           << ", ignore_ratio=" << ignore_ratio << "]";
+           << ", decline_count=" << decline_count
+           << ", ignore_count=" << ignore_count << "]";
 
-  double score = CalculateScore(accept_ratio, decline_ratio, ignore_ratio,
+  double score = CalculateScore(accept_count, decline_count, ignore_count,
                                 src_lang, dst_lang, app_locale, country);
 
   DVLOG(2) << "TranslateRanker Score: " << score;
@@ -185,9 +170,9 @@
 
 TranslateRanker::TranslateRanker() {}
 
-double TranslateRanker::CalculateScore(double accept_ratio,
-                                       double decline_ratio,
-                                       double ignore_ratio,
+double TranslateRanker::CalculateScore(int accept_count,
+                                       int decline_count,
+                                       int ignore_count,
                                        const std::string& src_lang,
                                        const std::string& dst_lang,
                                        const std::string& locale,
@@ -195,12 +180,28 @@
   SCOPED_UMA_HISTOGRAM_TIMER("Translate.Ranker.Timer.CalculateScore");
   DCHECK(model_ != nullptr);
   DCHECK(model_->has_logistic_regression_model());
+
+  int total_count = accept_count + decline_count + ignore_count;
+  double accept_ratio =
+      (total_count == 0) ? 0.0 : (double(accept_count) / total_count);
+  double decline_ratio =
+      (total_count == 0) ? 0.0 : (double(decline_count) / total_count);
+  double ignore_ratio =
+      (total_count == 0) ? 0.0 : (double(ignore_count) / total_count);
+  DVLOG(3) << "TranslateRanker: ratios=["
+           << ", accept_ratio=" << accept_ratio
+           << ", decline_ratio=" << decline_ratio
+           << ", ignore_ratio=" << ignore_ratio << "]";
+
   const chrome_intelligence::TranslateRankerModel::LogisticRegressionModel&
       logit = model_->logistic_regression_model();
   double dot_product =
       (accept_ratio * logit.accept_ratio_weight()) +
       (decline_ratio * logit.decline_ratio_weight()) +
       (ignore_ratio * logit.ignore_ratio_weight()) +
+      (accept_count * logit.accept_count_weight()) +
+      (decline_count * logit.decline_count_weight()) +
+      (ignore_count * logit.ignore_count_weight()) +
       ScoreComponent(logit.source_language_weight(), src_lang) +
       ScoreComponent(logit.dest_language_weight(), dst_lang) +
       ScoreComponent(logit.country_weight(), country) +
@@ -289,6 +290,8 @@
   ReportModelStatus(MODEL_STATUS_OK);
   model_ = std::move(new_model);
   model_fetcher_.reset();
+
+  DVLOG(3) << "Successfully loaded model version " << GetModelVersion() << ".";
 }
 
 void TranslateRanker::FlushTranslateEvents(
diff --git a/components/translate/core/browser/translate_ranker.h b/components/translate/core/browser/translate_ranker.h
index d8ed8ab..bb2da8b 100644
--- a/components/translate/core/browser/translate_ranker.h
+++ b/components/translate/core/browser/translate_ranker.h
@@ -88,9 +88,9 @@
   TranslateRanker();
 
   // Exposed for testing via FRIEND_TEST.
-  double CalculateScore(double accept_ratio,
-                        double decline_ratio,
-                        double ignore_ratio,
+  double CalculateScore(int accept_count,
+                        int decline_count,
+                        int ignore_count,
                         const std::string& src_lang,
                         const std::string& dst_lang,
                         const std::string& app_locale,
diff --git a/components/translate/core/browser/translate_ranker_unittest.cc b/components/translate/core/browser/translate_ranker_unittest.cc
index 2c24bc9..495a1b861 100644
--- a/components/translate/core/browser/translate_ranker_unittest.cc
+++ b/components/translate/core/browser/translate_ranker_unittest.cc
@@ -57,6 +57,8 @@
     details->set_bias(bias);
     details->set_accept_ratio_weight(0.02f);
     details->set_decline_ratio_weight(0.03f);
+    details->set_accept_count_weight(0.13f);
+    details->set_decline_count_weight(-0.14f);
 
     auto& src_language_weight = *details->mutable_source_language_weight();
     src_language_weight["en"] = 0.04f;
@@ -156,9 +158,12 @@
   std::unique_ptr<translate::TranslateRanker> ranker = GetRankerForTest(0.01f);
   // Calculate the score using: a 50:50 accept/decline ratio; the one-hot
   // values for the src lang, dest lang, locale and counry; and, the bias.
-  double expected = Sigmoid(0.5 * 0.02f +  // accept ratio * weight
-                            0.5 * 0.03f +  // decline ratio * weight
-                            0.0 * 0.00f +  // ignore ratio * (default) weight
+  double expected = Sigmoid(0.5 * 0.02f +    // accept ratio * weight
+                            0.5 * 0.03f +    // decline ratio * weight
+                            0.0 * 0.00f +    // ignore ratio * (default) weight
+                            50.0 * 0.13f +   // accept count * weight
+                            50.0 * -0.14f +  // decline count * weight
+                            0.0 * 0.00f +    // ignore count * (default) weight
                             1.0 * 0.04f +  // one-hot src-language "en" * weight
                             1.0 * 0.00f +  // one-hot dst-language "fr" * weight
                             1.0 * 0.07f +  // one-hot country * weight
@@ -166,7 +171,7 @@
                             0.01f);        // bias
 
   EXPECT_NEAR(expected,
-              ranker->CalculateScore(0.5, 0.5, 0.0, "en", "fr", "zh-CN", "us"),
+              ranker->CalculateScore(50, 50, 0, "en", "fr", "zh-CN", "us"),
               0.000001);
 }
 
diff --git a/media/formats/mp4/aac.cc b/media/formats/mp4/aac.cc
index bbb24ad..cbabddb0 100644
--- a/media/formats/mp4/aac.cc
+++ b/media/formats/mp4/aac.cc
@@ -149,12 +149,6 @@
   }
   DCHECK(channel_layout_ != CHANNEL_LAYOUT_NONE);
 
-  MEDIA_LOG(INFO, media_log)
-      << "Audio codec: mp4a.40." << static_cast<int>(profile_)
-      << ". Sampling frequency: " << frequency_ << "Hz"
-      << ". Sampling frequency(Extension): " << extension_frequency_ << "Hz"
-      << ". Channel layout: " << channel_layout_ << ".";
-
   return true;
 }
 
diff --git a/media/formats/mp4/aac_unittest.cc b/media/formats/mp4/aac_unittest.cc
index 6a05cf0..645dbe8 100644
--- a/media/formats/mp4/aac_unittest.cc
+++ b/media/formats/mp4/aac_unittest.cc
@@ -20,26 +20,6 @@
 
 namespace mp4 {
 
-MATCHER_P(AudioProfileLog, profile_string, "") {
-  return CONTAINS_STRING(arg,
-                         "Audio codec: " + std::string(profile_string) + ".");
-}
-
-MATCHER_P(AudioSamplingFrequencyLog, frequency_string, "") {
-  return CONTAINS_STRING(
-      arg, "Sampling frequency: " + std::string(frequency_string) + "Hz.");
-}
-
-MATCHER_P(AudioExtensionSamplingFrequencyLog, ex_string, "") {
-  return CONTAINS_STRING(
-      arg, "Sampling frequency(Extension): " + std::string(ex_string) + "Hz.");
-}
-
-MATCHER_P(AudioChannelLayoutLog, layout_string, "") {
-  return CONTAINS_STRING(
-      arg, "Channel layout: " + std::string(layout_string) + ".");
-}
-
 MATCHER_P(UnsupportedFrequencyIndexLog, frequency_index, "") {
   return CONTAINS_STRING(
       arg,
@@ -85,10 +65,6 @@
 
   data.assign(buffer, buffer + sizeof(buffer));
 
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.2"),
-                         AudioSamplingFrequencyLog("44100"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("3")));
   EXPECT_TRUE(Parse(data));
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(false), 44100);
   EXPECT_EQ(aac_.GetChannelLayout(false), CHANNEL_LAYOUT_STEREO);
@@ -100,10 +76,6 @@
 
   data.assign(buffer, buffer + sizeof(buffer));
 
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.2"),
-                         AudioSamplingFrequencyLog("24000"),
-                         AudioExtensionSamplingFrequencyLog("48000"),
-                         AudioChannelLayoutLog("3")));
   EXPECT_TRUE(Parse(data));
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(false), 48000);
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(true), 48000);
@@ -120,10 +92,6 @@
 
   data.assign(buffer, buffer + sizeof(buffer));
 
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.2"),
-                         AudioSamplingFrequencyLog("24000"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("2")));
   EXPECT_TRUE(Parse(data));
 
   // Test w/o implict SBR.
@@ -142,10 +110,6 @@
 
   data.assign(buffer, buffer + sizeof(buffer));
 
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.2"),
-                         AudioSamplingFrequencyLog("24000"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("3")));
   EXPECT_TRUE(Parse(data));
 
   // Test w/o implict SBR.
@@ -163,10 +127,6 @@
 
   data.assign(buffer, buffer + sizeof(buffer));
 
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.2"),
-                         AudioSamplingFrequencyLog("48000"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("12")));
   EXPECT_TRUE(Parse(data));
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(false), 48000);
   EXPECT_EQ(aac_.GetChannelLayout(false), CHANNEL_LAYOUT_5_1_BACK);
@@ -191,10 +151,7 @@
   EXPECT_FALSE(Parse(data));
 
   data[0] = 0x08;
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.1"),
-                         AudioSamplingFrequencyLog("96000"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("2")));
+
   EXPECT_TRUE(Parse(data));
 
   data[0] = 0x28;
@@ -212,10 +169,6 @@
 
   data[0] = 0x0e;
   data[1] = 0x08;
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.1"),
-                         AudioSamplingFrequencyLog("7350"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("2")));
   EXPECT_TRUE(Parse(data));
 }
 
@@ -227,10 +180,6 @@
   EXPECT_FALSE(Parse(data));
 
   data[1] = 0x08;
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.1"),
-                         AudioSamplingFrequencyLog("7350"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("2")));
   EXPECT_TRUE(Parse(data));
 }
 
@@ -245,10 +194,6 @@
 
   data[0] = 0x12;
   data[1] = 0x18;
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.2"),
-                         AudioSamplingFrequencyLog("44100"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("5")));
   EXPECT_TRUE(Parse(data));
 }
 
@@ -262,10 +207,6 @@
   EXPECT_FALSE(Parse(data));
 
   data[1] = 0x18;
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.2"),
-                         AudioSamplingFrequencyLog("44100"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("5")));
   EXPECT_TRUE(Parse(data));
 }
 
@@ -279,10 +220,6 @@
   EXPECT_FALSE(Parse(data));
 
   data[0] = 0x13;
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.2"),
-                         AudioSamplingFrequencyLog("24000"),
-                         AudioExtensionSamplingFrequencyLog("0"),
-                         AudioChannelLayoutLog("3")));
   EXPECT_TRUE(Parse(data));
 }
 
@@ -296,10 +233,6 @@
   EXPECT_FALSE(Parse(data));
 
   data[1] = 0x11;
-  EXPECT_MEDIA_LOG(AllOf(AudioProfileLog("mp4a.40.2"),
-                         AudioSamplingFrequencyLog("64000"),
-                         AudioExtensionSamplingFrequencyLog("64000"),
-                         AudioChannelLayoutLog("3")));
   EXPECT_TRUE(Parse(data));
 }
 
diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc
index b6ea088a..558367e7 100644
--- a/media/formats/mp4/box_definitions.cc
+++ b/media/formats/mp4/box_definitions.cc
@@ -610,11 +610,6 @@
     RCHECK(reader->Read2(&sps_length) &&
            reader->ReadVec(&sps_list[i], sps_length));
     RCHECK(sps_list[i].size() > 4);
-
-    if (media_log.get()) {
-      MEDIA_LOG(INFO, media_log) << "Video codec: avc1."
-                                 << base::HexEncode(sps_list[i].data() + 1, 3);
-    }
   }
 
   uint8_t num_pps;
@@ -815,11 +810,6 @@
 
   object_type = es_desc.object_type();
 
-  if (object_type != 0x40) {
-    MEDIA_LOG(INFO, reader->media_log()) << "Audio codec: mp4a." << std::hex
-                                         << static_cast<int>(object_type);
-  }
-
   if (es_desc.IsAAC(object_type))
     RCHECK(aac.Parse(es_desc.decoder_specific_info(), reader->media_log()));
 
diff --git a/media/formats/mp4/hevc.cc b/media/formats/mp4/hevc.cc
index 817c172..de8fe962 100644
--- a/media/formats/mp4/hevc.cc
+++ b/media/formats/mp4/hevc.cc
@@ -116,10 +116,6 @@
     }
   }
 
-  if (media_log.get()) {
-    MEDIA_LOG(INFO, media_log) << "Video codec: hevc";
-  }
-
   return true;
 }
 
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc
index c2168a6..ba32379 100644
--- a/media/formats/mp4/mp4_stream_parser_unittest.cc
+++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -40,14 +40,6 @@
 namespace mp4 {
 
 // Matchers for verifying common media log entry strings.
-MATCHER_P(VideoCodecLog, codec_string, "") {
-  return CONTAINS_STRING(arg, "Video codec: " + std::string(codec_string));
-}
-
-MATCHER_P(AudioCodecLog, codec_string, "") {
-  return CONTAINS_STRING(arg, "Audio codec: " + std::string(codec_string));
-}
-
 MATCHER(SampleEncryptionInfoUnavailableLog, "") {
   return CONTAINS_STRING(arg, "Sample encryption info is not available.");
 }
@@ -237,16 +229,12 @@
 TEST_F(MP4StreamParserTest, UnalignedAppend) {
   // Test small, non-segment-aligned appends (small enough to exercise
   // incremental append system)
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F"));
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2"));
   InitializeParser();
   ParseMP4File("bear-1280x720-av_frag.mp4", 512);
 }
 
 TEST_F(MP4StreamParserTest, BytewiseAppend) {
   // Ensure no incremental errors occur when parsing
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F"));
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2"));
   InitializeParser();
   ParseMP4File("bear-1280x720-av_frag.mp4", 1);
 }
@@ -254,16 +242,12 @@
 TEST_F(MP4StreamParserTest, MultiFragmentAppend) {
   // Large size ensures multiple fragments are appended in one call (size is
   // larger than this particular test file)
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F"));
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2"));
   InitializeParser();
   ParseMP4File("bear-1280x720-av_frag.mp4", 768432);
 }
 
 TEST_F(MP4StreamParserTest, Flush) {
   // Flush while reading sample data, then start a new stream.
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F")).Times(2);
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2")).Times(2);
   InitializeParser();
 
   scoped_refptr<DecoderBuffer> buffer =
@@ -276,8 +260,6 @@
 }
 
 TEST_F(MP4StreamParserTest, Reinitialization) {
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F")).Times(2);
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2")).Times(2);
   InitializeParser();
 
   scoped_refptr<DecoderBuffer> buffer =
@@ -291,8 +273,6 @@
 }
 
 TEST_F(MP4StreamParserTest, UnknownDuration_V0_AllBitsSet) {
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F"));
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2"));
   InitializeParser();
   // 32 bit duration field in mvhd box, all bits set.
   ParseMP4File(
@@ -306,8 +286,6 @@
   std::set<int> audio_object_types;
   audio_object_types.insert(kISO_13818_7_AAC_LC);
   parser_.reset(new MP4StreamParser(audio_object_types, false));
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.67"));
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2"));
   auto params = GetDefaultInitParametersExpectations();
   params.detected_video_track_count = 0;
   InitializeParserWithInitParametersExpectations(params);
@@ -316,8 +294,6 @@
 
 // Test that a moov box is not always required after Flush() is called.
 TEST_F(MP4StreamParserTest, NoMoovAfterFlush) {
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F"));
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2"));
   InitializeParser();
 
   scoped_refptr<DecoderBuffer> buffer =
@@ -350,7 +326,6 @@
 
   scoped_refptr<DecoderBuffer> buffer =
       ReadTestDataFile("bear-1280x720-a_frag-cenc_missing-saiz-saio.mp4");
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2")).Times(2);
   EXPECT_MEDIA_LOG(SampleEncryptionInfoUnavailableLog());
   EXPECT_FALSE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
 }
@@ -358,7 +333,6 @@
 // Test a file where all video samples start with an Access Unit
 // Delimiter (AUD) NALU.
 TEST_F(MP4StreamParserTest, VideoSamplesStartWithAUDs) {
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.4D4028"));
   auto params = GetDefaultInitParametersExpectations();
   params.detected_audio_track_count = 0;
   InitializeParserWithInitParametersExpectations(params);
@@ -368,7 +342,6 @@
 TEST_F(MP4StreamParserTest, HEVC_in_MP4_container) {
 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
   bool expect_success = true;
-  EXPECT_MEDIA_LOG(VideoCodecLog("hevc"));
 #else
   bool expect_success = false;
   EXPECT_MEDIA_LOG(ErrorLog("Parse unsupported video format hev1"));
@@ -401,7 +374,6 @@
 
   scoped_refptr<DecoderBuffer> buffer =
       ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F"));
   EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
 }
 
@@ -416,7 +388,6 @@
 
   scoped_refptr<DecoderBuffer> buffer =
       ReadTestDataFile("bear-640x360-v_frag-cenc-senc.mp4");
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001E"));
   EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
 }
 
@@ -430,7 +401,6 @@
   scoped_refptr<DecoderBuffer> buffer =
       ReadTestDataFile("bear-640x360-non_square_pixel-without_pasp.mp4");
 
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001E"));
   EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
   EXPECT_EQ(gfx::Size(639, 360), video_decoder_config_.natural_size());
 }
@@ -445,7 +415,6 @@
   scoped_refptr<DecoderBuffer> buffer =
       ReadTestDataFile("bear-640x360-non_square_pixel-with_pasp.mp4");
 
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001E"));
   EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
   EXPECT_EQ(gfx::Size(639, 360), video_decoder_config_.natural_size());
 }
@@ -510,8 +479,6 @@
 }
 
 TEST_F(MP4StreamParserTest, MediaTrackInfoSourcing) {
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F"));
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2"));
   InitializeParser();
   ParseMP4File("bear-1280x720-av_frag.mp4", 4096);
 
@@ -539,8 +506,6 @@
   scoped_refptr<DecoderBuffer> buffer =
       ReadTestDataFile("bear-1280x720-avt_subt_frag.mp4");
 
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2"));
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F"));
   EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
 }
 
@@ -551,8 +516,6 @@
   params.detected_audio_track_count = 2;
   params.detected_video_track_count = 2;
   InitializeParserWithInitParametersExpectations(params);
-  EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64000D")).Times(2);
-  EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2")).Times(2);
   ParseMP4File("bbb-320x240-2video-2audio.mp4", 4096);
 
   EXPECT_EQ(media_tracks_->tracks().size(), 4u);
diff --git a/net/cert/caching_cert_verifier.cc b/net/cert/caching_cert_verifier.cc
index 342adf8..15a48ae 100644
--- a/net/cert/caching_cert_verifier.cc
+++ b/net/cert/caching_cert_verifier.cc
@@ -198,7 +198,7 @@
   }
 }
 
-void CachingCertVerifier::OnCertDBChanged(const X509Certificate* cert) {
+void CachingCertVerifier::OnCertDBChanged() {
   ClearCache();
 }
 
diff --git a/net/cert/caching_cert_verifier.h b/net/cert/caching_cert_verifier.h
index 57a61428..a6878b2 100644
--- a/net/cert/caching_cert_verifier.h
+++ b/net/cert/caching_cert_verifier.h
@@ -144,7 +144,7 @@
                         int error);
 
   // CertDatabase::Observer methods:
-  void OnCertDBChanged(const X509Certificate* cert) override;
+  void OnCertDBChanged() override;
 
   // For unit testing.
   void ClearCache();
diff --git a/net/cert/cert_database.cc b/net/cert/cert_database.cc
index d2ef9ff..51f0005 100644
--- a/net/cert/cert_database.cc
+++ b/net/cert/cert_database.cc
@@ -25,9 +25,8 @@
   observer_list_->RemoveObserver(observer);
 }
 
-void CertDatabase::NotifyObserversCertDBChanged(const X509Certificate* cert) {
-  observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged,
-                         base::RetainedRef(cert));
+void CertDatabase::NotifyObserversCertDBChanged() {
+  observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged);
 }
 
 }  // namespace net
diff --git a/net/cert/cert_database.h b/net/cert/cert_database.h
index 819716a..b44b78ce 100644
--- a/net/cert/cert_database.h
+++ b/net/cert/cert_database.h
@@ -43,7 +43,7 @@
     // Typically, this will be in response to a CA certificate being added,
     // removed, or its trust changed, but may also signal on client
     // certificate events when they can be reliably detected.
-    virtual void OnCertDBChanged(const X509Certificate* cert) {}
+    virtual void OnCertDBChanged() {}
 
    protected:
     Observer() {}
@@ -86,7 +86,7 @@
   // Synthetically injects notifications to all observers. In general, this
   // should only be called by the creator of the CertDatabase. Used to inject
   // notifcations from other DB interfaces.
-  void NotifyObserversCertDBChanged(const X509Certificate* cert);
+  void NotifyObserversCertDBChanged();
 
  private:
   friend struct base::DefaultSingletonTraits<CertDatabase>;
diff --git a/net/cert/cert_database_android.cc b/net/cert/cert_database_android.cc
index b3a75b09a..8cde45e2 100644
--- a/net/cert/cert_database_android.cc
+++ b/net/cert/cert_database_android.cc
@@ -18,7 +18,7 @@
 CertDatabase::~CertDatabase() {}
 
 void CertDatabase::OnAndroidKeyStoreChanged() {
-  NotifyObserversCertDBChanged(NULL);
+  NotifyObserversCertDBChanged();
   // Dump the OpenSSLClientKeyStore to drop references to now disconnected
   // PrivateKeys stored in the in-memory key store. Note: this assumes that
   // every SSLClientAuthCache is dumped as part of notifying
@@ -28,7 +28,7 @@
 }
 
 void CertDatabase::OnAndroidKeyChainChanged() {
-  observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged, nullptr);
+  observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged);
 }
 
 }  // namespace net
diff --git a/net/cert/cert_database_mac.cc b/net/cert/cert_database_mac.cc
index 34088e2..98f8dc9 100644
--- a/net/cert/cert_database_mac.cc
+++ b/net/cert/cert_database_mac.cc
@@ -104,7 +104,7 @@
   switch (keychain_event) {
     case kSecKeychainListChangedEvent:
     case kSecTrustSettingsChangedEvent:
-      that->cert_db_->NotifyObserversCertDBChanged(NULL);
+      that->cert_db_->NotifyObserversCertDBChanged();
       break;
 
     default:
diff --git a/net/cert/nss_cert_database.cc b/net/cert/nss_cert_database.cc
index 33440b3..14aa891 100644
--- a/net/cert/nss_cert_database.cc
+++ b/net/cert/nss_cert_database.cc
@@ -51,9 +51,7 @@
 
   ~CertNotificationForwarder() override {}
 
-  void OnCertDBChanged(const X509Certificate* cert) override {
-    cert_db_->NotifyObserversCertDBChanged(cert);
-  }
+  void OnCertDBChanged() override { cert_db_->NotifyObserversCertDBChanged(); }
 
  private:
   CertDatabase* cert_db_;
@@ -184,7 +182,7 @@
                                         is_extractable,
                                         imported_certs);
   if (result == OK)
-    NotifyObserversCertDBChanged(NULL);
+    NotifyObserversCertDBChanged();
 
   return result;
 }
@@ -226,7 +224,7 @@
   int result = psm::ImportUserCert(certificates);
 
   if (result == OK)
-    NotifyObserversCertDBChanged(NULL);
+    NotifyObserversCertDBChanged();
 
   return result;
 }
@@ -237,7 +235,7 @@
   int result = psm::ImportUserCert(certificates);
 
   if (result == OK)
-    NotifyObserversCertDBChanged(NULL);
+    NotifyObserversCertDBChanged();
 
   return result;
 }
@@ -250,7 +248,7 @@
   bool success = psm::ImportCACerts(
       slot.get(), certificates, root, trust_bits, not_imported);
   if (success)
-    NotifyObserversCertDBChanged(NULL);
+    NotifyObserversCertDBChanged();
 
   return success;
 }
@@ -368,7 +366,7 @@
                                 TrustBits trust_bits) {
   bool success = psm::SetCertTrust(cert, type, trust_bits);
   if (success)
-    NotifyObserversCertDBChanged(cert);
+    NotifyObserversCertDBChanged();
 
   return success;
 }
@@ -376,7 +374,7 @@
 bool NSSCertDatabase::DeleteCertAndKey(X509Certificate* cert) {
   if (!DeleteCertAndKeyImpl(cert))
     return false;
-  NotifyObserversCertDBChanged(cert);
+  NotifyObserversCertDBChanged();
   return true;
 }
 
@@ -390,7 +388,7 @@
                      .MayBlock(),
       base::Bind(&NSSCertDatabase::DeleteCertAndKeyImpl, cert),
       base::Bind(&NSSCertDatabase::NotifyCertRemovalAndCallBack,
-                 weak_factory_.GetWeakPtr(), cert, callback));
+                 weak_factory_.GetWeakPtr(), callback));
 }
 
 bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const {
@@ -432,18 +430,15 @@
 }
 
 void NSSCertDatabase::NotifyCertRemovalAndCallBack(
-    scoped_refptr<X509Certificate> cert,
     const DeleteCertCallback& callback,
     bool success) {
   if (success)
-    NotifyObserversCertDBChanged(cert.get());
+    NotifyObserversCertDBChanged();
   callback.Run(success);
 }
 
-void NSSCertDatabase::NotifyObserversCertDBChanged(
-    const X509Certificate* cert) {
-  observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged,
-                         base::RetainedRef(cert));
+void NSSCertDatabase::NotifyObserversCertDBChanged() {
+  observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged);
 }
 
 // static
diff --git a/net/cert/nss_cert_database.h b/net/cert/nss_cert_database.h
index f52995e..d096f18 100644
--- a/net/cert/nss_cert_database.h
+++ b/net/cert/nss_cert_database.h
@@ -41,10 +41,9 @@
    public:
     virtual ~Observer() {}
 
-    // Will be called when a CA certificate is changed.
-    // Called with |cert| == NULL after importing a list of certificates
-    // in ImportCACerts().
-    virtual void OnCertDBChanged(const X509Certificate* cert) {}
+    // Will be called when a certificate is added, removed, or trust settings
+    // are changed.
+    virtual void OnCertDBChanged() {}
 
    protected:
     Observer() {}
@@ -246,7 +245,7 @@
 
  protected:
   // Broadcasts notifications to all registered observers.
-  void NotifyObserversCertDBChanged(const X509Certificate* cert);
+  void NotifyObserversCertDBChanged();
 
  private:
   // Registers |observer| to receive notifications of certificate changes.  The
@@ -261,10 +260,9 @@
   // on the same thread on which AddObserver() was called.
   void RemoveObserver(Observer* observer);
 
-  // Notifies observers of the removal of |cert| and calls |callback| with
+  // Notifies observers of the removal of a cert and calls |callback| with
   // |success| as argument.
-  void NotifyCertRemovalAndCallBack(scoped_refptr<X509Certificate> cert,
-                                    const DeleteCertCallback& callback,
+  void NotifyCertRemovalAndCallBack(const DeleteCertCallback& callback,
                                     bool success);
 
   // Certificate removal implementation used by |DeleteCertAndKey*|. Static so
diff --git a/net/cert/nss_cert_database_chromeos_unittest.cc b/net/cert/nss_cert_database_chromeos_unittest.cc
index 1171041..e5e3606 100644
--- a/net/cert/nss_cert_database_chromeos_unittest.cc
+++ b/net/cert/nss_cert_database_chromeos_unittest.cc
@@ -52,6 +52,7 @@
   NSSCertDatabaseChromeOSTest()
       : scoped_task_scheduler_(base::MessageLoop::current()),
         observer_added_(false),
+        db_changed_count_(0),
         user_1_("user1"),
         user_2_("user2") {}
 
@@ -88,16 +89,13 @@
   }
 
   // CertDatabase::Observer:
-  void OnCertDBChanged(const X509Certificate* cert) override {
-    added_ca_.push_back(cert ? cert->os_cert_handle() : NULL);
-  }
+  void OnCertDBChanged() override { db_changed_count_++; }
 
  protected:
   base::test::ScopedTaskScheduler scoped_task_scheduler_;
 
   bool observer_added_;
-  // Certificates that were passed to the CertDatabase observers.
-  std::vector<CERTCertificate*> added_ca_;
+  int db_changed_count_;
 
   crypto::ScopedTestNSSChromeOSUser user_1_;
   crypto::ScopedTestNSSChromeOSUser user_2_;
@@ -179,11 +177,7 @@
   // Run the message loop so the observer notifications get processed.
   base::RunLoop().RunUntilIdle();
   // Should have gotten two OnCertDBChanged notifications.
-  ASSERT_EQ(2U, added_ca_.size());
-  // TODO(mattm): make NSSCertDatabase actually pass the cert to the callback,
-  // and enable these checks:
-  // EXPECT_EQ(certs_1[0]->os_cert_handle(), added_ca_[0]);
-  // EXPECT_EQ(certs_2[0]->os_cert_handle(), added_ca_[1]);
+  ASSERT_EQ(2, db_changed_count_);
 
   // Tests that the new certs are loaded by async ListCerts method.
   CertificateList user_1_certlist_async;
@@ -247,7 +241,7 @@
   base::RunLoop().RunUntilIdle();
   // TODO(mattm): ImportServerCert doesn't actually cause any observers to
   // fire. Is that correct?
-  EXPECT_EQ(0U, added_ca_.size());
+  EXPECT_EQ(0, db_changed_count_);
 
   // Tests that the new certs are loaded by async ListCerts method.
   CertificateList user_1_certlist_async;
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index 6e63b9be0..24ff534 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -1558,7 +1558,7 @@
   CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
 }
 
-void QuicStreamFactory::OnCertDBChanged(const X509Certificate* cert) {
+void QuicStreamFactory::OnCertDBChanged() {
   // We should flush the sessions if we removed trust from a
   // cert, because a previously trusted server may have become
   // untrusted.
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h
index 2d01e34..966f3b2 100644
--- a/net/quic/chromium/quic_stream_factory.h
+++ b/net/quic/chromium/quic_stream_factory.h
@@ -360,7 +360,7 @@
   // CertDatabase::Observer methods:
 
   // We close all sessions when certificate database is changed.
-  void OnCertDBChanged(const X509Certificate* cert) override;
+  void OnCertDBChanged() override;
 
   bool require_confirmation() const { return require_confirmation_; }
 
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index 4b9f10f..19d40b5e 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -4360,7 +4360,7 @@
                                          net_log_, CompletionCallback()));
 
   // Change the CA cert and verify that stream saw the event.
-  factory_->OnCertDBChanged(nullptr);
+  factory_->OnCertDBChanged();
   EXPECT_EQ(ERR_CERT_DATABASE_CHANGED,
             stream->ReadResponseHeaders(callback_.callback()));
   EXPECT_FALSE(factory_->require_confirmation());
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index 78e5abc..908e3191 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -33,7 +33,7 @@
     CertDatabase::GetInstance()->RemoveObserver(this);
   }
 
-  void OnCertDBChanged(const X509Certificate* cert) override {
+  void OnCertDBChanged() override {
     // Flush sockets whenever CA trust changes.
     ClearSSLSessionCache();
   }
diff --git a/net/socket/client_socket_pool_manager_impl.cc b/net/socket/client_socket_pool_manager_impl.cc
index 26348cbb7..0e917283 100644
--- a/net/socket/client_socket_pool_manager_impl.cc
+++ b/net/socket/client_socket_pool_manager_impl.cc
@@ -356,7 +356,7 @@
   return std::move(list);
 }
 
-void ClientSocketPoolManagerImpl::OnCertDBChanged(const X509Certificate* cert) {
+void ClientSocketPoolManagerImpl::OnCertDBChanged() {
   FlushSocketPoolsWithError(ERR_NETWORK_CHANGED);
 }
 
diff --git a/net/socket/client_socket_pool_manager_impl.h b/net/socket/client_socket_pool_manager_impl.h
index f2f4e7e..7aea01f 100644
--- a/net/socket/client_socket_pool_manager_impl.h
+++ b/net/socket/client_socket_pool_manager_impl.h
@@ -79,7 +79,7 @@
   std::unique_ptr<base::Value> SocketPoolInfoToValue() const override;
 
   // CertDatabase::Observer methods:
-  void OnCertDBChanged(const X509Certificate* cert) override;
+  void OnCertDBChanged() override;
 
   void DumpMemoryStats(
       base::trace_event::ProcessMemoryDump* pmd,
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index 7af02fc..b014e51 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -368,7 +368,7 @@
   CloseCurrentSessions(ERR_NETWORK_CHANGED);
 }
 
-void SpdySessionPool::OnCertDBChanged(const X509Certificate* cert) {
+void SpdySessionPool::OnCertDBChanged() {
   CloseCurrentSessions(ERR_CERT_DATABASE_CHANGED);
 }
 
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h
index 661501f1..fc82c40 100644
--- a/net/spdy/spdy_session_pool.h
+++ b/net/spdy/spdy_session_pool.h
@@ -154,7 +154,7 @@
 
   // We perform the same flushing as described above when certificate database
   // is changed.
-  void OnCertDBChanged(const X509Certificate* cert) override;
+  void OnCertDBChanged() override;
 
   void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
                        const std::string& parent_dump_absolute_name) const;
diff --git a/net/ssl/ssl_client_auth_cache.cc b/net/ssl/ssl_client_auth_cache.cc
index 8b822bc..bfc5ade 100644
--- a/net/ssl/ssl_client_auth_cache.cc
+++ b/net/ssl/ssl_client_auth_cache.cc
@@ -44,7 +44,7 @@
   cache_.erase(server);
 }
 
-void SSLClientAuthCache::OnCertDBChanged(const X509Certificate* cert) {
+void SSLClientAuthCache::OnCertDBChanged() {
   cache_.clear();
 }
 
diff --git a/net/ssl/ssl_client_auth_cache.h b/net/ssl/ssl_client_auth_cache.h
index a19929b..51b496f 100644
--- a/net/ssl/ssl_client_auth_cache.h
+++ b/net/ssl/ssl_client_auth_cache.h
@@ -53,7 +53,7 @@
   void Remove(const HostPortPair& server);
 
   // CertDatabase::Observer methods:
-  void OnCertDBChanged(const X509Certificate* cert) override;
+  void OnCertDBChanged() override;
 
  private:
   typedef HostPortPair AuthCacheKey;
diff --git a/net/ssl/ssl_client_auth_cache_unittest.cc b/net/ssl/ssl_client_auth_cache_unittest.cc
index d934f5c..c6b608b 100644
--- a/net/ssl/ssl_client_auth_cache_unittest.cc
+++ b/net/ssl/ssl_client_auth_cache_unittest.cc
@@ -194,7 +194,7 @@
   EXPECT_TRUE(cache.Lookup(server2, &cached_cert, &cached_pkey));
   EXPECT_EQ(nullptr, cached_cert.get());
 
-  cache.OnCertDBChanged(nullptr);
+  cache.OnCertDBChanged();
 
   // Check that we no longer have entries for either server.
   EXPECT_FALSE(cache.Lookup(server1, &cached_cert, &cached_pkey));
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
index 1bb9756d..e181286c 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
@@ -7,11 +7,6 @@
 #  Console error messages are wrongly ordered.
 crbug.com/551000 http/tests/inspector/console-resource-errors.html [ Failure ]
 crbug.com/551000 virtual/mojo-loading/http/tests/inspector/console-resource-errors.html [ Failure ]
-#  We don't report the right initiator type or line number.
-crbug.com/551000 http/tests/inspector/network/network-document-initiator.html [ Failure ]
-crbug.com/551000 http/tests/inspector/network/network-initiator.html [ Failure ]
-crbug.com/551000 virtual/mojo-loading/http/tests/inspector/network/network-document-initiator.html [ Failure ]
-crbug.com/551000 virtual/mojo-loading/http/tests/inspector/network/network-initiator.html [ Failure ]
 
 #  Forward redirect info to the renderer. Fixed by https://codereview.chromium.org/2653953005/.
 crbug.com/551000 http/tests/inspector/extensions-network-redirect.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt
index cd4ddd2..33b98ec 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 15: Done.
+CONSOLE MESSAGE: line 14: Done.
 Tests resources initiator for images initiated by IMG tag, static CSS, CSS class added from JavaScript and XHR.
 
 Bug 65105  
@@ -7,9 +7,9 @@
 http://127.0.0.1:8000/inspector/network/resources/resource.php?type=image&random=1&size=100: parser
     http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 4
 http://127.0.0.1:8000/inspector/network/resources/resource.php?type=image&random=1&size=400: script
-    loadData http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 13
+    loadData http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 12
 http://127.0.0.1:8000/inspector/network/resources/style.css: parser
     http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 7
 http://127.0.0.1:8000/inspector/network/resources/empty.html: parser
-    http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 8
+    http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 16
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/network-initiator-frame.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/network-initiator-frame.html
index 78e2d64..84ab44d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/network-initiator-frame.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/network-initiator-frame.html
@@ -6,7 +6,6 @@
 <div class="image-background">This div has background image set from CSS.</div>
 <div id="div-without-class">This div will have background image set from JavaScript.</div>
 <style>@import "style.css";</style>
-<iframe src="empty.html"></iframe>
 <script>
 function loadData() {
     var xhr = new XMLHttpRequest();
@@ -14,8 +13,7 @@
     xhr.send(null);
     console.log("Done.");
 }
-
-loadData();
 </script>
+<iframe src="empty.html" onload="loadData()"></iframe>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/automapping-sourcemap-nameclash-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/automapping-sourcemap-nameclash-expected.txt
new file mode 100644
index 0000000..2a5ab85
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/automapping-sourcemap-nameclash-expected.txt
@@ -0,0 +1,16 @@
+CONSOLE MESSAGE: line 1: 1
+CONSOLE MESSAGE: line 1: function (){}
+Verify that sourcemap sources are mapped event when sourcemap compiled url matches with one of the source urls.
+
+Binding created: {
+       network: http://127.0.0.1:8000/inspector/persistence/resources/sourcemap-name-clash/out.js? [sm]
+    fileSystem: file:///var/www/src/out.js
+    exactMatch: true
+}
+Binding created: {
+       network: http://127.0.0.1:8000/inspector/persistence/resources/sourcemap-name-clash/out.js
+    fileSystem: file:///var/www/out.js
+    exactMatch: true
+}
+Mapping has stabilized.
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/automapping-sourcemap-nameclash.html b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/automapping-sourcemap-nameclash.html
new file mode 100644
index 0000000..4e30f40
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/automapping-sourcemap-nameclash.html
@@ -0,0 +1,63 @@
+<html>
+<head>
+<script src="../inspector-test.js"></script>
+<script src="../isolated-filesystem-test.js"></script>
+<script src="../debugger-test.js"></script>
+<script src="./persistence-test.js"></script>
+<script src="./automapping-test.js"></script>
+<script src="./resources/sourcemap-name-clash/out.js"></script>
+<script>
+
+function test()
+{
+    InspectorTest.overrideNetworkModificationTime({
+        "http://127.0.0.1:8000/inspector/persistence/resources/sourcemap-name-clash/out.js": null
+    });
+
+    Promise.all([
+        getResourceContent("out.js"),
+        getResourceContent("out.js? [sm]")
+    ]).then(onResourceContents);
+
+    function onResourceContents(contents)
+    {
+        var fs = new InspectorTest.TestFileSystem("file:///var/www");
+        InspectorTest.addFiles(fs, {
+            "out.js": {
+                content: contents[0],
+                time: new Date("December 1, 1989")
+            },
+            "src/out.js": {
+                content: contents[1],
+                time: new Date("December 1, 1989")
+            }
+        });
+        fs.reportCreated(onFileSystemCreated);
+    }
+
+    function onFileSystemCreated()
+    {
+        var automappingTest = new InspectorTest.AutomappingTest(Workspace.workspace);
+        automappingTest.waitUntilMappingIsStabilized(InspectorTest.completeTest.bind(InspectorTest));
+    }
+
+    function getResourceContent(name)
+    {
+        var fulfill;
+        var promise = new Promise(x => fulfill = x);
+        InspectorTest.waitForScriptSource(name, onSource);
+        return promise;
+
+        function onSource(uiSourceCode)
+        {
+            uiSourceCode.requestContent().then(content => fulfill(content));
+        }
+    }
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Verify that sourcemap sources are mapped event when sourcemap compiled url matches with one of the
+source urls.</p>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-do-not-overwrite-css-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-do-not-overwrite-css-expected.txt
new file mode 100644
index 0000000..454d517
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-do-not-overwrite-css-expected.txt
@@ -0,0 +1,28 @@
+Verify that persistence does not overwrite CSS files when CSS model reports error on getStyleSheetText.
+
+
+Running: initializeTestFileSystem
+
+Running: waitForPersistenceBinding
+Initial content of file:///var/www/simple.css
+----
+
+body {
+    color: red;
+}
+
+----
+
+Running: breakCSSModelProtocol
+Protocol Error: FAKE PROTOCOL ERROR
+
+Running: onStylesSourcemappingSynced
+Updated content of file:///var/www/simple.css
+----
+
+body {
+    color: red;
+}
+
+----
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-do-not-overwrite-css.html b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-do-not-overwrite-css.html
new file mode 100644
index 0000000..def843e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-do-not-overwrite-css.html
@@ -0,0 +1,87 @@
+<html>
+<head>
+<script src="../inspector-test.js"></script>
+<script src="../isolated-filesystem-test.js"></script>
+<script src="../debugger-test.js"></script>
+<script src="./persistence-test.js"></script>
+<script src="./automapping-test.js"></script>
+<style>
+body {
+    color: red;
+}
+/*# sourceURL=http://127.0.0.1:8000/simple.css */
+</style>
+<script>
+
+function test()
+{
+    var fsUISourceCode, fs;
+
+    InspectorTest.runTestSuite([
+        function initializeTestFileSystem(next)
+        {
+            InspectorTest.waitForUISourceCode('simple.css')
+                .then(uiSourceCode => uiSourceCode.requestContent())
+                .then(onCSSContent);
+
+            function onCSSContent(content)
+            {
+                fs = new InspectorTest.TestFileSystem("file:///var/www");
+                InspectorTest.addFiles(fs, { "simple.css": { content: content }, });
+                fs.reportCreated(next);
+            }
+        },
+
+        function waitForPersistenceBinding(next)
+        {
+            Workspace.fileSystemMapping.addFileMapping(fs.fileSystemPath, "http://127.0.0.1:8000/", "/");
+            InspectorTest.waitForBinding('simple.css').then(onBinding);
+
+            function onBinding(binding)
+            {
+                fsUISourceCode = binding.fileSystem;
+                fsUISourceCode.requestContent().then(onContent);
+            }
+
+            function onContent(content) {
+                InspectorTest.addResult('Initial content of file:///var/www/simple.css');
+                InspectorTest.addResult('----\n' + content + '\n----');
+                next();
+            }
+        },
+
+        function breakCSSModelProtocol(next)
+        {
+            // Nullify console.error since it dumps style sheet Ids and make test flake.
+            console.error = function() { };
+
+            var styleSheet = InspectorTest.cssModel.styleSheetHeaders().find(header => header.contentURL().endsWith('simple.css'));
+            // Make CSSModel constantly return errors on all getStyleSheetText requests.
+            InspectorTest.override(InspectorTest.cssModel._agent, 'getStyleSheetText', throwProtocolError, true);
+            // Set a new stylesheet text
+            InspectorTest.cssModel.setStyleSheetText(styleSheet.id, 'body {color: blue}');
+            // Expect StylesSourceMapping to sync styleSheet with network UISourceCode.
+            // Persistence acts synchronously.
+            InspectorTest.addSniffer(Bindings.StylesSourceMapping.prototype, '_styleFileSyncedForTest', next);
+
+            function throwProtocolError(styleSheetId, textCallback) {
+                var error = 'FAKE PROTOCOL ERROR';
+                var result = textCallback(error);
+                InspectorTest.addResult('Protocol Error: ' + error);
+                return Promise.resolve(result);
+            }
+        },
+
+        function onStylesSourcemappingSynced(next) {
+            InspectorTest.addResult('Updated content of file:///var/www/simple.css');
+            InspectorTest.addResult('----\n' + fsUISourceCode.content() + '\n----');
+            next()
+        }
+    ]);
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Verify that persistence does not overwrite CSS files when CSS model reports error on getStyleSheetText.</p>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/resources/sourcemap-name-clash/out.js b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/resources/sourcemap-name-clash/out.js
new file mode 100644
index 0000000..89da9c41
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/resources/sourcemap-name-clash/out.js
@@ -0,0 +1,2 @@
+"use strict";var foo=1;console.log(foo);var baz=function(){};console.log(baz);
+//# sourceMappingURL=out.js.map
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/resources/sourcemap-name-clash/out.js.map b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/resources/sourcemap-name-clash/out.js.map
new file mode 100644
index 0000000..0f030f0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/resources/sourcemap-name-clash/out.js.map
@@ -0,0 +1,19 @@
+{
+  "version": 3,
+  "sources": [
+    "out.js"
+  ],
+  "names": [
+    "foo",
+    "console",
+    "log",
+    "baz"
+  ],
+  "mappings": "YAAA,IAAIA,KAAM,CACVC,SAAQC,IAAIF,IACZ,IAAIG,KAAM,YACVF,SAAQC,IAAIC;;AAHZ,IAAI,GAAG,GAAG,CAAC,CAAC;AACZ,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACjB,IAAI,GAAG,GAAG,SAAN,GAAG,GAAe,EAAE,CAAC;AACzB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC",
+  "file": "input.js",
+  "sourceRoot": ".",
+  "sourcesContent": [
+    "var foo = 1;\nconsole.log(foo);\nvar baz = function () {};\nconsole.log(baz);\n"
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/text-source-map-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/text-source-map-expected.txt
index 9e7dc41..f79973e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/text-source-map-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/text-source-map-expected.txt
@@ -70,7 +70,7 @@
 0 === 0
 
 Running: testNameClash
-example.js === example.js [sm]
+example.js === example.js? [sm]
 0 === 0
 9 === 9
 source line 0 has no mappings.
diff --git a/third_party/WebKit/LayoutTests/inspector/css_tracker/css-tracker-view.html b/third_party/WebKit/LayoutTests/inspector/css_tracker/css-tracker-view.html
index de812884..5c98b64 100644
--- a/third_party/WebKit/LayoutTests/inspector/css_tracker/css-tracker-view.html
+++ b/third_party/WebKit/LayoutTests/inspector/css_tracker/css-tracker-view.html
@@ -13,10 +13,10 @@
 
 function test()
 {
-    InspectorTest.addSniffer(CSSTracker.CSSTrackerView.prototype, "_onGotStyleSheets", displayResults);
-    
+    InspectorTest.addSniffer(CSSTracker.CSSTrackerView.prototype, "_updateTree", displayResults);
+
     var tracker = self.runtime.sharedInstance(CSSTracker.CSSTrackerView);
-    
+
     tracker._toggleRecording(true);
     UI.viewManager.showView("css_tracker");
     tracker._toggleRecording(false);
diff --git a/third_party/WebKit/LayoutTests/inspector/css_tracker/decorations-after-inplace-formatter.html b/third_party/WebKit/LayoutTests/inspector/css_tracker/decorations-after-inplace-formatter.html
index f7b3fdb..86adbdb 100644
--- a/third_party/WebKit/LayoutTests/inspector/css_tracker/decorations-after-inplace-formatter.html
+++ b/third_party/WebKit/LayoutTests/inspector/css_tracker/decorations-after-inplace-formatter.html
@@ -17,7 +17,7 @@
     var scriptFormatter;
 
     var tracker = self.runtime.sharedInstance(CSSTracker.CSSTrackerView);
-    InspectorTest.addSniffer(CSSTracker.CSSTrackerView.prototype, "_renderRuleUsage", onTracingFinished);
+    InspectorTest.addSniffer(CSSTracker.CSSTrackerView.prototype, "_updateGutter", onTracingFinished);
 
     tracker._toggleRecording(true);
     UI.viewManager.showView("css_tracker");
@@ -55,7 +55,7 @@
         InspectorTest.addResult(lines);   
         InspectorTest.completeTest();
     }
-    
+
     function inplaceFormatter()
     {
         return self.runtime.allInstances(Sources.SourcesView.EditorAction).then(function(editorActions) {
diff --git a/third_party/WebKit/LayoutTests/inspector/css_tracker/highlight-in-source.html b/third_party/WebKit/LayoutTests/inspector/css_tracker/highlight-in-source.html
index f9157f0..a134463 100644
--- a/third_party/WebKit/LayoutTests/inspector/css_tracker/highlight-in-source.html
+++ b/third_party/WebKit/LayoutTests/inspector/css_tracker/highlight-in-source.html
@@ -16,10 +16,10 @@
 {
     InspectorTest.runTestSuite([
         function testMarking(next)
-        {            
+        {
             var tracker = self.runtime.sharedInstance(CSSTracker.CSSTrackerView);
-            InspectorTest.addSniffer(CSSTracker.CSSTrackerView.prototype, "_renderRuleUsage", printResults);
-    
+            InspectorTest.addSniffer(CSSTracker.CSSTrackerView.prototype, "_updateGutter", printResults);
+
             tracker._toggleRecording(true);
             UI.viewManager.showView("css_tracker");
             tracker._toggleRecording(false);
@@ -28,7 +28,7 @@
             {
                 UI.inspectorView.showPanel("sources").then(showSource);
             }
-        
+
             function showSource()
             {
                 InspectorTest.showScriptSource("highlight-in-source.css", waitForDecorations);
@@ -44,7 +44,7 @@
                 var lines = Array.prototype.map.call(document.querySelectorAll(".text-editor-css-rule-unused-marker"), 
                                                         e => e.parentElement.previousSibling.textContent);
 
-                InspectorTest.addResult(lines);   
+                InspectorTest.addResult(lines);
                 next();
             }
         }
diff --git a/third_party/WebKit/Source/core/events/PointerEventFactory.cpp b/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
index 598fafb6..164a6cb 100644
--- a/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
+++ b/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
@@ -274,7 +274,9 @@
     HeapVector<Member<PointerEvent>> coalescedPointerEvents;
     for (const auto& coalescedMouseEvent : coalescedMouseEvents) {
       DCHECK_EQ(mouseEvent.id, coalescedMouseEvent.id);
-      DCHECK_EQ(mouseEvent.pointerType, coalescedMouseEvent.pointerType);
+      // TODO(crbug.com/684292): We need further investigation of why the
+      // following DCHECK fails.
+      // DCHECK_EQ(mouseEvent.pointerType, coalescedMouseEvent.pointerType);
       PointerEventInit coalescedEventInit = pointerEventInit;
       updateMousePointerEventInit(coalescedMouseEvent, view,
                                   &coalescedEventInit);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.idl b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.idl
index 255196cd..296ae19e 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.idl
+++ b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.idl
@@ -258,6 +258,12 @@
     [Page, Network]
     void frameClearedScheduledNavigation([Keep] LocalFrame*);
 
+    [Network]
+    void frameScheduledClientNavigation([Keep] LocalFrame*);
+
+    [Network]
+    void frameClearedScheduledClientNavigation([Keep] LocalFrame*);
+
     [Worker]
     void didStartWorker(ExecutionContext*, WorkerInspectorProxy* proxy, bool waitingForDebugger);
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
index d0d9559b..5eb6b5ba 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
@@ -1490,14 +1490,36 @@
 
 void InspectorNetworkAgent::frameScheduledNavigation(LocalFrame* frame,
                                                      double) {
-  std::unique_ptr<protocol::Network::Initiator> initiator =
-      buildInitiatorObject(frame->document(), FetchInitiatorInfo());
-  m_frameNavigationInitiatorMap.set(IdentifiersFactory::frameId(frame),
-                                    std::move(initiator));
+  String frameId = IdentifiersFactory::frameId(frame);
+  m_framesWithScheduledNavigation.insert(frameId);
+  if (!m_framesWithScheduledClientNavigation.contains(frameId)) {
+    m_frameNavigationInitiatorMap.set(
+        frameId, buildInitiatorObject(frame->document(), FetchInitiatorInfo()));
+  }
 }
 
 void InspectorNetworkAgent::frameClearedScheduledNavigation(LocalFrame* frame) {
-  m_frameNavigationInitiatorMap.erase(IdentifiersFactory::frameId(frame));
+  String frameId = IdentifiersFactory::frameId(frame);
+  m_framesWithScheduledNavigation.erase(frameId);
+  if (!m_framesWithScheduledClientNavigation.contains(frameId))
+    m_frameNavigationInitiatorMap.erase(frameId);
+}
+
+void InspectorNetworkAgent::frameScheduledClientNavigation(LocalFrame* frame) {
+  String frameId = IdentifiersFactory::frameId(frame);
+  m_framesWithScheduledClientNavigation.insert(frameId);
+  if (!m_framesWithScheduledNavigation.contains(frameId)) {
+    m_frameNavigationInitiatorMap.set(
+        frameId, buildInitiatorObject(frame->document(), FetchInitiatorInfo()));
+  }
+}
+
+void InspectorNetworkAgent::frameClearedScheduledClientNavigation(
+    LocalFrame* frame) {
+  String frameId = IdentifiersFactory::frameId(frame);
+  m_framesWithScheduledClientNavigation.erase(frameId);
+  if (!m_framesWithScheduledNavigation.contains(frameId))
+    m_frameNavigationInitiatorMap.erase(frameId);
 }
 
 void InspectorNetworkAgent::setHostId(const String& hostId) {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h
index 29838c9..b01d9fe 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h
@@ -166,6 +166,8 @@
 
   void frameScheduledNavigation(LocalFrame*, double);
   void frameClearedScheduledNavigation(LocalFrame*);
+  void frameScheduledClientNavigation(LocalFrame*);
+  void frameClearedScheduledClientNavigation(LocalFrame*);
 
   std::unique_ptr<protocol::Network::Initiator> buildInitiatorObject(
       Document*,
@@ -274,6 +276,8 @@
   typedef HashMap<String, std::unique_ptr<protocol::Network::Initiator>>
       FrameNavigationInitiatorMap;
   FrameNavigationInitiatorMap m_frameNavigationInitiatorMap;
+  HashSet<String> m_framesWithScheduledNavigation;
+  HashSet<String> m_framesWithScheduledClientNavigation;
 
   // FIXME: InspectorNetworkAgent should now be aware of style recalculation.
   std::unique_ptr<protocol::Network::Initiator> m_styleRecalculationInitiator;
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index 3f62008..d675d5d 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1246,7 +1246,7 @@
         ResourceError::cancelledError(String()), StandardCommit);
   }
 
-  m_isNavigationHandledByClient = false;
+  clearNavigationHandledByClient();
 
   for (Frame* child = m_frame->tree().firstChild(); child;
        child = child->tree().nextSibling()) {
@@ -1674,7 +1674,7 @@
   if (policy == NavigationPolicyIgnore)
     return false;
   if (policy == NavigationPolicyHandledByClient) {
-    m_isNavigationHandledByClient = true;
+    setNavigationHandledByClient();
     // Mark the frame as loading since the embedder is handling the navigation.
     m_progressTracker->progressStarted(frameLoadType);
 
@@ -1752,7 +1752,7 @@
       // navigation, record that there is no longer a navigation handled by the
       // client.
       if (!frameLoadRequest.resourceRequest().checkForBrowserSideNavigation()) {
-        m_isNavigationHandledByClient = false;
+        clearNavigationHandledByClient();
       } else {
         DocumentLoader* loader = createDocumentLoader(
             resourceRequest, frameLoadRequest, type, navigationType);
@@ -1796,6 +1796,7 @@
   if (frameLoadRequest.form())
     client()->dispatchWillSubmitForm(frameLoadRequest.form());
 
+  bool isNavigationHandledByClient = m_isNavigationHandledByClient;
   // If the loader wasn't waiting for the client to handle a navigation, update
   // the progress tracker. Otherwise don't, as it was already notified before
   // sending the navigation to teh client.
@@ -1814,6 +1815,11 @@
 
   m_provisionalDocumentLoader->startLoadingMainResource();
 
+  // This should happen after the request is sent, so we don't use
+  // clearNavigationHandledByClient() above.
+  if (isNavigationHandledByClient)
+    InspectorInstrumentation::frameClearedScheduledClientNavigation(m_frame);
+
   takeObjectSnapshot();
 }
 
@@ -2020,4 +2026,14 @@
   return loader;
 }
 
+void FrameLoader::setNavigationHandledByClient() {
+  m_isNavigationHandledByClient = true;
+  InspectorInstrumentation::frameScheduledClientNavigation(m_frame);
+}
+
+void FrameLoader::clearNavigationHandledByClient() {
+  m_isNavigationHandledByClient = false;
+  InspectorInstrumentation::frameClearedScheduledClientNavigation(m_frame);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.h b/third_party/WebKit/Source/core/loader/FrameLoader.h
index dc55504..7ebb01e 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.h
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.h
@@ -217,9 +217,7 @@
     return provisionalDocumentLoader() || m_isNavigationHandledByClient;
   }
 
-  void clearNavigationHandledByClient() {
-    m_isNavigationHandledByClient = false;
-  }
+  void clearNavigationHandledByClient();
 
   DECLARE_TRACE();
 
@@ -272,6 +270,8 @@
                                        FrameLoadType,
                                        NavigationType);
 
+  void setNavigationHandledByClient();
+
   Member<LocalFrame> m_frame;
   AtomicString m_requiredCSP;
 
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js b/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js
index 1ae17f4..620a238 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js
@@ -31,37 +31,15 @@
    * @param {!SDK.CSSModel} cssModel
    */
   modelRemoved(cssModel) {
-    this._modelToInfo.remove(cssModel)._dispose();
-  }
-
-  /**
-   * @param {!SDK.CSSStyleSheetHeader} header
-   * @return {?Bindings.CSSWorkspaceBinding.ModelInfo}
-   */
-  _modelInfo(header) {
-    return this._modelToInfo.get(header.cssModel()) || null;
-  }
-
-  /**
-   * @param {!SDK.CSSStyleSheetHeader} header
-   * @return {!Bindings.CSSWorkspaceBinding.ModelInfo}
-   */
-  _ensureModelInfo(header) {
-    var modelInfo = this._modelToInfo.get(header.cssModel());
-    if (!modelInfo) {
-      modelInfo = new Bindings.CSSWorkspaceBinding.ModelInfo(header.cssModel(), this._workspace);
-      this._modelToInfo.set(header.cssModel(), modelInfo);
-    }
-    return modelInfo;
+    this._modelToInfo.get(cssModel)._dispose();
+    this._modelToInfo.delete(cssModel);
   }
 
   /**
    * @param {!SDK.CSSStyleSheetHeader} header
    */
   updateLocations(header) {
-    var modelInfo = this._modelInfo(header);
-    if (modelInfo)
-      modelInfo._updateLocations(header);
+    this._modelToInfo.get(header.cssModel())._updateLocations(header);
   }
 
   /**
@@ -71,26 +49,7 @@
    * @return {!Bindings.CSSWorkspaceBinding.LiveLocation}
    */
   createLiveLocation(rawLocation, updateDelegate, locationPool) {
-    var header =
-        rawLocation.styleSheetId ? rawLocation.cssModel().styleSheetHeaderForId(rawLocation.styleSheetId) : null;
-    return new Bindings.CSSWorkspaceBinding.LiveLocation(
-        rawLocation.cssModel(), header, rawLocation, this, updateDelegate, locationPool);
-  }
-
-  /**
-   * @param {!Bindings.CSSWorkspaceBinding.LiveLocation} location
-   */
-  _addLiveLocation(location) {
-    this._ensureModelInfo(location._header)._addLocation(location);
-  }
-
-  /**
-   * @param {!Bindings.CSSWorkspaceBinding.LiveLocation} location
-   */
-  _removeLiveLocation(location) {
-    var modelInfo = this._modelInfo(location._header);
-    if (modelInfo)
-      modelInfo._removeLocation(location);
+    return this._modelToInfo.get(rawLocation.cssModel())._createLiveLocation(rawLocation, updateDelegate, locationPool);
   }
 
   /**
@@ -124,12 +83,7 @@
   rawLocationToUILocation(rawLocation) {
     if (!rawLocation)
       return null;
-    var header = rawLocation.cssModel().styleSheetHeaderForId(rawLocation.styleSheetId);
-    if (!header)
-      return null;
-    var modelInfo = this._modelInfo(header);
-    return modelInfo ? modelInfo._rawLocationToUILocation(header, rawLocation.lineNumber, rawLocation.columnNumber) :
-                       null;
+    return this._modelToInfo.get(rawLocation.cssModel())._rawLocationToUILocation(rawLocation);
   }
 };
 
@@ -139,29 +93,48 @@
    * @param {!Workspace.Workspace} workspace
    */
   constructor(cssModel, workspace) {
-    this._cssModel = cssModel;
+    this._eventListeners = [
+      cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetAdded, this._styleSheetAdded, this),
+      cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this)
+    ];
+
     this._stylesSourceMapping = new Bindings.StylesSourceMapping(cssModel, workspace);
     this._sassSourceMapping =
         new Bindings.SASSSourceMapping(cssModel, workspace, Bindings.NetworkProject.forTarget(cssModel.target()));
 
-    /** @type {!Multimap<!SDK.CSSStyleSheetHeader, !Bindings.LiveLocation>} */
+    /** @type {!Multimap<!SDK.CSSStyleSheetHeader, !Bindings.CSSWorkspaceBinding.LiveLocation>} */
     this._locations = new Multimap();
+    /** @type {!Multimap<string, !Bindings.CSSWorkspaceBinding.LiveLocation>} */
+    this._unboundLocations = new Multimap();
+  }
+
+  /**
+   * @param {!SDK.CSSLocation} rawLocation
+   * @param {function(!Bindings.LiveLocation)} updateDelegate
+   * @param {!Bindings.LiveLocationPool} locationPool
+   * @return {!Bindings.CSSWorkspaceBinding.LiveLocation}
+   */
+  _createLiveLocation(rawLocation, updateDelegate, locationPool) {
+    var location = new Bindings.CSSWorkspaceBinding.LiveLocation(rawLocation, this, updateDelegate, locationPool);
+    var header = rawLocation.header();
+    if (header) {
+      location._header = header;
+      this._locations.set(header, location);
+      location.update();
+    } else {
+      this._unboundLocations.set(rawLocation.url, location);
+    }
+    return location;
   }
 
   /**
    * @param {!Bindings.CSSWorkspaceBinding.LiveLocation} location
    */
-  _addLocation(location) {
-    var header = location._header;
-    this._locations.set(header, location);
-    location.update();
-  }
-
-  /**
-   * @param {!Bindings.CSSWorkspaceBinding.LiveLocation} location
-   */
-  _removeLocation(location) {
-    this._locations.remove(location._header, location);
+  _disposeLocation(location) {
+    if (location._header)
+      this._locations.remove(location._header, location);
+    else
+      this._unboundLocations.remove(location._url, location);
   }
 
   /**
@@ -173,13 +146,39 @@
   }
 
   /**
-   * @param {!SDK.CSSStyleSheetHeader} header
-   * @param {number} lineNumber
-   * @param {number=} columnNumber
+   * @param {!Common.Event} event
+   */
+  _styleSheetAdded(event) {
+    var header = /** @type {!SDK.CSSStyleSheetHeader} */ (event.data);
+    if (!header.sourceURL)
+      return;
+
+    for (var location of this._unboundLocations.get(header.sourceURL)) {
+      location._header = header;
+      this._locations.set(header, location);
+      location.update();
+    }
+    this._unboundLocations.removeAll(header.sourceURL);
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _styleSheetRemoved(event) {
+    var header = /** @type {!SDK.CSSStyleSheetHeader} */ (event.data);
+    for (var location of this._locations.get(header)) {
+      location._header = null;
+      this._unboundLocations.set(location._url, location);
+      location.update();
+    }
+    this._locations.removeAll(header);
+  }
+
+  /**
+   * @param {!SDK.CSSLocation} rawLocation
    * @return {?Workspace.UILocation}
    */
-  _rawLocationToUILocation(header, lineNumber, columnNumber) {
-    var rawLocation = new SDK.CSSLocation(header, lineNumber, columnNumber);
+  _rawLocationToUILocation(rawLocation) {
     var uiLocation = null;
     uiLocation = uiLocation || this._sassSourceMapping.rawLocationToUILocation(rawLocation);
     uiLocation = uiLocation || this._stylesSourceMapping.rawLocationToUILocation(rawLocation);
@@ -187,6 +186,7 @@
   }
 
   _dispose() {
+    Common.EventTarget.removeEventListeners(this._eventListeners);
     this._stylesSourceMapping.dispose();
     this._sassSourceMapping.dispose();
   }
@@ -197,60 +197,18 @@
  */
 Bindings.CSSWorkspaceBinding.LiveLocation = class extends Bindings.LiveLocationWithPool {
   /**
-   * @param {!SDK.CSSModel} cssModel
-   * @param {?SDK.CSSStyleSheetHeader} header
    * @param {!SDK.CSSLocation} rawLocation
-   * @param {!Bindings.CSSWorkspaceBinding} binding
+   * @param {!Bindings.CSSWorkspaceBinding.ModelInfo} info
    * @param {function(!Bindings.LiveLocation)} updateDelegate
    * @param {!Bindings.LiveLocationPool} locationPool
    */
-  constructor(cssModel, header, rawLocation, binding, updateDelegate, locationPool) {
+  constructor(rawLocation, info, updateDelegate, locationPool) {
     super(updateDelegate, locationPool);
-    this._cssModel = cssModel;
-    this._rawLocation = rawLocation;
-    this._binding = binding;
-    if (!header)
-      this._clearStyleSheet();
-    else
-      this._setStyleSheet(header);
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _styleSheetAdded(event) {
-    console.assert(!this._header);
-    var header = /** @type {!SDK.CSSStyleSheetHeader} */ (event.data);
-    if (header.sourceURL && header.sourceURL === this._rawLocation.url)
-      this._setStyleSheet(header);
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _styleSheetRemoved(event) {
-    console.assert(this._header);
-    var header = /** @type {!SDK.CSSStyleSheetHeader} */ (event.data);
-    if (this._header !== header)
-      return;
-    this._binding._removeLiveLocation(this);
-    this._clearStyleSheet();
-  }
-
-  /**
-   * @param {!SDK.CSSStyleSheetHeader} header
-   */
-  _setStyleSheet(header) {
-    this._header = header;
-    this._binding._addLiveLocation(this);
-    this._cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
-    this._cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
-  }
-
-  _clearStyleSheet() {
-    delete this._header;
-    this._cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
-    this._cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
+    this._url = rawLocation.url;
+    this._lineNumber = rawLocation.lineNumber;
+    this._columnNumber = rawLocation.columnNumber;
+    this._info = info;
+    this._header = null;
   }
 
   /**
@@ -258,16 +216,10 @@
    * @return {?Workspace.UILocation}
    */
   uiLocation() {
-    var cssLocation = this._rawLocation;
-    if (this._header) {
-      var modelInfo = this._binding._modelInfo(this._header);
-      return modelInfo._rawLocationToUILocation(this._header, cssLocation.lineNumber, cssLocation.columnNumber);
-    }
-    var uiSourceCode = Bindings.NetworkProject.uiSourceCodeForStyleURL(
-        this._binding._workspace, cssLocation.url, cssLocation.header());
-    if (!uiSourceCode)
+    if (!this._header)
       return null;
-    return uiSourceCode.uiLocation(cssLocation.lineNumber, cssLocation.columnNumber);
+    var rawLocation = new SDK.CSSLocation(this._header, this._lineNumber, this._columnNumber);
+    return this._info._rawLocationToUILocation(rawLocation);
   }
 
   /**
@@ -275,10 +227,7 @@
    */
   dispose() {
     super.dispose();
-    if (this._header)
-      this._binding._removeLiveLocation(this);
-    this._cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
-    this._cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
+    this._info._disposeLocation(this);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/SASSSourceMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/SASSSourceMapping.js
index 72322eb..7012890 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/SASSSourceMapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/SASSSourceMapping.js
@@ -102,14 +102,16 @@
    * @return {?Workspace.UILocation}
    */
   rawLocationToUILocation(rawLocation) {
-    var sourceMap = this._cssModel.sourceMapForHeader(rawLocation.header());
+    var header = rawLocation.header();
+    if (!header)
+      return null;
+    var sourceMap = this._cssModel.sourceMapForHeader(header);
     if (!sourceMap)
       return null;
     var entry = sourceMap.findEntry(rawLocation.lineNumber, rawLocation.columnNumber);
     if (!entry || !entry.sourceURL)
       return null;
-    var uiSourceCode =
-        Bindings.NetworkProject.uiSourceCodeForStyleURL(this._workspace, entry.sourceURL, rawLocation.header());
+    var uiSourceCode = Bindings.NetworkProject.uiSourceCodeForStyleURL(this._workspace, entry.sourceURL, header);
     if (!uiSourceCode)
       return null;
     return uiSourceCode.uiLocation(entry.sourceLineNumber || 0, entry.sourceColumnNumber);
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
index 49cb560..b9760d6 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
@@ -63,13 +63,14 @@
    * @return {?Workspace.UILocation}
    */
   rawLocationToUILocation(rawLocation) {
-    var uiSourceCode =
-        Bindings.NetworkProject.uiSourceCodeForStyleURL(this._workspace, rawLocation.url, rawLocation.header());
+    var header = rawLocation.header();
+    if (!header)
+      return null;
+    var uiSourceCode = Bindings.NetworkProject.uiSourceCodeForStyleURL(this._workspace, rawLocation.url, header);
     if (!uiSourceCode)
       return null;
     var lineNumber = rawLocation.lineNumber;
     var columnNumber = rawLocation.columnNumber;
-    var header = this._cssModel.styleSheetHeaderForId(rawLocation.styleSheetId);
     if (header && header.isInline && header.hasSourceURL) {
       lineNumber -= header.lineNumberInSource(0);
       columnNumber -= header.columnNumberInSource(lineNumber, 0);
@@ -269,11 +270,15 @@
      */
     function callback(uiSourceCode, content) {
       var styleFile = this._styleFiles.get(uiSourceCode);
-      if (styleFile)
-        styleFile.addRevision(content || '');
+      if (typeof content === 'string' && styleFile)
+        styleFile.addRevision(content);
+      this._styleFileSyncedForTest();
     }
   }
 
+  _styleFileSyncedForTest() {
+  }
+
   dispose() {
     Common.EventTarget.removeEventListeners(this._eventListeners);
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/common/StaticContentProvider.js b/third_party/WebKit/Source/devtools/front_end/common/StaticContentProvider.js
index 7403bb8..07bfc7eb 100644
--- a/third_party/WebKit/Source/devtools/front_end/common/StaticContentProvider.js
+++ b/third_party/WebKit/Source/devtools/front_end/common/StaticContentProvider.js
@@ -9,7 +9,7 @@
   /**
    * @param {string} contentURL
    * @param {!Common.ResourceType} contentType
-   * @param {function():!Promise<string>} lazyContent
+   * @param {function():!Promise<?string>} lazyContent
    */
   constructor(contentURL, contentType, lazyContent) {
     this._contentURL = contentURL;
@@ -61,9 +61,13 @@
    */
   searchInContent(query, caseSensitive, isRegex, callback) {
     /**
-     * @param {string} content
+     * @param {?string} content
      */
     function performSearch(content) {
+      if (!content) {
+        callback(/** @type {!Array<!Common.ContentProvider.SearchMatch>} */ ([]));
+        return;
+      }
       callback(Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex));
     }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/css_tracker/CSSTrackerView.js b/third_party/WebKit/Source/devtools/front_end/css_tracker/CSSTrackerView.js
index 38318b0..354ed14 100644
--- a/third_party/WebKit/Source/devtools/front_end/css_tracker/CSSTrackerView.js
+++ b/third_party/WebKit/Source/devtools/front_end/css_tracker/CSSTrackerView.js
@@ -84,130 +84,138 @@
     var cssModel = mainTarget.model(SDK.CSSModel);
     if (!cssModel)
       return;
-    cssModel.ruleListPromise().then(ruleListReceived.bind(this, cssModel));
+
+    cssModel.ruleListPromise().then(processRuleList.bind(this)).then(updateViews.bind(this));
 
     /**
-     * @param {!SDK.CSSModel} cssModel
-     * @param {!Array<!CSSTracker.RuleUsage>} ruleUsageList
+     * @param {!Array<!SDK.CSSModel.RuleUsage>} ruleUsageList
+     * @this {!CSSTracker.CSSTrackerView}
+     * @return {!Promise<!Array<!CSSTracker.StyleSheetUsage>>}
+     */
+    function processRuleList(ruleUsageList) {
+      /** @type {!Map<?SDK.CSSStyleSheetHeader, !CSSTracker.StyleSheetUsage>} */
+      var rulesByStyleSheet = new Map();
+      for (var rule of ruleUsageList) {
+        var styleSheetHeader = cssModel.styleSheetHeaderForId(rule.styleSheetId);
+        var entry = rulesByStyleSheet.get(styleSheetHeader);
+        if (!entry) {
+          entry = {styleSheetHeader: styleSheetHeader, rules: []};
+          rulesByStyleSheet.set(styleSheetHeader, entry);
+        }
+        entry.rules.push(rule);
+      }
+      return Promise.all(Array.from(
+          rulesByStyleSheet.values(),
+          entry => this._populateSourceInfo(/** @type {!CSSTracker.StyleSheetUsage} */ (entry))));
+    }
+
+    /**
+     * @param {!Array<!CSSTracker.StyleSheetUsage>} styleSheetUsages
      * @this {!CSSTracker.CSSTrackerView}
      */
-    function ruleListReceived(cssModel, ruleUsageList) {
-      var unusedRulesCount = 0;
-      for (var rule of ruleUsageList) {
-        if (!rule.wasUsed)
-          unusedRulesCount++;
+    function updateViews(styleSheetUsages) {
+      this._updateStats(styleSheetUsages);
+      this._updateGutter(styleSheetUsages);
+      this._updateTree(styleSheetUsages);
+    }
+  }
 
-        var url = this._urlForStyleSheetId(cssModel, rule.styleSheetId);
-        if (!url)
-          continue;
-        var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
-        if (!uiSourceCode)
-          continue;
+  /**
+   * @param {!CSSTracker.StyleSheetUsage} styleSheetUsage
+   * @return {!Promise<!CSSTracker.StyleSheetUsage>}
+   */
+  _populateSourceInfo(styleSheetUsage) {
+    if (!styleSheetUsage.styleSheetHeader)
+      return Promise.resolve(styleSheetUsage);
+    var ruleIndex =
+        new Map(styleSheetUsage.rules.map(rule => [`${rule.range.startLine}.${rule.range.startColumn}`, rule]));
 
+    return new Promise(fulfill => {
+      styleSheetUsage.styleSheetHeader.requestContent().then(
+          content => Common.formatterWorkerPool.parseCSS(content || '', onRules));
+
+      /**
+       * @param {boolean} isLastChunk
+       * @param {!Array<!Common.FormatterWorkerPool.CSSStyleRule>} rules
+       */
+      function onRules(isLastChunk, rules) {
+        for (var rule of rules) {
+          if (!rule.styleRange)
+            continue;
+          var entry = ruleIndex.get(`${rule.styleRange.startLine}.${rule.styleRange.startColumn}`);
+          if (entry)
+            entry.selector = rule.selectorText;
+        }
+        if (isLastChunk)
+          fulfill(styleSheetUsage);
+      }
+    });
+  }
+
+  /**
+   * @param {!Array<!CSSTracker.StyleSheetUsage>} styleSheetUsage
+   */
+  _updateStats(styleSheetUsage) {
+    var total = 0;
+    var unused = 0;
+    for (var styleSheet of styleSheetUsage) {
+      total += styleSheet.rules.length;
+      unused += styleSheet.rules.reduce((count, rule) => rule.wasUsed ? count : count + 1, 0);
+    }
+    var percentUnused = total ? Math.round(100 * unused / total) : 0;
+    if (unused === 1) {
+      this._statusMessageElement.textContent =
+          Common.UIString('%d CSS rule is not used. (%d%%)', unused, percentUnused);
+    } else {
+      this._statusMessageElement.textContent =
+          Common.UIString('%d CSS rules are not used. (%d%%)', unused, percentUnused);
+    }
+  }
+
+  /**
+   * @param {!Array<!CSSTracker.StyleSheetUsage>} styleSheetUsages
+   */
+  _updateGutter(styleSheetUsages) {
+    for (var styleSheet of styleSheetUsages) {
+      if (!styleSheet.styleSheetHeader)
+        continue;
+      var url = styleSheet.styleSheetHeader.sourceURL;
+      var uiSourceCode = url && Workspace.workspace.uiSourceCodeForURL(url);
+      if (!uiSourceCode)
+        continue;
+      for (var rule of styleSheet.rules) {
         var gutterRange = Common.TextRange.fromObject(rule.range);
         if (gutterRange.startColumn)
           gutterRange.startColumn--;
         uiSourceCode.addDecoration(gutterRange, CSSTracker.CSSTrackerView.LineDecorator.type, rule.wasUsed);
       }
-      var percentUnused = Math.round(100 * unusedRulesCount / ruleUsageList.length);
-      if (unusedRulesCount === 1) {
-        this._statusMessageElement.textContent =
-            Common.UIString('%d CSS rule is not used. (%d%%)', unusedRulesCount, percentUnused);
-      } else {
-        this._statusMessageElement.textContent =
-            Common.UIString('%d CSS rules are not used. (%d%%)', unusedRulesCount, percentUnused);
-      }
-
-      this._renderRuleUsage(cssModel, ruleUsageList);
     }
   }
 
   /**
-   * @param {!Array<!SDK.CSSStyleSheetHeader>} styleSheetHeaders
-   * @return {!Promise<!Array<!CSSTracker.ParsedStyleSheet>>}
+   * @param {!Array<!CSSTracker.StyleSheetUsage>} styleSheetUsages
    */
-  _parseStyleSheets(styleSheetHeaders) {
-    var promises = styleSheetHeaders.map(header => parseStyleSheet(header));
-    return Promise.all(promises);
+  _updateTree(styleSheetUsages) {
+    this._cssResultsElement.removeChildren();
+    this._cssResultsElement.appendChild(this._treeOutline.element);
 
-    /**
-     * @param {!SDK.CSSStyleSheetHeader} styleSheet
-     * @return {!Promise<!CSSTracker.ParsedStyleSheet>}
-     */
-    function parseStyleSheet(styleSheet) {
-      return new Promise(fulfill => {
-        /** @type {!Array<!Common.FormatterWorkerPool.CSSStyleRule>} */
-        var allRules = [];
-        styleSheet.requestContent().then(content => Common.formatterWorkerPool.parseCSS(content || '', onRules));
-
-        /**
-         * @param {boolean} isLastChunk
-         * @param {!Array<!Common.FormatterWorkerPool.CSSStyleRule>} rules
-         */
-        function onRules(isLastChunk, rules) {
-          allRules.pushAll(rules);
-          if (isLastChunk)
-            fulfill({sourceURL: styleSheet.sourceURL, rules: allRules});
-        }
-      });
-    }
-  }
-
-  /**
-   * @param {!SDK.CSSModel} cssModel
-   * @param {!Array<!CSSTracker.RuleUsage>} ruleList
-   */
-  _renderRuleUsage(cssModel, ruleList) {
-    var headers = cssModel.allStyleSheets();
-    if (!headers.length)
-      return;
-
-    this._parseStyleSheets(headers).then(this._onGotStyleSheets.bind(this, cssModel, ruleList));
-  }
-
-  /**
-   * @param {!SDK.CSSModel} cssModel
-   * @param {!Array<!CSSTracker.RuleUsage>} ruleList
-   * @param {!Array<!CSSTracker.ParsedStyleSheet>} styleSheets
-   * @this {CSSTracker.CSSTrackerView}
-   */
-  _onGotStyleSheets(cssModel, ruleList, styleSheets) {
-    /** @type {!Map<string, string>} */
-    var rangeToSelector = new Map();
-
-    for (var styleSheet of styleSheets) {
-      for (var rule of styleSheet.rules) {
-        if (!rule.styleRange)
+    for (var sheet of styleSheetUsages) {
+      var unusedRuleCount = sheet.rules.reduce((count, rule) => rule.wasUsed ? count : count + 1, 0);
+      if (sheet.styleSheetHeader) {
+        var url = sheet.styleSheetHeader.sourceURL;
+        if (!url)
           continue;
 
-        rangeToSelector.set(
-            rule.styleRange.startLine + ',' + rule.styleRange.startColumn + ',' + styleSheet.sourceURL,
-            rule.selectorText);
-      }
-    }
-
-    var unattributedRulesCount = 0;
-
-    for (var rule of ruleList) {
-      var url = this._urlForStyleSheetId(cssModel, rule.styleSheetId);
-      if (url === '')
+        var styleSheetTreeElement = new CSSTracker.CSSTrackerView.StyleSheetTreeElement(url, sheet.rules);
+        this._treeOutline.appendChild(styleSheetTreeElement);
         continue;
-      var range = rule.range.startLine + ',' + rule.range.startColumn + ',' + url;
-      rule.selector = rangeToSelector.get(range);
-      if (!rule.selector && !rule.wasUsed)
-        ++unattributedRulesCount;
-    }
-    ruleList = ruleList.filter(rule => rule.selector);
-
-    this._cssResultsElement.removeChildren();
-
-    if (unattributedRulesCount) {
-      if (unattributedRulesCount === 1) {
-        var removedStyleSheetStats = Common.UIString('1 unused rule in a removed style sheet.');
-      } else {
-        var removedStyleSheetStats =
-            Common.UIString('%d unused rules in removed style sheets.', unattributedRulesCount);
       }
+      if (!unusedRuleCount)
+        continue;
+      var removedStyleSheetStats = unusedRuleCount === 1 ?
+          Common.UIString('1 unused rule in a removed style sheet.') :
+          Common.UIString('%d unused rules in removed style sheets.', unusedRuleCount);
+
       var treeElement = new UI.TreeElement(Common.UIString('Unknown style sheets'), true);
       treeElement.toggleOnClick = true;
       treeElement.selectable = false;
@@ -217,51 +225,17 @@
       treeElement.appendChild(stats);
       this._treeOutline.appendChild(treeElement);
     }
-
-    if (!ruleList.length)
-      return;
-
-    this._cssResultsElement.appendChild(this._treeOutline.element);
-
-    var startPosition = 0;
-    for (var i = 1; i < ruleList.length; ++i) {
-      if (ruleList[i].styleSheetId === ruleList[i - 1].styleSheetId)
-        continue;
-
-      var url = this._urlForStyleSheetId(cssModel, ruleList[startPosition].styleSheetId);
-      var styleSheetTreeElement =
-          new CSSTracker.CSSTrackerView.StyleSheetTreeElement(url, ruleList.slice(startPosition, i));
-      this._treeOutline.appendChild(styleSheetTreeElement);
-
-      startPosition = i;
-    }
-    var url = this._urlForStyleSheetId(cssModel, ruleList[startPosition].styleSheetId);
-    var styleSheetTreeElement = new CSSTracker.CSSTrackerView.StyleSheetTreeElement(url, ruleList.slice(startPosition));
-    this._treeOutline.appendChild(styleSheetTreeElement);
-  }
-
-  /**
-   * @param {string} styleSheetId
-   * @param {!SDK.CSSModel} cssModel
-   * @return {string}
-   */
-  _urlForStyleSheetId(cssModel, styleSheetId) {
-    var styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId);
-    if (!styleSheetHeader)
-      return '';
-    return styleSheetHeader.sourceURL;
   }
 };
 
 /** @typedef {{range: !Protocol.CSS.SourceRange,
  *              selector: (string|undefined),
- *              styleSheetId: !Protocol.CSS.StyleSheetId,
  *              wasUsed: boolean}}
  */
 CSSTracker.RuleUsage;
 
-/** @typedef {{sourceURL: string, rules: !Array<!Common.FormatterWorkerPool.CSSStyleRule>}} */
-CSSTracker.ParsedStyleSheet;
+/** @typedef {{styleSheetHeader: ?SDK.CSSStyleSheetHeader, rules: !Array<!CSSTracker.RuleUsage>}} */
+CSSTracker.StyleSheetUsage;
 
 CSSTracker.CSSTrackerView._rulesShownAtOnce = 20;
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
index 25421fc..fb5b77f 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
@@ -52,7 +52,7 @@
     /** @type {!Map.<string, !Object.<!Protocol.Page.FrameId, !Array.<!Protocol.CSS.StyleSheetId>>>} */
     this._styleSheetIdsForURL = new Map();
 
-    /** @type {!Map.<!SDK.CSSStyleSheetHeader, !Promise<string>>} */
+    /** @type {!Map.<!SDK.CSSStyleSheetHeader, !Promise<?string>>} */
     this._originalStyleSheetText = new Map();
 
     /** @type {!Multimap<string, !Protocol.CSS.StyleSheetId>} */
@@ -784,12 +784,12 @@
 
   /**
    * @param {!Protocol.CSS.StyleSheetId} styleSheetId
-   * @return {!Promise<string>}
+   * @return {!Promise<?string>}
    */
   _ensureOriginalStyleSheetText(styleSheetId) {
     var header = this.styleSheetHeaderForId(styleSheetId);
     if (!header)
-      return Promise.resolve('');
+      return Promise.resolve(/** @type {?string} */ (null));
     var promise = this._originalStyleSheetText.get(header);
     if (!promise) {
       promise = this.getStyleSheetText(header.id);
@@ -807,7 +807,7 @@
 
   /**
    * @param {!SDK.CSSStyleSheetHeader} header
-   * @return {!Promise<string>}
+   * @return {!Promise<?string>}
    */
   originalStyleSheetText(header) {
     return this._ensureOriginalStyleSheetText(header.id);
@@ -909,24 +909,23 @@
 
   /**
    * @param {!Protocol.CSS.StyleSheetId} styleSheetId
-   * @return {!Promise<string>}
+   * @return {!Promise<?string>}
    */
   getStyleSheetText(styleSheetId) {
     /**
      * @param {?Protocol.Error} error
      * @param {?string} text
-     * @return {string}
+     * @return {?string}
      */
     function textCallback(error, text) {
       if (error || text === null) {
         console.error('Failed to get text for stylesheet ' + styleSheetId + ': ' + error);
-        text = '';
-        // Fall through.
+        return null;
       }
       return SDK.CSSModel.trimSourceURL(text);
     }
 
-    return this._agent.getStyleSheetText(styleSheetId, textCallback).catchException(/** @type {string} */ (''));
+    return this._agent.getStyleSheetText(styleSheetId, textCallback).catchException(/** @type {?string} */ (null));
   }
 
   _resetStyleSheets() {
@@ -1036,7 +1035,7 @@
    * @param {number=} columnNumber
    */
   constructor(header, lineNumber, columnNumber) {
-    this._header = header;
+    this._cssModel = header.cssModel();
     this.styleSheetId = header.id;
     this.url = header.resourceURL();
     this.lineNumber = lineNumber;
@@ -1047,14 +1046,14 @@
    * @return {!SDK.CSSModel}
    */
   cssModel() {
-    return this._header.cssModel();
+    return this._cssModel;
   }
 
   /**
-   * @return {!SDK.CSSStyleSheetHeader}
+   * @return {?SDK.CSSStyleSheetHeader}
    */
   header() {
-    return this._header;
+    return this._cssModel.styleSheetHeaderForId(this.styleSheetId);
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleSheetHeader.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleSheetHeader.js
index 3595ca7..591c067 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleSheetHeader.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleSheetHeader.js
@@ -129,7 +129,7 @@
    * @return {!Promise<?string>}
    */
   requestContent() {
-    return /** @type {!Promise<?string>} */ (this._cssModel.getStyleSheetText(this.id));
+    return this._cssModel.getStyleSheetText(this.id);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js b/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js
index 24dbe1dc..a7645e0 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js
@@ -423,7 +423,7 @@
       var url = Common.ParsedURL.completeURL(this._sourceMappingURL, href) || href;
       var source = sourceMap.sourcesContent && sourceMap.sourcesContent[i];
       if (url === this._compiledURL && source)
-        url += Common.UIString(' [sm]');
+        url += Common.UIString('? [sm]');
       this._sourceInfos.set(url, new SDK.TextSourceMap.SourceInfo(source, null));
       sourcesList.push(url);
     }