diff --git a/base/test/values_test_util.cc b/base/test/values_test_util.cc
index 0cd8ea29..9334df4 100644
--- a/base/test/values_test_util.cc
+++ b/base/test/values_test_util.cc
@@ -54,11 +54,9 @@
   EXPECT_EQ(expected_value, string_value) << key;
 }
 
-void ExpectStringValue(const std::string& expected_str, Value* actual) {
-  std::unique_ptr<Value> scoped_actual(actual);
-  std::string actual_str;
-  EXPECT_TRUE(scoped_actual->GetAsString(&actual_str));
-  EXPECT_EQ(expected_str, actual_str);
+void ExpectStringValue(const std::string& expected_str, const Value& actual) {
+  EXPECT_EQ(Value::Type::STRING, actual.type());
+  EXPECT_EQ(expected_str, actual.GetString());
 }
 
 namespace test {
diff --git a/base/test/values_test_util.h b/base/test/values_test_util.h
index e545660..02ebca1 100644
--- a/base/test/values_test_util.h
+++ b/base/test/values_test_util.h
@@ -38,8 +38,7 @@
                            const DictionaryValue& value,
                            const std::string& key);
 
-// Takes ownership of |actual|.
-void ExpectStringValue(const std::string& expected_str, Value* actual);
+void ExpectStringValue(const std::string& expected_str, const Value& actual);
 
 namespace test {
 
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index e29cf68..ffc5b7d 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -214,6 +214,7 @@
     "//services/service_manager/public/java:service_manager_java",
     "//services/shape_detection:shape_detection_java",
     "//services/shape_detection/public/interfaces:interfaces_java",
+    "//skia/public/interfaces:interfaces_java",
     "//third_party/WebKit/public:android_mojo_bindings_java",
     "//third_party/WebKit/public:blink_headers_java",
     "//third_party/android_data_chart:android_data_chart_java",
diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/bookmarks/bookmark_html_writer.cc
index 5bfecb94..2ebc262 100644
--- a/chrome/browser/bookmarks/bookmark_html_writer.cc
+++ b/chrome/browser/bookmarks/bookmark_html_writer.cc
@@ -96,15 +96,14 @@
 // Class responsible for the actual writing. Takes ownership of favicons_map.
 class Writer : public base::RefCountedThreadSafe<Writer> {
  public:
-  Writer(base::Value* bookmarks,
+  Writer(std::unique_ptr<base::Value> bookmarks,
          const base::FilePath& path,
          BookmarkFaviconFetcher::URLFaviconMap* favicons_map,
          BookmarksExportObserver* observer)
-      : bookmarks_(bookmarks),
+      : bookmarks_(std::move(bookmarks)),
         path_(path),
         favicons_map_(favicons_map),
-        observer_(observer) {
-  }
+        observer_(observer) {}
 
   // Writing bookmarks and favicons data to file.
   void DoWrite() {
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
index f069335..91c3678 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
@@ -185,14 +185,12 @@
     case chromeos::DeviceSettingsService::STORE_KEY_UNAVAILABLE:
       status_ = STATUS_BAD_STATE;
       return;
-    case chromeos::DeviceSettingsService::STORE_POLICY_ERROR:
     case chromeos::DeviceSettingsService::STORE_OPERATION_FAILED:
       status_ = STATUS_STORE_ERROR;
       return;
     case chromeos::DeviceSettingsService::STORE_NO_POLICY:
     case chromeos::DeviceSettingsService::STORE_INVALID_POLICY:
     case chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR:
-    case chromeos::DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR:
       status_ = STATUS_LOAD_ERROR;
       return;
   }
@@ -210,9 +208,7 @@
     case chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR:
       // Continue with the check below.
       break;
-    case chromeos::DeviceSettingsService::STORE_POLICY_ERROR:
     case chromeos::DeviceSettingsService::STORE_OPERATION_FAILED:
-    case chromeos::DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR:
       // Don't check for write errors or transient read errors.
       return;
   }
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index 6e0e106..79d581b 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -890,7 +890,6 @@
       VLOG(1) << "No policies present yet, will use the temp storage.";
       trusted_status_ = PERMANENTLY_UNTRUSTED;
       break;
-    case DeviceSettingsService::STORE_POLICY_ERROR:
     case DeviceSettingsService::STORE_VALIDATION_ERROR:
     case DeviceSettingsService::STORE_INVALID_POLICY:
     case DeviceSettingsService::STORE_OPERATION_FAILED:
@@ -898,13 +897,6 @@
                  << device_settings_service_->status();
       trusted_status_ = PERMANENTLY_UNTRUSTED;
       break;
-    case DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR:
-      // The policy has failed to validate due to temporary error but it might
-      // take a long time until we recover so behave as it is a permanent error.
-      LOG(ERROR) << "Failed to retrieve cros policies because a temporary "
-                 << "validation error has occurred. Retrying might succeed.";
-      trusted_status_ = PERMANENTLY_UNTRUSTED;
-      break;
   }
 
   // Notify the observers we are done.
diff --git a/chrome/browser/chromeos/settings/device_settings_service.cc b/chrome/browser/chromeos/settings/device_settings_service.cc
index 1fc8db3..ed3fd6b 100644
--- a/chrome/browser/chromeos/settings/device_settings_service.cc
+++ b/chrome/browser/chromeos/settings/device_settings_service.cc
@@ -29,19 +29,6 @@
 using ownership::OwnerKeyUtil;
 using ownership::PublicKey;
 
-namespace {
-
-// Delay between load retries when there was a validation error.
-// NOTE: This code is here to mitigate clock loss on some devices where policy
-// loads will fail with a validation error caused by RTC clock being reset when
-// the battery is drained.
-int kLoadRetryDelayMs = 1000 * 5;
-// Maximal number of retries before we give up. Calculated to allow for 10 min
-// of retry time.
-int kMaxLoadRetries = (1000 * 60 * 10) / kLoadRetryDelayMs;
-
-}  // namespace
-
 namespace chromeos {
 
 DeviceSettingsService::Observer::~Observer() {}
@@ -78,8 +65,7 @@
   return g_device_settings_service;
 }
 
-DeviceSettingsService::DeviceSettingsService()
-    : load_retries_left_(kMaxLoadRetries), weak_factory_(this) {}
+DeviceSettingsService::DeviceSettingsService() {}
 
 DeviceSettingsService::~DeviceSettingsService() {
   DCHECK(pending_operations_.empty());
@@ -303,26 +289,8 @@
   if (status == STORE_SUCCESS) {
     policy_data_ = std::move(operation->policy_data());
     device_settings_ = std::move(operation->device_settings());
-    load_retries_left_ = kMaxLoadRetries;
   } else if (status != STORE_KEY_UNAVAILABLE) {
     LOG(ERROR) << "Session manager operation failed: " << status;
-    // Validation errors can be temporary if the rtc has gone on holiday for a
-    // short while. So we will retry such loads for up to 10 minutes.
-    if (status == STORE_TEMP_VALIDATION_ERROR) {
-      if (load_retries_left_ > 0) {
-        load_retries_left_--;
-        LOG(ERROR) << "A re-load has been scheduled due to a validation error.";
-        content::BrowserThread::PostDelayedTask(
-            content::BrowserThread::UI,
-            FROM_HERE,
-            base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
-            base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
-      } else {
-        // Once we've given up retrying, the validation error is not temporary
-        // anymore.
-        store_status_ = STORE_VALIDATION_ERROR;
-      }
-    }
   }
 
   public_key_ = scoped_refptr<PublicKey>(operation->public_key());
diff --git a/chrome/browser/chromeos/settings/device_settings_service.h b/chrome/browser/chromeos/settings/device_settings_service.h
index e080658..0840b621 100644
--- a/chrome/browser/chromeos/settings/device_settings_service.h
+++ b/chrome/browser/chromeos/settings/device_settings_service.h
@@ -59,16 +59,14 @@
 
   typedef base::Callback<void(OwnershipStatus)> OwnershipStatusCallback;
 
-  // Status codes for Store().
+  // Status codes for Load() and Store().
   enum Status {
     STORE_SUCCESS,
-    STORE_KEY_UNAVAILABLE,       // Owner key not yet configured.
-    STORE_POLICY_ERROR,          // Failure constructing the settings blob.
-    STORE_OPERATION_FAILED,      // IPC to session_manager daemon failed.
-    STORE_NO_POLICY,             // No settings blob present.
-    STORE_INVALID_POLICY,        // Invalid settings blob.
-    STORE_VALIDATION_ERROR,      // Unrecoverable policy validation failure.
-    STORE_TEMP_VALIDATION_ERROR, // Temporary policy validation failure.
+    STORE_KEY_UNAVAILABLE,   // Owner key not yet configured.
+    STORE_OPERATION_FAILED,  // IPC to session_manager daemon failed.
+    STORE_NO_POLICY,         // No settings blob present.
+    STORE_INVALID_POLICY,    // Invalid settings blob (proto parse failed).
+    STORE_VALIDATION_ERROR,  // Policy validation failure.
   };
 
   // Observer interface.
@@ -253,13 +251,10 @@
 
   base::ObserverList<Observer> observers_;
 
-  // For recoverable load errors how many retries are left before we give up.
-  int load_retries_left_;
-
   // Whether the device will be establishing consumer ownership.
   bool will_establish_consumer_ownership_ = false;
 
-  base::WeakPtrFactory<DeviceSettingsService> weak_factory_;
+  base::WeakPtrFactory<DeviceSettingsService> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(DeviceSettingsService);
 };
diff --git a/chrome/browser/chromeos/settings/session_manager_operation.cc b/chrome/browser/chromeos/settings/session_manager_operation.cc
index 47d6007..c3e2659d 100644
--- a/chrome/browser/chromeos/settings/session_manager_operation.cc
+++ b/chrome/browser/chromeos/settings/session_manager_operation.cc
@@ -151,13 +151,13 @@
 void SessionManagerOperation::ValidateDeviceSettings(
     const std::string& policy_blob,
     RetrievePolicyResponseType response_type) {
-  std::unique_ptr<em::PolicyFetchResponse> policy(
-      new em::PolicyFetchResponse());
   if (policy_blob.empty()) {
     ReportResult(DeviceSettingsService::STORE_NO_POLICY);
     return;
   }
 
+  std::unique_ptr<em::PolicyFetchResponse> policy =
+      base::MakeUnique<em::PolicyFetchResponse>();
   if (!policy->ParseFromString(policy_blob) || !policy->IsInitialized()) {
     ReportResult(DeviceSettingsService::STORE_INVALID_POLICY);
     return;
@@ -210,23 +210,14 @@
 
 void SessionManagerOperation::ReportValidatorStatus(
     policy::DeviceCloudPolicyValidator* validator) {
-  DeviceSettingsService::Status status =
-      DeviceSettingsService::STORE_VALIDATION_ERROR;
   if (validator->success()) {
-    status = DeviceSettingsService::STORE_SUCCESS;
     policy_data_ = std::move(validator->policy_data());
     device_settings_ = std::move(validator->payload());
+    ReportResult(DeviceSettingsService::STORE_SUCCESS);
   } else {
     LOG(ERROR) << "Policy validation failed: " << validator->status();
-
-    // Those are mostly caused by RTC loss and are recoverable.
-    if (validator->status() ==
-        policy::DeviceCloudPolicyValidator::VALIDATION_BAD_TIMESTAMP) {
-      status = DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR;
-    }
+    ReportResult(DeviceSettingsService::STORE_VALIDATION_ERROR);
   }
-
-  ReportResult(status);
 }
 
 LoadSettingsOperation::LoadSettingsOperation(bool force_key_load,
diff --git a/components/autofill/core/browser/autofill_address_util.cc b/components/autofill/core/browser/autofill_address_util.cc
index bdeea81..e5d9872 100644
--- a/components/autofill/core/browser/autofill_address_util.cc
+++ b/components/autofill/core/browser/autofill_address_util.cc
@@ -171,7 +171,7 @@
         "value", countries[i] ? countries[i]->country_code() : "separator");
     country_list->Append(std::move(option_details));
   }
-  localized_strings->Set("autofillCountrySelectList", country_list.release());
+  localized_strings->Set("autofillCountrySelectList", std::move(country_list));
 
   std::unique_ptr<base::ListValue> default_country_components(
       new base::ListValue);
@@ -180,7 +180,7 @@
                        default_country_components.get(),
                        &default_country_language_code);
   localized_strings->Set("autofillDefaultCountryComponents",
-                         default_country_components.release());
+                         std::move(default_country_components));
   localized_strings->SetString("autofillDefaultCountryLanguageCode",
                                default_country_language_code);
 }
diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmarks/browser/bookmark_codec.cc
index 81aca1f8..97ede4fda 100644
--- a/components/bookmarks/browser/bookmark_codec.cc
+++ b/components/bookmarks/browser/bookmark_codec.cc
@@ -56,7 +56,7 @@
 
 BookmarkCodec::~BookmarkCodec() {}
 
-base::Value* BookmarkCodec::Encode(BookmarkModel* model) {
+std::unique_ptr<base::Value> BookmarkCodec::Encode(BookmarkModel* model) {
   return Encode(model->bookmark_bar_node(),
                 model->other_node(),
                 model->mobile_node(),
@@ -64,7 +64,7 @@
                 model->root_node()->sync_transaction_version());
 }
 
-base::Value* BookmarkCodec::Encode(
+std::unique_ptr<base::Value> BookmarkCodec::Encode(
     const BookmarkNode* bookmark_bar_node,
     const BookmarkNode* other_folder_node,
     const BookmarkNode* mobile_folder_node,
@@ -72,7 +72,7 @@
     int64_t sync_transaction_version) {
   ids_reassigned_ = false;
   InitializeChecksum();
-  base::DictionaryValue* roots = new base::DictionaryValue();
+  auto roots = base::MakeUnique<base::DictionaryValue>();
   roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node));
   roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node));
   roots->Set(kMobileBookmarkFolderNameKey, EncodeNode(mobile_folder_node));
@@ -83,15 +83,15 @@
     roots->SetString(kSyncTransactionVersion,
                      base::Int64ToString(sync_transaction_version));
   }
-  base::DictionaryValue* main = new base::DictionaryValue();
+  auto main = base::MakeUnique<base::DictionaryValue>();
   main->SetInteger(kVersionKey, kCurrentVersion);
   FinalizeChecksum();
   // We are going to store the computed checksum. So set stored checksum to be
   // the same as computed checksum.
   stored_checksum_ = computed_checksum_;
-  main->Set(kChecksumKey, new base::Value(computed_checksum_));
-  main->Set(kRootsKey, roots);
-  return main;
+  main->SetString(kChecksumKey, computed_checksum_);
+  main->Set(kRootsKey, std::move(roots));
+  return std::move(main);
 }
 
 bool BookmarkCodec::Decode(BookmarkNode* bb_node,
@@ -137,10 +137,10 @@
         base::Int64ToString(node->date_folder_modified().ToInternalValue()));
     UpdateChecksumWithFolderNode(id, title);
 
-    base::ListValue* child_values = new base::ListValue();
-    value->Set(kChildrenKey, child_values);
+    auto child_values = base::MakeUnique<base::ListValue>();
     for (int i = 0; i < node->child_count(); ++i)
       child_values->Append(EncodeNode(node->GetChild(i)));
+    value->Set(kChildrenKey, std::move(child_values));
   }
   const BookmarkNode::MetaInfoMap* meta_info_map = node->GetMetaInfoMap();
   if (meta_info_map)
@@ -153,14 +153,14 @@
   return std::move(value);
 }
 
-base::Value* BookmarkCodec::EncodeMetaInfo(
+std::unique_ptr<base::Value> BookmarkCodec::EncodeMetaInfo(
     const BookmarkNode::MetaInfoMap& meta_info_map) {
-  base::DictionaryValue* meta_info = new base::DictionaryValue;
+  auto meta_info = base::MakeUnique<base::DictionaryValue>();
   for (BookmarkNode::MetaInfoMap::const_iterator it = meta_info_map.begin();
       it != meta_info_map.end(); ++it) {
     meta_info->SetStringWithoutPathExpansion(it->first, it->second);
   }
-  return meta_info;
+  return std::move(meta_info);
 }
 
 bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node,
diff --git a/components/bookmarks/browser/bookmark_codec.h b/components/bookmarks/browser/bookmark_codec.h
index 7760826e..313729ef 100644
--- a/components/bookmarks/browser/bookmark_codec.h
+++ b/components/bookmarks/browser/bookmark_codec.h
@@ -42,15 +42,15 @@
   // returned object. This is invoked to encode the contents of the bookmark bar
   // model and is currently a convenience to invoking Encode that takes the
   // bookmark bar node and other folder node.
-  base::Value* Encode(BookmarkModel* model);
+  std::unique_ptr<base::Value> Encode(BookmarkModel* model);
 
-  // Encodes the bookmark bar and other folders returning the JSON value. It's
-  // up to the caller to delete the returned object.
-  base::Value* Encode(const BookmarkNode* bookmark_bar_node,
-                      const BookmarkNode* other_folder_node,
-                      const BookmarkNode* mobile_folder_node,
-                      const BookmarkNode::MetaInfoMap* model_meta_info_map,
-                      int64_t sync_transaction_version);
+  // Encodes the bookmark bar and other folders returning the JSON value.
+  std::unique_ptr<base::Value> Encode(
+      const BookmarkNode* bookmark_bar_node,
+      const BookmarkNode* other_folder_node,
+      const BookmarkNode* mobile_folder_node,
+      const BookmarkNode::MetaInfoMap* model_meta_info_map,
+      int64_t sync_transaction_version);
 
   // Decodes the previously encoded value to the specified nodes as well as
   // setting |max_node_id| to the greatest node id. Returns true on success,
@@ -112,9 +112,9 @@
   // Encodes node and all its children into a Value object and returns it.
   std::unique_ptr<base::Value> EncodeNode(const BookmarkNode* node);
 
-  // Encodes the given meta info into a Value object and returns it. The caller
-  // takes ownership of the returned object.
-  base::Value* EncodeMetaInfo(const BookmarkNode::MetaInfoMap& meta_info_map);
+  // Encodes the given meta info into a Value object and returns it.
+  std::unique_ptr<base::Value> EncodeMetaInfo(
+      const BookmarkNode::MetaInfoMap& meta_info_map);
 
   // Helper to perform decoding.
   bool DecodeHelper(BookmarkNode* bb_node,
diff --git a/components/cloud_devices/common/cloud_device_description.cc b/components/cloud_devices/common/cloud_device_description.cc
index 56cbb46..75518b2 100644
--- a/components/cloud_devices/common/cloud_device_description.cc
+++ b/components/cloud_devices/common/cloud_device_description.cc
@@ -63,9 +63,7 @@
 
 base::DictionaryValue* CloudDeviceDescription::CreateItem(
     const std::string& path) {
-  base::DictionaryValue* value = new base::DictionaryValue;
-  root_->Set(path, value);
-  return value;
+  return root_->SetDictionary(path, base::MakeUnique<base::DictionaryValue>());
 }
 
 const base::ListValue* CloudDeviceDescription::GetListItem(
@@ -77,9 +75,7 @@
 
 base::ListValue* CloudDeviceDescription::CreateListItem(
     const std::string& path) {
-  base::ListValue* value = new base::ListValue;
-  root_->Set(path, value);
-  return value;
+  return root_->SetList(path, base::MakeUnique<base::ListValue>());
 }
 
 }  // namespace cloud_devices
diff --git a/components/cloud_devices/common/printer_description.cc b/components/cloud_devices/common/printer_description.cc
index aa7fa38..3cff189 100644
--- a/components/cloud_devices/common/printer_description.cc
+++ b/components/cloud_devices/common/printer_description.cc
@@ -13,6 +13,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "components/cloud_devices/common/cloud_device_description_consts.h"
@@ -733,16 +734,15 @@
 
   static void Save(const PageRange& option, base::DictionaryValue* dict) {
     if (!option.empty()) {
-      base::ListValue* list = new base::ListValue;
-      dict->Set(kPageRangeInterval, list);
+      auto list = base::MakeUnique<base::ListValue>();
       for (size_t i = 0; i < option.size(); ++i) {
-        std::unique_ptr<base::DictionaryValue> interval(
-            new base::DictionaryValue);
+        auto interval = base::MakeUnique<base::DictionaryValue>();
         interval->SetInteger(kPageRangeStart, option[i].start);
         if (option[i].end < kMaxPageNumber)
           interval->SetInteger(kPageRangeEnd, option[i].end);
         list->Append(std::move(interval));
       }
+      dict->Set(kPageRangeInterval, std::move(list));
     }
   }
 };
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc
index fd6ddc7..ee0fa9d 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc
@@ -106,8 +106,8 @@
   auto data_reduction_proxy_values = base::MakeUnique<base::DictionaryValue>();
   data_reduction_proxy_values->SetBoolean("enabled", enabled_);
   if (current_configuration_) {
-    data_reduction_proxy_values->Set("proxy_config",
-                                     current_configuration_->DeepCopy());
+    data_reduction_proxy_values->Set(
+        "proxy_config", base::MakeUnique<base::Value>(*current_configuration_));
   }
 
   switch (secure_proxy_check_state_) {
@@ -129,8 +129,8 @@
     int current_time_ticks_ms =
         (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
     if (expiration_ticks_ > current_time_ticks_ms) {
-      data_reduction_proxy_values->Set("last_bypass",
-                                       last_bypass_event->DeepCopy());
+      data_reduction_proxy_values->Set(
+          "last_bypass", base::MakeUnique<base::Value>(*last_bypass_event));
     }
   }
 
diff --git a/components/domain_reliability/beacon.cc b/components/domain_reliability/beacon.cc
index 8a8a549f..590a666 100644
--- a/components/domain_reliability/beacon.cc
+++ b/components/domain_reliability/beacon.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/memory/ptr_util.h"
 #include "base/values.h"
 #include "components/domain_reliability/util.h"
 #include "net/base/net_errors.h"
@@ -25,7 +26,7 @@
     base::TimeTicks last_network_change_time,
     const GURL& collector_url,
     const std::vector<std::unique_ptr<std::string>>& path_prefixes) const {
-  std::unique_ptr<DictionaryValue> beacon_value(new DictionaryValue());
+  auto beacon_value = base::MakeUnique<DictionaryValue>();
   DCHECK(url.is_valid());
   GURL sanitized_url = SanitizeURLForReport(url, collector_url, path_prefixes);
   beacon_value->SetString("url", sanitized_url.spec());
@@ -33,10 +34,10 @@
   if (!quic_error.empty())
     beacon_value->SetString("quic_error", quic_error);
   if (chrome_error != net::OK) {
-    DictionaryValue* failure_value = new DictionaryValue();
+    auto failure_value = base::MakeUnique<DictionaryValue>();
     failure_value->SetString("custom_error",
                              net::ErrorToString(chrome_error));
-    beacon_value->Set("failure_data", failure_value);
+    beacon_value->Set("failure_data", std::move(failure_value));
   }
   beacon_value->SetString("server_ip", server_ip);
   beacon_value->SetBoolean("was_proxied", was_proxied);
diff --git a/components/domain_reliability/context.cc b/components/domain_reliability/context.cc
index a5c0e197..826b13c 100644
--- a/components/domain_reliability/context.cc
+++ b/components/domain_reliability/context.cc
@@ -231,7 +231,7 @@
 
   std::unique_ptr<DictionaryValue> report_value(new DictionaryValue());
   report_value->SetString("reporter", upload_reporter_string_);
-  report_value->Set("entries", beacons_value.release());
+  report_value->Set("entries", std::move(beacons_value));
 
   *max_upload_depth_out = max_upload_depth;
   return std::move(report_value);
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc
index 580d3d7..7400c61 100644
--- a/components/error_page/common/localized_error.cc
+++ b/components/error_page/common/localized_error.cc
@@ -506,7 +506,7 @@
             l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY));
       cache_button->SetString("cacheUrl", cache_url);
       cache_button->SetInteger("trackingId", cache_tracking_id);
-      error_strings->Set("cacheButton", cache_button.release());
+      error_strings->Set("cacheButton", std::move(cache_button));
 
       // Remove the item from suggestions dictionary so that it does not get
       // displayed by the template in the details section.
@@ -900,13 +900,13 @@
   std::string icon_class = GetIconClassForError(error_domain, error_code);
   error_strings->SetString("iconClass", icon_class);
 
-  base::DictionaryValue* heading = new base::DictionaryValue;
+  auto heading = base::MakeUnique<base::DictionaryValue>();
   heading->SetString("msg",
                      l10n_util::GetStringUTF16(options.heading_resource_id));
   heading->SetString("hostName", host_name);
-  error_strings->Set("heading", heading);
+  error_strings->Set("heading", std::move(heading));
 
-  base::DictionaryValue* summary = new base::DictionaryValue;
+  auto summary = base::MakeUnique<base::DictionaryValue>();
 
   // Set summary message under the heading.
   summary->SetString(
@@ -934,7 +934,7 @@
   error_strings->SetString(
       "hideDetails", l10n_util::GetStringUTF16(
           IDS_ERRORPAGE_NET_BUTTON_HIDE_DETAILS));
-  error_strings->Set("summary", summary);
+  error_strings->Set("summary", std::move(summary));
 
   base::string16 error_string;
   if (error_domain == net::kErrorDomain) {
@@ -961,16 +961,17 @@
 
   bool use_default_suggestions = true;
   if (!params->override_suggestions) {
-    suggestions_details = new base::ListValue();
-    suggestions_summary_list = new base::ListValue();
     // Detailed suggestion information.
-    error_strings->Set("suggestionsDetails", suggestions_details);
+    suggestions_details = error_strings->SetList(
+        "suggestionsDetails", base::MakeUnique<base::ListValue>());
+    suggestions_summary_list = error_strings->SetList(
+        "suggestionsSummaryList", base::MakeUnique<base::ListValue>());
   } else {
-    suggestions_summary_list = params->override_suggestions.release();
+    suggestions_summary_list = error_strings->SetList(
+        "suggestionsSummaryList", std::move(params->override_suggestions));
     use_default_suggestions = false;
     AddGoogleCachedCopyButton(suggestions_summary_list, error_strings);
   }
-  error_strings->Set("suggestionsSummaryList", suggestions_summary_list);
 
   if (params->search_url.is_valid()) {
     std::unique_ptr<base::DictionaryValue> search_suggestion(
@@ -994,12 +995,12 @@
 #if defined(OS_ANDROID)
     reload_visible = true;
 #endif  // defined(OS_ANDROID)
-    base::DictionaryValue* reload_button = new base::DictionaryValue;
+    auto reload_button = base::MakeUnique<base::DictionaryValue>();
     reload_button->SetString(
         "msg", l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_RELOAD));
     reload_button->SetString("reloadUrl", failed_url.spec());
-    error_strings->Set("reloadButton", reload_button);
     reload_button->SetInteger("reloadTrackingId", params->reload_tracking_id);
+    error_strings->Set("reloadButton", std::move(reload_button));
   }
 
   // If not using the default suggestions, nothing else to do.
@@ -1033,7 +1034,7 @@
       (show_saved_copy_primary || show_saved_copy_secondary));
 
   if (show_saved_copy_visible) {
-    base::DictionaryValue* show_saved_copy_button = new base::DictionaryValue;
+    auto show_saved_copy_button = base::MakeUnique<base::DictionaryValue>();
     show_saved_copy_button->SetString(
         "msg", l10n_util::GetStringUTF16(
             IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY));
@@ -1042,7 +1043,8 @@
         l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY_HELP));
     if (show_saved_copy_primary)
       show_saved_copy_button->SetString("primary", "true");
-    error_strings->Set("showSavedCopyButton", show_saved_copy_button);
+    error_strings->Set("showSavedCopyButton",
+                       std::move(show_saved_copy_button));
   }
 
 #if defined(OS_ANDROID)
diff --git a/components/error_page/renderer/net_error_helper_core.cc b/components/error_page/renderer/net_error_helper_core.cc
index 287cd84d..89dff328 100644
--- a/components/error_page/renderer/net_error_helper_core.cc
+++ b/components/error_page/renderer/net_error_helper_core.cc
@@ -209,7 +209,7 @@
   base::DictionaryValue request_dict;
   request_dict.SetString("method", method);
   request_dict.SetString("apiVersion", "v1");
-  request_dict.Set("params", params_dict.release());
+  request_dict.Set("params", std::move(params_dict));
 
   std::string request_body;
   bool success = base::JSONWriter::Write(request_dict, &request_body);
diff --git a/components/error_page/renderer/net_error_helper_core_unittest.cc b/components/error_page/renderer/net_error_helper_core_unittest.cc
index f67d1cd..12bb4a4 100644
--- a/components/error_page/renderer/net_error_helper_core_unittest.cc
+++ b/components/error_page/renderer/net_error_helper_core_unittest.cc
@@ -9,12 +9,14 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/histogram_tester.h"
@@ -82,12 +84,12 @@
 
 std::string SuggestionsToResponse(const NavigationCorrection* corrections,
                                   int num_corrections) {
-  base::ListValue* url_corrections = new base::ListValue();
+  auto url_corrections = base::MakeUnique<base::ListValue>();
   for (int i = 0; i < num_corrections; ++i)
     url_corrections->Append(corrections[i].ToValue());
 
   base::DictionaryValue response;
-  response.Set("result.UrlCorrections", url_corrections);
+  response.Set("result.UrlCorrections", std::move(url_corrections));
   response.SetString("result.eventId", kNavigationCorrectionEventId);
   response.SetString("result.fingerprint", kNavigationCorrectionFingerprint);
 
diff --git a/components/flags_ui/flags_state.cc b/components/flags_ui/flags_state.cc
index d89c3629..c08d3983 100644
--- a/components/flags_ui/flags_state.cc
+++ b/components/flags_ui/flags_state.cc
@@ -11,6 +11,7 @@
 #include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/stl_util.h"
 #include "base/strings/string_piece.h"
@@ -175,22 +176,23 @@
 }
 
 // Returns the Value representing the choice data in the specified entry.
-base::Value* CreateOptionsData(const FeatureEntry& entry,
-                               const std::set<std::string>& enabled_entries) {
+std::unique_ptr<base::Value> CreateOptionsData(
+    const FeatureEntry& entry,
+    const std::set<std::string>& enabled_entries) {
   DCHECK(entry.type == FeatureEntry::MULTI_VALUE ||
          entry.type == FeatureEntry::ENABLE_DISABLE_VALUE ||
          entry.type == FeatureEntry::FEATURE_VALUE ||
          entry.type == FeatureEntry::FEATURE_WITH_PARAMS_VALUE);
-  base::ListValue* result = new base::ListValue;
+  auto result = base::MakeUnique<base::ListValue>();
   for (int i = 0; i < entry.num_options; ++i) {
-    std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue);
+    auto value = base::MakeUnique<base::DictionaryValue>();
     const std::string name = entry.NameForOption(i);
     value->SetString("internal_name", name);
     value->SetString("description", entry.DescriptionForOption(i));
     value->SetBoolean("selected", enabled_entries.count(name) > 0);
     result->Append(std::move(value));
   }
-  return result;
+  return std::move(result);
 }
 
 // Registers variation parameters specified by |feature_variation_params| for
@@ -515,9 +517,9 @@
     data->SetString("description",
                     base::StringPiece(entry.visible_description));
 
-    base::ListValue* supported_platforms = new base::ListValue();
-    AddOsStrings(entry.supported_platforms, supported_platforms);
-    data->Set("supported_platforms", supported_platforms);
+    auto supported_platforms = base::MakeUnique<base::ListValue>();
+    AddOsStrings(entry.supported_platforms, supported_platforms.get());
+    data->Set("supported_platforms", std::move(supported_platforms));
     // True if the switch is not currently passed.
     bool is_default_value = IsDefaultValue(entry, enabled_entries);
     data->SetBoolean("is_default", is_default_value);
diff --git a/components/gcm_driver/gcm_internals_helper.cc b/components/gcm_driver/gcm_internals_helper.cc
index 79c397d..eb26693 100644
--- a/components/gcm_driver/gcm_internals_helper.cc
+++ b/components/gcm_driver/gcm_internals_helper.cc
@@ -9,6 +9,7 @@
 
 #include "base/format_macros.h"
 #include "base/i18n/time_formatting.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -104,8 +105,7 @@
                          gcm::GCMProfileService* profile_service,
                          PrefService* prefs,
                          base::DictionaryValue* results) {
-  base::DictionaryValue* device_info = new base::DictionaryValue();
-  results->Set(kDeviceInfo, device_info);
+  auto device_info = base::MakeUnique<base::DictionaryValue>();
 
   device_info->SetBoolean(kProfileServiceCreated, profile_service != NULL);
   device_info->SetBoolean(kGcmEnabled,
@@ -136,43 +136,45 @@
     }
     device_info->SetInteger(kSendQueueSize, stats->send_queue_size);
     device_info->SetInteger(kResendQueueSize, stats->resend_queue_size);
+    results->Set(kDeviceInfo, std::move(device_info));
 
     if (stats->recorded_activities.checkin_activities.size() > 0) {
-      base::ListValue* checkin_info = new base::ListValue();
-      results->Set(kCheckinInfo, checkin_info);
+      auto checkin_info = base::MakeUnique<base::ListValue>();
       SetCheckinInfo(stats->recorded_activities.checkin_activities,
-                     checkin_info);
+                     checkin_info.get());
+      results->Set(kCheckinInfo, std::move(checkin_info));
     }
     if (stats->recorded_activities.connection_activities.size() > 0) {
-      base::ListValue* connection_info = new base::ListValue();
-      results->Set(kConnectionInfo, connection_info);
+      auto connection_info = base::MakeUnique<base::ListValue>();
       SetConnectionInfo(stats->recorded_activities.connection_activities,
-                        connection_info);
+                        connection_info.get());
+      results->Set(kConnectionInfo, std::move(connection_info));
     }
     if (stats->recorded_activities.registration_activities.size() > 0) {
-      base::ListValue* registration_info = new base::ListValue();
-      results->Set(kRegistrationInfo, registration_info);
+      auto registration_info = base::MakeUnique<base::ListValue>();
       SetRegistrationInfo(stats->recorded_activities.registration_activities,
-                          registration_info);
+                          registration_info.get());
+      results->Set(kRegistrationInfo, std::move(registration_info));
     }
     if (stats->recorded_activities.receiving_activities.size() > 0) {
-      base::ListValue* receive_info = new base::ListValue();
-      results->Set(kReceiveInfo, receive_info);
+      auto receive_info = base::MakeUnique<base::ListValue>();
       SetReceivingInfo(stats->recorded_activities.receiving_activities,
-                       receive_info);
+                       receive_info.get());
+      results->Set(kReceiveInfo, std::move(receive_info));
     }
     if (stats->recorded_activities.sending_activities.size() > 0) {
-      base::ListValue* send_info = new base::ListValue();
-      results->Set(kSendInfo, send_info);
-      SetSendingInfo(stats->recorded_activities.sending_activities, send_info);
+      auto send_info = base::MakeUnique<base::ListValue>();
+      SetSendingInfo(stats->recorded_activities.sending_activities,
+                     send_info.get());
+      results->Set(kSendInfo, std::move(send_info));
     }
 
     if (stats->recorded_activities.decryption_failure_activities.size() > 0) {
-      base::ListValue* failure_info = new base::ListValue();
-      results->Set(kDecryptionFailureInfo, failure_info);
+      auto failure_info = base::MakeUnique<base::ListValue>();
       SetDecryptionFailureInfo(
           stats->recorded_activities.decryption_failure_activities,
-          failure_info);
+          failure_info.get());
+      results->Set(kDecryptionFailureInfo, std::move(failure_info));
     }
   }
 }
diff --git a/components/history/core/browser/web_history_service.cc b/components/history/core/browser/web_history_service.cc
index 0ce75efc..2a8a8f1 100644
--- a/components/history/core/browser/web_history_service.cc
+++ b/components/history/core/browser/web_history_service.cc
@@ -5,6 +5,7 @@
 #include "components/history/core/browser/web_history_service.h"
 
 #include <memory>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -414,7 +415,7 @@
     if (expire.urls.empty())
       deletions->Append(CreateDeletion(min_timestamp, max_timestamp, GURL()));
   }
-  delete_request.Set("del", deletions.release());
+  delete_request.Set("del", std::move(deletions));
   std::string post_data;
   base::JSONWriter::Write(delete_request, &post_data);
 
diff --git a/components/invalidation/impl/p2p_invalidator.cc b/components/invalidation/impl/p2p_invalidator.cc
index 92562ab8..0502815e 100644
--- a/components/invalidation/impl/p2p_invalidator.cc
+++ b/components/invalidation/impl/p2p_invalidator.cc
@@ -106,7 +106,7 @@
   base::DictionaryValue dict;
   dict.SetString(kSenderIdKey, sender_id_);
   dict.SetString(kNotificationTypeKey, P2PNotificationTargetToString(target_));
-  dict.Set(kInvalidationsKey, invalidation_map_.ToValue().release());
+  dict.Set(kInvalidationsKey, invalidation_map_.ToValue());
   std::string json;
   base::JSONWriter::Write(dict, &json);
   return json;
diff --git a/components/invalidation/impl/sync_invalidation_listener.cc b/components/invalidation/impl/sync_invalidation_listener.cc
index 9473db6..e0cbb97 100644
--- a/components/invalidation/impl/sync_invalidation_listener.cc
+++ b/components/invalidation/impl/sync_invalidation_listener.cc
@@ -395,10 +395,10 @@
            unacked_invalidations_map_.begin();
        it != unacked_invalidations_map_.end();
        ++it) {
-    unacked_map->Set((it->first).name(), (it->second).ToValue().release());
+    unacked_map->Set((it->first).name(), (it->second).ToValue());
   }
   return_value->Set("SyncInvalidationListener.UnackedInvalidationsMap",
-                    unacked_map.release());
+                    std::move(unacked_map));
   return return_value;
 }
 
diff --git a/components/invalidation/impl/unacked_invalidation_set.cc b/components/invalidation/impl/unacked_invalidation_set.cc
index ece3176..92d80f29 100644
--- a/components/invalidation/impl/unacked_invalidation_set.cc
+++ b/components/invalidation/impl/unacked_invalidation_set.cc
@@ -4,6 +4,8 @@
 
 #include "components/invalidation/impl/unacked_invalidation_set.h"
 
+#include <utility>
+
 #include "base/strings/string_number_conversions.h"
 #include "components/invalidation/public/ack_handle.h"
 #include "components/invalidation/public/object_id_invalidation_map.h"
@@ -167,7 +169,7 @@
        it != invalidations_.end(); ++it) {
     list_value->Append(it->ToValue());
   }
-  value->Set(kInvalidationListKey, list_value.release());
+  value->Set(kInvalidationListKey, std::move(list_value));
 
   return value;
 }
diff --git a/components/invalidation/public/invalidation.cc b/components/invalidation/public/invalidation.cc
index 8877a239..f69c0ec92 100644
--- a/components/invalidation/public/invalidation.cc
+++ b/components/invalidation/public/invalidation.cc
@@ -140,7 +140,7 @@
 
 std::unique_ptr<base::DictionaryValue> Invalidation::ToValue() const {
   std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue());
-  value->Set(kObjectIdKey, ObjectIdToValue(id_).release());
+  value->Set(kObjectIdKey, ObjectIdToValue(id_));
   if (is_unknown_version_) {
     value->SetBoolean(kIsUnknownVersionKey, true);
   } else {
diff --git a/components/json_schema/json_schema_validator_unittest_base.cc b/components/json_schema/json_schema_validator_unittest_base.cc
index d49bb067..2b03abe 100644
--- a/components/json_schema/json_schema_validator_unittest_base.cc
+++ b/components/json_schema/json_schema_validator_unittest_base.cc
@@ -255,9 +255,9 @@
   schema->Remove(schema::kPatternProperties, NULL);
 
   // Test additional properties.
-  base::DictionaryValue* additional_properties = new base::DictionaryValue();
+  base::DictionaryValue* additional_properties = schema->SetDictionary(
+      schema::kAdditionalProperties, base::MakeUnique<base::DictionaryValue>());
   additional_properties->SetString(schema::kType, schema::kAny);
-  schema->Set(schema::kAdditionalProperties, additional_properties);
 
   instance->SetBoolean("extra", true);
   ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL);
@@ -406,9 +406,9 @@
                      schema::kString,
                      schema::kInteger));
 
-  base::DictionaryValue* additional_properties = new base::DictionaryValue();
+  base::DictionaryValue* additional_properties = schema->SetDictionary(
+      schema::kAdditionalProperties, base::MakeUnique<base::DictionaryValue>());
   additional_properties->SetString(schema::kType, schema::kAny);
-  schema->Set(schema::kAdditionalProperties, additional_properties);
   instance->Set(0, base::MakeUnique<base::Value>("42"));
   instance->AppendString("anything");
   ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL);
diff --git a/components/login/screens/screen_context.cc b/components/login/screens/screen_context.cc
index 3473d9c3..343570b 100644
--- a/components/login/screens/screen_context.cc
+++ b/components/login/screens/screen_context.cc
@@ -5,8 +5,10 @@
 #include "components/login/screens/screen_context.h"
 
 #include <memory>
+#include <utility>
 
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 
 namespace login {
 
@@ -177,8 +179,8 @@
   if (in_storage && new_value->Equals(current_value))
     return false;
 
-  changes_.Set(key, new_value->DeepCopy());
-  storage_.Set(key, new_value.release());
+  changes_.Set(key, base::MakeUnique<base::Value>(*new_value));
+  storage_.Set(key, std::move(new_value));
   return true;
 }
 
diff --git a/components/physical_web/webui/physical_web_base_message_handler.cc b/components/physical_web/webui/physical_web_base_message_handler.cc
index dd28dc3d..f68cfb0 100644
--- a/components/physical_web/webui/physical_web_base_message_handler.cc
+++ b/components/physical_web/webui/physical_web_base_message_handler.cc
@@ -4,6 +4,8 @@
 
 #include "components/physical_web/webui/physical_web_base_message_handler.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
@@ -88,7 +90,7 @@
     ++index;
   }
 
-  results.Set(physical_web_ui::kMetadata, metadata.release());
+  results.Set(physical_web_ui::kMetadata, std::move(metadata));
 
   // Pass the list of Physical Web URL metadata to the WebUI. A jstemplate will
   // create a list view with an item for each URL.
diff --git a/components/policy/core/common/config_dir_policy_loader_unittest.cc b/components/policy/core/common/config_dir_policy_loader_unittest.cc
index 640eb37..5e1db900 100644
--- a/components/policy/core/common/config_dir_policy_loader_unittest.cc
+++ b/components/policy/core/common/config_dir_policy_loader_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
@@ -121,7 +122,7 @@
 void TestHarness::InstallStringListPolicy(const std::string& policy_name,
                                           const base::ListValue* policy_value) {
   base::DictionaryValue dict;
-  dict.Set(policy_name, policy_value->DeepCopy());
+  dict.Set(policy_name, base::MakeUnique<base::Value>(*policy_value));
   WriteConfigFile(dict, NextConfigFileName());
 }
 
@@ -129,13 +130,13 @@
     const std::string& policy_name,
     const base::DictionaryValue* policy_value) {
   base::DictionaryValue dict;
-  dict.Set(policy_name, policy_value->DeepCopy());
+  dict.Set(policy_name, base::MakeUnique<base::Value>(*policy_value));
   WriteConfigFile(dict, NextConfigFileName());
 }
 
 void TestHarness::Install3rdPartyPolicy(const base::DictionaryValue* policies) {
   base::DictionaryValue dict;
-  dict.Set("3rdparty", policies->DeepCopy());
+  dict.Set("3rdparty", base::MakeUnique<base::Value>(*policies));
   WriteConfigFile(dict, NextConfigFileName());
 }
 
diff --git a/components/policy/core/common/configuration_policy_provider_test.cc b/components/policy/core/common/configuration_policy_provider_test.cc
index cf9c8e1f..0cf58de1 100644
--- a/components/policy/core/common/configuration_policy_provider_test.cc
+++ b/components/policy/core/common/configuration_policy_provider_test.cc
@@ -301,24 +301,24 @@
   expected_value.SetInteger("int", 123);
   expected_value.SetString("string", "omg");
 
-  base::ListValue* list = new base::ListValue();
+  auto list = base::MakeUnique<base::ListValue>();
   list->AppendString("first");
   list->AppendString("second");
-  expected_value.Set("array", list);
+  expected_value.Set("array", std::move(list));
 
-  base::DictionaryValue* dict = new base::DictionaryValue();
+  auto dict = base::MakeUnique<base::DictionaryValue>();
   dict->SetString("sub", "value");
-  list = new base::ListValue();
-  std::unique_ptr<base::DictionaryValue> sub(new base::DictionaryValue());
+  list = base::MakeUnique<base::ListValue>();
+  auto sub = base::MakeUnique<base::DictionaryValue>();
   sub->SetInteger("aaa", 111);
   sub->SetInteger("bbb", 222);
   list->Append(std::move(sub));
-  sub.reset(new base::DictionaryValue());
+  sub = base::MakeUnique<base::DictionaryValue>();
   sub->SetString("ccc", "333");
   sub->SetString("ddd", "444");
   list->Append(std::move(sub));
-  dict->Set("sublist", list);
-  expected_value.Set("dictionary", dict);
+  dict->Set("sublist", std::move(list));
+  expected_value.Set("dictionary", std::move(dict));
 
   CheckValue(test_keys::kKeyDictionary,
              expected_value,
@@ -370,15 +370,15 @@
   policy_dict.SetInteger("int", 789);
   policy_dict.SetString("string", "string value");
 
-  base::ListValue* list = new base::ListValue();
+  auto list = base::MakeUnique<base::ListValue>();
   for (int i = 0; i < 2; ++i) {
-    std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+    auto dict = base::MakeUnique<base::DictionaryValue>();
     dict->SetInteger("subdictindex", i);
-    dict->Set("subdict", policy_dict.DeepCopy());
+    dict->Set("subdict", base::MakeUnique<base::Value>(policy_dict));
     list->Append(std::move(dict));
   }
-  policy_dict.Set("list", list);
-  policy_dict.Set("dict", policy_dict.DeepCopy());
+  policy_dict.Set("list", std::move(list));
+  policy_dict.Set("dict", base::MakeUnique<base::Value>(policy_dict));
 
   // Install these policies as a Chrome policy.
   test_harness_->InstallDictionaryPolicy(test_keys::kKeyDictionary,
@@ -386,14 +386,15 @@
   // Install them as 3rd party policies too.
   base::DictionaryValue policy_3rdparty;
   policy_3rdparty.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-                      policy_dict.DeepCopy());
+                      base::MakeUnique<base::Value>(policy_dict));
   policy_3rdparty.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
-                      policy_dict.DeepCopy());
+                      base::MakeUnique<base::Value>(policy_dict));
   // Install invalid 3rd party policies that shouldn't be loaded. These also
   // help detecting memory leaks in the code paths that detect invalid input.
-  policy_3rdparty.Set("invalid-domain.component", policy_dict.DeepCopy());
-  policy_3rdparty.Set("extensions.cccccccccccccccccccccccccccccccc",
-                      new base::Value("invalid-value"));
+  policy_3rdparty.Set("invalid-domain.component",
+                      base::MakeUnique<base::Value>(policy_dict));
+  policy_3rdparty.SetString("extensions.cccccccccccccccccccccccccccccccc",
+                            "invalid-value");
   test_harness_->Install3rdPartyPolicy(&policy_3rdparty);
 
   provider_->RefreshPolicies();
diff --git a/components/policy/core/common/schema_unittest.cc b/components/policy/core/common/schema_unittest.cc
index 3ebec136..d0af065 100644
--- a/components/policy/core/common/schema_unittest.cc
+++ b/components/policy/core/common/schema_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/values.h"
 #include "components/policy/core/common/schema_internal.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -619,7 +620,7 @@
     bundle.Clear();
     base::ListValue list;
     list.AppendInteger(1);
-    bundle.Set("Array", list.DeepCopy());
+    bundle.Set("Array", base::MakeUnique<base::Value>(list));
     TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
   }
 
@@ -628,7 +629,7 @@
     bundle.Clear();
     base::DictionaryValue dict;
     dict.SetString("one", "one");
-    bundle.Set("Object", dict.DeepCopy());
+    bundle.Set("Object", base::MakeUnique<base::Value>(dict));
     TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
   }
 
@@ -642,14 +643,14 @@
   bundle.SetBoolean("Boolean", true);
   bundle.SetInteger("Integer", 123);
   bundle.Set("Null", base::MakeUnique<base::Value>());
-  bundle.Set("Number", new base::Value(3.14));
+  bundle.SetDouble("Number", 3.14);
   bundle.SetString("String", "omg");
 
   {
     base::ListValue list;
     list.AppendString("a string");
     list.AppendString("another string");
-    bundle.Set("Array", list.DeepCopy());
+    bundle.Set("Array", base::MakeUnique<base::Value>(list));
   }
 
   {
@@ -657,9 +658,9 @@
     dict.SetString("one", "string");
     dict.SetInteger("two", 2);
     base::ListValue list;
-    list.Append(dict.CreateDeepCopy());
-    list.Append(dict.CreateDeepCopy());
-    bundle.Set("ArrayOfObjects", list.DeepCopy());
+    list.GetList().push_back(dict);
+    list.GetList().push_back(dict);
+    bundle.Set("ArrayOfObjects", base::MakeUnique<base::Value>(list));
   }
 
   {
@@ -667,9 +668,9 @@
     list.AppendString("a string");
     list.AppendString("another string");
     base::ListValue listlist;
-    listlist.Append(list.CreateDeepCopy());
-    listlist.Append(list.CreateDeepCopy());
-    bundle.Set("ArrayOfArray", listlist.DeepCopy());
+    listlist.GetList().push_back(list);
+    listlist.GetList().push_back(list);
+    bundle.Set("ArrayOfArray", base::MakeUnique<base::Value>(listlist));
   }
 
   {
@@ -678,7 +679,7 @@
     dict.SetInteger("two", 2);
     dict.SetString("additionally", "a string");
     dict.SetString("and also", "another string");
-    bundle.Set("Object", dict.DeepCopy());
+    bundle.Set("Object", base::MakeUnique<base::Value>(dict));
   }
 
   bundle.SetInteger("IntegerWithEnums", 1);
@@ -803,8 +804,8 @@
     ASSERT_TRUE(subschema.valid());
     base::DictionaryValue root;
 
-    base::ListValue* list_value = new base::ListValue();
-    root.Set("List", list_value);  // Pass ownership to root.
+    base::ListValue* list_value =
+        root.SetList("List", base::MakeUnique<base::ListValue>());
 
     // Test that there are not errors here.
     list_value->AppendInteger(12345);
@@ -830,10 +831,9 @@
     ASSERT_TRUE(subschema.valid());
     base::ListValue root;
 
-    base::ListValue* list_value = new base::ListValue();
-    std::unique_ptr<base::DictionaryValue> dict_value(
-        new base::DictionaryValue());
-    dict_value->Set("List", list_value);  // Pass ownership to dict_value.
+    auto dict_value = base::MakeUnique<base::DictionaryValue>();
+    base::ListValue* list_value =
+        dict_value->SetList("List", base::MakeUnique<base::ListValue>());
     root.Append(std::move(dict_value));
 
     // Test that there are not errors here.
diff --git a/components/printing/test/print_web_view_helper_browsertest.cc b/components/printing/test/print_web_view_helper_browsertest.cc
index 3c708f7..8f4e244 100644
--- a/components/printing/test/print_web_view_helper_browsertest.cc
+++ b/components/printing/test/print_web_view_helper_browsertest.cc
@@ -1054,7 +1054,7 @@
 
   // Non default scaling value
   dict.SetInteger(kSettingScaleFactor, 80);
-  dict.Set(kSettingMediaSize, media_size.release());
+  dict.Set(kSettingMediaSize, std::move(media_size));
 
   OnPrintForPrintPreview(dict);
 
diff --git a/components/proximity_auth/screenlock_bridge.cc b/components/proximity_auth/screenlock_bridge.cc
index e5ca4f2..891c9d1 100644
--- a/components/proximity_auth/screenlock_bridge.cc
+++ b/components/proximity_auth/screenlock_bridge.cc
@@ -4,6 +4,9 @@
 
 #include "components/proximity_auth/screenlock_bridge.h"
 
+#include <utility>
+
+#include "base/memory/ptr_util.h"
 #include "base/strings/string16.h"
 #include "build/build_config.h"
 #include "components/proximity_auth/logging/logging.h"
@@ -63,15 +66,15 @@
 
 std::unique_ptr<base::DictionaryValue>
 ScreenlockBridge::UserPodCustomIconOptions::ToDictionaryValue() const {
-  std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
+  auto result = base::MakeUnique<base::DictionaryValue>();
   std::string icon_id = GetIdForIcon(icon_);
   result->SetString("id", icon_id);
 
   if (!tooltip_.empty()) {
-    base::DictionaryValue* tooltip_options = new base::DictionaryValue();
+    auto tooltip_options = base::MakeUnique<base::DictionaryValue>();
     tooltip_options->SetString("text", tooltip_);
     tooltip_options->SetBoolean("autoshow", autoshow_tooltip_);
-    result->Set("tooltip", tooltip_options);
+    result->Set("tooltip", std::move(tooltip_options));
   }
 
   if (!aria_label_.empty())
diff --git a/components/search_engines/default_search_manager_unittest.cc b/components/search_engines/default_search_manager_unittest.cc
index 5e72128e..8b2c54b 100644
--- a/components/search_engines/default_search_manager_unittest.cc
+++ b/components/search_engines/default_search_manager_unittest.cc
@@ -34,7 +34,7 @@
   prefs->SetUserPref(prefs::kSearchProviderOverridesVersion,
                      base::MakeUnique<base::Value>(1));
   auto overrides = base::MakeUnique<base::ListValue>();
-  std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
+  auto entry = base::MakeUnique<base::DictionaryValue>();
 
   entry->SetString("name", update ? "new_foo" : "foo");
   entry->SetString("keyword", update ? "new_fook" : "fook");
@@ -44,23 +44,23 @@
   entry->SetInteger("id", 1001);
   entry->SetString("suggest_url", "http://foo.com/suggest?q={searchTerms}");
   entry->SetString("instant_url", "http://foo.com/instant?q={searchTerms}");
-  base::ListValue* alternate_urls = new base::ListValue;
+  auto alternate_urls = base::MakeUnique<base::ListValue>();
   alternate_urls->AppendString("http://foo.com/alternate?q={searchTerms}");
-  entry->Set("alternate_urls", alternate_urls);
+  entry->Set("alternate_urls", std::move(alternate_urls));
   entry->SetString("search_terms_replacement_key", "espv");
-  overrides->Append(entry->CreateDeepCopy());
+  overrides->Append(std::move(entry));
 
-  entry.reset(new base::DictionaryValue);
+  entry = base::MakeUnique<base::DictionaryValue>();
   entry->SetInteger("id", 1002);
   entry->SetString("name", update ? "new_bar" : "bar");
   entry->SetString("keyword", update ? "new_bark" : "bark");
   entry->SetString("encoding", std::string());
-  overrides->Append(entry->CreateDeepCopy());
+  overrides->Append(base::MakeUnique<base::Value>(*entry));
   entry->SetInteger("id", 1003);
   entry->SetString("name", "baz");
   entry->SetString("keyword", "bazk");
   entry->SetString("encoding", "UTF-8");
-  overrides->Append(entry->CreateDeepCopy());
+  overrides->Append(std::move(entry));
   prefs->SetUserPref(prefs::kSearchProviderOverrides, std::move(overrides));
 }
 
diff --git a/components/search_engines/default_search_policy_handler.cc b/components/search_engines/default_search_policy_handler.cc
index 83a35651..295334d 100644
--- a/components/search_engines/default_search_policy_handler.cc
+++ b/components/search_engines/default_search_policy_handler.cc
@@ -36,7 +36,8 @@
     bool is_list = policy_value->GetAsList(&policy_list);
     DCHECK(is_list);
   }
-  dict->Set(key, policy_list ? policy_list->DeepCopy() : new base::ListValue());
+  dict->Set(key, policy_list ? base::MakeUnique<base::ListValue>(*policy_list)
+                             : base::MakeUnique<base::ListValue>());
 }
 
 // Extracts a string from a policy value and adds it to a pref dictionary.
diff --git a/components/search_engines/template_url_prepopulate_data_unittest.cc b/components/search_engines/template_url_prepopulate_data_unittest.cc
index 08c323e..75517f2 100644
--- a/components/search_engines/template_url_prepopulate_data_unittest.cc
+++ b/components/search_engines/template_url_prepopulate_data_unittest.cc
@@ -12,7 +12,9 @@
 #include "base/command_line.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
 #include "components/google/core/browser/google_switches.h"
 #include "components/search_engines/prepopulated_engines.h"
 #include "components/search_engines/search_engines_pref_names.h"
@@ -159,9 +161,9 @@
   // Test the optional settings too.
   entry->SetString("suggest_url", "http://foo.com/suggest?q={searchTerms}");
   entry->SetString("instant_url", "http://foo.com/instant?q={searchTerms}");
-  base::ListValue* alternate_urls = new base::ListValue;
+  auto alternate_urls = base::MakeUnique<base::ListValue>();
   alternate_urls->AppendString("http://foo.com/alternate?q={searchTerms}");
-  entry->Set("alternate_urls", alternate_urls);
+  entry->Set("alternate_urls", std::move(alternate_urls));
   entry->SetString("search_terms_replacement_key", "espv");
   overrides = base::MakeUnique<base::ListValue>();
   overrides->Append(entry->CreateDeepCopy());
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc
index da7be07..cdd9a4cf 100644
--- a/components/signin/core/browser/about_signin_internals.cc
+++ b/components/signin/core/browser/about_signin_internals.cc
@@ -42,11 +42,11 @@
 
 base::ListValue* AddSection(base::ListValue* parent_list,
                             const std::string& title) {
-  std::unique_ptr<base::DictionaryValue> section(new base::DictionaryValue());
-  base::ListValue* section_contents = new base::ListValue();
+  auto section = base::MakeUnique<base::DictionaryValue>();
 
   section->SetString("title", title);
-  section->Set("data", section_contents);
+  base::ListValue* section_contents =
+      section->SetList("data", base::MakeUnique<base::ListValue>());
   parent_list->Append(std::move(section));
   return section_contents;
 }
@@ -410,24 +410,21 @@
   if (error.state() != GoogleServiceAuthError::NONE)
     return;
 
-  base::DictionaryValue cookie_status;
-  base::ListValue* cookie_info = new base::ListValue();
-  cookie_status.Set("cookie_info", cookie_info);
+  auto cookie_info = base::MakeUnique<base::ListValue>();
 
   for (size_t i = 0; i < gaia_accounts.size(); ++i) {
-    AddCookieEntry(cookie_info,
-                   gaia_accounts[i].raw_email,
+    AddCookieEntry(cookie_info.get(), gaia_accounts[i].raw_email,
                    gaia_accounts[i].gaia_id,
                    gaia_accounts[i].valid ? "Valid" : "Invalid");
   }
 
   if (gaia_accounts.size() == 0) {
-    AddCookieEntry(cookie_info,
-                   "No Accounts Present.",
-                   std::string(),
+    AddCookieEntry(cookie_info.get(), "No Accounts Present.", std::string(),
                    std::string());
   }
 
+  base::DictionaryValue cookie_status;
+  cookie_status.Set("cookie_info", std::move(cookie_info));
   // Update the observers that the cookie's accounts are updated.
   for (auto& observer : signin_observers_)
     observer.OnCookieAccountsFetched(&cookie_status);
@@ -529,13 +526,12 @@
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
           "422460 AboutSigninInternals::SigninStatus::ToValue1"));
 
-  std::unique_ptr<base::DictionaryValue> signin_status(
-      new base::DictionaryValue());
-  base::ListValue* signin_info = new base::ListValue();
-  signin_status->Set("signin_info", signin_info);
+  auto signin_status = base::MakeUnique<base::DictionaryValue>();
+  auto signin_info = base::MakeUnique<base::ListValue>();
 
   // A summary of signin related info first.
-  base::ListValue* basic_info = AddSection(signin_info, "Basic Information");
+  base::ListValue* basic_info =
+      AddSection(signin_info.get(), "Basic Information");
   AddSectionEntry(basic_info, "Chrome Version", product_version);
   AddSectionEntry(basic_info, "Account Consistency?",
       switches::IsEnableAccountConsistency() == true ? "On" : "Off");
@@ -589,7 +585,8 @@
 
   // Time and status information of the possible sign in types.
   base::ListValue* detailed_info =
-      AddSection(signin_info, "Last Signin Details");
+      AddSection(signin_info.get(), "Last Signin Details");
+  signin_status->Set("signin_info", std::move(signin_info));
   for (int i = TIMED_FIELDS_BEGIN; i < TIMED_FIELDS_END; ++i) {
     const std::string status_field_label =
         SigninStatusFieldToLabel(static_cast<TimedSigninStatusField>(i));
@@ -644,8 +641,7 @@
           "422460 AboutSigninInternals::SigninStatus::ToValue4"));
 
   // Token information for all services.
-  base::ListValue* token_info = new base::ListValue();
-  signin_status->Set("token_info", token_info);
+  auto token_info = base::MakeUnique<base::ListValue>();
   for (auto it = token_info_map.begin(); it != token_info_map.end(); ++it) {
     // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460
     // is fixed.
@@ -653,7 +649,7 @@
         FROM_HERE_WITH_EXPLICIT_FUNCTION(
             "422460 AboutSigninInternals::SigninStatus::ToValue41"));
 
-    base::ListValue* token_details = AddSection(token_info, it->first);
+    base::ListValue* token_details = AddSection(token_info.get(), it->first);
 
     // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460
     // is fixed.
@@ -674,24 +670,24 @@
       token_details->Append(token->ToValue());
     }
   }
+  signin_status->Set("token_info", std::move(token_info));
 
-  base::ListValue* account_info = new base::ListValue();
-  signin_status->Set("accountInfo", account_info);
+  auto account_info = base::MakeUnique<base::ListValue>();
   const std::vector<std::string>& accounts_in_token_service =
       token_service->GetAccounts();
 
-  if(accounts_in_token_service.size() == 0) {
-    std::unique_ptr<base::DictionaryValue> no_token_entry(
-        new base::DictionaryValue());
+  if (accounts_in_token_service.size() == 0) {
+    auto no_token_entry = base::MakeUnique<base::DictionaryValue>();
     no_token_entry->SetString("accountId", "No token in Token Service.");
     account_info->Append(std::move(no_token_entry));
   }
 
-  for(const std::string& account_id : accounts_in_token_service) {
-    std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue());
+  for (const std::string& account_id : accounts_in_token_service) {
+    auto entry = base::MakeUnique<base::DictionaryValue>();
     entry->SetString("accountId", account_id);
     account_info->Append(std::move(entry));
   }
 
+  signin_status->Set("accountInfo", std::move(account_info));
   return signin_status;
 }
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h
index eb83653..1d84ced 100644
--- a/components/sync/base/model_type.h
+++ b/components/sync/base/model_type.h
@@ -285,9 +285,7 @@
 int ModelTypeToHistogramInt(ModelType model_type);
 
 // Handles all model types, and not just real ones.
-//
-// Caller takes ownership of returned value.
-base::Value* ModelTypeToValue(ModelType model_type);
+std::unique_ptr<base::Value> ModelTypeToValue(ModelType model_type);
 
 // Converts a Value into a ModelType - complement to ModelTypeToValue().
 ModelType ModelTypeFromValue(const base::Value& value);
diff --git a/components/sync/driver/about_sync_util.cc b/components/sync/driver/about_sync_util.cc
index 054ef74..366affcc 100644
--- a/components/sync/driver/about_sync_util.cc
+++ b/components/sync/driver/about_sync_util.cc
@@ -77,10 +77,10 @@
 // |parent_list|, not the caller, owns the newly added section.
 base::ListValue* AddSection(base::ListValue* parent_list,
                             const std::string& title) {
-  std::unique_ptr<base::DictionaryValue> section(new base::DictionaryValue());
-  base::ListValue* section_contents = new base::ListValue();
+  auto section = base::MakeUnique<base::DictionaryValue>();
   section->SetString("title", title);
-  section->Set("data", section_contents);
+  base::ListValue* section_contents =
+      section->SetList("data", base::MakeUnique<base::ListValue>());
   section->SetBoolean("is_sensitive", false);
   // If the following |Append| results in a reallocation, pointers to the
   // members of |parent_list| will be invalidated. This would result in
@@ -96,10 +96,10 @@
 // form and posted in a public forum (e.g. unique identifiers).
 base::ListValue* AddSensitiveSection(base::ListValue* parent_list,
                                      const std::string& title) {
-  std::unique_ptr<base::DictionaryValue> section(new base::DictionaryValue());
-  base::ListValue* section_contents = new base::ListValue();
+  auto section = base::MakeUnique<base::DictionaryValue>();
   section->SetString("title", title);
-  section->Set("data", section_contents);
+  base::ListValue* section_contents =
+      section->SetList("data", base::MakeUnique<base::ListValue>());
   section->SetBoolean("is_sensitive", true);
   // If the following |Append| results in a reallocation, pointers to
   // |parent_list| and its members will be invalidated. This would result in
@@ -284,37 +284,38 @@
 std::unique_ptr<base::DictionaryValue> ConstructAboutInformation(
     SyncService* service,
     version_info::Channel channel) {
-  std::unique_ptr<base::DictionaryValue> about_info(
-      new base::DictionaryValue());
+  auto about_info = base::MakeUnique<base::DictionaryValue>();
 
   // 'details': A list of sections.
-  base::ListValue* stats_list = new base::ListValue();
+  auto stats_list = base::MakeUnique<base::ListValue>();
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   stats_list->Reserve(12);
 
   // The following lines define the sections and their fields.  For each field,
   // a class is instantiated, which allows us to reference the fields in
   // 'setter' code later on in this function.
-  base::ListValue* section_summary = AddSection(stats_list, "Summary");
+  base::ListValue* section_summary = AddSection(stats_list.get(), "Summary");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_summary->Reserve(1);
   StringSyncStat summary_string(section_summary, "Summary");
 
-  base::ListValue* section_version = AddSection(stats_list, "Version Info");
+  base::ListValue* section_version =
+      AddSection(stats_list.get(), "Version Info");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_version->Reserve(2);
   StringSyncStat client_version(section_version, "Client Version");
   StringSyncStat server_url(section_version, "Server URL");
 
   base::ListValue* section_identity =
-      AddSensitiveSection(stats_list, kIdentityTitle);
+      AddSensitiveSection(stats_list.get(), kIdentityTitle);
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_identity->Reserve(3);
   StringSyncStat sync_id(section_identity, "Sync Client ID");
   StringSyncStat invalidator_id(section_identity, "Invalidator Client ID");
   StringSyncStat username(section_identity, "Username");
 
-  base::ListValue* section_credentials = AddSection(stats_list, "Credentials");
+  base::ListValue* section_credentials =
+      AddSection(stats_list.get(), "Credentials");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_credentials->Reserve(4);
   StringSyncStat request_token_time(section_credentials, "Requested Token");
@@ -323,7 +324,7 @@
                                       "Token Request Status");
   StringSyncStat next_token_request(section_credentials, "Next Token Request");
 
-  base::ListValue* section_local = AddSection(stats_list, "Local State");
+  base::ListValue* section_local = AddSection(stats_list.get(), "Local State");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_local->Reserve(7);
   StringSyncStat server_connection(section_local, "Server Connection");
@@ -337,7 +338,7 @@
                                      "Local sync backend enabled");
   StringSyncStat local_backend_path(section_local, "Local backend path");
 
-  base::ListValue* section_network = AddSection(stats_list, "Network");
+  base::ListValue* section_network = AddSection(stats_list.get(), "Network");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_network->Reserve(3);
   BoolSyncStat is_throttled(section_network, "Throttled");
@@ -345,7 +346,8 @@
   BoolSyncStat are_notifications_enabled(section_network,
                                          "Notifications Enabled");
 
-  base::ListValue* section_encryption = AddSection(stats_list, "Encryption");
+  base::ListValue* section_encryption =
+      AddSection(stats_list.get(), "Encryption");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_encryption->Reserve(9);
   BoolSyncStat is_using_explicit_passphrase(section_encryption,
@@ -364,7 +366,7 @@
   StringSyncStat passphrase_time(section_encryption, "Passphrase Time");
 
   base::ListValue* section_last_session =
-      AddSection(stats_list, "Status from Last Completed Session");
+      AddSection(stats_list.get(), "Status from Last Completed Session");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_last_session->Reserve(4);
   StringSyncStat session_source(section_last_session, "Sync Source");
@@ -372,7 +374,8 @@
   StringSyncStat download_result(section_last_session, "Download Step Result");
   StringSyncStat commit_result(section_last_session, "Commit Step Result");
 
-  base::ListValue* section_counters = AddSection(stats_list, "Running Totals");
+  base::ListValue* section_counters =
+      AddSection(stats_list.get(), "Running Totals");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_counters->Reserve(7);
   IntSyncStat notifications_received(section_counters,
@@ -387,7 +390,7 @@
                                              "Conflicts Resolved: Server Wins");
 
   base::ListValue* section_this_cycle =
-      AddSection(stats_list, "Transient Counters (this cycle)");
+      AddSection(stats_list.get(), "Transient Counters (this cycle)");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_this_cycle->Reserve(4);
   IntSyncStat encryption_conflicts(section_this_cycle, "Encryption Conflicts");
@@ -395,8 +398,9 @@
   IntSyncStat server_conflicts(section_this_cycle, "Server Conflicts");
   IntSyncStat committed_items(section_this_cycle, "Committed Items");
 
-  base::ListValue* section_that_cycle = AddSection(
-      stats_list, "Transient Counters (last cycle of last completed session)");
+  base::ListValue* section_that_cycle =
+      AddSection(stats_list.get(),
+                 "Transient Counters (last cycle of last completed session)");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_that_cycle->Reserve(3);
   IntSyncStat updates_downloaded(section_that_cycle, "Updates Downloaded");
@@ -404,7 +408,7 @@
   IntSyncStat entries(section_that_cycle, "Entries");
 
   base::ListValue* section_nudge_info =
-      AddSection(stats_list, "Nudge Source Counters");
+      AddSection(stats_list.get(), "Nudge Source Counters");
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   section_nudge_info->Reserve(3);
   IntSyncStat nudge_source_notification(section_nudge_info,
@@ -414,7 +418,7 @@
 
   // This list of sections belongs in the 'details' field of the returned
   // message.
-  about_info->Set(kDetailsKey, stats_list);
+  about_info->Set(kDetailsKey, std::move(stats_list));
 
   // Populate all the fields we declared above.
   client_version.SetValue(GetVersionString(channel));
@@ -554,15 +558,15 @@
   // NOTE: We won't bother showing any of the following values unless
   // actionable_error_detected is set.
 
-  base::ListValue* actionable_error = new base::ListValue();
+  auto actionable_error = base::MakeUnique<base::ListValue>();
   // TODO(crbug.com/702230): Remove the usages of raw pointers in this file.
   actionable_error->Reserve(4);
-  about_info->Set("actionable_error", actionable_error);
 
-  StringSyncStat error_type(actionable_error, "Error Type");
-  StringSyncStat action(actionable_error, "Action");
-  StringSyncStat url(actionable_error, "URL");
-  StringSyncStat description(actionable_error, "Error Description");
+  StringSyncStat error_type(actionable_error.get(), "Error Type");
+  StringSyncStat action(actionable_error.get(), "Action");
+  StringSyncStat url(actionable_error.get(), "URL");
+  StringSyncStat description(actionable_error.get(), "Error Description");
+  about_info->Set("actionable_error", std::move(actionable_error));
 
   if (actionable_error_detected) {
     error_type.SetValue(
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot.cc b/components/sync/engine/cycle/sync_cycle_snapshot.cc
index 765e120..fab6c65 100644
--- a/components/sync/engine/cycle/sync_cycle_snapshot.cc
+++ b/components/sync/engine/cycle/sync_cycle_snapshot.cc
@@ -95,7 +95,7 @@
                              num_to_delete_entries_by_type_[i]);
 
     const std::string model_type = ModelTypeToString(static_cast<ModelType>(i));
-    counter_entries->Set(model_type, type_entries.release());
+    counter_entries->Set(model_type, std::move(type_entries));
   }
   value->Set("counter_entries", std::move(counter_entries));
   return value;
diff --git a/components/sync/engine/events/protocol_event.cc b/components/sync/engine/events/protocol_event.cc
index 629b2bb..ec29379 100644
--- a/components/sync/engine/events/protocol_event.cc
+++ b/components/sync/engine/events/protocol_event.cc
@@ -4,8 +4,6 @@
 
 #include "components/sync/engine/events/protocol_event.h"
 
-#include <utility>
-
 #include "base/memory/ptr_util.h"
 
 namespace syncer {
diff --git a/components/sync/engine_impl/js_mutation_event_observer.cc b/components/sync/engine_impl/js_mutation_event_observer.cc
index 7b174482..9dfce05 100644
--- a/components/sync/engine_impl/js_mutation_event_observer.cc
+++ b/components/sync/engine_impl/js_mutation_event_observer.cc
@@ -5,9 +5,11 @@
 #include "components/sync/engine_impl/js_mutation_event_observer.h"
 
 #include <stddef.h>
+#include <utility>
 
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "components/sync/js/js_event_details.h"
@@ -53,20 +55,20 @@
   details.SetString("modelType", ModelTypeToString(model_type));
   details.SetString("writeTransactionId",
                     base::Int64ToString(write_transaction_id));
-  base::Value* changes_value = nullptr;
+  std::unique_ptr<base::Value> changes_value;
   const size_t changes_size = changes.Get().size();
   if (changes_size <= kChangeLimit) {
-    base::ListValue* changes_list = new base::ListValue();
+    auto changes_list = base::MakeUnique<base::ListValue>();
     for (ChangeRecordList::const_iterator it = changes.Get().begin();
          it != changes.Get().end(); ++it) {
       changes_list->Append(it->ToValue());
     }
-    changes_value = changes_list;
+    changes_value = std::move(changes_list);
   } else {
-    changes_value =
-        new base::Value(base::SizeTToString(changes_size) + " changes");
+    changes_value = base::MakeUnique<base::Value>(
+        base::SizeTToString(changes_size) + " changes");
   }
-  details.Set("changes", changes_value);
+  details.Set("changes", std::move(changes_value));
   HandleJsEvent(FROM_HERE, "onChangesApplied", JsEventDetails(&details));
 }
 
diff --git a/components/sync/engine_impl/js_mutation_event_observer_unittest.cc b/components/sync/engine_impl/js_mutation_event_observer_unittest.cc
index 1a8da57..cffd892 100644
--- a/components/sync/engine_impl/js_mutation_event_observer_unittest.cc
+++ b/components/sync/engine_impl/js_mutation_event_observer_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "components/sync/engine_impl/js_mutation_event_observer.h"
 
+#include <utility>
+
+#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/values.h"
@@ -69,11 +72,11 @@
     base::DictionaryValue expected_details;
     expected_details.SetString("modelType", model_type_str);
     expected_details.SetString("writeTransactionId", "0");
-    base::ListValue* expected_changes = new base::ListValue();
-    expected_details.Set("changes", expected_changes);
+    auto expected_changes = base::MakeUnique<base::ListValue>();
     for (int j = i; j < MODEL_TYPE_COUNT; ++j) {
       expected_changes->Append(changes[j].ToValue());
     }
+    expected_details.Set("changes", std::move(expected_changes));
     EXPECT_CALL(mock_js_event_handler_,
                 HandleJsEvent("onChangesApplied",
                               HasDetailsAsDictionary(expected_details)));
diff --git a/components/sync/engine_impl/js_sync_encryption_handler_observer_unittest.cc b/components/sync/engine_impl/js_sync_encryption_handler_observer_unittest.cc
index 8ce7f06..05b6013 100644
--- a/components/sync/engine_impl/js_sync_encryption_handler_observer_unittest.cc
+++ b/components/sync/engine_impl/js_sync_encryption_handler_observer_unittest.cc
@@ -4,7 +4,10 @@
 
 #include "components/sync/engine_impl/js_sync_encryption_handler_observer.h"
 
+#include <utility>
+
 #include "base/location.h"
+#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/values.h"
@@ -104,11 +107,7 @@
 }
 
 TEST_F(JsSyncEncryptionHandlerObserverTest, OnEncryptedTypesChanged) {
-  base::DictionaryValue expected_details;
-  base::ListValue* encrypted_type_values = new base::ListValue();
-  const bool encrypt_everything = false;
-  expected_details.Set("encryptedTypes", encrypted_type_values);
-  expected_details.SetBoolean("encryptEverything", encrypt_everything);
+  auto encrypted_type_values = base::MakeUnique<base::ListValue>();
   ModelTypeSet encrypted_types;
 
   for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
@@ -117,12 +116,17 @@
     encrypted_type_values->AppendString(ModelTypeToString(type));
   }
 
+  base::DictionaryValue expected_details;
+  const bool kEncrytEverything = false;
+  expected_details.Set("encryptedTypes", std::move(encrypted_type_values));
+  expected_details.SetBoolean("encryptEverything", kEncrytEverything);
+
   EXPECT_CALL(mock_js_event_handler_,
               HandleJsEvent("onEncryptedTypesChanged",
                             HasDetailsAsDictionary(expected_details)));
 
   js_sync_encryption_handler_observer_.OnEncryptedTypesChanged(
-      encrypted_types, encrypt_everything);
+      encrypted_types, kEncrytEverything);
   PumpLoop();
 }
 
diff --git a/components/sync/js/js_event_details_unittest.cc b/components/sync/js/js_event_details_unittest.cc
index 4b56e7d..d20cd0d 100644
--- a/components/sync/js/js_event_details_unittest.cc
+++ b/components/sync/js/js_event_details_unittest.cc
@@ -5,7 +5,10 @@
 #include "components/sync/js/js_event_details.h"
 
 #include <memory>
+#include <utility>
 
+#include "base/memory/ptr_util.h"
+#include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace syncer {
@@ -22,9 +25,9 @@
 TEST_F(JsEventDetailsTest, FromDictionary) {
   base::DictionaryValue dict;
   dict.SetString("foo", "bar");
-  dict.Set("baz", new base::ListValue());
+  dict.Set("baz", base::MakeUnique<base::ListValue>());
 
-  std::unique_ptr<base::DictionaryValue> dict_copy(dict.DeepCopy());
+  auto dict_copy = base::MakeUnique<base::DictionaryValue>(dict);
 
   JsEventDetails details(&dict);
 
diff --git a/components/sync/protocol/sync_protocol_error.cc b/components/sync/protocol/sync_protocol_error.cc
index 01fd3b0..1f1ff0d 100644
--- a/components/sync/protocol/sync_protocol_error.cc
+++ b/components/sync/protocol/sync_protocol_error.cc
@@ -4,7 +4,10 @@
 
 #include "components/sync/protocol/sync_protocol_error.h"
 
+#include <utility>
+
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 
 namespace syncer {
 #define ENUM_CASE(x) \
@@ -52,8 +55,8 @@
 
 SyncProtocolError::~SyncProtocolError() {}
 
-base::DictionaryValue* SyncProtocolError::ToValue() const {
-  base::DictionaryValue* value = new base::DictionaryValue();
+std::unique_ptr<base::DictionaryValue> SyncProtocolError::ToValue() const {
+  auto value = base::MakeUnique<base::DictionaryValue>();
   value->SetString("ErrorType", GetSyncErrorTypeString(error_type));
   value->SetString("ErrorDescription", error_description);
   value->SetString("url", url);
diff --git a/components/sync/protocol/sync_protocol_error.h b/components/sync/protocol/sync_protocol_error.h
index cfb1edf..c76efb1c 100644
--- a/components/sync/protocol/sync_protocol_error.h
+++ b/components/sync/protocol/sync_protocol_error.h
@@ -4,6 +4,7 @@
 #ifndef COMPONENTS_SYNC_PROTOCOL_SYNC_PROTOCOL_ERROR_H_
 #define COMPONENTS_SYNC_PROTOCOL_SYNC_PROTOCOL_ERROR_H_
 
+#include <memory>
 #include <string>
 
 #include "base/values.h"
@@ -88,7 +89,7 @@
   SyncProtocolError();
   SyncProtocolError(const SyncProtocolError& other);
   ~SyncProtocolError();
-  base::DictionaryValue* ToValue() const;
+  std::unique_ptr<base::DictionaryValue> ToValue() const;
 };
 
 const char* GetSyncErrorTypeString(SyncProtocolErrorType type);
diff --git a/components/sync/syncable/base_node.cc b/components/sync/syncable/base_node.cc
index 58096c3..9e64f49 100644
--- a/components/sync/syncable/base_node.cc
+++ b/components/sync/syncable/base_node.cc
@@ -217,7 +217,7 @@
   return GetEntry()->GetPositionIndex();
 }
 
-base::DictionaryValue* BaseNode::ToValue() const {
+std::unique_ptr<base::DictionaryValue> BaseNode::ToValue() const {
   return GetEntry()->ToValue(GetTransaction()->GetCryptographer());
 }
 
diff --git a/components/sync/syncable/base_node.h b/components/sync/syncable/base_node.h
index 7e7c8ecd..ac53ace 100644
--- a/components/sync/syncable/base_node.h
+++ b/components/sync/syncable/base_node.h
@@ -171,7 +171,7 @@
   const AttachmentIdList GetAttachmentIds() const;
 
   // Returns a base::DictionaryValue serialization of this node.
-  base::DictionaryValue* ToValue() const;
+  std::unique_ptr<base::DictionaryValue> ToValue() const;
 
  protected:
   BaseNode();
diff --git a/components/sync/syncable/entry.cc b/components/sync/syncable/entry.cc
index cd1a78f..8b36c5d 100644
--- a/components/sync/syncable/entry.cc
+++ b/components/sync/syncable/entry.cc
@@ -6,6 +6,8 @@
 
 #include <iomanip>
 
+#include "base/memory/ptr_util.h"
+#include "base/values.h"
 #include "components/sync/syncable/directory.h"
 #include "components/sync/syncable/syncable_base_transaction.h"
 
@@ -42,8 +44,9 @@
   return basetrans_->directory();
 }
 
-base::DictionaryValue* Entry::ToValue(Cryptographer* cryptographer) const {
-  base::DictionaryValue* entry_info = new base::DictionaryValue();
+std::unique_ptr<base::DictionaryValue> Entry::ToValue(
+    Cryptographer* cryptographer) const {
+  auto entry_info = base::MakeUnique<base::DictionaryValue>();
   entry_info->SetBoolean("good", good());
   if (good()) {
     entry_info->Set("kernel", kernel_->ToValue(cryptographer));
diff --git a/components/sync/syncable/entry.h b/components/sync/syncable/entry.h
index 77a80c8..7669eba 100644
--- a/components/sync/syncable/entry.h
+++ b/components/sync/syncable/entry.h
@@ -8,10 +8,12 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 #include <vector>
 
 #include "base/macros.h"
+#include "base/values.h"
 #include "components/sync/syncable/entry_kernel.h"
 
 namespace syncer {
@@ -256,8 +258,8 @@
   const EntryKernel GetKernelCopy() const { return *kernel_; }
 
   // Dumps all entry info into a DictionaryValue and returns it.
-  // Transfers ownership of the DictionaryValue to the caller.
-  base::DictionaryValue* ToValue(Cryptographer* cryptographer) const;
+  std::unique_ptr<base::DictionaryValue> ToValue(
+      Cryptographer* cryptographer) const;
 
  protected:  // Don't allow creation on heap, except by sync API wrappers.
   void* operator new(size_t size) { return (::operator new)(size); }
diff --git a/components/sync/syncable/entry_kernel.cc b/components/sync/syncable/entry_kernel.cc
index 383d04c..ee8bab4 100644
--- a/components/sync/syncable/entry_kernel.cc
+++ b/components/sync/syncable/entry_kernel.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/json/string_escape.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/trace_event/memory_usage_estimator.h"
 #include "components/sync/base/cryptographer.h"
@@ -82,15 +83,15 @@
 void SetFieldValues(const EntryKernel& kernel,
                     base::DictionaryValue* dictionary_value,
                     const char* (*enum_key_fn)(T),
-                    V* (*enum_value_fn)(U),
+                    std::unique_ptr<V> (*enum_value_fn)(U),
                     int field_key_min,
                     int field_key_max) {
   DCHECK_LE(field_key_min, field_key_max);
   for (int i = field_key_min; i <= field_key_max; ++i) {
     T field = static_cast<T>(i);
     const std::string& key = enum_key_fn(field);
-    V* value = enum_value_fn(kernel.ref(field));
-    dictionary_value->Set(key, value);
+    std::unique_ptr<V> value = enum_value_fn(kernel.ref(field));
+    dictionary_value->Set(key, std::move(value));
   }
 }
 
@@ -121,32 +122,33 @@
 
 // Helper functions for SetFieldValues().
 
-base::Value* Int64ToValue(int64_t i) {
-  return new base::Value(base::Int64ToString(i));
+std::unique_ptr<base::Value> Int64ToValue(int64_t i) {
+  return base::MakeUnique<base::Value>(base::Int64ToString(i));
 }
 
-base::Value* TimeToValue(const base::Time& t) {
-  return new base::Value(GetTimeDebugString(t));
+std::unique_ptr<base::Value> TimeToValue(const base::Time& t) {
+  return base::MakeUnique<base::Value>(GetTimeDebugString(t));
 }
 
-base::Value* IdToValue(const Id& id) {
+std::unique_ptr<base::Value> IdToValue(const Id& id) {
   return id.ToValue();
 }
 
-base::Value* BooleanToValue(bool bool_val) {
-  return new base::Value(bool_val);
+std::unique_ptr<base::Value> BooleanToValue(bool bool_val) {
+  return base::MakeUnique<base::Value>(bool_val);
 }
 
-base::Value* StringToValue(const std::string& str) {
-  return new base::Value(str);
+std::unique_ptr<base::Value> StringToValue(const std::string& str) {
+  return base::MakeUnique<base::Value>(str);
 }
 
-base::Value* UniquePositionToValue(const UniquePosition& pos) {
-  return new base::Value(pos.ToDebugString());
+std::unique_ptr<base::Value> UniquePositionToValue(const UniquePosition& pos) {
+  return base::MakeUnique<base::Value>(pos.ToDebugString());
 }
 
-base::Value* AttachmentMetadataToValue(const sync_pb::AttachmentMetadata& a) {
-  return new base::Value(a.SerializeAsString());
+std::unique_ptr<base::Value> AttachmentMetadataToValue(
+    const sync_pb::AttachmentMetadata& a) {
+  return base::MakeUnique<base::Value>(a.SerializeAsString());
 }
 
 // Estimates memory usage of ProtoValuePtr<T> arrays where consecutive
@@ -166,9 +168,9 @@
 
 }  // namespace
 
-base::DictionaryValue* EntryKernel::ToValue(
+std::unique_ptr<base::DictionaryValue> EntryKernel::ToValue(
     Cryptographer* cryptographer) const {
-  base::DictionaryValue* kernel_info = new base::DictionaryValue();
+  auto kernel_info = base::MakeUnique<base::DictionaryValue>();
   kernel_info->SetBoolean("isDirty", is_dirty());
   ModelType dataType = GetServerModelType();
   if (!IsRealDataType(dataType))
@@ -176,52 +178,52 @@
   kernel_info->Set("modelType", ModelTypeToValue(dataType));
 
   // Int64 fields.
-  SetFieldValues(*this, kernel_info, &GetMetahandleFieldString, &Int64ToValue,
-                 INT64_FIELDS_BEGIN, META_HANDLE);
-  SetFieldValues(*this, kernel_info, &GetBaseVersionString, &Int64ToValue,
+  SetFieldValues(*this, kernel_info.get(), &GetMetahandleFieldString,
+                 &Int64ToValue, INT64_FIELDS_BEGIN, META_HANDLE);
+  SetFieldValues(*this, kernel_info.get(), &GetBaseVersionString, &Int64ToValue,
                  META_HANDLE + 1, BASE_VERSION);
-  SetFieldValues(*this, kernel_info, &GetInt64FieldString, &Int64ToValue,
+  SetFieldValues(*this, kernel_info.get(), &GetInt64FieldString, &Int64ToValue,
                  BASE_VERSION + 1, INT64_FIELDS_END - 1);
 
   // Time fields.
-  SetFieldValues(*this, kernel_info, &GetTimeFieldString, &TimeToValue,
+  SetFieldValues(*this, kernel_info.get(), &GetTimeFieldString, &TimeToValue,
                  TIME_FIELDS_BEGIN, TIME_FIELDS_END - 1);
 
   // ID fields.
-  SetFieldValues(*this, kernel_info, &GetIdFieldString, &IdToValue,
+  SetFieldValues(*this, kernel_info.get(), &GetIdFieldString, &IdToValue,
                  ID_FIELDS_BEGIN, ID_FIELDS_END - 1);
 
   // Bit fields.
-  SetFieldValues(*this, kernel_info, &GetIndexedBitFieldString, &BooleanToValue,
-                 BIT_FIELDS_BEGIN, INDEXED_BIT_FIELDS_END - 1);
-  SetFieldValues(*this, kernel_info, &GetIsDelFieldString, &BooleanToValue,
-                 INDEXED_BIT_FIELDS_END, IS_DEL);
-  SetFieldValues(*this, kernel_info, &GetBitFieldString, &BooleanToValue,
+  SetFieldValues(*this, kernel_info.get(), &GetIndexedBitFieldString,
+                 &BooleanToValue, BIT_FIELDS_BEGIN, INDEXED_BIT_FIELDS_END - 1);
+  SetFieldValues(*this, kernel_info.get(), &GetIsDelFieldString,
+                 &BooleanToValue, INDEXED_BIT_FIELDS_END, IS_DEL);
+  SetFieldValues(*this, kernel_info.get(), &GetBitFieldString, &BooleanToValue,
                  IS_DEL + 1, BIT_FIELDS_END - 1);
 
   // String fields.
   {
     // Pick out the function overload we want.
-    SetFieldValues(*this, kernel_info, &GetStringFieldString, &StringToValue,
-                   STRING_FIELDS_BEGIN, STRING_FIELDS_END - 1);
+    SetFieldValues(*this, kernel_info.get(), &GetStringFieldString,
+                   &StringToValue, STRING_FIELDS_BEGIN, STRING_FIELDS_END - 1);
   }
 
   // Proto fields.
-  SetEncryptableProtoValues(*this, cryptographer, kernel_info,
+  SetEncryptableProtoValues(*this, cryptographer, kernel_info.get(),
                             PROTO_FIELDS_BEGIN, PROTO_FIELDS_END - 1);
 
   // UniquePosition fields
-  SetFieldValues(*this, kernel_info, &GetUniquePositionFieldString,
+  SetFieldValues(*this, kernel_info.get(), &GetUniquePositionFieldString,
                  &UniquePositionToValue, UNIQUE_POSITION_FIELDS_BEGIN,
                  UNIQUE_POSITION_FIELDS_END - 1);
 
   // AttachmentMetadata fields
-  SetFieldValues(*this, kernel_info, &GetAttachmentMetadataFieldString,
+  SetFieldValues(*this, kernel_info.get(), &GetAttachmentMetadataFieldString,
                  &AttachmentMetadataToValue, ATTACHMENT_METADATA_FIELDS_BEGIN,
                  ATTACHMENT_METADATA_FIELDS_END - 1);
 
   // Bit temps.
-  SetFieldValues(*this, kernel_info, &GetBitTempString, &BooleanToValue,
+  SetFieldValues(*this, kernel_info.get(), &GetBitTempString, &BooleanToValue,
                  BIT_TEMPS_BEGIN, BIT_TEMPS_END - 1);
 
   return kernel_info;
@@ -251,7 +253,7 @@
 
 std::unique_ptr<base::DictionaryValue> EntryKernelMutationToValue(
     const EntryKernelMutation& mutation) {
-  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+  auto dict = base::MakeUnique<base::DictionaryValue>();
   dict->Set("original", mutation.original.ToValue(nullptr));
   dict->Set("mutated", mutation.mutated.ToValue(nullptr));
   return dict;
diff --git a/components/sync/syncable/entry_kernel.h b/components/sync/syncable/entry_kernel.h
index 2be38b6..fa57de9 100644
--- a/components/sync/syncable/entry_kernel.h
+++ b/components/sync/syncable/entry_kernel.h
@@ -372,11 +372,11 @@
   bool ShouldMaintainHierarchy() const;
 
   // Dumps all kernel info into a DictionaryValue and returns it.
-  // Transfers ownership of the DictionaryValue to the caller.
   // Note: |cryptographer| is an optional parameter for use in decrypting
   // encrypted specifics. If it is null or the specifics are not decryptsble,
   // they will be serialized as empty proto's.
-  base::DictionaryValue* ToValue(Cryptographer* cryptographer) const;
+  std::unique_ptr<base::DictionaryValue> ToValue(
+      Cryptographer* cryptographer) const;
 
   size_t EstimateMemoryUsage() const;
 
diff --git a/components/sync/syncable/model_type.cc b/components/sync/syncable/model_type.cc
index e1f4d49d..20094c7b 100644
--- a/components/sync/syncable/model_type.cc
+++ b/components/sync/syncable/model_type.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_split.h"
 #include "base/values.h"
 #include "components/reading_list/core/reading_list_enable_flags.h"
@@ -562,16 +563,16 @@
   return 0;
 }
 
-base::Value* ModelTypeToValue(ModelType model_type) {
+std::unique_ptr<base::Value> ModelTypeToValue(ModelType model_type) {
   if (model_type >= FIRST_REAL_MODEL_TYPE) {
-    return new base::Value(ModelTypeToString(model_type));
+    return base::MakeUnique<base::Value>(ModelTypeToString(model_type));
   } else if (model_type == TOP_LEVEL_FOLDER) {
-    return new base::Value("Top-level folder");
+    return base::MakeUnique<base::Value>("Top-level folder");
   } else if (model_type == UNSPECIFIED) {
-    return new base::Value("Unspecified");
+    return base::MakeUnique<base::Value>("Unspecified");
   }
   NOTREACHED();
-  return new base::Value(std::string());
+  return base::MakeUnique<base::Value>(std::string());
 }
 
 ModelType ModelTypeFromValue(const base::Value& value) {
diff --git a/components/sync/syncable/model_type_unittest.cc b/components/sync/syncable/model_type_unittest.cc
index 701f4d3..f2a6bb9 100644
--- a/components/sync/syncable/model_type_unittest.cc
+++ b/components/sync/syncable/model_type_unittest.cc
@@ -21,11 +21,11 @@
   for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
     ModelType model_type = ModelTypeFromInt(i);
     base::ExpectStringValue(ModelTypeToString(model_type),
-                            ModelTypeToValue(model_type));
+                            *ModelTypeToValue(model_type));
   }
   base::ExpectStringValue("Top-level folder",
-                          ModelTypeToValue(TOP_LEVEL_FOLDER));
-  base::ExpectStringValue("Unspecified", ModelTypeToValue(UNSPECIFIED));
+                          *ModelTypeToValue(TOP_LEVEL_FOLDER));
+  base::ExpectStringValue("Unspecified", *ModelTypeToValue(UNSPECIFIED));
 }
 
 TEST_F(ModelTypeTest, ModelTypeFromValue) {
diff --git a/components/sync/syncable/syncable_id.cc b/components/sync/syncable/syncable_id.cc
index 24d8dfd..14c7e58 100644
--- a/components/sync/syncable/syncable_id.cc
+++ b/components/sync/syncable/syncable_id.cc
@@ -5,6 +5,7 @@
 #include "components/sync/syncable/syncable_id.h"
 
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/values.h"
 
 using std::ostream;
@@ -18,8 +19,8 @@
   return out;
 }
 
-base::Value* Id::ToValue() const {
-  return new base::Value(s_);
+std::unique_ptr<base::Value> Id::ToValue() const {
+  return base::MakeUnique<base::Value>(s_);
 }
 
 string Id::GetServerId() const {
diff --git a/components/sync/syncable/syncable_id.h b/components/sync/syncable/syncable_id.h
index 100244b..67cf909 100644
--- a/components/sync/syncable/syncable_id.h
+++ b/components/sync/syncable/syncable_id.h
@@ -69,9 +69,8 @@
   // by operator<.
   Id GetLexicographicSuccessor() const;
 
-  // Dumps the ID as a value and returns it.  Transfers ownership of
-  // the StringValue to the caller.
-  base::Value* ToValue() const;
+  // Dumps the ID as a value and returns it.
+  std::unique_ptr<base::Value> ToValue() const;
 
   // Three functions are used to work with our proto buffers.
   std::string GetServerId() const;
diff --git a/components/sync/syncable/syncable_id_unittest.cc b/components/sync/syncable/syncable_id_unittest.cc
index c537db5..c291674 100644
--- a/components/sync/syncable/syncable_id_unittest.cc
+++ b/components/sync/syncable/syncable_id_unittest.cc
@@ -83,12 +83,12 @@
 }
 
 TEST(SyncableIdTest, ToValue) {
-  base::ExpectStringValue("r", Id::CreateFromServerId("0").ToValue());
-  base::ExpectStringValue("svalue", Id::CreateFromServerId("value").ToValue());
+  base::ExpectStringValue("r", *Id::CreateFromServerId("0").ToValue());
+  base::ExpectStringValue("svalue", *Id::CreateFromServerId("value").ToValue());
 
-  base::ExpectStringValue("r", Id::CreateFromClientString("0").ToValue());
+  base::ExpectStringValue("r", *Id::CreateFromClientString("0").ToValue());
   base::ExpectStringValue("cvalue",
-                          Id::CreateFromClientString("value").ToValue());
+                          *Id::CreateFromClientString("value").ToValue());
 }
 
 }  // namespace syncable
diff --git a/components/sync/syncable/write_transaction_info.cc b/components/sync/syncable/write_transaction_info.cc
index 0c4ac29..69e4f4f 100644
--- a/components/sync/syncable/write_transaction_info.cc
+++ b/components/sync/syncable/write_transaction_info.cc
@@ -30,9 +30,9 @@
 
 WriteTransactionInfo::~WriteTransactionInfo() {}
 
-base::DictionaryValue* WriteTransactionInfo::ToValue(
+std::unique_ptr<base::DictionaryValue> WriteTransactionInfo::ToValue(
     size_t max_mutations_size) const {
-  base::DictionaryValue* dict = new base::DictionaryValue();
+  auto dict = base::MakeUnique<base::DictionaryValue>();
   dict->SetString("id", base::Int64ToString(id));
   dict->SetString("location", location_string);
   dict->SetString("writer", WriterTagToString(writer));
diff --git a/components/sync/syncable/write_transaction_info.h b/components/sync/syncable/write_transaction_info.h
index f4d7b0d..cf385cb 100644
--- a/components/sync/syncable/write_transaction_info.h
+++ b/components/sync/syncable/write_transaction_info.h
@@ -8,8 +8,10 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 
+#include "base/values.h"
 #include "components/sync/syncable/entry_kernel.h"
 #include "components/sync/syncable/syncable_base_transaction.h"
 
@@ -26,8 +28,8 @@
   WriteTransactionInfo(const WriteTransactionInfo& other);
   ~WriteTransactionInfo();
 
-  // Caller owns the return value.
-  base::DictionaryValue* ToValue(size_t max_mutations_size) const;
+  std::unique_ptr<base::DictionaryValue> ToValue(
+      size_t max_mutations_size) const;
 
   int64_t id;
   // If tracked_objects::Location becomes assignable, we can use that
diff --git a/components/sync/test/fake_server/fake_server.cc b/components/sync/test/fake_server/fake_server.cc
index c2a1a60..de1cb20 100644
--- a/components/sync/test/fake_server/fake_server.cc
+++ b/components/sync/test/fake_server/fake_server.cc
@@ -504,7 +504,8 @@
   // Initialize an empty ListValue for all ModelTypes.
   ModelTypeSet all_types = ModelTypeSet::All();
   for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) {
-    dictionary->Set(ModelTypeToString(it.Get()), new base::ListValue());
+    dictionary->Set(ModelTypeToString(it.Get()),
+                    base::MakeUnique<base::ListValue>());
   }
 
   for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
diff --git a/components/sync_wifi/wifi_credential.cc b/components/sync_wifi/wifi_credential.cc
index 0337ee8..bf6294a3f 100644
--- a/components/sync_wifi/wifi_credential.cc
+++ b/components/sync_wifi/wifi_credential.cc
@@ -52,20 +52,19 @@
     return base::MakeUnique<base::DictionaryValue>();
   }
 
-  std::unique_ptr<base::DictionaryValue> onc_properties(
-      new base::DictionaryValue());
-  onc_properties->Set(onc::toplevel_config::kType,
-                      new base::Value(onc::network_type::kWiFi));
+  auto onc_properties = base::MakeUnique<base::DictionaryValue>();
+  onc_properties->SetString(onc::toplevel_config::kType,
+                            onc::network_type::kWiFi);
   // TODO(quiche): Switch to the HexSSID property, once ONC fully supports it.
   // crbug.com/432546.
-  onc_properties->Set(onc::network_config::WifiProperty(onc::wifi::kSSID),
-                      new base::Value(ssid_utf8));
-  onc_properties->Set(onc::network_config::WifiProperty(onc::wifi::kSecurity),
-                      new base::Value(onc_security));
+  onc_properties->SetString(onc::network_config::WifiProperty(onc::wifi::kSSID),
+                            ssid_utf8);
+  onc_properties->SetString(
+      onc::network_config::WifiProperty(onc::wifi::kSecurity), onc_security);
   if (WifiSecurityClassSupportsPassphrases(security_class())) {
-    onc_properties->Set(
+    onc_properties->SetString(
         onc::network_config::WifiProperty(onc::wifi::kPassphrase),
-        new base::Value(passphrase()));
+        passphrase());
   }
   return onc_properties;
 }
diff --git a/components/url_matcher/url_matcher_factory_unittest.cc b/components/url_matcher/url_matcher_factory_unittest.cc
index 3e51023d..bb598348 100644
--- a/components/url_matcher/url_matcher_factory_unittest.cc
+++ b/components/url_matcher/url_matcher_factory_unittest.cc
@@ -34,7 +34,8 @@
 
   // Invalid value type: {"hostSuffix": []}
   base::DictionaryValue invalid_condition2;
-  invalid_condition2.Set(keys::kHostSuffixKey, new base::ListValue);
+  invalid_condition2.Set(keys::kHostSuffixKey,
+                         base::MakeUnique<base::ListValue>());
 
   // Invalid regex value: {"urlMatches": "*"}
   base::DictionaryValue invalid_condition3;
@@ -53,21 +54,21 @@
   // }
 
   // Port range: Allow 80;1000-1010.
-  std::unique_ptr<base::ListValue> port_range(new base::ListValue());
+  auto port_range = base::MakeUnique<base::ListValue>();
   port_range->AppendInteger(1000);
   port_range->AppendInteger(1010);
-  base::ListValue* port_ranges = new base::ListValue();
+  auto port_ranges = base::MakeUnique<base::ListValue>();
   port_ranges->AppendInteger(80);
   port_ranges->Append(std::move(port_range));
 
-  base::ListValue* scheme_list = new base::ListValue();
+  auto scheme_list = base::MakeUnique<base::ListValue>();
   scheme_list->AppendString("http");
 
   base::DictionaryValue valid_condition;
   valid_condition.SetString(keys::kHostSuffixKey, "example.com");
   valid_condition.SetString(keys::kHostPrefixKey, "www");
-  valid_condition.Set(keys::kPortsKey, port_ranges);
-  valid_condition.Set(keys::kSchemesKey, scheme_list);
+  valid_condition.Set(keys::kPortsKey, std::move(port_ranges));
+  valid_condition.Set(keys::kSchemesKey, std::move(scheme_list));
 
   // Test wrong condition name passed.
   error.clear();
@@ -142,10 +143,10 @@
   invalid_condition4.SetString(keys::kHostEqualsKey, "WWW.example.Com");
 
   // {"scheme": ["HTTP"]}
-  base::ListValue* scheme_list = new base::ListValue();
+  auto scheme_list = base::MakeUnique<base::ListValue>();
   scheme_list->AppendString("HTTP");
   base::DictionaryValue invalid_condition5;
-  invalid_condition5.Set(keys::kSchemesKey, scheme_list);
+  invalid_condition5.Set(keys::kSchemesKey, std::move(scheme_list));
 
   const base::DictionaryValue* invalid_conditions[] = {
     &invalid_condition1,
diff --git a/components/webcrypto/algorithms/aes_cbc_unittest.cc b/components/webcrypto/algorithms/aes_cbc_unittest.cc
index 86c67db9..8820498 100644
--- a/components/webcrypto/algorithms/aes_cbc_unittest.cc
+++ b/components/webcrypto/algorithms/aes_cbc_unittest.cc
@@ -6,7 +6,10 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <utility>
+
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/values.h"
 #include "components/webcrypto/algorithm_dispatch.h"
 #include "components/webcrypto/algorithms/test_helpers.h"
@@ -219,7 +222,7 @@
   dict.SetString("kty", "oct");
   dict.SetBoolean("ext", false);
   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
-  dict.Set("key_ops", new base::ListValue);  // Takes ownership.
+  dict.Set("key_ops", base::MakeUnique<base::ListValue>());
 
   // The JWK does not contain encrypt usages.
   EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
@@ -260,8 +263,8 @@
   base::DictionaryValue dict;
   dict.SetString("kty", "oct");
   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
-  base::ListValue* key_ops = new base::ListValue;
-  dict.Set("key_ops", key_ops);  // Takes ownership.
+  base::ListValue* key_ops =
+      dict.SetList("key_ops", base::MakeUnique<base::ListValue>());
 
   key_ops->AppendString("encrypt");
 
@@ -298,10 +301,9 @@
   base::DictionaryValue dict;
   dict.SetString("kty", "oct");
   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
-  base::ListValue* key_ops = new base::ListValue;
-  dict.Set("key_ops", key_ops);  // Takes ownership.
-
+  auto key_ops = base::MakeUnique<base::ListValue>();
   key_ops->AppendString("encrypt");
+  dict.Set("key_ops", std::move(key_ops));
 
   EXPECT_EQ(
       Status::ErrorJwkKeyopsInconsistent(),
@@ -364,10 +366,9 @@
   dict.SetString("kty", "oct");
   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
 
-  base::ListValue* key_ops = new base::ListValue;
-  // Note: the following call makes dict assume ownership of key_ops.
-  dict.Set("key_ops", key_ops);
+  auto key_ops = base::MakeUnique<base::ListValue>();
   key_ops->AppendString("foo");
+  dict.Set("key_ops", std::move(key_ops));
   EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
             ImportKeyJwkFromDict(
                 dict, CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesCbc),
diff --git a/components/webcrypto/algorithms/aes_kw_unittest.cc b/components/webcrypto/algorithms/aes_kw_unittest.cc
index 2935100..12dea24 100644
--- a/components/webcrypto/algorithms/aes_kw_unittest.cc
+++ b/components/webcrypto/algorithms/aes_kw_unittest.cc
@@ -6,6 +6,7 @@
 #include <stdint.h>
 
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/values.h"
 #include "components/webcrypto/algorithm_dispatch.h"
@@ -58,8 +59,8 @@
   base::DictionaryValue dict;
   dict.SetString("kty", "oct");
   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
-  base::ListValue* key_ops = new base::ListValue;
-  dict.Set("key_ops", key_ops);  // Takes ownership.
+  base::ListValue* key_ops =
+      dict.SetList("key_ops", base::MakeUnique<base::ListValue>());
 
   key_ops->AppendString("wrapKey");
 
diff --git a/components/webcrypto/algorithms/hmac_unittest.cc b/components/webcrypto/algorithms/hmac_unittest.cc
index fe5b331..a57cdd8 100644
--- a/components/webcrypto/algorithms/hmac_unittest.cc
+++ b/components/webcrypto/algorithms/hmac_unittest.cc
@@ -6,7 +6,10 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <utility>
+
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/values.h"
 #include "components/webcrypto/algorithm_dispatch.h"
 #include "components/webcrypto/algorithms/test_helpers.h"
@@ -228,8 +231,8 @@
   base::DictionaryValue dict;
   dict.SetString("kty", "oct");
   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
-  base::ListValue* key_ops = new base::ListValue;
-  dict.Set("key_ops", key_ops);  // Takes ownership.
+  base::ListValue* key_ops =
+      dict.SetList("key_ops", base::MakeUnique<base::ListValue>());
 
   key_ops->AppendString("sign");
 
@@ -258,14 +261,14 @@
   base::DictionaryValue dict;
   dict.SetString("kty", "oct");
   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
-  base::ListValue* key_ops = new base::ListValue;
-  dict.Set("key_ops", key_ops);  // Takes ownership.
-
   dict.SetString("alg", "HS256");
   dict.SetString("use", "sig");
+
+  auto key_ops = base::MakeUnique<base::ListValue>();
   key_ops->AppendString("sign");
   key_ops->AppendString("verify");
   key_ops->AppendString("encrypt");
+  dict.Set("key_ops", std::move(key_ops));
   EXPECT_EQ(
       Status::ErrorJwkUseAndKeyopsInconsistent(),
       ImportKeyJwkFromDict(
diff --git a/components/webcrypto/jwk.cc b/components/webcrypto/jwk.cc
index 326ce2b8..50f81bb 100644
--- a/components/webcrypto/jwk.cc
+++ b/components/webcrypto/jwk.cc
@@ -353,7 +353,7 @@
                      const std::string& kty) {
   if (!algorithm.empty())
     dict_.SetString("alg", algorithm);
-  dict_.Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(usages).release());
+  dict_.Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(usages));
   dict_.SetBoolean("ext", extractable);
   dict_.SetString("kty", kty);
 }
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h
index f813389..7e75b49 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -42,6 +42,9 @@
 struct ServiceWorkerRegistrationObjectInfo;
 struct ServiceWorkerVersionAttributes;
 
+// This class is bound with mojom::ServiceWorkerDispatcherHost. All
+// InterfacePtrs on the same render process are bound to the same
+// content::ServiceWorkerDispatcherHost.
 class CONTENT_EXPORT ServiceWorkerDispatcherHost
     : public mojom::ServiceWorkerDispatcherHost,
       public BrowserMessageFilter {
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index bf34ff1..a097aee 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -57,15 +57,17 @@
 // For providers hosting a running service worker, this class will observe
 // resource loads made directly by the service worker.
 //
-// This instance is created when navigation is started and
-// ServiceWorkerNetworkProvider is create on the renderer process. Mojo's
-// connection from ServiceWorkerNetworkProvider is established on the creation
-// time, and the instance is destroyed on disconnection from the renderer side.
-// If PlzNavigate is turned on, this instance is pre-created on the browser
+// A ServiceWorkerProviderHost instance is created when a
+// ServiceWorkerNetworkProvider is created on the renderer process, which
+// happens 1) when a document or worker (i.e., a service worker client) is
+// created, or 2) during service worker startup. Mojo's connection from
+// ServiceWorkerNetworkProvider is established on the creation time, and the
+// instance is destroyed on disconnection from the renderer side.
+// If PlzNavigate is turned on, an instance is pre-created on the browser
 // before ServiceWorkerNetworkProvider is created on the renderer because
-// navigation is possible to be initiated on the browser side. In that case,
-// establishment of Mojo's connection will be deferred until
-// ServiceWorkerNetworkProvider is created on the renderer.
+// navigation is initiated on the browser side. In that case, establishment of
+// Mojo's connection will be deferred until ServiceWorkerNetworkProvider is
+// created on the renderer.
 class CONTENT_EXPORT ServiceWorkerProviderHost
     : public NON_EXPORTED_BASE(ServiceWorkerRegistration::Listener),
       public base::SupportsWeakPtr<ServiceWorkerProviderHost>,
diff --git a/content/browser/webrtc/webrtc_internals_unittest.cc b/content/browser/webrtc/webrtc_internals_unittest.cc
index 783e49f..da52039b 100644
--- a/content/browser/webrtc/webrtc_internals_unittest.cc
+++ b/content/browser/webrtc/webrtc_internals_unittest.cc
@@ -55,8 +55,7 @@
   void RequestWakeLock() override { has_wakelock_ = true; }
   void CancelWakeLock() override { has_wakelock_ = false; }
   void AddClient(device::mojom::WakeLockServiceRequest request) override {}
-  void HasWakeLockForTests(
-      const HasWakeLockForTestsCallback& callback) override {}
+  void HasWakeLockForTests(HasWakeLockForTestsCallback callback) override {}
 
   bool HasWakeLock() {
     base::RunLoop().RunUntilIdle();
diff --git a/content/common/service_worker/service_worker.mojom b/content/common/service_worker/service_worker.mojom
index 185e018..7e8f5c8 100644
--- a/content/common/service_worker/service_worker.mojom
+++ b/content/common/service_worker/service_worker.mojom
@@ -6,12 +6,9 @@
 
 import "content/common/service_worker/service_worker_provider.mojom";
 
-// Per-process browser-side interface bound to
-// content::ServiceWorkerDispatcherHost.
-// All InterfacePtrs on the same render process are bound to the same
-// content::ServiceWorkerDispatcherHost. The renderer uses this interface to
-// tell the browser when potential service worker clients are created and when
-// service workers are starting up.
+// Per-process browser-side interface.
+// The renderer uses this interface to tell the browser when potential service
+// worker clients are created and when service workers are starting up.
 interface ServiceWorkerDispatcherHost {
   // Creates a content::ServiceWorkerProviderHost on the browser
   // process. |provider_info| has Mojo endpoints to connect the provider host
diff --git a/content/common/service_worker/service_worker_provider.mojom b/content/common/service_worker/service_worker_provider.mojom
index 6c897f8..4016e42 100644
--- a/content/common/service_worker/service_worker_provider.mojom
+++ b/content/common/service_worker/service_worker_provider.mojom
@@ -8,8 +8,7 @@
 import "content/common/service_worker/service_worker_types.mojom";
 
 // A container object carried from the renderer to the browser process.
-// This contains the params for the constructor of
-// content::ServiceWorkerProviderHost.
+// This contains the parameters to specify the provider on the browser side.
 // See also comments in
 // content/common/service_worker/service_worker_provider_host_info.h.
 struct ServiceWorkerProviderHostInfo {
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index dee0774..4b534b9 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -219,6 +219,8 @@
     "media/audio_device_factory.h",
     "media/audio_input_message_filter.cc",
     "media/audio_input_message_filter.h",
+    "media/audio_ipc_factory.cc",
+    "media/audio_ipc_factory.h",
     "media/audio_message_filter.cc",
     "media/audio_message_filter.h",
     "media/audio_renderer_mixer_manager.cc",
diff --git a/content/renderer/media/audio_device_factory.cc b/content/renderer/media/audio_device_factory.cc
index e83ca0fa..7f72d25 100644
--- a/content/renderer/media/audio_device_factory.cc
+++ b/content/renderer/media/audio_device_factory.cc
@@ -11,7 +11,7 @@
 #include "build/build_config.h"
 #include "content/common/content_constants_internal.h"
 #include "content/renderer/media/audio_input_message_filter.h"
-#include "content/renderer/media/audio_message_filter.h"
+#include "content/renderer/media/audio_ipc_factory.h"
 #include "content/renderer/media/audio_renderer_mixer_manager.h"
 #include "content/renderer/render_thread_impl.h"
 #include "media/audio/audio_input_device.h"
@@ -43,14 +43,14 @@
     int session_id,
     const std::string& device_id,
     const url::Origin& security_origin) {
-  AudioMessageFilter* const filter = AudioMessageFilter::Get();
-  scoped_refptr<media::AudioOutputDevice> device(new media::AudioOutputDevice(
-      filter->CreateAudioOutputIPC(render_frame_id), filter->io_task_runner(),
-      session_id, device_id, security_origin,
-      // Set authorization request timeout at 80% of renderer hung timeout, but
-      // no more than kMaxAuthorizationTimeout.
-      base::TimeDelta::FromMilliseconds(std::min(kHungRendererDelayMs * 8 / 10,
-                                                 kMaxAuthorizationTimeoutMs))));
+  auto device = base::MakeRefCounted<media::AudioOutputDevice>(
+      AudioIPCFactory::get()->CreateAudioOutputIPC(render_frame_id),
+      AudioIPCFactory::get()->io_task_runner(), session_id, device_id,
+      security_origin,
+      // Set authorization request timeout at 80% of renderer hung timeout,
+      // but no more than kMaxAuthorizationTimeout.
+      base::TimeDelta::FromMilliseconds(
+          std::min(kHungRendererDelayMs * 8 / 10, kMaxAuthorizationTimeoutMs)));
   device->RequestDeviceAuthorization();
   return device;
 }
diff --git a/content/renderer/media/audio_ipc_factory.cc b/content/renderer/media/audio_ipc_factory.cc
new file mode 100644
index 0000000..0cc05ea
--- /dev/null
+++ b/content/renderer/media/audio_ipc_factory.cc
@@ -0,0 +1,120 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/audio_ipc_factory.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
+#include "content/renderer/media/audio_message_filter.h"
+#include "content/renderer/media/mojo_audio_output_ipc.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+
+namespace content {
+
+AudioIPCFactory* AudioIPCFactory::instance_ = nullptr;
+
+AudioIPCFactory::AudioIPCFactory(
+    scoped_refptr<AudioMessageFilter> audio_message_filter,
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
+    : audio_message_filter_(std::move(audio_message_filter)),
+      io_task_runner_(std::move(io_task_runner)) {
+  // TODO(maxmorin): In the future, use a feature to control whether
+  // audio_message_filter should be used.
+  DCHECK(!instance_);
+  instance_ = this;
+}
+
+AudioIPCFactory::~AudioIPCFactory() {
+  // Allow destruction in tests.
+  DCHECK(factory_ptrs_.empty());
+  DCHECK_EQ(instance_, this);
+  instance_ = nullptr;
+}
+
+std::unique_ptr<media::AudioOutputIPC> AudioIPCFactory::CreateAudioOutputIPC(
+    int frame_id) const {
+  if (UsingMojoFactories()) {
+    // Unretained is safe due to the contract at the top of the header file.
+    return base::MakeUnique<MojoAudioOutputIPC>(base::BindRepeating(
+        &AudioIPCFactory::GetRemoteFactory, base::Unretained(this), frame_id));
+  }
+  return audio_message_filter_->CreateAudioOutputIPC(frame_id);
+}
+
+void AudioIPCFactory::MaybeRegisterRemoteFactory(
+    int frame_id,
+    service_manager::InterfaceProvider* interface_provider) {
+  if (!UsingMojoFactories())
+    return;
+  mojom::RendererAudioOutputStreamFactoryPtr factory_ptr;
+  interface_provider->GetInterface(&factory_ptr);
+  // PassInterface unbinds the message pipe from the current thread. This
+  // allows us to bind it to the IO thread.
+  // Unretained is safe due to the contract at the top of the header file.
+  io_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&AudioIPCFactory::RegisterRemoteFactoryOnIOThread,
+                     base::Unretained(this), frame_id,
+                     factory_ptr.PassInterface()));
+}
+
+void AudioIPCFactory::MaybeDeregisterRemoteFactory(int frame_id) {
+  if (!UsingMojoFactories())
+    return;
+  io_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&AudioIPCFactory::MaybeDeregisterRemoteFactoryOnIOThread,
+                     base::Unretained(this), frame_id));
+}
+
+mojom::RendererAudioOutputStreamFactory* AudioIPCFactory::GetRemoteFactory(
+    int frame_id) const {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  DCHECK(UsingMojoFactories());
+  auto it = factory_ptrs_.find(frame_id);
+  return it == factory_ptrs_.end() ? nullptr : it->second.get();
+}
+
+void AudioIPCFactory::RegisterRemoteFactoryOnIOThread(
+    int frame_id,
+    mojom::RendererAudioOutputStreamFactoryPtrInfo factory_ptr_info) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  DCHECK(UsingMojoFactories());
+  std::pair<StreamFactoryMap::iterator, bool> emplace_result =
+      factory_ptrs_.emplace(frame_id,
+                            mojo::MakeProxy(std::move(factory_ptr_info)));
+
+  DCHECK(emplace_result.second) << "Attempt to register a factory for a "
+                                   "frame which already has a factory "
+                                   "registered.";
+
+  auto& emplaced_factory = emplace_result.first->second;
+  DCHECK(emplaced_factory.is_bound())
+      << "Factory is not bound to a remote implementation.";
+
+  // Unretained is safe because |this| owns the binding, so a connection error
+  // cannot trigger after destruction.
+  emplaced_factory.set_connection_error_handler(
+      base::Bind(&AudioIPCFactory::MaybeDeregisterRemoteFactory,
+                 base::Unretained(this), frame_id));
+}
+
+void AudioIPCFactory::MaybeDeregisterRemoteFactoryOnIOThread(int frame_id) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  DCHECK(UsingMojoFactories());
+  // This function can be called both by the frame and the connection error
+  // handler of the factory pointer. Calling erase multiple times even though
+  // there is nothing to erase is safe, so we don't have to handle this in any
+  // particular way.
+  factory_ptrs_.erase(frame_id);
+}
+
+bool AudioIPCFactory::UsingMojoFactories() const {
+  return audio_message_filter_ == nullptr;
+}
+
+}  // namespace content
diff --git a/content/renderer/media/audio_ipc_factory.h b/content/renderer/media/audio_ipc_factory.h
new file mode 100644
index 0000000..ae33fee
--- /dev/null
+++ b/content/renderer/media/audio_ipc_factory.h
@@ -0,0 +1,97 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_AUDIO_IPC_FACTORY_H_
+#define CONTENT_RENDERER_MEDIA_AUDIO_IPC_FACTORY_H_
+
+#include <memory>
+
+#include "base/containers/flat_map.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
+#include "content/renderer/media/audio_message_filter.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace media {
+class AudioOutputIPC;
+}
+
+namespace service_manager {
+class InterfaceProvider;
+}
+
+namespace content {
+
+// This is a factory for AudioOutputIPC objects. It has two modes, using either
+// AudioMessageFilter or Mojo RendererAudioOutputStreamFactory objects. It is
+// threadsafe. This class is designed to be leaked at shutdown, as it posts
+// tasks to itself using base::Unretained and also hands out references to
+// itself in the AudioOutputIPCs it creates, but in the case where the owner is
+// sure that there are no outstanding references (such as in a unit test), the
+// class can be destructed.
+// TODO(maxmorin): Registering the factories for each frame will become
+// unnecessary when crbug.com/668275 is fixed. When that is done, this class can
+// be greatly simplified.
+class CONTENT_EXPORT AudioIPCFactory {
+ public:
+  AudioIPCFactory(scoped_refptr<AudioMessageFilter> audio_message_filter,
+                  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+  ~AudioIPCFactory();
+
+  static AudioIPCFactory* get() { return instance_; }
+
+  const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner() const {
+    return io_task_runner_;
+  }
+
+  // Enables |this| to create MojoAudioOutputIPCs for the specified frame.
+  // Does nothing if not using mojo factories.
+  void MaybeRegisterRemoteFactory(
+      int frame_id,
+      service_manager::InterfaceProvider* interface_provider);
+
+  // Every call to the above method must be matched by a call to this one when
+  // the frame is destroyed. Does nothing if not using mojo factories.
+  void MaybeDeregisterRemoteFactory(int frame_id);
+
+  // The returned object may only be used on |io_task_runner()|.
+  std::unique_ptr<media::AudioOutputIPC> CreateAudioOutputIPC(
+      int frame_id) const;
+
+ private:
+  using StreamFactoryMap =
+      base::flat_map<int, mojom::RendererAudioOutputStreamFactoryPtr>;
+
+  mojom::RendererAudioOutputStreamFactory* GetRemoteFactory(int frame_id) const;
+
+  void RegisterRemoteFactoryOnIOThread(
+      int frame_id,
+      mojom::RendererAudioOutputStreamFactoryPtrInfo factory_ptr_info);
+
+  void MaybeDeregisterRemoteFactoryOnIOThread(int frame_id);
+
+  // Indicates whether mojo factories are used.
+  bool UsingMojoFactories() const;
+
+  // Maps frame id to the corresponding factory.
+  StreamFactoryMap factory_ptrs_;
+
+  // If this is non-null, it will be used rather than using mojo implementation.
+  const scoped_refptr<AudioMessageFilter> audio_message_filter_;
+
+  const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
+  // Global instance, set in constructor and unset in destructor.
+  static AudioIPCFactory* instance_;
+
+  DISALLOW_COPY_AND_ASSIGN(AudioIPCFactory);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_AUDIO_IPC_FACTORY_H_
diff --git a/content/renderer/media/audio_ipc_factory_unittest.cc b/content/renderer/media/audio_ipc_factory_unittest.cc
new file mode 100644
index 0000000..166e840
--- /dev/null
+++ b/content/renderer/media/audio_ipc_factory_unittest.cc
@@ -0,0 +1,223 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/audio_ipc_factory.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/message_loop/message_loop.h"
+#include "base/threading/thread.h"
+#include "content/renderer/media/audio_message_filter.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace content {
+
+namespace {
+
+const int kRenderFrameId = 0;
+
+std::unique_ptr<base::Thread> MakeIOThread() {
+  auto io_thread = base::MakeUnique<base::Thread>("test IO thread");
+  base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
+  CHECK(io_thread->StartWithOptions(thread_options));
+  return io_thread;
+}
+
+class FakeRemoteFactory : public mojom::RendererAudioOutputStreamFactory {
+ public:
+  FakeRemoteFactory() : binding_(this) {}
+  ~FakeRemoteFactory() override {}
+
+  void RequestDeviceAuthorization(
+      media::mojom::AudioOutputStreamProviderRequest stream_provider,
+      int64_t session_id,
+      const std::string& device_id,
+      RequestDeviceAuthorizationCallback callback) override {
+    std::move(callback).Run(
+        media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
+        media::AudioParameters::UnavailableDeviceParams(), std::string());
+    EXPECT_FALSE(on_called_.is_null());
+    std::move(on_called_).Run();
+  }
+
+  void SetOnCalledCallback(base::OnceClosure on_called) {
+    on_called_ = std::move(on_called);
+  }
+
+  void Bind(mojo::ScopedMessagePipeHandle handle) {
+    EXPECT_FALSE(binding_.is_bound());
+    binding_.Bind(
+        mojo::InterfaceRequest<mojom::RendererAudioOutputStreamFactory>(
+            std::move(handle)));
+  }
+
+ private:
+  mojo::Binding<mojom::RendererAudioOutputStreamFactory> binding_;
+  base::OnceClosure on_called_;
+};
+
+class FakeAudioIPCDelegate : public media::AudioOutputIPCDelegate {
+  void OnError() override {}
+  void OnDeviceAuthorized(media::OutputDeviceStatus device_status,
+                          const media::AudioParameters& output_params,
+                          const std::string& matched_device_id) override {}
+  void OnStreamCreated(base::SharedMemoryHandle handle,
+                       base::SyncSocket::Handle socket_handle,
+                       int length) override {}
+  void OnIPCClosed() override {}
+};
+
+}  // namespace
+
+class AudioIPCFactoryTest : public testing::Test {
+ public:
+  AudioIPCFactoryTest() {}
+  ~AudioIPCFactoryTest() override {}
+
+  void RequestAuthorizationOnIOThread(
+      std::unique_ptr<media::AudioOutputIPC> output_ipc) {
+    output_ipc->RequestDeviceAuthorization(&fake_delegate, 0, "",
+                                           url::Origin());
+
+    output_ipc->CloseStream();
+  }
+
+ private:
+  FakeAudioIPCDelegate fake_delegate;
+};
+
+TEST_F(AudioIPCFactoryTest, CallFactoryFromIOThread) {
+  // This test makes sure that AudioIPCFactory correctly binds the
+  // RendererAudioOutputStreamFactoryPtr to the IO thread.
+  base::MessageLoop message_loop;
+  base::RunLoop run_loop;
+  auto io_thread = MakeIOThread();
+
+  FakeRemoteFactory remote_factory;
+  remote_factory.SetOnCalledCallback(run_loop.QuitWhenIdleClosure());
+
+  service_manager::InterfaceProvider interface_provider;
+  service_manager::InterfaceProvider::TestApi(&interface_provider)
+      .SetBinderForName(mojom::RendererAudioOutputStreamFactory::Name_,
+                        base::BindRepeating(&FakeRemoteFactory::Bind,
+                                            base::Unretained(&remote_factory)));
+
+  AudioIPCFactory ipc_factory(nullptr, io_thread->task_runner());
+
+  ipc_factory.MaybeRegisterRemoteFactory(kRenderFrameId, &interface_provider);
+
+  // To make sure that the pointer stored in |ipc_factory| is connected to
+  // |remote_factory|, and also that it's bound to |io_thread|, we create an
+  // AudioOutputIPC object and request device authorization on the IO thread.
+  // This is supposed to call |remote_factory| on the main thread.
+  io_thread->task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&AudioIPCFactoryTest::RequestAuthorizationOnIOThread,
+                     base::Unretained(this),
+                     ipc_factory.CreateAudioOutputIPC(kRenderFrameId)));
+
+  // Wait for call to |remote_factory|:
+  run_loop.Run();
+
+  ipc_factory.MaybeDeregisterRemoteFactory(0);
+
+  io_thread.reset();
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(AudioIPCFactoryTest, SeveralFactories) {
+  // This test simulates having several frames being created and destructed.
+  base::MessageLoop message_loop;
+  auto io_thread = MakeIOThread();
+  const int n_factories = 5;
+
+  std::vector<service_manager::InterfaceProvider> interface_providers(
+      n_factories);
+
+  std::vector<FakeRemoteFactory> remote_factories(n_factories);
+
+  for (size_t i = 0; i < n_factories; i++) {
+    service_manager::InterfaceProvider::TestApi(&interface_providers[i])
+        .SetBinderForName(
+            mojom::RendererAudioOutputStreamFactory::Name_,
+            base::BindRepeating(&FakeRemoteFactory::Bind,
+                                base::Unretained(&remote_factories[i])));
+  }
+
+  base::RunLoop().RunUntilIdle();
+
+  AudioIPCFactory ipc_factory(nullptr, io_thread->task_runner());
+
+  for (size_t i = 0; i < n_factories; i++) {
+    ipc_factory.MaybeRegisterRemoteFactory(kRenderFrameId + i,
+                                           &interface_providers[i]);
+  }
+
+  base::RunLoop run_loop;
+  remote_factories[0].SetOnCalledCallback(run_loop.QuitWhenIdleClosure());
+  io_thread->task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&AudioIPCFactoryTest::RequestAuthorizationOnIOThread,
+                     base::Unretained(this),
+                     ipc_factory.CreateAudioOutputIPC(kRenderFrameId)));
+  run_loop.Run();
+
+  // Do some operation and make sure the internal state isn't messed up:
+  ipc_factory.MaybeDeregisterRemoteFactory(1);
+
+  base::RunLoop run_loop2;
+  remote_factories[2].SetOnCalledCallback(run_loop2.QuitWhenIdleClosure());
+  io_thread->task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&AudioIPCFactoryTest::RequestAuthorizationOnIOThread,
+                     base::Unretained(this),
+                     ipc_factory.CreateAudioOutputIPC(kRenderFrameId + 2)));
+  run_loop2.Run();
+
+  for (size_t i = 0; i < n_factories; i++) {
+    if (i == 1)
+      continue;
+    ipc_factory.MaybeDeregisterRemoteFactory(i);
+  }
+
+  io_thread.reset();
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(AudioIPCFactoryTest, RegisterDeregisterBackToBack_Deregisters) {
+  // This test makes sure that calling Register... followed by Deregister...
+  // correctly sequences the registration before the deregistration.
+  base::MessageLoop message_loop;
+  auto io_thread = MakeIOThread();
+
+  FakeRemoteFactory remote_factory;
+
+  service_manager::InterfaceProvider interface_provider;
+  service_manager::InterfaceProvider::TestApi(&interface_provider)
+      .SetBinderForName(mojom::RendererAudioOutputStreamFactory::Name_,
+                        base::BindRepeating(&FakeRemoteFactory::Bind,
+                                            base::Unretained(&remote_factory)));
+
+  AudioIPCFactory ipc_factory(nullptr, io_thread->task_runner());
+
+  ipc_factory.MaybeRegisterRemoteFactory(kRenderFrameId, &interface_provider);
+  ipc_factory.MaybeDeregisterRemoteFactory(kRenderFrameId);
+  // That there is no factory remaining at destruction is DCHECKed in the
+  // AudioIPCFactory destructor.
+
+  base::RunLoop().RunUntilIdle();
+  io_thread.reset();
+  base::RunLoop().RunUntilIdle();
+}
+
+}  // namespace content
diff --git a/content/renderer/pepper/pepper_platform_audio_output.cc b/content/renderer/pepper/pepper_platform_audio_output.cc
index 0a16cf12..52cda38 100644
--- a/content/renderer/pepper/pepper_platform_audio_output.cc
+++ b/content/renderer/pepper/pepper_platform_audio_output.cc
@@ -11,10 +11,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "content/child/child_process.h"
-#include "content/common/media/audio_messages.h"
-#include "content/renderer/media/audio_message_filter.h"
+#include "content/renderer/media/audio_ipc_factory.h"
 #include "content/renderer/pepper/audio_helper.h"
-#include "content/renderer/render_thread_impl.h"
 #include "ppapi/shared_impl/ppb_audio_config_shared.h"
 
 namespace content {
@@ -134,9 +132,7 @@
   DCHECK(client);
   client_ = client;
 
-  RenderThreadImpl* const render_thread = RenderThreadImpl::current();
-  ipc_ = render_thread->audio_message_filter()->CreateAudioOutputIPC(
-      source_render_frame_id);
+  ipc_ = AudioIPCFactory::get()->CreateAudioOutputIPC(source_render_frame_id);
   CHECK(ipc_);
 
   media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
diff --git a/content/renderer/pepper/pepper_platform_audio_output.h b/content/renderer/pepper/pepper_platform_audio_output.h
index ad218839..6499711 100644
--- a/content/renderer/pepper/pepper_platform_audio_output.h
+++ b/content/renderer/pepper/pepper_platform_audio_output.h
@@ -6,6 +6,7 @@
 #define CONTENT_RENDERER_PEPPER_PEPPER_PLATFORM_AUDIO_OUTPUT_H_
 
 #include <memory>
+#include <string>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
diff --git a/content/renderer/pepper/pepper_platform_audio_output_dev.cc b/content/renderer/pepper/pepper_platform_audio_output_dev.cc
index e13aec1e..905155d 100644
--- a/content/renderer/pepper/pepper_platform_audio_output_dev.cc
+++ b/content/renderer/pepper/pepper_platform_audio_output_dev.cc
@@ -14,16 +14,22 @@
 #include "build/build_config.h"
 #include "content/child/child_process.h"
 #include "content/common/content_constants_internal.h"
-#include "content/common/media/audio_messages.h"
-#include "content/renderer/media/audio_message_filter.h"
+#include "content/renderer/media/audio_ipc_factory.h"
 #include "content/renderer/pepper/audio_helper.h"
 #include "content/renderer/pepper/pepper_audio_output_host.h"
 #include "content/renderer/pepper/pepper_media_device_manager.h"
 #include "content/renderer/render_frame_impl.h"
-#include "content/renderer/render_thread_impl.h"
 #include "media/audio/audio_device_description.h"
 #include "ppapi/shared_impl/ppb_audio_config_shared.h"
 
+namespace {
+#if defined(OS_WIN) || defined(OS_MACOSX)
+const int64_t kMaxAuthorizationTimeoutMs = 4000;
+#else
+const int64_t kMaxAuthorizationTimeoutMs = 0;  // No timeout.
+#endif
+}
+
 namespace content {
 
 // static
@@ -254,9 +260,7 @@
 
   client_ = client;
 
-  RenderThreadImpl* const render_thread = RenderThreadImpl::current();
-  ipc_ = render_thread->audio_message_filter()->CreateAudioOutputIPC(
-      render_frame_id_);
+  ipc_ = AudioIPCFactory::get()->CreateAudioOutputIPC(render_frame_id_);
   CHECK(ipc_);
 
   params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
diff --git a/content/renderer/pepper/pepper_platform_audio_output_dev.h b/content/renderer/pepper/pepper_platform_audio_output_dev.h
index 50d4537a..e44dce8 100644
--- a/content/renderer/pepper/pepper_platform_audio_output_dev.h
+++ b/content/renderer/pepper/pepper_platform_audio_output_dev.h
@@ -6,6 +6,7 @@
 #define CONTENT_RENDERER_PEPPER_PEPPER_PLATFORM_AUDIO_OUTPUT_DEV_H_
 
 #include <memory>
+#include <string>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
@@ -18,14 +19,6 @@
 class SingleThreadTaskRunner;
 }
 
-namespace {
-#if defined(OS_WIN) || defined(OS_MACOSX)
-const int64_t kMaxAuthorizationTimeoutMs = 4000;
-#else
-const int64_t kMaxAuthorizationTimeoutMs = 0;  // No timeout.
-#endif
-}
-
 namespace content {
 class PepperAudioOutputHost;
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index de85563ae..8ff540e 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -118,6 +118,7 @@
 #include "content/renderer/internal_document_state_data.h"
 #include "content/renderer/manifest/manifest_manager.h"
 #include "content/renderer/media/audio_device_factory.h"
+#include "content/renderer/media/audio_ipc_factory.h"
 #include "content/renderer/media/media_devices_listener_impl.h"
 #include "content/renderer/media/media_permission_dispatcher.h"
 #include "content/renderer/media/media_stream_dispatcher.h"
@@ -1228,6 +1229,9 @@
   if (input_handler_manager)
     input_handler_manager->UnregisterRoutingID(GetRoutingID());
 
+  if (auto* factory = AudioIPCFactory::get())
+    factory->MaybeDeregisterRemoteFactory(GetRoutingID());
+
   if (is_main_frame_) {
     // Ensure the RenderView doesn't point to this object, once it is destroyed.
     // TODO(nasko): Add a check that the |main_render_frame_| of |render_view_|
@@ -1301,6 +1305,10 @@
         GetRoutingID(), render_view_->GetRoutingID());
   }
 
+  // AudioIPCFactory may be null in tests.
+  if (auto* factory = AudioIPCFactory::get())
+    factory->MaybeRegisterRemoteFactory(GetRoutingID(), GetRemoteInterfaces());
+
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
   if (command_line.HasSwitch(switches::kDomAutomationController))
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 7d56be9..bc63aab 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -708,8 +708,13 @@
   audio_input_message_filter_ = new AudioInputMessageFilter(GetIOTaskRunner());
   AddFilter(audio_input_message_filter_.get());
 
-  audio_message_filter_ = new AudioMessageFilter(GetIOTaskRunner());
-  AddFilter(audio_message_filter_.get());
+  auto audio_message_filter =
+      base::MakeRefCounted<AudioMessageFilter>(GetIOTaskRunner());
+  AddFilter(audio_message_filter.get());
+  // TODO(maxmorin): Based on a feature flag, don't create the
+  // AudioMessageFilter, making AudioIPCFactory instead use mojo factories.
+  audio_ipc_factory_.emplace(std::move(audio_message_filter),
+                             GetIOTaskRunner());
 
   midi_message_filter_ = new MidiMessageFilter(GetIOTaskRunner());
   AddFilter(midi_message_filter_.get());
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 5d57ec6..ecf995c 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -8,9 +8,11 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <map>
 #include <memory>
 #include <set>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/cancelable_callback.h"
@@ -21,6 +23,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/observer_list.h"
+#include "base/optional.h"
 #include "base/strings/string16.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
@@ -41,6 +44,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "content/renderer/gpu/compositor_dependencies.h"
 #include "content/renderer/layout_test_dependencies.h"
+#include "content/renderer/media/audio_ipc_factory.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "media/media_features.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
@@ -319,10 +323,6 @@
     return audio_input_message_filter_.get();
   }
 
-  AudioMessageFilter* audio_message_filter() {
-    return audio_message_filter_.get();
-  }
-
   MidiMessageFilter* midi_message_filter() {
     return midi_message_filter_.get();
   }
@@ -619,7 +619,6 @@
   scoped_refptr<BlobMessageFilter> blob_message_filter_;
   scoped_refptr<DBMessageFilter> db_message_filter_;
   scoped_refptr<AudioInputMessageFilter> audio_input_message_filter_;
-  scoped_refptr<AudioMessageFilter> audio_message_filter_;
   scoped_refptr<MidiMessageFilter> midi_message_filter_;
   scoped_refptr<DevToolsAgentFilter> devtools_agent_message_filter_;
 
@@ -642,6 +641,11 @@
   scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_;
 #endif
 
+  // Provides AudioOutputIPC objects for audio output devices. It either uses
+  // an AudioMessageFilter for this or provides MojoAudioOutputIPC objects.
+  // Initialized in Init.
+  base::Optional<AudioIPCFactory> audio_ipc_factory_;
+
   // Used on the render thread.
   std::unique_ptr<VideoCaptureImplManager> vc_manager_;
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 8536ad44..ea57ae5 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1415,6 +1415,7 @@
     "../renderer/input/main_thread_event_queue_unittest.cc",
     "../renderer/manifest/manifest_parser_unittest.cc",
     "../renderer/media/android/media_info_loader_unittest.cc",
+    "../renderer/media/audio_ipc_factory_unittest.cc",
     "../renderer/media/audio_message_filter_unittest.cc",
     "../renderer/media/audio_renderer_mixer_manager_unittest.cc",
     "../renderer/media/audio_renderer_sink_cache_unittest.cc",
diff --git a/device/wake_lock/public/interfaces/BUILD.gn b/device/wake_lock/public/interfaces/BUILD.gn
index 06045e1..d5de08a1f 100644
--- a/device/wake_lock/public/interfaces/BUILD.gn
+++ b/device/wake_lock/public/interfaces/BUILD.gn
@@ -10,7 +10,4 @@
     "wake_lock_provider.mojom",
     "wake_lock_service.mojom",
   ]
-
-  # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
-  use_once_callback = false
 }
diff --git a/device/wake_lock/wake_lock_service_impl.cc b/device/wake_lock/wake_lock_service_impl.cc
index a5065b6..7031f78 100644
--- a/device/wake_lock/wake_lock_service_impl.cc
+++ b/device/wake_lock/wake_lock_service_impl.cc
@@ -104,8 +104,8 @@
 }
 
 void WakeLockServiceImpl::HasWakeLockForTests(
-    const HasWakeLockForTestsCallback& callback) {
-  callback.Run(!!wake_lock_);
+    HasWakeLockForTestsCallback callback) {
+  std::move(callback).Run(!!wake_lock_);
 }
 void WakeLockServiceImpl::UpdateWakeLock() {
   DCHECK(num_lock_requests_ >= 0);
diff --git a/device/wake_lock/wake_lock_service_impl.h b/device/wake_lock/wake_lock_service_impl.h
index a64ff408..7991796 100644
--- a/device/wake_lock/wake_lock_service_impl.h
+++ b/device/wake_lock/wake_lock_service_impl.h
@@ -35,8 +35,7 @@
   void RequestWakeLock() override;
   void CancelWakeLock() override;
   void AddClient(mojom::WakeLockServiceRequest request) override;
-  void HasWakeLockForTests(
-      const HasWakeLockForTestsCallback& callback) override;
+  void HasWakeLockForTests(HasWakeLockForTestsCallback callback) override;
 
  private:
   void UpdateWakeLock();
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm
index 011ca2b..1e40ad97 100644
--- a/ios/chrome/browser/translate/translate_egtest.mm
+++ b/ios/chrome/browser/translate/translate_egtest.mm
@@ -636,7 +636,7 @@
 }
 
 // Tests that the Translate infobar is displayed after translation.
-- (void)DISABLED_testTranslateInfobar {
+- (void)testTranslateInfobar {
   const GURL URL =
       web::test::HttpServer::MakeUrl("http://scenarioTranslateInfobar");
   std::map<GURL, std::string> responses;
diff --git a/ios/chrome/browser/ui/history/favicon_view.h b/ios/chrome/browser/ui/history/favicon_view.h
index 60bf6bd..3a0ce2e 100644
--- a/ios/chrome/browser/ui/history/favicon_view.h
+++ b/ios/chrome/browser/ui/history/favicon_view.h
@@ -7,6 +7,7 @@
 
 #import <UIKit/UIKit.h>
 
+// View for displaying the favicon of a history entry.
 @interface FaviconView : UIView
 
 // Size for the favicon.
diff --git a/services/BUILD.gn b/services/BUILD.gn
index e1580d08..a46978d 100644
--- a/services/BUILD.gn
+++ b/services/BUILD.gn
@@ -98,7 +98,7 @@
     java_files = [
       "device/generic_sensor/android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java",
       "device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java",
-      "shape_detection/android/junit/src/org/chromium/shape_detection/SharedBufferUtilsTest.java",
+      "shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java",
     ]
     deps = [
       "$google_play_services_package:google_play_services_base_java",
@@ -115,6 +115,7 @@
       "//services/device/public/interfaces:interfaces_java",
       "//services/device/public/java:nfc_java",
       "//services/shape_detection:shape_detection_java",
+      "//skia/public/interfaces:interfaces_java",
       "//third_party/android_tools:android_support_annotations_java",
     ]
   }
diff --git a/services/shape_detection/BUILD.gn b/services/shape_detection/BUILD.gn
index 3a80c583..8fd0971 100644
--- a/services/shape_detection/BUILD.gn
+++ b/services/shape_detection/BUILD.gn
@@ -68,7 +68,7 @@
       "android/java/src/org/chromium/shape_detection/FaceDetectionImplGmsCore.java",
       "android/java/src/org/chromium/shape_detection/FaceDetectionProviderImpl.java",
       "android/java/src/org/chromium/shape_detection/InterfaceRegistrar.java",
-      "android/java/src/org/chromium/shape_detection/SharedBufferUtils.java",
+      "android/java/src/org/chromium/shape_detection/BitmapUtils.java",
       "android/java/src/org/chromium/shape_detection/TextDetectionImpl.java",
     ]
 
@@ -84,6 +84,7 @@
       "//services/service_manager/public/interfaces:interfaces_java",
       "//services/service_manager/public/java:service_manager_java",
       "//services/shape_detection/public/interfaces:interfaces_java",
+      "//skia/public/interfaces:interfaces_java",
       "//ui/gfx/geometry/mojo:mojo_java",
     ]
   }
diff --git a/services/shape_detection/DEPS b/services/shape_detection/DEPS
index 90dc774..09ca6e8 100644
--- a/services/shape_detection/DEPS
+++ b/services/shape_detection/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+media/capture/video/scoped_result_callback.h",
   "+jni",
+  "+skia/ext/skia_utils_mac.h",
   "+third_party/skia/include",
   "+ui/gfx/codec",
   "+ui/gl/gl_switches.h"
diff --git a/services/shape_detection/android/java/src/org/chromium/shape_detection/BarcodeDetectionImpl.java b/services/shape_detection/android/java/src/org/chromium/shape_detection/BarcodeDetectionImpl.java
index 6f02069..337ab1d 100644
--- a/services/shape_detection/android/java/src/org/chromium/shape_detection/BarcodeDetectionImpl.java
+++ b/services/shape_detection/android/java/src/org/chromium/shape_detection/BarcodeDetectionImpl.java
@@ -19,7 +19,6 @@
 import org.chromium.gfx.mojom.PointF;
 import org.chromium.gfx.mojom.RectF;
 import org.chromium.mojo.system.MojoException;
-import org.chromium.mojo.system.SharedBufferHandle;
 import org.chromium.services.service_manager.InterfaceFactory;
 import org.chromium.shape_detection.mojom.BarcodeDetection;
 import org.chromium.shape_detection.mojom.BarcodeDetectionResult;
@@ -38,8 +37,7 @@
     }
 
     @Override
-    public void detect(
-            SharedBufferHandle frameData, int width, int height, DetectResponse callback) {
+    public void detect(org.chromium.skia.mojom.Bitmap bitmapData, DetectResponse callback) {
         if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(
                     ContextUtils.getApplicationContext())
                 != ConnectionResult.SUCCESS) {
@@ -57,7 +55,7 @@
             return;
         }
 
-        Frame frame = SharedBufferUtils.convertToFrame(frameData, width, height);
+        Frame frame = BitmapUtils.convertToFrame(bitmapData);
         if (frame == null) {
             Log.e(TAG, "Error converting SharedMemory to Frame");
             callback.call(new BarcodeDetectionResult[0]);
diff --git a/services/shape_detection/android/java/src/org/chromium/shape_detection/BitmapUtils.java b/services/shape_detection/android/java/src/org/chromium/shape_detection/BitmapUtils.java
new file mode 100644
index 0000000..cec759d
--- /dev/null
+++ b/services/shape_detection/android/java/src/org/chromium/shape_detection/BitmapUtils.java
@@ -0,0 +1,59 @@
+// 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.shape_detection;
+
+import android.graphics.Bitmap;
+
+import com.google.android.gms.vision.Frame;
+
+import org.chromium.skia.mojom.ColorType;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Utility class to convert a Bitmap to a GMS core YUV Frame.
+ */
+public class BitmapUtils {
+    public static Bitmap convertToBitmap(org.chromium.skia.mojom.Bitmap bitmapData) {
+        int width = bitmapData.width;
+        int height = bitmapData.height;
+        final long numPixels = (long) width * height;
+        // TODO(mcasas): https://crbug.com/670028 homogeneize overflow checking.
+        if (bitmapData.pixelData == null || width <= 0 || height <= 0
+                || numPixels > (Long.MAX_VALUE / 4)) {
+            return null;
+        }
+
+        // TODO(junwei.fu): https://crbug.com/684921 support other bitmap pixel formats.
+        if (bitmapData.colorType != ColorType.RGBA_8888
+                && bitmapData.colorType != ColorType.BGRA_8888) {
+            return null;
+        }
+
+        ByteBuffer imageBuffer = ByteBuffer.wrap(bitmapData.pixelData);
+        if (imageBuffer.capacity() <= 0) {
+            return null;
+        }
+
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        bitmap.copyPixelsFromBuffer(imageBuffer);
+
+        return bitmap;
+    }
+
+    public static Frame convertToFrame(org.chromium.skia.mojom.Bitmap bitmapData) {
+        Bitmap bitmap = convertToBitmap(bitmapData);
+        if (bitmap == null) {
+            return null;
+        }
+
+        try {
+            // This constructor implies a pixel format conversion to YUV.
+            return new Frame.Builder().setBitmap(bitmap).build();
+        } catch (IllegalArgumentException | IllegalStateException ex) {
+            return null;
+        }
+    }
+}
diff --git a/services/shape_detection/android/java/src/org/chromium/shape_detection/FaceDetectionImpl.java b/services/shape_detection/android/java/src/org/chromium/shape_detection/FaceDetectionImpl.java
index 4d88df1..cb94456 100644
--- a/services/shape_detection/android/java/src/org/chromium/shape_detection/FaceDetectionImpl.java
+++ b/services/shape_detection/android/java/src/org/chromium/shape_detection/FaceDetectionImpl.java
@@ -10,18 +10,13 @@
 import android.media.FaceDetector.Face;
 import android.os.AsyncTask;
 
-import org.chromium.base.Log;
 import org.chromium.gfx.mojom.RectF;
 import org.chromium.mojo.system.MojoException;
-import org.chromium.mojo.system.SharedBufferHandle;
-import org.chromium.mojo.system.SharedBufferHandle.MapFlags;
 import org.chromium.shape_detection.mojom.FaceDetection;
 import org.chromium.shape_detection.mojom.FaceDetectionResult;
 import org.chromium.shape_detection.mojom.FaceDetectorOptions;
 import org.chromium.shape_detection.mojom.Landmark;
 
-import java.nio.ByteBuffer;
-
 /**
  * Android implementation of the FaceDetection service defined in
  * services/shape_detection/public/interfaces/facedetection.mojom
@@ -38,32 +33,11 @@
     }
 
     @Override
-    public void detect(SharedBufferHandle frameData, final int width, final int height,
-            final DetectResponse callback) {
-        final long numPixels = (long) width * height;
-        // TODO(xianglu): https://crbug.com/670028 homogeneize overflow checking.
-        if (!frameData.isValid() || width <= 0 || height <= 0 || numPixels > (Long.MAX_VALUE / 4)) {
-            Log.d(TAG, "Invalid argument(s).");
-            callback.call(new FaceDetectionResult[0]);
-            return;
-        }
-
-        ByteBuffer imageBuffer = frameData.map(0, numPixels * 4, MapFlags.none());
-        if (imageBuffer.capacity() <= 0) {
-            Log.d(TAG, "Failed to map from SharedBufferHandle.");
-            callback.call(new FaceDetectionResult[0]);
-            return;
-        }
-
-        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-
-        // An int array is needed to construct a Bitmap. However the Bytebuffer
-        // we get from |sharedBufferHandle| is directly allocated and does not
-        // have a supporting array. Therefore we need to copy from |imageBuffer|
-        // to create this intermediate Bitmap.
-        // TODO(xianglu): Consider worker pool as appropriate threads.
-        // http://crbug.com/655814
-        bitmap.copyPixelsFromBuffer(imageBuffer);
+    public void detect(org.chromium.skia.mojom.Bitmap bitmapData, final DetectResponse callback) {
+        // TODO(junwei.fu): Use |bitmapData| directly for |unPremultipliedBitmap| to spare a copy
+        // if the bitmap pixel format is RGB_565, the ARGB_8888 Bitmap doesn't need to be created
+        // in this case, https://crbug.com/684930.
+        Bitmap bitmap = BitmapUtils.convertToBitmap(bitmapData);
 
         // A Bitmap must be in 565 format for findFaces() to work. See
         // http://androidxref.com/7.0.0_r1/xref/frameworks/base/media/java/android/media/FaceDetector.java#124
@@ -74,6 +48,8 @@
         // original image is premultiplied. We can use getPixels() which does
         // the unmultiplication while copying to a new array. See
         // http://androidxref.com/7.0.0_r1/xref/frameworks/base/graphics/java/android/graphics/Bitmap.java#538
+        final int width = bitmapData.width;
+        final int height = bitmapData.height;
         int[] pixels = new int[width * height];
         bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
         final Bitmap unPremultipliedBitmap =
diff --git a/services/shape_detection/android/java/src/org/chromium/shape_detection/FaceDetectionImplGmsCore.java b/services/shape_detection/android/java/src/org/chromium/shape_detection/FaceDetectionImplGmsCore.java
index 12f18dbb..1c8b508 100644
--- a/services/shape_detection/android/java/src/org/chromium/shape_detection/FaceDetectionImplGmsCore.java
+++ b/services/shape_detection/android/java/src/org/chromium/shape_detection/FaceDetectionImplGmsCore.java
@@ -16,7 +16,6 @@
 import org.chromium.base.Log;
 import org.chromium.gfx.mojom.RectF;
 import org.chromium.mojo.system.MojoException;
-import org.chromium.mojo.system.SharedBufferHandle;
 import org.chromium.shape_detection.mojom.FaceDetection;
 import org.chromium.shape_detection.mojom.FaceDetectionResult;
 import org.chromium.shape_detection.mojom.FaceDetectorOptions;
@@ -57,8 +56,7 @@
     }
 
     @Override
-    public void detect(
-            SharedBufferHandle frameData, int width, int height, DetectResponse callback) {
+    public void detect(org.chromium.skia.mojom.Bitmap bitmapData, DetectResponse callback) {
         // The vision library will be downloaded the first time the API is used
         // on the device; this happens "fast", but it might have not completed,
         // bail in this case.
@@ -70,11 +68,11 @@
             options.fastMode = mFastMode;
             options.maxDetectedFaces = mMaxFaces;
             FaceDetectionImpl detector = new FaceDetectionImpl(options);
-            detector.detect(frameData, width, height, callback);
+            detector.detect(bitmapData, callback);
             return;
         }
 
-        Frame frame = SharedBufferUtils.convertToFrame(frameData, width, height);
+        Frame frame = BitmapUtils.convertToFrame(bitmapData);
         if (frame == null) {
             Log.e(TAG, "Error converting SharedMemory to Frame");
             callback.call(new FaceDetectionResult[0]);
diff --git a/services/shape_detection/android/java/src/org/chromium/shape_detection/SharedBufferUtils.java b/services/shape_detection/android/java/src/org/chromium/shape_detection/SharedBufferUtils.java
deleted file mode 100644
index 9112e26..0000000
--- a/services/shape_detection/android/java/src/org/chromium/shape_detection/SharedBufferUtils.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.shape_detection;
-
-import android.graphics.Bitmap;
-
-import com.google.android.gms.vision.Frame;
-
-import org.chromium.mojo.system.MojoException;
-import org.chromium.mojo.system.SharedBufferHandle;
-import org.chromium.mojo.system.SharedBufferHandle.MapFlags;
-
-import java.nio.ByteBuffer;
-
-/**
- * Utility class to convert a SharedBufferHandle to a GMS core YUV Frame.
- */
-public class SharedBufferUtils {
-    public static Frame convertToFrame(
-            SharedBufferHandle frameData, final int width, final int height) {
-        final long numPixels = (long) width * height;
-        // TODO(mcasas): https://crbug.com/670028 homogeneize overflow checking.
-        if (!frameData.isValid() || width <= 0 || height <= 0 || numPixels > (Long.MAX_VALUE / 4)) {
-            return null;
-        }
-
-        // Mapping |frameData| will fail if the intended mapped size is larger
-        // than its actual capacity, which is limited by the appropriate
-        // mojo::edk::Configuration entry.
-        ByteBuffer imageBuffer = frameData.map(0, numPixels * 4, MapFlags.none());
-        if (imageBuffer.capacity() <= 0) {
-            return null;
-        }
-
-        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-        bitmap.copyPixelsFromBuffer(imageBuffer);
-        try {
-            frameData.unmap(imageBuffer);
-            frameData.close();
-        } catch (MojoException e) {
-        }
-
-        try {
-            // This constructor implies a pixel format conversion to YUV.
-            return new Frame.Builder().setBitmap(bitmap).build();
-        } catch (IllegalArgumentException | IllegalStateException ex) {
-            return null;
-        }
-    }
-}
diff --git a/services/shape_detection/android/java/src/org/chromium/shape_detection/TextDetectionImpl.java b/services/shape_detection/android/java/src/org/chromium/shape_detection/TextDetectionImpl.java
index 5a6f94e7..4d9354b5 100644
--- a/services/shape_detection/android/java/src/org/chromium/shape_detection/TextDetectionImpl.java
+++ b/services/shape_detection/android/java/src/org/chromium/shape_detection/TextDetectionImpl.java
@@ -17,7 +17,6 @@
 import org.chromium.base.Log;
 import org.chromium.gfx.mojom.RectF;
 import org.chromium.mojo.system.MojoException;
-import org.chromium.mojo.system.SharedBufferHandle;
 import org.chromium.services.service_manager.InterfaceFactory;
 import org.chromium.shape_detection.mojom.TextDetection;
 import org.chromium.shape_detection.mojom.TextDetectionResult;
@@ -36,8 +35,7 @@
     }
 
     @Override
-    public void detect(
-            SharedBufferHandle frameData, int width, int height, DetectResponse callback) {
+    public void detect(org.chromium.skia.mojom.Bitmap bitmapData, DetectResponse callback) {
         if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(
                     ContextUtils.getApplicationContext())
                 != ConnectionResult.SUCCESS) {
@@ -55,7 +53,7 @@
             return;
         }
 
-        Frame frame = SharedBufferUtils.convertToFrame(frameData, width, height);
+        Frame frame = BitmapUtils.convertToFrame(bitmapData);
         if (frame == null) {
             Log.e(TAG, "Error converting SharedMemory to Frame");
             callback.call(new TextDetectionResult[0]);
diff --git a/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java b/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java
new file mode 100644
index 0000000..56d87fc
--- /dev/null
+++ b/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java
@@ -0,0 +1,81 @@
+// 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.shape_detection;
+
+import static org.junit.Assert.assertNull;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLog;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.skia.mojom.Bitmap;
+import org.chromium.skia.mojom.ColorType;
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
+/**
+ * Test suite for conversion-to-Frame utils.
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class BitmapUtilsTest {
+    private static final int VALID_WIDTH = 1;
+    private static final int VALID_HEIGHT = 1;
+    private static final int INVALID_WIDTH = 0;
+    private static final long NUM_BYTES = VALID_WIDTH * VALID_HEIGHT * 4;
+    private static final byte[] EMPTY_DATA = new byte[0];
+
+    public BitmapUtilsTest() {}
+
+    @Before
+    public void setUp() {
+        ShadowLog.stream = System.out;
+        MockitoAnnotations.initMocks(this);
+    }
+
+    /**
+     * Verify conversion fails if the Bitmap is invalid.
+     */
+    @Test
+    @Feature({"ShapeDetection"})
+    public void testConversionFailsWithInvalidBitmap() {
+        Bitmap bitmap = new Bitmap();
+        bitmap.pixelData = null;
+
+        assertNull(BitmapUtils.convertToFrame(bitmap));
+    }
+
+    /**
+     * Verify conversion fails if the sent dimensions are ugly.
+     */
+    @Test
+    @Feature({"ShapeDetection"})
+    public void testConversionFailsWithInvalidDimensions() {
+        Bitmap bitmap = new Bitmap();
+        bitmap.pixelData = EMPTY_DATA;
+        bitmap.width = INVALID_WIDTH;
+        bitmap.height = VALID_HEIGHT;
+
+        assertNull(BitmapUtils.convertToFrame(bitmap));
+    }
+
+    /**
+     * Verify conversion fails if Bitmap fails to wrap().
+     */
+    @Test
+    @Feature({"ShapeDetection"})
+    public void testConversionFailsWithWronglyWrappedData() {
+        Bitmap bitmap = new Bitmap();
+        bitmap.pixelData = EMPTY_DATA;
+        bitmap.width = VALID_WIDTH;
+        bitmap.height = VALID_HEIGHT;
+        bitmap.colorType = ColorType.RGBA_8888;
+
+        assertNull(BitmapUtils.convertToFrame(bitmap));
+    }
+}
diff --git a/services/shape_detection/android/junit/src/org/chromium/shape_detection/SharedBufferUtilsTest.java b/services/shape_detection/android/junit/src/org/chromium/shape_detection/SharedBufferUtilsTest.java
deleted file mode 100644
index 6078c0fb..0000000
--- a/services/shape_detection/android/junit/src/org/chromium/shape_detection/SharedBufferUtilsTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.shape_detection;
-
-import static org.junit.Assert.assertNull;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLog;
-
-import org.chromium.base.test.util.Feature;
-import org.chromium.mojo.system.SharedBufferHandle;
-import org.chromium.mojo.system.SharedBufferHandle.MapFlags;
-import org.chromium.testing.local.LocalRobolectricTestRunner;
-
-import java.nio.ByteBuffer;
-
-/**
- * Test suite for conversion-to-Frame utils.
- */
-@RunWith(LocalRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class SharedBufferUtilsTest {
-    private static final int VALID_WIDTH = 1;
-    private static final int VALID_HEIGHT = 1;
-    private static final int INVALID_WIDTH = 0;
-    private static final long NUM_BYTES = VALID_WIDTH * VALID_HEIGHT * 4;
-
-    public SharedBufferUtilsTest() {}
-
-    @Before
-    public void setUp() {
-        ShadowLog.stream = System.out;
-        MockitoAnnotations.initMocks(this);
-    }
-
-    /**
-     * Verify conversion fails if the SharedBufferHandle is invalid.
-     */
-    @Test
-    @Feature({"ShapeDetection"})
-    public void testConversionFailsWithInvalidHandle() {
-        SharedBufferHandle handle = Mockito.mock(SharedBufferHandle.class);
-        Mockito.when(handle.isValid()).thenReturn(false);
-
-        assertNull(SharedBufferUtils.convertToFrame(handle, VALID_WIDTH, VALID_HEIGHT));
-    }
-
-    /**
-     * Verify conversion fails if the sent dimensions are ugly.
-     */
-    @Test
-    @Feature({"ShapeDetection"})
-    public void testConversionFailsWithInvalidDimensions() {
-        SharedBufferHandle handle = Mockito.mock(SharedBufferHandle.class);
-        Mockito.when(handle.isValid()).thenReturn(true);
-
-        assertNull(SharedBufferUtils.convertToFrame(handle, INVALID_WIDTH, VALID_HEIGHT));
-    }
-
-    /**
-     * Verify conversion fails if SharedBufferHandle fails to map().
-     */
-    @Test
-    @Feature({"ShapeDetection"})
-    public void testConversionFailsWithWronglyMappedBuffer() {
-        SharedBufferHandle handle = Mockito.mock(SharedBufferHandle.class);
-        Mockito.when(handle.isValid()).thenReturn(true);
-        Mockito.when(handle.map(Mockito.eq(0L), Mockito.eq(NUM_BYTES), Mockito.any(MapFlags.class)))
-                .thenReturn(ByteBuffer.allocate(0));
-
-        assertNull(SharedBufferUtils.convertToFrame(handle, VALID_WIDTH, VALID_HEIGHT));
-    }
-}
diff --git a/services/shape_detection/barcode_detection_impl_mac.h b/services/shape_detection/barcode_detection_impl_mac.h
index a7779897..6a5609a 100644
--- a/services/shape_detection/barcode_detection_impl_mac.h
+++ b/services/shape_detection/barcode_detection_impl_mac.h
@@ -7,6 +7,7 @@
 
 #include "base/mac/scoped_nsobject.h"
 #include "services/shape_detection/public/interfaces/barcodedetection.mojom.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 
 @class CIDetector;
 
@@ -18,9 +19,7 @@
   BarcodeDetectionImplMac();
   ~BarcodeDetectionImplMac() override;
 
-  void Detect(mojo::ScopedSharedBufferHandle frame_data,
-              uint32_t width,
-              uint32_t height,
+  void Detect(const SkBitmap& bitmap,
               const shape_detection::mojom::BarcodeDetection::DetectCallback&
                   callback) override;
 
diff --git a/services/shape_detection/barcode_detection_impl_mac.mm b/services/shape_detection/barcode_detection_impl_mac.mm
index 777945f..1aef1a2f 100644
--- a/services/shape_detection/barcode_detection_impl_mac.mm
+++ b/services/shape_detection/barcode_detection_impl_mac.mm
@@ -51,22 +51,20 @@
 
 BarcodeDetectionImplMac::~BarcodeDetectionImplMac() {}
 
-void BarcodeDetectionImplMac::Detect(mojo::ScopedSharedBufferHandle frame_data,
-                                     uint32_t width,
-                                     uint32_t height,
+void BarcodeDetectionImplMac::Detect(const SkBitmap& bitmap,
                                      const DetectCallback& callback) {
   media::ScopedResultCallback<DetectCallback> scoped_callback(
       base::Bind(&RunCallbackWithBarcodes, callback),
       base::Bind(&RunCallbackWithNoBarcodes));
 
-  base::scoped_nsobject<CIImage> ci_image =
-      CreateCIImageFromSharedMemory(std::move(frame_data), width, height);
+  base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap);
   if (!ci_image)
     return;
 
   NSArray* const features = [detector_ featuresInImage:ci_image];
 
   std::vector<mojom::BarcodeDetectionResultPtr> results;
+  const int height = bitmap.height();
   for (CIQRCodeFeature* const f in features) {
     shape_detection::mojom::BarcodeDetectionResultPtr result =
         shape_detection::mojom::BarcodeDetectionResult::New();
diff --git a/services/shape_detection/barcode_detection_impl_mac_unittest.mm b/services/shape_detection/barcode_detection_impl_mac_unittest.mm
index 3184083..b30879c 100644
--- a/services/shape_detection/barcode_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/barcode_detection_impl_mac_unittest.mm
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/utils/mac/SkCGUtils.h"
 #include "ui/gl/gl_switches.h"
 
 namespace shape_detection {
@@ -65,7 +66,6 @@
 
   const gfx::Size size([qr_code_image extent].size.width,
                        [qr_code_image extent].size.height);
-  const int num_bytes = size.GetArea() * 4 /* bytes per pixel */;
 
   base::scoped_nsobject<CIContext> context([[CIContext alloc] init]);
 
@@ -74,30 +74,16 @@
   EXPECT_EQ(static_cast<size_t>(size.width()), CGImageGetWidth(cg_image));
   EXPECT_EQ(static_cast<size_t>(size.height()), CGImageGetHeight(cg_image));
 
-  base::ScopedCFTypeRef<CFDataRef> raw_cg_image_data(
-      CGDataProviderCopyData(CGImageGetDataProvider(cg_image)));
-  EXPECT_TRUE(CFDataGetBytePtr(raw_cg_image_data));
-  EXPECT_EQ(num_bytes, CFDataGetLength(raw_cg_image_data));
-
-  // Generate a new ScopedSharedBufferHandle of the aproppriate size, map it and
-  // copy the generated qr code image pixels into it.
-  mojo::ScopedSharedBufferHandle handle =
-      mojo::SharedBufferHandle::Create(num_bytes);
-  ASSERT_TRUE(handle->is_valid());
-
-  mojo::ScopedSharedBufferMapping mapping = handle->Map(num_bytes);
-  ASSERT_TRUE(mapping);
-
-  memcpy(mapping.get(), CFDataGetBytePtr(raw_cg_image_data), num_bytes);
+  SkBitmap bitmap;
+  ASSERT_TRUE(SkCreateBitmapFromCGImage(&bitmap, cg_image));
 
   base::RunLoop run_loop;
   base::Closure quit_closure = run_loop.QuitClosure();
   // Send the image Detect() and expect the response in callback.
   EXPECT_CALL(*this, Detection(1, kInfoString))
       .WillOnce(RunClosure(quit_closure));
-  impl_.Detect(std::move(handle), size.width(), size.height(),
-               base::Bind(&BarcodeDetectionImplMacTest::DetectCallback,
-                          base::Unretained(this)));
+  impl_.Detect(bitmap, base::Bind(&BarcodeDetectionImplMacTest::DetectCallback,
+                                  base::Unretained(this)));
 
   run_loop.Run();
 }
diff --git a/services/shape_detection/detection_utils_mac.h b/services/shape_detection/detection_utils_mac.h
index 98e3c0f..69e46426 100644
--- a/services/shape_detection/detection_utils_mac.h
+++ b/services/shape_detection/detection_utils_mac.h
@@ -9,15 +9,14 @@
 
 #include "base/mac/scoped_nsobject.h"
 #include "services/shape_detection/public/interfaces/barcodedetection.mojom.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 
 namespace shape_detection {
 
 // Takes a ScopedSharedBufferHandle with dimensions and produces a new CIImage
 // with the same contents, or a null scoped_nsobject is something goes wrong.
-base::scoped_nsobject<CIImage> CreateCIImageFromSharedMemory(
-    mojo::ScopedSharedBufferHandle frame_data,
-    uint32_t width,
-    uint32_t height);
+base::scoped_nsobject<CIImage> CreateCIImageFromSkBitmap(
+    const SkBitmap& bitmap);
 
 }  // namespace shape_detection
 
diff --git a/services/shape_detection/detection_utils_mac.mm b/services/shape_detection/detection_utils_mac.mm
index 4e87812e99..554cd7e5 100644
--- a/services/shape_detection/detection_utils_mac.mm
+++ b/services/shape_detection/detection_utils_mac.mm
@@ -9,61 +9,31 @@
 #include "base/memory/shared_memory.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/shape_detection/barcode_detection_impl.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "third_party/skia/include/utils/mac/SkCGUtils.h"
 
 namespace shape_detection {
 
-// These formats are available but not public until Mac 10.11.
-#if !defined(MAC_OS_X_VERSION_10_11) || \
-    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11
-const int kCIFormatRGBA8 = 24;
-#else
-//static_assert(kCIFormatRGBA8 == 24, "RGBA8 format enum index.");
-#endif
-
-base::scoped_nsobject<CIImage> CreateCIImageFromSharedMemory(
-    mojo::ScopedSharedBufferHandle frame_data,
-    uint32_t width,
-    uint32_t height) {
+base::scoped_nsobject<CIImage> CreateCIImageFromSkBitmap(
+    const SkBitmap& bitmap) {
   base::CheckedNumeric<uint32_t> num_pixels =
-      base::CheckedNumeric<uint32_t>(width) * height;
+      base::CheckedNumeric<uint32_t>(bitmap.width()) * bitmap.height();
   base::CheckedNumeric<uint32_t> num_bytes = num_pixels * 4;
   if (!num_bytes.IsValid()) {
     DLOG(ERROR) << "Data overflow";
     return base::scoped_nsobject<CIImage>();
   }
 
-  base::SharedMemoryHandle memory_handle;
-  size_t memory_size = 0;
-  bool read_only_flag = false;
-  const MojoResult result = mojo::UnwrapSharedMemoryHandle(
-      std::move(frame_data), &memory_handle, &memory_size, &read_only_flag);
-  DCHECK_EQ(MOJO_RESULT_OK, result) << "Failed to unwrap SharedBufferHandle";
-  if (!memory_size || memory_size != num_bytes.ValueOrDie()) {
-    DLOG(ERROR) << "Invalid image size";
+  // First convert SkBitmap to CGImageRef.
+  base::ScopedCFTypeRef<CGImageRef> cg_image(
+      SkCreateCGImageRefWithColorspace(bitmap, NULL));
+  if (!cg_image) {
+    DLOG(ERROR) << "Failed to create CGImageRef";
     return base::scoped_nsobject<CIImage>();
   }
 
-  auto shared_memory =
-      base::MakeUnique<base::SharedMemory>(memory_handle, true /* read_only */);
-  if (!shared_memory->Map(memory_size)) {
-    DLOG(ERROR) << "Failed to map bytes from shared memory";
-    return base::scoped_nsobject<CIImage>();
-  }
-
-  NSData* byte_data = [NSData dataWithBytesNoCopy:shared_memory->memory()
-                                           length:num_bytes.ValueOrDie()
-                                     freeWhenDone:NO];
-
-  base::ScopedCFTypeRef<CGColorSpaceRef> colorspace(
-      CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
-
-  // CIImage will return nil if RGBA8 is not supported in a certain version.
-  base::scoped_nsobject<CIImage> ci_image([[CIImage alloc]
-      initWithBitmapData:byte_data
-             bytesPerRow:width * 4
-                    size:CGSizeMake(width, height)
-                  format:kCIFormatRGBA8
-              colorSpace:colorspace]);
+  base::scoped_nsobject<CIImage> ci_image(
+      [[CIImage alloc] initWithCGImage:cg_image]);
   if (!ci_image) {
     DLOG(ERROR) << "Failed to create CIImage";
     return base::scoped_nsobject<CIImage>();
diff --git a/services/shape_detection/face_detection_impl_mac.h b/services/shape_detection/face_detection_impl_mac.h
index fb978c7..459ffa7 100644
--- a/services/shape_detection/face_detection_impl_mac.h
+++ b/services/shape_detection/face_detection_impl_mac.h
@@ -7,6 +7,7 @@
 
 #include "base/mac/scoped_nsobject.h"
 #include "services/shape_detection/public/interfaces/facedetection.mojom.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 
 @class CIDetector;
 
@@ -18,9 +19,7 @@
       shape_detection::mojom::FaceDetectorOptionsPtr options);
   ~FaceDetectionImplMac() override;
 
-  void Detect(mojo::ScopedSharedBufferHandle frame_data,
-              uint32_t width,
-              uint32_t height,
+  void Detect(const SkBitmap& bitmap,
               const shape_detection::mojom::FaceDetection::DetectCallback&
                   callback) override;
 
diff --git a/services/shape_detection/face_detection_impl_mac.mm b/services/shape_detection/face_detection_impl_mac.mm
index 4057a74..7ff5856 100644
--- a/services/shape_detection/face_detection_impl_mac.mm
+++ b/services/shape_detection/face_detection_impl_mac.mm
@@ -47,20 +47,18 @@
 
 FaceDetectionImplMac::~FaceDetectionImplMac() {}
 
-void FaceDetectionImplMac::Detect(mojo::ScopedSharedBufferHandle frame_data,
-                                  uint32_t width,
-                                  uint32_t height,
+void FaceDetectionImplMac::Detect(const SkBitmap& bitmap,
                                   const DetectCallback& callback) {
   media::ScopedResultCallback<DetectCallback> scoped_callback(
       base::Bind(&RunCallbackWithFaces, callback),
       base::Bind(&RunCallbackWithNoFaces));
 
-  base::scoped_nsobject<CIImage> ci_image =
-      CreateCIImageFromSharedMemory(std::move(frame_data), width, height);
+  base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap);
   if (!ci_image)
     return;
 
   NSArray* const features = [detector_ featuresInImage:ci_image];
+  const int height = bitmap.height();
 
   std::vector<mojom::FaceDetectionResultPtr> results;
   for (CIFaceFeature* const f in features) {
diff --git a/services/shape_detection/face_detection_impl_mac_unittest.mm b/services/shape_detection/face_detection_impl_mac_unittest.mm
index d5f5275..c8c2ed6b 100644
--- a/services/shape_detection/face_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/face_detection_impl_mac_unittest.mm
@@ -82,24 +82,12 @@
   const int num_bytes = size.GetArea() * 4 /* bytes per pixel */;
   ASSERT_EQ(num_bytes, image->computeSize64());
 
-  // Generate a new ScopedSharedBufferHandle of the aproppriate size, map it and
-  // copy the image pixels into it.
-  mojo::ScopedSharedBufferHandle handle =
-      mojo::SharedBufferHandle::Create(num_bytes);
-  ASSERT_TRUE(handle->is_valid());
-
-  mojo::ScopedSharedBufferMapping mapping = handle->Map(num_bytes);
-  ASSERT_TRUE(mapping);
-
-  memcpy(mapping.get(), image->getPixels(), num_bytes);
-
   base::RunLoop run_loop;
   base::Closure quit_closure = run_loop.QuitClosure();
   // Send the image to Detect() and expect the response in callback.
   EXPECT_CALL(*this, Detection()).WillOnce(RunClosure(quit_closure));
-  impl_->Detect(std::move(handle), size.width(), size.height(),
-                base::Bind(&FaceDetectionImplMacTest::DetectCallback,
-                           base::Unretained(this)));
+  impl_->Detect(*image, base::Bind(&FaceDetectionImplMacTest::DetectCallback,
+                                   base::Unretained(this)));
 
   run_loop.Run();
 }
diff --git a/services/shape_detection/public/interfaces/BUILD.gn b/services/shape_detection/public/interfaces/BUILD.gn
index 22266aec..432da86 100644
--- a/services/shape_detection/public/interfaces/BUILD.gn
+++ b/services/shape_detection/public/interfaces/BUILD.gn
@@ -14,6 +14,7 @@
   ]
 
   public_deps = [
+    "//skia/public/interfaces",
     "//ui/gfx/geometry/mojo",
   ]
 
diff --git a/services/shape_detection/public/interfaces/barcodedetection.mojom b/services/shape_detection/public/interfaces/barcodedetection.mojom
index 27f95ecd..5ae9aef5 100644
--- a/services/shape_detection/public/interfaces/barcodedetection.mojom
+++ b/services/shape_detection/public/interfaces/barcodedetection.mojom
@@ -6,6 +6,7 @@
 
 module shape_detection.mojom;
 
+import "skia/public/interfaces/bitmap.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
 struct BarcodeDetectionResult {
@@ -17,9 +18,7 @@
 };
 
 interface BarcodeDetection {
-  // |frame_data| contains tightly packed image pixels in ARGB32 format,
-  // row-major order.
-  // TODO(mcasas): Consider using mojo::Bitmap here, https://crbug.com/665488.
-  Detect(handle<shared_buffer> frame_data, uint32 width, uint32 height)
+  // |bitmap_data| contains tightly packed image pixels in row-major order.
+  Detect(skia.mojom.Bitmap bitmap_data)
     => (array<BarcodeDetectionResult> results);
 };
diff --git a/services/shape_detection/public/interfaces/facedetection.mojom b/services/shape_detection/public/interfaces/facedetection.mojom
index dda46fa9..eb90fa99 100644
--- a/services/shape_detection/public/interfaces/facedetection.mojom
+++ b/services/shape_detection/public/interfaces/facedetection.mojom
@@ -6,6 +6,7 @@
 
 module shape_detection.mojom;
 
+import "skia/public/interfaces/bitmap.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
 // https://wicg.github.io/shape-detection-api/#enumdef-landmarktype
@@ -31,9 +32,7 @@
 };
 
 interface FaceDetection {
-  // |frame_data| contains tightly packed image pixels in ARGB32 format,
-  // row-major order.
-  // TODO(mcasas): Consider using mojo::Bitmap here, https://crbug.com/665488.
-  Detect(handle<shared_buffer> frame_data, uint32 width, uint32 height)
+  // |bitmap_data| contains tightly packed image pixels in row-major order.
+  Detect(skia.mojom.Bitmap bitmap_data)
     => (array<FaceDetectionResult> results);
 };
diff --git a/services/shape_detection/public/interfaces/textdetection.mojom b/services/shape_detection/public/interfaces/textdetection.mojom
index 6e8bb01..7a0fed5 100644
--- a/services/shape_detection/public/interfaces/textdetection.mojom
+++ b/services/shape_detection/public/interfaces/textdetection.mojom
@@ -4,6 +4,7 @@
 
 module shape_detection.mojom;
 
+import "skia/public/interfaces/bitmap.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
 struct TextDetectionResult {
@@ -12,8 +13,7 @@
 };
 
 interface TextDetection {
-  // |frame_data| contains tightly packed image pixels in ARGB32 format,
-  // row-major order.
-  Detect(handle<shared_buffer> frame_data, uint32 width, uint32 height)
+  // |bitmap_data| contains tightly packed image pixels in row-major order.
+  Detect(skia.mojom.Bitmap bitmap_data)
     => (array<TextDetectionResult> results);
 };
diff --git a/services/shape_detection/text_detection_impl_mac.h b/services/shape_detection/text_detection_impl_mac.h
index d86be927..738d8da 100644
--- a/services/shape_detection/text_detection_impl_mac.h
+++ b/services/shape_detection/text_detection_impl_mac.h
@@ -17,9 +17,7 @@
   TextDetectionImplMac();
   ~TextDetectionImplMac() override;
 
-  void Detect(mojo::ScopedSharedBufferHandle frame_data,
-              uint32_t width,
-              uint32_t height,
+  void Detect(const SkBitmap& bitmap,
               const mojom::TextDetection::DetectCallback& callback) override;
 
  private:
diff --git a/services/shape_detection/text_detection_impl_mac.mm b/services/shape_detection/text_detection_impl_mac.mm
index 95ca50a..b47744e 100644
--- a/services/shape_detection/text_detection_impl_mac.mm
+++ b/services/shape_detection/text_detection_impl_mac.mm
@@ -50,22 +50,20 @@
 
 TextDetectionImplMac::~TextDetectionImplMac() {}
 
-void TextDetectionImplMac::Detect(mojo::ScopedSharedBufferHandle frame_data,
-                                  uint32_t width,
-                                  uint32_t height,
+void TextDetectionImplMac::Detect(const SkBitmap& bitmap,
                                   const DetectCallback& callback) {
   DCHECK(base::mac::IsAtLeastOS10_11());
   media::ScopedResultCallback<DetectCallback> scoped_callback(
       base::Bind(&RunCallbackWithResults, callback),
       base::Bind(&RunCallbackWithNoResults));
 
-  base::scoped_nsobject<CIImage> ci_image =
-      CreateCIImageFromSharedMemory(std::move(frame_data), width, height);
+  base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap);
   if (!ci_image)
     return;
 
   NSArray* const features = [detector_ featuresInImage:ci_image];
 
+  const int height = bitmap.height();
   std::vector<mojom::TextDetectionResultPtr> results;
   for (CIRectangleFeature* const f in features) {
     // CIRectangleFeature only has bounding box information.
diff --git a/services/shape_detection/text_detection_impl_mac_unittest.mm b/services/shape_detection/text_detection_impl_mac_unittest.mm
index f316d8e..71def0f 100644
--- a/services/shape_detection/text_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/text_detection_impl_mac_unittest.mm
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/utils/mac/SkCGUtils.h"
 #include "ui/gl/gl_switches.h"
 
 namespace shape_detection {
@@ -82,29 +83,15 @@
   EXPECT_EQ(static_cast<size_t>(width), CGImageGetWidth(cg_image));
   EXPECT_EQ(static_cast<size_t>(height), CGImageGetHeight(cg_image));
 
-  base::ScopedCFTypeRef<CFDataRef> raw_cg_image_data(
-      CGDataProviderCopyData(CGImageGetDataProvider(cg_image)));
-  EXPECT_TRUE(CFDataGetBytePtr(raw_cg_image_data));
-  const int num_bytes = width * height * 4;
-  EXPECT_EQ(num_bytes, CFDataGetLength(raw_cg_image_data));
-
-  // Generate a new ScopedSharedBufferHandle of the aproppriate size, map it and
-  // copy the generated text image pixels into it.
-  auto handle = mojo::SharedBufferHandle::Create(num_bytes);
-  ASSERT_TRUE(handle->is_valid());
-
-  mojo::ScopedSharedBufferMapping mapping = handle->Map(num_bytes);
-  ASSERT_TRUE(mapping);
-
-  memcpy(mapping.get(), CFDataGetBytePtr(raw_cg_image_data), num_bytes);
+  SkBitmap bitmap;
+  ASSERT_TRUE(SkCreateBitmapFromCGImage(&bitmap, cg_image));
 
   base::RunLoop run_loop;
   base::Closure quit_closure = run_loop.QuitClosure();
   // Send the image to Detect() and expect the response in callback.
   EXPECT_CALL(*this, Detection(1)).WillOnce(RunClosure(quit_closure));
-  impl_.Detect(std::move(handle), width, height,
-               base::Bind(&TextDetectionImplMacTest::DetectCallback,
-                          base::Unretained(this)));
+  impl_.Detect(bitmap, base::Bind(&TextDetectionImplMacTest::DetectCallback,
+                                  base::Unretained(this)));
 
   run_loop.Run();
 }
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 4145aceb..b8874850 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -18931,10 +18931,14 @@
 crbug.com/591099 mhtml/malformed_mhtml_no_footer.mht [ Failure ]
 crbug.com/591099 netinfo/basic-operation.html [ Failure ]
 crbug.com/591099 netinfo/connection-types.html [ Failure ]
+crbug.com/591099 netinfo/estimate-basic-operation.html [ Failure ]
+crbug.com/591099 netinfo/estimate-multiple-frames.html [ Failure ]
+crbug.com/591099 netinfo/estimate-web-worker.html [ Failure ]
 crbug.com/591099 netinfo/gc-frame-listeners.html [ Failure ]
 crbug.com/591099 netinfo/gc-unused-listeners.html [ Failure ]
 crbug.com/591099 netinfo/gc-used-listeners.html [ Failure ]
 crbug.com/591099 netinfo/multiple-frames.html [ Failure ]
+crbug.com/591099 netinfo/network-quality.html [ Failure ]
 crbug.com/591099 netinfo/type-change-no-listener.html [ Failure ]
 crbug.com/591099 netinfo/unregister-during-event.html [ Failure ]
 crbug.com/591099 netinfo/web-worker.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 9045e0d5..d9aaf4f 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2512,6 +2512,7 @@
 crbug.com/713732 fast/dom/Window/dom-access-from-closure-window.html [ NeedsManualRebaseline ]
 crbug.com/713732 http/tests/serviceworker/chromium/frame-detached-by-navigation.html [ NeedsManualRebaseline ]
 crbug.com/713732 virtual/mojo-loading/http/tests/serviceworker/chromium/frame-detached-by-navigation.html [ NeedsManualRebaseline ]
+crbug.com/713732 virtual/off-main-thread-fetch/http/tests/serviceworker/chromium/frame-detached-by-navigation.html [ NeedsManualRebaseline ]
 
 # Crashes with DCHECK enabled, but not on normal Release builds.
 crbug.com/626703 external/wpt/workers/opaque-origin.html [ Failure Crash Timeout ]
diff --git a/third_party/WebKit/LayoutTests/css3/fonts/resources/style-matching-test.js b/third_party/WebKit/LayoutTests/css3/fonts/resources/style-matching-test.js
index 58a883fd..c5f964ba 100644
--- a/third_party/WebKit/LayoutTests/css3/fonts/resources/style-matching-test.js
+++ b/third_party/WebKit/LayoutTests/css3/fonts/resources/style-matching-test.js
@@ -183,14 +183,22 @@
         }
     }
 
-    async function platformFontsForElementWithSelector(selector)
+    function platformFontsForElementWithSelector(selector)
     {
-        var nodeId = await InspectorTest.requestNodeId(documentNodeId, selector);
-        await InspectorTest.sendCommandOrDie("CSS.enable", {});
-        var response = await InspectorTest.sendCommandOrDie("CSS.getPlatformFontsForNode",
-                                                            { nodeId: nodeId });
-        logResults(response);
-        nextTest();
+        InspectorTest.requestNodeId(documentNodeId, selector, onNodeId);
+
+        function onNodeId(nodeId)
+        {
+            InspectorTest.sendCommandOrDie("CSS.getPlatformFontsForNode",
+                                           { nodeId: nodeId },
+                                           onGotComputedFonts);
+        }
+
+        function onGotComputedFonts(response)
+        {
+            logResults(response);
+            nextTest();
+        }
     }
 
     function logResults(response)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
index a7f5ddda..c39113dc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
-<title>Embedded Enforcement: Required-CSP header.</title>
+<title>Embedded Enforcement: Sec-Required-CSP header.</title>
   <script src="/resources/testharness.js"></script>
   <script src="/resources/testharnessreport.js"></script>
   <script src="support/testharness-helper.sub.js"></script>
@@ -9,18 +9,44 @@
 <body>
   <script>
     var tests = [
-      { "name": "Required-CSP is not sent if `csp` attribute is not set on <iframe>.",
+      { "name": "Sec-Required-CSP is not sent if `csp` attribute is not set on <iframe>.",
         "csp": null,
         "expected":  null },
-      { "name": "Send Required-CSP when `csp` attribute of <iframe> is not empty.",
+      { "name": "Send Sec-Required-CSP when `csp` attribute of <iframe> is not empty.",
         "csp": "script-src 'unsafe-inline'",
         "expected":  "script-src 'unsafe-inline'" },
-      { "name": "Send Required-CSP Header on change of `src` attribute on iframe.",
+      { "name": "Send Sec-Required-CSP Header on change of `src` attribute on iframe.",
         "csp": "script-src 'unsafe-inline'",
         "expected":  "script-src 'unsafe-inline'" },
-      { "name": "Wrong value of `csp` should not trigger sending Required-CSP Header.",
+      { "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - gibberish csp",
         "csp": "completely wrong csp",
         "expected": null },
+      { "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - unknown policy name",
+        "csp": "invalid-policy-name http://example.com",
+        "expected": null },
+      { "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - unknown policy name in multiple directives",
+        "csp": "default-src http://example.com; invalid-policy-name http://example.com",
+        "expected": null },
+      { "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - misspeled 'none'",
+        "csp": "default-src 'non'",
+        "expected": null },
+      { "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - query values in path",
+        "csp": "script-src 127.0.0.1:8000/path?query=string",
+        "expected": null },
+      { "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - missing semicolon",
+        "csp": "script-src 'self' object-src 'self' style-src *",
+        "expected": null },
+      { "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - comma separated",
+        "csp": "script-src 'none', object-src 'none'",
+        "expected": null },
+      { "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - html encoded string",
+        // script-src 127.0.0.1:8000
+        "csp": "script-src &#x31;&#x32;&#x37;&#x2E;&#x30;&#x2E;&#x30;&#x2E;&#x31;&#x3A;&#x38;&#x30;&#x30;&#x30;",
+        "expected": null },
+      { "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - url encoded string",
+        // script-src 127.0.0.1:8000
+        "csp": "script-src%20127.0.0.1%3A8000",
+        "expected": null },
     ];
 
     tests.forEach(test => {
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom-protocol-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom-protocol-test.js
index 1be873c..e8ee26a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom-protocol-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom-protocol-test.js
@@ -3,44 +3,48 @@
 
 InspectorTest.trackGetChildNodesEvents = function(nodeInfo, callback)
 {
-  InspectorTest.eventHandler["DOM.setChildNodes"] = setChildNodes;
+    InspectorTest.eventHandler["DOM.setChildNodes"] = setChildNodes;
 
-  function setChildNodes(message)
-  {
-      var nodes = message.params.nodes;
-      for (var i = 0; i < nodes.length; ++i)
-        InspectorTest.addNode(nodeInfo, nodes[i]);
-      if (callback)
-        callback();
-  }
+    function setChildNodes(message)
+    {
+        var nodes = message.params.nodes;
+        for (var i = 0; i < nodes.length; ++i)
+            InspectorTest.addNode(nodeInfo, nodes[i]);
+        if (callback)
+            callback();
+    }
 }
 
 InspectorTest.addNode = function(nodeInfo, node)
 {
-  nodeInfo[node.nodeId] = node;
-  delete node.nodeId;
-  var children = node.children || [];
-  for (var i = 0; i < children.length; ++i)
-    InspectorTest.addNode(nodeInfo, children[i]);
-  var shadowRoots = node.shadowRoots || [];
-  for (var i = 0; i < shadowRoots.length; ++i)
-    InspectorTest.addNode(nodeInfo, shadowRoots[i]);
+    nodeInfo[node.nodeId] = node;
+    delete node.nodeId;
+    var children = node.children || [];
+    for (var i = 0; i < children.length; ++i)
+        InspectorTest.addNode(nodeInfo, children[i]);
+    var shadowRoots = node.shadowRoots || [];
+    for (var i = 0; i < shadowRoots.length; ++i)
+        InspectorTest.addNode(nodeInfo, shadowRoots[i]);
 }
 
-InspectorTest.requestDocumentNodeId = async function(callback)
+InspectorTest.requestDocumentNodeId = function(callback)
 {
-    var result = await InspectorTest.sendCommandOrDie("DOM.getDocument", {});
-    if (callback)
-      callback(result.root.nodeId);
-    return result.root.nodeId;
+    InspectorTest.sendCommandOrDie("DOM.getDocument", {}, onGotDocument);
+
+    function onGotDocument(result)
+    {
+        callback(result.root.nodeId);
+    }
 };
 
-InspectorTest.requestNodeId = async function(documentNodeId, selector, callback)
+InspectorTest.requestNodeId = function(documentNodeId, selector, callback)
 {
-    var result = await InspectorTest.sendCommandOrDie("DOM.querySelector", { "nodeId": documentNodeId , "selector": selector });
-    if (callback)
-      callback(result.nodeId);
-    return result.nodeId;
+    InspectorTest.sendCommandOrDie("DOM.querySelector", { "nodeId": documentNodeId , "selector": selector }, onGotNode);
+
+    function onGotNode(result)
+    {
+        callback(result.nodeId);
+    }
 };
 
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/resources/protocol-test.html b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/resources/protocol-test.html
index 1f3ce3c..510b441 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/resources/protocol-test.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/resources/protocol-test.html
@@ -62,9 +62,6 @@
 
 InspectorTest.sendCommandOrDie = function(command, properties, callback)
 {
-    var fulfill;
-    var result = new Promise(f => fulfill = f);
-
     InspectorTest.sendCommand(command, properties || {}, commandCallback);
     function commandCallback(msg)
     {
@@ -75,9 +72,7 @@
         }
         if (callback)
             callback(msg.result);
-        fulfill(msg.result);
     }
-    return result;
 }
 
 InspectorTest.sendCommandPromise = function(method, params)
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/css/css-get-platform-fonts.html b/third_party/WebKit/LayoutTests/inspector-protocol/css/css-get-platform-fonts.html
index bc8d880..616c5941 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/css/css-get-platform-fonts.html
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/css/css-get-platform-fonts.html
@@ -28,13 +28,20 @@
     }
 
 
-    async function platformFontsForElementWithSelector(selector, callback)
+    function platformFontsForElementWithSelector(selector, callback)
     {
-        var nodeId = await InspectorTest.requestNodeId(documentNodeId, selector);
-        await InspectorTest.sendCommandOrDie("CSS.enable", {  });
-        var response = await InspectorTest.sendCommandOrDie("CSS.getPlatformFontsForNode", { nodeId: nodeId });
-        dumpComputedFonts(response);
-        callback();
+        InspectorTest.requestNodeId(documentNodeId, selector, onNodeId);
+
+        function onNodeId(nodeId)
+        {
+            InspectorTest.sendCommandOrDie("CSS.getPlatformFontsForNode", { nodeId: nodeId }, onGotComputedFonts);
+        }
+
+        function onGotComputedFonts(response)
+        {
+            dumpComputedFonts(response);
+            callback();
+        }
     }
 
     function dumpComputedFonts(response)
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/css/css-set-inline-styleSheetText.html b/third_party/WebKit/LayoutTests/inspector-protocol/css/css-set-inline-styleSheetText.html
index 9667efb..44e8920 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/css/css-set-inline-styleSheetText.html
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/css/css-set-inline-styleSheetText.html
@@ -9,29 +9,47 @@
 
     InspectorTest.sendCommand("CSS.enable", {}, cssWasEnabled);
 
-    async function cssWasEnabled()
+    function cssWasEnabled()
     {
-        var result = await InspectorTest.sendCommandOrDie("DOM.getDocument", {});
+        InspectorTest.sendCommandOrDie("DOM.getDocument", {}, onGotDocument);
+    }
+
+    function onGotDocument(result)
+    {
         var root = result.root;
-        var node = await InspectorTest.sendCommandOrDie("DOM.querySelector", {
+        InspectorTest.sendCommandOrDie("DOM.querySelector", {
             nodeId: root.nodeId,
             selector: "#inliner"
-        });
+        }, onGotNode);
+    }
 
-        await InspectorTest.sendCommandOrDie("CSS.enable", {  });
+    function onGotNode(node)
+    {
+        InspectorTest.sendCommandOrDie("CSS.getInlineStylesForNode", { nodeId: node.nodeId }, onGotInlineStyles);
+    }
 
-        result = await InspectorTest.sendCommandOrDie("CSS.getInlineStylesForNode", { nodeId: node.nodeId });
+    function onGotInlineStyles(result)
+    {
         inlineStyleSheetId = result.inlineStyle.styleSheetId;
+        InspectorTest.sendCommandOrDie("CSS.getStyleSheetText", { styleSheetId: inlineStyleSheetId }, onReceiveStyleSheetText);
+    }
 
-        result = await InspectorTest.sendCommandOrDie("CSS.getStyleSheetText", { styleSheetId: inlineStyleSheetId });
+    function onReceiveStyleSheetText(result)
+    {
         InspectorTest.log(result.text);
-
-        result = await InspectorTest.sendCommandOrDie("CSS.setStyleSheetText", {
+        InspectorTest.sendCommandOrDie("CSS.setStyleSheetText", {
             styleSheetId: inlineStyleSheetId,
             text: "border: 1px solid black;"
-        });
+        }, onSetStyleSheetBody);
+    }
 
-        result = await InspectorTest.sendCommandOrDie("CSS.getStyleSheetText", { styleSheetId: inlineStyleSheetId });
+    function onSetStyleSheetBody(result)
+    {
+        InspectorTest.sendCommandOrDie("CSS.getStyleSheetText", { styleSheetId: inlineStyleSheetId }, onCheckStyleSheetBody);
+    }
+
+    function onCheckStyleSheetBody(result)
+    {
         InspectorTest.log(result.text);
         InspectorTest.completeTest();
     }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/css/pseudo-element-matching-selectors.html b/third_party/WebKit/LayoutTests/inspector-protocol/css/pseudo-element-matching-selectors.html
index b658c98..980b0285 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/css/pseudo-element-matching-selectors.html
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/css/pseudo-element-matching-selectors.html
@@ -8,37 +8,61 @@
     document.getElementById("style").textContent = "#for-pseudo:before { content: \"BEFORE\" }";
 }
 
-async function test()
+function test()
 {
     var nodeInfo = {};
     var childrenCallback;
 
     InspectorTest.eventHandler["DOM.setChildNodes"] = setChildNodes;
-    await InspectorTest.sendCommandOrDie("DOM.enable", {});
-    await InspectorTest.sendCommandOrDie("CSS.enable", {});
+    getDocument();
 
-    InspectorTest.log("\n=== Get the Document ===\n");
-    var result = await InspectorTest.sendCommandOrDie("DOM.getDocument", {});
-    var bodyId = result.root.children[0].children[1].nodeId;
+    function getDocument()
+    {
+        step({
+            name: "Get the Document",
+            command: "DOM.getDocument",
+            parameters: {},
+            callback: getImmediateChildren
+        });
+    };
 
-    InspectorTest.log("\n=== Get immediate children of the body ===\n");
-    result = await InspectorTest.sendCommandOrDie("DOM.requestChildNodes", {"nodeId": bodyId});
-    var node = findNodeById("for-pseudo");
-    var beforeNode = node.pseudoElements[0];
+    function getImmediateChildren(result)
+    {
+        var bodyId = result.root.children[0].children[1].nodeId;
+        childrenCallback = onChildrenRequested;
+        step({
+            name: "Get immediate children of the body",
+            command: "DOM.requestChildNodes",
+            parameters: {"nodeId": bodyId}
+        });
+    };
 
-    InspectorTest.log("\n=== Request matching styles for #for-pseudo::before ===\n");
-    result = await InspectorTest.sendCommandOrDie("CSS.getMatchedStylesForNode", {nodeId: beforeNode.nodeId});
-    var matchedRules = result.matchedCSSRules;
-    for (var i = 0; i < matchedRules.length; ++i) {
-        var match = matchedRules[i];
-        if (match.rule.selectorList.text === "#for-pseudo::before") {
-            InspectorTest.log("#for-pseudo::before matching the :before element: " + (match.matchingSelectors[0] === 0));
-            InspectorTest.completeTest();
-            return;
-        }
+    function onChildrenRequested()
+    {
+        var node = findNodeById("for-pseudo");
+        var beforeNode = node.pseudoElements[0];
+        step({
+            name: "Request matching styles for #for-pseudo::before",
+            command: "CSS.getMatchedStylesForNode",
+            parameters: {nodeId: beforeNode.nodeId},
+            callback: stylesReceived
+        });
     }
-    InspectorTest.log("#for-pseudo::before rule not received");
-    InspectorTest.completeTest();
+
+    function stylesReceived(result)
+    {
+        var matchedRules = result.matchedCSSRules;
+        for (var i = 0; i < matchedRules.length; ++i) {
+            var match = matchedRules[i];
+            if (match.rule.selectorList.text === "#for-pseudo::before") {
+                InspectorTest.log("#for-pseudo::before matching the :before element: " + (match.matchingSelectors[0] === 0));
+                InspectorTest.completeTest();
+                return;
+            }
+        }
+        InspectorTest.log("#for-pseudo::before rule not received");
+        InspectorTest.completeTest();
+    }
 
     function setChildNodes(message)
     {
@@ -51,6 +75,18 @@
             callback();
     }
 
+    function step(test)
+    {
+        InspectorTest.log("\n=== " + test.name + " ===\n");
+        InspectorTest.sendCommand(test.command, test.parameters, function(messageObject) {
+            if (messageObject.hasOwnProperty("error"))
+                InspectorTest.log("Backend error: " + messageObject.error.message + " (" + messageObject.error.code + ")\n");
+
+            if (test.callback)
+                test.callback(messageObject.result);
+        });
+    }
+
     function findNodeById(id)
     {
         for (var nodeId in nodeInfo) {
@@ -69,10 +105,18 @@
         return null;
     }
 
-    function addNodesRecursive(node)
+    function addNodesRecursive(root)
+    {
+        addNode(root);
+        if (!root.children)
+            return;
+        for (var i = 0; i < root.children.length; ++i)
+            addNodesRecursive(root.children[i]);
+    }
+
+    function addNode(node)
     {
         nodeInfo[node.nodeId] = node;
-        (node.children || []).forEach(addNodesRecursive);
     }
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/layout-fonts/resources/layout-font-test.js b/third_party/WebKit/LayoutTests/inspector-protocol/layout-fonts/resources/layout-font-test.js
index 996ca6b..f3efc86 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/layout-fonts/resources/layout-font-test.js
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/layout-fonts/resources/layout-font-test.js
@@ -57,13 +57,20 @@
 
     }
 
-    async function platformFontsForElementWithSelector(selector)
+    function platformFontsForElementWithSelector(selector)
     {
-        var nodeId = await InspectorTest.requestNodeId(documentNodeId, selector);
-        await InspectorTest.sendCommandOrDie("CSS.enable", {});
-        var response = await InspectorTest.sendCommandOrDie("CSS.getPlatformFontsForNode", { nodeId: nodeId });
-        collectResults(response);
-        testNextPageElement();
+        InspectorTest.requestNodeId(documentNodeId, selector, onNodeId);
+
+        function onNodeId(nodeId)
+        {
+            InspectorTest.sendCommandOrDie("CSS.getPlatformFontsForNode", { nodeId: nodeId }, onGotComputedFonts);
+        }
+
+        function onGotComputedFonts(response)
+        {
+            collectResults(response);
+            testNextPageElement();
+        }
     }
 
     function collectResults(response)
diff --git a/third_party/WebKit/LayoutTests/netinfo/basic-operation-expected.txt b/third_party/WebKit/LayoutTests/netinfo/basic-operation-expected.txt
index b97504e..40ed482 100644
--- a/third_party/WebKit/LayoutTests/netinfo/basic-operation-expected.txt
+++ b/third_party/WebKit/LayoutTests/netinfo/basic-operation-expected.txt
@@ -12,9 +12,15 @@
 PASS typeof connection.type is "string"
 PASS connection.type is newConnectionType
 PASS connection.downlinkMax is newDownlinkMax
+PASS connection.effectiveType is initialEffectiveType
+PASS connection.rtt is initialRtt
+PASS connection.downlink is initialDownlink
 PASS typeof connection.type is "string"
 PASS connection.type is initialType
 PASS connection.downlinkMax is initialDownlinkMax
+PASS connection.effectiveType is initialEffectiveType
+PASS connection.rtt is initialRtt
+PASS connection.downlink is initialDownlink
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/netinfo/basic-operation.html b/third_party/WebKit/LayoutTests/netinfo/basic-operation.html
index ad3d610..e258752 100644
--- a/third_party/WebKit/LayoutTests/netinfo/basic-operation.html
+++ b/third_party/WebKit/LayoutTests/netinfo/basic-operation.html
@@ -21,6 +21,9 @@
     shouldBe("typeof connection.type", '"string"');
     shouldBe('connection.type', 'initialType');
     shouldBe('connection.downlinkMax', 'initialDownlinkMax');
+    shouldBe('connection.effectiveType', 'initialEffectiveType');
+    shouldBe('connection.rtt', 'initialRtt');
+    shouldBe('connection.downlink', 'initialDownlink');
     finishJSTest();
 }
 
@@ -28,6 +31,9 @@
     shouldBe("typeof connection.type", '"string"');
     shouldBe('connection.type', 'newConnectionType');
     shouldBe('connection.downlinkMax', 'newDownlinkMax');
+    shouldBe('connection.effectiveType', 'initialEffectiveType');
+    shouldBe('connection.rtt', 'initialRtt');
+    shouldBe('connection.downlink', 'initialDownlink');
     connection.removeEventListener('change', changeListener);
     connection.addEventListener('typechange', typeChangeListener);
 	internals.setNetworkConnectionInfoOverride(isTypeOnline(initialType), initialType, initialDownlinkMax);
diff --git a/third_party/WebKit/LayoutTests/netinfo/estimate-basic-operation-expected.txt b/third_party/WebKit/LayoutTests/netinfo/estimate-basic-operation-expected.txt
new file mode 100644
index 0000000..9bdf4c36
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/netinfo/estimate-basic-operation-expected.txt
@@ -0,0 +1,27 @@
+Tests the basic operation of NetInfo.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS navigator.connection is defined.
+PASS navigator.connection.type is defined.
+PASS navigator.connection.downlinkMax is defined.
+PASS navigator.connection.effectiveType is defined.
+PASS navigator.connection.rtt is defined.
+PASS navigator.connection.downlink is defined.
+PASS typeof connection.type is "string"
+PASS connection.type is initialType
+PASS connection.downlinkMax is initialDownlinkMax
+PASS connection.effectiveType is newEffectiveType
+PASS connection.rtt is newRtt
+PASS connection.downlink is newDownlink
+PASS typeof connection.type is "string"
+PASS connection.type is initialType
+PASS connection.downlinkMax is initialDownlinkMax
+PASS connection.effectiveType is initialEffectiveType
+PASS connection.rtt is initialRtt
+PASS connection.downlink is initialDownlink
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/netinfo/estimate-basic-operation.html b/third_party/WebKit/LayoutTests/netinfo/estimate-basic-operation.html
new file mode 100644
index 0000000..e83c084
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/netinfo/estimate-basic-operation.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<head>
+<script src="../resources/js-test.js"></script>
+<script src="resources/netinfo_common.js"></script>
+</head>
+<body>
+<script>
+description('Tests the basic operation of NetInfo.');
+
+shouldBe('typeof window.internals.observeGC', '"function"',
+'this test requires window.internals');
+
+shouldBeDefined("navigator.connection");
+shouldBeDefined("navigator.connection.type");
+shouldBeDefined("navigator.connection.downlinkMax");
+shouldBeDefined("navigator.connection.effectiveType");
+shouldBeDefined("navigator.connection.rtt");
+shouldBeDefined("navigator.connection.downlink");
+
+var typeChangeListener = function(e) {
+    shouldBe("typeof connection.type", '"string"');
+    shouldBe('connection.type', 'initialType');
+    shouldBe('connection.downlinkMax', 'initialDownlinkMax');
+    shouldBe('connection.effectiveType', 'initialEffectiveType');
+    shouldBe('connection.rtt', 'initialRtt');
+    shouldBe('connection.downlink', 'initialDownlink');
+    finishJSTest();
+}
+
+var changeListener = function(e) {
+    shouldBe("typeof connection.type", '"string"');
+    shouldBe('connection.type', 'initialType');
+    shouldBe('connection.downlinkMax', 'initialDownlinkMax');
+    shouldBe('connection.effectiveType', 'newEffectiveType');
+    shouldBe('connection.rtt', 'newRtt');
+    shouldBe('connection.downlink', 'newDownlink');
+    connection.removeEventListener('change', changeListener);
+    connection.addEventListener('typechange', typeChangeListener);
+    internals.setNetworkQualityInfoOverride(initialEffectiveType, initialRtt, initialDownlink);
+}
+
+connection.addEventListener('change', changeListener);
+internals.setNetworkQualityInfoOverride(newEffectiveType, newRtt, newDownlink);
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/netinfo/estimate-multiple-frames-expected.txt b/third_party/WebKit/LayoutTests/netinfo/estimate-multiple-frames-expected.txt
new file mode 100644
index 0000000..2ad4a5dd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/netinfo/estimate-multiple-frames-expected.txt
@@ -0,0 +1,9 @@
+Tests using NetInfo from multiple frames.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/netinfo/estimate-multiple-frames.html b/third_party/WebKit/LayoutTests/netinfo/estimate-multiple-frames.html
new file mode 100644
index 0000000..88643d2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/netinfo/estimate-multiple-frames.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<head>
+<script src="../resources/js-test.js"></script>
+<script src="resources/netinfo_common.js"></script>
+</head>
+<body>
+<script>
+
+description('Tests using NetInfo from multiple frames.');
+
+shouldBe('typeof window.internals.observeGC', '"function"',
+'this test requires window.internals');
+
+var childFrame = document.createElement('iframe');
+document.body.appendChild(childFrame);
+
+var childConnection = childFrame.contentWindow.navigator.connection;
+
+if (connection.effectiveType != childConnection.effectiveType)
+    testFailed("Effective type not the same between main frame and child.");
+if (connection.rtt != childConnection.rtt)
+    testFailed("RTT not the same between main frame and child.");
+if (connection.downlink != childConnection.downlink)
+    testFailed("Downlink not the same between main frame and child.");
+
+var hasMainFrameEventFired = false;
+var hasChildFrameEventFired = false;
+
+function mainFrameListener() {
+    hasMainFrameEventFired = true;
+    if (connection.effectiveType != newEffectiveType)
+        testFailed("Event fired but effectiveType not yet changed.");
+    if (connection.rtt != newRtt)
+        testFailed("Event fired but rtt not yet changed.");
+    if (connection.downlink != newDownlink)
+        testFailed("Event fired but downlink not yet changed.");
+    if (!hasChildFrameEventFired && childConnection.rtt != initialRtt)
+        testFailed("Child frame connection rtt changed before firing its event.");
+    maybeFinishTest();
+}
+
+function childFrameListener() {
+    hasChildFrameEventFired = true;
+    if (childConnection.effectiveType != newEffectiveType)
+        testFailed("Child frame fired event but effectiveType not yet changed.");
+    if (childConnection.rtt != newRtt)
+        testFailed("Child frame fired event but rtt not yet changed.");
+    if (childConnection.downlink != newDownlink)
+        testFailed("Child frame fired event but downlink not yet changed.");
+    if (!hasMainFrameEventFired && connection.rtt != initialRtt)
+        testFailed("Main frame rtt changed before firing its event.");
+    maybeFinishTest();
+}
+
+function maybeFinishTest() {
+    if (hasMainFrameEventFired && hasChildFrameEventFired) {
+        finishJSTest();
+    }
+}
+
+connection.addEventListener('change', mainFrameListener);
+childConnection.addEventListener('change', childFrameListener);
+
+internals.setNetworkQualityInfoOverride(newEffectiveType, newRtt, newDownlink);
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/netinfo/estimate-web-worker-expected.txt b/third_party/WebKit/LayoutTests/netinfo/estimate-web-worker-expected.txt
new file mode 100644
index 0000000..c3a18b21
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/netinfo/estimate-web-worker-expected.txt
@@ -0,0 +1,9 @@
+Tests that web-workers have access to NetInfo.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/netinfo/estimate-web-worker.html b/third_party/WebKit/LayoutTests/netinfo/estimate-web-worker.html
new file mode 100644
index 0000000..52a88a3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/netinfo/estimate-web-worker.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<head>
+<script src="../resources/js-test.js"></script>
+<script src="resources/netinfo_common.js"></script>
+</head>
+<body>
+<script>
+
+description('Tests that web-workers have access to NetInfo.');
+
+shouldBe('typeof window.internals.observeGC', '"function"',
+'this test requires window.internals');
+
+var worker = new Worker("resources/web-worker.js");
+
+var msg_count = 0;
+
+worker.addEventListener('message', function(e) {
+    if (msg_count == 0) {
+        if (e.data != connection.type + ',' + connection.downlinkMax + ',' + connection.effectiveType + ',' + connection.rtt + ',' + connection.downlink) {
+            testFailed("Worker type disagrees with main frame.");
+        }
+       internals.setNetworkQualityInfoOverride(newEffectiveType, newRtt, newDownlink);
+    } else if (msg_count == 1) {
+        if (e.data != connection.type + ',' + connection.downlinkMax + ',' + newEffectiveType + ',' + newRtt + ',' + newDownlink) {
+            testFailed("Worker switched to wrong quality estimate.");
+        }
+        internals.setNetworkQualityInfoOverride(initialEffectiveType, initialRtt, initialDownlink);
+    } else if (msg_count == 2) {
+        if (e.data != connection.type + ',' + connection.downlinkMax + ',' + initialEffectiveType + ',' + initialRtt + ',' + initialDownlink) {
+            testFailed("Worker did not revert back to initial quality estimate.");
+        }
+        finishJSTest();
+    }
+    msg_count += 1;
+});
+
+worker.postMessage('kickoff');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/netinfo/network-quality-expected.txt b/third_party/WebKit/LayoutTests/netinfo/network-quality-expected.txt
new file mode 100644
index 0000000..d807449c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/netinfo/network-quality-expected.txt
@@ -0,0 +1,36 @@
+Tests that all rtt and downlink is exposed correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS connection.effectiveType is values[count][3]
+PASS connection.rtt is values[count][4]
+PASS connection.downlink is values[count][5]
+PASS connection.effectiveType is values[count][3]
+PASS connection.rtt is values[count][4]
+PASS connection.downlink is values[count][5]
+PASS connection.effectiveType is values[count][3]
+PASS connection.rtt is values[count][4]
+PASS connection.downlink is values[count][5]
+PASS connection.effectiveType is values[count][3]
+PASS connection.rtt is values[count][4]
+PASS connection.downlink is values[count][5]
+PASS connection.effectiveType is values[count][3]
+PASS connection.rtt is values[count][4]
+PASS connection.downlink is values[count][5]
+PASS connection.effectiveType is values[count][3]
+PASS connection.rtt is values[count][4]
+PASS connection.downlink is values[count][5]
+PASS connection.effectiveType is values[count][3]
+PASS connection.rtt is values[count][4]
+PASS connection.downlink is values[count][5]
+PASS connection.effectiveType is values[count][3]
+PASS connection.rtt is values[count][4]
+PASS connection.downlink is values[count][5]
+PASS connection.effectiveType is values[count][3]
+PASS connection.rtt is values[count][4]
+PASS connection.downlink is values[count][5]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/netinfo/network-quality.html b/third_party/WebKit/LayoutTests/netinfo/network-quality.html
new file mode 100644
index 0000000..9cfb2d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/netinfo/network-quality.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<head>
+<script src="../resources/js-test.js"></script>
+<script src="resources/netinfo_common.js"></script>
+</head>
+<body>
+<script>
+description('Tests that all rtt and downlink is exposed correctly.');
+
+if (!window.internals)
+  log("This test requires window.internals");
+
+var values = [
+  ["slow-2g", 25.0, 2.0, "slow-2g", 25.0, 2.0],
+  ["slow-2g", 40.0, 2.0, "slow-2g", 50.0, 2.0],
+  ["slow-2g", 40.0, 0.0, "slow-2g", 50.0, 0.0],
+  ["slow-2g", 40.0, 0.125, "slow-2g", 50.0, 0.125],
+  ["slow-2g", 40.0, 0.103, "slow-2g", 50.0, 0.1],
+  ["slow-2g", 40.0, 0.123, "slow-2g", 50.0, 0.125],
+  ["2g", 40.0, 0.123, "2g", 50.0, 0.125],
+  ["3g", 40.0, 0.123, "3g", 50.0, 0.125],
+  ["3g", 10.0, 0.123, "3g", 0.0, 0.125],
+];
+
+var count = 0;
+connection.addEventListener('change', function(e) {
+  shouldBe('connection.effectiveType', 'values[count][3]');
+  shouldBe('connection.rtt', 'values[count][4]');
+  shouldBe('connection.downlink', 'values[count][5]');
+
+  if (++count === values.length)
+    finishJSTest();
+});
+
+for(var i = 0; i < values.length; i++)
+  internals.setNetworkQualityInfoOverride(values[i][0], values[i][1], values[i][2]);
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/netinfo/resources/netinfo_common.js b/third_party/WebKit/LayoutTests/netinfo/resources/netinfo_common.js
index c47ad46..07273363 100644
--- a/third_party/WebKit/LayoutTests/netinfo/resources/netinfo_common.js
+++ b/third_party/WebKit/LayoutTests/netinfo/resources/netinfo_common.js
@@ -5,10 +5,17 @@
 var initialDownlinkMax = 1.0;
 var newConnectionType = "ethernet";
 var newDownlinkMax = 2.0;
+var initialEffectiveType = "3g";
+var initialRtt = 25.0;
+var initialDownlink = 10.0;
+var newEffectiveType = "4g";
+var newRtt = 50.0;
+var newDownlink = 30.0;
 
 // Suppress connection messages information from the host.
 if (window.internals) {
     internals.setNetworkConnectionInfoOverride(true, initialType, initialDownlinkMax);
+    internals.setNetworkQualityInfoOverride(initialEffectiveType, initialRtt, initialDownlink);
 
     // Reset the state of the singleton network state notifier.
     window.addEventListener('beforeunload', function() {
diff --git a/third_party/WebKit/LayoutTests/netinfo/resources/web-worker.js b/third_party/WebKit/LayoutTests/netinfo/resources/web-worker.js
index ee7656db..ef6891b 100644
--- a/third_party/WebKit/LayoutTests/netinfo/resources/web-worker.js
+++ b/third_party/WebKit/LayoutTests/netinfo/resources/web-worker.js
@@ -1,7 +1,7 @@
 addEventListener('message', function(e) {
-    self.postMessage(navigator.connection.type + ',' + navigator.connection.downlinkMax);
+    self.postMessage(navigator.connection.type + ',' + navigator.connection.downlinkMax + ',' + navigator.connection.effectiveType + ',' + navigator.connection.rtt + ',' + navigator.connection.downlink);
 }, false);
 
 navigator.connection.addEventListener('change', function() {
-    self.postMessage(navigator.connection.type + ',' + navigator.connection.downlinkMax);
+    self.postMessage(navigator.connection.type + ',' + navigator.connection.downlinkMax + ',' + navigator.connection.effectiveType + ',' + navigator.connection.rtt + ',' + navigator.connection.downlink);
 }, false);
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/netinfo/type-change-no-listener-expected.txt b/third_party/WebKit/LayoutTests/netinfo/type-change-no-listener-expected.txt
index 13e7ed0..3e3a65d 100644
--- a/third_party/WebKit/LayoutTests/netinfo/type-change-no-listener-expected.txt
+++ b/third_party/WebKit/LayoutTests/netinfo/type-change-no-listener-expected.txt
@@ -5,6 +5,9 @@
 
 PASS connection.type is newConnectionType
 PASS connection.downlinkMax is newDownlinkMax
+PASS connection.effectiveType is newEffectiveType
+PASS connection.rtt is newRtt
+PASS connection.downlink is newDownlink
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/netinfo/type-change-no-listener.html b/third_party/WebKit/LayoutTests/netinfo/type-change-no-listener.html
index 5f6d2924..cc1bc2c 100644
--- a/third_party/WebKit/LayoutTests/netinfo/type-change-no-listener.html
+++ b/third_party/WebKit/LayoutTests/netinfo/type-change-no-listener.html
@@ -8,8 +8,12 @@
 description('Tests that the type changes without an active listener');
 
 internals.setNetworkConnectionInfoOverride(isTypeOnline(newConnectionType), newConnectionType, newDownlinkMax);
+internals.setNetworkQualityInfoOverride(newEffectiveType, newRtt, newDownlink);
 shouldBe('connection.type', 'newConnectionType');
 shouldBe('connection.downlinkMax', 'newDownlinkMax');
+shouldBe('connection.effectiveType', 'newEffectiveType');
+shouldBe('connection.rtt', 'newRtt');
+shouldBe('connection.downlink', 'newDownlink');
 
 finishJSTest();
 </script>
diff --git a/third_party/WebKit/LayoutTests/netinfo/unregister-during-event-expected.txt b/third_party/WebKit/LayoutTests/netinfo/unregister-during-event-expected.txt
index 145305a..5eda713c 100644
--- a/third_party/WebKit/LayoutTests/netinfo/unregister-during-event-expected.txt
+++ b/third_party/WebKit/LayoutTests/netinfo/unregister-during-event-expected.txt
@@ -5,8 +5,14 @@
 
 PASS connection.type is newConnectionType
 PASS connection.downlinkMax is newDownlinkMax
+PASS connection.effectiveType is initialEffectiveType
+PASS connection.rtt is initialRtt
+PASS connection.downlink is initialDownlink
 PASS connection.type is initialType
 PASS connection.downlinkMax is initialDownlinkMax
+PASS connection.effectiveType is initialEffectiveType
+PASS connection.rtt is initialRtt
+PASS connection.downlink is initialDownlink
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/netinfo/unregister-during-event.html b/third_party/WebKit/LayoutTests/netinfo/unregister-during-event.html
index d5124dd7..db30c9e 100644
--- a/third_party/WebKit/LayoutTests/netinfo/unregister-during-event.html
+++ b/third_party/WebKit/LayoutTests/netinfo/unregister-during-event.html
@@ -14,6 +14,9 @@
 var otherHandler = function(e) {
     shouldBe('connection.type', 'initialType');
     shouldBe('connection.downlinkMax', 'initialDownlinkMax');
+    shouldBe('connection.effectiveType', 'initialEffectiveType');
+    shouldBe('connection.rtt', 'initialRtt');
+    shouldBe('connection.downlink', 'initialDownlink');
 
     finishJSTest();
 };
@@ -21,6 +24,9 @@
 var handler = function(e) {
     shouldBe('connection.type', 'newConnectionType');
     shouldBe('connection.downlinkMax', 'newDownlinkMax');
+    shouldBe('connection.effectiveType', 'initialEffectiveType');
+    shouldBe('connection.rtt', 'initialRtt');
+    shouldBe('connection.downlink', 'initialDownlink');
     connection.removeEventListener('change', handler);
     connection.addEventListener('change', otherHandler);
     internals.setNetworkConnectionInfoOverride(isTypeOnline(initialType), initialType, initialDownlinkMax);
diff --git a/third_party/WebKit/LayoutTests/netinfo/web-worker.html b/third_party/WebKit/LayoutTests/netinfo/web-worker.html
index cdb0c1d..c5569c9 100644
--- a/third_party/WebKit/LayoutTests/netinfo/web-worker.html
+++ b/third_party/WebKit/LayoutTests/netinfo/web-worker.html
@@ -17,17 +17,19 @@
 
 worker.addEventListener('message', function(e) {
     if (msg_count == 0) {
-        if (e.data != connection.type + ',' + connection.downlinkMax) {
+        if (e.data != connection.type + ',' + connection.downlinkMax + ',' + connection.effectiveType + ',' + connection.rtt + ',' + connection.downlink) {
             testFailed("Worker type disagrees with main frame.");
         }
        internals.setNetworkConnectionInfoOverride(isTypeOnline(newConnectionType), newConnectionType, newDownlinkMax);
     } else if (msg_count == 1) {
-        if (e.data != newConnectionType + ',' + newDownlinkMax)
+        if (e.data != newConnectionType + ',' + newDownlinkMax + ',' + connection.effectiveType + ',' + connection.rtt + ',' + connection.downlink) {
             testFailed("Worker switched to wrong connection type.");
+        }
         internals.setNetworkConnectionInfoOverride(isTypeOnline(initialType), initialType, initialDownlinkMax);
     } else if (msg_count == 2) {
-        if (e.data != initialType + ',' + initialDownlinkMax)
+        if (e.data != initialType + ',' + initialDownlinkMax + ','  + connection.effectiveType + ',' + connection.rtt + ',' + connection.downlink) {
             testFailed("Worker did not revert back to initial type.");
+        }
         finishJSTest();
     }
     msg_count += 1;
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js
index 1f6a479..129c660ee 100644
--- a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js
+++ b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js
@@ -18,8 +18,8 @@
           handle => this.bindingSet_.addBinding(this, handle));
     }
 
-    detect(frame_data, width, height) {
-      let receivedStruct = mojo.mapBuffer(frame_data, 0, width*height*4, 0);
+    detect(bitmap_data) {
+      let receivedStruct = new Uint8Array(bitmap_data.pixel_data);
       this.buffer_data_ = new Uint32Array(receivedStruct.buffer);
       return Promise.resolve({
         results: [
@@ -45,7 +45,6 @@
           },
         ],
       });
-      mojo.unmapBuffer(receivedStruct.buffer);
     }
 
     getFrameData() {
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js
index d117ee0..773c04c8 100644
--- a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js
+++ b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js
@@ -44,8 +44,8 @@
                                            request);
     }
 
-    detect(frame_data, width, height) {
-      let receivedStruct = mojo.mapBuffer(frame_data, 0, width*height*4, 0);
+    detect(bitmap_data) {
+      let receivedStruct = new Uint8Array(bitmap_data.pixel_data);
       this.bufferData_ = new Uint32Array(receivedStruct.buffer);
       return Promise.resolve({
         results: [
@@ -66,7 +66,6 @@
           },
         ]
       });
-      mojo.unmapBuffer(receivedStruct.buffer);
     }
   }
   return new MockFaceDetectionProvider();
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js
index 08195c9..a622605 100644
--- a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js
+++ b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js
@@ -17,8 +17,8 @@
           handle => this.bindingSet_.addBinding(this, handle));
     }
 
-    detect(frame_data, width, height) {
-      let receivedStruct = mojo.mapBuffer(frame_data, 0, width*height*4, 0);
+    detect(bitmap_data) {
+      let receivedStruct = new Uint8Array(bitmap_data.pixel_data);
       this.buffer_data_ = new Uint32Array(receivedStruct.buffer);
       return Promise.resolve({
         results: [
@@ -32,7 +32,6 @@
           },
         ],
       });
-      mojo.unmapBuffer(receivedStruct.buffer);
     }
 
     getFrameData() {
diff --git a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
index 8ff8877..d5f82f7 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
@@ -220,12 +220,6 @@
   DataRef<{{subgroup.type_name}}> {{subgroup.member_name}};
   {% endfor %}
 
-  static unsigned WidthToFixedPoint(float width) {
-    DCHECK_GE(width, 0);
-    return static_cast<unsigned>(std::min<float>(width, kMaxForBorderWidth) *
-                                 kBorderWidthDenominator);
-  }
-
  private:
   {% for field in computed_style.fields %}
   {{declare_storage(field)}}
diff --git a/third_party/WebKit/Source/core/dom/DOMTokenList.cpp b/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
index df83eeb..b2387b53 100644
--- a/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
+++ b/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
@@ -54,19 +54,12 @@
   return false;
 }
 
-}  // anonymous namespace
-
-DEFINE_TRACE(DOMTokenList) {
-  visitor->Trace(element_);
-}
-
 // This implements the common part of the following operations:
 // https://dom.spec.whatwg.org/#dom-domtokenlist-add
 // https://dom.spec.whatwg.org/#dom-domtokenlist-remove
 // https://dom.spec.whatwg.org/#dom-domtokenlist-toggle
 // https://dom.spec.whatwg.org/#dom-domtokenlist-replace
-bool DOMTokenList::ValidateToken(const String& token,
-                                 ExceptionState& exception_state) const {
+bool CheckTokenSyntax(const String& token, ExceptionState& exception_state) {
   // 1. If token is the empty string, then throw a SyntaxError.
   if (!CheckEmptyToken(token, exception_state))
     return false;
@@ -76,16 +69,21 @@
   return CheckTokenWithWhitespace(token, exception_state);
 }
 
-bool DOMTokenList::ValidateTokens(const Vector<String>& tokens,
-                                  ExceptionState& exception_state) const {
+bool CheckTokensSyntax(const Vector<String>& tokens,
+                       ExceptionState& exception_state) {
   for (const auto& token : tokens) {
-    if (!ValidateToken(token, exception_state))
+    if (!CheckTokenSyntax(token, exception_state))
       return false;
   }
-
   return true;
 }
 
+}  // anonymous namespace
+
+DEFINE_TRACE(DOMTokenList) {
+  visitor->Trace(element_);
+}
+
 // https://dom.spec.whatwg.org/#concept-domtokenlist-validation
 bool DOMTokenList::ValidateTokenValue(const AtomicString&,
                                       ExceptionState& exception_state) const {
@@ -107,9 +105,8 @@
 // the bindings generator does not handle that.
 void DOMTokenList::add(const Vector<String>& tokens,
                        ExceptionState& exception_state) {
-  if (!ValidateTokens(tokens, exception_state))
+  if (!CheckTokensSyntax(tokens, exception_state))
     return;
-
   AddTokens(tokens);
 }
 
@@ -122,7 +119,7 @@
 // the bindings generator does not handle that.
 void DOMTokenList::remove(const Vector<String>& tokens,
                           ExceptionState& exception_state) {
-  if (!ValidateTokens(tokens, exception_state))
+  if (!CheckTokensSyntax(tokens, exception_state))
     return;
 
   // TODO(tkent): This null check doesn't conform to the DOM specification.
@@ -135,7 +132,7 @@
 // https://dom.spec.whatwg.org/#dom-domtokenlist-toggle
 bool DOMTokenList::toggle(const AtomicString& token,
                           ExceptionState& exception_state) {
-  if (!ValidateToken(token, exception_state))
+  if (!CheckTokenSyntax(token, exception_state))
     return false;
 
   // 4. If context object’s token set[token] exists, then:
@@ -155,7 +152,7 @@
 bool DOMTokenList::toggle(const AtomicString& token,
                           bool force,
                           ExceptionState& exception_state) {
-  if (!ValidateToken(token, exception_state))
+  if (!CheckTokenSyntax(token, exception_state))
     return false;
 
   // 4. If context object’s token set[token] exists, then:
diff --git a/third_party/WebKit/Source/core/dom/DOMTokenList.h b/third_party/WebKit/Source/core/dom/DOMTokenList.h
index 8018ef1..5f2db853 100644
--- a/third_party/WebKit/Source/core/dom/DOMTokenList.h
+++ b/third_party/WebKit/Source/core/dom/DOMTokenList.h
@@ -80,13 +80,11 @@
       : element_(element), attribute_name_(attr) {}
   Element& GetElement() const { return *element_; }
 
-  bool ValidateToken(const String&, ExceptionState&) const;
-  bool ValidateTokens(const Vector<String>&, ExceptionState&) const;
   virtual bool ValidateTokenValue(const AtomicString&, ExceptionState&) const;
-  void AddTokens(const Vector<String>&);
-  void RemoveTokens(const Vector<String>&);
 
  private:
+  void AddTokens(const Vector<String>&);
+  void RemoveTokens(const Vector<String>&);
   void UpdateWithTokenSet(const SpaceSplitString&);
   static AtomicString SerializeSet(const SpaceSplitString&);
 
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
index 5ff8ed7d..2a1c2e8 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
@@ -37,6 +37,7 @@
 #include "core/editing/Position.h"
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/iterators/TextIteratorTextNodeHandler.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/frame/UseCounter.h"
 #include "core/html/HTMLElement.h"
@@ -186,8 +187,9 @@
       shadow_depth_(
           ShadowDepthOf<Strategy>(*start_container_, *end_container_)),
       behavior_(AdjustBehaviorFlags<Strategy>(behavior)),
-      text_state_(behavior_),
-      text_node_handler_(behavior_, &text_state_) {
+      text_state_(new TextIteratorTextState(behavior_)),
+      text_node_handler_(
+          new TextIteratorTextNodeHandler(behavior_, text_state_)) {
   DCHECK(start_container_);
   DCHECK(end_container_);
 
@@ -253,12 +255,12 @@
 
   if (needs_handle_replaced_element_) {
     HandleReplacedElement();
-    if (text_state_.PositionNode())
+    if (text_state_->PositionNode())
       return true;
   }
 
   // Try to emit more text runs if we are handling a text node.
-  return text_node_handler_.HandleRemainingTextRuns();
+  return text_node_handler_->HandleRemainingTextRuns();
 }
 
 template <typename Strategy>
@@ -269,7 +271,7 @@
   if (node_)
     DCHECK(!node_->GetDocument().NeedsLayoutTreeUpdate()) << node_;
 
-  text_state_.ResetRunInformation();
+  text_state_->ResetRunInformation();
 
   if (HandleRememberedProgress())
     return;
@@ -355,7 +357,7 @@
           HandleNonTextNode();
         }
         iteration_progress_ = kHandledNode;
-        if (text_state_.PositionNode())
+        if (text_state_->PositionNode())
           return;
       }
     }
@@ -388,7 +390,7 @@
           parent_node = Strategy::Parent(*node_);
           if (have_layout_object)
             ExitNode();
-          if (text_state_.PositionNode()) {
+          if (text_state_->PositionNode()) {
             iteration_progress_ = kHandledChildren;
             return;
           }
@@ -449,7 +451,7 @@
     iteration_progress_ = kHandledNone;
 
     // how would this ever be?
-    if (text_state_.PositionNode())
+    if (text_state_->PositionNode())
       return;
   }
 }
@@ -473,16 +475,16 @@
   // an offset range with unbounded endpoint(s) in an easy but still clear way.
   if (node_ != start_container_) {
     if (node_ != end_container_)
-      text_node_handler_.HandleTextNodeWhole(text);
+      text_node_handler_->HandleTextNodeWhole(text);
     else
-      text_node_handler_.HandleTextNodeEndAt(text, end_offset_);
+      text_node_handler_->HandleTextNodeEndAt(text, end_offset_);
     return;
   }
   if (node_ != end_container_) {
-    text_node_handler_.HandleTextNodeStartFrom(text, start_offset_);
+    text_node_handler_->HandleTextNodeStartFrom(text, start_offset_);
     return;
   }
-  text_node_handler_.HandleTextNodeInRange(text, start_offset_, end_offset_);
+  text_node_handler_->HandleTextNodeInRange(text, start_offset_, end_offset_);
 }
 
 template <typename Strategy>
@@ -519,9 +521,9 @@
     return;
   }
 
-  DCHECK_EQ(last_text_node_, text_node_handler_.GetNode());
+  DCHECK_EQ(last_text_node_, text_node_handler_->GetNode());
   if (last_text_node_) {
-    if (text_node_handler_.FixLeadingWhiteSpaceForReplacedElement(
+    if (text_node_handler_->FixLeadingWhiteSpaceForReplacedElement(
             Strategy::Parent(*last_text_node_))) {
       needs_handle_replaced_element_ = true;
       return;
@@ -541,11 +543,11 @@
     return;
   }
 
-  text_state_.UpdateForReplacedElement(node_);
+  text_state_->UpdateForReplacedElement(node_);
 
   if (EmitsImageAltText() && TextIterator::SupportsAltText(node_)) {
-    text_state_.EmitAltText(node_);
-    if (text_state_.length())
+    text_state_->EmitAltText(node_);
+    if (text_state_->length())
       return;
   }
 }
@@ -673,11 +675,11 @@
 
   // Leave element positioned flush with start of a paragraph
   // (e.g. do not insert tab before a table cell at the start of a paragraph)
-  if (text_state_.LastCharacter() == '\n')
+  if (text_state_->LastCharacter() == '\n')
     return false;
 
   // Otherwise, show the position if we have emitted any characters
-  if (text_state_.HasEmitted())
+  if (text_state_->HasEmitted())
     return true;
 
   // We've not emitted anything yet. Generally, there is no need for any
@@ -782,7 +784,7 @@
   // FIXME: !m_hasEmitted does not necessarily mean there was a collapsed
   // block... it could have been an hr (e.g.). Also, a collapsed block could
   // have height (e.g. a table) and therefore look like a blank line.
-  if (!text_state_.HasEmitted())
+  if (!text_state_->HasEmitted())
     return;
 
   // Emit with a position *inside* m_node, after m_node's contents, in
@@ -801,7 +803,7 @@
 
     // FIXME: We need to emit a '\n' as we leave an empty block(s) that
     // contain a VisiblePosition when doing selection preservation.
-    if (text_state_.LastCharacter() != '\n') {
+    if (text_state_->LastCharacter() != '\n') {
       // insert a newline with a position following this block's contents.
       SpliceBuffer(kNewlineCharacter, Strategy::Parent(*base_node), base_node,
                    1, 1);
@@ -816,7 +818,7 @@
   }
 
   // If nothing was emitted, see if we need to emit a space.
-  if (!text_state_.PositionNode() && ShouldEmitSpaceBeforeAndAfterNode(node_))
+  if (!text_state_->PositionNode() && ShouldEmitSpaceBeforeAndAfterNode(node_))
     SpliceBuffer(kSpaceCharacter, Strategy::Parent(*base_node), base_node, 1,
                  1);
 }
@@ -827,16 +829,16 @@
                                                    Node* offset_base_node,
                                                    int text_start_offset,
                                                    int text_end_offset) {
-  text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset,
-                           text_end_offset);
-  text_node_handler_.ResetCollapsedWhiteSpaceFixup();
+  text_state_->SpliceBuffer(c, text_node, offset_base_node, text_start_offset,
+                            text_end_offset);
+  text_node_handler_->ResetCollapsedWhiteSpaceFixup();
 }
 
 template <typename Strategy>
 EphemeralRangeTemplate<Strategy> TextIteratorAlgorithm<Strategy>::Range()
     const {
   // use the current run information, if we have it
-  if (text_state_.PositionNode()) {
+  if (text_state_->PositionNode()) {
     return EphemeralRangeTemplate<Strategy>(StartPositionInCurrentContainer(),
                                             EndPositionInCurrentContainer());
   }
@@ -851,8 +853,8 @@
 
 template <typename Strategy>
 Document* TextIteratorAlgorithm<Strategy>::OwnerDocument() const {
-  if (text_state_.PositionNode())
-    return &text_state_.PositionNode()->GetDocument();
+  if (text_state_->PositionNode())
+    return &text_state_->PositionNode()->GetDocument();
   if (end_container_)
     return &end_container_->GetDocument();
   return 0;
@@ -860,7 +862,7 @@
 
 template <typename Strategy>
 Node* TextIteratorAlgorithm<Strategy>::GetNode() const {
-  if (text_state_.PositionNode() || end_container_) {
+  if (text_state_->PositionNode() || end_container_) {
     Node* node = CurrentContainer();
     if (node->IsCharacterDataNode())
       return node;
@@ -871,9 +873,9 @@
 
 template <typename Strategy>
 int TextIteratorAlgorithm<Strategy>::StartOffsetInCurrentContainer() const {
-  if (text_state_.PositionNode()) {
-    text_state_.FlushPositionOffsets();
-    return text_state_.PositionStartOffset() + text_state_.TextStartOffset();
+  if (text_state_->PositionNode()) {
+    text_state_->FlushPositionOffsets();
+    return text_state_->PositionStartOffset() + text_state_->TextStartOffset();
   }
   DCHECK(end_container_);
   return end_offset_;
@@ -881,9 +883,9 @@
 
 template <typename Strategy>
 int TextIteratorAlgorithm<Strategy>::EndOffsetInCurrentContainer() const {
-  if (text_state_.PositionNode()) {
-    text_state_.FlushPositionOffsets();
-    return text_state_.PositionEndOffset() + text_state_.TextStartOffset();
+  if (text_state_->PositionNode()) {
+    text_state_->FlushPositionOffsets();
+    return text_state_->PositionEndOffset() + text_state_->TextStartOffset();
   }
   DCHECK(end_container_);
   return end_offset_;
@@ -891,8 +893,8 @@
 
 template <typename Strategy>
 Node* TextIteratorAlgorithm<Strategy>::CurrentContainer() const {
-  if (text_state_.PositionNode()) {
-    return text_state_.PositionNode();
+  if (text_state_->PositionNode()) {
+    return text_state_->PositionNode();
   }
   DCHECK(end_container_);
   return end_container_;
@@ -966,7 +968,7 @@
     ForwardsTextBuffer* output,
     int position,
     int copy_length) const {
-  text_state_.AppendTextTo(output, position, copy_length);
+  text_state_->AppendTextTo(output, position, copy_length);
 }
 
 // --------
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.h b/third_party/WebKit/Source/core/editing/iterators/TextIterator.h
index f2e00dc..6a1037e5 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.h
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.h
@@ -32,12 +32,13 @@
 #include "core/editing/FindOptions.h"
 #include "core/editing/iterators/FullyClippedStateStack.h"
 #include "core/editing/iterators/TextIteratorBehavior.h"
-#include "core/editing/iterators/TextIteratorTextNodeHandler.h"
 #include "core/editing/iterators/TextIteratorTextState.h"
 #include "platform/heap/Handle.h"
 
 namespace blink {
 
+class TextIteratorTextNodeHandler;
+
 CORE_EXPORT String
 PlainText(const EphemeralRange&,
           const TextIteratorBehavior& = TextIteratorBehavior());
@@ -67,7 +68,7 @@
 
   ~TextIteratorAlgorithm();
 
-  bool AtEnd() const { return !text_state_.PositionNode() || should_stop_; }
+  bool AtEnd() const { return !text_state_->PositionNode() || should_stop_; }
   void Advance();
   bool IsInsideAtomicInlineElement() const;
   bool IsInTextSecurityMode() const;
@@ -82,10 +83,10 @@
   PositionTemplate<Strategy> StartPositionInCurrentContainer() const;
   PositionTemplate<Strategy> EndPositionInCurrentContainer() const;
 
-  const TextIteratorTextState& GetText() const { return text_state_; }
-  int length() const { return text_state_.length(); }
+  const TextIteratorTextState& GetText() const { return *text_state_; }
+  int length() const { return text_state_->length(); }
   UChar CharacterAt(unsigned index) const {
-    return text_state_.CharacterAt(index);
+    return text_state_->CharacterAt(index);
   }
 
   bool BreaksAtReplacedElement() {
@@ -228,12 +229,10 @@
   bool handle_shadow_root_ = false;
 
   // Contains state of emitted text.
-  TextIteratorTextState text_state_;
+  const Member<TextIteratorTextState> text_state_;
 
   // Helper for extracting text content from text nodes.
-  // TODO(xiaochengh): We should store a pointer here, so that we can use
-  // forward declaration and switch it to Layout NG easier.
-  TextIteratorTextNodeHandler text_node_handler_;
+  const Member<TextIteratorTextNodeHandler> text_node_handler_;
 };
 
 extern template class CORE_EXTERN_TEMPLATE_EXPORT
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
index be88802..d96e3c70 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
@@ -16,7 +16,12 @@
 TextIteratorTextNodeHandler::TextIteratorTextNodeHandler(
     const TextIteratorBehavior& behavior,
     TextIteratorTextState* text_state)
-    : behavior_(behavior), text_state_(*text_state) {}
+    : behavior_(behavior), text_state_(text_state) {}
+
+DEFINE_TRACE(TextIteratorTextNodeHandler) {
+  visitor->Trace(text_node_);
+  visitor->Trace(text_state_);
+}
 
 bool TextIteratorTextNodeHandler::HandleRemainingTextRuns() {
   if (ShouldProceedToRemainingText())
@@ -24,13 +29,13 @@
   // Handle remembered text box
   if (text_box_) {
     HandleTextBox();
-    return text_state_.PositionNode();
+    return text_state_->PositionNode();
   }
   // Handle remembered pre-formatted text node.
   if (!needs_handle_pre_formatted_text_node_)
     return false;
   HandlePreFormattedTextNode();
-  return text_state_.PositionNode();
+  return text_state_->PositionNode();
 }
 
 bool TextIteratorTextNodeHandler::ShouldHandleFirstLetter(
@@ -256,8 +261,8 @@
                                text_box_start == run_start && run_start > 0);
       if (need_space &&
           !layout_object->Style()->IsCollapsibleWhiteSpace(
-              text_state_.LastCharacter()) &&
-          text_state_.LastCharacter()) {
+              text_state_->LastCharacter()) &&
+          text_state_->LastCharacter()) {
         if (run_start > 0 && str[run_start - 1] == ' ') {
           unsigned space_run_start = run_start - 1;
           while (space_run_start > 0 && str[space_run_start - 1] == ' ')
@@ -324,7 +329,7 @@
         // If we are doing a subrun that doesn't go to the end of the text box,
         // come back again to finish handling this text box; don't advance to
         // the next one.
-        if (static_cast<unsigned>(text_state_.PositionEndOffset()) <
+        if (static_cast<unsigned>(text_state_->PositionEndOffset()) <
             text_box_end)
           return;
 
@@ -436,8 +441,8 @@
                                                Node* offset_base_node,
                                                int text_start_offset,
                                                int text_end_offset) {
-  text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset,
-                           text_end_offset);
+  text_state_->SpliceBuffer(c, text_node, offset_base_node, text_start_offset,
+                            text_end_offset);
   ResetCollapsedWhiteSpaceFixup();
 }
 
@@ -445,8 +450,8 @@
                                            LayoutText* layout_object,
                                            int text_start_offset,
                                            int text_end_offset) {
-  text_state_.EmitText(text_node, layout_object, text_start_offset,
-                       text_end_offset);
+  text_state_->EmitText(text_node, layout_object, text_start_offset,
+                        text_end_offset);
   ResetCollapsedWhiteSpaceFixup();
 }
 
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.h b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.h
index 9d89fe31..48d1596 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.h
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.h
@@ -19,12 +19,12 @@
 
 // TextIteratorTextNodeHandler extracts plain text from a text node by calling
 // HandleTextNode() function. It should be used only by TextIterator.
-class TextIteratorTextNodeHandler final {
-  STACK_ALLOCATED();
-
+class TextIteratorTextNodeHandler final
+    : public GarbageCollectedFinalized<TextIteratorTextNodeHandler> {
  public:
   TextIteratorTextNodeHandler(const TextIteratorBehavior&,
                               TextIteratorTextState*);
+  ~TextIteratorTextNodeHandler() {}
 
   Text* GetNode() const { return text_node_; }
 
@@ -44,6 +44,8 @@
   void HandleTextNodeEndAt(Text*, int end_offset);
   void HandleTextNodeInRange(Text*, int start_offset, int end_offset);
 
+  DECLARE_TRACE();
+
  private:
   void HandlePreFormattedTextNode();
   void HandleTextBox();
@@ -97,7 +99,7 @@
   const TextIteratorBehavior behavior_;
 
   // Contains state of emitted text.
-  TextIteratorTextState& text_state_;
+  const Member<TextIteratorTextState> text_state_;
 
   DISALLOW_COPY_AND_ASSIGN(TextIteratorTextNodeHandler);
 };
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.cpp
index d4f9296..e6cc3b1 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.cpp
@@ -36,6 +36,11 @@
     const TextIteratorBehavior& behavior)
     : behavior_(behavior) {}
 
+DEFINE_TRACE(TextIteratorTextState) {
+  visitor->Trace(position_node_);
+  visitor->Trace(position_offset_base_node_);
+}
+
 UChar TextIteratorTextState::CharacterAt(unsigned index) const {
   SECURITY_DCHECK(index < static_cast<unsigned>(length()));
   if (!(index < static_cast<unsigned>(length())))
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.h b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.h
index aeff02db..f81bb8fe 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.h
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.h
@@ -38,9 +38,8 @@
 class LayoutText;
 class TextIteratorBehavior;
 
-class CORE_EXPORT TextIteratorTextState {
-  STACK_ALLOCATED();
-
+class CORE_EXPORT TextIteratorTextState
+    : public GarbageCollectedFinalized<TextIteratorTextState> {
  public:
   explicit TextIteratorTextState(const TextIteratorBehavior&);
   ~TextIteratorTextState() {}
@@ -79,6 +78,8 @@
                     unsigned position,
                     unsigned length_to_append) const;
 
+  DECLARE_TRACE();
+
  private:
   int text_length_ = 0;
   String text_;
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElementTest.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElementTest.cpp
index 8ef5798..93e6f3ae 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElementTest.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElementTest.cpp
@@ -125,7 +125,7 @@
     Media()->GetDocument().GetSettings()->SetForcePreloadNoneForMediaElements(
         data.force_preload_none_for_media_elements);
     if (data.is_cellular) {
-      GetNetworkStateNotifier().SetOverride(
+      GetNetworkStateNotifier().SetNetworkConnectionInfoOverride(
           true, WebConnectionType::kWebConnectionTypeCellular3G, 2.0);
     } else {
       GetNetworkStateNotifier().ClearOverride();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
index eddcc1c..77463d4 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -757,7 +757,6 @@
   HeapVector<Member<Document>> documents = dom_agent_->Documents();
   for (Document* document : documents)
     UpdateActiveStyleSheets(document);
-  was_enabled_ = true;
 }
 
 Response InspectorCSSAgent::disable() {
@@ -765,7 +764,6 @@
   dom_agent_->SetDOMListener(nullptr);
   instrumenting_agents_->removeInspectorCSSAgent(this);
   state_->setBoolean(CSSAgentState::kCssAgentEnabled, false);
-  was_enabled_ = false;
   resource_content_loader_->Cancel(resource_content_loader_client_id_);
   state_->setBoolean(CSSAgentState::kRuleRecordingEnabled, false);
   SetCoverageEnabled(false);
@@ -917,12 +915,8 @@
         inherited_entries,
     Maybe<protocol::Array<protocol::CSS::CSSKeyframesRule>>*
         css_keyframes_rules) {
-  Response response = AssertEnabled();
-  if (!response.isSuccess())
-    return response;
-
   Element* element = nullptr;
-  response = dom_agent_->AssertElement(node_id, element);
+  Response response = dom_agent_->AssertElement(node_id, element);
   if (!response.isSuccess())
     return response;
 
@@ -1098,11 +1092,8 @@
     int node_id,
     Maybe<protocol::CSS::CSSStyle>* inline_style,
     Maybe<protocol::CSS::CSSStyle>* attributes_style) {
-  Response response = AssertEnabled();
-  if (!response.isSuccess())
-    return response;
   Element* element = nullptr;
-  response = dom_agent_->AssertElement(node_id, element);
+  Response response = dom_agent_->AssertElement(node_id, element);
   if (!response.isSuccess())
     return response;
 
@@ -1120,11 +1111,8 @@
     int node_id,
     std::unique_ptr<protocol::Array<protocol::CSS::CSSComputedStyleProperty>>*
         style) {
-  Response response = AssertEnabled();
-  if (!response.isSuccess())
-    return response;
   Node* node = nullptr;
-  response = dom_agent_->AssertNode(node_id, node);
+  Response response = dom_agent_->AssertNode(node_id, node);
   if (!response.isSuccess())
     return response;
 
@@ -1190,11 +1178,8 @@
     int node_id,
     std::unique_ptr<protocol::Array<protocol::CSS::PlatformFontUsage>>*
         platform_fonts) {
-  Response response = AssertEnabled();
-  if (!response.isSuccess())
-    return response;
   Node* node = nullptr;
-  response = dom_agent_->AssertNode(node_id, node);
+  Response response = dom_agent_->AssertNode(node_id, node);
   if (!response.isSuccess())
     return response;
 
@@ -1580,11 +1565,8 @@
 Response InspectorCSSAgent::forcePseudoState(
     int node_id,
     std::unique_ptr<protocol::Array<String>> forced_pseudo_classes) {
-  Response response = AssertEnabled();
-  if (!response.isSuccess())
-    return response;
   Element* element = nullptr;
-  response = dom_agent_->AssertElement(node_id, element);
+  Response response = dom_agent_->AssertElement(node_id, element);
   if (!response.isSuccess())
     return response;
 
@@ -1909,17 +1891,9 @@
   return css_style_sheet_to_inspector_style_sheet_.at(&inspector_sheet);
 }
 
-Response InspectorCSSAgent::AssertEnabled() {
-  return was_enabled_ ? Response::OK()
-                      : Response::Error("CSS agent was not enabled");
-}
-
 Response InspectorCSSAgent::AssertInspectorStyleSheetForId(
     const String& style_sheet_id,
     InspectorStyleSheet*& result) {
-  Response response = AssertEnabled();
-  if (!response.isSuccess())
-    return response;
   IdToInspectorStyleSheet::iterator it =
       id_to_inspector_style_sheet_.find(style_sheet_id);
   if (it == id_to_inspector_style_sheet_.end())
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h
index 81f8b8b5..6b381b2 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h
@@ -280,8 +280,6 @@
   InspectorStyleSheet* InspectorStyleSheetForRule(CSSStyleRule*);
 
   InspectorStyleSheet* ViaInspectorStyleSheet(Document*);
-
-  protocol::Response AssertEnabled();
   protocol::Response AssertInspectorStyleSheetForId(const String&,
                                                     InspectorStyleSheet*&);
   protocol::Response AssertStyleSheetForId(const String&,
@@ -354,7 +352,6 @@
   Member<CSSStyleSheet> inspector_user_agent_style_sheet_;
 
   int resource_content_loader_client_id_;
-  bool was_enabled_ = false;
 
   friend class InspectorResourceContentLoaderCallback;
   friend class StyleSheetBinder;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
index dc0f1bc..01b2b58b 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
@@ -1389,7 +1389,7 @@
   // TODO(dgozman): networkStateNotifier is per-process. It would be nice to
   // have per-frame override instead.
   if (offline || latency || download_throughput || upload_throughput)
-    GetNetworkStateNotifier().SetOverride(
+    GetNetworkStateNotifier().SetNetworkConnectionInfoOverride(
         !offline, type, download_throughput / (1024 * 1024 / 8));
   else
     GetNetworkStateNotifier().ClearOverride();
diff --git a/third_party/WebKit/Source/core/loader/PingLoader.cpp b/third_party/WebKit/Source/core/loader/PingLoader.cpp
index 293fe8b..15e33dc8 100644
--- a/third_party/WebKit/Source/core/loader/PingLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/PingLoader.cpp
@@ -282,8 +282,7 @@
 }
 
 PingLoaderImpl::~PingLoaderImpl() {
-  // TODO(kinuko): Turn this to DCHECK once crbug.com/662769 is resolved.
-  CHECK(!loader_);
+  DCHECK(!loader_);
 }
 
 void PingLoaderImpl::Dispose() {
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
index 7738547a..76deee5 100644
--- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -4,6 +4,7 @@
 
 #include "core/loader/WorkerFetchContext.h"
 
+#include "core/dom/TaskRunnerHelper.h"
 #include "core/frame/Deprecation.h"
 #include "core/frame/UseCounter.h"
 #include "core/loader/MixedContentChecker.h"
@@ -13,11 +14,8 @@
 #include "platform/WebTaskRunner.h"
 #include "platform/exported/WrappedResourceRequest.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
-#include "platform/scheduler/child/web_scheduler.h"
-#include "public/platform/Platform.h"
 #include "public/platform/WebMixedContent.h"
 #include "public/platform/WebMixedContentContextType.h"
-#include "public/platform/WebThread.h"
 #include "public/platform/WebURLRequest.h"
 #include "public/platform/WebWorkerFetchContext.h"
 
@@ -80,10 +78,8 @@
     std::unique_ptr<WebWorkerFetchContext> web_context)
     : global_scope_(global_scope),
       web_context_(std::move(web_context)),
-      loading_task_runner_(Platform::Current()
-                               ->CurrentThread()
-                               ->Scheduler()
-                               ->LoadingTaskRunner()) {
+      loading_task_runner_(
+          TaskRunnerHelper::Get(TaskType::kUnspecedLoading, global_scope_)) {
   web_context_->InitializeOnWorkerThread(
       loading_task_runner_->ToSingleThreadTaskRunner());
 }
diff --git a/third_party/WebKit/Source/core/style/BorderValue.h b/third_party/WebKit/Source/core/style/BorderValue.h
index 22e75640..cf7c1d2 100644
--- a/third_party/WebKit/Source/core/style/BorderValue.h
+++ b/third_party/WebKit/Source/core/style/BorderValue.h
@@ -32,6 +32,16 @@
 
 namespace blink {
 
+// In order to conserve memory, the border width uses fixed point,
+// which can be bitpacked.  This fixed point implementation is
+// essentially the same as in LayoutUnit.  Six bits are used for the
+// fraction, which leaves 20 bits for the integer part, making 1048575
+// the largest number.
+
+static const int kBorderWidthFractionalBits = 6;
+static const int kBorderWidthDenominator = 1 << kBorderWidthFractionalBits;
+static const int kMaxForBorderWidth = ((1 << 26) - 1) / kBorderWidthDenominator;
+
 class BorderValue {
   DISALLOW_NEW();
   friend class ComputedStyle;
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index b073dd9..f8f5725d 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -886,24 +886,6 @@
           rare_non_inherited_data_->visited_link_text_decoration_color_ !=
               other.rare_non_inherited_data_
                   ->visited_link_text_decoration_color_)) ||
-        (rare_inherited_data_.Get() != other.rare_inherited_data_.Get() &&
-         (TextFillColor() != other.TextFillColor() ||
-          TextStrokeColor() != other.TextStrokeColor() ||
-          TextEmphasisColor() != other.TextEmphasisColor() ||
-          VisitedLinkTextFillColor() != other.VisitedLinkTextFillColor() ||
-          VisitedLinkTextStrokeColor() != other.VisitedLinkTextStrokeColor() ||
-          VisitedLinkTextEmphasisColor() !=
-              other.VisitedLinkTextEmphasisColor() ||
-          rare_inherited_data_->text_emphasis_fill_ !=
-              other.rare_inherited_data_->text_emphasis_fill_ ||
-          rare_inherited_data_->text_underline_position_ !=
-              other.rare_inherited_data_->text_underline_position_ ||
-          rare_inherited_data_->text_decoration_skip_ !=
-              other.rare_inherited_data_->text_decoration_skip_ ||
-          rare_inherited_data_->applied_text_decorations_ !=
-              other.rare_inherited_data_->applied_text_decorations_ ||
-          CaretColor() != CaretColor() ||
-          VisitedLinkCaretColor() != other.VisitedLinkCaretColor())) ||
         ComputedStyleBase::
             UpdatePropertySpecificDifferencesTextDecorationOrColor(other)) {
       diff.SetTextDecorationOrColorChanged();
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index d4a285e..1adb46d 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -390,16 +390,6 @@
   kResolved    // Size is fully resolved.
 };
 
-// In order to conserve memory, the border width uses fixed point,
-// which can be bitpacked.  This fixed point implementation is
-// essentially the same as in LayoutUnit.  Six bits are used for the
-// fraction, which leaves 20 bits for the integer part, making 1048575
-// the largest number.
-
-static const int kBorderWidthFractionalBits = 6;
-static const int kBorderWidthDenominator = 1 << kBorderWidthFractionalBits;
-static const int kMaxForBorderWidth = ((1 << 26) - 1) / kBorderWidthDenominator;
-
 }  // namespace blink
 
 #endif  // ComputedStyleConstants_h
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 4f71ec46..45b35aa 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -3105,7 +3105,35 @@
         ExceptionMessages::FailedToEnumerate("connection type", type));
     return;
   }
-  GetNetworkStateNotifier().SetOverride(on_line, webtype, downlink_max_mbps);
+  GetNetworkStateNotifier().SetNetworkConnectionInfoOverride(on_line, webtype,
+                                                             downlink_max_mbps);
+}
+
+void Internals::setNetworkQualityInfoOverride(const String& effective_type,
+                                              unsigned long transport_rtt_msec,
+                                              double downlink_throughput_mbps,
+                                              ExceptionState& exception_state) {
+  WebEffectiveConnectionType web_effective_type =
+      WebEffectiveConnectionType::kTypeUnknown;
+  if (effective_type == "offline") {
+    web_effective_type = WebEffectiveConnectionType::kTypeOffline;
+  } else if (effective_type == "slow-2g") {
+    web_effective_type = WebEffectiveConnectionType::kTypeSlow2G;
+  } else if (effective_type == "2g") {
+    web_effective_type = WebEffectiveConnectionType::kType2G;
+  } else if (effective_type == "3g") {
+    web_effective_type = WebEffectiveConnectionType::kType3G;
+  } else if (effective_type == "4g") {
+    web_effective_type = WebEffectiveConnectionType::kType4G;
+  } else if (effective_type != "unknown") {
+    exception_state.ThrowDOMException(
+        kNotFoundError, ExceptionMessages::FailedToEnumerate(
+                            "effective connection type", effective_type));
+    return;
+  }
+
+  GetNetworkStateNotifier().SetNetworkQualityInfoOverride(
+      web_effective_type, transport_rtt_msec, downlink_throughput_mbps);
 }
 
 void Internals::clearNetworkConnectionInfoOverride() {
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h
index 428a64f..2e98fa2e 100644
--- a/third_party/WebKit/Source/core/testing/Internals.h
+++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -478,6 +478,10 @@
                                         const String&,
                                         double downlink_max_mbps,
                                         ExceptionState&);
+  void setNetworkQualityInfoOverride(const String&,
+                                     unsigned long transport_rtt_msec,
+                                     double downlink_throughput_mbps,
+                                     ExceptionState&);
   void clearNetworkConnectionInfoOverride();
 
   unsigned countHitRegions(CanvasRenderingContext*);
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl
index 918c88f..cbe31e0 100644
--- a/third_party/WebKit/Source/core/testing/Internals.idl
+++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -24,6 +24,13 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+enum EffectiveConnectionType {
+    "slow-2g",
+    "2g",
+    "3g",
+    "4g"
+};
+
 [
     DoNotCheckConstants,
 ] interface Internals {
@@ -314,6 +321,7 @@
 
     // These functions are for testing NetInfo. You must call clearNetworkConnectionInfoOverride() at the end.
     [RaisesException] void setNetworkConnectionInfoOverride(boolean onLine, DOMString type, double downlinkMaxMbps);
+    [RaisesException] void setNetworkQualityInfoOverride(EffectiveConnectionType effective_type, unsigned long transport_rtt_msec, double downlink_throughput_mbps);
     void clearNetworkConnectionInfoOverride();
 
     // This function is for testing HitRegions on Canvas2D.
diff --git a/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp b/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp
index 73a6794..816d418 100644
--- a/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp
+++ b/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp
@@ -150,19 +150,25 @@
     const Optional<double>& downlink_mbps) {
   DCHECK(GetExecutionContext()->IsContextThread());
 
-  effective_type_ = effective_type;
-  transport_rtt_msec_ = RoundRtt(transport_rtt);
-  downlink_mbps_ = RoundMbps(downlink_mbps);
+  unsigned long new_transport_rtt_msec = RoundRtt(transport_rtt);
+  double new_downlink_mbps = RoundMbps(downlink_mbps);
   // TODO(tbansal): https://crbug.com/719108. Dispatch |change| event if the
   // expected network quality has changed.
 
   // This can happen if the observer removes and then adds itself again
-  // during notification, or if HTTP RTT was the only metric that changed.
-  if (type_ == type && downlink_max_mbps_ == downlink_max_mbps)
+  // during notification, or if |http_rtt| was the only metric that changed.
+  if (type_ == type && downlink_max_mbps_ == downlink_max_mbps &&
+      effective_type_ == effective_type &&
+      transport_rtt_msec_ == new_transport_rtt_msec &&
+      downlink_mbps_ == new_downlink_mbps) {
     return;
+  }
 
   type_ = type;
   downlink_max_mbps_ = downlink_max_mbps;
+  effective_type_ = effective_type;
+  transport_rtt_msec_ = new_transport_rtt_msec;
+  downlink_mbps_ = new_downlink_mbps;
   DispatchEvent(Event::Create(EventTypeNames::typechange));
 
   if (RuntimeEnabledFeatures::netInfoDownlinkMaxEnabled())
diff --git a/third_party/WebKit/Source/modules/shapedetection/BUILD.gn b/third_party/WebKit/Source/modules/shapedetection/BUILD.gn
index 8102c764..663f27599 100644
--- a/third_party/WebKit/Source/modules/shapedetection/BUILD.gn
+++ b/third_party/WebKit/Source/modules/shapedetection/BUILD.gn
@@ -24,5 +24,6 @@
 
   public_deps = [
     "//services/shape_detection/public/interfaces:interfaces_blink",
+    "//skia/public/interfaces:interfaces_blink",
   ]
 }
diff --git a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp
index f657b7f5..7f5f3a37 100644
--- a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp
+++ b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp
@@ -26,11 +26,8 @@
                 WrapWeakPersistent(this))));
 }
 
-ScriptPromise BarcodeDetector::DoDetect(
-    ScriptPromiseResolver* resolver,
-    mojo::ScopedSharedBufferHandle shared_buffer_handle,
-    int image_width,
-    int image_height) {
+ScriptPromise BarcodeDetector::DoDetect(ScriptPromiseResolver* resolver,
+                                        skia::mojom::blink::BitmapPtr bitmap) {
   ScriptPromise promise = resolver->Promise();
   if (!barcode_service_) {
     resolver->Reject(DOMException::Create(
@@ -39,10 +36,9 @@
   }
   barcode_service_requests_.insert(resolver);
   barcode_service_->Detect(
-      std::move(shared_buffer_handle), image_width, image_height,
-      ConvertToBaseCallback(WTF::Bind(&BarcodeDetector::OnDetectBarcodes,
-                                      WrapPersistent(this),
-                                      WrapPersistent(resolver))));
+      std::move(bitmap), ConvertToBaseCallback(WTF::Bind(
+                             &BarcodeDetector::OnDetectBarcodes,
+                             WrapPersistent(this), WrapPersistent(resolver))));
   return promise;
 }
 
diff --git a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.h b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.h
index 2f22803..12af152 100644
--- a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.h
+++ b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.h
@@ -29,9 +29,7 @@
   ~BarcodeDetector() override = default;
 
   ScriptPromise DoDetect(ScriptPromiseResolver*,
-                         mojo::ScopedSharedBufferHandle,
-                         int image_width,
-                         int image_height) override;
+                         skia::mojom::blink::BitmapPtr) override;
   void OnDetectBarcodes(
       ScriptPromiseResolver*,
       Vector<shape_detection::mojom::blink::BarcodeDetectionResultPtr>);
diff --git a/third_party/WebKit/Source/modules/shapedetection/DEPS b/third_party/WebKit/Source/modules/shapedetection/DEPS
index aefd1f3..2ebe46d3 100644
--- a/third_party/WebKit/Source/modules/shapedetection/DEPS
+++ b/third_party/WebKit/Source/modules/shapedetection/DEPS
@@ -5,6 +5,7 @@
     "+modules/imagecapture/Point2D.h",
     "+modules/shapedetection",
     "+services/shape_detection",
+    "+skia/public/interfaces/bitmap.mojom-blink.h",
     "+third_party/skia/include/core/SkImage.h",
     "+third_party/skia/include/core/SkImageInfo.h",
     "+ui/gfx/geometry",
diff --git a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp
index e9390f4..2f5c485 100644
--- a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp
+++ b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp
@@ -37,11 +37,8 @@
       &FaceDetector::OnFaceServiceConnectionError, WrapWeakPersistent(this))));
 }
 
-ScriptPromise FaceDetector::DoDetect(
-    ScriptPromiseResolver* resolver,
-    mojo::ScopedSharedBufferHandle shared_buffer_handle,
-    int image_width,
-    int image_height) {
+ScriptPromise FaceDetector::DoDetect(ScriptPromiseResolver* resolver,
+                                     skia::mojom::blink::BitmapPtr bitmap) {
   ScriptPromise promise = resolver->Promise();
   if (!face_service_) {
     resolver->Reject(DOMException::Create(
@@ -49,8 +46,7 @@
     return promise;
   }
   face_service_requests_.insert(resolver);
-  face_service_->Detect(std::move(shared_buffer_handle), image_width,
-                        image_height,
+  face_service_->Detect(std::move(bitmap),
                         ConvertToBaseCallback(WTF::Bind(
                             &FaceDetector::OnDetectFaces, WrapPersistent(this),
                             WrapPersistent(resolver))));
diff --git a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.h b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.h
index a436e7b..19dae40fb 100644
--- a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.h
+++ b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.h
@@ -31,9 +31,7 @@
   ~FaceDetector() override = default;
 
   ScriptPromise DoDetect(ScriptPromiseResolver*,
-                         mojo::ScopedSharedBufferHandle,
-                         int image_width,
-                         int image_height) override;
+                         skia::mojom::blink::BitmapPtr) override;
   void OnDetectFaces(
       ScriptPromiseResolver*,
       Vector<shape_detection::mojom::blink::FaceDetectionResultPtr>);
diff --git a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
index 98791a53f..0604c0e 100644
--- a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
+++ b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
@@ -23,28 +23,22 @@
 
 namespace {
 
-mojo::ScopedSharedBufferHandle GetSharedBufferOnData(
-    ScriptPromiseResolver* resolver,
-    uint8_t* data,
-    int size) {
-  DCHECK(data);
-  DCHECK(size);
-  ScriptPromise promise = resolver->Promise();
+skia::mojom::blink::BitmapPtr createBitmapFromData(int width,
+                                                   int height,
+                                                   Vector<uint8_t> bitmapData) {
+  skia::mojom::blink::BitmapPtr bitmap = skia::mojom::blink::Bitmap::New();
 
-  mojo::ScopedSharedBufferHandle shared_buffer_handle =
-      mojo::SharedBufferHandle::Create(size);
-  if (!shared_buffer_handle->is_valid()) {
-    resolver->Reject(
-        DOMException::Create(kInvalidStateError, "Internal allocation error"));
-    return shared_buffer_handle;
-  }
+  bitmap->color_type = (kN32_SkColorType == kRGBA_8888_SkColorType)
+                           ? skia::mojom::blink::ColorType::RGBA_8888
+                           : skia::mojom::blink::ColorType::BGRA_8888;
+  bitmap->alpha_type = skia::mojom::blink::AlphaType::ALPHA_TYPE_OPAQUE;
+  bitmap->profile_type = skia::mojom::blink::ColorProfileType::LINEAR;
+  bitmap->width = width;
+  bitmap->height = height;
+  bitmap->row_bytes = width * 4 /* bytes per pixel */;
+  bitmap->pixel_data = std::move(bitmapData);
 
-  const mojo::ScopedSharedBufferMapping mapped_buffer =
-      shared_buffer_handle->Map(size);
-  DCHECK(mapped_buffer.get());
-  memcpy(mapped_buffer.get(), data, size);
-
-  return shared_buffer_handle;
+  return bitmap;
 }
 
 }  // anonymous namespace
@@ -131,13 +125,13 @@
     return promise;
   }
 
-  mojo::ScopedSharedBufferHandle shared_buffer_handle = GetSharedBufferOnData(
-      resolver, pixel_data_ptr, allocation_size.ValueOrDefault(0));
-  if (!shared_buffer_handle->is_valid())
-    return promise;
+  WTF::Vector<uint8_t> bitmap_data;
+  bitmap_data.Append(pixel_data_ptr,
+                     static_cast<int>(allocation_size.ValueOrDefault(0)));
 
-  return DoDetect(resolver, std::move(shared_buffer_handle), image->width(),
-                  image->height());
+  return DoDetect(resolver,
+                  createBitmapFromData(image->width(), image->height(),
+                                       std::move(bitmap_data)));
 }
 
 ScriptPromise ShapeDetector::DetectShapesOnImageData(
@@ -153,13 +147,12 @@
   uint8_t* const data = image_data->data()->Data();
   WTF::CheckedNumeric<int> allocation_size = image_data->Size().Area() * 4;
 
-  mojo::ScopedSharedBufferHandle shared_buffer_handle =
-      GetSharedBufferOnData(resolver, data, allocation_size.ValueOrDefault(0));
-  if (!shared_buffer_handle->is_valid())
-    return promise;
+  WTF::Vector<uint8_t> bitmap_data;
+  bitmap_data.Append(data, static_cast<int>(allocation_size.ValueOrDefault(0)));
 
-  return DoDetect(resolver, std::move(shared_buffer_handle),
-                  image_data->width(), image_data->height());
+  return DoDetect(
+      resolver, createBitmapFromData(image_data->width(), image_data->height(),
+                                     std::move(bitmap_data)));
 }
 
 ScriptPromise ShapeDetector::DetectShapesOnImageElement(
@@ -198,28 +191,11 @@
 
   const SkImageInfo skia_info =
       SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType());
+  size_t rowBytes = skia_info.minRowBytes();
 
-  const uint32_t allocation_size =
-      skia_info.getSafeSize(skia_info.minRowBytes());
+  Vector<uint8_t> bitmap_data(skia_info.getSafeSize(rowBytes));
+  const SkPixmap pixmap(skia_info, bitmap_data.data(), rowBytes);
 
-  mojo::ScopedSharedBufferHandle shared_buffer_handle =
-      mojo::SharedBufferHandle::Create(allocation_size);
-  if (!shared_buffer_handle.is_valid()) {
-    DLOG(ERROR) << "Requested allocation : " << allocation_size
-                << "B, larger than |mojo::edk::kMaxSharedBufferSize| == 16MB ";
-    // TODO(xianglu): For now we reject the promise if the image is too large.
-    // But consider resizing the image to remove restriction on the user side.
-    // Also, add LayoutTests for this case later.
-    resolver->Reject(
-        DOMException::Create(kInvalidStateError, "Image exceeds size limit."));
-    return promise;
-  }
-
-  const mojo::ScopedSharedBufferMapping mapped_buffer =
-      shared_buffer_handle->Map(allocation_size);
-
-  const SkPixmap pixmap(skia_info, mapped_buffer.get(),
-                        skia_info.minRowBytes());
   if (!image->readPixels(pixmap, 0, 0)) {
     resolver->Reject(DOMException::Create(
         kInvalidStateError,
@@ -227,8 +203,9 @@
     return promise;
   }
 
-  return DoDetect(resolver, std::move(shared_buffer_handle),
-                  img->naturalWidth(), img->naturalHeight());
+  return DoDetect(
+      resolver, createBitmapFromData(img->naturalWidth(), img->naturalHeight(),
+                                     std::move(bitmap_data)));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.h b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.h
index b86d37b..b1bc45f 100644
--- a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.h
+++ b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.h
@@ -10,6 +10,7 @@
 #include "core/imagebitmap/ImageBitmapFactories.h"
 #include "modules/ModulesExport.h"
 #include "modules/canvas2d/CanvasRenderingContext2D.h"
+#include "skia/public/interfaces/bitmap.mojom-blink.h"
 
 namespace blink {
 
@@ -27,9 +28,7 @@
                                            const HTMLImageElement*);
 
   virtual ScriptPromise DoDetect(ScriptPromiseResolver*,
-                                 mojo::ScopedSharedBufferHandle,
-                                 int image_width,
-                                 int image_height) = 0;
+                                 skia::mojom::blink::BitmapPtr) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp
index 5de4222..1d6ad27 100644
--- a/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp
+++ b/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp
@@ -24,11 +24,8 @@
       &TextDetector::OnTextServiceConnectionError, WrapWeakPersistent(this))));
 }
 
-ScriptPromise TextDetector::DoDetect(
-    ScriptPromiseResolver* resolver,
-    mojo::ScopedSharedBufferHandle shared_buffer_handle,
-    int image_width,
-    int image_height) {
+ScriptPromise TextDetector::DoDetect(ScriptPromiseResolver* resolver,
+                                     skia::mojom::blink::BitmapPtr bitmap) {
   ScriptPromise promise = resolver->Promise();
   if (!text_service_) {
     resolver->Reject(DOMException::Create(
@@ -36,8 +33,7 @@
     return promise;
   }
   text_service_requests_.insert(resolver);
-  text_service_->Detect(std::move(shared_buffer_handle), image_width,
-                        image_height,
+  text_service_->Detect(std::move(bitmap),
                         ConvertToBaseCallback(WTF::Bind(
                             &TextDetector::OnDetectText, WrapPersistent(this),
                             WrapPersistent(resolver))));
diff --git a/third_party/WebKit/Source/modules/shapedetection/TextDetector.h b/third_party/WebKit/Source/modules/shapedetection/TextDetector.h
index 5bd4843..4d21cc6 100644
--- a/third_party/WebKit/Source/modules/shapedetection/TextDetector.h
+++ b/third_party/WebKit/Source/modules/shapedetection/TextDetector.h
@@ -29,9 +29,7 @@
   ~TextDetector() override = default;
 
   ScriptPromise DoDetect(ScriptPromiseResolver*,
-                         mojo::ScopedSharedBufferHandle,
-                         int image_width,
-                         int image_height) override;
+                         skia::mojom::blink::BitmapPtr) override;
   void OnDetectText(
       ScriptPromiseResolver*,
       Vector<shape_detection::mojom::blink::TextDetectionResultPtr>);
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
index ee7ce04..7562f9e 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
@@ -713,8 +713,15 @@
     if (start < segment_range.end && end > segment_range.start)
       ShapeSegment(&range_data, segment_range, result.Get());
   }
-  DCHECK(!result->NumCharacters() || (start == result->StartIndexForResult() &&
-                                      end == result->EndIndexForResult()));
+
+#if DCHECK_IS_ON()
+  DCHECK_EQ(length, result->NumCharacters());
+  if (length) {
+    DCHECK_EQ(start, result->StartIndexForResult());
+    DCHECK_EQ(end, result->EndIndexForResult());
+  }
+#endif
+
   return result.Release();
 }
 
diff --git a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
index ed45db0..baf8c9e 100644
--- a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
+++ b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
@@ -146,9 +146,10 @@
   RemoveObserver(on_line_state_observers_, observer, std::move(task_runner));
 }
 
-void NetworkStateNotifier::SetOverride(bool on_line,
-                                       WebConnectionType type,
-                                       double max_bandwidth_mbps) {
+void NetworkStateNotifier::SetNetworkConnectionInfoOverride(
+    bool on_line,
+    WebConnectionType type,
+    double max_bandwidth_mbps) {
   DCHECK(IsMainThread());
   ScopedNotifier notifier(*this);
   {
@@ -162,6 +163,26 @@
   }
 }
 
+void NetworkStateNotifier::SetNetworkQualityInfoOverride(
+    WebEffectiveConnectionType effective_type,
+    unsigned long transport_rtt_msec,
+    double downlink_throughput_mbps) {
+  DCHECK(IsMainThread());
+  ScopedNotifier notifier(*this);
+  {
+    MutexLocker locker(mutex_);
+    has_override_ = true;
+    override_.on_line_initialized = true;
+    override_.connection_initialized = true;
+    override_.effective_type = effective_type;
+    override_.transport_rtt =
+        base::TimeDelta::FromMilliseconds(transport_rtt_msec);
+    override_.downlink_throughput_mbps = base::nullopt;
+    if (downlink_throughput_mbps >= 0)
+      override_.downlink_throughput_mbps = downlink_throughput_mbps;
+  }
+}
+
 void NetworkStateNotifier::ClearOverride() {
   DCHECK(IsMainThread());
   ScopedNotifier notifier(*this);
diff --git a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.h b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.h
index 18e56e2..9969c26 100644
--- a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.h
+++ b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.h
@@ -172,7 +172,12 @@
   //
   // Since this class is a singleton, tests must clear override when completed
   // to avoid indeterminate state across the test harness.
-  void SetOverride(bool on_line, WebConnectionType, double max_bandwidth_mbps);
+  void SetNetworkConnectionInfoOverride(bool on_line,
+                                        WebConnectionType,
+                                        double max_bandwidth_mbps);
+  void SetNetworkQualityInfoOverride(WebEffectiveConnectionType effective_type,
+                                     unsigned long transport_rtt_msec,
+                                     double downlink_throughput_mbps);
   void ClearOverride();
 
   // Must be called on the given task runner. An added observer must be removed
diff --git a/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp b/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp
index 756603c..1797c84 100644
--- a/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp
+++ b/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp
@@ -512,7 +512,7 @@
       kUnknownThroughputMbps));
 }
 
-TEST_F(NetworkStateNotifierTest, SetOverride) {
+TEST_F(NetworkStateNotifierTest, SetNetworkConnectionInfoOverride) {
   StateObserver observer;
   notifier_.AddConnectionObserver(&observer, GetTaskRunner());
 
@@ -528,8 +528,8 @@
   EXPECT_EQ(kWebConnectionTypeBluetooth, notifier_.ConnectionType());
   EXPECT_EQ(kBluetoothMaxBandwidthMbps, notifier_.MaxBandwidth());
 
-  notifier_.SetOverride(true, kWebConnectionTypeEthernet,
-                        kEthernetMaxBandwidthMbps);
+  notifier_.SetNetworkConnectionInfoOverride(true, kWebConnectionTypeEthernet,
+                                             kEthernetMaxBandwidthMbps);
   RunPendingTasks();
   EXPECT_TRUE(VerifyObservations(
       observer, kWebConnectionTypeEthernet, kEthernetMaxBandwidthMbps,
@@ -567,6 +567,91 @@
   notifier_.RemoveConnectionObserver(&observer, GetTaskRunner());
 }
 
+TEST_F(NetworkStateNotifierTest, SetNetworkQualityInfoOverride) {
+  StateObserver observer;
+  notifier_.AddConnectionObserver(&observer, GetTaskRunner());
+
+  notifier_.SetOnLine(true);
+  SetConnection(kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+                WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt,
+                kUnknownRtt, kUnknownThroughputMbps);
+  EXPECT_TRUE(VerifyObservations(
+      observer, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+      WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+      kUnknownThroughputMbps));
+  EXPECT_TRUE(notifier_.OnLine());
+  EXPECT_EQ(kWebConnectionTypeBluetooth, notifier_.ConnectionType());
+  EXPECT_EQ(kBluetoothMaxBandwidthMbps, notifier_.MaxBandwidth());
+
+  notifier_.SetNetworkQualityInfoOverride(
+      WebEffectiveConnectionType::kType3G,
+      kEthernetTransportRtt.value().InMilliseconds(),
+      kEthernetThroughputMbps.value());
+  RunPendingTasks();
+  EXPECT_TRUE(VerifyObservations(
+      observer, kWebConnectionTypeOther,
+      NetworkStateNotifier::NetworkState::kInvalidMaxBandwidth,
+      WebEffectiveConnectionType::kType3G, kUnknownRtt, kEthernetTransportRtt,
+      kEthernetThroughputMbps));
+  EXPECT_TRUE(notifier_.OnLine());
+  EXPECT_EQ(kWebConnectionTypeOther, notifier_.ConnectionType());
+  EXPECT_EQ(-1, notifier_.MaxBandwidth());
+  EXPECT_EQ(WebEffectiveConnectionType::kType3G, notifier_.EffectiveType());
+  EXPECT_EQ(kEthernetTransportRtt, notifier_.TransportRtt());
+  EXPECT_EQ(kEthernetThroughputMbps, notifier_.DownlinkThroughputMbps());
+
+  // When override is active, calls to SetConnection are temporary ignored.
+  notifier_.SetOnLine(false);
+  SetConnection(kWebConnectionTypeNone, kNoneMaxBandwidthMbps,
+                WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt,
+                kUnknownRtt, kUnknownThroughputMbps);
+  RunPendingTasks();
+  EXPECT_TRUE(VerifyObservations(
+      observer, kWebConnectionTypeOther,
+      NetworkStateNotifier::NetworkState::kInvalidMaxBandwidth,
+      WebEffectiveConnectionType::kType3G, kUnknownRtt, kEthernetTransportRtt,
+      kEthernetThroughputMbps));
+  EXPECT_TRUE(notifier_.OnLine());
+  EXPECT_EQ(kWebConnectionTypeOther, notifier_.ConnectionType());
+  EXPECT_EQ(-1, notifier_.MaxBandwidth());
+  EXPECT_EQ(WebEffectiveConnectionType::kType3G, notifier_.EffectiveType());
+  EXPECT_EQ(kEthernetTransportRtt, notifier_.TransportRtt());
+  EXPECT_EQ(kEthernetThroughputMbps, notifier_.DownlinkThroughputMbps());
+
+  // Override the network connection info as well.
+  notifier_.SetNetworkConnectionInfoOverride(true, kWebConnectionTypeEthernet,
+                                             kEthernetMaxBandwidthMbps);
+  RunPendingTasks();
+  EXPECT_TRUE(VerifyObservations(
+      observer, kWebConnectionTypeEthernet, kEthernetMaxBandwidthMbps,
+      WebEffectiveConnectionType::kType3G, kUnknownRtt, kEthernetTransportRtt,
+      kEthernetThroughputMbps));
+  EXPECT_TRUE(notifier_.OnLine());
+  EXPECT_EQ(kWebConnectionTypeEthernet, notifier_.ConnectionType());
+  EXPECT_EQ(kEthernetMaxBandwidthMbps, notifier_.MaxBandwidth());
+  EXPECT_EQ(WebEffectiveConnectionType::kType3G, notifier_.EffectiveType());
+  EXPECT_EQ(kEthernetTransportRtt, notifier_.TransportRtt());
+  EXPECT_EQ(kEthernetThroughputMbps, notifier_.DownlinkThroughputMbps());
+
+  // CLearing the override should cause the network state to be changed and
+  // notified to observers.
+  notifier_.ClearOverride();
+  RunPendingTasks();
+  EXPECT_TRUE(VerifyObservations(
+      observer, kWebConnectionTypeNone, kNoneMaxBandwidthMbps,
+      WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+      kUnknownThroughputMbps));
+  EXPECT_FALSE(notifier_.OnLine());
+  EXPECT_EQ(kWebConnectionTypeNone, notifier_.ConnectionType());
+  EXPECT_EQ(kNoneMaxBandwidthMbps, notifier_.MaxBandwidth());
+  EXPECT_EQ(WebEffectiveConnectionType::kTypeUnknown,
+            notifier_.EffectiveType());
+  EXPECT_EQ(kUnknownRtt, notifier_.TransportRtt());
+  EXPECT_EQ(kUnknownThroughputMbps, notifier_.DownlinkThroughputMbps());
+
+  notifier_.RemoveConnectionObserver(&observer, GetTaskRunner());
+}
+
 TEST_F(NetworkStateNotifierTest, NoExtraNotifications) {
   StateObserver observer;
   notifier_.AddConnectionObserver(&observer, GetTaskRunner());
diff --git a/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp b/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp
index 842b662..73ee0296 100644
--- a/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp
@@ -53,8 +53,7 @@
     void CancelWakeLock() override { registry_->SetWakeLockStatus(false); }
     void AddClient(
         device::mojom::blink::WakeLockServiceRequest wake_lock) override {}
-    void HasWakeLockForTests(
-        const HasWakeLockForTestsCallback& callback) override {}
+    void HasWakeLockForTests(HasWakeLockForTestsCallback callback) override {}
 
     mojo::Binding<WakeLockService> binding_;
     MockInterfaceProvider* const registry_;