diff --git a/cc/tiles/tile.h b/cc/tiles/tile.h
index 50eb6d1..d413c3c0 100644
--- a/cc/tiles/tile.h
+++ b/cc/tiles/tile.h
@@ -67,6 +67,10 @@
     required_for_draw_ = is_required;
   }
 
+  bool is_prepaint() const {
+    return !required_for_activation() && !required_for_draw();
+  }
+
   bool use_picture_analysis() const {
     return !!(flags_ & USE_PICTURE_ANALYSIS);
   }
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index f3f52fa..1484864 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -705,8 +705,7 @@
     }
 
     // Prepaint tiles that are far away are only processed for images.
-    if (!tile->required_for_activation() && !tile->required_for_draw() &&
-        prioritized_tile.is_process_for_images_only()) {
+    if (tile->is_prepaint() && prioritized_tile.is_process_for_images_only()) {
       work_to_schedule.tiles_to_process_for_images.push_back(prioritized_tile);
       continue;
     }
@@ -734,8 +733,6 @@
       break;
     }
 
-    tile->scheduled_priority_ = schedule_priority++;
-
     DCHECK(tile->draw_info().mode() == TileDrawInfo::OOM_MODE ||
            !tile->draw_info().IsReadyToDraw());
 
@@ -787,11 +784,16 @@
     } else {
       // Creating the raster task here will acquire resources, but
       // this resource usage has already been accounted for above.
-      tile->raster_task_ =
-          CreateRasterTask(prioritized_tile, client_->GetRasterColorSpace(),
-                           &work_to_schedule.checker_image_decode_queue);
+      auto raster_task = CreateRasterTask(
+          prioritized_tile, client_->GetRasterColorSpace(), &work_to_schedule);
+      if (!raster_task) {
+        continue;
+      }
+
+      tile->raster_task_ = std::move(raster_task);
     }
 
+    tile->scheduled_priority_ = schedule_priority++;
     memory_usage += memory_required_by_tile_to_be_scheduled;
     work_to_schedule.tiles_to_raster.push_back(prioritized_tile);
   }
@@ -1040,6 +1042,10 @@
     }
   }
 
+  new_locked_images.insert(new_locked_images.end(),
+                           work_to_schedule.extra_prepaint_images.begin(),
+                           work_to_schedule.extra_prepaint_images.end());
+
   // TODO(vmpstr): SOON is misleading here, but these images can come from
   // several diffent tiles. Rethink what we actually want to trace here. Note
   // that I'm using SOON, since it can't be NOW (these are prepaint).
@@ -1049,6 +1055,8 @@
   std::vector<scoped_refptr<TileTask>> new_locked_image_tasks =
       image_controller_.SetPredecodeImages(std::move(new_locked_images),
                                            tracing_info);
+  work_to_schedule.extra_prepaint_images.clear();
+
   for (auto& task : new_locked_image_tasks) {
     auto decode_it = std::find_if(graph_.nodes.begin(), graph_.nodes.end(),
                                   [&task](const TaskGraph::Node& node) {
@@ -1112,7 +1120,7 @@
 scoped_refptr<TileTask> TileManager::CreateRasterTask(
     const PrioritizedTile& prioritized_tile,
     const gfx::ColorSpace& color_space,
-    CheckerImageTracker::ImageDecodeQueue* checker_image_decode_queue) {
+    PrioritizedWorkToSchedule* work_to_schedule) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "TileManager::CreateRasterTask");
   Tile* tile = prioritized_tile.tile();
@@ -1154,35 +1162,15 @@
   std::vector<DrawImage>& sync_decoded_images =
       scheduled_draw_images_[tile->id()];
   sync_decoded_images.clear();
-  PaintImageIdFlatSet images_to_skip;
+  std::vector<PaintImage> checkered_images;
   base::flat_map<PaintImage::Id, size_t> image_id_to_current_frame_index;
   if (!skip_images) {
-    std::vector<PaintImage> checkered_images;
     PartitionImagesForCheckering(
         prioritized_tile, color_space, &sync_decoded_images, &checkered_images,
         partial_tile_decode ? &invalidated_rect : nullptr,
         &image_id_to_current_frame_index);
-    for (const auto& image : checkered_images) {
-      DCHECK(!image.ShouldAnimate());
-
-      images_to_skip.insert(image.stable_id());
-
-      // This can be the case for tiles on the active tree that will be replaced
-      // or are occluded on the pending tree. While we still need to continue
-      // skipping images for these tiles, we don't need to decode them since
-      // they will not be required on the next active tree.
-      if (prioritized_tile.should_decode_checkered_images_for_tile()) {
-        checker_image_decode_queue->emplace_back(
-            image, CheckerImageTracker::DecodeType::kRaster);
-      }
-    }
   }
 
-  const bool has_checker_images = !images_to_skip.empty();
-  tile->set_raster_task_scheduled_with_checker_images(has_checker_images);
-  if (has_checker_images)
-    num_of_tiles_with_checker_images_++;
-
   // Get the tasks for the required images.
   ImageDecodeCache::TracingInfo tracing_info(
       prepare_tiles_count_, prioritized_tile.priority().priority_bin,
@@ -1191,6 +1179,39 @@
   image_controller_.GetTasksForImagesAndRef(
       &sync_decoded_images, &at_raster_images, &decode_tasks, tracing_info);
 
+  const bool has_checker_images = !checkered_images.empty();
+  tile->set_raster_task_scheduled_with_checker_images(has_checker_images);
+  if (has_checker_images)
+    num_of_tiles_with_checker_images_++;
+
+  // Don't allow at-raster prepaint tiles, because they could be very slow
+  // and block high-priority tasks.
+  if (!at_raster_images.empty() && tile->is_prepaint()) {
+    work_to_schedule->extra_prepaint_images.insert(
+        work_to_schedule->extra_prepaint_images.end(),
+        sync_decoded_images.begin(), sync_decoded_images.end());
+    // This will unref the images, but ScheduleTasks will schedule them
+    // right away anyway.
+    OnRasterTaskCompleted(tile->id(), resource, true /* was_canceled */);
+    return nullptr;
+  }
+
+  PaintImageIdFlatSet images_to_skip;
+  for (const auto& image : checkered_images) {
+    DCHECK(!image.ShouldAnimate());
+
+    images_to_skip.insert(image.stable_id());
+
+    // This can be the case for tiles on the active tree that will be replaced
+    // or are occluded on the pending tree. While we still need to continue
+    // skipping images for these tiles, we don't need to decode them since
+    // they will not be required on the next active tree.
+    if (prioritized_tile.should_decode_checkered_images_for_tile()) {
+      work_to_schedule->checker_image_decode_queue.emplace_back(
+          image, CheckerImageTracker::DecodeType::kRaster);
+    }
+  }
+
   std::unique_ptr<RasterBuffer> raster_buffer =
       raster_buffer_provider_->AcquireBufferForRaster(
           resource, resource_content_id, tile->invalidated_id());
@@ -1224,16 +1245,14 @@
   signals_.reset();
 }
 
-void TileManager::OnRasterTaskCompleted(
-    Tile::Id tile_id,
-    Resource* resource,
-    bool was_canceled) {
+void TileManager::OnRasterTaskCompleted(Tile::Id tile_id,
+                                        Resource* resource,
+                                        bool was_canceled) {
   auto found = tiles_.find(tile_id);
   Tile* tile = nullptr;
   bool raster_task_was_scheduled_with_checker_images = false;
   if (found != tiles_.end()) {
     tile = found->second;
-    DCHECK(tile->raster_task_.get());
     tile->raster_task_ = nullptr;
     raster_task_was_scheduled_with_checker_images =
         tile->set_raster_task_scheduled_with_checker_images(false);
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h
index 1061726..ddad219 100644
--- a/cc/tiles/tile_manager.h
+++ b/cc/tiles/tile_manager.h
@@ -323,6 +323,9 @@
 
     std::vector<PrioritizedTile> tiles_to_raster;
     std::vector<PrioritizedTile> tiles_to_process_for_images;
+    // A vector of additional images to be decoded for prepaint, but that
+    // are not necessarily associated with any tile.
+    std::vector<DrawImage> extra_prepaint_images;
     CheckerImageTracker::ImageDecodeQueue checker_image_decode_queue;
   };
 
@@ -331,7 +334,7 @@
   scoped_refptr<TileTask> CreateRasterTask(
       const PrioritizedTile& prioritized_tile,
       const gfx::ColorSpace& color_space,
-      CheckerImageTracker::ImageDecodeQueue* checker_image_decode_queue);
+      PrioritizedWorkToSchedule* work_to_schedule);
 
   std::unique_ptr<EvictionTilePriorityQueue>
   FreeTileResourcesUntilUsageIsWithinLimit(
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index d6d4536..6a7c7bc 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -2510,6 +2510,89 @@
   EXPECT_FALSE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting());
 }
 
+class EmptyCacheTileManagerTest : public TileManagerTest {
+ public:
+  LayerTreeSettings CreateSettings() override {
+    LayerTreeSettings settings;
+    settings.decoded_image_working_set_budget_bytes = 0;
+    return settings;
+  }
+};
+
+TEST_F(EmptyCacheTileManagerTest, AtRasterOnScreenTileRasterTasks) {
+  const gfx::Size layer_bounds(500, 500);
+
+  std::unique_ptr<FakeRecordingSource> recording_source =
+      FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
+  recording_source->set_fill_with_nonsolid_color(true);
+
+  int dimension = 500;
+  PaintImage image =
+      CreateDiscardablePaintImage(gfx::Size(dimension, dimension));
+  recording_source->add_draw_image(image, gfx::Point(0, 0));
+
+  recording_source->Rerecord();
+  scoped_refptr<RasterSource> raster_source =
+      recording_source->CreateRasterSource();
+
+  gfx::Size tile_size(500, 500);
+  Region invalidation((gfx::Rect(layer_bounds)));
+  SetupPendingTree(raster_source, tile_size, invalidation);
+
+  PictureLayerTilingSet* tiling_set =
+      pending_layer()->picture_layer_tiling_set();
+  PictureLayerTiling* pending_tiling = tiling_set->tiling_at(0);
+  pending_tiling->set_resolution(HIGH_RESOLUTION);
+  pending_tiling->CreateAllTilesForTesting();
+  pending_tiling->SetTilePriorityRectsForTesting(
+      gfx::Rect(layer_bounds),   // Visible rect.
+      gfx::Rect(layer_bounds),   // Skewport rect.
+      gfx::Rect(layer_bounds),   // Soon rect.
+      gfx::Rect(layer_bounds));  // Eventually rect.
+
+  host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+  // There will be a tile raster task and an image decode task.
+  EXPECT_TRUE(pending_tiling->TileAt(0, 0)->HasRasterTask());
+  EXPECT_TRUE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting());
+}
+
+TEST_F(EmptyCacheTileManagerTest, AtRasterPrepaintTileRasterTasksSkipped) {
+  const gfx::Size layer_bounds(500, 500);
+
+  std::unique_ptr<FakeRecordingSource> recording_source =
+      FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
+  recording_source->set_fill_with_nonsolid_color(true);
+
+  int dimension = 500;
+  PaintImage image =
+      CreateDiscardablePaintImage(gfx::Size(dimension, dimension));
+  recording_source->add_draw_image(image, gfx::Point(0, 0));
+
+  recording_source->Rerecord();
+  scoped_refptr<RasterSource> raster_source =
+      recording_source->CreateRasterSource();
+
+  gfx::Size tile_size(500, 500);
+  Region invalidation((gfx::Rect(layer_bounds)));
+  SetupPendingTree(raster_source, tile_size, invalidation);
+
+  PictureLayerTilingSet* tiling_set =
+      pending_layer()->picture_layer_tiling_set();
+  PictureLayerTiling* pending_tiling = tiling_set->tiling_at(0);
+  pending_tiling->set_resolution(HIGH_RESOLUTION);
+  pending_tiling->CreateAllTilesForTesting();
+  pending_tiling->SetTilePriorityRectsForTesting(
+      gfx::Rect(),  // An empty visual rect leads to the tile being pre-paint.
+      gfx::Rect(layer_bounds),   // Skewport rect.
+      gfx::Rect(layer_bounds),   // Soon rect.
+      gfx::Rect(layer_bounds));  // Eventually rect.
+
+  host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+  // There will be no tile raster task, but there will be an image decode task.
+  EXPECT_FALSE(pending_tiling->TileAt(0, 0)->HasRasterTask());
+  EXPECT_TRUE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting());
+}
+
 TEST_F(CheckerImagingTileManagerTest, BuildsImageDecodeQueueAsExpected) {
   const gfx::Size layer_bounds(900, 900);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
index 0db59b1..a995c52 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
@@ -25,6 +25,7 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.ContentSettingsType;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleCell;
 import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleWifi;
@@ -389,10 +390,12 @@
      */
     static boolean isLocationDisabledForUrl(Uri uri, boolean isIncognito) {
         boolean enabled =
-                // TODO(raymes): The call to arePermissionsControlledByDSE is only needed if this
+                // TODO(raymes): The call to isPermissionControlledByDSE is only needed if this
                 // could be called for an origin that isn't the default search engine. Otherwise
                 // remove this line.
-                WebsitePreferenceBridge.arePermissionsControlledByDSE(uri.toString(), isIncognito)
+                WebsitePreferenceBridge.isPermissionControlledByDSE(
+                        ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION, uri.toString(),
+                        isIncognito)
                 && locationContentSettingForUrl(uri, isIncognito) == ContentSetting.ALLOW;
         return !enabled;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
index e1cbfb8..f3a0ec4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
@@ -676,8 +676,7 @@
                 assert false : "Invalid setting " + permission.setting + " for permission "
                         + permission.type;
         }
-        if (permission.type == ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION
-                && WebsitePreferenceBridge.arePermissionsControlledByDSE(mFullUrl, false)) {
+        if (WebsitePreferenceBridge.isPermissionControlledByDSE(permission.type, mFullUrl, false)) {
             status_text = statusTextForDSEPermission(permission);
         }
         builder.append(status_text);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
index 1ebff007..f1009a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
@@ -617,7 +617,8 @@
     private void setUpLocationPreference(Preference preference) {
         ContentSetting permission = mSite.getGeolocationPermission();
         setUpListPreference(preference, permission);
-        if (arePermissionsControlledByDSE() && permission != null) {
+        if (isPermissionControlledByDSE(ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION)
+                && permission != null) {
             updateLocationPreferenceForDSESetting(preference);
         }
     }
@@ -672,9 +673,9 @@
      * Returns true if the DSE (default search engine) geolocation and notifications permissions
      * are configured for the DSE.
      */
-    private boolean arePermissionsControlledByDSE() {
-        return WebsitePreferenceBridge.arePermissionsControlledByDSE(
-                mSite.getAddress().getOrigin(), false);
+    private boolean isPermissionControlledByDSE(@ContentSettingsType int contentSettingsType) {
+        return WebsitePreferenceBridge.isPermissionControlledByDSE(
+                contentSettingsType, mSite.getAddress().getOrigin(), false);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java
index a05c547..badf166cd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java
@@ -6,6 +6,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.annotations.CalledByNative;
+import org.chromium.chrome.browser.ContentSettingsType;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 
 import java.util.ArrayList;
@@ -169,7 +170,7 @@
     }
 
     public static List<ContentSettingException> getContentSettingsExceptions(
-            int contentSettingsType) {
+            @ContentSettingsType int contentSettingsType) {
         List<ContentSettingException> exceptions =
                 PrefServiceBridge.getInstance().getContentSettingsExceptions(
                         contentSettingsType);
@@ -218,11 +219,12 @@
     }
 
     /**
-     * Returns whether the DSE (Default Search Engine) controls the geolocation
-     * and notifications settings for the given origin.
+     * Returns whether the DSE (Default Search Engine) controls the given permission the given
+     * origin.
      */
-    public static boolean arePermissionsControlledByDSE(String origin, boolean isIncognito) {
-        return nativeArePermissionsControlledByDSE(origin, isIncognito);
+    public static boolean isPermissionControlledByDSE(
+            @ContentSettingsType int contentSettingsType, String origin, boolean isIncognito) {
+        return nativeIsPermissionControlledByDSE(contentSettingsType, origin, isIncognito);
     }
 
     /**
@@ -274,8 +276,8 @@
     static native void nativeGetUsbOrigins(Object list);
     static native void nativeRevokeUsbPermission(String origin, String embedder, String object);
     static native void nativeClearBannerData(String origin);
-    private static native boolean nativeArePermissionsControlledByDSE(
-            String origin, boolean isIncognito);
+    private static native boolean nativeIsPermissionControlledByDSE(
+            @ContentSettingsType int contentSettingsType, String origin, boolean isIncognito);
     private static native boolean nativeGetAdBlockingActivated(String origin);
     static native void nativeResetNotificationsSettingsForTest();
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java
index e1bc0c00..3291e5d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java
@@ -26,6 +26,7 @@
 
 import org.chromium.base.library_loader.ProcessInitException;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.ContentSettingsType;
 import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderUnitTest.ShadowRecordHistogram;
 import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderUnitTest.ShadowUrlUtilities;
 import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderUnitTest.ShadowWebsitePreferenceBridge;
@@ -306,7 +307,8 @@
     @Implements(WebsitePreferenceBridge.class)
     public static class ShadowWebsitePreferenceBridge {
         @Implementation
-        public static boolean arePermissionsControlledByDSE(String origin, boolean isIncognito) {
+        public static boolean isPermissionControlledByDSE(
+                @ContentSettingsType int contentSettingsType, String origin, boolean isIncognito) {
             return true;
         }
 
diff --git a/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.cc b/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.cc
index 1384190..91c2c51 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.cc
@@ -18,6 +18,7 @@
 #include "components/assist_ranker/binary_classifier_predictor.h"
 #include "components/assist_ranker/proto/ranker_example.pb.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/ukm/content/source_url_recorder.h"
 #include "content/public/browser/web_contents.h"
 #include "jni/ContextualSearchRankerLoggerImpl_jni.h"
 #include "services/metrics/public/cpp/ukm_entry_builder.h"
@@ -52,8 +53,7 @@
 
 ContextualSearchRankerLoggerImpl::ContextualSearchRankerLoggerImpl(JNIEnv* env,
                                                                    jobject obj)
-    : ukm_recorder_(nullptr),
-      source_id_(0),
+    : source_id_(ukm::kInvalidSourceId),
       builder_(nullptr),
       predictor_(nullptr),
       browser_context_(nullptr),
@@ -76,9 +76,8 @@
   if (!web_contents)
     return;
 
-  GURL page_url = web_contents->GetURL();
-  ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
-  SetUkmRecorder(ukm_recorder, page_url);
+  source_id_ = ukm::GetSourceIdForWebContentsDocument(web_contents);
+  ResetUkmEntry();
 
   if (IsRankerQueryEnabled()) {
     SetupRankerPredictor(web_contents);
@@ -90,18 +89,10 @@
   }
 }
 
-void ContextualSearchRankerLoggerImpl::SetUkmRecorder(
-    ukm::UkmRecorder* ukm_recorder,
-    const GURL& page_url) {
-  if (!ukm_recorder) {
-    builder_.reset();
-    return;
-  }
-
-  ukm_recorder_ = ukm_recorder;
-  source_id_ = ukm_recorder_->GetNewSourceID();
-  ukm_recorder_->UpdateSourceURL(source_id_, page_url);
-  builder_ = ukm_recorder_->GetEntryBuilder(source_id_, "ContextualSearch");
+void ContextualSearchRankerLoggerImpl::ResetUkmEntry() {
+  // Releasing the old entry triggers logging.
+  builder_ =
+      ukm::UkmRecorder::Get()->GetEntryBuilder(source_id_, "ContextualSearch");
 }
 
 void ContextualSearchRankerLoggerImpl::SetupRankerPredictor(
@@ -186,11 +177,8 @@
 void ContextualSearchRankerLoggerImpl::WriteLogAndReset(JNIEnv* env,
                                                         jobject obj) {
   has_predicted_decision_ = false;
-  if (!ukm_recorder_)
-    return;
-
   // Set up another builder for the next record (in case it's needed).
-  builder_ = ukm_recorder_->GetEntryBuilder(source_id_, "ContextualSearch");
+  ResetUkmEntry();
   ranker_example_.reset();
 }
 
diff --git a/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.h b/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.h
index 19e76f2..e06433d 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.h
+++ b/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.h
@@ -7,8 +7,6 @@
 
 #include "base/android/jni_android.h"
 
-class GURL;
-
 namespace content {
 class BrowserContext;
 class WebContents;
@@ -21,7 +19,6 @@
 
 namespace ukm {
 class UkmEntryBuilder;
-class UkmRecorder;
 }  // namespace ukm
 
 // A Java counterpart will be generated for this enum.
@@ -69,9 +66,9 @@
   void WriteLogAndReset(JNIEnv* env, jobject obj);
 
  private:
-  // Set the UKM recorder and base-page URL.
-  // TODO(donnd): write a test, using this to inject a test-ukm-recorder.
-  void SetUkmRecorder(ukm::UkmRecorder* ukm_recorder, const GURL& page_url);
+  // Log the current UKM entry (if any) and start a new one.
+  // TODO(donnd): write a test using TestAutoSetUkmRecorder.
+  void ResetUkmEntry();
 
   // Sets up the Ranker Predictor for the given |web_contents|.
   void SetupRankerPredictor(content::WebContents* web_contents);
@@ -79,10 +76,6 @@
   // Whether querying Ranker for model loading and prediction is enabled.
   bool IsRankerQueryEnabled();
 
-  // Used to log URL-keyed metrics. This pointer will outlive |this|, and may
-  // be nullptr.
-  ukm::UkmRecorder* ukm_recorder_;
-
   // The UKM source ID being used for this session.
   int32_t source_id_;
 
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc
index eda997cc..c83e56ce 100644
--- a/chrome/browser/android/preferences/website_preference_bridge.cc
+++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -91,10 +91,11 @@
           GetActiveUserProfile(is_incognito));
   bool same_embedder = embedder.is_empty() || embedder == origin;
   if (same_embedder && search_helper &&
-      search_helper->ArePermissionsControlledByDSE(
-          url::Origin::Create(origin)) &&
+      search_helper->IsPermissionControlledByDSE(type,
+                                                 url::Origin::Create(origin)) &&
       setting == CONTENT_SETTING_DEFAULT) {
-    return search_helper->ResetDSEPermission(type);
+    search_helper->ResetDSEPermission(type);
+    return true;
   }
   return false;
 }
@@ -826,16 +827,18 @@
       CONTENT_SETTINGS_TYPE_APP_BANNER, std::string(), nullptr);
 }
 
-static jboolean JNI_WebsitePreferenceBridge_ArePermissionsControlledByDSE(
+static jboolean JNI_WebsitePreferenceBridge_IsPermissionControlledByDSE(
     JNIEnv* env,
     const JavaParamRef<jclass>& clazz,
+    int content_settings_type,
     const JavaParamRef<jstring>& jorigin,
     jboolean is_incognito) {
   SearchPermissionsService* search_helper =
       SearchPermissionsService::Factory::GetForBrowserContext(
           GetActiveUserProfile(is_incognito));
   return search_helper &&
-         search_helper->ArePermissionsControlledByDSE(
+         search_helper->IsPermissionControlledByDSE(
+             static_cast<ContentSettingsType>(content_settings_type),
              url::Origin::Create(GURL(ConvertJavaStringToUTF8(env, jorigin))));
 }
 
diff --git a/chrome/browser/android/search_permissions/search_geolocation_disclosure_tab_helper.cc b/chrome/browser/android/search_permissions/search_geolocation_disclosure_tab_helper.cc
index d16a8937..a6f2737 100644
--- a/chrome/browser/android/search_permissions/search_geolocation_disclosure_tab_helper.cc
+++ b/chrome/browser/android/search_permissions/search_geolocation_disclosure_tab_helper.cc
@@ -184,7 +184,8 @@
   if (gIgnoreUrlChecksForTesting)
     return true;
 
-  return service->ArePermissionsControlledByDSE(url::Origin::Create(gurl));
+  return service->IsPermissionControlledByDSE(CONTENT_SETTINGS_TYPE_GEOLOCATION,
+                                              url::Origin::Create(gurl));
 }
 
 bool SearchGeolocationDisclosureTabHelper::ShouldShowDisclosureForNavigation(
diff --git a/chrome/browser/android/search_permissions/search_permissions_service.cc b/chrome/browser/android/search_permissions/search_permissions_service.cc
index 29463f4..ddf59d5 100644
--- a/chrome/browser/android/search_permissions/search_permissions_service.cc
+++ b/chrome/browser/android/search_permissions/search_permissions_service.cc
@@ -159,8 +159,19 @@
   InitializeSettingsIfNeeded();
 }
 
-bool SearchPermissionsService::ArePermissionsControlledByDSE(
+bool SearchPermissionsService::IsPermissionControlledByDSE(
+    ContentSettingsType type,
     const url::Origin& requesting_origin) {
+  if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS &&
+      !base::FeatureList::IsEnabled(features::kGrantNotificationsToDSE)) {
+    return false;
+  }
+
+  if (type != CONTENT_SETTINGS_TYPE_GEOLOCATION &&
+      type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+    return false;
+  }
+
   if (requesting_origin.scheme() != url::kHttpsScheme)
     return false;
 
@@ -170,20 +181,13 @@
   return true;
 }
 
-bool SearchPermissionsService::ResetDSEPermission(ContentSettingsType type) {
-  GURL dse_origin = delegate_->GetDSEOrigin().GetURL();
-  if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
-    SetContentSetting(dse_origin, type, CONTENT_SETTING_ALLOW);
-    return true;
-  }
+void SearchPermissionsService::ResetDSEPermission(ContentSettingsType type) {
+  url::Origin dse_origin = delegate_->GetDSEOrigin();
+  GURL dse_url = dse_origin.GetURL();
+  DCHECK(dse_url.is_empty() || IsPermissionControlledByDSE(type, dse_origin));
 
-  if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS &&
-      base::FeatureList::IsEnabled(features::kGrantNotificationsToDSE)) {
-    SetContentSetting(dse_origin, type, CONTENT_SETTING_ALLOW);
-    return true;
-  }
-
-  return false;
+  if (!dse_url.is_empty())
+    SetContentSetting(dse_url, type, CONTENT_SETTING_ALLOW);
 }
 
 void SearchPermissionsService::ResetDSEPermissions() {
@@ -451,10 +455,8 @@
 ContentSetting SearchPermissionsService::GetContentSetting(
     const GURL& origin,
     ContentSettingsType type) {
-  // TODO(raymes): For this to be correct, it should only query the user-defined
-  // settings in HostContentSettingsMap. Add a function to do this.
-  return host_content_settings_map_->GetContentSetting(origin, origin, type,
-                                                       std::string());
+  return host_content_settings_map_->GetUserModifiableContentSetting(
+      origin, origin, type, std::string());
 }
 
 void SearchPermissionsService::SetContentSetting(const GURL& origin,
diff --git a/chrome/browser/android/search_permissions/search_permissions_service.h b/chrome/browser/android/search_permissions/search_permissions_service.h
index 785fd58d..8110e1f 100644
--- a/chrome/browser/android/search_permissions/search_permissions_service.h
+++ b/chrome/browser/android/search_permissions/search_permissions_service.h
@@ -74,13 +74,13 @@
 
   explicit SearchPermissionsService(Profile* profile);
 
-  // Returns whether the geolocation and notifications permissions are being
-  // configured for the DSE for that given origin.
-  bool ArePermissionsControlledByDSE(const url::Origin& requesting_origin);
+  // Returns whether the given permission is being configured for the DSE for
+  // the given origin.
+  bool IsPermissionControlledByDSE(ContentSettingsType type,
+                                   const url::Origin& requesting_origin);
 
-  // Resets the DSE permission for a single ContentSettingsType. Returns true
-  // if that type is controlled by the DSE and was thus reset, false otherwise.
-  bool ResetDSEPermission(ContentSettingsType type);
+  // Resets the DSE permission for a single ContentSettingsType.
+  void ResetDSEPermission(ContentSettingsType type);
 
   // Reset all supported DSE permissions.
   void ResetDSEPermissions();
diff --git a/chrome/browser/android/search_permissions/search_permissions_service_unittest.cc b/chrome/browser/android/search_permissions/search_permissions_service_unittest.cc
index da1e219..95fd8b4 100644
--- a/chrome/browser/android/search_permissions/search_permissions_service_unittest.cc
+++ b/chrome/browser/android/search_permissions/search_permissions_service_unittest.cc
@@ -283,25 +283,29 @@
       profile()));
 }
 
-TEST_F(SearchPermissionsServiceTest, ArePermissionsControlledByDSE) {
+TEST_F(SearchPermissionsServiceTest, IsPermissionControlledByDSE) {
   // True for origin that matches the CCTLD and meets all requirements.
   test_delegate()->ChangeDSEOrigin(kGoogleURL);
-  EXPECT_TRUE(
-      GetService()->ArePermissionsControlledByDSE(ToOrigin(kGoogleURL)));
+  EXPECT_TRUE(GetService()->IsPermissionControlledByDSE(
+      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, ToOrigin(kGoogleURL)));
 
   // False for different origin.
-  EXPECT_FALSE(
-      GetService()->ArePermissionsControlledByDSE(ToOrigin(kGoogleAusURL)));
+  EXPECT_FALSE(GetService()->IsPermissionControlledByDSE(
+      CONTENT_SETTINGS_TYPE_GEOLOCATION, ToOrigin(kGoogleAusURL)));
 
   // False for http origin.
   test_delegate()->ChangeDSEOrigin(kGoogleHTTPURL);
-  EXPECT_FALSE(
-      GetService()->ArePermissionsControlledByDSE(ToOrigin(kGoogleHTTPURL)));
+  EXPECT_FALSE(GetService()->IsPermissionControlledByDSE(
+      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, ToOrigin(kGoogleHTTPURL)));
 
   // True even for non-Google search engines.
   test_delegate()->ChangeDSEOrigin(kExampleURL);
-  EXPECT_TRUE(
-      GetService()->ArePermissionsControlledByDSE(ToOrigin(kExampleURL)));
+  EXPECT_TRUE(GetService()->IsPermissionControlledByDSE(
+      CONTENT_SETTINGS_TYPE_GEOLOCATION, ToOrigin(kExampleURL)));
+
+  // False for permissions not controlled by the DSE.
+  EXPECT_FALSE(GetService()->IsPermissionControlledByDSE(
+      CONTENT_SETTINGS_TYPE_COOKIES, ToOrigin(kExampleURL)));
 }
 
 TEST_F(SearchPermissionsServiceTest, DSEChanges) {
@@ -370,6 +374,64 @@
       GetContentSetting(kGoogleAusURL, CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
 }
 
+TEST_F(SearchPermissionsServiceTest, DSEChangesWithEnterprisePolicy) {
+  test_delegate()->ChangeDSEOrigin(kGoogleURL);
+
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            GetContentSetting(kGoogleURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
+
+  // Set a policy value for the geolocation setting.
+  sync_preferences::TestingPrefServiceSyncable* prefs =
+      profile()->GetTestingPrefService();
+  prefs->SetManagedPref(prefs::kManagedDefaultGeolocationSetting,
+                        base::MakeUnique<base::Value>(CONTENT_SETTING_BLOCK));
+  EXPECT_EQ(CONTENT_SETTING_BLOCK,
+            GetContentSetting(kGoogleURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
+
+  // Change DSE.
+  test_delegate()->ChangeDSEOrigin(kGoogleAusURL);
+
+  // The enterprise policy should still be in effect.
+  EXPECT_EQ(
+      CONTENT_SETTING_BLOCK,
+      GetContentSetting(kGoogleAusURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
+
+  // When the enterprise policy goes away, the setting should revert to ALLOW
+  // for the current DSE and ASK for the previous one.
+  prefs->RemoveManagedPref(prefs::kManagedDefaultGeolocationSetting);
+  EXPECT_EQ(CONTENT_SETTING_ASK,
+            GetContentSetting(kGoogleURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
+  EXPECT_EQ(
+      CONTENT_SETTING_ALLOW,
+      GetContentSetting(kGoogleAusURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
+
+  // Simulate the user setting google.com to BLOCK.
+  SetContentSetting(kGoogleURL, CONTENT_SETTINGS_TYPE_GEOLOCATION,
+                    CONTENT_SETTING_BLOCK);
+
+  // Put an ALLOW enterprise policy in place.
+  prefs->SetManagedPref(prefs::kManagedDefaultGeolocationSetting,
+                        base::MakeUnique<base::Value>(CONTENT_SETTING_ALLOW));
+  EXPECT_EQ(
+      CONTENT_SETTING_ALLOW,
+      GetContentSetting(kGoogleAusURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
+
+  // Now change the DSE back to google.com. The enterprise setting should still
+  // be in effect so it should be ALLOW.
+  test_delegate()->ChangeDSEOrigin(kGoogleURL);
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            GetContentSetting(kGoogleURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
+
+  // Remove the enterprise policy. google.com should go back to blocked.
+  // google.com.au should be ASK.
+  prefs->RemoveManagedPref(prefs::kManagedDefaultGeolocationSetting);
+  EXPECT_EQ(CONTENT_SETTING_BLOCK,
+            GetContentSetting(kGoogleURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
+  EXPECT_EQ(
+      CONTENT_SETTING_ASK,
+      GetContentSetting(kGoogleAusURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
+}
+
 TEST_F(SearchPermissionsServiceTest, DSEChangesAndDisclosure) {
   test_delegate()->ChangeDSEOrigin(kGoogleURL);
   SearchGeolocationDisclosureTabHelper::FakeShowingDisclosureForTests(
@@ -511,8 +573,7 @@
   SetContentSetting(kGoogleURL, CONTENT_SETTINGS_TYPE_GEOLOCATION,
                     CONTENT_SETTING_BLOCK);
 
-  EXPECT_TRUE(
-      GetService()->ResetDSEPermission(CONTENT_SETTINGS_TYPE_GEOLOCATION));
+  GetService()->ResetDSEPermission(CONTENT_SETTINGS_TYPE_GEOLOCATION);
   EXPECT_EQ(
       CONTENT_SETTING_ALLOW,
       GetContentSetting(kGoogleAusURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
@@ -522,8 +583,7 @@
   EXPECT_EQ(CONTENT_SETTING_BLOCK,
             GetContentSetting(kGoogleURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
 
-  EXPECT_TRUE(
-      GetService()->ResetDSEPermission(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
+  GetService()->ResetDSEPermission(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
   EXPECT_EQ(
       CONTENT_SETTING_ALLOW,
       GetContentSetting(kGoogleAusURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
@@ -532,8 +592,6 @@
       GetContentSetting(kGoogleAusURL, CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
   EXPECT_EQ(CONTENT_SETTING_BLOCK,
             GetContentSetting(kGoogleURL, CONTENT_SETTINGS_TYPE_GEOLOCATION));
-
-  EXPECT_FALSE(GetService()->ResetDSEPermission(CONTENT_SETTINGS_TYPE_MIDI));
 }
 
 TEST_F(SearchPermissionsServiceTest, ResetDSEPermissions) {
diff --git a/chrome/browser/printing/cloud_print/privet_http_impl.cc b/chrome/browser/printing/cloud_print/privet_http_impl.cc
index 5ab2c01..15b15a2c 100644
--- a/chrome/browser/printing/cloud_print/privet_http_impl.cc
+++ b/chrome/browser/printing/cloud_print/privet_http_impl.cc
@@ -390,46 +390,51 @@
       base::BindRepeating(&PrivetLocalPrintOperationImpl::OnPrivetInfoDone,
                           base::Unretained(this)));
   info_operation_->Start();
-
   started_ = true;
 }
 
 void PrivetLocalPrintOperationImpl::OnPrivetInfoDone(
     const base::DictionaryValue* value) {
-  if (value && !value->HasKey(kPrivetKeyError)) {
-    has_extended_workflow_ = false;
-    bool has_printing = false;
-
-    const base::ListValue* api_list;
-    if (value->GetList(kPrivetInfoKeyAPIList, &api_list)) {
-      for (size_t i = 0; i < api_list->GetSize(); i++) {
-        std::string api;
-        api_list->GetString(i, &api);
-        if (api == kPrivetSubmitdocPath) {
-          has_printing = true;
-        } else if (api == kPrivetCreatejobPath) {
-          has_extended_workflow_ = true;
-        }
-      }
-    }
-
-    if (!has_printing) {
-      delegate_->OnPrivetPrintingError(this, -1);
-      return;
-    }
-
-    StartInitialRequest();
-  } else {
+  if (!value || value->HasKey(kPrivetKeyError)) {
     delegate_->OnPrivetPrintingError(this, -1);
+    return;
   }
+
+  has_extended_workflow_ = false;
+  bool has_printing = false;
+  const base::Value* api_list =
+      value->FindKeyOfType(kPrivetInfoKeyAPIList, base::Value::Type::LIST);
+  if (api_list) {
+    for (const auto& api : api_list->GetList()) {
+      if (!api.is_string())
+        continue;
+
+      const std::string& api_str = api.GetString();
+      if (!has_printing && api_str == kPrivetSubmitdocPath)
+        has_printing = true;
+      else if (!has_extended_workflow_ && api_str == kPrivetCreatejobPath)
+        has_extended_workflow_ = true;
+
+      if (has_printing && has_extended_workflow_)
+        break;
+    }
+  }
+
+  if (!has_printing) {
+    delegate_->OnPrivetPrintingError(this, -1);
+    return;
+  }
+
+  StartInitialRequest();
 }
 
 void PrivetLocalPrintOperationImpl::StartInitialRequest() {
-  use_pdf_ = false;
   cloud_devices::printer::ContentTypesCapability content_types;
   if (content_types.LoadFrom(capabilities_)) {
     use_pdf_ = content_types.Contains(kPrivetContentTypePDF) ||
                content_types.Contains(kPrivetContentTypeAny);
+  } else {
+    use_pdf_ = false;
   }
 
   if (use_pdf_) {
diff --git a/chrome/browser/printing/cloud_print/privet_url_fetcher.cc b/chrome/browser/printing/cloud_print/privet_url_fetcher.cc
index d79d4c3..ec3fc1b 100644
--- a/chrome/browser/printing/cloud_print/privet_url_fetcher.cc
+++ b/chrome/browser/printing/cloud_print/privet_url_fetcher.cc
@@ -296,40 +296,34 @@
 
   base::JSONReader json_reader(base::JSON_ALLOW_TRAILING_COMMAS);
   std::unique_ptr<base::Value> value = json_reader.ReadToValue(response_str);
-  if (!value) {
+  if (!value || !value->is_dict()) {
     delegate_->OnError(0, JSON_PARSE_ERROR);
     return;
   }
 
-  const base::DictionaryValue* dictionary_value = NULL;
-
-  if (!value->GetAsDictionary(&dictionary_value)) {
-    delegate_->OnError(0, JSON_PARSE_ERROR);
-    return;
-  }
-
-  std::string error;
-  if (dictionary_value->GetString(kPrivetKeyError, &error)) {
+  const base::Value* error_value =
+      value->FindKeyOfType(kPrivetKeyError, base::Value::Type::STRING);
+  if (error_value) {
+    const std::string& error = error_value->GetString();
     if (error == kPrivetErrorInvalidXPrivetToken) {
       RequestTokenRefresh();
       return;
-    } else if (PrivetErrorTransient(error)) {
+    }
+    if (PrivetErrorTransient(error)) {
       if (!do_not_retry_on_transient_error_) {
-        int timeout_seconds;
-        if (!dictionary_value->GetInteger(kPrivetKeyTimeout,
-                                          &timeout_seconds)) {
-          timeout_seconds = kPrivetDefaultTimeout;
-        }
-
-        ScheduleRetry(timeout_seconds);
+        const base::Value* timeout_value =
+            value->FindKeyOfType(kPrivetKeyTimeout, base::Value::Type::INTEGER);
+        ScheduleRetry(timeout_value ? timeout_value->GetInt()
+                                    : kPrivetDefaultTimeout);
         return;
       }
     }
     is_error_response = true;
   }
 
-  delegate_->OnParsedJson(response_code(), *dictionary_value,
-                          is_error_response);
+  delegate_->OnParsedJson(
+      response_code(), *static_cast<const base::DictionaryValue*>(value.get()),
+      is_error_response);
 }
 
 void PrivetURLFetcher::ScheduleRetry(int timeout_seconds) {
diff --git a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
index 165d760..ed59766 100644
--- a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
+++ b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
@@ -477,6 +477,12 @@
   // TODO(kmackay) Determine required sample formats/channel numbers.
   config.sample_format = kSampleFormatS16;
   config.bytes_per_channel = 2;
+  config.codec = kCodecPCM;
+  EXPECT_TRUE(audio_decoder->SetConfig(config))
+      << "Audio decoder does not accept kCodecPCM";
+  config.codec = kCodecPCM_S16BE;
+  EXPECT_TRUE(audio_decoder->SetConfig(config))
+      << "Audio decoder does not accept kCodecPCM_S16BE";
   config.codec = kCodecAAC;
   EXPECT_TRUE(audio_decoder->SetConfig(config))
       << "Audio decoder does not accept kCodecAAC";
@@ -484,24 +490,6 @@
   EXPECT_TRUE(audio_decoder->SetConfig(config))
       << "Audio decoder does not accept kCodecMP3";
 
-  // Test optional codecs.
-  // TODO(kmackay) Make sure other parts of config are correct for each codec.
-  config.codec = kCodecPCM_S16BE;
-  if (!audio_decoder->SetConfig(config))
-    LOG(INFO) << "Audio decoder does not accept kCodecPCM_S16BE";
-  config.codec = kCodecOpus;
-  if (!audio_decoder->SetConfig(config))
-    LOG(INFO) << "Audio decoder does not accept kCodecOpus";
-  config.codec = kCodecEAC3;
-  if (!audio_decoder->SetConfig(config))
-    LOG(INFO) << "Audio decoder does not accept kCodecEAC3";
-  config.codec = kCodecAC3;
-  if (!audio_decoder->SetConfig(config))
-    LOG(INFO) << "Audio decoder does not accept kCodecAC3";
-  config.codec = kCodecFLAC;
-  if (!audio_decoder->SetConfig(config))
-    LOG(INFO) << "Audio decoder does not accept kCodecFLAC";
-
   // Test supported sample rates.
   const int kRequiredSampleRates[] = {8000,  11025, 12000, 16000, 22050,
                                       24000, 32000, 44100, 48000};
@@ -534,11 +522,12 @@
 void BufferFeeder::TestVideoConfigs() {
   MediaPipelineBackend::VideoDecoder* video_decoder =
       static_cast<MediaPipelineBackend::VideoDecoder*>(decoder_);
-  VideoConfig config;
-  config.codec = kVideoCodecUnknown;
   // Set invalid config first, to test that the decoder still accepts valid
   // config after an invalid config.
+  VideoConfig config;
+  config.codec = kVideoCodecUnknown;
   video_decoder->SetConfig(config);
+
   EXPECT_TRUE(video_decoder->SetConfig(video_config_));
 }
 
diff --git a/chromeos/components/tether/ad_hoc_ble_advertiser.h b/chromeos/components/tether/ad_hoc_ble_advertiser.h
index 103681b..28c42e1 100644
--- a/chromeos/components/tether/ad_hoc_ble_advertiser.h
+++ b/chromeos/components/tether/ad_hoc_ble_advertiser.h
@@ -7,7 +7,6 @@
 
 #include "base/macros.h"
 #include "base/observer_list.h"
-#include "components/cryptauth/remote_device.h"
 
 namespace chromeos {
 
@@ -40,8 +39,7 @@
   // Requests that |remote_device| add GATT services. This should only be called
   // when the device has a stale advertisement with no GATT services. See
   // crbug.com/784968.
-  virtual void RequestGattServicesForDevice(
-      const cryptauth::RemoteDevice& remote_device) = 0;
+  virtual void RequestGattServicesForDevice(const std::string& device_id) = 0;
 
   // Returns whether there are any pending requests for GATT services.
   virtual bool HasPendingRequests() = 0;
diff --git a/chromeos/components/tether/ad_hoc_ble_advertiser_impl.cc b/chromeos/components/tether/ad_hoc_ble_advertiser_impl.cc
index 7e43e098..d0239c2f 100644
--- a/chromeos/components/tether/ad_hoc_ble_advertiser_impl.cc
+++ b/chromeos/components/tether/ad_hoc_ble_advertiser_impl.cc
@@ -8,6 +8,7 @@
 #include "chromeos/components/tether/error_tolerant_ble_advertisement_impl.h"
 #include "chromeos/components/tether/timer_factory.h"
 #include "components/cryptauth/ble/ble_advertisement_generator.h"
+#include "components/cryptauth/remote_device.h"
 #include "components/proximity_auth/logging/logging.h"
 
 namespace chromeos {
@@ -43,27 +44,26 @@
 AdHocBleAdvertiserImpl::~AdHocBleAdvertiserImpl() {}
 
 void AdHocBleAdvertiserImpl::RequestGattServicesForDevice(
-    const cryptauth::RemoteDevice& remote_device) {
-  const std::string device_id = remote_device.GetDeviceId();
-
+    const std::string& device_id) {
   // If an advertisement to that device is already in progress, there is nothing
   // to do.
   if (device_id_to_advertisement_with_timer_map_.find(device_id) !=
       device_id_to_advertisement_with_timer_map_.end()) {
     PA_LOG(INFO) << "Advertisement already in progress to device with ID \""
-                 << remote_device.GetTruncatedDeviceIdForLogs() << "\".";
+                 << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
+                 << "\".";
     return;
   }
 
-  // Generate a new advertisement to |remote_device|.
+  // Generate a new advertisement to device with ID |device_id|.
   std::unique_ptr<cryptauth::DataWithTimestamp> service_data =
       cryptauth::BleAdvertisementGenerator::GenerateBleAdvertisement(
-          remote_device, local_device_data_provider_,
-          remote_beacon_seed_fetcher_);
+          device_id, local_device_data_provider_, remote_beacon_seed_fetcher_);
   if (!service_data) {
     PA_LOG(WARNING) << "Cannot generate advertisement for device with ID \""
-                    << remote_device.GetTruncatedDeviceIdForLogs() << "\"; "
-                    << "GATT services cannot be requested.";
+                    << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(
+                           device_id)
+                    << "\"; GATT services cannot be requested.";
     return;
   }
 
@@ -72,8 +72,8 @@
           device_id, std::move(service_data), ble_synchronizer_);
 
   PA_LOG(INFO) << "Requesting GATT services for device with ID \""
-               << remote_device.GetTruncatedDeviceIdForLogs() << "\" by "
-               << "creating a new advertisement to that device.";
+               << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
+               << "\" by creating a new advertisement to that device.";
 
   std::unique_ptr<base::Timer> timer = timer_factory_->CreateOneShotTimer();
   timer->Start(FROM_HERE, base::TimeDelta::FromSeconds(kNumSecondsToAdvertise),
diff --git a/chromeos/components/tether/ad_hoc_ble_advertiser_impl.h b/chromeos/components/tether/ad_hoc_ble_advertiser_impl.h
index e492c247..3e2c174 100644
--- a/chromeos/components/tether/ad_hoc_ble_advertiser_impl.h
+++ b/chromeos/components/tether/ad_hoc_ble_advertiser_impl.h
@@ -43,8 +43,7 @@
   ~AdHocBleAdvertiserImpl() override;
 
   // AdHocBleAdvertiser:
-  void RequestGattServicesForDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
+  void RequestGattServicesForDevice(const std::string& device_id) override;
   bool HasPendingRequests() override;
 
  private:
diff --git a/chromeos/components/tether/ad_hoc_ble_advertiser_impl_unittest.cc b/chromeos/components/tether/ad_hoc_ble_advertiser_impl_unittest.cc
index 7c86dc9..bef056f9 100644
--- a/chromeos/components/tether/ad_hoc_ble_advertiser_impl_unittest.cc
+++ b/chromeos/components/tether/ad_hoc_ble_advertiser_impl_unittest.cc
@@ -217,7 +217,7 @@
 
 TEST_F(AdHocBleAdvertiserImplTest, CannotGenerateAdvertisement) {
   fake_generator_->set_advertisement(nullptr);
-  workaround_->RequestGattServicesForDevice(fake_devices_[0]);
+  workaround_->RequestGattServicesForDevice(fake_devices_[0].GetDeviceId());
   EXPECT_EQ(0u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(0u, test_observer_->num_times_shutdown_complete());
   EXPECT_FALSE(workaround_->HasPendingRequests());
@@ -228,7 +228,7 @@
   test_timer_factory_->set_device_id_for_next_timer(
       fake_devices_[0].GetDeviceId());
 
-  workaround_->RequestGattServicesForDevice(fake_devices_[0]);
+  workaround_->RequestGattServicesForDevice(fake_devices_[0].GetDeviceId());
   EXPECT_TRUE(workaround_->HasPendingRequests());
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
 
@@ -246,12 +246,12 @@
   test_timer_factory_->set_device_id_for_next_timer(
       fake_devices_[0].GetDeviceId());
 
-  workaround_->RequestGattServicesForDevice(fake_devices_[0]);
+  workaround_->RequestGattServicesForDevice(fake_devices_[0].GetDeviceId());
   EXPECT_TRUE(workaround_->HasPendingRequests());
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
 
   // No additional advertisement should be created.
-  workaround_->RequestGattServicesForDevice(fake_devices_[0]);
+  workaround_->RequestGattServicesForDevice(fake_devices_[0].GetDeviceId());
   EXPECT_TRUE(workaround_->HasPendingRequests());
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
 
@@ -268,7 +268,7 @@
   test_timer_factory_->set_device_id_for_next_timer(
       fake_devices_[0].GetDeviceId());
 
-  workaround_->RequestGattServicesForDevice(fake_devices_[0]);
+  workaround_->RequestGattServicesForDevice(fake_devices_[0].GetDeviceId());
   EXPECT_TRUE(workaround_->HasPendingRequests());
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
 
@@ -276,7 +276,7 @@
   EXPECT_TRUE(workaround_->HasPendingRequests());
 
   // No additional advertisement should be created.
-  workaround_->RequestGattServicesForDevice(fake_devices_[0]);
+  workaround_->RequestGattServicesForDevice(fake_devices_[0].GetDeviceId());
   EXPECT_TRUE(workaround_->HasPendingRequests());
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
 
@@ -289,14 +289,14 @@
   SetAdvertisement(0 /* index */);
   test_timer_factory_->set_device_id_for_next_timer(
       fake_devices_[0].GetDeviceId());
-  workaround_->RequestGattServicesForDevice(fake_devices_[0]);
+  workaround_->RequestGattServicesForDevice(fake_devices_[0].GetDeviceId());
   EXPECT_TRUE(workaround_->HasPendingRequests());
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
 
   SetAdvertisement(1 /* index */);
   test_timer_factory_->set_device_id_for_next_timer(
       fake_devices_[1].GetDeviceId());
-  workaround_->RequestGattServicesForDevice(fake_devices_[1]);
+  workaround_->RequestGattServicesForDevice(fake_devices_[1].GetDeviceId());
   EXPECT_TRUE(workaround_->HasPendingRequests());
   EXPECT_EQ(2u, fake_advertisement_factory_->num_created());
 
diff --git a/chromeos/components/tether/asynchronous_shutdown_object_container_impl.cc b/chromeos/components/tether/asynchronous_shutdown_object_container_impl.cc
index 52a368a..f201cc2 100644
--- a/chromeos/components/tether/asynchronous_shutdown_object_container_impl.cc
+++ b/chromeos/components/tether/asynchronous_shutdown_object_container_impl.cc
@@ -96,7 +96,8 @@
       ble_scanner_(
           base::MakeUnique<BleScannerImpl>(adapter,
                                            local_device_data_provider_.get(),
-                                           ble_synchronizer_.get())),
+                                           ble_synchronizer_.get(),
+                                           tether_host_fetcher_)),
       ad_hoc_ble_advertiser_(base::MakeUnique<AdHocBleAdvertiserImpl>(
           local_device_data_provider_.get(),
           remote_beacon_seed_fetcher_.get(),
diff --git a/chromeos/components/tether/ble_advertisement_device_queue.cc b/chromeos/components/tether/ble_advertisement_device_queue.cc
index 0840f10..51fb14c 100644
--- a/chromeos/components/tether/ble_advertisement_device_queue.cc
+++ b/chromeos/components/tether/ble_advertisement_device_queue.cc
@@ -15,14 +15,14 @@
 
 namespace {
 
-bool DoesVectorContainDevice(
+bool DoesVectorContainPrioritizedDeviceId(
     const ConnectionPriority& connection_priority,
-    const cryptauth::RemoteDevice& remote_device,
-    const std::vector<BleAdvertisementDeviceQueue::PrioritizedDevice>&
+    const std::string& device_id,
+    const std::vector<BleAdvertisementDeviceQueue::PrioritizedDeviceId>&
         prioritized_devices) {
   for (const auto& prioritized_device : prioritized_devices) {
     if (prioritized_device.connection_priority == connection_priority &&
-        prioritized_device.remote_device == remote_device) {
+        prioritized_device.device_id == device_id) {
       return true;
     }
   }
@@ -32,41 +32,43 @@
 
 }  // namespace
 
-BleAdvertisementDeviceQueue::PrioritizedDevice::PrioritizedDevice(
-    const cryptauth::RemoteDevice& remote_device,
+BleAdvertisementDeviceQueue::PrioritizedDeviceId::PrioritizedDeviceId(
+    const std::string& device_id,
     const ConnectionPriority& connection_priority)
-    : remote_device(remote_device), connection_priority(connection_priority) {}
+    : device_id(device_id), connection_priority(connection_priority) {}
 
-BleAdvertisementDeviceQueue::PrioritizedDevice::~PrioritizedDevice() = default;
+BleAdvertisementDeviceQueue::PrioritizedDeviceId::~PrioritizedDeviceId() =
+    default;
 
 BleAdvertisementDeviceQueue::BleAdvertisementDeviceQueue() = default;
 
 BleAdvertisementDeviceQueue::~BleAdvertisementDeviceQueue() = default;
 
-bool BleAdvertisementDeviceQueue::SetDevices(
-    const std::vector<PrioritizedDevice>& devices) {
+bool BleAdvertisementDeviceQueue::SetPrioritizedDeviceIds(
+    const std::vector<PrioritizedDeviceId>& prioritized_ids) {
   bool updated = false;
 
   // For each device provided, check to see if the device is already part of the
   // queue. If it is not, add it to the end of the deque associated with the
   // device's priority.
-  for (const auto& device : devices) {
-    std::deque<cryptauth::RemoteDevice>& deque_for_priority =
-        priority_to_deque_map_[device.connection_priority];
+  for (const auto& priotizied_id : prioritized_ids) {
+    std::deque<std::string>& deque_for_priority =
+        priority_to_deque_map_[priotizied_id.connection_priority];
     if (std::find(deque_for_priority.begin(), deque_for_priority.end(),
-                  device.remote_device) == deque_for_priority.end()) {
-      deque_for_priority.push_back(device.remote_device);
+                  priotizied_id.device_id) == deque_for_priority.end()) {
+      deque_for_priority.push_back(priotizied_id.device_id);
       updated = true;
     }
   }
 
   // Now, iterate through each priority's deque to see if any of the entries
-  // were not provided as part of the |devices| parameter. If any such entries
-  // exist, remove them from the map.
+  // were not provided as part of the |prioritized_ids| parameter. If any such
+  // entries exist, remove them from the map.
   for (auto& map_entry : priority_to_deque_map_) {
     auto device_deque_it = map_entry.second.begin();
     while (device_deque_it != map_entry.second.end()) {
-      if (DoesVectorContainDevice(map_entry.first, *device_deque_it, devices)) {
+      if (DoesVectorContainPrioritizedDeviceId(
+              map_entry.first, *device_deque_it, prioritized_ids)) {
         ++device_deque_it;
         continue;
       }
@@ -86,7 +88,7 @@
   for (auto& map_entry : priority_to_deque_map_) {
     auto device_deque_it = map_entry.second.begin();
     while (device_deque_it != map_entry.second.end()) {
-      if (device_deque_it->GetDeviceId() == device_id)
+      if (*device_deque_it == device_id)
         break;
       ++device_deque_it;
     }
@@ -94,23 +96,23 @@
     if (device_deque_it == map_entry.second.end())
       continue;
 
-    cryptauth::RemoteDevice to_move = *device_deque_it;
+    std::string to_move = *device_deque_it;
     map_entry.second.erase(device_deque_it);
     map_entry.second.push_back(to_move);
   }
 }
 
-std::vector<cryptauth::RemoteDevice>
-BleAdvertisementDeviceQueue::GetDevicesToWhichToAdvertise() const {
-  std::vector<cryptauth::RemoteDevice> devices;
+std::vector<std::string>
+BleAdvertisementDeviceQueue::GetDeviceIdsToWhichToAdvertise() const {
+  std::vector<std::string> device_ids;
   AddDevicesToVectorForPriority(ConnectionPriority::CONNECTION_PRIORITY_HIGH,
-                                &devices);
+                                &device_ids);
   AddDevicesToVectorForPriority(ConnectionPriority::CONNECTION_PRIORITY_MEDIUM,
-                                &devices);
+                                &device_ids);
   AddDevicesToVectorForPriority(ConnectionPriority::CONNECTION_PRIORITY_LOW,
-                                &devices);
-  DCHECK(devices.size() <= kMaxConcurrentAdvertisements);
-  return devices;
+                                &device_ids);
+  DCHECK(device_ids.size() <= kMaxConcurrentAdvertisements);
+  return device_ids;
 }
 
 size_t BleAdvertisementDeviceQueue::GetSize() const {
@@ -122,19 +124,19 @@
 
 void BleAdvertisementDeviceQueue::AddDevicesToVectorForPriority(
     ConnectionPriority connection_priority,
-    std::vector<cryptauth::RemoteDevice>* remote_devices_out) const {
+    std::vector<std::string>* device_ids_out) const {
   if (priority_to_deque_map_.find(connection_priority) ==
       priority_to_deque_map_.end()) {
     // Nothing to do if there is no entry for this priority.
     return;
   }
 
-  const std::deque<cryptauth::RemoteDevice>& deque_for_priority =
+  const std::deque<std::string>& deque_for_priority =
       priority_to_deque_map_.at(connection_priority);
   size_t i = 0;
   while (i < deque_for_priority.size() &&
-         remote_devices_out->size() < kMaxConcurrentAdvertisements) {
-    remote_devices_out->push_back(deque_for_priority[i]);
+         device_ids_out->size() < kMaxConcurrentAdvertisements) {
+    device_ids_out->push_back(deque_for_priority[i]);
     ++i;
   }
 }
diff --git a/chromeos/components/tether/ble_advertisement_device_queue.h b/chromeos/components/tether/ble_advertisement_device_queue.h
index 25a8ed96..d2944c1 100644
--- a/chromeos/components/tether/ble_advertisement_device_queue.h
+++ b/chromeos/components/tether/ble_advertisement_device_queue.h
@@ -11,7 +11,6 @@
 
 #include "base/macros.h"
 #include "chromeos/components/tether/connection_priority.h"
-#include "components/cryptauth/remote_device.h"
 
 namespace chromeos {
 
@@ -26,23 +25,24 @@
   BleAdvertisementDeviceQueue();
   virtual ~BleAdvertisementDeviceQueue();
 
-  struct PrioritizedDevice {
-    PrioritizedDevice(const cryptauth::RemoteDevice& remote_device,
-                      const ConnectionPriority& connection_priority);
-    ~PrioritizedDevice();
+  struct PrioritizedDeviceId {
+    PrioritizedDeviceId(const std::string& device_id,
+                        const ConnectionPriority& connection_priority);
+    ~PrioritizedDeviceId();
 
-    cryptauth::RemoteDevice remote_device;
+    std::string device_id;
     ConnectionPriority connection_priority;
   };
 
-  // Updates the queue with the given |devices|. Devices which are already in
-  // the queue and are not in |devices| are removed from the queue, and all
-  // devices which are not in the queue but are in |devices| are added to the
-  // end of the queue. Note devices that are already in the queue will not
-  // change order as a result of this function being called to ensure that the
-  // queue remains in order. Returns whether the device list has changed due to
-  // the function call.
-  bool SetDevices(const std::vector<PrioritizedDevice>& devices);
+  // Updates the queue with the given |prioritized_ids|. Devices which are
+  // already in the queue and are not in |prioritized_ids| are removed from the
+  // queue, and all devices which are not in the queue but are in
+  // |prioritized_ids| are added to the end of the queue. Note devices that are
+  // already in the queue will not change order as a result of this function
+  // being called to ensure that the queue remains in order. Returns whether the
+  // device list has changed due to the function call.
+  bool SetPrioritizedDeviceIds(
+      const std::vector<PrioritizedDeviceId>& prioritized_ids);
 
   // Moves the given device to the end of the queue. If the device was not in
   // the queue to begin with, do nothing.
@@ -51,17 +51,16 @@
   // Returns a list of devices to which to advertise. The devices returned are
   // the first |kMaxConcurrentAdvertisements| devices in the front of the queue,
   // or fewer if the number of devices in the queue is less than that value.
-  std::vector<cryptauth::RemoteDevice> GetDevicesToWhichToAdvertise() const;
+  std::vector<std::string> GetDeviceIdsToWhichToAdvertise() const;
 
   size_t GetSize() const;
 
  private:
   void AddDevicesToVectorForPriority(
       ConnectionPriority connection_priority,
-      std::vector<cryptauth::RemoteDevice>* remote_devices_out) const;
+      std::vector<std::string>* device_ids_out) const;
 
-  std::map<ConnectionPriority, std::deque<cryptauth::RemoteDevice>>
-      priority_to_deque_map_;
+  std::map<ConnectionPriority, std::deque<std::string>> priority_to_deque_map_;
 
   DISALLOW_COPY_AND_ASSIGN(BleAdvertisementDeviceQueue);
 };
diff --git a/chromeos/components/tether/ble_advertisement_device_queue_unittest.cc b/chromeos/components/tether/ble_advertisement_device_queue_unittest.cc
index 10a5ff5..cb8cc65 100644
--- a/chromeos/components/tether/ble_advertisement_device_queue_unittest.cc
+++ b/chromeos/components/tether/ble_advertisement_device_queue_unittest.cc
@@ -18,7 +18,7 @@
 
 namespace tether {
 
-typedef BleAdvertisementDeviceQueue::PrioritizedDevice PrioritizedDevice;
+typedef BleAdvertisementDeviceQueue::PrioritizedDeviceId PrioritizedDeviceId;
 
 class BleAdvertisementDeviceQueueTest : public testing::Test {
  protected:
@@ -39,63 +39,69 @@
 
 TEST_F(BleAdvertisementDeviceQueueTest, TestEmptyQueue) {
   EXPECT_EQ(0u, device_queue_->GetSize());
-  std::vector<cryptauth::RemoteDevice> to_advertise =
-      device_queue_->GetDevicesToWhichToAdvertise();
+  std::vector<std::string> to_advertise =
+      device_queue_->GetDeviceIdsToWhichToAdvertise();
   EXPECT_TRUE(to_advertise.empty());
 }
 
 TEST_F(BleAdvertisementDeviceQueueTest, TestSingleDevice) {
-  EXPECT_TRUE(device_queue_->SetDevices({PrioritizedDevice(
-      test_devices_[0], ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[0].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
   EXPECT_EQ(1u, device_queue_->GetSize());
 
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId()));
 }
 
 TEST_F(BleAdvertisementDeviceQueueTest, TestSingleDevice_MoveToEnd) {
-  EXPECT_TRUE(device_queue_->SetDevices({PrioritizedDevice(
-      test_devices_[0], ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[0].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
   EXPECT_EQ(1u, device_queue_->GetSize());
 
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId()));
 
   device_queue_->MoveDeviceToEnd(test_devices_[0].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId()));
 }
 
 TEST_F(BleAdvertisementDeviceQueueTest, TestTwoDevices) {
-  EXPECT_TRUE(device_queue_->SetDevices(
-      {PrioritizedDevice(test_devices_[0],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[1],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[0].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
   EXPECT_EQ(2u, device_queue_->GetSize());
 
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0], test_devices_[1]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId(),
+                          test_devices_[1].GetDeviceId()));
 }
 
 TEST_F(BleAdvertisementDeviceQueueTest, TestTwoDevices_MoveToEnd) {
-  EXPECT_TRUE(device_queue_->SetDevices(
-      {PrioritizedDevice(test_devices_[0],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[1],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[0].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
   EXPECT_EQ(2u, device_queue_->GetSize());
 
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0], test_devices_[1]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId(),
+                          test_devices_[1].GetDeviceId()));
 
   device_queue_->MoveDeviceToEnd(test_devices_[0].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1], test_devices_[0]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId(),
+                          test_devices_[0].GetDeviceId()));
 
   device_queue_->MoveDeviceToEnd(test_devices_[1].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0], test_devices_[1]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId(),
+                          test_devices_[1].GetDeviceId()));
 }
 
 TEST_F(BleAdvertisementDeviceQueueTest, TestThreeDevices) {
@@ -103,29 +109,33 @@
   // ever changed.
   ASSERT_GT(3u, kMaxConcurrentAdvertisements);
 
-  EXPECT_TRUE(device_queue_->SetDevices(
-      {PrioritizedDevice(test_devices_[0],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[1],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[2],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[0].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[2].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
   EXPECT_EQ(3u, device_queue_->GetSize());
 
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0], test_devices_[1]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId(),
+                          test_devices_[1].GetDeviceId()));
 
   device_queue_->MoveDeviceToEnd(test_devices_[0].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1], test_devices_[2]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId(),
+                          test_devices_[2].GetDeviceId()));
 
   device_queue_->MoveDeviceToEnd(test_devices_[1].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[2], test_devices_[0]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[2].GetDeviceId(),
+                          test_devices_[0].GetDeviceId()));
 
   device_queue_->MoveDeviceToEnd(test_devices_[2].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0], test_devices_[1]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId(),
+                          test_devices_[1].GetDeviceId()));
 }
 
 TEST_F(BleAdvertisementDeviceQueueTest, TestAddingDevices) {
@@ -133,40 +143,45 @@
   // ever changed.
   ASSERT_GT(3u, kMaxConcurrentAdvertisements);
 
-  EXPECT_TRUE(device_queue_->SetDevices(
-      {PrioritizedDevice(test_devices_[0],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[1],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[0].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
   EXPECT_EQ(2u, device_queue_->GetSize());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0], test_devices_[1]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId(),
+                          test_devices_[1].GetDeviceId()));
 
   device_queue_->MoveDeviceToEnd(test_devices_[0].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1], test_devices_[0]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId(),
+                          test_devices_[0].GetDeviceId()));
 
   // Device 0 has been unregistered; devices 3 and 4 have been registered.
-  EXPECT_TRUE(device_queue_->SetDevices(
-      {PrioritizedDevice(test_devices_[1],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[2],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[3],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[4],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[2].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[3].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[4].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH)}));
   EXPECT_EQ(4u, device_queue_->GetSize());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1], test_devices_[2]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId(),
+                          test_devices_[2].GetDeviceId()));
 
   device_queue_->MoveDeviceToEnd(test_devices_[2].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1], test_devices_[3]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId(),
+                          test_devices_[3].GetDeviceId()));
 
   device_queue_->MoveDeviceToEnd(test_devices_[1].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[3], test_devices_[4]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[3].GetDeviceId(),
+                          test_devices_[4].GetDeviceId()));
 }
 
 TEST_F(BleAdvertisementDeviceQueueTest, TestMultiplePriorityLevels) {
@@ -174,100 +189,111 @@
   // ever changed.
   ASSERT_GT(3u, kMaxConcurrentAdvertisements);
 
-  EXPECT_TRUE(device_queue_->SetDevices(
-      {PrioritizedDevice(test_devices_[0],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[1],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[2],
-                         ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
-       PrioritizedDevice(test_devices_[3],
-                         ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
-       PrioritizedDevice(test_devices_[4],
-                         ConnectionPriority::CONNECTION_PRIORITY_LOW)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[0].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[2].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
+       PrioritizedDeviceId(test_devices_[3].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
+       PrioritizedDeviceId(test_devices_[4].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_LOW)}));
   EXPECT_EQ(5u, device_queue_->GetSize());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[0], test_devices_[1]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[0].GetDeviceId(),
+                          test_devices_[1].GetDeviceId()));
 
   // Moving a high-priority device to the end of the queue should still keep it
   // before all other priority levels.
   device_queue_->MoveDeviceToEnd(test_devices_[0].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1], test_devices_[0]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId(),
+                          test_devices_[0].GetDeviceId()));
 
   // Device 0 has been unregistered; device 2 has moved to low-priority.
-  EXPECT_TRUE(device_queue_->SetDevices(
-      {PrioritizedDevice(test_devices_[1],
-                         ConnectionPriority::CONNECTION_PRIORITY_HIGH),
-       PrioritizedDevice(test_devices_[2],
-                         ConnectionPriority::CONNECTION_PRIORITY_LOW),
-       PrioritizedDevice(test_devices_[3],
-                         ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
-       PrioritizedDevice(test_devices_[4],
-                         ConnectionPriority::CONNECTION_PRIORITY_LOW)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_HIGH),
+       PrioritizedDeviceId(test_devices_[2].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_LOW),
+       PrioritizedDeviceId(test_devices_[3].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
+       PrioritizedDeviceId(test_devices_[4].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_LOW)}));
   EXPECT_EQ(4u, device_queue_->GetSize());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1], test_devices_[3]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId(),
+                          test_devices_[3].GetDeviceId()));
 
   // Moving a high-priority device to the end of the queue should still keep it
   // before all other priority levels.
   device_queue_->MoveDeviceToEnd(test_devices_[1].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1], test_devices_[3]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId(),
+                          test_devices_[3].GetDeviceId()));
 
   // Likewise, moving a medium-priority device to the end of the queue should
   // still keep it before all low-priority devices.
   device_queue_->MoveDeviceToEnd(test_devices_[3].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1], test_devices_[3]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId(),
+                          test_devices_[3].GetDeviceId()));
 
   // Now, all devices are priority medium. Since device 3 was already at the
   // medium priority, it should still be in front of the other devices that
   // were just added.
-  EXPECT_TRUE(device_queue_->SetDevices(
-      {PrioritizedDevice(test_devices_[1],
-                         ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
-       PrioritizedDevice(test_devices_[2],
-                         ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
-       PrioritizedDevice(test_devices_[3],
-                         ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
-       PrioritizedDevice(test_devices_[4],
-                         ConnectionPriority::CONNECTION_PRIORITY_MEDIUM)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
+       PrioritizedDeviceId(test_devices_[2].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
+       PrioritizedDeviceId(test_devices_[3].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_MEDIUM),
+       PrioritizedDeviceId(test_devices_[4].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_MEDIUM)}));
   EXPECT_EQ(4u, device_queue_->GetSize());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[3], test_devices_[1]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[3].GetDeviceId(),
+                          test_devices_[1].GetDeviceId()));
 
   // Since all devices are the same priority, moving one to the end of the queue
   // should bring a new one to the front.
   device_queue_->MoveDeviceToEnd(test_devices_[1].GetDeviceId());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[3], test_devices_[2]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[3].GetDeviceId(),
+                          test_devices_[2].GetDeviceId()));
 
   // Leave only one low-priority device left.
-  EXPECT_TRUE(device_queue_->SetDevices({PrioritizedDevice(
-      test_devices_[1], ConnectionPriority::CONNECTION_PRIORITY_LOW)}));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      {PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                           ConnectionPriority::CONNECTION_PRIORITY_LOW)}));
   EXPECT_EQ(1u, device_queue_->GetSize());
-  EXPECT_THAT(device_queue_->GetDevicesToWhichToAdvertise(),
-              ElementsAre(test_devices_[1]));
+  EXPECT_THAT(device_queue_->GetDeviceIdsToWhichToAdvertise(),
+              ElementsAre(test_devices_[1].GetDeviceId()));
 
   // Empty the queue.
-  EXPECT_TRUE(device_queue_->SetDevices(std::vector<PrioritizedDevice>()));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(
+      std::vector<PrioritizedDeviceId>()));
   EXPECT_EQ(0u, device_queue_->GetSize());
-  EXPECT_TRUE(device_queue_->GetDevicesToWhichToAdvertise().empty());
+  EXPECT_TRUE(device_queue_->GetDeviceIdsToWhichToAdvertise().empty());
 }
 
 TEST_F(BleAdvertisementDeviceQueueTest, TestSettingSameDevices) {
-  std::vector<PrioritizedDevice> prioritized_devices = {PrioritizedDevice(
-      test_devices_[0], ConnectionPriority::CONNECTION_PRIORITY_HIGH)};
-  EXPECT_TRUE(device_queue_->SetDevices(prioritized_devices));
+  std::vector<PrioritizedDeviceId> prioritized_devices = {
+      PrioritizedDeviceId(test_devices_[0].GetDeviceId(),
+                          ConnectionPriority::CONNECTION_PRIORITY_HIGH)};
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(prioritized_devices));
 
   // Setting the same devices again should return false.
-  EXPECT_FALSE(device_queue_->SetDevices(prioritized_devices));
-  EXPECT_FALSE(device_queue_->SetDevices(prioritized_devices));
+  EXPECT_FALSE(device_queue_->SetPrioritizedDeviceIds(prioritized_devices));
+  EXPECT_FALSE(device_queue_->SetPrioritizedDeviceIds(prioritized_devices));
 
-  prioritized_devices.push_back(PrioritizedDevice(
-      test_devices_[1], ConnectionPriority::CONNECTION_PRIORITY_HIGH));
-  EXPECT_TRUE(device_queue_->SetDevices(prioritized_devices));
+  prioritized_devices.push_back(
+      PrioritizedDeviceId(test_devices_[1].GetDeviceId(),
+                          ConnectionPriority::CONNECTION_PRIORITY_HIGH));
+  EXPECT_TRUE(device_queue_->SetPrioritizedDeviceIds(prioritized_devices));
 }
 
 }  // namespace tether
diff --git a/chromeos/components/tether/ble_advertiser.h b/chromeos/components/tether/ble_advertiser.h
index 1a01afa..644dd03 100644
--- a/chromeos/components/tether/ble_advertiser.h
+++ b/chromeos/components/tether/ble_advertiser.h
@@ -30,13 +30,11 @@
   // Starts advertising to |remote_device| by generating a device-specific EID
   // and setting it as the service data for the advertisement. Returns whether
   // the advertisement could be generated.
-  virtual bool StartAdvertisingToDevice(
-      const cryptauth::RemoteDevice& remote_device) = 0;
+  virtual bool StartAdvertisingToDevice(const std::string& device_id) = 0;
 
   // Stops advertising to |remote_device|. Returns whether the advertising was
   // stopped successfully.
-  virtual bool StopAdvertisingToDevice(
-      const cryptauth::RemoteDevice& remote_device) = 0;
+  virtual bool StopAdvertisingToDevice(const std::string& device_id) = 0;
 
   // Returns whether there is currently an advertisement registered. Note that
   // registering and unregistering advertisements are asynchronous operations,
diff --git a/chromeos/components/tether/ble_advertiser_impl.cc b/chromeos/components/tether/ble_advertiser_impl.cc
index 37b3078..fd5fd99 100644
--- a/chromeos/components/tether/ble_advertiser_impl.cc
+++ b/chromeos/components/tether/ble_advertiser_impl.cc
@@ -9,6 +9,7 @@
 #include "chromeos/components/tether/error_tolerant_ble_advertisement_impl.h"
 #include "components/cryptauth/ble/ble_advertisement_generator.h"
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
+#include "components/cryptauth/remote_device.h"
 #include "components/proximity_auth/logging/logging.h"
 #include "device/bluetooth/bluetooth_advertisement.h"
 
@@ -64,8 +65,7 @@
 
 BleAdvertiserImpl::~BleAdvertiserImpl() = default;
 
-bool BleAdvertiserImpl::StartAdvertisingToDevice(
-    const cryptauth::RemoteDevice& remote_device) {
+bool BleAdvertiserImpl::StartAdvertisingToDevice(const std::string& device_id) {
   int index_for_device = -1;
   for (size_t i = 0; i < kMaxConcurrentAdvertisements; ++i) {
     if (!registered_device_metadata_[i]) {
@@ -82,26 +82,25 @@
 
   std::unique_ptr<cryptauth::DataWithTimestamp> service_data =
       cryptauth::BleAdvertisementGenerator::GenerateBleAdvertisement(
-          remote_device, local_device_data_provider_,
-          remote_beacon_seed_fetcher_);
+          device_id, local_device_data_provider_, remote_beacon_seed_fetcher_);
   if (!service_data) {
     PA_LOG(WARNING) << "Error generating advertisement for device with ID "
-                    << remote_device.GetTruncatedDeviceIdForLogs() << ". "
-                    << "Cannot advertise.";
+                    << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(
+                           device_id)
+                    << ". Cannot advertise.";
     return false;
   }
 
-  registered_device_metadata_[index_for_device].reset(new AdvertisementMetadata(
-      remote_device.GetDeviceId(), std::move(service_data)));
+  registered_device_metadata_[index_for_device].reset(
+      new AdvertisementMetadata(device_id, std::move(service_data)));
   UpdateAdvertisements();
 
   return true;
 }
 
-bool BleAdvertiserImpl::StopAdvertisingToDevice(
-    const cryptauth::RemoteDevice& remote_device) {
+bool BleAdvertiserImpl::StopAdvertisingToDevice(const std::string& device_id) {
   for (auto& metadata : registered_device_metadata_) {
-    if (metadata && metadata->device_id == remote_device.GetDeviceId()) {
+    if (metadata && metadata->device_id == device_id) {
       metadata.reset();
       UpdateAdvertisements();
       return true;
diff --git a/chromeos/components/tether/ble_advertiser_impl.h b/chromeos/components/tether/ble_advertiser_impl.h
index f04995b..313d7a3a 100644
--- a/chromeos/components/tether/ble_advertiser_impl.h
+++ b/chromeos/components/tether/ble_advertiser_impl.h
@@ -13,7 +13,6 @@
 #include "chromeos/components/tether/ble_advertiser.h"
 #include "chromeos/components/tether/ble_constants.h"
 #include "components/cryptauth/data_with_timestamp.h"
-#include "components/cryptauth/remote_device.h"
 
 namespace base {
 class TaskRunner;
@@ -59,10 +58,8 @@
   ~BleAdvertiserImpl() override;
 
   // BleAdvertiser:
-  bool StartAdvertisingToDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
-  bool StopAdvertisingToDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
+  bool StartAdvertisingToDevice(const std::string& device_id) override;
+  bool StopAdvertisingToDevice(const std::string& device_id) override;
   bool AreAdvertisementsRegistered() override;
 
  private:
diff --git a/chromeos/components/tether/ble_advertiser_impl_unittest.cc b/chromeos/components/tether/ble_advertiser_impl_unittest.cc
index de40974..66ee516 100644
--- a/chromeos/components/tether/ble_advertiser_impl_unittest.cc
+++ b/chromeos/components/tether/ble_advertiser_impl_unittest.cc
@@ -203,7 +203,8 @@
 
 TEST_F(BleAdvertiserImplTest, CannotGenerateAdvertisement) {
   fake_generator_->set_advertisement(nullptr);
-  EXPECT_FALSE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
+  EXPECT_FALSE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[0].GetDeviceId()));
   EXPECT_EQ(0u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(0u, test_observer_->num_times_all_advertisements_unregistered());
 }
@@ -212,14 +213,16 @@
   fake_generator_->set_advertisement(
       base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
 
-  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
+  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[0].GetDeviceId()));
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(1u, fake_advertisement_factory_->active_advertisements().size());
   EXPECT_TRUE(ble_advertiser_->AreAdvertisementsRegistered());
   EXPECT_EQ(0u, test_observer_->num_times_all_advertisements_unregistered());
 
   // Now, unregister.
-  EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0]));
+  EXPECT_TRUE(
+      ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0].GetDeviceId()));
   EXPECT_TRUE(ble_advertiser_->AreAdvertisementsRegistered());
 
   // The advertisement should have been stopped, but it should not yet have
@@ -241,7 +244,8 @@
   // Register device 0.
   fake_generator_->set_advertisement(
       base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
-  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
+  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[0].GetDeviceId()));
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(1u, fake_advertisement_factory_->active_advertisements().size());
   EXPECT_TRUE(ble_advertiser_->AreAdvertisementsRegistered());
@@ -250,14 +254,16 @@
   // Register device 1.
   fake_generator_->set_advertisement(
       base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[1]));
-  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[1]));
+  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[1].GetDeviceId()));
   EXPECT_EQ(2u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(2u, fake_advertisement_factory_->active_advertisements().size());
   EXPECT_TRUE(ble_advertiser_->AreAdvertisementsRegistered());
   EXPECT_EQ(0u, test_observer_->num_times_all_advertisements_unregistered());
 
   // Unregister device 0.
-  EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0]));
+  EXPECT_TRUE(
+      ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0].GetDeviceId()));
   EXPECT_EQ(2u, fake_advertisement_factory_->active_advertisements().size());
   InvokeAdvertisementStoppedCallback(0u /* index */,
                                      fake_devices_[0].GetDeviceId());
@@ -266,7 +272,8 @@
   EXPECT_EQ(0u, test_observer_->num_times_all_advertisements_unregistered());
 
   // Unregister device 1.
-  EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[1]));
+  EXPECT_TRUE(
+      ble_advertiser_->StopAdvertisingToDevice(fake_devices_[1].GetDeviceId()));
   EXPECT_EQ(1u, fake_advertisement_factory_->active_advertisements().size());
   InvokeAdvertisementStoppedCallback(0u /* index */,
                                      fake_devices_[1].GetDeviceId());
@@ -282,28 +289,33 @@
   // Register device 0.
   fake_generator_->set_advertisement(
       base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
-  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
+  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[0].GetDeviceId()));
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(1u, fake_advertisement_factory_->active_advertisements().size());
 
   // Register device 1.
   fake_generator_->set_advertisement(
       base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[1]));
-  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[1]));
+  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[1].GetDeviceId()));
   EXPECT_EQ(2u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(2u, fake_advertisement_factory_->active_advertisements().size());
 
   // Register device 2. This should fail, since it is over the limit.
   fake_generator_->set_advertisement(
       base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[2]));
-  EXPECT_FALSE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[2]));
+  EXPECT_FALSE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[2].GetDeviceId()));
   EXPECT_EQ(2u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(2u, fake_advertisement_factory_->active_advertisements().size());
 
   // Now, stop advertising to device 1. It should now be possible to advertise
   // to device 2.
-  EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[1]));
-  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[2]));
+  EXPECT_TRUE(
+      ble_advertiser_->StopAdvertisingToDevice(fake_devices_[1].GetDeviceId()));
+  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[2].GetDeviceId()));
 
   // However, the advertisement for device 1 should still be present, and no new
   // advertisement for device 2 should have yet been created.
@@ -345,12 +357,14 @@
   fake_generator_->set_advertisement(
       base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
 
-  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
+  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[0].GetDeviceId()));
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(1u, fake_advertisement_factory_->active_advertisements().size());
 
   // Unregister, but do not invoke the stop callback.
-  EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0]));
+  EXPECT_TRUE(
+      ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0].GetDeviceId()));
   VerifyAdvertisementHasBeenStopped(0u /* index */,
                                     fake_devices_[0].GetDeviceId());
 
@@ -359,7 +373,8 @@
   // have been created yet.
   fake_generator_->set_advertisement(
       base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
-  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
+  EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(
+      fake_devices_[0].GetDeviceId()));
   EXPECT_EQ(1u, fake_advertisement_factory_->num_created());
   EXPECT_EQ(1u, fake_advertisement_factory_->active_advertisements().size());
 
@@ -385,8 +400,8 @@
 
   fake_generator_->set_advertisement(
       base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
-  ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]);
-  ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0]);
+  ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0].GetDeviceId());
+  ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0].GetDeviceId());
   InvokeAdvertisementStoppedCallback(0u /* index */,
                                      fake_devices_[0].GetDeviceId());
   test_task_runner_->RunUntilIdle();
diff --git a/chromeos/components/tether/ble_connection_manager.cc b/chromeos/components/tether/ble_connection_manager.cc
index 031f1117..ce46c3d 100644
--- a/chromeos/components/tether/ble_connection_manager.cc
+++ b/chromeos/components/tether/ble_connection_manager.cc
@@ -11,6 +11,7 @@
 #include "chromeos/components/tether/timer_factory.h"
 #include "components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h"
 #include "components/cryptauth/cryptauth_service.h"
+#include "components/cryptauth/remote_device.h"
 #include "components/proximity_auth/logging/logging.h"
 #include "device/bluetooth/bluetooth_uuid.h"
 
@@ -43,10 +44,10 @@
 }
 
 BleConnectionManager::ConnectionMetadata::ConnectionMetadata(
-    const cryptauth::RemoteDevice remote_device,
+    const std::string& device_id,
     std::unique_ptr<base::Timer> timer,
     base::WeakPtr<BleConnectionManager> manager)
-    : remote_device_(remote_device),
+    : device_id_(device_id),
       connection_attempt_timeout_timer_(std::move(timer)),
       manager_(manager),
       weak_ptr_factory_(this) {}
@@ -113,7 +114,7 @@
 }
 
 void BleConnectionManager::ConnectionMetadata::OnConnectionAttemptTimeout() {
-  manager_->OnConnectionAttemptTimeout(remote_device_);
+  manager_->OnConnectionAttemptTimeout(device_id_);
 }
 
 bool BleConnectionManager::ConnectionMetadata::HasSecureChannel() {
@@ -162,7 +163,7 @@
     secure_channel_.reset();
   }
 
-  manager_->OnSecureChannelStatusChanged(remote_device_, old_status_copy,
+  manager_->OnSecureChannelStatusChanged(device_id_, old_status_copy,
                                          new_status_copy);
 }
 
@@ -176,7 +177,7 @@
     return;
   }
 
-  manager_->SendMessageReceivedEvent(remote_device_, payload);
+  manager_->SendMessageReceivedEvent(device_id_, payload);
 }
 
 void BleConnectionManager::ConnectionMetadata::OnMessageSent(
@@ -184,14 +185,14 @@
     int sequence_number) {
   DCHECK(secure_channel_.get() == secure_channel);
   PA_LOG(INFO) << "Message sent successfully to device with ID \""
-               << remote_device_.GetTruncatedDeviceIdForLogs() << "\"; "
-               << "message sequence number: " << sequence_number;
+               << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id_)
+               << "\"; message sequence number: " << sequence_number;
   manager_->SendMessageSentEvent(sequence_number);
 }
 
 void BleConnectionManager::ConnectionMetadata::
     OnGattCharacteristicsNotAvailable() {
-  manager_->OnGattCharacteristicsNotAvailable(remote_device_);
+  manager_->OnGattCharacteristicsNotAvailable(device_id_);
 }
 
 BleConnectionManager::BleConnectionManager(
@@ -219,7 +220,7 @@
 }
 
 void BleConnectionManager::RegisterRemoteDevice(
-    const cryptauth::RemoteDevice& remote_device,
+    const std::string& device_id,
     const MessageType& connection_reason) {
   if (!has_registered_observer_) {
     ble_scanner_->AddObserver(this);
@@ -227,50 +228,52 @@
   has_registered_observer_ = true;
 
   PA_LOG(INFO) << "Register - Device ID: \""
-               << remote_device.GetTruncatedDeviceIdForLogs()
+               << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
                << "\", Reason: " << MessageTypeToString(connection_reason);
 
-  ConnectionMetadata* connection_metadata =
-      GetConnectionMetadata(remote_device);
-  if (!connection_metadata) {
-    connection_metadata = AddMetadataForDevice(remote_device);
-  }
+  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
+  if (!connection_metadata)
+    connection_metadata = AddMetadataForDevice(device_id);
 
   connection_metadata->RegisterConnectionReason(connection_reason);
   UpdateConnectionAttempts();
 }
 
 void BleConnectionManager::UnregisterRemoteDevice(
-    const cryptauth::RemoteDevice& remote_device,
+    const std::string& device_id,
     const MessageType& connection_reason) {
-  ConnectionMetadata* connection_metadata =
-      GetConnectionMetadata(remote_device);
+  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
   if (!connection_metadata) {
     PA_LOG(WARNING) << "Tried to unregister device, but was not registered - "
                     << "Device ID: \""
-                    << remote_device.GetTruncatedDeviceIdForLogs()
+                    << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(
+                           device_id)
                     << "\", Reason: " << MessageTypeToString(connection_reason);
     return;
   }
 
   PA_LOG(INFO) << "Unregister - Device ID: \""
-               << remote_device.GetTruncatedDeviceIdForLogs()
+               << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
                << "\", Reason: " << MessageTypeToString(connection_reason);
 
   connection_metadata->UnregisterConnectionReason(connection_reason);
   if (!connection_metadata->HasReasonForConnection()) {
+    // Use a copy of the device ID. It's possible that the device ID passed to
+    // this function will be destroyed due to fields being manipulated below.
+    const std::string device_id_copy = device_id;
+
     cryptauth::SecureChannel::Status status_before_disconnect =
         connection_metadata->GetStatus();
-    device_to_metadata_map_.erase(remote_device);
+    device_id_to_metadata_map_.erase(device_id_copy);
     if (status_before_disconnect ==
         cryptauth::SecureChannel::Status::CONNECTING) {
-      StopConnectionAttemptAndMoveToEndOfQueue(remote_device);
+      StopConnectionAttemptAndMoveToEndOfQueue(device_id_copy);
     }
     if (status_before_disconnect !=
         cryptauth::SecureChannel::Status::DISCONNECTED) {
       // Send a status update for the disconnection.
       SendSecureChannelStatusChangeEvent(
-          remote_device, status_before_disconnect,
+          device_id_copy, status_before_disconnect,
           cryptauth::SecureChannel::Status::DISCONNECTED);
     }
   }
@@ -278,35 +281,31 @@
   UpdateConnectionAttempts();
 }
 
-int BleConnectionManager::SendMessage(
-    const cryptauth::RemoteDevice& remote_device,
-    const std::string& message) {
-  ConnectionMetadata* connection_metadata =
-      GetConnectionMetadata(remote_device);
+int BleConnectionManager::SendMessage(const std::string& device_id,
+                                      const std::string& message) {
+  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
   if (!connection_metadata ||
       connection_metadata->GetStatus() !=
           cryptauth::SecureChannel::Status::AUTHENTICATED) {
     PA_LOG(ERROR) << "SendMessage(): Error - no authenticated channel. "
                   << "Device ID: \""
-                  << remote_device.GetTruncatedDeviceIdForLogs() << "\", "
-                  << "Message: \"" << message << "\"";
+                  << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
+                  << "\", Message: \"" << message << "\"";
     return -1;
   }
 
   PA_LOG(INFO) << "SendMessage(): Device ID: \""
-               << remote_device.GetTruncatedDeviceIdForLogs() << "\", "
-               << "Message: \"" << message << "\"";
+               << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
+               << "\", Message: \"" << message << "\"";
   return connection_metadata->SendMessage(message);
 }
 
 bool BleConnectionManager::GetStatusForDevice(
-    const cryptauth::RemoteDevice& remote_device,
+    const std::string& device_id,
     cryptauth::SecureChannel::Status* status) const {
-  ConnectionMetadata* connection_metadata =
-      GetConnectionMetadata(remote_device);
-  if (!connection_metadata) {
+  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
+  if (!connection_metadata)
     return false;
-  }
 
   *status = connection_metadata->GetStatus();
   return true;
@@ -323,15 +322,17 @@
 void BleConnectionManager::OnReceivedAdvertisementFromDevice(
     const cryptauth::RemoteDevice& remote_device,
     device::BluetoothDevice* bluetooth_device) {
-  ConnectionMetadata* connection_metadata =
-      GetConnectionMetadata(remote_device);
+  const std::string device_id = remote_device.GetDeviceId();
+
+  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
   if (!connection_metadata) {
     // If an advertisement  is received from a device that is not registered,
     // ignore it.
     PA_LOG(WARNING) << "Received an advertisement from a device which is not "
                     << "registered. Bluetooth address: "
-                    << bluetooth_device->GetAddress() << ", Remote Device ID: "
-                    << remote_device.GetTruncatedDeviceIdForLogs();
+                    << bluetooth_device->GetAddress() << ", Remote Device "
+                    << "ID: \"" << remote_device.GetTruncatedDeviceIdForLogs()
+                    << "\".";
     return;
   }
 
@@ -339,17 +340,18 @@
     PA_LOG(WARNING) << "Received another advertisement from a registered "
                     << "device which is already being actively communicated "
                     << "with. Bluetooth address: "
-                    << bluetooth_device->GetAddress() << ", Remote Device ID: "
-                    << remote_device.GetTruncatedDeviceIdForLogs();
+                    << bluetooth_device->GetAddress() << ", Remote Device "
+                    << "ID: \"" << remote_device.GetTruncatedDeviceIdForLogs()
+                    << "\".";
     return;
   }
 
   PA_LOG(INFO) << "Received advertisement - Device ID: \""
-               << remote_device.GetTruncatedDeviceIdForLogs() << "\". "
-               << "Starting authentication handshake.";
+               << remote_device.GetTruncatedDeviceIdForLogs()
+               << "\". Starting authentication handshake.";
 
   // Stop trying to connect to that device, since it has been found.
-  StopConnectionAttemptAndMoveToEndOfQueue(remote_device);
+  StopConnectionAttemptAndMoveToEndOfQueue(device_id);
 
   // Create a connection to that device.
   std::unique_ptr<cryptauth::Connection> connection = cryptauth::weave::
@@ -366,33 +368,30 @@
 
 BleConnectionManager::ConnectionMetadata*
 BleConnectionManager::GetConnectionMetadata(
-    const cryptauth::RemoteDevice& remote_device) const {
-  const auto map_iter = device_to_metadata_map_.find(remote_device);
-  if (map_iter == device_to_metadata_map_.end())
+    const std::string& device_id) const {
+  const auto map_iter = device_id_to_metadata_map_.find(device_id);
+  if (map_iter == device_id_to_metadata_map_.end())
     return nullptr;
 
   return map_iter->second.get();
 }
 
 BleConnectionManager::ConnectionMetadata*
-BleConnectionManager::AddMetadataForDevice(
-    const cryptauth::RemoteDevice& remote_device) {
-  ConnectionMetadata* existing_data = GetConnectionMetadata(remote_device);
-  if (existing_data) {
+BleConnectionManager::AddMetadataForDevice(const std::string& device_id) {
+  ConnectionMetadata* existing_data = GetConnectionMetadata(device_id);
+  if (existing_data)
     return existing_data;
-  }
 
   // Create the metadata.
-  std::unique_ptr<ConnectionMetadata> metadata =
-      base::WrapUnique(new ConnectionMetadata(
-          remote_device, timer_factory_->CreateOneShotTimer(),
-          weak_ptr_factory_.GetWeakPtr()));
+  std::unique_ptr<ConnectionMetadata> metadata = base::WrapUnique(
+      new ConnectionMetadata(device_id, timer_factory_->CreateOneShotTimer(),
+                             weak_ptr_factory_.GetWeakPtr()));
   ConnectionMetadata* metadata_raw_ptr = metadata.get();
 
   // Add it to the map.
-  device_to_metadata_map_.emplace(
-      std::pair<cryptauth::RemoteDevice, std::unique_ptr<ConnectionMetadata>>(
-          remote_device, std::move(metadata)));
+  device_id_to_metadata_map_.emplace(
+      std::pair<std::string, std::unique_ptr<ConnectionMetadata>>(
+          device_id, std::move(metadata)));
 
   return metadata_raw_ptr;
 }
@@ -400,71 +399,73 @@
 void BleConnectionManager::UpdateConnectionAttempts() {
   UpdateAdvertisementQueue();
 
-  std::vector<cryptauth::RemoteDevice> should_advertise_to =
-      ble_advertisement_device_queue_->GetDevicesToWhichToAdvertise();
+  std::vector<std::string> should_advertise_to =
+      ble_advertisement_device_queue_->GetDeviceIdsToWhichToAdvertise();
   DCHECK(should_advertise_to.size() <= kMaxConcurrentAdvertisements);
 
   // Generate a list of devices which are advertising but are not present in
   // |should_advertise_to|.
-  std::vector<cryptauth::RemoteDevice> devices_to_stop;
-  for (const auto& map_entry : device_to_metadata_map_) {
+  std::vector<std::string> device_ids_to_stop;
+  for (const auto& map_entry : device_id_to_metadata_map_) {
     if (map_entry.second->GetStatus() ==
             cryptauth::SecureChannel::Status::CONNECTING &&
         !map_entry.second->HasEstablishedConnection() &&
         std::find(should_advertise_to.begin(), should_advertise_to.end(),
                   map_entry.first) == should_advertise_to.end()) {
-      devices_to_stop.push_back(map_entry.first);
+      device_ids_to_stop.push_back(map_entry.first);
     }
   }
+
   // For each device that should not be advertised to, end the connection
   // attempt. Note that this is done outside of the map iteration above because
   // it is possible that EndSuccessfulAttempt() will cause that map to be
   // modified during iteration.
-  for (const auto& device_to_stop : devices_to_stop) {
+  for (const auto& device_id_to_stop : device_ids_to_stop) {
     PA_LOG(INFO) << "Connection attempt for device ID \""
-                 << device_to_stop.GetTruncatedDeviceIdForLogs() << "\""
-                 << " interrupted by higher-priority connection.";
-    EndUnsuccessfulAttempt(device_to_stop);
+                 << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(
+                        device_id_to_stop)
+                 << "\" interrupted by higher-priority connection.";
+    EndUnsuccessfulAttempt(device_id_to_stop);
   }
 
-  for (const auto& remote_device : should_advertise_to) {
-    ConnectionMetadata* associated_data = GetConnectionMetadata(remote_device);
+  for (const auto& device_id : should_advertise_to) {
+    ConnectionMetadata* associated_data = GetConnectionMetadata(device_id);
     if (associated_data->GetStatus() !=
         cryptauth::SecureChannel::Status::CONNECTING) {
       // If there is no active attempt to connect to a device at the front of
       // the queue, start a connection attempt.
-      StartConnectionAttempt(remote_device);
+      StartConnectionAttempt(device_id);
     }
   }
 }
 
 void BleConnectionManager::UpdateAdvertisementQueue() {
-  std::vector<BleAdvertisementDeviceQueue::PrioritizedDevice> devices;
-  for (const auto& map_entry : device_to_metadata_map_) {
+  std::vector<BleAdvertisementDeviceQueue::PrioritizedDeviceId> prioritized_ids;
+  for (const auto& map_entry : device_id_to_metadata_map_) {
     if (map_entry.second->HasEstablishedConnection()) {
       // If there is already an active connection to the device, there is no
       // need to advertise to the device to bootstrap a connection.
       continue;
     }
 
-    devices.emplace_back(map_entry.first,
-                         map_entry.second->GetConnectionPriority());
+    prioritized_ids.emplace_back(map_entry.first,
+                                 map_entry.second->GetConnectionPriority());
   }
 
-  ble_advertisement_device_queue_->SetDevices(devices);
+  ble_advertisement_device_queue_->SetPrioritizedDeviceIds(prioritized_ids);
 }
 
 void BleConnectionManager::StartConnectionAttempt(
-    const cryptauth::RemoteDevice& remote_device) {
-  ConnectionMetadata* connection_metadata =
-      GetConnectionMetadata(remote_device);
+    const std::string& device_id) {
+  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
   DCHECK(connection_metadata);
 
   PA_LOG(INFO) << "Attempting connection - Device ID: \""
-               << remote_device.GetTruncatedDeviceIdForLogs() << "\"";
+               << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
+               << "\"";
 
-  bool success = ble_scanner_->RegisterScanFilterForDevice(remote_device) &&
-                 ble_advertiser_->StartAdvertisingToDevice(remote_device);
+  bool success = ble_scanner_->RegisterScanFilterForDevice(device_id) &&
+                 ble_advertiser_->StartAdvertisingToDevice(device_id);
 
   // Start a timer; if a connection is unable to be created before the timer
   // fires, a timeout occurs. Note that if this class is unable to start both
@@ -477,100 +478,93 @@
       !success /* fail_immediately */);
 
   // Send a "disconnected => connecting" update to alert clients that a
-  // connection attempt for |remote_device| is underway.
+  // connection attempt for |device_id| is underway.
   SendSecureChannelStatusChangeEvent(
-      remote_device, cryptauth::SecureChannel::Status::DISCONNECTED,
+      device_id, cryptauth::SecureChannel::Status::DISCONNECTED,
       cryptauth::SecureChannel::Status::CONNECTING);
 }
 
 void BleConnectionManager::EndUnsuccessfulAttempt(
-    const cryptauth::RemoteDevice& remote_device) {
-  GetConnectionMetadata(remote_device)->StopConnectionAttemptTimer();
-  StopConnectionAttemptAndMoveToEndOfQueue(remote_device);
-
-  device_id_to_advertising_start_time_map_[remote_device.GetDeviceId()] =
-      base::Time();
+    const std::string& device_id) {
+  GetConnectionMetadata(device_id)->StopConnectionAttemptTimer();
+  StopConnectionAttemptAndMoveToEndOfQueue(device_id);
+  device_id_to_advertising_start_time_map_[device_id] = base::Time();
 
   // Send a "connecting => disconnected" update to alert clients that a
-  // connection attempt for |remote_device| has failed.
+  // connection attempt for |device_id| has failed.
   SendSecureChannelStatusChangeEvent(
-      remote_device, cryptauth::SecureChannel::Status::CONNECTING,
+      device_id, cryptauth::SecureChannel::Status::CONNECTING,
       cryptauth::SecureChannel::Status::DISCONNECTED);
 }
 
 void BleConnectionManager::StopConnectionAttemptAndMoveToEndOfQueue(
-    const cryptauth::RemoteDevice& remote_device) {
-  ble_scanner_->UnregisterScanFilterForDevice(remote_device);
-  ble_advertiser_->StopAdvertisingToDevice(remote_device);
-  ble_advertisement_device_queue_->MoveDeviceToEnd(remote_device.GetDeviceId());
+    const std::string& device_id) {
+  ble_scanner_->UnregisterScanFilterForDevice(device_id);
+  ble_advertiser_->StopAdvertisingToDevice(device_id);
+  ble_advertisement_device_queue_->MoveDeviceToEnd(device_id);
 }
 
 void BleConnectionManager::OnConnectionAttemptTimeout(
-    const cryptauth::RemoteDevice& remote_device) {
+    const std::string& device_id) {
   PA_LOG(INFO) << "Connection attempt timeout - Device ID \""
-               << remote_device.GetTruncatedDeviceIdForLogs() << "\"";
-  EndUnsuccessfulAttempt(remote_device);
+               << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
+               << "\".";
+  EndUnsuccessfulAttempt(device_id);
   UpdateConnectionAttempts();
 }
 
 void BleConnectionManager::OnSecureChannelStatusChanged(
-    const cryptauth::RemoteDevice& remote_device,
+    const std::string& device_id,
     const cryptauth::SecureChannel::Status& old_status,
     const cryptauth::SecureChannel::Status& new_status) {
-  SendSecureChannelStatusChangeEvent(remote_device, old_status, new_status);
+  SendSecureChannelStatusChangeEvent(device_id, old_status, new_status);
   UpdateConnectionAttempts();
 }
 
 void BleConnectionManager::OnGattCharacteristicsNotAvailable(
-    const cryptauth::RemoteDevice& remote_device) {
+    const std::string& device_id) {
   PA_LOG(WARNING) << "Previous connection attempt failed due to unavailable "
                   << "GATT services for device ID \""
-                  << remote_device.GetTruncatedDeviceIdForLogs() << "\".";
-  ad_hoc_ble_advertisement_->RequestGattServicesForDevice(remote_device);
+                  << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
+                  << "\".";
+  ad_hoc_ble_advertisement_->RequestGattServicesForDevice(device_id);
 }
 
-void BleConnectionManager::SendMessageReceivedEvent(
-    cryptauth::RemoteDevice remote_device,
-    std::string payload) {
+void BleConnectionManager::SendMessageReceivedEvent(std::string device_id,
+                                                    std::string payload) {
   PA_LOG(INFO) << "Message received - Device ID: \""
-               << remote_device.GetTruncatedDeviceIdForLogs() << "\", "
-               << "Message: \"" << payload << "\".";
-  for (auto& observer : observer_list_) {
-    observer.OnMessageReceived(remote_device, payload);
-  }
+               << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
+               << "\", Message: \"" << payload << "\".";
+  for (auto& observer : observer_list_)
+    observer.OnMessageReceived(device_id, payload);
 }
 
 void BleConnectionManager::SendSecureChannelStatusChangeEvent(
-    cryptauth::RemoteDevice remote_device,
+    std::string device_id,
     cryptauth::SecureChannel::Status old_status,
     cryptauth::SecureChannel::Status new_status) {
   PA_LOG(INFO) << "Status change - Device ID: \""
-               << remote_device.GetTruncatedDeviceIdForLogs()
+               << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
                << "\": " << cryptauth::SecureChannel::StatusToString(old_status)
                << " => "
                << cryptauth::SecureChannel::StatusToString(new_status);
 
   if (new_status == cryptauth::SecureChannel::Status::CONNECTING) {
-    device_id_to_advertising_start_time_map_[remote_device.GetDeviceId()] =
-        clock_->Now();
+    device_id_to_advertising_start_time_map_[device_id] = clock_->Now();
   } else if (new_status == cryptauth::SecureChannel::Status::CONNECTED) {
-    device_id_to_status_connected_time_map_[remote_device.GetDeviceId()] =
-        clock_->Now();
-    RecordAdvertisementToConnectionDuration(remote_device.GetDeviceId());
+    device_id_to_status_connected_time_map_[device_id] = clock_->Now();
+    RecordAdvertisementToConnectionDuration(device_id);
   } else if (new_status == cryptauth::SecureChannel::Status::AUTHENTICATED) {
-    RecordConnectionToAuthenticationDuration(remote_device.GetDeviceId());
+    RecordConnectionToAuthenticationDuration(device_id);
   }
 
-  for (auto& observer : observer_list_) {
-    observer.OnSecureChannelStatusChanged(remote_device, old_status,
-                                          new_status);
-  }
+  for (auto& observer : observer_list_)
+    observer.OnSecureChannelStatusChanged(device_id, old_status, new_status);
 }
 
 void BleConnectionManager::SendMessageSentEvent(int sequence_number) {
-  for (auto& observer : observer_list_) {
+  for (auto& observer : observer_list_)
     observer.OnMessageSent(sequence_number);
-  }
 }
 
 void BleConnectionManager::SetTestDoubles(
diff --git a/chromeos/components/tether/ble_connection_manager.h b/chromeos/components/tether/ble_connection_manager.h
index 5ccefc3..2cce9d27 100644
--- a/chromeos/components/tether/ble_connection_manager.h
+++ b/chromeos/components/tether/ble_connection_manager.h
@@ -20,7 +20,6 @@
 #include "chromeos/components/tether/ble_scanner.h"
 #include "chromeos/components/tether/connection_priority.h"
 #include "chromeos/components/tether/proto/tether.pb.h"
-#include "components/cryptauth/remote_device.h"
 #include "components/cryptauth/secure_channel.h"
 
 namespace cryptauth {
@@ -68,11 +67,11 @@
   class Observer {
    public:
     virtual void OnSecureChannelStatusChanged(
-        const cryptauth::RemoteDevice& remote_device,
+        const std::string& device_id,
         const cryptauth::SecureChannel::Status& old_status,
         const cryptauth::SecureChannel::Status& new_status) = 0;
 
-    virtual void OnMessageReceived(const cryptauth::RemoteDevice& remote_device,
+    virtual void OnMessageReceived(const std::string& device_id,
                                    const std::string& payload) = 0;
 
     // Called when a message has been sent successfully; |sequence_number|
@@ -89,33 +88,31 @@
       AdHocBleAdvertiser* ad_hoc_ble_advertisement);
   virtual ~BleConnectionManager();
 
-  // Registers |remote_device| for |connection_reason|. Once registered, this
+  // Registers |device_id| for |connection_reason|. Once registered, this
   // instance will continue to attempt to connect and authenticate to that
   // device until the device is unregistered.
-  virtual void RegisterRemoteDevice(
-      const cryptauth::RemoteDevice& remote_device,
-      const MessageType& connection_reason);
+  virtual void RegisterRemoteDevice(const std::string& device_id,
+                                    const MessageType& connection_reason);
 
-  // Unregisters |remote_device| for |connection_reason|. Once registered, a
-  // device will continue trying to connect until *ALL* of its
-  // MessageTypes have been unregistered.
-  virtual void UnregisterRemoteDevice(
-      const cryptauth::RemoteDevice& remote_device,
-      const MessageType& connection_reason);
+  // Unregisters |device_id| for |connection_reason|. Once registered, a device
+  // will continue trying to connect until *ALL* of its MessageTypes have been
+  // unregistered.
+  virtual void UnregisterRemoteDevice(const std::string& device_id,
+                                      const MessageType& connection_reason);
 
-  // Sends |message| to |remote_device|. This function can only be called if the
-  // given device is authenticated. This function returns a sequence number for
-  // the message; if this message is sent successfully, observers will be
-  // notified and provided this number. Note that -1 is returned when the
-  // message cannot be sent.
-  virtual int SendMessage(const cryptauth::RemoteDevice& remote_device,
+  // Sends |message| to the device with ID |device_id|. This function can only
+  // be called if the given device is authenticated. This function returns a
+  // sequence number for the message; if this message is sent successfully,
+  // observers will be notified and provided this number. Note that -1 is
+  // returned when the message cannot be sent.
+  virtual int SendMessage(const std::string& device_id,
                           const std::string& message);
 
-  // Gets |remote_device|'s status and stores it to |status|, returning whether
-  // |remote_device| is registered. If this function returns |false|, no value
-  // is saved to |status|.
+  // Gets the device with ID |device_id|'s status and stores it to |status|,
+  // returning whether that device is registered. If this function returns
+  // |false|, no value is saved to |status|.
   virtual bool GetStatusForDevice(
-      const cryptauth::RemoteDevice& remote_device,
+      const std::string& device_id,
       cryptauth::SecureChannel::Status* status) const;
 
   void AddObserver(Observer* observer);
@@ -127,10 +124,9 @@
       device::BluetoothDevice* bluetooth_device) override;
 
  protected:
-  void SendMessageReceivedEvent(cryptauth::RemoteDevice remote_device,
-                                std::string payload);
+  void SendMessageReceivedEvent(std::string device_id, std::string payload);
   void SendSecureChannelStatusChangeEvent(
-      cryptauth::RemoteDevice remote_device,
+      std::string device_id,
       cryptauth::SecureChannel::Status old_status,
       cryptauth::SecureChannel::Status new_status);
   void SendMessageSentEvent(int sequence_number);
@@ -142,13 +138,13 @@
   static const int64_t kFailImmediatelyTimeoutMillis;
 
   // Data associated with a registered device. Each registered device has an
-  // associated |ConnectionMetadata| stored in |device_to_metadata_map_|, and
+  // associated |ConnectionMetadata| stored in |device_id_to_metadata_map_|, and
   // the |ConnectionMetadata| is removed when the device is unregistered. A
   // |ConnectionMetadata| stores the associated |SecureChannel| for registered
   // devices which have an active connection.
   class ConnectionMetadata final : public cryptauth::SecureChannel::Observer {
    public:
-    ConnectionMetadata(const cryptauth::RemoteDevice remote_device,
+    ConnectionMetadata(const std::string& device_id,
                        std::unique_ptr<base::Timer> timer,
                        base::WeakPtr<BleConnectionManager> manager);
     ~ConnectionMetadata();
@@ -185,7 +181,7 @@
 
     void OnConnectionAttemptTimeout();
 
-    cryptauth::RemoteDevice remote_device_;
+    std::string device_id_;
     std::set<MessageType> active_connection_reasons_;
     std::unique_ptr<cryptauth::SecureChannel> secure_channel_;
     std::unique_ptr<base::Timer> connection_attempt_timeout_timer_;
@@ -194,26 +190,22 @@
     base::WeakPtrFactory<ConnectionMetadata> weak_ptr_factory_;
   };
 
-  ConnectionMetadata* GetConnectionMetadata(
-      const cryptauth::RemoteDevice& remote_device) const;
-  ConnectionMetadata* AddMetadataForDevice(
-      const cryptauth::RemoteDevice& remote_device);
+  ConnectionMetadata* GetConnectionMetadata(const std::string& device_id) const;
+  ConnectionMetadata* AddMetadataForDevice(const std::string& device_id);
 
   void UpdateConnectionAttempts();
   void UpdateAdvertisementQueue();
 
-  void StartConnectionAttempt(const cryptauth::RemoteDevice& remote_device);
-  void EndUnsuccessfulAttempt(const cryptauth::RemoteDevice& remote_device);
-  void StopConnectionAttemptAndMoveToEndOfQueue(
-      const cryptauth::RemoteDevice& remote_device);
+  void StartConnectionAttempt(const std::string& device_id);
+  void EndUnsuccessfulAttempt(const std::string& device_id);
+  void StopConnectionAttemptAndMoveToEndOfQueue(const std::string& device_id);
 
-  void OnConnectionAttemptTimeout(const cryptauth::RemoteDevice& remote_device);
+  void OnConnectionAttemptTimeout(const std::string& device_id);
   void OnSecureChannelStatusChanged(
-      const cryptauth::RemoteDevice& remote_device,
+      const std::string& device_id,
       const cryptauth::SecureChannel::Status& old_status,
       const cryptauth::SecureChannel::Status& new_status);
-  void OnGattCharacteristicsNotAvailable(
-      const cryptauth::RemoteDevice& remote_device);
+  void OnGattCharacteristicsNotAvailable(const std::string& device_id);
 
   void SetTestDoubles(std::unique_ptr<base::Clock> test_clock,
                       std::unique_ptr<TimerFactory> test_timer_factory);
@@ -235,8 +227,8 @@
   std::unique_ptr<base::Clock> clock_;
 
   bool has_registered_observer_;
-  std::map<cryptauth::RemoteDevice, std::unique_ptr<ConnectionMetadata>>
-      device_to_metadata_map_;
+  std::map<std::string, std::unique_ptr<ConnectionMetadata>>
+      device_id_to_metadata_map_;
 
   std::map<std::string, base::Time> device_id_to_advertising_start_time_map_;
   std::map<std::string, base::Time> device_id_to_status_connected_time_map_;
diff --git a/chromeos/components/tether/ble_connection_manager_unittest.cc b/chromeos/components/tether/ble_connection_manager_unittest.cc
index d4986fde6..201a435 100644
--- a/chromeos/components/tether/ble_connection_manager_unittest.cc
+++ b/chromeos/components/tether/ble_connection_manager_unittest.cc
@@ -48,24 +48,21 @@
     base::TimeDelta::FromSeconds(3);
 
 struct SecureChannelStatusChange {
-  SecureChannelStatusChange(const cryptauth::RemoteDevice& remote_device,
+  SecureChannelStatusChange(const std::string& device_id,
                             const cryptauth::SecureChannel::Status& old_status,
                             const cryptauth::SecureChannel::Status& new_status)
-      : remote_device(remote_device),
-        old_status(old_status),
-        new_status(new_status) {}
+      : device_id(device_id), old_status(old_status), new_status(new_status) {}
 
-  cryptauth::RemoteDevice remote_device;
+  std::string device_id;
   cryptauth::SecureChannel::Status old_status;
   cryptauth::SecureChannel::Status new_status;
 };
 
 struct ReceivedMessage {
-  ReceivedMessage(const cryptauth::RemoteDevice& remote_device,
-                  const std::string& payload)
-      : remote_device(remote_device), payload(payload) {}
+  ReceivedMessage(const std::string& device_id, const std::string& payload)
+      : device_id(device_id), payload(payload) {}
 
-  cryptauth::RemoteDevice remote_device;
+  std::string device_id;
   std::string payload;
 };
 
@@ -85,16 +82,16 @@
 
   // BleConnectionManager::Observer:
   void OnSecureChannelStatusChanged(
-      const cryptauth::RemoteDevice& remote_device,
+      const std::string& device_id,
       const cryptauth::SecureChannel::Status& old_status,
       const cryptauth::SecureChannel::Status& new_status) override {
     connection_status_changes_.push_back(
-        SecureChannelStatusChange(remote_device, old_status, new_status));
+        SecureChannelStatusChange(device_id, old_status, new_status));
   }
 
-  void OnMessageReceived(const cryptauth::RemoteDevice& remote_device,
+  void OnMessageReceived(const std::string& device_id,
                          const std::string& payload) override {
-    received_messages_.push_back(ReceivedMessage(remote_device, payload));
+    received_messages_.push_back(ReceivedMessage(device_id, payload));
   }
 
   void OnMessageSent(int sequence_number) override {
@@ -130,15 +127,15 @@
 
   // BleConnectionManager::Observer:
   void OnSecureChannelStatusChanged(
-      const cryptauth::RemoteDevice& remote_device,
+      const std::string& device_id,
       const cryptauth::SecureChannel::Status& old_status,
       const cryptauth::SecureChannel::Status& new_status) override {
-    manager_->UnregisterRemoteDevice(remote_device, connection_reason_);
+    manager_->UnregisterRemoteDevice(device_id, connection_reason_);
   }
 
-  void OnMessageReceived(const cryptauth::RemoteDevice& remote_device,
+  void OnMessageReceived(const std::string& device_id,
                          const std::string& payload) override {
-    manager_->UnregisterRemoteDevice(remote_device, connection_reason_);
+    manager_->UnregisterRemoteDevice(device_id, connection_reason_);
   }
 
   void OnMessageSent(int sequence_number) override { NOTIMPLEMENTED(); }
@@ -316,8 +313,8 @@
               test_observer_->connection_status_changes().size());
 
     for (size_t i = 0; i < verified_status_changes_.size(); i++) {
-      EXPECT_EQ(verified_status_changes_[i].remote_device,
-                test_observer_->connection_status_changes()[i].remote_device);
+      EXPECT_EQ(verified_status_changes_[i].device_id,
+                test_observer_->connection_status_changes()[i].device_id);
       EXPECT_EQ(verified_status_changes_[i].old_status,
                 test_observer_->connection_status_changes()[i].old_status);
       EXPECT_EQ(verified_status_changes_[i].new_status,
@@ -335,8 +332,8 @@
               test_observer_->received_messages().size());
 
     for (size_t i = 0; i < verified_received_messages_.size(); i++) {
-      EXPECT_EQ(verified_received_messages_[i].remote_device,
-                test_observer_->received_messages()[i].remote_device);
+      EXPECT_EQ(verified_received_messages_[i].device_id,
+                test_observer_->received_messages()[i].device_id);
       EXPECT_EQ(verified_received_messages_[i].payload,
                 test_observer_->received_messages()[i].payload);
     }
@@ -344,7 +341,7 @@
 
   void VerifyNoTimeoutSet(const cryptauth::RemoteDevice& remote_device) {
     BleConnectionManager::ConnectionMetadata* connection_metadata =
-        manager_->GetConnectionMetadata(remote_device);
+        manager_->GetConnectionMetadata(remote_device.GetDeviceId());
     EXPECT_TRUE(connection_metadata);
     EXPECT_FALSE(
         connection_metadata->connection_attempt_timeout_timer_->IsRunning());
@@ -365,7 +362,7 @@
   void VerifyTimeoutSet(const cryptauth::RemoteDevice& remote_device,
                         int64_t expected_num_millis) {
     BleConnectionManager::ConnectionMetadata* connection_metadata =
-        manager_->GetConnectionMetadata(remote_device);
+        manager_->GetConnectionMetadata(remote_device.GetDeviceId());
     EXPECT_TRUE(connection_metadata);
     EXPECT_TRUE(
         connection_metadata->connection_attempt_timeout_timer_->IsRunning());
@@ -376,7 +373,7 @@
 
   void FireTimerForDevice(const cryptauth::RemoteDevice& remote_device) {
     BleConnectionManager::ConnectionMetadata* connection_metadata =
-        manager_->GetConnectionMetadata(remote_device);
+        manager_->GetConnectionMetadata(remote_device.GetDeviceId());
     EXPECT_TRUE(connection_metadata);
     EXPECT_TRUE(
         connection_metadata->connection_attempt_timeout_timer_->IsRunning());
@@ -398,7 +395,7 @@
   FakeSecureChannel* GetChannelForDevice(
       const cryptauth::RemoteDevice& remote_device) {
     BleConnectionManager::ConnectionMetadata* connection_metadata =
-        manager_->GetConnectionMetadata(remote_device);
+        manager_->GetConnectionMetadata(remote_device.GetDeviceId());
     EXPECT_TRUE(connection_metadata);
     EXPECT_TRUE(connection_metadata->secure_channel_);
     return static_cast<FakeSecureChannel*>(
@@ -407,13 +404,13 @@
 
   void VerifyDeviceRegistered(const cryptauth::RemoteDevice& remote_device) {
     BleConnectionManager::ConnectionMetadata* connection_metadata =
-        manager_->GetConnectionMetadata(remote_device);
+        manager_->GetConnectionMetadata(remote_device.GetDeviceId());
     EXPECT_TRUE(connection_metadata);
   }
 
   void VerifyDeviceNotRegistered(const cryptauth::RemoteDevice& remote_device) {
     BleConnectionManager::ConnectionMetadata* connection_metadata =
-        manager_->GetConnectionMetadata(remote_device);
+        manager_->GetConnectionMetadata(remote_device.GetDeviceId());
     EXPECT_FALSE(connection_metadata);
   }
 
@@ -425,10 +422,12 @@
       const MessageType connection_reason) {
     test_clock_->SetNow(base::Time::UnixEpoch());
 
-    manager_->RegisterRemoteDevice(remote_device, connection_reason);
+    manager_->RegisterRemoteDevice(remote_device.GetDeviceId(),
+                                   connection_reason);
     VerifyAdvertisingTimeoutSet(remote_device);
     VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-        {remote_device, cryptauth::SecureChannel::Status::DISCONNECTED,
+        {remote_device.GetDeviceId(),
+         cryptauth::SecureChannel::Status::DISCONNECTED,
          cryptauth::SecureChannel::Status::CONNECTING}});
 
     FakeSecureChannel* channel =
@@ -477,11 +476,14 @@
         kStatusAuthenticatedTime, num_expected_authenticated_channels_);
 
     VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-        {remote_device, cryptauth::SecureChannel::Status::CONNECTING,
+        {remote_device.GetDeviceId(),
+         cryptauth::SecureChannel::Status::CONNECTING,
          cryptauth::SecureChannel::Status::CONNECTED},
-        {remote_device, cryptauth::SecureChannel::Status::CONNECTED,
+        {remote_device.GetDeviceId(),
+         cryptauth::SecureChannel::Status::CONNECTED,
          cryptauth::SecureChannel::Status::AUTHENTICATING},
-        {remote_device, cryptauth::SecureChannel::Status::AUTHENTICATING,
+        {remote_device.GetDeviceId(),
+         cryptauth::SecureChannel::Status::AUTHENTICATING,
          cryptauth::SecureChannel::Status::AUTHENTICATED}});
   }
 
@@ -544,11 +546,12 @@
 TEST_F(BleConnectionManagerTest, TestCannotScan) {
   fake_ble_scanner_->set_should_fail_to_register(true);
 
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyFailImmediatelyTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   VerifyAdvertisingToConnectionDurationMetricNotRecorded();
@@ -558,11 +561,12 @@
 TEST_F(BleConnectionManagerTest, TestCannotAdvertise) {
   fake_ble_advertiser_->set_should_fail_to_start_advertising(true);
 
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyFailImmediatelyTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   VerifyAdvertisingToConnectionDurationMetricNotRecorded();
@@ -570,11 +574,12 @@
 }
 
 TEST_F(BleConnectionManagerTest, TestRegistersButNoResult) {
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   VerifyAdvertisingToConnectionDurationMetricNotRecorded();
@@ -582,17 +587,19 @@
 }
 
 TEST_F(BleConnectionManagerTest, TestRegistersAndUnregister_NoConnection) {
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
 
   VerifyAdvertisingToConnectionDurationMetricNotRecorded();
@@ -600,11 +607,12 @@
 }
 
 TEST_F(BleConnectionManagerTest, TestAdHocBleAdvertiser) {
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Simulate the channel failing to find GATT services and disconnecting.
@@ -613,9 +621,11 @@
   channel->NotifyGattCharacteristicsNotAvailable();
   channel->Disconnect();
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // A GATT services workaround should have been requested for that device.
@@ -624,24 +634,28 @@
 }
 
 TEST_F(BleConnectionManagerTest, TestRegisterWithNoConnection_TimeoutOccurs) {
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   FireTimerForDevice(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
 
   VerifyAdvertisingToConnectionDurationMetricNotRecorded();
@@ -649,11 +663,12 @@
 }
 
 TEST_F(BleConnectionManagerTest, TestSuccessfulConnection_FailsAuthentication) {
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   fake_secure_channel_factory_->SetExpectedDeviceAddress(kBluetoothAddress1);
@@ -666,20 +681,24 @@
 
   channel->ChangeStatus(cryptauth::SecureChannel::Status::CONNECTED);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::CONNECTED}});
 
   channel->ChangeStatus(cryptauth::SecureChannel::Status::AUTHENTICATING);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTED,
        cryptauth::SecureChannel::Status::AUTHENTICATING}});
 
   // Fail authentication, which should automatically start a retry.
   channel->ChangeStatus(cryptauth::SecureChannel::Status::DISCONNECTED);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATING,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   VerifyConnectionToAuthenticationDurationMetricNotRecorded();
@@ -690,24 +709,27 @@
       ConnectSuccessfully(test_devices_[0], kBluetoothAddress1,
                           MessageType::TETHER_AVAILABILITY_REQUEST);
 
-  int sequence_number = manager_->SendMessage(test_devices_[0], "request1");
+  int sequence_number =
+      manager_->SendMessage(test_devices_[0].GetDeviceId(), "request1");
   VerifyLastMessageSent(channel, sequence_number, "request1", 1);
 
   channel->ReceiveMessage(kTetherFeature, "response1");
-  VerifyReceivedMessages(
-      std::vector<ReceivedMessage>{{test_devices_[0], "response1"}});
+  VerifyReceivedMessages(std::vector<ReceivedMessage>{
+      {test_devices_[0].GetDeviceId(), "response1"}});
 
-  sequence_number = manager_->SendMessage(test_devices_[0], "request2");
+  sequence_number =
+      manager_->SendMessage(test_devices_[0].GetDeviceId(), "request2");
   VerifyLastMessageSent(channel, sequence_number, "request2", 2);
 
   channel->ReceiveMessage(kTetherFeature, "response2");
-  VerifyReceivedMessages(
-      std::vector<ReceivedMessage>{{test_devices_[0], "response2"}});
+  VerifyReceivedMessages(std::vector<ReceivedMessage>{
+      {test_devices_[0].GetDeviceId(), "response2"}});
 
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
   VerifyDeviceNotRegistered(test_devices_[0]);
 }
@@ -715,11 +737,12 @@
 // Test for fix to crbug.com/706640. This test will crash without the fix.
 TEST_F(BleConnectionManagerTest,
        TestSuccessfulConnection_MultipleAdvertisementsReceived) {
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   fake_secure_channel_factory_->SetExpectedDeviceAddress(kBluetoothAddress1);
@@ -743,21 +766,22 @@
                       MessageType::TETHER_AVAILABILITY_REQUEST);
 
   // Now, register a different connection reason.
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::CONNECT_TETHERING_REQUEST);
 
   // Unregister the |TETHER_AVAILABILITY_REQUEST| reason, but leave the
   // |CONNECT_TETHERING_REQUEST| registered.
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyDeviceRegistered(test_devices_[0]);
 
   // Now, unregister the other reason; this should cause the device to be
   // fully unregistered.
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::CONNECT_TETHERING_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
   VerifyDeviceNotRegistered(test_devices_[0]);
 }
@@ -766,17 +790,20 @@
   cryptauth::SecureChannel::Status status;
 
   // Should return false when the device has not yet been registered at all.
-  EXPECT_FALSE(manager_->GetStatusForDevice(test_devices_[0], &status));
+  EXPECT_FALSE(
+      manager_->GetStatusForDevice(test_devices_[0].GetDeviceId(), &status));
 
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Should be CONNECTING at this point.
-  EXPECT_TRUE(manager_->GetStatusForDevice(test_devices_[0], &status));
+  EXPECT_TRUE(
+      manager_->GetStatusForDevice(test_devices_[0].GetDeviceId(), &status));
   EXPECT_EQ(cryptauth::SecureChannel::Status::CONNECTING, status);
 
   fake_secure_channel_factory_->SetExpectedDeviceAddress(kBluetoothAddress1);
@@ -784,38 +811,47 @@
   FakeSecureChannel* channel = GetChannelForDevice(test_devices_[0]);
 
   channel->ChangeStatus(cryptauth::SecureChannel::Status::CONNECTING);
-  EXPECT_TRUE(manager_->GetStatusForDevice(test_devices_[0], &status));
+  EXPECT_TRUE(
+      manager_->GetStatusForDevice(test_devices_[0].GetDeviceId(), &status));
   EXPECT_EQ(cryptauth::SecureChannel::Status::CONNECTING, status);
 
   channel->ChangeStatus(cryptauth::SecureChannel::Status::CONNECTED);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::CONNECTED}});
-  EXPECT_TRUE(manager_->GetStatusForDevice(test_devices_[0], &status));
+  EXPECT_TRUE(
+      manager_->GetStatusForDevice(test_devices_[0].GetDeviceId(), &status));
   EXPECT_EQ(cryptauth::SecureChannel::Status::CONNECTED, status);
 
   channel->ChangeStatus(cryptauth::SecureChannel::Status::AUTHENTICATING);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTED,
        cryptauth::SecureChannel::Status::AUTHENTICATING}});
-  EXPECT_TRUE(manager_->GetStatusForDevice(test_devices_[0], &status));
+  EXPECT_TRUE(
+      manager_->GetStatusForDevice(test_devices_[0].GetDeviceId(), &status));
   EXPECT_EQ(cryptauth::SecureChannel::Status::AUTHENTICATING, status);
 
   channel->ChangeStatus(cryptauth::SecureChannel::Status::AUTHENTICATED);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATING,
        cryptauth::SecureChannel::Status::AUTHENTICATED}});
-  EXPECT_TRUE(manager_->GetStatusForDevice(test_devices_[0], &status));
+  EXPECT_TRUE(
+      manager_->GetStatusForDevice(test_devices_[0].GetDeviceId(), &status));
   EXPECT_EQ(cryptauth::SecureChannel::Status::AUTHENTICATED, status);
 
   // Now, unregister the device and check that GetStatusForDevice() once again
   // returns false.
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
-  EXPECT_FALSE(manager_->GetStatusForDevice(test_devices_[0], &status));
+  EXPECT_FALSE(
+      manager_->GetStatusForDevice(test_devices_[0].GetDeviceId(), &status));
 }
 
 TEST_F(BleConnectionManagerTest,
@@ -826,44 +862,50 @@
 
   channel->ChangeStatus(cryptauth::SecureChannel::Status::DISCONNECTED);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 }
 
 TEST_F(BleConnectionManagerTest, TwoDevices_NeitherCanScan) {
   fake_ble_scanner_->set_should_fail_to_register(true);
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyFailImmediatelyTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
-  manager_->RegisterRemoteDevice(test_devices_[1],
+  manager_->RegisterRemoteDevice(test_devices_[1].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyFailImmediatelyTimeoutSet(test_devices_[1]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 }
 
 TEST_F(BleConnectionManagerTest, TwoDevices_NeitherCanAdvertise) {
   fake_ble_advertiser_->set_should_fail_to_start_advertising(true);
 
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyFailImmediatelyTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
-  manager_->RegisterRemoteDevice(test_devices_[1],
+  manager_->RegisterRemoteDevice(test_devices_[1].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyFailImmediatelyTimeoutSet(test_devices_[1]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   VerifyAdvertisingToConnectionDurationMetricNotRecorded();
@@ -873,49 +915,57 @@
 TEST_F(BleConnectionManagerTest,
        TwoDevices_RegisterWithNoConnection_TimerFires) {
   // Register device 0.
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Register device 1.
-  manager_->RegisterRemoteDevice(test_devices_[1],
+  manager_->RegisterRemoteDevice(test_devices_[1].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[1]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Simulate timeout for device 0 by firing timeout.
   FireTimerForDevice(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Simulate timeout for device 1 by firing timeout.
   FireTimerForDevice(test_devices_[1]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Unregister device 0.
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
 
   // Unregister device 1.
-  manager_->UnregisterRemoteDevice(test_devices_[1],
+  manager_->UnregisterRemoteDevice(test_devices_[1].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
 
   VerifyAdvertisingToConnectionDurationMetricNotRecorded();
@@ -928,33 +978,38 @@
                       MessageType::TETHER_AVAILABILITY_REQUEST);
 
   // Register device 1.
-  manager_->RegisterRemoteDevice(test_devices_[1],
+  manager_->RegisterRemoteDevice(test_devices_[1].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyAdvertisingTimeoutSet(test_devices_[1]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Simulate timeout for device 1 by firing timeout.
   FireTimerForDevice(test_devices_[1]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Unregister device 0.
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
 
   // Unregister device 1.
-  manager_->UnregisterRemoteDevice(test_devices_[1],
+  manager_->UnregisterRemoteDevice(test_devices_[1].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
 }
 
@@ -968,45 +1023,50 @@
                           MessageType::TETHER_AVAILABILITY_REQUEST);
 
   int sequence_number =
-      manager_->SendMessage(test_devices_[0], "request1_device0");
+      manager_->SendMessage(test_devices_[0].GetDeviceId(), "request1_device0");
   VerifyLastMessageSent(channel0, sequence_number, "request1_device0", 1);
 
-  sequence_number = manager_->SendMessage(test_devices_[1], "request1_device1");
+  sequence_number =
+      manager_->SendMessage(test_devices_[1].GetDeviceId(), "request1_device1");
   VerifyLastMessageSent(channel1, sequence_number, "request1_device1", 1);
 
   channel0->ReceiveMessage(kTetherFeature, "response1_device0");
-  VerifyReceivedMessages(
-      std::vector<ReceivedMessage>{{test_devices_[0], "response1_device0"}});
+  VerifyReceivedMessages(std::vector<ReceivedMessage>{
+      {test_devices_[0].GetDeviceId(), "response1_device0"}});
 
   channel1->ReceiveMessage(kTetherFeature, "response1_device1");
-  VerifyReceivedMessages(
-      std::vector<ReceivedMessage>{{test_devices_[1], "response1_device1"}});
+  VerifyReceivedMessages(std::vector<ReceivedMessage>{
+      {test_devices_[1].GetDeviceId(), "response1_device1"}});
 
-  sequence_number = manager_->SendMessage(test_devices_[0], "request2_device0");
+  sequence_number =
+      manager_->SendMessage(test_devices_[0].GetDeviceId(), "request2_device0");
   VerifyLastMessageSent(channel0, sequence_number, "request2_device0", 2);
 
-  sequence_number = manager_->SendMessage(test_devices_[1], "request2_device1");
+  sequence_number =
+      manager_->SendMessage(test_devices_[1].GetDeviceId(), "request2_device1");
   VerifyLastMessageSent(channel1, sequence_number, "request2_device1", 2);
 
   channel0->ReceiveMessage(kTetherFeature, "response2_device0");
-  VerifyReceivedMessages(
-      std::vector<ReceivedMessage>{{test_devices_[0], "response2_device0"}});
+  VerifyReceivedMessages(std::vector<ReceivedMessage>{
+      {test_devices_[0].GetDeviceId(), "response2_device0"}});
 
   channel1->ReceiveMessage(kTetherFeature, "response2_device1");
-  VerifyReceivedMessages(
-      std::vector<ReceivedMessage>{{test_devices_[1], "response2_device1"}});
+  VerifyReceivedMessages(std::vector<ReceivedMessage>{
+      {test_devices_[1].GetDeviceId(), "response2_device1"}});
 
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
   VerifyDeviceNotRegistered(test_devices_[0]);
 
-  manager_->UnregisterRemoteDevice(test_devices_[1],
+  manager_->UnregisterRemoteDevice(test_devices_[1].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
   VerifyDeviceNotRegistered(test_devices_[1]);
 }
@@ -1014,13 +1074,13 @@
 TEST_F(BleConnectionManagerTest, FourDevices_ComprehensiveTest) {
   // Register all devices. Since the maximum number of simultaneous connection
   // attempts is 2, only devices 0 and 1 should actually start connecting.
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
-  manager_->RegisterRemoteDevice(test_devices_[1],
+  manager_->RegisterRemoteDevice(test_devices_[1].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
-  manager_->RegisterRemoteDevice(test_devices_[2],
+  manager_->RegisterRemoteDevice(test_devices_[2].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
-  manager_->RegisterRemoteDevice(test_devices_[3],
+  manager_->RegisterRemoteDevice(test_devices_[3].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
 
   // Devices 0 and 1 should be advertising; devices 2 and 3 should not be.
@@ -1029,9 +1089,11 @@
   VerifyNoTimeoutSet(test_devices_[2]);
   VerifyNoTimeoutSet(test_devices_[3]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING},
-      {test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Device 0 connects successfully.
@@ -1041,7 +1103,8 @@
   // Since device 0 has connected, advertising to that device is no longer
   // necessary. Device 2 should have filled up that advertising slot.
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[2], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[2].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Meanwhile, device 1 fails to connect, so the timeout fires. The advertising
@@ -1050,26 +1113,30 @@
   VerifyAdvertisingTimeoutSet(test_devices_[3]);
   VerifyNoTimeoutSet(test_devices_[1]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[3], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[3].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Now, device 0 authenticates and sends and receives a message.
   AuthenticateChannel(test_devices_[0]);
-  int sequence_number = manager_->SendMessage(test_devices_[0], "request1");
+  int sequence_number =
+      manager_->SendMessage(test_devices_[0].GetDeviceId(), "request1");
   VerifyLastMessageSent(channel0, sequence_number, "request1", 1);
 
   channel0->ReceiveMessage(kTetherFeature, "response1");
-  VerifyReceivedMessages(
-      std::vector<ReceivedMessage>{{test_devices_[0], "response1"}});
+  VerifyReceivedMessages(std::vector<ReceivedMessage>{
+      {test_devices_[0].GetDeviceId(), "response1"}});
 
   // Now, device 0 is unregistered.
-  manager_->UnregisterRemoteDevice(test_devices_[0],
+  manager_->UnregisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyDeviceNotRegistered(test_devices_[0]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
 
   // Device 2 fails to connect, so the timeout fires. Device 1 takes its spot.
@@ -1077,9 +1144,11 @@
   VerifyAdvertisingTimeoutSet(test_devices_[1]);
   VerifyNoTimeoutSet(test_devices_[2]);
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[2], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[2].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Device 3 connects successfully.
@@ -1088,36 +1157,41 @@
 
   // Since device 3 has connected, device 2 starts connecting again.
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[2], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[2].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING}});
 
   // Now, device 3 authenticates and sends and receives a message.
   AuthenticateChannel(test_devices_[3]);
-  sequence_number = manager_->SendMessage(test_devices_[3], "request3");
+  sequence_number =
+      manager_->SendMessage(test_devices_[3].GetDeviceId(), "request3");
   VerifyLastMessageSent(channel3, sequence_number, "request3", 1);
 
   channel3->ReceiveMessage(kTetherFeature, "response3");
-  VerifyReceivedMessages(
-      std::vector<ReceivedMessage>{{test_devices_[3], "response3"}});
+  VerifyReceivedMessages(std::vector<ReceivedMessage>{
+      {test_devices_[3].GetDeviceId(), "response3"}});
 
   // Assume that none of the other devices can connect, and unregister the
   // remaining 3 devices.
-  manager_->UnregisterRemoteDevice(test_devices_[3],
+  manager_->UnregisterRemoteDevice(test_devices_[3].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyDeviceNotRegistered(test_devices_[3]);
-  manager_->UnregisterRemoteDevice(test_devices_[1],
+  manager_->UnregisterRemoteDevice(test_devices_[1].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyDeviceNotRegistered(test_devices_[1]);
-  manager_->UnregisterRemoteDevice(test_devices_[2],
+  manager_->UnregisterRemoteDevice(test_devices_[2].GetDeviceId(),
                                    MessageType::TETHER_AVAILABILITY_REQUEST);
   VerifyDeviceNotRegistered(test_devices_[2]);
 
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[3], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[3].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[1].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED},
-      {test_devices_[2], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[2].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
 }
 
@@ -1150,12 +1224,12 @@
   // callbacks. This would have caused a crash before the fix for
   // crbug.com/733360.
   channel->ReceiveMessage(kTetherFeature, "response1");
-  VerifyReceivedMessages(
-      std::vector<ReceivedMessage>{{test_devices_[0], "response1"}});
-
+  VerifyReceivedMessages(std::vector<ReceivedMessage>{
+      {test_devices_[0].GetDeviceId(), "response1"}});
   // We expect the device to be unregistered (by the observer).
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::AUTHENTICATED,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
   VerifyDeviceNotRegistered(test_devices_[0]);
 
@@ -1163,14 +1237,16 @@
   // connecting" status change. This time, the multiple observers will respond
   // to a status change event instead of a message received event. This also
   // would have caused a crash before the fix for crbug.com/733360.
-  manager_->RegisterRemoteDevice(test_devices_[0],
+  manager_->RegisterRemoteDevice(test_devices_[0].GetDeviceId(),
                                  MessageType::TETHER_AVAILABILITY_REQUEST);
 
   // We expect the device to be unregistered (by the observer).
   VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
-      {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::DISCONNECTED,
        cryptauth::SecureChannel::Status::CONNECTING},
-      {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING,
+      {test_devices_[0].GetDeviceId(),
+       cryptauth::SecureChannel::Status::CONNECTING,
        cryptauth::SecureChannel::Status::DISCONNECTED}});
   VerifyDeviceNotRegistered(test_devices_[0]);
 }
diff --git a/chromeos/components/tether/ble_scanner.h b/chromeos/components/tether/ble_scanner.h
index e64259e..bdcf0b1 100644
--- a/chromeos/components/tether/ble_scanner.h
+++ b/chromeos/components/tether/ble_scanner.h
@@ -35,13 +35,11 @@
   // Registers a scan filter for the given device. The scan filter will remain
   // active until a subsequent call to UnregisterScanFilterForDevice() is made.
   // Returns whether the scan filter was successfully registered.
-  virtual bool RegisterScanFilterForDevice(
-      const cryptauth::RemoteDevice& remote_device) = 0;
+  virtual bool RegisterScanFilterForDevice(const std::string& device_id) = 0;
 
   // Unregisters a scan filter for |device|. Returns whether the scan filter was
   // successfully unregistered.
-  virtual bool UnregisterScanFilterForDevice(
-      const cryptauth::RemoteDevice& remote_device) = 0;
+  virtual bool UnregisterScanFilterForDevice(const std::string& device_id) = 0;
 
   // A discovery session should be active if at least one device has been
   // registered. However, discovery sessions are started and stopped
diff --git a/chromeos/components/tether/ble_scanner_impl.cc b/chromeos/components/tether/ble_scanner_impl.cc
index 10b3164..430eba4 100644
--- a/chromeos/components/tether/ble_scanner_impl.cc
+++ b/chromeos/components/tether/ble_scanner_impl.cc
@@ -10,6 +10,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/components/tether/ble_constants.h"
 #include "chromeos/components/tether/ble_synchronizer.h"
+#include "chromeos/components/tether/tether_host_fetcher.h"
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
 #include "components/cryptauth/remote_device.h"
 #include "components/proximity_auth/logging/logging.h"
@@ -37,12 +38,14 @@
 std::unique_ptr<BleScanner> BleScannerImpl::Factory::NewInstance(
     scoped_refptr<device::BluetoothAdapter> adapter,
     cryptauth::LocalDeviceDataProvider* local_device_data_provider,
-    BleSynchronizerBase* ble_synchronizer) {
+    BleSynchronizerBase* ble_synchronizer,
+    TetherHostFetcher* tether_host_fetcher) {
   if (!factory_instance_)
     factory_instance_ = new Factory();
 
   return factory_instance_->BuildInstance(adapter, local_device_data_provider,
-                                          ble_synchronizer);
+                                          ble_synchronizer,
+                                          tether_host_fetcher);
 }
 
 // static
@@ -53,9 +56,11 @@
 std::unique_ptr<BleScanner> BleScannerImpl::Factory::BuildInstance(
     scoped_refptr<device::BluetoothAdapter> adapter,
     cryptauth::LocalDeviceDataProvider* local_device_data_provider,
-    BleSynchronizerBase* ble_synchronizer) {
+    BleSynchronizerBase* ble_synchronizer,
+    TetherHostFetcher* tether_host_fetcher) {
   return base::MakeUnique<BleScannerImpl>(adapter, local_device_data_provider,
-                                          ble_synchronizer);
+                                          ble_synchronizer,
+                                          tether_host_fetcher);
 }
 
 BleScannerImpl::ServiceDataProviderImpl::ServiceDataProviderImpl() = default;
@@ -72,10 +77,12 @@
 BleScannerImpl::BleScannerImpl(
     scoped_refptr<device::BluetoothAdapter> adapter,
     cryptauth::LocalDeviceDataProvider* local_device_data_provider,
-    BleSynchronizerBase* ble_synchronizer)
+    BleSynchronizerBase* ble_synchronizer,
+    TetherHostFetcher* tether_host_fetcher)
     : adapter_(adapter),
       local_device_data_provider_(local_device_data_provider),
       ble_synchronizer_(ble_synchronizer),
+      tether_host_fetcher_(tether_host_fetcher),
       service_data_provider_(base::MakeUnique<ServiceDataProviderImpl>()),
       eid_generator_(base::MakeUnique<cryptauth::ForegroundEidGenerator>()),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
@@ -87,9 +94,8 @@
   adapter_->RemoveObserver(this);
 }
 
-bool BleScannerImpl::RegisterScanFilterForDevice(
-    const cryptauth::RemoteDevice& remote_device) {
-  if (registered_remote_devices_.size() >= kMaxConcurrentAdvertisements) {
+bool BleScannerImpl::RegisterScanFilterForDevice(const std::string& device_id) {
+  if (registered_remote_device_ids_.size() >= kMaxConcurrentAdvertisements) {
     // Each scan filter corresponds to an advertisement. Thus, the number of
     // concurrent advertisements cannot exceed the maximum number of concurrent
     // advertisements.
@@ -114,18 +120,18 @@
     return false;
   }
 
-  registered_remote_devices_.push_back(remote_device);
+  registered_remote_device_ids_.push_back(device_id);
   UpdateDiscoveryStatus();
 
   return true;
 }
 
 bool BleScannerImpl::UnregisterScanFilterForDevice(
-    const cryptauth::RemoteDevice& remote_device) {
-  for (auto it = registered_remote_devices_.begin();
-       it != registered_remote_devices_.end(); ++it) {
-    if (it->GetDeviceId() == remote_device.GetDeviceId()) {
-      registered_remote_devices_.erase(it);
+    const std::string& device_id) {
+  for (auto it = registered_remote_device_ids_.begin();
+       it != registered_remote_device_ids_.end(); ++it) {
+    if (*it == device_id) {
+      registered_remote_device_ids_.erase(it);
       UpdateDiscoveryStatus();
       return true;
     }
@@ -135,7 +141,7 @@
 }
 
 bool BleScannerImpl::ShouldDiscoverySessionBeActive() {
-  return !registered_remote_devices_.empty();
+  return !registered_remote_device_ids_.empty();
 }
 
 bool BleScannerImpl::IsDiscoverySessionActive() {
@@ -160,14 +166,9 @@
 }
 
 bool BleScannerImpl::IsDeviceRegistered(const std::string& device_id) {
-  for (auto it = registered_remote_devices_.begin();
-       it != registered_remote_devices_.end(); ++it) {
-    if (it->GetDeviceId() == device_id) {
-      return true;
-    }
-  }
-
-  return false;
+  return std::find(registered_remote_device_ids_.begin(),
+                   registered_remote_device_ids_.end(),
+                   device_id) != registered_remote_device_ids_.end();
 }
 
 void BleScannerImpl::DeviceAdded(device::BluetoothAdapter* adapter,
@@ -302,7 +303,7 @@
 
 void BleScannerImpl::CheckForMatchingScanFilters(
     device::BluetoothDevice* bluetooth_device,
-    std::string& service_data) {
+    const std::string& service_data) {
   std::vector<cryptauth::BeaconSeed> beacon_seeds;
   if (!local_device_data_provider_->GetLocalDeviceData(nullptr,
                                                        &beacon_seeds)) {
@@ -310,20 +311,33 @@
     return;
   }
 
-  const cryptauth::RemoteDevice* identified_device =
+  const std::string device_id =
       eid_generator_->IdentifyRemoteDeviceByAdvertisement(
-          service_data, registered_remote_devices_, beacon_seeds);
+          service_data, registered_remote_device_ids_, beacon_seeds);
 
   // If the service data does not correspond to an advertisement from a device
   // on this account, ignore it.
-  if (!identified_device)
+  if (device_id.empty())
     return;
 
-  // Make a copy before notifying observers. Since |identified_device| refers
-  // to an instance variable, it is possible that an observer could unregister
-  // that device, which would change the value of that pointer.
-  const cryptauth::RemoteDevice copy = *identified_device;
-  NotifyReceivedAdvertisementFromDevice(copy, bluetooth_device);
+  tether_host_fetcher_->FetchTetherHost(
+      device_id,
+      base::Bind(&BleScannerImpl::OnIdentifiedHostFetched,
+                 weak_ptr_factory_.GetWeakPtr(), bluetooth_device, device_id));
+}
+
+void BleScannerImpl::OnIdentifiedHostFetched(
+    device::BluetoothDevice* bluetooth_device,
+    const std::string& device_id,
+    std::unique_ptr<cryptauth::RemoteDevice> identified_device) {
+  if (!identified_device) {
+    PA_LOG(ERROR) << "Unable to fetch RemoteDevice object with ID \""
+                  << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
+                  << "\".";
+    return;
+  }
+
+  NotifyReceivedAdvertisementFromDevice(*identified_device, bluetooth_device);
 }
 
 void BleScannerImpl::ScheduleStatusChangeNotification(
diff --git a/chromeos/components/tether/ble_scanner_impl.h b/chromeos/components/tether/ble_scanner_impl.h
index b0dd0e7..794e1057 100644
--- a/chromeos/components/tether/ble_scanner_impl.h
+++ b/chromeos/components/tether/ble_scanner_impl.h
@@ -30,6 +30,7 @@
 namespace tether {
 
 class BleSynchronizerBase;
+class TetherHostFetcher;
 
 // Concrete BleScanner implementation.
 class BleScannerImpl : public BleScanner,
@@ -40,7 +41,8 @@
     static std::unique_ptr<BleScanner> NewInstance(
         scoped_refptr<device::BluetoothAdapter> adapter,
         cryptauth::LocalDeviceDataProvider* local_device_data_provider,
-        BleSynchronizerBase* ble_synchronizer);
+        BleSynchronizerBase* ble_synchronizer,
+        TetherHostFetcher* tether_host_fetcher);
 
     static void SetInstanceForTesting(Factory* factory);
 
@@ -48,7 +50,8 @@
     virtual std::unique_ptr<BleScanner> BuildInstance(
         scoped_refptr<device::BluetoothAdapter> adapter,
         cryptauth::LocalDeviceDataProvider* local_device_data_provider,
-        BleSynchronizerBase* ble_synchronizer);
+        BleSynchronizerBase* ble_synchronizer,
+        TetherHostFetcher* tether_host_fetcher);
 
    private:
     static Factory* factory_instance_;
@@ -56,14 +59,13 @@
 
   BleScannerImpl(scoped_refptr<device::BluetoothAdapter> adapter,
                  cryptauth::LocalDeviceDataProvider* local_device_data_provider,
-                 BleSynchronizerBase* ble_synchronizer);
+                 BleSynchronizerBase* ble_synchronizer,
+                 TetherHostFetcher* tether_host_fetcher);
   ~BleScannerImpl() override;
 
   // BleScanner:
-  bool RegisterScanFilterForDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
-  bool UnregisterScanFilterForDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
+  bool RegisterScanFilterForDevice(const std::string& device_id) override;
+  bool UnregisterScanFilterForDevice(const std::string& device_id) override;
   bool ShouldDiscoverySessionBeActive() override;
   bool IsDiscoverySessionActive() override;
 
@@ -118,18 +120,23 @@
 
   void HandleDeviceUpdated(device::BluetoothDevice* bluetooth_device);
   void CheckForMatchingScanFilters(device::BluetoothDevice* bluetooth_device,
-                                   std::string& service_data);
+                                   const std::string& service_data);
+  void OnIdentifiedHostFetched(
+      device::BluetoothDevice* bluetooth_device,
+      const std::string& device_id,
+      std::unique_ptr<cryptauth::RemoteDevice> identified_device);
 
   void ScheduleStatusChangeNotification(bool discovery_session_active);
 
   scoped_refptr<device::BluetoothAdapter> adapter_;
   cryptauth::LocalDeviceDataProvider* local_device_data_provider_;
   BleSynchronizerBase* ble_synchronizer_;
+  TetherHostFetcher* tether_host_fetcher_;
 
   std::unique_ptr<ServiceDataProvider> service_data_provider_;
   std::unique_ptr<cryptauth::ForegroundEidGenerator> eid_generator_;
 
-  std::vector<cryptauth::RemoteDevice> registered_remote_devices_;
+  std::vector<std::string> registered_remote_device_ids_;
 
   bool is_initializing_discovery_session_ = false;
   bool is_stopping_discovery_session_ = false;
diff --git a/chromeos/components/tether/ble_scanner_impl_unittest.cc b/chromeos/components/tether/ble_scanner_impl_unittest.cc
index 8b863cf..b0181ee 100644
--- a/chromeos/components/tether/ble_scanner_impl_unittest.cc
+++ b/chromeos/components/tether/ble_scanner_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/test/test_simple_task_runner.h"
 #include "chromeos/components/tether/ble_constants.h"
 #include "chromeos/components/tether/fake_ble_synchronizer.h"
+#include "chromeos/components/tether/fake_tether_host_fetcher.h"
 #include "components/cryptauth/mock_foreground_eid_generator.h"
 #include "components/cryptauth/mock_local_device_data_provider.h"
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
@@ -34,12 +35,12 @@
  public:
   TestBleScannerObserver() = default;
 
-  std::vector<std::string>& device_addresses() { return device_addresses_; }
-
-  std::vector<cryptauth::RemoteDevice>& remote_devices() {
-    return remote_devices_;
+  const std::vector<std::string>& device_addresses() {
+    return device_addresses_;
   }
 
+  const std::vector<cryptauth::RemoteDevice>& devices() { return devices_; }
+
   std::vector<bool>& discovery_session_state_changes() {
     return discovery_session_state_changes_;
   }
@@ -49,7 +50,7 @@
       const cryptauth::RemoteDevice& remote_device,
       device::BluetoothDevice* bluetooth_device) override {
     device_addresses_.push_back(bluetooth_device->GetAddress());
-    remote_devices_.push_back(remote_device);
+    devices_.push_back(remote_device);
   }
 
   void OnDiscoverySessionStateChanged(bool discovery_session_active) override {
@@ -58,7 +59,7 @@
 
  private:
   std::vector<std::string> device_addresses_;
-  std::vector<cryptauth::RemoteDevice> remote_devices_;
+  std::vector<cryptauth::RemoteDevice> devices_;
   std::vector<bool> discovery_session_state_changes_;
 };
 
@@ -197,6 +198,8 @@
             test_beacon_seeds_));
 
     fake_ble_synchronizer_ = base::MakeUnique<FakeBleSynchronizer>();
+    fake_tether_host_fetcher_ =
+        base::MakeUnique<FakeTetherHostFetcher>(test_devices_);
 
     mock_adapter_ =
         base::MakeRefCounted<NiceMock<device::MockBluetoothAdapter>>();
@@ -206,7 +209,7 @@
 
     ble_scanner_ = base::MakeUnique<BleScannerImpl>(
         mock_adapter_, mock_local_device_data_provider_.get(),
-        fake_ble_synchronizer_.get());
+        fake_ble_synchronizer_.get(), fake_tether_host_fetcher_.get());
 
     mock_eid_generator_ = new cryptauth::MockForegroundEidGenerator();
     mock_eid_generator_->set_background_scan_filter(
@@ -277,6 +280,7 @@
   std::unique_ptr<cryptauth::MockLocalDeviceDataProvider>
       mock_local_device_data_provider_;
   std::unique_ptr<FakeBleSynchronizer> fake_ble_synchronizer_;
+  std::unique_ptr<FakeTetherHostFetcher> fake_tether_host_fetcher_;
 
   scoped_refptr<NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
   device::MockBluetoothDiscoverySession* mock_discovery_session_;
@@ -299,31 +303,36 @@
 
 TEST_F(BleScannerImplTest, TestNoLocalBeaconSeeds) {
   mock_local_device_data_provider_->SetBeaconSeeds(nullptr);
-  EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_FALSE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
   EXPECT_EQ(0u, test_observer_->device_addresses().size());
 }
 
 TEST_F(BleScannerImplTest, TestNoBackgroundScanFilter) {
   mock_eid_generator_->set_background_scan_filter(nullptr);
-  EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_FALSE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
   EXPECT_EQ(0u, test_observer_->device_addresses().size());
 }
 
 TEST_F(BleScannerImplTest, TestDiscoverySessionFailsToStart) {
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
 
   InvokeDiscoveryStartedCallback(false /* success */, 0u /* command_index */);
 
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_EQ(0u, test_observer_->device_addresses().size());
 }
 
 TEST_F(BleScannerImplTest, TestDiscoveryStartsButNoDevicesFound) {
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
 
   InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
@@ -331,7 +340,8 @@
   // No devices found.
 
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_EQ(0u, test_observer_->device_addresses().size());
 
   InvokeStopDiscoveryCallback(true /* success */, 1u /* command_index */);
@@ -340,7 +350,8 @@
 TEST_F(BleScannerImplTest, TestDiscovery_NoServiceData) {
   std::string empty_service_data = "";
 
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
 
   InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
@@ -358,7 +369,8 @@
   std::string short_service_data = "abc";
   ASSERT_TRUE(short_service_data.size() < kMinNumBytesInServiceData);
 
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
 
   InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
@@ -377,7 +389,8 @@
   ASSERT_TRUE(valid_service_data_for_other_device.size() >=
               kMinNumBytesInServiceData);
 
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
 
   InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
@@ -399,7 +412,8 @@
   ASSERT_TRUE(valid_service_data_for_other_device.size() >=
               kMinNumBytesInServiceData);
 
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
 
   InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
@@ -423,7 +437,8 @@
   ASSERT_TRUE(valid_service_data_for_registered_device.size() >=
               kMinNumBytesInServiceData);
 
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
 
   InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
@@ -432,16 +447,17 @@
   MockBluetoothDeviceWithServiceData device(
       mock_adapter_.get(), kDefaultBluetoothAddress,
       valid_service_data_for_registered_device);
-  mock_eid_generator_->set_identified_device(&test_devices_[0]);
+  mock_eid_generator_->set_identified_device_id(test_devices_[0].GetDeviceId());
   DeviceAdded(&device);
   EXPECT_EQ(1, mock_eid_generator_->num_identify_calls());
   EXPECT_EQ(1u, test_observer_->device_addresses().size());
   EXPECT_EQ(device.GetAddress(), test_observer_->device_addresses()[0]);
-  EXPECT_EQ(1u, test_observer_->remote_devices().size());
-  EXPECT_EQ(test_devices_[0], test_observer_->remote_devices()[0]);
+  EXPECT_EQ(1u, test_observer_->devices().size());
+  EXPECT_EQ(test_devices_[0], test_observer_->devices()[0]);
 
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_EQ(1, mock_eid_generator_->num_identify_calls());
   EXPECT_EQ(1u, test_observer_->device_addresses().size());
   InvokeStopDiscoveryCallback(true /* success */, 1u /* command_index */);
@@ -451,27 +467,28 @@
   TestBleScannerObserver extra_observer;
   ble_scanner_->AddObserver(&extra_observer);
 
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
 
   InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
 
   MockBluetoothDeviceWithServiceData mock_bluetooth_device(
       mock_adapter_.get(), kDefaultBluetoothAddress, "fakeServiceData");
-  mock_eid_generator_->set_identified_device(&test_devices_[0]);
+  mock_eid_generator_->set_identified_device_id(test_devices_[0].GetDeviceId());
   DeviceAdded(&mock_bluetooth_device);
 
   EXPECT_EQ(1u, test_observer_->device_addresses().size());
   EXPECT_EQ(mock_bluetooth_device.GetAddress(),
             test_observer_->device_addresses()[0]);
-  EXPECT_EQ(1u, test_observer_->remote_devices().size());
-  EXPECT_EQ(test_devices_[0], test_observer_->remote_devices()[0]);
+  EXPECT_EQ(1u, test_observer_->devices().size());
+  EXPECT_EQ(test_devices_[0], test_observer_->devices()[0]);
 
   EXPECT_EQ(1u, extra_observer.device_addresses().size());
   EXPECT_EQ(mock_bluetooth_device.GetAddress(),
             extra_observer.device_addresses()[0]);
-  EXPECT_EQ(1u, extra_observer.remote_devices().size());
-  EXPECT_EQ(test_devices_[0], extra_observer.remote_devices()[0]);
+  EXPECT_EQ(1u, extra_observer.devices().size());
+  EXPECT_EQ(test_devices_[0], extra_observer.devices()[0]);
 
   // Now, unregister both observers.
   ble_scanner_->RemoveObserver(test_observer_.get());
@@ -485,7 +502,8 @@
   EXPECT_EQ(1u, extra_observer.device_addresses().size());
 
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
 
   // Note: Cannot use InvokeStopDiscoveryCallback() since that function
   // internally verifies observer callbacks, but the observers have been
@@ -495,49 +513,59 @@
 }
 
 TEST_F(BleScannerImplTest, TestRegistrationLimit) {
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[1]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[1].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[1].GetDeviceId()));
 
   // Attempt to register another device. Registration should fail since the
   // maximum number of devices have already been registered.
   ASSERT_EQ(2u, kMaxConcurrentAdvertisements);
-  EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[2]));
+  EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[2].GetDeviceId()));
   EXPECT_FALSE(IsDeviceRegistered(test_devices_[2].GetDeviceId()));
 
   // Unregistering a device which is not registered should also return false.
-  EXPECT_FALSE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[2]));
+  EXPECT_FALSE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[2].GetDeviceId()));
   EXPECT_FALSE(IsDeviceRegistered(test_devices_[2].GetDeviceId()));
 
   // Unregister device 0.
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_FALSE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
 
   // Now, device 2 can be registered.
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[2]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[2].GetDeviceId()));
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[2].GetDeviceId()));
 
   // Now, unregister the devices.
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[1].GetDeviceId()));
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[1]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[1].GetDeviceId()));
   EXPECT_FALSE(IsDeviceRegistered(test_devices_[1].GetDeviceId()));
 
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[2].GetDeviceId()));
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[2]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[2].GetDeviceId()));
   EXPECT_FALSE(IsDeviceRegistered(test_devices_[2].GetDeviceId()));
 }
 
 TEST_F(BleScannerImplTest, TestStartAndStopCallbacks_Success) {
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(ble_scanner_->ShouldDiscoverySessionBeActive());
 
   EXPECT_FALSE(ble_scanner_->IsDiscoverySessionActive());
   InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
 
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[1]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[1].GetDeviceId()));
 
   // Registering device 1 should not have triggered a new discovery session from
   // being created since one already existed.
@@ -545,7 +573,8 @@
   EXPECT_TRUE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
 
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
 
   // Unregistering device 0 should not have triggered a stopped session since
   // a device is still registered.
@@ -555,7 +584,8 @@
 
   // Device 1 is the only device remaining, so unregistering it should trigger
   // the session to stop.
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[1]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[1].GetDeviceId()));
   EXPECT_FALSE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
 
@@ -564,7 +594,8 @@
 }
 
 TEST_F(BleScannerImplTest, TestStartAndStopCallbacks_Errors) {
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_FALSE(ble_scanner_->IsDiscoverySessionActive());
 
@@ -582,7 +613,8 @@
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
 
   // Now, unregister it, but fail to stop the discovery session.
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_FALSE(ble_scanner_->ShouldDiscoverySessionBeActive());
   InvokeStopDiscoveryCallback(false /* success */, 3u /* command_index */);
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
@@ -598,12 +630,14 @@
 }
 
 TEST_F(BleScannerImplTest, TestStartAndStopCallbacks_UnregisterBeforeStarted) {
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_FALSE(ble_scanner_->IsDiscoverySessionActive());
 
   // Before invoking the discovery callback, unregister the device.
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_FALSE(ble_scanner_->ShouldDiscoverySessionBeActive());
 
   // Complete the start discovery successfully.
@@ -618,12 +652,14 @@
 
 TEST_F(BleScannerImplTest,
        TestStartAndStopCallbacks_UnregisterBeforeStartFails) {
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_FALSE(ble_scanner_->IsDiscoverySessionActive());
 
   // Before invoking the discovery callback, unregister the device.
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_FALSE(ble_scanner_->ShouldDiscoverySessionBeActive());
 
   // Fail to start discovery session.
@@ -636,7 +672,8 @@
 }
 
 TEST_F(BleScannerImplTest, TestStartAndStopCallbacks_RegisterBeforeStopFails) {
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_FALSE(ble_scanner_->IsDiscoverySessionActive());
 
@@ -645,12 +682,14 @@
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
 
   // Unregister device to attempt a stop.
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_FALSE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
 
   // Before the stop completes, register the device again.
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
 
@@ -666,7 +705,8 @@
 // Regression test for crbug.com/768521.
 TEST_F(BleScannerImplTest,
        TestStopCallback_DiscoverySessionInactiveButNotStopped) {
-  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_FALSE(ble_scanner_->IsDiscoverySessionActive());
 
@@ -676,7 +716,8 @@
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
 
   // Unregister device to attempt a stop.
-  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
   EXPECT_FALSE(ble_scanner_->ShouldDiscoverySessionBeActive());
   EXPECT_TRUE(ble_scanner_->IsDiscoverySessionActive());
 
@@ -705,10 +746,10 @@
 TEST_F(BleScannerImplTest, ObserverDeletesObjectWhenNotified) {
   DeletingObserver deleting_observer(ble_scanner_);
 
-  ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]);
+  ble_scanner_->RegisterScanFilterForDevice(test_devices_[0].GetDeviceId());
   InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
   test_task_runner_->RunUntilIdle();
-  ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]);
+  ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0].GetDeviceId());
   InvokeStopDiscoveryCallback(true /* success */, 1u /* command_index */);
   test_task_runner_->RunUntilIdle();
 }
diff --git a/chromeos/components/tether/connect_tethering_operation_unittest.cc b/chromeos/components/tether/connect_tethering_operation_unittest.cc
index 6ca3189..6326b09 100644
--- a/chromeos/components/tether/connect_tethering_operation_unittest.cc
+++ b/chromeos/components/tether/connect_tethering_operation_unittest.cc
@@ -144,7 +144,7 @@
     std::vector<FakeBleConnectionManager::SentMessage>& sent_messages =
         fake_ble_connection_manager_->sent_messages();
     ASSERT_EQ(1u, sent_messages.size());
-    EXPECT_EQ(test_device_, sent_messages[0].remote_device);
+    EXPECT_EQ(test_device_.GetDeviceId(), sent_messages[0].device_id);
     EXPECT_EQ(connect_tethering_request_string_, sent_messages[0].message);
 
     // Simulate BleConnectionManager notifying ConnectTetheringOperation that
@@ -162,8 +162,9 @@
     test_clock_->Advance(kConnectTetheringResponseTime);
 
     fake_ble_connection_manager_->ReceiveMessage(
-        test_device_, CreateConnectTetheringResponseString(
-                          response_code, use_proto_without_ssid_and_password));
+        test_device_.GetDeviceId(),
+        CreateConnectTetheringResponseString(
+            response_code, use_proto_without_ssid_and_password));
 
     bool is_success_response =
         response_code == ConnectTetheringResponse_ResponseCode::
@@ -275,17 +276,20 @@
 
   // Simulate the device failing to connect.
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::CONNECTING);
+      test_device_.GetDeviceId(), cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_device_.GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::CONNECTING);
+      test_device_.GetDeviceId(), cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_device_.GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::CONNECTING);
+      test_device_.GetDeviceId(), cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_device_.GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
 
   // The maximum number of connection failures has occurred.
   EXPECT_TRUE(test_observer_->has_received_failure());
diff --git a/chromeos/components/tether/disconnect_tethering_operation_unittest.cc b/chromeos/components/tether/disconnect_tethering_operation_unittest.cc
index d4874de..6853878 100644
--- a/chromeos/components/tether/disconnect_tethering_operation_unittest.cc
+++ b/chromeos/components/tether/disconnect_tethering_operation_unittest.cc
@@ -86,7 +86,7 @@
     std::vector<FakeBleConnectionManager::SentMessage>& sent_messages =
         fake_ble_connection_manager_->sent_messages();
     ASSERT_EQ(1u, sent_messages.size());
-    EXPECT_EQ(test_device_, sent_messages[0].remote_device);
+    EXPECT_EQ(test_device_.GetDeviceId(), sent_messages[0].device_id);
     EXPECT_EQ(disconnect_tethering_request_string_, sent_messages[0].message);
 
     test_clock_->Advance(kDisconnectTetheringRequestTime);
diff --git a/chromeos/components/tether/fake_ad_hoc_ble_advertiser.cc b/chromeos/components/tether/fake_ad_hoc_ble_advertiser.cc
index 432883a..a37b3c454 100644
--- a/chromeos/components/tether/fake_ad_hoc_ble_advertiser.cc
+++ b/chromeos/components/tether/fake_ad_hoc_ble_advertiser.cc
@@ -17,8 +17,8 @@
 }
 
 void FakeAdHocBleAdvertiser::RequestGattServicesForDevice(
-    const cryptauth::RemoteDevice& remote_device) {
-  requested_device_ids_.push_back(remote_device.GetDeviceId());
+    const std::string& device_id) {
+  requested_device_ids_.push_back(device_id);
 }
 
 bool FakeAdHocBleAdvertiser::HasPendingRequests() {
diff --git a/chromeos/components/tether/fake_ad_hoc_ble_advertiser.h b/chromeos/components/tether/fake_ad_hoc_ble_advertiser.h
index d79a8da..a6a2ad6 100644
--- a/chromeos/components/tether/fake_ad_hoc_ble_advertiser.h
+++ b/chromeos/components/tether/fake_ad_hoc_ble_advertiser.h
@@ -32,8 +32,7 @@
   void NotifyAsynchronousShutdownComplete();
 
   // AdHocBleAdvertiser:
-  void RequestGattServicesForDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
+  void RequestGattServicesForDevice(const std::string& device_id) override;
   bool HasPendingRequests() override;
 
  private:
diff --git a/chromeos/components/tether/fake_ble_advertiser.cc b/chromeos/components/tether/fake_ble_advertiser.cc
index df714b2..939c4bf 100644
--- a/chromeos/components/tether/fake_ble_advertiser.cc
+++ b/chromeos/components/tether/fake_ble_advertiser.cc
@@ -23,17 +23,16 @@
   BleAdvertiser::NotifyAllAdvertisementsUnregistered();
 }
 
-bool FakeBleAdvertiser::StartAdvertisingToDevice(
-    const cryptauth::RemoteDevice& remote_device) {
+bool FakeBleAdvertiser::StartAdvertisingToDevice(const std::string& device_id) {
   if (should_fail_to_start_advertising_)
     return false;
 
-  if (std::find(registered_devices_.begin(), registered_devices_.end(),
-                remote_device) != registered_devices_.end()) {
+  if (std::find(registered_device_ids_.begin(), registered_device_ids_.end(),
+                device_id) != registered_device_ids_.end()) {
     return false;
   }
 
-  registered_devices_.push_back(remote_device);
+  registered_device_ids_.push_back(device_id);
 
   if (automatically_update_active_advertisements_)
     are_advertisements_registered_ = true;
@@ -41,16 +40,15 @@
   return true;
 }
 
-bool FakeBleAdvertiser::StopAdvertisingToDevice(
-    const cryptauth::RemoteDevice& remote_device) {
-  if (std::find(registered_devices_.begin(), registered_devices_.end(),
-                remote_device) == registered_devices_.end()) {
+bool FakeBleAdvertiser::StopAdvertisingToDevice(const std::string& device_id) {
+  if (std::find(registered_device_ids_.begin(), registered_device_ids_.end(),
+                device_id) == registered_device_ids_.end()) {
     return false;
   }
 
-  base::Erase(registered_devices_, remote_device);
+  base::Erase(registered_device_ids_, device_id);
   if (automatically_update_active_advertisements_ &&
-      registered_devices_.empty()) {
+      registered_device_ids_.empty()) {
     are_advertisements_registered_ = false;
     NotifyAllAdvertisementsUnregistered();
   }
diff --git a/chromeos/components/tether/fake_ble_advertiser.h b/chromeos/components/tether/fake_ble_advertiser.h
index ac3cac3..cc410cd 100644
--- a/chromeos/components/tether/fake_ble_advertiser.h
+++ b/chromeos/components/tether/fake_ble_advertiser.h
@@ -25,8 +25,8 @@
   FakeBleAdvertiser(bool automatically_update_active_advertisements);
   ~FakeBleAdvertiser() override;
 
-  const std::vector<cryptauth::RemoteDevice>& registered_devices() {
-    return registered_devices_;
+  const std::vector<std::string>& registered_device_ids() {
+    return registered_device_ids_;
   }
 
   void set_should_fail_to_start_advertising(
@@ -41,10 +41,8 @@
   void NotifyAllAdvertisementsUnregistered();
 
   // BleAdvertiser:
-  bool StartAdvertisingToDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
-  bool StopAdvertisingToDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
+  bool StartAdvertisingToDevice(const std::string& device_id) override;
+  bool StopAdvertisingToDevice(const std::string& device_id) override;
   bool AreAdvertisementsRegistered() override;
 
  private:
@@ -52,7 +50,7 @@
 
   bool should_fail_to_start_advertising_ = false;
   bool are_advertisements_registered_ = false;
-  std::vector<cryptauth::RemoteDevice> registered_devices_;
+  std::vector<std::string> registered_device_ids_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeBleAdvertiser);
 };
diff --git a/chromeos/components/tether/fake_ble_connection_manager.cc b/chromeos/components/tether/fake_ble_connection_manager.cc
index fd159d2..e3e7a75 100644
--- a/chromeos/components/tether/fake_ble_connection_manager.cc
+++ b/chromeos/components/tether/fake_ble_connection_manager.cc
@@ -33,10 +33,10 @@
 FakeBleConnectionManager::~FakeBleConnectionManager() = default;
 
 void FakeBleConnectionManager::SetDeviceStatus(
-    const cryptauth::RemoteDevice& remote_device,
+    const std::string& device_id,
     const cryptauth::SecureChannel::Status& status) {
-  const auto iter = device_map_.find(remote_device);
-  DCHECK(iter != device_map_.end());
+  const auto iter = device_id_map_.find(device_id);
+  DCHECK(iter != device_id_map_.end());
 
   cryptauth::SecureChannel::Status old_status = iter->second.status;
   if (old_status == status) {
@@ -45,14 +45,13 @@
   }
 
   iter->second.status = status;
-  SendSecureChannelStatusChangeEvent(remote_device, old_status, status);
+  SendSecureChannelStatusChangeEvent(device_id, old_status, status);
 }
 
-void FakeBleConnectionManager::ReceiveMessage(
-    const cryptauth::RemoteDevice& remote_device,
-    const std::string& payload) {
-  DCHECK(device_map_.find(remote_device) != device_map_.end());
-  SendMessageReceivedEvent(remote_device, payload);
+void FakeBleConnectionManager::ReceiveMessage(const std::string& device_id,
+                                              const std::string& payload) {
+  DCHECK(device_id_map_.find(device_id) != device_id_map_.end());
+  SendMessageReceivedEvent(device_id, payload);
 }
 
 void FakeBleConnectionManager::SetMessageSent(int sequence_number) {
@@ -60,42 +59,38 @@
   SendMessageSentEvent(sequence_number);
 }
 
-bool FakeBleConnectionManager::IsRegistered(
-    const cryptauth::RemoteDevice& remote_device) {
-  return base::ContainsKey(device_map_, remote_device);
+bool FakeBleConnectionManager::IsRegistered(const std::string& device_id) {
+  return base::ContainsKey(device_id_map_, device_id);
 }
 
 void FakeBleConnectionManager::RegisterRemoteDevice(
-    const cryptauth::RemoteDevice& remote_device,
+    const std::string& device_id,
     const MessageType& connection_reason) {
-  StatusAndRegisteredMessageTypes& value = device_map_[remote_device];
+  StatusAndRegisteredMessageTypes& value = device_id_map_[device_id];
   value.registered_message_types.insert(connection_reason);
 }
 
 void FakeBleConnectionManager::UnregisterRemoteDevice(
-    const cryptauth::RemoteDevice& remote_device,
+    const std::string& device_id,
     const MessageType& connection_reason) {
-  StatusAndRegisteredMessageTypes& value = device_map_[remote_device];
+  StatusAndRegisteredMessageTypes& value = device_id_map_[device_id];
   value.registered_message_types.erase(connection_reason);
-  if (value.registered_message_types.empty()) {
-    device_map_.erase(remote_device);
-  }
+  if (value.registered_message_types.empty())
+    device_id_map_.erase(device_id);
 }
 
-int FakeBleConnectionManager::SendMessage(
-    const cryptauth::RemoteDevice& remote_device,
-    const std::string& message) {
-  sent_messages_.push_back({remote_device, message});
+int FakeBleConnectionManager::SendMessage(const std::string& device_id,
+                                          const std::string& message) {
+  sent_messages_.push_back({device_id, message});
   return next_sequence_number_++;
 }
 
 bool FakeBleConnectionManager::GetStatusForDevice(
-    const cryptauth::RemoteDevice& remote_device,
+    const std::string& device_id,
     cryptauth::SecureChannel::Status* status) const {
-  const auto iter = device_map_.find(remote_device);
-  if (iter == device_map_.end()) {
+  const auto iter = device_id_map_.find(device_id);
+  if (iter == device_id_map_.end())
     return false;
-  }
 
   *status = iter->second.status;
   return true;
diff --git a/chromeos/components/tether/fake_ble_connection_manager.h b/chromeos/components/tether/fake_ble_connection_manager.h
index a8a1a13..26ce7a3 100644
--- a/chromeos/components/tether/fake_ble_connection_manager.h
+++ b/chromeos/components/tether/fake_ble_connection_manager.h
@@ -10,7 +10,6 @@
 
 #include "base/macros.h"
 #include "chromeos/components/tether/ble_connection_manager.h"
-#include "components/cryptauth/remote_device.h"
 
 namespace chromeos {
 
@@ -23,31 +22,30 @@
   ~FakeBleConnectionManager() override;
 
   struct SentMessage {
-    cryptauth::RemoteDevice remote_device;
+    std::string device_id;
     std::string message;
   };
 
-  void SetDeviceStatus(const cryptauth::RemoteDevice& remote_device,
+  void SetDeviceStatus(const std::string& device_id,
                        const cryptauth::SecureChannel::Status& status);
-  void ReceiveMessage(const cryptauth::RemoteDevice& remote_device,
-                      const std::string& payload);
+  void ReceiveMessage(const std::string& device_id, const std::string& payload);
   void SetMessageSent(int sequence_number);
 
   std::vector<SentMessage>& sent_messages() { return sent_messages_; }
   // Returns -1 if no sequence numbers have been used yet.
   int last_sequence_number() { return next_sequence_number_ - 1; }
 
-  bool IsRegistered(const cryptauth::RemoteDevice& remote_device);
+  bool IsRegistered(const std::string& device_id);
 
   // BleConnectionManager:
-  void RegisterRemoteDevice(const cryptauth::RemoteDevice& remote_device,
+  void RegisterRemoteDevice(const std::string& device_id,
                             const MessageType& connection_reason) override;
-  void UnregisterRemoteDevice(const cryptauth::RemoteDevice& remote_device,
+  void UnregisterRemoteDevice(const std::string& device_id,
                               const MessageType& connection_reason) override;
-  int SendMessage(const cryptauth::RemoteDevice& remote_device,
+  int SendMessage(const std::string& device_id,
                   const std::string& message) override;
   bool GetStatusForDevice(
-      const cryptauth::RemoteDevice& remote_device,
+      const std::string& device_id,
       cryptauth::SecureChannel::Status* status) const override;
 
  private:
@@ -62,8 +60,7 @@
   };
 
   int next_sequence_number_ = 0;
-  std::map<cryptauth::RemoteDevice, StatusAndRegisteredMessageTypes>
-      device_map_;
+  std::map<std::string, StatusAndRegisteredMessageTypes> device_id_map_;
   std::vector<SentMessage> sent_messages_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeBleConnectionManager);
diff --git a/chromeos/components/tether/fake_ble_scanner.cc b/chromeos/components/tether/fake_ble_scanner.cc
index 39d49373..c79b273 100644
--- a/chromeos/components/tether/fake_ble_scanner.cc
+++ b/chromeos/components/tether/fake_ble_scanner.cc
@@ -30,18 +30,17 @@
   BleScanner::NotifyDiscoverySessionStateChanged(discovery_session_active);
 }
 
-bool FakeBleScanner::RegisterScanFilterForDevice(
-    const cryptauth::RemoteDevice& remote_device) {
+bool FakeBleScanner::RegisterScanFilterForDevice(const std::string& device_id) {
   if (should_fail_to_register_)
     return false;
 
-  if (std::find(registered_devices_.begin(), registered_devices_.end(),
-                remote_device) != registered_devices_.end()) {
+  if (std::find(registered_device_ids_.begin(), registered_device_ids_.end(),
+                device_id) != registered_device_ids_.end()) {
     return false;
   }
 
-  bool was_empty = registered_devices_.empty();
-  registered_devices_.push_back(remote_device);
+  bool was_empty = registered_device_ids_.empty();
+  registered_device_ids_.push_back(device_id);
 
   if (was_empty && automatically_update_discovery_session_) {
     is_discovery_session_active_ = true;
@@ -52,15 +51,16 @@
 }
 
 bool FakeBleScanner::UnregisterScanFilterForDevice(
-    const cryptauth::RemoteDevice& remote_device) {
-  if (std::find(registered_devices_.begin(), registered_devices_.end(),
-                remote_device) == registered_devices_.end()) {
+    const std::string& device_id) {
+  if (std::find(registered_device_ids_.begin(), registered_device_ids_.end(),
+                device_id) == registered_device_ids_.end()) {
     return false;
   }
 
-  base::Erase(registered_devices_, remote_device);
+  base::Erase(registered_device_ids_, device_id);
 
-  if (automatically_update_discovery_session_ && registered_devices_.empty()) {
+  if (automatically_update_discovery_session_ &&
+      registered_device_ids_.empty()) {
     is_discovery_session_active_ = false;
     NotifyDiscoverySessionStateChanged(false);
   }
@@ -69,7 +69,7 @@
 }
 
 bool FakeBleScanner::ShouldDiscoverySessionBeActive() {
-  return !registered_devices_.empty();
+  return !registered_device_ids_.empty();
 }
 
 bool FakeBleScanner::IsDiscoverySessionActive() {
diff --git a/chromeos/components/tether/fake_ble_scanner.h b/chromeos/components/tether/fake_ble_scanner.h
index 819043d7..b78d698 100644
--- a/chromeos/components/tether/fake_ble_scanner.h
+++ b/chromeos/components/tether/fake_ble_scanner.h
@@ -29,8 +29,8 @@
   FakeBleScanner(bool automatically_update_discovery_session);
   ~FakeBleScanner() override;
 
-  const std::vector<cryptauth::RemoteDevice>& registered_devices() {
-    return registered_devices_;
+  const std::vector<std::string>& registered_device_ids() {
+    return registered_device_ids_;
   }
 
   void set_should_fail_to_register(bool should_fail_to_register) {
@@ -47,10 +47,8 @@
   void NotifyDiscoverySessionStateChanged(bool discovery_session_active);
 
   // BleScanner:
-  bool RegisterScanFilterForDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
-  bool UnregisterScanFilterForDevice(
-      const cryptauth::RemoteDevice& remote_device) override;
+  bool RegisterScanFilterForDevice(const std::string& device_id) override;
+  bool UnregisterScanFilterForDevice(const std::string& device_id) override;
   bool ShouldDiscoverySessionBeActive() override;
   bool IsDiscoverySessionActive() override;
 
@@ -59,7 +57,7 @@
 
   bool should_fail_to_register_ = false;
   bool is_discovery_session_active_ = false;
-  std::vector<cryptauth::RemoteDevice> registered_devices_;
+  std::vector<std::string> registered_device_ids_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeBleScanner);
 };
diff --git a/chromeos/components/tether/host_scanner_operation_unittest.cc b/chromeos/components/tether/host_scanner_operation_unittest.cc
index cfa33d4..6134f0d7 100644
--- a/chromeos/components/tether/host_scanner_operation_unittest.cc
+++ b/chromeos/components/tether/host_scanner_operation_unittest.cc
@@ -157,8 +157,8 @@
     std::vector<FakeBleConnectionManager::SentMessage>& sent_messages =
         fake_ble_connection_manager_->sent_messages();
     ASSERT_EQ(expected_num_messages_sent, sent_messages.size());
-    EXPECT_EQ(remote_device,
-              sent_messages[expected_num_messages_sent - 1].remote_device);
+    EXPECT_EQ(remote_device.GetDeviceId(),
+              sent_messages[expected_num_messages_sent - 1].device_id);
     EXPECT_EQ(tether_availability_request_string_,
               sent_messages[expected_num_messages_sent - 1].message);
   }
@@ -174,8 +174,8 @@
     test_clock_->Advance(kTetherAvailabilityResponseTime);
 
     fake_ble_connection_manager_->ReceiveMessage(
-        remote_device, CreateTetherAvailabilityResponseString(
-                           response_code, cell_provider_name));
+        remote_device.GetDeviceId(), CreateTetherAvailabilityResponseString(
+                                         response_code, cell_provider_name));
 
     bool tether_available =
         response_code ==
@@ -350,17 +350,23 @@
 
   // Simulate device 1 failing to connect.
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
 
   // The scan should still not be over, and no new scan results should have
   // come in.
@@ -369,17 +375,23 @@
 
   // Simulate device 3 failing to connect.
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
 
   // The scan should still not be over, and no new scan results should have
   // come in.
diff --git a/chromeos/components/tether/keep_alive_operation_unittest.cc b/chromeos/components/tether/keep_alive_operation_unittest.cc
index a05dc1f3..a11abe44f 100644
--- a/chromeos/components/tether/keep_alive_operation_unittest.cc
+++ b/chromeos/components/tether/keep_alive_operation_unittest.cc
@@ -98,7 +98,7 @@
     std::vector<FakeBleConnectionManager::SentMessage>& sent_messages =
         fake_ble_connection_manager_->sent_messages();
     ASSERT_EQ(1u, sent_messages.size());
-    EXPECT_EQ(test_device_, sent_messages[0].remote_device);
+    EXPECT_EQ(test_device_.GetDeviceId(), sent_messages[0].device_id);
     EXPECT_EQ(keep_alive_tickle_string_, sent_messages[0].message);
   }
 
@@ -126,7 +126,7 @@
   test_clock_->Advance(kKeepAliveTickleResponseTime);
 
   fake_ble_connection_manager_->ReceiveMessage(
-      test_device_, CreateKeepAliveTickleResponseString());
+      test_device_.GetDeviceId(), CreateKeepAliveTickleResponseString());
   EXPECT_TRUE(test_observer_->has_run_callback());
   EXPECT_EQ(test_device_, test_observer_->last_remote_device_received());
   ASSERT_TRUE(test_observer_->last_device_status_received());
@@ -141,17 +141,20 @@
 TEST_F(KeepAliveOperationTest, TestCannotConnect) {
   // Simulate the device failing to connect.
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::CONNECTING);
+      test_device_.GetDeviceId(), cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_device_.GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::CONNECTING);
+      test_device_.GetDeviceId(), cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_device_.GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::CONNECTING);
+      test_device_.GetDeviceId(), cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_device_, cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_device_.GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
 
   // The maximum number of connection failures has occurred.
   EXPECT_TRUE(test_observer_->has_run_callback());
diff --git a/chromeos/components/tether/message_transfer_operation.cc b/chromeos/components/tether/message_transfer_operation.cc
index cccecd2..450d8973 100644
--- a/chromeos/components/tether/message_transfer_operation.cc
+++ b/chromeos/components/tether/message_transfer_operation.cc
@@ -82,11 +82,12 @@
   OnOperationStarted();
 
   for (const auto& remote_device : remote_devices_) {
-    connection_manager_->RegisterRemoteDevice(remote_device,
+    connection_manager_->RegisterRemoteDevice(remote_device.GetDeviceId(),
                                               message_type_for_connection_);
 
     cryptauth::SecureChannel::Status status;
-    if (connection_manager_->GetStatusForDevice(remote_device, &status) &&
+    if (connection_manager_->GetStatusForDevice(remote_device.GetDeviceId(),
+                                                &status) &&
         status == cryptauth::SecureChannel::Status::AUTHENTICATED) {
       StartTimerForDevice(remote_device);
       OnDeviceAuthenticated(remote_device);
@@ -95,11 +96,11 @@
 }
 
 void MessageTransferOperation::OnSecureChannelStatusChanged(
-    const cryptauth::RemoteDevice& remote_device,
+    const std::string& device_id,
     const cryptauth::SecureChannel::Status& old_status,
     const cryptauth::SecureChannel::Status& new_status) {
-  if (std::find(remote_devices_.begin(), remote_devices_.end(),
-                remote_device) == remote_devices_.end()) {
+  cryptauth::RemoteDevice* remote_device = GetRemoteDevice(device_id);
+  if (!remote_device) {
     // If the device whose status has changed does not correspond to any of the
     // devices passed to this MessageTransferOperation instance, ignore the
     // status change.
@@ -107,8 +108,8 @@
   }
 
   if (new_status == cryptauth::SecureChannel::Status::AUTHENTICATED) {
-    StartTimerForDevice(remote_device);
-    OnDeviceAuthenticated(remote_device);
+    StartTimerForDevice(*remote_device);
+    OnDeviceAuthenticated(*remote_device);
   } else if (new_status == cryptauth::SecureChannel::Status::DISCONNECTED) {
     // Note: In success cases, the channel advances from DISCONNECTED to
     // CONNECTING to CONNECTED to AUTHENTICATING to AUTHENTICATED. If the
@@ -116,37 +117,36 @@
     // DISCONNECTED and starts over.
 
     uint32_t num_attempts_so_far;
-    if (remote_device_to_num_attempts_map_.find(remote_device) ==
+    if (remote_device_to_num_attempts_map_.find(*remote_device) ==
         remote_device_to_num_attempts_map_.end()) {
       num_attempts_so_far = 0;
     } else {
-      num_attempts_so_far = remote_device_to_num_attempts_map_[remote_device];
+      num_attempts_so_far = remote_device_to_num_attempts_map_[*remote_device];
     }
 
     num_attempts_so_far++;
-    remote_device_to_num_attempts_map_[remote_device] = num_attempts_so_far;
+    remote_device_to_num_attempts_map_[*remote_device] = num_attempts_so_far;
 
     PA_LOG(INFO) << "Connection attempt failed for device with ID "
-                 << remote_device.GetTruncatedDeviceIdForLogs() << ". "
+                 << remote_device->GetTruncatedDeviceIdForLogs() << ". "
                  << "Number of failures so far: " << num_attempts_so_far;
 
     if (num_attempts_so_far >= kMaxConnectionAttemptsPerDevice) {
       PA_LOG(INFO) << "Connection retry limit reached for device with ID "
-                   << remote_device.GetTruncatedDeviceIdForLogs() << ". "
+                   << remote_device->GetTruncatedDeviceIdForLogs() << ". "
                    << "Unregistering device.";
 
       // If the number of failures so far is equal to the maximum allowed number
       // of connection attempts, give up and unregister the device.
-      UnregisterDevice(remote_device);
+      UnregisterDevice(*remote_device);
     }
   }
 }
 
-void MessageTransferOperation::OnMessageReceived(
-    const cryptauth::RemoteDevice& remote_device,
-    const std::string& payload) {
-  if (std::find(remote_devices_.begin(), remote_devices_.end(),
-                remote_device) == remote_devices_.end()) {
+void MessageTransferOperation::OnMessageReceived(const std::string& device_id,
+                                                 const std::string& payload) {
+  cryptauth::RemoteDevice* remote_device = GetRemoteDevice(device_id);
+  if (!remote_device) {
     // If the device from which the message has been received does not
     // correspond to any of the devices passed to this MessageTransferOperation
     // instance, ignore the message.
@@ -156,7 +156,7 @@
   std::unique_ptr<MessageWrapper> message_wrapper =
       MessageWrapper::FromRawMessage(payload);
   if (message_wrapper) {
-    OnMessageReceived(std::move(message_wrapper), remote_device);
+    OnMessageReceived(std::move(message_wrapper), *remote_device);
   }
 }
 
@@ -165,24 +165,27 @@
   // Note: This function may be called from the destructor. It is invalid to
   // invoke any virtual methods if |shutting_down_| is true.
 
-  remote_device_to_num_attempts_map_.erase(remote_device);
-  remote_devices_.erase(std::remove(remote_devices_.begin(),
-                                    remote_devices_.end(), remote_device),
-                        remote_devices_.end());
-  StopTimerForDeviceIfRunning(remote_device);
+  // Make a copy of |remote_device| before continuing, since the code below may
+  // cause the original reference to be deleted.
+  cryptauth::RemoteDevice remote_device_copy = remote_device;
 
-  connection_manager_->UnregisterRemoteDevice(remote_device,
+  remote_device_to_num_attempts_map_.erase(remote_device_copy);
+  remote_devices_.erase(std::remove(remote_devices_.begin(),
+                                    remote_devices_.end(), remote_device_copy),
+                        remote_devices_.end());
+  StopTimerForDeviceIfRunning(remote_device_copy);
+
+  connection_manager_->UnregisterRemoteDevice(remote_device_copy.GetDeviceId(),
                                               message_type_for_connection_);
 
-  if (!shutting_down_ && remote_devices_.empty()) {
+  if (!shutting_down_ && remote_devices_.empty())
     OnOperationFinished();
-  }
 }
 
 int MessageTransferOperation::SendMessageToDevice(
     const cryptauth::RemoteDevice& remote_device,
     std::unique_ptr<MessageWrapper> message_wrapper) {
-  return connection_manager_->SendMessage(remote_device,
+  return connection_manager_->SendMessage(remote_device.GetDeviceId(),
                                           message_wrapper->ToRawMessage());
 }
 
@@ -228,6 +231,16 @@
   UnregisterDevice(remote_device);
 }
 
+cryptauth::RemoteDevice* MessageTransferOperation::GetRemoteDevice(
+    const std::string& device_id) {
+  for (auto& remote_device : remote_devices_) {
+    if (remote_device.GetDeviceId() == device_id)
+      return &remote_device;
+  }
+
+  return nullptr;
+}
+
 }  // namespace tether
 
 }  // namespace chromeos
diff --git a/chromeos/components/tether/message_transfer_operation.h b/chromeos/components/tether/message_transfer_operation.h
index 203ac86..619042a 100644
--- a/chromeos/components/tether/message_transfer_operation.h
+++ b/chromeos/components/tether/message_transfer_operation.h
@@ -33,10 +33,10 @@
 
   // BleConnectionManager::Observer:
   void OnSecureChannelStatusChanged(
-      const cryptauth::RemoteDevice& remote_device,
+      const std::string& device_id,
       const cryptauth::SecureChannel::Status& old_status,
       const cryptauth::SecureChannel::Status& new_status) override;
-  void OnMessageReceived(const cryptauth::RemoteDevice& remote_device,
+  void OnMessageReceived(const std::string& device_id,
                          const std::string& payload) override;
   void OnMessageSent(int sequence_number) override {}
 
@@ -104,6 +104,7 @@
   void StopTimerForDeviceIfRunning(
       const cryptauth::RemoteDevice& remote_device);
   void OnTimeout(const cryptauth::RemoteDevice& remote_device);
+  cryptauth::RemoteDevice* GetRemoteDevice(const std::string& device_id);
 
   std::vector<cryptauth::RemoteDevice> remote_devices_;
   BleConnectionManager* connection_manager_;
diff --git a/chromeos/components/tether/message_transfer_operation_unittest.cc b/chromeos/components/tether/message_transfer_operation_unittest.cc
index d537cd92..bea4961b 100644
--- a/chromeos/components/tether/message_transfer_operation_unittest.cc
+++ b/chromeos/components/tether/message_transfer_operation_unittest.cc
@@ -191,13 +191,17 @@
         remote_device.GetDeviceId());
 
     fake_ble_connection_manager_->SetDeviceStatus(
-        remote_device, cryptauth::SecureChannel::Status::CONNECTING);
+        remote_device.GetDeviceId(),
+        cryptauth::SecureChannel::Status::CONNECTING);
     fake_ble_connection_manager_->SetDeviceStatus(
-        remote_device, cryptauth::SecureChannel::Status::CONNECTED);
+        remote_device.GetDeviceId(),
+        cryptauth::SecureChannel::Status::CONNECTED);
     fake_ble_connection_manager_->SetDeviceStatus(
-        remote_device, cryptauth::SecureChannel::Status::AUTHENTICATING);
+        remote_device.GetDeviceId(),
+        cryptauth::SecureChannel::Status::AUTHENTICATING);
     fake_ble_connection_manager_->SetDeviceStatus(
-        remote_device, cryptauth::SecureChannel::Status::AUTHENTICATED);
+        remote_device.GetDeviceId(),
+        cryptauth::SecureChannel::Status::AUTHENTICATED);
   }
 
   base::MockTimer* GetTimerForDevice(
@@ -231,29 +235,39 @@
 TEST_F(MessageTransferOperationTest, TestCannotConnectAndReachesRetryLimit) {
   ConstructOperation(std::vector<cryptauth::RemoteDevice>{test_devices_[0]});
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   // Try to connect and fail. The device should still be registered.
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[0].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED);
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+      test_devices_[0].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   // Try and fail again. The device should still be registered.
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[0].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED);
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+      test_devices_[0].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   // Try and fail a third time. The maximum number of failures has been reached,
   // so the device should be unregistered.
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[0].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED);
-  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+      test_devices_[0].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
+  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   VerifyOperationStartedAndFinished(true /* has_started */,
                                     true /* has_finished */);
 
@@ -264,18 +278,23 @@
 TEST_F(MessageTransferOperationTest, TestFailsThenConnects) {
   ConstructOperation(std::vector<cryptauth::RemoteDevice>{test_devices_[0]});
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   // Try to connect and fail. The device should still be registered.
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[0].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED);
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+      test_devices_[0].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   // Try again and succeed.
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[0]);
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(operation_->HasDeviceAuthenticated(test_devices_[0]));
   VerifyDefaultTimerCreatedForDevice(test_devices_[0]);
 
@@ -286,19 +305,21 @@
        TestSuccessfulConnectionAndReceiveMessage) {
   ConstructOperation(std::vector<cryptauth::RemoteDevice>{test_devices_[0]});
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   // Simulate how subclasses behave after a successful response: unregister the
   // device.
   operation_->set_should_unregister_device_on_message_received(true);
 
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[0]);
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(operation_->HasDeviceAuthenticated(test_devices_[0]));
   VerifyDefaultTimerCreatedForDevice(test_devices_[0]);
 
   fake_ble_connection_manager_->ReceiveMessage(
-      test_devices_[0],
+      test_devices_[0].GetDeviceId(),
       MessageWrapper(CreateTetherAvailabilityResponse()).ToRawMessage());
 
   EXPECT_EQ(1u, operation_->GetReceivedMessages(test_devices_[0]).size());
@@ -313,17 +334,25 @@
 TEST_F(MessageTransferOperationTest, TestDevicesUnregisteredAfterDeletion) {
   ConstructOperation(test_devices_);
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[1]));
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[2]));
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[3]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[1].GetDeviceId()));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[2].GetDeviceId()));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[3].GetDeviceId()));
 
   // Delete the operation. All registered devices should be unregistered.
   operation_.reset();
-  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
-  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(test_devices_[1]));
-  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(test_devices_[2]));
-  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(test_devices_[3]));
+  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
+  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[1].GetDeviceId()));
+  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[2].GetDeviceId()));
+  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[3].GetDeviceId()));
 }
 
 TEST_F(MessageTransferOperationTest,
@@ -332,12 +361,14 @@
 
   ConstructOperation(std::vector<cryptauth::RemoteDevice>{test_devices_[0]});
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   operation_->set_timeout_seconds(timeout_seconds);
 
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[0]);
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(operation_->HasDeviceAuthenticated(test_devices_[0]));
   VerifyTimerCreatedForDevice(test_devices_[0], timeout_seconds);
 
@@ -345,7 +376,7 @@
             GetTimerForDevice(test_devices_[0])->GetCurrentDelay());
 
   fake_ble_connection_manager_->ReceiveMessage(
-      test_devices_[0],
+      test_devices_[0].GetDeviceId(),
       MessageWrapper(CreateTetherAvailabilityResponse()).ToRawMessage());
 
   EXPECT_EQ(1u, operation_->GetReceivedMessages(test_devices_[0]).size());
@@ -360,16 +391,19 @@
 TEST_F(MessageTransferOperationTest, TestAuthenticatesButTimesOut) {
   ConstructOperation(std::vector<cryptauth::RemoteDevice>{test_devices_[0]});
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[0]);
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(operation_->HasDeviceAuthenticated(test_devices_[0]));
   VerifyDefaultTimerCreatedForDevice(test_devices_[0]);
 
   GetTimerForDevice(test_devices_[0])->Fire();
 
-  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(operation_->has_operation_finished());
 }
 
@@ -378,15 +412,17 @@
   ConstructOperation(
       std::vector<cryptauth::RemoteDevice>{test_devices_[0], test_devices_[0]});
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[0]);
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(operation_->HasDeviceAuthenticated(test_devices_[0]));
   VerifyDefaultTimerCreatedForDevice(test_devices_[0]);
 
   fake_ble_connection_manager_->ReceiveMessage(
-      test_devices_[0],
+      test_devices_[0].GetDeviceId(),
       MessageWrapper(CreateTetherAvailabilityResponse()).ToRawMessage());
 
   // Should still have received only one message even though the device was
@@ -403,23 +439,26 @@
 TEST_F(MessageTransferOperationTest, TestReceiveEventForOtherDevice) {
   ConstructOperation(std::vector<cryptauth::RemoteDevice>{test_devices_[0]});
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 
   // Simulate the authentication of |test_devices_[1]|'s channel. Since the
   // operation was only constructed with |test_devices_[0]|, this operation
   // should not be affected.
   fake_ble_connection_manager_->RegisterRemoteDevice(
-      test_devices_[1], MessageType::CONNECT_TETHERING_REQUEST);
+      test_devices_[1].GetDeviceId(), MessageType::CONNECT_TETHERING_REQUEST);
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[1]);
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[1]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[1].GetDeviceId()));
   EXPECT_FALSE(operation_->HasDeviceAuthenticated(test_devices_[0]));
   EXPECT_FALSE(operation_->HasDeviceAuthenticated(test_devices_[1]));
 
   // Now, receive a message for |test_devices[1]|. Likewise, this operation
   // should not be affected.
   fake_ble_connection_manager_->ReceiveMessage(
-      test_devices_[1],
+      test_devices_[1].GetDeviceId(),
       MessageWrapper(CreateTetherAvailabilityResponse()).ToRawMessage());
 
   EXPECT_FALSE(operation_->GetReceivedMessages(test_devices_[0]).size());
@@ -432,18 +471,19 @@
   // Simulate the authentication of |test_devices_[0]|'s channel before
   // initialization.
   fake_ble_connection_manager_->RegisterRemoteDevice(
-      test_devices_[0], MessageType::CONNECT_TETHERING_REQUEST);
+      test_devices_[0].GetDeviceId(), MessageType::CONNECT_TETHERING_REQUEST);
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[0]);
 
   // Now initialize; the authentication handler should have been invoked.
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(operation_->HasDeviceAuthenticated(test_devices_[0]));
   VerifyDefaultTimerCreatedForDevice(test_devices_[0]);
 
   // Receiving a message should work at this point.
   fake_ble_connection_manager_->ReceiveMessage(
-      test_devices_[0],
+      test_devices_[0].GetDeviceId(),
       MessageWrapper(CreateTetherAvailabilityResponse()).ToRawMessage());
 
   EXPECT_EQ(1u, operation_->GetReceivedMessages(test_devices_[0]).size());
@@ -462,12 +502,13 @@
   // Simulate the authentication of |test_devices_[0]|'s channel before
   // initialization.
   fake_ble_connection_manager_->RegisterRemoteDevice(
-      test_devices_[0], MessageType::CONNECT_TETHERING_REQUEST);
+      test_devices_[0].GetDeviceId(), MessageType::CONNECT_TETHERING_REQUEST);
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[0]);
 
   // Now initialize; the authentication handler should have been invoked.
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(operation_->HasDeviceAuthenticated(test_devices_[0]));
   VerifyDefaultTimerCreatedForDevice(test_devices_[0]);
 
@@ -476,69 +517,90 @@
 
   // Should still be registered since it was also registered for the
   // CONNECT_TETHERING_REQUEST MessageType.
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
 }
 
 TEST_F(MessageTransferOperationTest, MultipleDevices) {
   ConstructOperation(test_devices_);
   InitializeOperation();
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[1]));
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[2]));
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[3]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[1].GetDeviceId()));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[2].GetDeviceId()));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[3].GetDeviceId()));
 
   // Authenticate |test_devices_[0]|'s channel.
   fake_ble_connection_manager_->RegisterRemoteDevice(
-      test_devices_[0], MessageType::CONNECT_TETHERING_REQUEST);
+      test_devices_[0].GetDeviceId(), MessageType::CONNECT_TETHERING_REQUEST);
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[0]);
   EXPECT_TRUE(operation_->HasDeviceAuthenticated(test_devices_[0]));
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[0]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[0].GetDeviceId()));
   VerifyDefaultTimerCreatedForDevice(test_devices_[0]);
 
   // Fail 3 times to connect to |test_devices_[1]|.
   test_timer_factory_->set_device_id_for_next_timer(
       test_devices_[1].GetDeviceId());
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[1], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[1].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   EXPECT_FALSE(operation_->HasDeviceAuthenticated(test_devices_[1]));
-  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(test_devices_[1]));
+  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[1].GetDeviceId()));
   EXPECT_FALSE(GetTimerForDevice(test_devices_[1]));
 
   // Authenticate |test_devices_[2]|'s channel.
   fake_ble_connection_manager_->RegisterRemoteDevice(
-      test_devices_[2], MessageType::CONNECT_TETHERING_REQUEST);
+      test_devices_[2].GetDeviceId(), MessageType::CONNECT_TETHERING_REQUEST);
   TransitionDeviceStatusFromDisconnectedToAuthenticated(test_devices_[2]);
   EXPECT_TRUE(operation_->HasDeviceAuthenticated(test_devices_[2]));
-  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(test_devices_[2]));
+  EXPECT_TRUE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[2].GetDeviceId()));
   VerifyDefaultTimerCreatedForDevice(test_devices_[2]);
 
   // Fail 3 times to connect to |test_devices_[3]|.
   test_timer_factory_->set_device_id_for_next_timer(
       test_devices_[3].GetDeviceId());
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::CONNECTING);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::CONNECTING);
   fake_ble_connection_manager_->SetDeviceStatus(
-      test_devices_[3], cryptauth::SecureChannel::Status::DISCONNECTED);
+      test_devices_[3].GetDeviceId(),
+      cryptauth::SecureChannel::Status::DISCONNECTED);
   EXPECT_FALSE(operation_->HasDeviceAuthenticated(test_devices_[3]));
-  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(test_devices_[3]));
+  EXPECT_FALSE(fake_ble_connection_manager_->IsRegistered(
+      test_devices_[3].GetDeviceId()));
   EXPECT_FALSE(GetTimerForDevice(test_devices_[3]));
 }
 
diff --git a/components/cryptauth/ble/ble_advertisement_generator.cc b/components/cryptauth/ble/ble_advertisement_generator.cc
index 29b0dca..da4f92b 100644
--- a/components/cryptauth/ble/ble_advertisement_generator.cc
+++ b/components/cryptauth/ble/ble_advertisement_generator.cc
@@ -9,6 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "components/cryptauth/local_device_data_provider.h"
 #include "components/cryptauth/remote_beacon_seed_fetcher.h"
+#include "components/cryptauth/remote_device.h"
 #include "components/proximity_auth/logging/logging.h"
 
 namespace cryptauth {
@@ -19,14 +20,14 @@
 // static
 std::unique_ptr<DataWithTimestamp>
 BleAdvertisementGenerator::GenerateBleAdvertisement(
-    const RemoteDevice& remote_device,
+    const std::string& device_id,
     LocalDeviceDataProvider* local_device_data_provider,
     RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher) {
   if (!instance_)
     instance_ = new BleAdvertisementGenerator();
 
   return instance_->GenerateBleAdvertisementInternal(
-      remote_device, local_device_data_provider, remote_beacon_seed_fetcher);
+      device_id, local_device_data_provider, remote_beacon_seed_fetcher);
 }
 
 // static
@@ -42,7 +43,7 @@
 
 std::unique_ptr<DataWithTimestamp>
 BleAdvertisementGenerator::GenerateBleAdvertisementInternal(
-    const RemoteDevice& remote_device,
+    const std::string& device_id,
     LocalDeviceDataProvider* local_device_data_provider,
     RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher) {
   std::string local_device_public_key;
@@ -60,17 +61,17 @@
   }
 
   std::vector<BeaconSeed> remote_beacon_seeds;
-  if (!remote_beacon_seed_fetcher->FetchSeedsForDevice(remote_device,
-                                                       &remote_beacon_seeds)) {
+  if (!remote_beacon_seed_fetcher->FetchSeedsForDeviceId(
+          device_id, &remote_beacon_seeds)) {
     PA_LOG(WARNING) << "Error fetching beacon seeds for device with ID "
-                    << remote_device.GetTruncatedDeviceIdForLogs() << ". "
+                    << RemoteDevice::TruncateDeviceIdForLogs(device_id) << ". "
                     << "Cannot advertise without seeds.";
     return nullptr;
   }
 
   if (remote_beacon_seeds.empty()) {
     PA_LOG(WARNING) << "No synced seeds exist for device with ID "
-                    << remote_device.GetTruncatedDeviceIdForLogs() << ". "
+                    << RemoteDevice::TruncateDeviceIdForLogs(device_id) << ". "
                     << "Cannot advertise without seeds.";
     return nullptr;
   }
@@ -80,7 +81,7 @@
                                             remote_beacon_seeds);
   if (!service_data) {
     PA_LOG(WARNING) << "Error generating advertisement for device with ID "
-                    << remote_device.GetTruncatedDeviceIdForLogs() << ". "
+                    << RemoteDevice::TruncateDeviceIdForLogs(device_id) << ". "
                     << "Cannot advertise.";
     return nullptr;
   }
diff --git a/components/cryptauth/ble/ble_advertisement_generator.h b/components/cryptauth/ble/ble_advertisement_generator.h
index 69ce5a3..38b8d8f0 100644
--- a/components/cryptauth/ble/ble_advertisement_generator.h
+++ b/components/cryptauth/ble/ble_advertisement_generator.h
@@ -9,7 +9,6 @@
 
 #include "base/macros.h"
 #include "components/cryptauth/foreground_eid_generator.h"
-#include "components/cryptauth/remote_device.h"
 
 namespace chromeos {
 namespace tether {
@@ -26,11 +25,11 @@
 // Generates advertisements for the ProximityAuth BLE advertisement scheme.
 class BleAdvertisementGenerator {
  public:
-  // Generates an advertisement from the current device to |remote_device|. The
-  // generated advertisement should be used immediately since it is based on
-  // the current timestamp.
+  // Generates an advertisement from the current device to the device with ID
+  // |device_id|. The generated advertisement should be used immediately since
+  // it is based on the current timestamp.
   static std::unique_ptr<DataWithTimestamp> GenerateBleAdvertisement(
-      const RemoteDevice& remote_device,
+      const std::string& device_id,
       LocalDeviceDataProvider* local_device_data_provider,
       RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher);
 
@@ -40,7 +39,7 @@
   BleAdvertisementGenerator();
 
   virtual std::unique_ptr<DataWithTimestamp> GenerateBleAdvertisementInternal(
-      const RemoteDevice& remote_device,
+      const std::string& device_id,
       LocalDeviceDataProvider* local_device_data_provider,
       RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher);
 
diff --git a/components/cryptauth/ble/ble_advertisement_generator_unittest.cc b/components/cryptauth/ble/ble_advertisement_generator_unittest.cc
index 942ef4c..33bd0d7e 100644
--- a/components/cryptauth/ble/ble_advertisement_generator_unittest.cc
+++ b/components/cryptauth/ble/ble_advertisement_generator_unittest.cc
@@ -51,7 +51,8 @@
     mock_seed_fetcher_ = base::MakeUnique<MockRemoteBeaconSeedFetcher>();
     std::vector<BeaconSeed> device_0_beacon_seeds =
         CreateFakeBeaconSeedsForDevice(fake_device_);
-    mock_seed_fetcher_->SetSeedsForDevice(fake_device_, &device_0_beacon_seeds);
+    mock_seed_fetcher_->SetSeedsForDeviceId(fake_device_.GetDeviceId(),
+                                            &device_0_beacon_seeds);
 
     mock_local_data_provider_ = base::MakeUnique<MockLocalDeviceDataProvider>();
     mock_local_data_provider_->SetPublicKey(
@@ -68,7 +69,7 @@
 
   std::unique_ptr<DataWithTimestamp> GenerateBleAdvertisement() {
     return generator_->GenerateBleAdvertisementInternal(
-        fake_device_, mock_local_data_provider_.get(),
+        fake_device_.GetDeviceId(), mock_local_data_provider_.get(),
         mock_seed_fetcher_.get());
   }
 
@@ -97,13 +98,14 @@
 }
 
 TEST_F(CryptAuthBleAdvertisementGeneratorTest, NoBeaconSeeds) {
-  mock_seed_fetcher_->SetSeedsForDevice(fake_device_, nullptr);
+  mock_seed_fetcher_->SetSeedsForDeviceId(fake_device_.GetDeviceId(), nullptr);
   EXPECT_EQ(nullptr, GenerateBleAdvertisement());
 }
 
 TEST_F(CryptAuthBleAdvertisementGeneratorTest, EmptyBeaconSeeds) {
   std::vector<BeaconSeed> empty_seeds;
-  mock_seed_fetcher_->SetSeedsForDevice(fake_device_, &empty_seeds);
+  mock_seed_fetcher_->SetSeedsForDeviceId(fake_device_.GetDeviceId(),
+                                          &empty_seeds);
   EXPECT_EQ(nullptr, GenerateBleAdvertisement());
 }
 
diff --git a/components/cryptauth/ble/fake_ble_advertisement_generator.cc b/components/cryptauth/ble/fake_ble_advertisement_generator.cc
index c2e1a30..f95ad9e4 100644
--- a/components/cryptauth/ble/fake_ble_advertisement_generator.cc
+++ b/components/cryptauth/ble/fake_ble_advertisement_generator.cc
@@ -12,7 +12,7 @@
 
 std::unique_ptr<DataWithTimestamp>
 FakeBleAdvertisementGenerator::GenerateBleAdvertisementInternal(
-    const RemoteDevice& remote_device,
+    const std::string& device_id,
     LocalDeviceDataProvider* local_device_data_provider,
     RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher) {
   return std::move(advertisement_);
diff --git a/components/cryptauth/ble/fake_ble_advertisement_generator.h b/components/cryptauth/ble/fake_ble_advertisement_generator.h
index f79685e..1dad802 100644
--- a/components/cryptauth/ble/fake_ble_advertisement_generator.h
+++ b/components/cryptauth/ble/fake_ble_advertisement_generator.h
@@ -27,7 +27,7 @@
 
  protected:
   std::unique_ptr<DataWithTimestamp> GenerateBleAdvertisementInternal(
-      const RemoteDevice& remote_device,
+      const std::string& device_id,
       LocalDeviceDataProvider* local_device_data_provider,
       RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher) override;
 
diff --git a/components/cryptauth/foreground_eid_generator.cc b/components/cryptauth/foreground_eid_generator.cc
index 6dd7de3..d50464c 100644
--- a/components/cryptauth/foreground_eid_generator.cc
+++ b/components/cryptauth/foreground_eid_generator.cc
@@ -112,9 +112,9 @@
                                timestamps->current_period_end_timestamp_ms);
 }
 
-RemoteDevice const* ForegroundEidGenerator::IdentifyRemoteDeviceByAdvertisement(
+std::string ForegroundEidGenerator::IdentifyRemoteDeviceByAdvertisement(
     const std::string& advertisement_service_data,
-    const std::vector<RemoteDevice>& device_list,
+    const std::vector<std::string>& device_ids,
     const std::vector<BeaconSeed>& scanning_device_beacon_seeds) const {
   // Resize the service data to analyze only the first |2 * kNumBytesInEidValue|
   // bytes. The bytes following these are flags, so they are not needed to
@@ -122,18 +122,18 @@
   std::string service_data_without_flags = advertisement_service_data;
   service_data_without_flags.resize(2 * RawEidGenerator::kNumBytesInEidValue);
 
-  for (const auto& remote_device : device_list) {
+  for (const auto& device_id : device_ids) {
     std::vector<std::string> possible_advertisements =
-        GeneratePossibleAdvertisements(remote_device.public_key,
+        GeneratePossibleAdvertisements(RemoteDevice::DerivePublicKey(device_id),
                                        scanning_device_beacon_seeds);
     for (const auto& possible_advertisement : possible_advertisements) {
       if (service_data_without_flags == possible_advertisement) {
-        return const_cast<RemoteDevice*>(&remote_device);
+        return device_id;
       }
     }
   }
 
-  return nullptr;
+  return std::string();
 }
 
 std::vector<std::string> ForegroundEidGenerator::GeneratePossibleAdvertisements(
diff --git a/components/cryptauth/foreground_eid_generator.h b/components/cryptauth/foreground_eid_generator.h
index fa175a1..d534afad 100644
--- a/components/cryptauth/foreground_eid_generator.h
+++ b/components/cryptauth/foreground_eid_generator.h
@@ -18,7 +18,6 @@
 
 class BeaconSeed;
 class RawEidGenerator;
-struct RemoteDevice;
 
 // Generates ephemeral ID (EID) values that are broadcast for foreground BLE
 // advertisements in the ProximityAuth protocol.
@@ -89,11 +88,13 @@
       const std::string& advertising_device_public_key,
       const std::vector<BeaconSeed>& scanning_device_beacon_seeds) const;
 
-  // Given a list of RemoteDevices, identifies the device which could have
-  // produced the supplied advertisement service data.
-  virtual RemoteDevice const* IdentifyRemoteDeviceByAdvertisement(
+  // Given a list of device IDs, returns the device ID which could have
+  // produced the supplied advertisement service data. If none of the provided
+  // device IDs could have produced the advertisement, an empty string is
+  // returned.
+  virtual std::string IdentifyRemoteDeviceByAdvertisement(
       const std::string& advertisement_service_data,
-      const std::vector<RemoteDevice>& device_list,
+      const std::vector<std::string>& device_ids,
       const std::vector<BeaconSeed>& scanning_device_beacon_seeds) const;
 
  private:
diff --git a/components/cryptauth/foreground_eid_generator_unittest.cc b/components/cryptauth/foreground_eid_generator_unittest.cc
index 0fcb9e75..814cc4c7 100644
--- a/components/cryptauth/foreground_eid_generator_unittest.cc
+++ b/components/cryptauth/foreground_eid_generator_unittest.cc
@@ -53,9 +53,9 @@
 
 const std::string kDefaultAdvertisingDevicePublicKey = "publicKey";
 
-static BeaconSeed CreateBeaconSeed(const std::string& data,
-                                   const int64_t start_timestamp_ms,
-                                   const int64_t end_timestamp_ms) {
+BeaconSeed CreateBeaconSeed(const std::string& data,
+                            int64_t start_timestamp_ms,
+                            int64_t end_timestamp_ms) {
   BeaconSeed seed;
   seed.set_data(data);
   seed.set_start_time_millis(start_timestamp_ms);
@@ -63,10 +63,9 @@
   return seed;
 }
 
-static std::string GenerateFakeEidData(
-    const std::string& eid_seed,
-    const int64_t start_of_period_timestamp_ms,
-    const std::string* extra_entropy) {
+std::string GenerateFakeEidData(const std::string& eid_seed,
+                                int64_t start_of_period_timestamp_ms,
+                                const std::string* extra_entropy) {
   std::hash<std::string> string_hash;
   int64_t seed_hash = string_hash(eid_seed);
   int64_t extra_hash = extra_entropy ? string_hash(*extra_entropy) : 0;
@@ -79,9 +78,9 @@
   return fake_data;
 }
 
-static std::string GenerateFakeAdvertisement(
+std::string GenerateFakeAdvertisement(
     const std::string& scanning_device_eid_seed,
-    const int64_t start_of_period_timestamp_ms,
+    int64_t start_of_period_timestamp_ms,
     const std::string& advertising_device_public_key) {
   std::string fake_scanning_eid = GenerateFakeEidData(
       scanning_device_eid_seed, start_of_period_timestamp_ms, nullptr);
@@ -94,11 +93,6 @@
   return fake_advertisement;
 }
 
-static RemoteDevice CreateRemoteDevice(const std::string& public_key) {
-  RemoteDevice remote_device;
-  remote_device.public_key = public_key;
-  return remote_device;
-}
 }  //  namespace
 
 class CryptAuthForegroundEidGeneratorTest : public testing::Test {
@@ -533,11 +527,11 @@
       GenerateFakeAdvertisement(kSecondSeed, kDefaultCurrentPeriodStart,
                                 kDefaultAdvertisingDevicePublicKey);
 
-  std::vector<RemoteDevice> device_list;
-  const RemoteDevice* identified_device =
+  std::vector<std::string> device_id_list;
+  const std::string identified_device_id =
       eid_generator_->IdentifyRemoteDeviceByAdvertisement(
-          service_data, device_list, scanning_device_beacon_seeds_);
-  EXPECT_FALSE(identified_device);
+          service_data, device_id_list, scanning_device_beacon_seeds_);
+  EXPECT_TRUE(identified_device_id.empty());
 }
 
 TEST_F(CryptAuthForegroundEidGeneratorTest,
@@ -548,13 +542,13 @@
       GenerateFakeAdvertisement(kSecondSeed, kDefaultCurrentPeriodStart,
                                 kDefaultAdvertisingDevicePublicKey);
 
-  RemoteDevice correct_device =
-      CreateRemoteDevice(kDefaultAdvertisingDevicePublicKey);
-  std::vector<RemoteDevice> device_list = {correct_device};
-  const RemoteDevice* identified_device =
+  std::string device_id =
+      RemoteDevice::GenerateDeviceId(kDefaultAdvertisingDevicePublicKey);
+  std::vector<std::string> device_id_list = {device_id};
+  std::string identified_device_id =
       eid_generator_->IdentifyRemoteDeviceByAdvertisement(
-          service_data, device_list, scanning_device_beacon_seeds_);
-  EXPECT_EQ(correct_device.public_key, identified_device->public_key);
+          service_data, device_id_list, scanning_device_beacon_seeds_);
+  EXPECT_EQ(device_id, identified_device_id);
 }
 
 TEST_F(CryptAuthForegroundEidGeneratorTest,
@@ -570,13 +564,13 @@
   service_data.append(
       1, static_cast<char>(ForegroundEidGenerator::kBluetooth4Flag));
 
-  RemoteDevice correct_device =
-      CreateRemoteDevice(kDefaultAdvertisingDevicePublicKey);
-  std::vector<RemoteDevice> device_list = {correct_device};
-  const RemoteDevice* identified_device =
+  std::string device_id =
+      RemoteDevice::GenerateDeviceId(kDefaultAdvertisingDevicePublicKey);
+  std::vector<std::string> device_id_list = {device_id};
+  std::string identified_device_id =
       eid_generator_->IdentifyRemoteDeviceByAdvertisement(
-          service_data, device_list, scanning_device_beacon_seeds_);
-  EXPECT_EQ(correct_device.public_key, identified_device->public_key);
+          service_data, device_id_list, scanning_device_beacon_seeds_);
+  EXPECT_EQ(device_id, identified_device_id);
 }
 
 TEST_F(CryptAuthForegroundEidGeneratorTest,
@@ -591,13 +585,13 @@
   // after the first 4 bytes.
   service_data.append("extra_flag_bytes");
 
-  RemoteDevice correct_device =
-      CreateRemoteDevice(kDefaultAdvertisingDevicePublicKey);
-  std::vector<RemoteDevice> device_list = {correct_device};
-  const RemoteDevice* identified_device =
+  std::string device_id =
+      RemoteDevice::GenerateDeviceId(kDefaultAdvertisingDevicePublicKey);
+  std::vector<std::string> device_id_list = {device_id};
+  std::string identified_device_id =
       eid_generator_->IdentifyRemoteDeviceByAdvertisement(
-          service_data, device_list, scanning_device_beacon_seeds_);
-  EXPECT_EQ(correct_device.public_key, identified_device->public_key);
+          service_data, device_id_list, scanning_device_beacon_seeds_);
+  EXPECT_EQ(device_id, identified_device_id);
 }
 
 TEST_F(CryptAuthForegroundEidGeneratorTest,
@@ -608,12 +602,11 @@
       GenerateFakeAdvertisement(kSecondSeed, kDefaultCurrentPeriodStart,
                                 kDefaultAdvertisingDevicePublicKey);
 
-  RemoteDevice wrong_device = CreateRemoteDevice("wrongPublicKey");
-  std::vector<RemoteDevice> device_list = {wrong_device};
-  const RemoteDevice* identified_device =
+  std::vector<std::string> device_id_list = {"wrongDeviceId"};
+  std::string identified_device_id =
       eid_generator_->IdentifyRemoteDeviceByAdvertisement(
-          service_data, device_list, scanning_device_beacon_seeds_);
-  EXPECT_FALSE(identified_device);
+          service_data, device_id_list, scanning_device_beacon_seeds_);
+  EXPECT_TRUE(identified_device_id.empty());
 }
 
 TEST_F(CryptAuthForegroundEidGeneratorTest,
@@ -624,14 +617,13 @@
       GenerateFakeAdvertisement(kSecondSeed, kDefaultCurrentPeriodStart,
                                 kDefaultAdvertisingDevicePublicKey);
 
-  RemoteDevice correct_device =
-      CreateRemoteDevice(kDefaultAdvertisingDevicePublicKey);
-  RemoteDevice wrong_device = CreateRemoteDevice("wrongPublicKey");
-  std::vector<RemoteDevice> device_list = {correct_device, wrong_device};
-  const RemoteDevice* identified_device =
+  std::string device_id =
+      RemoteDevice::GenerateDeviceId(kDefaultAdvertisingDevicePublicKey);
+  std::vector<std::string> device_id_list = {device_id, "wrongDeviceId"};
+  std::string identified_device_id =
       eid_generator_->IdentifyRemoteDeviceByAdvertisement(
-          service_data, device_list, scanning_device_beacon_seeds_);
-  EXPECT_EQ(correct_device.public_key, identified_device->public_key);
+          service_data, device_id_list, scanning_device_beacon_seeds_);
+  EXPECT_EQ(device_id, identified_device_id);
 }
 
 TEST_F(CryptAuthForegroundEidGeneratorTest,
@@ -642,12 +634,11 @@
       GenerateFakeAdvertisement(kSecondSeed, kDefaultCurrentPeriodStart,
                                 kDefaultAdvertisingDevicePublicKey);
 
-  RemoteDevice wrong_device = CreateRemoteDevice("wrongPublicKey");
-  std::vector<RemoteDevice> device_list = {wrong_device, wrong_device};
-  const RemoteDevice* identified_device =
+  std::vector<std::string> device_id_list = {"wrongDeviceId", "wrongDeviceId"};
+  std::string identified_device_id =
       eid_generator_->IdentifyRemoteDeviceByAdvertisement(
-          service_data, device_list, scanning_device_beacon_seeds_);
-  EXPECT_FALSE(identified_device);
+          service_data, device_id_list, scanning_device_beacon_seeds_);
+  EXPECT_TRUE(identified_device_id.empty());
 }
 
 TEST_F(CryptAuthForegroundEidGeneratorTest, DataWithTimestamp_ContainsTime) {
diff --git a/components/cryptauth/mock_foreground_eid_generator.cc b/components/cryptauth/mock_foreground_eid_generator.cc
index 0dc949c..7964b4e0 100644
--- a/components/cryptauth/mock_foreground_eid_generator.cc
+++ b/components/cryptauth/mock_foreground_eid_generator.cc
@@ -9,11 +9,7 @@
 namespace cryptauth {
 
 MockForegroundEidGenerator::MockForegroundEidGenerator()
-    : background_scan_filter_(nullptr),
-      advertisement_(nullptr),
-      possible_advertisements_(nullptr),
-      identified_device_(nullptr),
-      num_identify_calls_(0) {}
+    : num_identify_calls_(0) {}
 
 MockForegroundEidGenerator::~MockForegroundEidGenerator() {}
 
@@ -60,17 +56,16 @@
   return *possible_advertisements_;
 }
 
-RemoteDevice const*
-MockForegroundEidGenerator::IdentifyRemoteDeviceByAdvertisement(
+std::string MockForegroundEidGenerator::IdentifyRemoteDeviceByAdvertisement(
     const std::string& advertisement_service_data,
-    const std::vector<RemoteDevice>& device_list,
+    const std::vector<std::string>& device_id_list,
     const std::vector<BeaconSeed>& scanning_device_beacon_seeds) const {
   // Increment num_identify_calls_. Since this overrides a const method, some
   // hacking is needed to modify the num_identify_calls_ instance variable.
   int* num_identify_calls_ptr = const_cast<int*>(&num_identify_calls_);
   *num_identify_calls_ptr = *num_identify_calls_ptr + 1;
 
-  return identified_device_;
+  return identified_device_id_;
 }
 
 }  // namespace cryptauth
diff --git a/components/cryptauth/mock_foreground_eid_generator.h b/components/cryptauth/mock_foreground_eid_generator.h
index ef7232c8..ec8fc6ab 100644
--- a/components/cryptauth/mock_foreground_eid_generator.h
+++ b/components/cryptauth/mock_foreground_eid_generator.h
@@ -14,7 +14,6 @@
 namespace cryptauth {
 
 class BeaconSeed;
-struct RemoteDevice;
 
 // Mock class for ForegroundEidGenerator. Note that GoogleMock cannot be used to
 // mock this class because GoogleMock's mock functions cannot return a
@@ -39,8 +38,8 @@
     possible_advertisements_ = std::move(possible_advertisements);
   }
 
-  void set_identified_device(const RemoteDevice* identified_device) {
-    identified_device_ = identified_device;
+  void set_identified_device_id(const std::string& identified_device_id) {
+    identified_device_id_ = identified_device_id;
   }
 
   // ForegroundEidGenerator:
@@ -55,9 +54,9 @@
       const std::string& advertising_device_public_key,
       const std::vector<BeaconSeed>& scanning_device_beacon_seeds)
       const override;
-  RemoteDevice const* IdentifyRemoteDeviceByAdvertisement(
+  std::string IdentifyRemoteDeviceByAdvertisement(
       const std::string& advertisement_service_data,
-      const std::vector<RemoteDevice>& device_list,
+      const std::vector<std::string>& device_id_list,
       const std::vector<BeaconSeed>& scanning_device_beacon_seeds)
       const override;
 
@@ -67,7 +66,7 @@
   std::unique_ptr<EidData> background_scan_filter_;
   std::unique_ptr<DataWithTimestamp> advertisement_;
   std::unique_ptr<std::vector<std::string>> possible_advertisements_;
-  const RemoteDevice* identified_device_;
+  std::string identified_device_id_;
 
   int num_identify_calls_;
 };
diff --git a/components/cryptauth/mock_remote_beacon_seed_fetcher.cc b/components/cryptauth/mock_remote_beacon_seed_fetcher.cc
index 21fc308..3988077 100644
--- a/components/cryptauth/mock_remote_beacon_seed_fetcher.cc
+++ b/components/cryptauth/mock_remote_beacon_seed_fetcher.cc
@@ -13,32 +13,31 @@
 
 MockRemoteBeaconSeedFetcher::~MockRemoteBeaconSeedFetcher() {}
 
-bool MockRemoteBeaconSeedFetcher::FetchSeedsForDevice(
-    const RemoteDevice& remote_device,
+bool MockRemoteBeaconSeedFetcher::FetchSeedsForDeviceId(
+    const std::string& device_id,
     std::vector<BeaconSeed>* beacon_seeds_out) const {
-  const auto& seeds_iter =
-      public_key_to_beacon_seeds_map_.find(remote_device.public_key);
-  if (seeds_iter == public_key_to_beacon_seeds_map_.end()) {
+  const auto& seeds_iter = device_id_to_beacon_seeds_map_.find(device_id);
+
+  if (seeds_iter == device_id_to_beacon_seeds_map_.end())
     return false;
-  }
 
   *beacon_seeds_out = seeds_iter->second;
   return true;
 }
 
-void MockRemoteBeaconSeedFetcher::SetSeedsForDevice(
-    const RemoteDevice& remote_device,
+void MockRemoteBeaconSeedFetcher::SetSeedsForDeviceId(
+    const std::string& device_id,
     const std::vector<BeaconSeed>* beacon_seeds) {
   if (!beacon_seeds) {
-    const auto& it =
-        public_key_to_beacon_seeds_map_.find(remote_device.public_key);
-    if (it != public_key_to_beacon_seeds_map_.end()) {
-      public_key_to_beacon_seeds_map_.erase(it);
-    }
+    const auto& it = device_id_to_beacon_seeds_map_.find(device_id);
+
+    if (it != device_id_to_beacon_seeds_map_.end())
+      device_id_to_beacon_seeds_map_.erase(it);
+
     return;
   }
 
-  public_key_to_beacon_seeds_map_[remote_device.public_key] = *beacon_seeds;
+  device_id_to_beacon_seeds_map_[device_id] = *beacon_seeds;
 }
 
 }  // namespace cryptauth
diff --git a/components/cryptauth/mock_remote_beacon_seed_fetcher.h b/components/cryptauth/mock_remote_beacon_seed_fetcher.h
index 9b8efe04..84dc7a91 100644
--- a/components/cryptauth/mock_remote_beacon_seed_fetcher.h
+++ b/components/cryptauth/mock_remote_beacon_seed_fetcher.h
@@ -18,20 +18,18 @@
   MockRemoteBeaconSeedFetcher();
   ~MockRemoteBeaconSeedFetcher() override;
 
-  // RemoteBeaconSeedFetcher:
-  bool FetchSeedsForDevice(
-      const RemoteDevice& remote_device,
-      std::vector<BeaconSeed>* beacon_seeds_out) const override;
-
   // If |beacon_seeds| is null, FetchSeedsForDevice() will fail for the same
   // |remote_device|.
-  void SetSeedsForDevice(
-      const RemoteDevice& remote_device,
-      const std::vector<BeaconSeed>* beacon_seeds);
+  void SetSeedsForDeviceId(const std::string& device_id,
+                           const std::vector<BeaconSeed>* beacon_seeds);
+
+  // RemoteBeaconSeedFetcher:
+  bool FetchSeedsForDeviceId(
+      const std::string& device_id,
+      std::vector<BeaconSeed>* beacon_seeds_out) const override;
 
  private:
-  std::map<std::string, std::vector<BeaconSeed>>
-      public_key_to_beacon_seeds_map_;
+  std::map<std::string, std::vector<BeaconSeed>> device_id_to_beacon_seeds_map_;
 
   DISALLOW_COPY_AND_ASSIGN(MockRemoteBeaconSeedFetcher);
 };
diff --git a/components/cryptauth/remote_beacon_seed_fetcher.cc b/components/cryptauth/remote_beacon_seed_fetcher.cc
index c53a630..709a495 100644
--- a/components/cryptauth/remote_beacon_seed_fetcher.cc
+++ b/components/cryptauth/remote_beacon_seed_fetcher.cc
@@ -5,6 +5,7 @@
 #include "components/cryptauth/remote_beacon_seed_fetcher.h"
 
 #include "components/cryptauth/cryptauth_device_manager.h"
+#include "components/cryptauth/remote_device.h"
 
 namespace cryptauth {
 
@@ -14,15 +15,11 @@
 
 RemoteBeaconSeedFetcher::~RemoteBeaconSeedFetcher() {}
 
-bool RemoteBeaconSeedFetcher::FetchSeedsForDevice(
-    const RemoteDevice& remote_device,
+bool RemoteBeaconSeedFetcher::FetchSeedsForDeviceId(
+    const std::string& device_id,
     std::vector<BeaconSeed>* beacon_seeds_out) const {
-  if (remote_device.public_key.empty()) {
-    return false;
-  }
-
   for(const auto& device_info : device_manager_->GetSyncedDevices()) {
-    if (device_info.public_key() == remote_device.public_key) {
+    if (RemoteDevice::GenerateDeviceId(device_info.public_key()) == device_id) {
       if (device_info.beacon_seeds_size() == 0) {
         return false;
       }
diff --git a/components/cryptauth/remote_beacon_seed_fetcher.h b/components/cryptauth/remote_beacon_seed_fetcher.h
index 6eb3825..5c53e90 100644
--- a/components/cryptauth/remote_beacon_seed_fetcher.h
+++ b/components/cryptauth/remote_beacon_seed_fetcher.h
@@ -9,7 +9,6 @@
 
 #include "base/macros.h"
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
-#include "components/cryptauth/remote_device.h"
 
 namespace cryptauth {
 
@@ -24,8 +23,8 @@
   RemoteBeaconSeedFetcher(const CryptAuthDeviceManager* device_manager);
   virtual ~RemoteBeaconSeedFetcher();
 
-  virtual bool FetchSeedsForDevice(
-      const RemoteDevice& remote_device,
+  virtual bool FetchSeedsForDeviceId(
+      const std::string& device_id,
       std::vector<BeaconSeed>* beacon_seeds_out) const;
 
  private:
diff --git a/components/cryptauth/remote_beacon_seed_fetcher_unittest.cc b/components/cryptauth/remote_beacon_seed_fetcher_unittest.cc
index 25cda2f..31fcaeeee 100644
--- a/components/cryptauth/remote_beacon_seed_fetcher_unittest.cc
+++ b/components/cryptauth/remote_beacon_seed_fetcher_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/memory/ptr_util.h"
 #include "components/cryptauth/cryptauth_client.h"
 #include "components/cryptauth/cryptauth_device_manager.h"
+#include "components/cryptauth/remote_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -45,12 +46,6 @@
   MOCK_CONST_METHOD0(GetSyncedDevices, std::vector<ExternalDeviceInfo>());
 };
 
-RemoteDevice CreateRemoteDevice(const std::string& public_key) {
-  RemoteDevice remote_device;
-  remote_device.public_key = public_key;
-  return remote_device;
-}
-
 ExternalDeviceInfo CreateFakeInfo1() {
   BeaconSeed seed1;
   seed1.set_data(fake_beacon_seed1_data);
@@ -111,47 +106,39 @@
 };
 
 TEST_F(CryptAuthRemoteBeaconSeedFetcherTest, TestRemoteDeviceWithNoPublicKey) {
-  RemoteDevice device = CreateRemoteDevice("");
-
   std::vector<BeaconSeed> seeds;
-  EXPECT_FALSE(fetcher_->FetchSeedsForDevice(device, &seeds));
+  EXPECT_FALSE(fetcher_->FetchSeedsForDeviceId(std::string(), &seeds));
 }
 
 TEST_F(CryptAuthRemoteBeaconSeedFetcherTest, TestNoSyncedDevices) {
-  RemoteDevice device = CreateRemoteDevice(public_key1);
-
   EXPECT_CALL(*mock_device_manager_, GetSyncedDevices())
       .WillOnce(Return(std::vector<ExternalDeviceInfo>()));
 
   std::vector<BeaconSeed> seeds;
-  EXPECT_FALSE(fetcher_->FetchSeedsForDevice(device, &seeds));
+  EXPECT_FALSE(fetcher_->FetchSeedsForDeviceId(
+      RemoteDevice::GenerateDeviceId(public_key1), &seeds));
 }
 
 TEST_F(CryptAuthRemoteBeaconSeedFetcherTest, TestDeviceHasDifferentPublicKey) {
-  // A public key which is different from the public keys of all of the synced
-  // devices.
-  RemoteDevice device = CreateRemoteDevice("differentPublicKey");
-
   std::vector<ExternalDeviceInfo> device_infos = {fake_info1_, fake_info2_};
   EXPECT_CALL(*mock_device_manager_, GetSyncedDevices())
       .WillOnce(Return(device_infos));
 
   std::vector<BeaconSeed> seeds;
-  EXPECT_FALSE(fetcher_->FetchSeedsForDevice(device, &seeds));
+  EXPECT_FALSE(fetcher_->FetchSeedsForDeviceId(
+      RemoteDevice::GenerateDeviceId("differentPublicKey"), &seeds));
 }
 
 TEST_F(CryptAuthRemoteBeaconSeedFetcherTest, TestSuccess) {
-  RemoteDevice device1 = CreateRemoteDevice(public_key1);
-  RemoteDevice device2 = CreateRemoteDevice(public_key2);
-
   std::vector<ExternalDeviceInfo> device_infos = {fake_info1_, fake_info2_};
   EXPECT_CALL(*mock_device_manager_, GetSyncedDevices())
       .Times(2)
       .WillRepeatedly(Return(device_infos));
 
   std::vector<BeaconSeed> seeds1;
-  ASSERT_TRUE(fetcher_->FetchSeedsForDevice(device1, &seeds1));
-  ASSERT_EQ(static_cast<size_t>(2), seeds1.size());
+  ASSERT_TRUE(fetcher_->FetchSeedsForDeviceId(
+      RemoteDevice::GenerateDeviceId(public_key1), &seeds1));
+  ASSERT_EQ(2u, seeds1.size());
   EXPECT_EQ(fake_beacon_seed1_data, seeds1[0].data());
   EXPECT_EQ(fake_beacon_seed1_start_ms, seeds1[0].start_time_millis());
   EXPECT_EQ(fake_beacon_seed1_end_ms, seeds1[0].end_time_millis());
@@ -160,8 +147,9 @@
   EXPECT_EQ(fake_beacon_seed2_end_ms, seeds1[1].end_time_millis());
 
   std::vector<BeaconSeed> seeds2;
-  ASSERT_TRUE(fetcher_->FetchSeedsForDevice(device2, &seeds2));
-  ASSERT_EQ(static_cast<size_t>(2), seeds2.size());
+  ASSERT_TRUE(fetcher_->FetchSeedsForDeviceId(
+      RemoteDevice::GenerateDeviceId(public_key2), &seeds2));
+  ASSERT_EQ(2u, seeds2.size());
   EXPECT_EQ(fake_beacon_seed3_data, seeds2[0].data());
   EXPECT_EQ(fake_beacon_seed3_start_ms, seeds2[0].start_time_millis());
   EXPECT_EQ(fake_beacon_seed3_end_ms, seeds2[0].end_time_millis());
diff --git a/components/cryptauth/remote_device.cc b/components/cryptauth/remote_device.cc
index 7a176026..20f1f69 100644
--- a/components/cryptauth/remote_device.cc
+++ b/components/cryptauth/remote_device.cc
@@ -65,9 +65,7 @@
 }
 
 std::string RemoteDevice::GetDeviceId() const {
-  std::string to_return;
-  base::Base64Encode(public_key, &to_return);
-  return to_return;
+  return RemoteDevice::GenerateDeviceId(public_key);
 }
 
 std::string RemoteDevice::GetTruncatedDeviceIdForLogs() const {
@@ -103,6 +101,21 @@
 }
 
 // static
+std::string RemoteDevice::GenerateDeviceId(const std::string& public_key) {
+  std::string device_id;
+  base::Base64Encode(public_key, &device_id);
+  return device_id;
+}
+
+// static
+std::string RemoteDevice::DerivePublicKey(const std::string& device_id) {
+  std::string public_key;
+  if (base::Base64Decode(device_id, &public_key))
+    return public_key;
+  return std::string();
+}
+
+// static
 std::string RemoteDevice::TruncateDeviceIdForLogs(const std::string& full_id) {
   if (full_id.length() <= 10) {
     return full_id;
diff --git a/components/cryptauth/remote_device.h b/components/cryptauth/remote_device.h
index abdd4db..59ad7aba 100644
--- a/components/cryptauth/remote_device.h
+++ b/components/cryptauth/remote_device.h
@@ -57,6 +57,13 @@
   // necessary in order to use |RemoteDevice| as a key of a std::map.
   bool operator<(const RemoteDevice& other) const;
 
+  // Generates the device ID for a device given its public key.
+  static std::string GenerateDeviceId(const std::string& public_key);
+
+  // Derives the public key that was used to generate the given device ID;
+  // returns empty string if |device_id| is not a valid device ID.
+  static std::string DerivePublicKey(const std::string& device_id);
+
   // Static method for truncated device ID for logs.
   static std::string TruncateDeviceIdForLogs(const std::string& full_id);
 };
diff --git a/content/browser/payments/payment_app_content_unittest_base.cc b/content/browser/payments/payment_app_content_unittest_base.cc
index 4200f42..ad032730 100644
--- a/content/browser/payments/payment_app_content_unittest_base.cc
+++ b/content/browser/payments/payment_app_content_unittest_base.cc
@@ -69,7 +69,7 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
       override {
     ServiceWorkerVersion* version =
         context()->GetLiveVersion(service_worker_version_id);
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index 1924b88..040b4fc 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -479,7 +479,7 @@
     ProviderInfoGetter provider_info_getter,
     mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
     mojom::ControllerServiceWorkerRequest controller_request,
-    mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
     blink::mojom::ServiceWorkerHostAssociatedPtrInfo
         service_worker_host_ptr_info,
     StatusCallback callback) {
diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h
index 71ee8df..a2197154 100644
--- a/content/browser/service_worker/embedded_worker_instance.h
+++ b/content/browser/service_worker/embedded_worker_instance.h
@@ -30,6 +30,7 @@
 #include "content/common/service_worker/service_worker_status_code.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "third_party/WebKit/common/service_worker/service_worker.mojom.h"
+#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
 #include "url/gurl.h"
 
 namespace IPC {
@@ -132,14 +133,15 @@
   // it is null.
   // |provider_info_getter| is called when this instance
   // allocates a process and is ready to send a StartWorker message.
-  void Start(std::unique_ptr<EmbeddedWorkerStartParams> params,
-             ProviderInfoGetter provider_info_getter,
-             mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
-             mojom::ControllerServiceWorkerRequest controller_request,
-             mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
-             blink::mojom::ServiceWorkerHostAssociatedPtrInfo
-                 service_worker_host_ptr_info,
-             StatusCallback callback);
+  void Start(
+      std::unique_ptr<EmbeddedWorkerStartParams> params,
+      ProviderInfoGetter provider_info_getter,
+      mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+      mojom::ControllerServiceWorkerRequest controller_request,
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+      blink::mojom::ServiceWorkerHostAssociatedPtrInfo
+          service_worker_host_ptr_info,
+      StatusCallback callback);
 
   // Stops the worker. It is invalid to call this when the worker is not in
   // STARTING or RUNNING status.
@@ -331,7 +333,8 @@
   // changed to a mojo struct and we put them in EmbeddedWorkerStartParams.
   mojom::ServiceWorkerEventDispatcherRequest pending_dispatcher_request_;
   mojom::ControllerServiceWorkerRequest pending_controller_request_;
-  mojom::ServiceWorkerInstalledScriptsInfoPtr pending_installed_scripts_info_;
+  blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
+      pending_installed_scripts_info_;
   blink::mojom::ServiceWorkerHostAssociatedPtrInfo
       pending_service_worker_host_ptr_info_;
 
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index 07bb84b..cac0d65 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -243,9 +243,10 @@
     return worker->SendStartWorker(std::move(params));
   }
 
-  mojom::ServiceWorkerInstalledScriptsInfoPtr GetInstalledScriptsInfoPtr() {
+  blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
+  GetInstalledScriptsInfoPtr() {
     installed_scripts_managers_.emplace_back();
-    auto info = mojom::ServiceWorkerInstalledScriptsInfo::New();
+    auto info = blink::mojom::ServiceWorkerInstalledScriptsInfo::New();
     info->manager_request =
         mojo::MakeRequest(&installed_scripts_managers_.back());
     installed_scripts_manager_host_requests_.push_back(
@@ -278,9 +279,9 @@
   // Mojo endpoints.
   std::vector<mojom::ServiceWorkerEventDispatcherPtr> dispatchers_;
   std::vector<mojom::ControllerServiceWorkerPtr> controllers_;
-  std::vector<mojom::ServiceWorkerInstalledScriptsManagerPtr>
+  std::vector<blink::mojom::ServiceWorkerInstalledScriptsManagerPtr>
       installed_scripts_managers_;
-  std::vector<mojom::ServiceWorkerInstalledScriptsManagerHostRequest>
+  std::vector<blink::mojom::ServiceWorkerInstalledScriptsManagerHostRequest>
       installed_scripts_manager_host_requests_;
   std::vector<blink::mojom::ServiceWorkerHostAssociatedRequest>
       service_worker_host_requests_;
@@ -312,7 +313,7 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
       override {
     if (force_stall_in_start_) {
       // Prepare for OnStopWorker().
@@ -925,15 +926,16 @@
       : EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient(helper) {}
 
  private:
-  void StartWorker(const EmbeddedWorkerStartParams&,
-                   mojom::ServiceWorkerEventDispatcherRequest,
-                   mojom::ControllerServiceWorkerRequest,
-                   mojom::ServiceWorkerInstalledScriptsInfoPtr /* unused */,
-                   blink::mojom::ServiceWorkerHostAssociatedPtrInfo,
-                   mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo,
-                   mojom::ServiceWorkerProviderInfoForStartWorkerPtr,
-                   blink::mojom::WorkerContentSettingsProxyPtr
-                       content_settings_proxy) override {
+  void StartWorker(
+      const EmbeddedWorkerStartParams&,
+      mojom::ServiceWorkerEventDispatcherRequest,
+      mojom::ControllerServiceWorkerRequest,
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr /* unused */,
+      blink::mojom::ServiceWorkerHostAssociatedPtrInfo,
+      mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo,
+      mojom::ServiceWorkerProviderInfoForStartWorkerPtr,
+      blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy)
+      override {
     helper_->mock_instance_clients()->clear();
   }
 };
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index 10574bdf..3526a90 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -100,7 +100,7 @@
     const EmbeddedWorkerStartParams& params,
     mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
     mojom::ControllerServiceWorkerRequest controller_request,
-    mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
     blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
     mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
     mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -547,7 +547,7 @@
     blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
     mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
     mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-    mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info) {
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info) {
   EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
   ASSERT_TRUE(worker);
   MockServiceWorkerEventDispatcher::Create(AsWeakPtr(), worker->thread_id(),
@@ -835,7 +835,7 @@
     blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
     mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
     mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-    mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info) {
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info) {
   EmbeddedWorkerInstance* worker =
       registry()->GetWorker(params.embedded_worker_id);
   ASSERT_TRUE(worker);
diff --git a/content/browser/service_worker/embedded_worker_test_helper.h b/content/browser/service_worker/embedded_worker_test_helper.h
index d3fa607..cca54d8 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/content/browser/service_worker/embedded_worker_test_helper.h
@@ -28,6 +28,7 @@
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "net/http/http_response_info.h"
 #include "third_party/WebKit/common/service_worker/service_worker.mojom.h"
+#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
 #include "url/gurl.h"
 
 class GURL;
@@ -83,7 +84,8 @@
         const EmbeddedWorkerStartParams& params,
         mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
         mojom::ControllerServiceWorkerRequest controller_request,
-        mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+        blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
+            installed_scripts_info,
         blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
         mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
         mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -197,7 +199,8 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info);
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
+          installed_scripts_info);
   virtual void OnResumeAfterDownload(int embedded_worker_id);
   // StopWorker IPC handler routed through MockEmbeddedWorkerInstanceClient.
   // This calls SimulateWorkerStopped() by default.
@@ -306,7 +309,8 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info);
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
+          installed_scripts_info);
   void OnResumeAfterDownloadStub(int embedded_worker_id);
   void OnStopWorkerStub(int embedded_worker_id);
   void OnMessageToWorkerStub(int thread_id,
@@ -417,7 +421,7 @@
   std::map<int /* embedded_worker_id */, ServiceWorkerRemoteProviderEndpoint>
       embedded_worker_id_remote_provider_map_;
   std::map<int /* embedded_worker_id */,
-           mojom::ServiceWorkerInstalledScriptsInfoPtr>
+           blink::mojom::ServiceWorkerInstalledScriptsInfoPtr>
       embedded_worker_id_installed_scripts_info_map_;
 
   std::vector<Event> events_;
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc
index c0b7219d..0f23228 100644
--- a/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -185,7 +185,7 @@
       const EmbeddedWorkerStartParams& params,
       mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
       mojom::ControllerServiceWorkerRequest controller_request,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info,
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info,
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 3784a818..2143ef1 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -138,7 +138,7 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
       override {
     mojom::EmbeddedWorkerInstanceHostAssociatedPtr instance_host_ptr;
     instance_host_ptr.Bind(std::move(instance_host));
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
index 9594dac..5b182b4 100644
--- a/content/browser/service_worker/service_worker_installed_scripts_sender.cc
+++ b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -296,7 +296,7 @@
 
 ServiceWorkerInstalledScriptsSender::~ServiceWorkerInstalledScriptsSender() {}
 
-mojom::ServiceWorkerInstalledScriptsInfoPtr
+blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
 ServiceWorkerInstalledScriptsSender::CreateInfoAndBind() {
   DCHECK_EQ(State::kNotStarted, state_);
 
@@ -312,7 +312,7 @@
   DCHECK(!installed_urls.empty())
       << "At least the main script should be installed.";
 
-  auto info = mojom::ServiceWorkerInstalledScriptsInfo::New();
+  auto info = blink::mojom::ServiceWorkerInstalledScriptsInfo::New();
   info->manager_request = mojo::MakeRequest(&manager_);
   info->installed_urls = std::move(installed_urls);
   binding_.Bind(mojo::MakeRequest(&info->manager_host_ptr));
@@ -355,7 +355,7 @@
   TRACE_EVENT_NESTABLE_ASYNC_INSTANT2(
       "ServiceWorker", "SendScriptInfoToRenderer", this, "body_size", body_size,
       "meta_data_size", meta_data_size);
-  auto script_info = mojom::ServiceWorkerScriptInfo::New();
+  auto script_info = blink::mojom::ServiceWorkerScriptInfo::New();
   script_info->script_url = current_sending_url_;
   script_info->headers = std::move(headers);
   script_info->encoding = std::move(encoding);
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender.h b/content/browser/service_worker/service_worker_installed_scripts_sender.h
index 0d031b3..98ab3700 100644
--- a/content/browser/service_worker/service_worker_installed_scripts_sender.h
+++ b/content/browser/service_worker/service_worker_installed_scripts_sender.h
@@ -6,8 +6,9 @@
 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_INSTALLED_SCRIPTS_SENDER_H_
 
 #include "base/containers/queue.h"
-#include "content/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
+#include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
 
 namespace content {
 
@@ -29,7 +30,7 @@
 // 3. The sender sends requested scripts. |state_| is kSendingScripts. When all
 //    the requested scripts are sent, returns to the phase 2.
 class CONTENT_EXPORT ServiceWorkerInstalledScriptsSender
-    : public mojom::ServiceWorkerInstalledScriptsManagerHost {
+    : public blink::mojom::ServiceWorkerInstalledScriptsManagerHost {
  public:
   // Do not change the order. This is used for UMA.
   enum class FinishedReason {
@@ -49,10 +50,10 @@
 
   ~ServiceWorkerInstalledScriptsSender() override;
 
-  // Creates a Mojo struct (mojom::ServiceWorkerInstalledScriptsInfo) and sets
-  // it with the information to create WebServiceWorkerInstalledScriptsManager
-  // on the renderer.
-  mojom::ServiceWorkerInstalledScriptsInfoPtr CreateInfoAndBind();
+  // Creates a Mojo struct (blink::mojom::ServiceWorkerInstalledScriptsInfo) and
+  // sets it with the information to create
+  // WebServiceWorkerInstalledScriptsManager on the renderer.
+  blink::mojom::ServiceWorkerInstalledScriptsInfoPtr CreateInfoAndBind();
 
   // Starts sending installed scripts to the worker.
   void Start();
@@ -91,7 +92,7 @@
   void OnHttpInfoRead(scoped_refptr<HttpResponseInfoIOBuffer> http_info);
   void OnFinishSendingScript(FinishedReason reason);
 
-  // Implements mojom::ServiceWorkerInstalledScriptsManagerHost.
+  // Implements blink::mojom::ServiceWorkerInstalledScriptsManagerHost.
   void RequestInstalledScript(const GURL& script_url) override;
 
   bool IsSendingMainScript() const;
@@ -101,8 +102,9 @@
   const int64_t main_script_id_;
   bool sent_main_script_;
 
-  mojo::Binding<mojom::ServiceWorkerInstalledScriptsManagerHost> binding_;
-  mojom::ServiceWorkerInstalledScriptsManagerPtr manager_;
+  mojo::Binding<blink::mojom::ServiceWorkerInstalledScriptsManagerHost>
+      binding_;
+  blink::mojom::ServiceWorkerInstalledScriptsManagerPtr manager_;
   std::unique_ptr<Sender> running_sender_;
 
   State state_;
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
index f54a0e66..b195ab2 100644
--- a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
+++ b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
@@ -95,7 +95,7 @@
   }
 
   void CheckIfIdentical(
-      const mojom::ServiceWorkerScriptInfoPtr& script_info) const {
+      const blink::mojom::ServiceWorkerScriptInfoPtr& script_info) const {
     EXPECT_EQ(script_url_, script_info->script_url);
     EXPECT_EQ(encoding_, script_info->encoding);
     for (const auto& header : headers_) {
@@ -129,13 +129,13 @@
 };
 
 class MockServiceWorkerInstalledScriptsManager
-    : public mojom::ServiceWorkerInstalledScriptsManager {
+    : public blink::mojom::ServiceWorkerInstalledScriptsManager {
  public:
   explicit MockServiceWorkerInstalledScriptsManager(
-      mojom::ServiceWorkerInstalledScriptsManagerRequest request)
+      blink::mojom::ServiceWorkerInstalledScriptsManagerRequest request)
       : binding_(this, std::move(request)) {}
 
-  mojom::ServiceWorkerScriptInfoPtr WaitUntilTransferInstalledScript() {
+  blink::mojom::ServiceWorkerScriptInfoPtr WaitUntilTransferInstalledScript() {
     EXPECT_TRUE(incoming_script_info_.is_null());
     EXPECT_FALSE(transfer_installed_script_waiter_);
     base::RunLoop loop;
@@ -146,7 +146,7 @@
   }
 
   void TransferInstalledScript(
-      mojom::ServiceWorkerScriptInfoPtr script_info) override {
+      blink::mojom::ServiceWorkerScriptInfoPtr script_info) override {
     EXPECT_TRUE(incoming_script_info_.is_null());
     EXPECT_TRUE(transfer_installed_script_waiter_);
     incoming_script_info_ = std::move(script_info);
@@ -155,9 +155,9 @@
   }
 
  private:
-  mojo::Binding<mojom::ServiceWorkerInstalledScriptsManager> binding_;
+  mojo::Binding<blink::mojom::ServiceWorkerInstalledScriptsManager> binding_;
   base::OnceClosure transfer_installed_script_waiter_;
-  mojom::ServiceWorkerScriptInfoPtr incoming_script_info_;
+  blink::mojom::ServiceWorkerScriptInfoPtr incoming_script_info_;
 
   DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerInstalledScriptsManager);
 };
@@ -258,7 +258,7 @@
 
   std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
   {
-    mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
         sender->CreateInfoAndBind();
     ASSERT_TRUE(scripts_info);
     ASSERT_EQ(kExpectedScriptInfoMap.size(),
@@ -315,7 +315,7 @@
 
   std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
   {
-    mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
         sender->CreateInfoAndBind();
     ASSERT_TRUE(scripts_info);
     ASSERT_EQ(kExpectedScriptInfoMap.size(),
@@ -375,7 +375,7 @@
 
   std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
   {
-    mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
         sender->CreateInfoAndBind();
     ASSERT_TRUE(scripts_info);
     ASSERT_EQ(kExpectedScriptInfoMap.size(),
@@ -446,7 +446,7 @@
 
   std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
   {
-    mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
         sender->CreateInfoAndBind();
     ASSERT_TRUE(scripts_info);
     ASSERT_EQ(kExpectedScriptInfoMap.size(),
@@ -526,9 +526,9 @@
       std::make_unique<ServiceWorkerInstalledScriptsSender>(version());
 
   std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
-  mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host_ptr;
+  blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host_ptr;
   {
-    mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
         sender->CreateInfoAndBind();
     ASSERT_TRUE(scripts_info);
     ASSERT_EQ(kExpectedScriptInfoMap.size(),
@@ -613,9 +613,9 @@
       std::make_unique<ServiceWorkerInstalledScriptsSender>(version());
 
   std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
-  mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host_ptr;
+  blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host_ptr;
   {
-    mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
         sender->CreateInfoAndBind();
     ASSERT_TRUE(scripts_info);
     ASSERT_EQ(kExpectedScriptInfoMap.size(),
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 6922cb77..23c3ff6 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -472,7 +472,7 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
       override {
     mojom::EmbeddedWorkerInstanceHostAssociatedPtr instance_host_ptr;
     instance_host_ptr.Bind(std::move(instance_host));
@@ -941,7 +941,7 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
       override {
     const std::string kMockScriptBody = "mock_script";
     const uint64_t kMockScriptSize = 19284;
@@ -1079,7 +1079,7 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
       override {
     ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
     ServiceWorkerRegistration* registration =
@@ -1785,7 +1785,7 @@
       const EmbeddedWorkerStartParams& params,
       mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
       mojom::ControllerServiceWorkerRequest controller_request,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info,
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info,
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index b1a5f4e..9642cf4 100644
--- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -65,6 +65,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/common/service_worker/service_worker.mojom.h"
 #include "third_party/WebKit/common/service_worker/service_worker_event_status.mojom.h"
+#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
 #include "third_party/WebKit/common/service_worker/service_worker_registration.mojom.h"
 
 namespace content {
@@ -517,7 +518,7 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
       override {
     embedded_worker_id_ = embedded_worker_id;
     service_worker_version_id_ = service_worker_version_id;
@@ -556,7 +557,7 @@
   mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
       start_worker_instance_host_;
   mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info_;
-  mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info_;
+  blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info_;
   int embedded_worker_id_ = 0;
   mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_;
   mojom::FetchEventPreloadHandlePtr preload_handle_;
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 6d62c16..b56626c 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -48,6 +48,7 @@
 #include "third_party/WebKit/common/origin_trials/trial_token_validator.h"
 #include "third_party/WebKit/common/service_worker/service_worker_client.mojom.h"
 #include "third_party/WebKit/common/service_worker/service_worker_error_type.mojom.h"
+#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
 #include "third_party/WebKit/common/service_worker/service_worker_object.mojom.h"
 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
 
@@ -1520,7 +1521,7 @@
   params->is_installed = IsInstalled(status_);
   params->pause_after_download = pause_after_download_;
 
-  mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info;
+  blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info;
   if (ServiceWorkerUtils::IsScriptStreamingEnabled() && IsInstalled(status()) &&
       !pause_after_download_) {
     DCHECK(!installed_scripts_sender_);
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc
index 318e190..0e61c8a 100644
--- a/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -31,6 +31,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/common/service_worker/service_worker.mojom.h"
 #include "third_party/WebKit/common/service_worker/service_worker_event_status.mojom.h"
+#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
 #include "third_party/WebKit/common/service_worker/service_worker_registration.mojom.h"
 
 // IPC messages for testing ---------------------------------------------------
@@ -94,7 +95,7 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
       override {
     service_worker_host_map_[embedded_worker_id].Bind(
         std::move(service_worker_host));
@@ -339,7 +340,7 @@
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
       override {
     switch (mode_) {
       case StartMode::STALL:
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index f6e6757..8357828 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -211,8 +211,6 @@
     "media/cdm_info.cc",
     "media/media_devices.cc",
     "media/media_devices.h",
-    "media/media_devices_param_traits.cc",
-    "media/media_devices_param_traits.h",
     "media/media_player_delegate_messages.h",
     "media/media_player_messages_android.h",
     "media/media_stream_controls.cc",
@@ -599,7 +597,6 @@
     "service_worker/service_worker_container.mojom",
     "service_worker/service_worker_event_dispatcher.mojom",
     "service_worker/service_worker_fetch_response_callback.mojom",
-    "service_worker/service_worker_installed_scripts_manager.mojom",
     "service_worker/service_worker_provider.mojom",
     "shared_worker/shared_worker.mojom",
     "shared_worker/shared_worker_client.mojom",
diff --git a/content/common/DEPS b/content/common/DEPS
index 26cda20..66c506c 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -52,6 +52,7 @@
   "+third_party/WebKit/public/platform/modules/fetch/fetch_api_request.mojom.h",
   "+third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h",
   "+third_party/WebKit/public/platform/modules/mediasession/media_session.mojom.h",
+  "+third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom.h",
   "+third_party/WebKit/public/platform/modules/permissions/permission.mojom.h",
   "+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h",
   "+third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h",
diff --git a/content/common/media/media_devices.typemap b/content/common/media/media_devices.typemap
index 3b65711..0ffd81c 100644
--- a/content/common/media/media_devices.typemap
+++ b/content/common/media/media_devices.typemap
@@ -4,7 +4,10 @@
 
 mojom = "//third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom"
 public_headers = [ "//content/common/media/media_devices.h" ]
-traits_headers = [ "//content/common/media/media_devices_param_traits.h" ]
+traits_headers = [ "//content/common/media/media_devices_typemap_traits.h" ]
+sources = [
+  "//content/common/media/media_devices_typemap_traits.cc",
+]
 type_mappings = [
   "blink.mojom.MediaDeviceType=content::MediaDeviceType",
   "blink.mojom.MediaDeviceInfo=content::MediaDeviceInfo",
diff --git a/content/common/media/media_devices_param_traits.cc b/content/common/media/media_devices_param_traits.cc
deleted file mode 100644
index 74874406..0000000
--- a/content/common/media/media_devices_param_traits.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/media/media_devices_param_traits.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#include "content/common/media/media_devices_param_traits.h"
-}  // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#include "content/common/media/media_devices_param_traits.h"
-}  // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#include "content/common/media/media_devices_param_traits.h"
-}  // namespace IPC
diff --git a/content/common/media/media_devices_param_traits.h b/content/common/media/media_devices_param_traits.h
deleted file mode 100644
index ed0830c..0000000
--- a/content/common/media/media_devices_param_traits.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Multiply-included IPC traits file, hence no include guard.
-
-#include "content/common/content_export.h"
-#include "content/common/media/media_devices.h"
-#include "ipc/ipc_message_macros.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-
-IPC_ENUM_TRAITS_MAX_VALUE(content::MediaDeviceType,
-                          content::NUM_MEDIA_DEVICE_TYPES - 1)
-
-IPC_STRUCT_TRAITS_BEGIN(content::MediaDeviceInfo)
-  IPC_STRUCT_TRAITS_MEMBER(device_id)
-  IPC_STRUCT_TRAITS_MEMBER(label)
-  IPC_STRUCT_TRAITS_MEMBER(group_id)
-IPC_STRUCT_TRAITS_END()
diff --git a/content/common/media/media_devices_typemap_traits.cc b/content/common/media/media_devices_typemap_traits.cc
new file mode 100644
index 0000000..e265d22
--- /dev/null
+++ b/content/common/media/media_devices_typemap_traits.cc
@@ -0,0 +1,64 @@
+// 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/common/media/media_devices_typemap_traits.h"
+
+#include "base/logging.h"
+
+namespace mojo {
+
+// static
+blink::mojom::MediaDeviceType
+EnumTraits<blink::mojom::MediaDeviceType, content::MediaDeviceType>::ToMojom(
+    content::MediaDeviceType type) {
+  switch (type) {
+    case content::MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT:
+      return blink::mojom::MediaDeviceType::MEDIA_AUDIO_INPUT;
+    case content::MediaDeviceType::MEDIA_DEVICE_TYPE_VIDEO_INPUT:
+      return blink::mojom::MediaDeviceType::MEDIA_VIDEO_INPUT;
+    case content::MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_OUTPUT:
+      return blink::mojom::MediaDeviceType::MEDIA_AUDIO_OUTPUT;
+    default:
+      break;
+  }
+  NOTREACHED();
+  return blink::mojom::MediaDeviceType::NUM_MEDIA_DEVICE_TYPES;
+}
+
+// static
+bool EnumTraits<blink::mojom::MediaDeviceType, content::MediaDeviceType>::
+    FromMojom(blink::mojom::MediaDeviceType input,
+              content::MediaDeviceType* out) {
+  switch (input) {
+    case blink::mojom::MediaDeviceType::MEDIA_AUDIO_INPUT:
+      *out = content::MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT;
+      return true;
+    case blink::mojom::MediaDeviceType::MEDIA_VIDEO_INPUT:
+      *out = content::MediaDeviceType::MEDIA_DEVICE_TYPE_VIDEO_INPUT;
+      return true;
+    case blink::mojom::MediaDeviceType::MEDIA_AUDIO_OUTPUT:
+      *out = content::MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_OUTPUT;
+      return true;
+    default:
+      break;
+  }
+  NOTREACHED();
+  return false;
+}
+
+// static
+bool StructTraits<
+    blink::mojom::MediaDeviceInfoDataView,
+    content::MediaDeviceInfo>::Read(blink::mojom::MediaDeviceInfoDataView input,
+                                    content::MediaDeviceInfo* out) {
+  if (!input.ReadDeviceId(&out->device_id))
+    return false;
+  if (!input.ReadLabel(&out->label))
+    return false;
+  if (!input.ReadGroupId(&out->group_id))
+    return false;
+  return true;
+}
+
+}  // namespace mojo
diff --git a/content/common/media/media_devices_typemap_traits.h b/content/common/media/media_devices_typemap_traits.h
new file mode 100644
index 0000000..b30cc69
--- /dev/null
+++ b/content/common/media/media_devices_typemap_traits.h
@@ -0,0 +1,42 @@
+// 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_COMMON_MEDIA_MEDIA_DEVICES_TYPEMAP_TRAITS_H_
+#define CONTENT_COMMON_MEDIA_MEDIA_DEVICES_TYPEMAP_TRAITS_H_
+
+#include "content/common/media/media_devices.h"
+#include "third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<blink::mojom::MediaDeviceType, content::MediaDeviceType> {
+  static blink::mojom::MediaDeviceType ToMojom(content::MediaDeviceType type);
+
+  static bool FromMojom(blink::mojom::MediaDeviceType input,
+                        content::MediaDeviceType* out);
+};
+
+template <>
+struct StructTraits<blink::mojom::MediaDeviceInfoDataView,
+                    content::MediaDeviceInfo> {
+  static const std::string& device_id(const content::MediaDeviceInfo& info) {
+    return info.device_id;
+  }
+
+  static const std::string& label(const content::MediaDeviceInfo& info) {
+    return info.label;
+  }
+
+  static const std::string& group_id(const content::MediaDeviceInfo& info) {
+    return info.group_id;
+  }
+
+  static bool Read(blink::mojom::MediaDeviceInfoDataView input,
+                   content::MediaDeviceInfo* out);
+};
+
+}  // namespace mojo
+
+#endif  // CONTENT_COMMON_MEDIA_MEDIA_DEVICES_TYPEMAP_TRAITS_H_
\ No newline at end of file
diff --git a/content/common/service_worker/embedded_worker.mojom b/content/common/service_worker/embedded_worker.mojom
index 80a62b7..9d9179b 100644
--- a/content/common/service_worker/embedded_worker.mojom
+++ b/content/common/service_worker/embedded_worker.mojom
@@ -7,13 +7,13 @@
 import "content/common/native_types.mojom";
 import "content/common/service_worker/controller_service_worker.mojom";
 import "content/common/service_worker/service_worker_event_dispatcher.mojom";
-import "content/common/service_worker/service_worker_installed_scripts_manager.mojom";
 import "content/common/service_worker/service_worker_provider.mojom";
 import "mojo/common/string16.mojom";
 import "mojo/common/time.mojom";
 import "mojo/common/unguessable_token.mojom";
 import "services/service_manager/public/interfaces/interface_provider.mojom";
 import "third_party/WebKit/common/service_worker/service_worker.mojom";
+import "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom";
 import "third_party/WebKit/public/web/console_message.mojom";
 import "third_party/WebKit/public/web/worker_content_settings_proxy.mojom";
 import "url/mojo/url.mojom";
@@ -74,7 +74,7 @@
   StartWorker(EmbeddedWorkerStartParams params,
               ServiceWorkerEventDispatcher& dispatcher_request,
               ControllerServiceWorker& controller_request,
-              ServiceWorkerInstalledScriptsInfo? installed_scripts_info,
+              blink.mojom.ServiceWorkerInstalledScriptsInfo? installed_scripts_info,
               associated blink.mojom.ServiceWorkerHost service_worker_host,
               associated EmbeddedWorkerInstanceHost instance_host,
               ServiceWorkerProviderInfoForStartWorker provider_info,
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
index 539f94d..218f6ff 100644
--- a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
+++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -59,7 +59,7 @@
     const EmbeddedWorkerStartParams& params,
     mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
     mojom::ControllerServiceWorkerRequest controller_request,
-    mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
     blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
     mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
     mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -129,7 +129,7 @@
 std::unique_ptr<EmbeddedWorkerInstanceClientImpl::WorkerWrapper>
 EmbeddedWorkerInstanceClientImpl::StartWorkerContext(
     const EmbeddedWorkerStartParams& params,
-    mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
     std::unique_ptr<ServiceWorkerContextClient> context_client,
     blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy,
     service_manager::mojom::InterfaceProviderPtr interface_provider) {
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.h b/content/renderer/service_worker/embedded_worker_instance_client_impl.h
index 12f5eb0f..9403b704 100644
--- a/content/renderer/service_worker/embedded_worker_instance_client_impl.h
+++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.h
@@ -12,6 +12,7 @@
 #include "content/child/scoped_child_process_reference.h"
 #include "content/common/service_worker/embedded_worker.mojom.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
+#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
 #include "third_party/WebKit/public/web/worker_content_settings_proxy.mojom.h"
 
 namespace blink {
@@ -90,7 +91,7 @@
       const EmbeddedWorkerStartParams& params,
       mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
       mojom::ControllerServiceWorkerRequest controller_request,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
       blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -106,7 +107,7 @@
 
   std::unique_ptr<WorkerWrapper> StartWorkerContext(
       const EmbeddedWorkerStartParams& params,
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
       std::unique_ptr<ServiceWorkerContextClient> context_client,
       blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy,
       service_manager::mojom::InterfaceProviderPtr interface_provider);
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc
index 4302774..157340b 100644
--- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc
+++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc
@@ -138,17 +138,17 @@
   Receiver body_;
 };
 
-// Internal lives on the IO thread. This receives mojom::ServiceWorkerScriptInfo
-// for all installed scripts and then starts reading the body and meta data from
-// the browser. This instance will be kept alive as long as the Mojo's
-// connection is established.
-class Internal : public mojom::ServiceWorkerInstalledScriptsManager {
+// Internal lives on the IO thread. This receives
+// blink::mojom::ServiceWorkerScriptInfo for all installed scripts and then
+// starts reading the body and meta data from the browser. This instance will be
+// kept alive as long as the Mojo's connection is established.
+class Internal : public blink::mojom::ServiceWorkerInstalledScriptsManager {
  public:
   // Called on the IO thread.
   // Creates and binds a new Internal instance to |request|.
   static void Create(
       scoped_refptr<ThreadSafeScriptContainer> script_container,
-      mojom::ServiceWorkerInstalledScriptsManagerRequest request) {
+      blink::mojom::ServiceWorkerInstalledScriptsManagerRequest request) {
     mojo::MakeStrongBinding(
         std::make_unique<Internal>(std::move(script_container)),
         std::move(request));
@@ -166,10 +166,10 @@
     script_container_->OnAllDataAddedOnIOThread();
   }
 
-  // Implements mojom::ServiceWorkerInstalledScriptsManager.
+  // Implements blink::mojom::ServiceWorkerInstalledScriptsManager.
   // Called on the IO thread.
   void TransferInstalledScript(
-      mojom::ServiceWorkerScriptInfoPtr script_info) override {
+      blink::mojom::ServiceWorkerScriptInfoPtr script_info) override {
     DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
     GURL script_url = script_info->script_url;
     auto receivers = std::make_unique<BundledReceivers>(
@@ -183,7 +183,7 @@
   }
 
   // Called on the IO thread.
-  void OnScriptReceived(mojom::ServiceWorkerScriptInfoPtr script_info) {
+  void OnScriptReceived(blink::mojom::ServiceWorkerScriptInfoPtr script_info) {
     DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
     const GURL& script_url = script_info->script_url;
     auto iter = running_receivers_.find(script_url);
@@ -221,10 +221,10 @@
 // static
 std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager>
 WebServiceWorkerInstalledScriptsManagerImpl::Create(
-    mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
   auto script_container = base::MakeRefCounted<ThreadSafeScriptContainer>();
-  mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host_ptr(
+  blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host_ptr(
       std::move(installed_scripts_info->manager_host_ptr));
   std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> manager =
       base::WrapUnique<WebServiceWorkerInstalledScriptsManagerImpl>(
@@ -242,12 +242,12 @@
     WebServiceWorkerInstalledScriptsManagerImpl(
         std::vector<GURL>&& installed_urls,
         scoped_refptr<ThreadSafeScriptContainer> script_container,
-        mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host)
+        blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host)
     : installed_urls_(installed_urls.begin(), installed_urls.end()),
       script_container_(std::move(script_container)),
       manager_host_(
-          mojom::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr::Create(
-              std::move(manager_host))) {}
+          blink::mojom::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr::
+              Create(std::move(manager_host))) {}
 
 WebServiceWorkerInstalledScriptsManagerImpl::
     ~WebServiceWorkerInstalledScriptsManagerImpl() = default;
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h
index 2c5f9ca..9df608af 100644
--- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h
+++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h
@@ -8,8 +8,8 @@
 #include <set>
 #include <vector>
 
-#include "content/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
 #include "content/renderer/service_worker/thread_safe_script_container.h"
+#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h"
 
 namespace content {
@@ -19,7 +19,7 @@
  public:
   // Called on the main thread.
   static std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> Create(
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
 
   ~WebServiceWorkerInstalledScriptsManagerImpl() override;
@@ -33,12 +33,13 @@
   WebServiceWorkerInstalledScriptsManagerImpl(
       std::vector<GURL>&& installed_urls,
       scoped_refptr<ThreadSafeScriptContainer> script_container,
-      mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host);
+      blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host);
 
   const std::set<GURL> installed_urls_;
   scoped_refptr<ThreadSafeScriptContainer> script_container_;
 
-  scoped_refptr<mojom::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr>
+  scoped_refptr<
+      blink::mojom::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr>
       manager_host_;
 };
 
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc
index 2d4763f0..5b24150 100644
--- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc
+++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc
@@ -15,17 +15,18 @@
 
 namespace content {
 
-class BrowserSideSender : mojom::ServiceWorkerInstalledScriptsManagerHost {
+class BrowserSideSender
+    : blink::mojom::ServiceWorkerInstalledScriptsManagerHost {
  public:
   BrowserSideSender() : binding_(this) {}
   ~BrowserSideSender() override = default;
 
-  mojom::ServiceWorkerInstalledScriptsInfoPtr CreateAndBind(
+  blink::mojom::ServiceWorkerInstalledScriptsInfoPtr CreateAndBind(
       const std::vector<GURL>& installed_urls) {
     EXPECT_FALSE(manager_.is_bound());
     EXPECT_FALSE(body_handle_.is_valid());
     EXPECT_FALSE(meta_data_handle_.is_valid());
-    auto scripts_info = mojom::ServiceWorkerInstalledScriptsInfo::New();
+    auto scripts_info = blink::mojom::ServiceWorkerInstalledScriptsInfo::New();
     scripts_info->installed_urls = installed_urls;
     scripts_info->manager_request = mojo::MakeRequest(&manager_);
     binding_.Bind(mojo::MakeRequest(&scripts_info->manager_host_ptr));
@@ -37,7 +38,7 @@
                                int64_t meta_data_size) {
     EXPECT_FALSE(body_handle_.is_valid());
     EXPECT_FALSE(meta_data_handle_.is_valid());
-    auto script_info = mojom::ServiceWorkerScriptInfo::New();
+    auto script_info = blink::mojom::ServiceWorkerScriptInfo::New();
     script_info->script_url = script_url;
     EXPECT_EQ(MOJO_RESULT_OK,
               mojo::CreateDataPipe(nullptr, &body_handle_, &script_info->body));
@@ -90,8 +91,9 @@
   base::OnceClosure requested_script_closure_;
   GURL waiting_requested_url_;
 
-  mojom::ServiceWorkerInstalledScriptsManagerPtr manager_;
-  mojo::Binding<mojom::ServiceWorkerInstalledScriptsManagerHost> binding_;
+  blink::mojom::ServiceWorkerInstalledScriptsManagerPtr manager_;
+  mojo::Binding<blink::mojom::ServiceWorkerInstalledScriptsManagerHost>
+      binding_;
 
   mojo::ScopedDataPipeProducerHandle body_handle_;
   mojo::ScopedDataPipeProducerHandle meta_data_handle_;
@@ -124,7 +126,8 @@
   }
 
   void CreateInstalledScriptsManager(
-      mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info) {
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
+          installed_scripts_info) {
     installed_scripts_manager_ =
         WebServiceWorkerInstalledScriptsManagerImpl::Create(
             std::move(installed_scripts_info), io_task_runner_);
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index ebb1c1eb..5bf4aec9f 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -49,8 +49,10 @@
 }
 
 scoped_refptr<gl::GLContext> InitializeGLContext(gl::GLSurface* surface) {
+  gl::GLContextAttribs attribs;
+  attribs.client_major_es_version = 2;
   scoped_refptr<gl::GLContext> context(
-      gl::init::CreateGLContext(nullptr, surface, gl::GLContextAttribs()));
+      gl::init::CreateGLContext(nullptr, surface, attribs));
   if (!context.get()) {
     LOG(ERROR) << "gl::init::CreateGLContext failed";
     return NULL;
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 9671cbf5..35643b7 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2650,8 +2650,6 @@
 
 crbug.com/619427 [ Mac Linux ] fast/overflow/overflow-height-float-not-removed-crash3.html [ Pass Failure ]
 
-crbug.com/667371 http/tests/devtools/elements/styles-1/color-aware-property-value-edit.js [ Pass Failure ]
-
 # [css-ui] Imported tests from W3C suite.
 crbug.com/669473 external/wpt/css/css-ui/box-sizing-014.html [ Failure ]
 crbug.com/669473 external/wpt/css/css-ui/box-sizing-015.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-background-image.https.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-background-image.https.html
index 716c28c..cb894e57 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-background-image.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-background-image.https.html
@@ -43,7 +43,7 @@
         ctx.strokeStyle = 'green';
         if (serializedStrings[0] != "--bar: [null]")
             ctx.strokeStyle = 'red';
-        if (serializedStrings[1] != "--foo: [CSSStyleValue= bar]")
+        if (serializedStrings[1] != "--foo: [CSSUnparsedValue= bar]")
             ctx.strokeStyle = 'blue';
         if (serializedStrings[2] != "align-items: [CSSKeywordValue=normal]")
             ctx.strokeStyle = 'yellow';
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-before-pseudo.https.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-before-pseudo.https.html
index 8ba4cdb..707d02b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-before-pseudo.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-before-pseudo.https.html
@@ -46,7 +46,7 @@
         ctx.strokeStyle = 'green';
         if (serializedStrings[0] != "--bar: [null]")
             ctx.strokeStyle = 'red';
-        if (serializedStrings[1] != "--foo: [CSSStyleValue= bar]")
+        if (serializedStrings[1] != "--foo: [CSSUnparsedValue= bar]")
             ctx.strokeStyle = 'blue';
         if (serializedStrings[2] != "border-radius: [CSSStyleValue=2px]")
             ctx.strokeStyle = 'yellow';
diff --git a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-normalization/normalize-tokens.html b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-normalization/normalize-tokens.html
index 26bbee6..f871699 100644
--- a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-normalization/normalize-tokens.html
+++ b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-normalization/normalize-tokens.html
@@ -8,6 +8,16 @@
 <script>
 'use strict';
 
+function assert_string_normalizes_to(property, str, expected) {
+  // From string
+  assert_style_value_equals(CSSStyleValue.parse(property, str), expected);
+  // From CSSOM
+  assert_style_value_equals(
+    newDivWithStyle(property + ':' + str).attributeStyleMap.get(property),
+    expected
+  );
+}
+
 const gTestCases = [
   {
     value: 'var(--A)',
@@ -40,16 +50,13 @@
 ];
 
 for (const {value, expectedResult} of gTestCases) {
-  // TODO(788570): Add similar tests using a custom property instead of 'color'
   test(() => {
-    const result = CSSStyleValue.parse('color', value);
-    assert_style_value_equals(result, new CSSUnparsedValue(...expectedResult));
-  }, 'Normalizing "' + value + '" from String returns correct CSSUnparsedValue');
+    assert_string_normalizes_to('color', value, new CSSUnparsedValue(...expectedResult));
+  }, 'Normalizing "' + value + '" on a CSS property returns correct CSSUnparsedValue');
 
   test(() => {
-    const result = newDivWithStyle('color:' + value).attributeStyleMap.get('color');
-    assert_style_value_equals(result, new CSSUnparsedValue(...expectedResult));
-  }, 'Normalizing "' + value + '" from CSSOM returns correct CSSUnparsedValue');
+    assert_string_normalizes_to('--X', value, new CSSUnparsedValue(...expectedResult));
+  }, 'Normalizing "' + value + '" on a custom property returns correct CSSUnparsedValue');
 }
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt
deleted file mode 100644
index f5a4c69..0000000
--- a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-This is a testharness.js-based test.
-PASS Calling CSSStyleValue.parse with an empty string throws a TypeError
-PASS Calling CSSStyleValue.parse with an unsupported CSS property throws a TypeError
-PASS Calling CSSStyleValue.parse with a CSS shorthand throws a TypeError
-PASS Calling CSSStyleValue.parse with an invalid cssText for the given property throws a SyntaxError
-PASS Calling CSSStyleValue.parseAll with an empty string throws a TypeError
-PASS Calling CSSStyleValue.parseAll with an unsupported CSS property throws a TypeError
-PASS Calling CSSStyleValue.parseAll with a CSS shorthand throws a TypeError
-PASS Calling CSSStyleValue.parseAll with an invalid cssText for the given property throws a SyntaxError
-PASS Calling CSSStyleValue.parse with a valid cssText for the given property returns a valid CSSStyleValue
-PASS Calling CSSStyleValue.parse with a mixed case cssText returns a valid CSSStyleValue
-FAIL Calling CSSStyleValue.parse with a custom property returns a valid CSSStyleValue Failed to execute 'parse' on 'CSSStyleValue': Invalid property name
-PASS Calling CSSStyleValue.parseAll with a valid cssText for the given property returns a single-element list containing a valid CSSStyleValue
-PASS Calling CSSStyleValue.parseAll with a mixed case cssText returns a single-element list containing a valid CSSStyleValue
-FAIL Calling CSSStyleValue.parseAll with a custom property returns a single-element list containing a valid CSSStyleValue Failed to execute 'parseAll' on 'CSSStyleValue': Invalid property name
-PASS Calling CSSStyleValue.parse with a list-value property returns first list value
-PASS Calling CSSStyleValue.parseAll with a list-value property returns a sequence of values
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll.html b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll.html
index 1a9530e..1137c7c 100644
--- a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll.html
+++ b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll.html
@@ -30,7 +30,7 @@
 const gValidNonListTests = [
   { property: 'width', value: '10px', expected: CSS.px(10), desc: 'a valid cssText for the given property' },
   { property: 'wIdTh', value: '10px', expected: CSS.px(10), desc: 'a mixed case cssText' },
-  { property: '--foo', value: '10%', expected: CSS.percent(10), desc: 'a custom property' },
+  { property: '--foo', value: '10%', expected: new CSSUnparsedValue('10%'), desc: 'a custom property' },
 ];
 
 for (const {property, value, expected, desc} of gValidNonListTests) {
diff --git a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/computed-expected.txt b/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/computed-expected.txt
index a56fe87d..f8c7b866 100644
--- a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/computed-expected.txt
+++ b/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/computed-expected.txt
@@ -1,9 +1,9 @@
 This is a testharness.js-based test.
 FAIL Computed StylePropertyMap contains every CSS property assert_equals: expected 296 but got 294
 PASS Computed StylePropertyMap contains CSS property declarations in style rules
-FAIL Computed StylePropertyMap contains custom property declarations in style rules assert_equals: expected "CSSUnparsedValue" but got "CSSStyleValue"
+PASS Computed StylePropertyMap contains custom property declarations in style rules
 PASS Computed StylePropertyMap contains CSS property declarations in inline styles
-FAIL Computed StylePropertyMap contains custom property declarations in inline rules assert_equals: expected "CSSUnparsedValue" but got "CSSStyleValue"
+PASS Computed StylePropertyMap contains custom property declarations in inline rules
 PASS Computed StylePropertyMap contains computed values and not resolved values
 PASS Computed StylePropertyMap is live
 Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/get-expected.txt b/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/get-expected.txt
deleted file mode 100644
index ad36f65..0000000
--- a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/get-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This is a testharness.js-based test.
-PASS Calling StylePropertyMap.get with an unsupported property throws a TypeError
-PASS Calling StylePropertyMap.get with a property not in the property model returns null
-PASS Calling StylePropertyMap.get with a custom property not in the property model returns null
-PASS Calling StylePropertyMap.get with a valid property returns the correct entry
-PASS StylePropertyMap.get with a valid property in mixed case returns the correct entry
-FAIL Calling StylePropertyMap.get with a valid custom property returns the correct entry assert_equals: expected "CSSUnparsedValue" but got "CSSStyleValue"
-PASS Calling StylePropertyMap.get with a list-valued property returns only the first value
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/getAll-expected.txt b/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/getAll-expected.txt
deleted file mode 100644
index 12e37b5..0000000
--- a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/getAll-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This is a testharness.js-based test.
-PASS Calling StylePropertyMap.getAll with an unsupported property throws a TypeError
-PASS Calling StylePropertyMap.getAll with a property not in the property model returns an empty list
-PASS Calling StylePropertyMap.getAll with a custom property not in the property model returns an empty list
-PASS Calling StylePropertyMap.getAll with a valid property returns a single element list with the correct entry
-PASS StylePropertyMap.getAll is case-insensitive
-FAIL Calling StylePropertyMap.getAll with a valid custom property returns a single element list with the correct entry assert_equals: expected "CSSUnparsedValue" but got "CSSStyleValue"
-PASS Calling StylePropertyMap.getAll with a list-valued property returns all the values
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.cpp.tmpl
index 189bab14..cebd271 100644
--- a/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.cpp.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.cpp.tmpl
@@ -228,7 +228,7 @@
 
 {% macro apply_fill_layer(property_id, fill_type, fill_type_getter = None) %}
 {% set layer_type = 'Background' if 'Background' in property_id else 'Mask' %}
-{% set fill_layer_type = 'k' + layer_type + 'FillLayer' %}
+{% set fill_layer_type = 'EFillLayerType::k' + layer_type %}
 {% set access_layers = 'Access' + layer_type + 'Layers' %}
 {% set map_fill = 'MapFill' + fill_type %}
 {% set fill_type_getter = fill_type_getter or fill_type %}
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
index ff6e5f31..33a0446 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -410,13 +410,13 @@
 inline CSSIdentifierValue::CSSIdentifierValue(EFillAttachment e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
-    case kScrollBackgroundAttachment:
+    case EFillAttachment::kScroll:
       value_id_ = CSSValueScroll;
       break;
-    case kLocalBackgroundAttachment:
+    case EFillAttachment::kLocal:
       value_id_ = CSSValueLocal;
       break;
-    case kFixedBackgroundAttachment:
+    case EFillAttachment::kFixed:
       value_id_ = CSSValueFixed;
       break;
   }
@@ -426,33 +426,33 @@
 inline EFillAttachment CSSIdentifierValue::ConvertTo() const {
   switch (value_id_) {
     case CSSValueScroll:
-      return kScrollBackgroundAttachment;
+      return EFillAttachment::kScroll;
     case CSSValueLocal:
-      return kLocalBackgroundAttachment;
+      return EFillAttachment::kLocal;
     case CSSValueFixed:
-      return kFixedBackgroundAttachment;
+      return EFillAttachment::kFixed;
     default:
       break;
   }
 
   NOTREACHED();
-  return kScrollBackgroundAttachment;
+  return EFillAttachment::kScroll;
 }
 
 template <>
 inline CSSIdentifierValue::CSSIdentifierValue(EFillBox e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
-    case kBorderFillBox:
+    case EFillBox::kBorder:
       value_id_ = CSSValueBorderBox;
       break;
-    case kPaddingFillBox:
+    case EFillBox::kPadding:
       value_id_ = CSSValuePaddingBox;
       break;
-    case kContentFillBox:
+    case EFillBox::kContent:
       value_id_ = CSSValueContentBox;
       break;
-    case kTextFillBox:
+    case EFillBox::kText:
       value_id_ = CSSValueText;
       break;
   }
@@ -463,37 +463,37 @@
   switch (value_id_) {
     case CSSValueBorder:
     case CSSValueBorderBox:
-      return kBorderFillBox;
+      return EFillBox::kBorder;
     case CSSValuePadding:
     case CSSValuePaddingBox:
-      return kPaddingFillBox;
+      return EFillBox::kPadding;
     case CSSValueContent:
     case CSSValueContentBox:
-      return kContentFillBox;
+      return EFillBox::kContent;
     case CSSValueText:
-      return kTextFillBox;
+      return EFillBox::kText;
     default:
       break;
   }
 
   NOTREACHED();
-  return kBorderFillBox;
+  return EFillBox::kBorder;
 }
 
 template <>
 inline CSSIdentifierValue::CSSIdentifierValue(EFillRepeat e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
-    case kRepeatFill:
+    case EFillRepeat::kRepeatFill:
       value_id_ = CSSValueRepeat;
       break;
-    case kNoRepeatFill:
+    case EFillRepeat::kNoRepeatFill:
       value_id_ = CSSValueNoRepeat;
       break;
-    case kRoundFill:
+    case EFillRepeat::kRoundFill:
       value_id_ = CSSValueRound;
       break;
-    case kSpaceFill:
+    case EFillRepeat::kSpaceFill:
       value_id_ = CSSValueSpace;
       break;
   }
@@ -503,19 +503,19 @@
 inline EFillRepeat CSSIdentifierValue::ConvertTo() const {
   switch (value_id_) {
     case CSSValueRepeat:
-      return kRepeatFill;
+      return EFillRepeat::kRepeatFill;
     case CSSValueNoRepeat:
-      return kNoRepeatFill;
+      return EFillRepeat::kNoRepeatFill;
     case CSSValueRound:
-      return kRoundFill;
+      return EFillRepeat::kRoundFill;
     case CSSValueSpace:
-      return kSpaceFill;
+      return EFillRepeat::kSpaceFill;
     default:
       break;
   }
 
   NOTREACHED();
-  return kRepeatFill;
+  return EFillRepeat::kRepeatFill;
 }
 
 template <>
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index 2cd78225..c34221e 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -162,9 +162,11 @@
   // return the shorthand.
   if (x_repeat == y_repeat)
     return CSSIdentifierValue::Create(x_repeat);
-  if (x_repeat == kRepeatFill && y_repeat == kNoRepeatFill)
+  if (x_repeat == EFillRepeat::kRepeatFill &&
+      y_repeat == EFillRepeat::kNoRepeatFill)
     return CSSIdentifierValue::Create(CSSValueRepeatX);
-  if (x_repeat == kNoRepeatFill && y_repeat == kRepeatFill)
+  if (x_repeat == EFillRepeat::kNoRepeatFill &&
+      y_repeat == EFillRepeat::kRepeatFill)
     return CSSIdentifierValue::Create(CSSValueRepeatY);
 
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5 b/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5
index 9c232491..196cdf3 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5
+++ b/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5
@@ -224,7 +224,7 @@
       field_template: "external",
       include_paths: ["core/style/FillLayer.h"],
       type_name: "FillLayer",
-      default_value: "FillLayer(kBackgroundFillLayer, true)",
+      default_value: "FillLayer(EFillLayerType::kBackground, true)",
       field_group: "background",
       computed_style_custom_functions: ["getter", "setter"],
     },
@@ -559,7 +559,7 @@
       field_template: "external",
       type_name: "FillLayer",
       field_group: "*",
-      default_value: "FillLayer(kMaskFillLayer, true)",
+      default_value: "FillLayer(EFillLayerType::kMask, true)",
       computed_style_custom_functions: ["getter", "setter"],
     },
     {
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
index a1a5842..dd2d548 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
@@ -23,8 +23,7 @@
     ExceptionState& exception_state) {
   const CSSPropertyID property_id = cssPropertyID(property_name);
 
-  // TODO(775804): Handle custom properties
-  if (property_id == CSSPropertyInvalid || property_id == CSSPropertyVariable) {
+  if (property_id == CSSPropertyInvalid) {
     exception_state.ThrowTypeError("Invalid property name");
     return CSSStyleValueVector();
   }
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
index 50390e0..daf1c319 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
@@ -4,6 +4,8 @@
 
 #include "core/css/cssom/CSSUnparsedValue.h"
 
+#include "core/css/CSSVariableData.h"
+#include "core/css/CSSVariableReferenceValue.h"
 #include "core/css/cssom/CSSStyleVariableReferenceValue.h"
 #include "core/css/parser/CSSTokenizer.h"
 #include "platform/wtf/text/StringBuilder.h"
@@ -65,9 +67,13 @@
 }  // namespace
 
 CSSUnparsedValue* CSSUnparsedValue::FromCSSValue(
-    const CSSVariableReferenceValue& css_variable_reference_value) {
-  return CSSUnparsedValue::Create(ParserTokenRangeToTokens(
-      css_variable_reference_value.VariableDataValue()->TokenRange()));
+    const CSSVariableReferenceValue& value) {
+  DCHECK(value.VariableDataValue());
+  return FromCSSValue(*value.VariableDataValue());
+}
+
+CSSUnparsedValue* CSSUnparsedValue::FromCSSValue(const CSSVariableData& value) {
+  return CSSUnparsedValue::Create(ParserTokenRangeToTokens(value.TokenRange()));
 }
 
 const CSSValue* CSSUnparsedValue::ToCSSValue(
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
index ac9cb1f0..c3a9f22 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
@@ -7,12 +7,14 @@
 
 #include "base/macros.h"
 #include "bindings/core/v8/string_or_css_variable_reference_value.h"
-#include "core/css/CSSVariableReferenceValue.h"
 #include "core/css/cssom/CSSStyleValue.h"
 #include "platform/wtf/Vector.h"
 
 namespace blink {
 
+class CSSVariableReferenceValue;
+class CSSVariableData;
+
 class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
   DEFINE_WRAPPERTYPEINFO();
 
@@ -23,6 +25,7 @@
   }
 
   static CSSUnparsedValue* FromCSSValue(const CSSVariableReferenceValue&);
+  static CSSUnparsedValue* FromCSSValue(const CSSVariableData&);
 
   const CSSValue* ToCSSValue(SecureContextMode) const override;
 
diff --git a/third_party/WebKit/Source/core/css/cssom/StyleValueFactory.cpp b/third_party/WebKit/Source/core/css/cssom/StyleValueFactory.cpp
index ea86274..30d38a0 100644
--- a/third_party/WebKit/Source/core/css/cssom/StyleValueFactory.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/StyleValueFactory.cpp
@@ -4,8 +4,10 @@
 
 #include "core/css/cssom/StyleValueFactory.h"
 
+#include "core/css/CSSCustomPropertyDeclaration.h"
 #include "core/css/CSSImageValue.h"
 #include "core/css/CSSValue.h"
+#include "core/css/CSSVariableReferenceValue.h"
 #include "core/css/cssom/CSSKeywordValue.h"
 #include "core/css/cssom/CSSNumericValue.h"
 #include "core/css/cssom/CSSOMTypes.h"
@@ -44,6 +46,12 @@
     return CSSNumericValue::FromCSSValue(ToCSSPrimitiveValue(value));
   if (value.IsVariableReferenceValue())
     return CSSUnparsedValue::FromCSSValue(ToCSSVariableReferenceValue(value));
+  if (value.IsCustomPropertyDeclaration()) {
+    const CSSVariableData* variable_data =
+        ToCSSCustomPropertyDeclaration(value).Value();
+    DCHECK(variable_data);
+    return CSSUnparsedValue::FromCSSValue(*variable_data);
+  }
   if (value.IsImageValue()) {
     return CSSURLImageValue::Create(ToCSSImageValue(value).Clone());
   }
@@ -73,12 +81,15 @@
   const auto tokens = tokenizer.TokenizeToEOF();
   const CSSParserTokenRange range(tokens);
 
-  if (const CSSValue* value =
-          CSSPropertyParser::ParseSingleValue(property_id, range, context)) {
-    return value;
+  if (property_id != CSSPropertyVariable) {
+    if (const CSSValue* value =
+            CSSPropertyParser::ParseSingleValue(property_id, range, context)) {
+      return value;
+    }
   }
 
-  if (CSSVariableParser::ContainsValidVariableReferences(range)) {
+  if (property_id == CSSPropertyVariable ||
+      CSSVariableParser::ContainsValidVariableReferences(range)) {
     return CSSVariableReferenceValue::Create(
         CSSVariableData::Create(range, false /* is_animation_tainted */,
                                 false /* needs variable resolution */),
@@ -97,11 +108,6 @@
   DCHECK_NE(property_id, CSSPropertyInvalid);
   DCHECK(!CSSProperty::Get(property_id).IsShorthand());
 
-  // TODO(775804): Handle custom properties
-  if (property_id == CSSPropertyVariable) {
-    return CSSStyleValueVector();
-  }
-
   const CSSValue* value = ParseProperty(property_id, css_text, parser_context);
   if (!value)
     return CSSStyleValueVector();
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.cpp b/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.cpp
index 22c45a8..9873293 100644
--- a/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.cpp
@@ -61,13 +61,13 @@
   const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
   switch (identifier_value.GetValueID()) {
     case CSSValueFixed:
-      layer->SetAttachment(kFixedBackgroundAttachment);
+      layer->SetAttachment(EFillAttachment::kFixed);
       break;
     case CSSValueScroll:
-      layer->SetAttachment(kScrollBackgroundAttachment);
+      layer->SetAttachment(EFillAttachment::kScroll);
       break;
     case CSSValueLocal:
-      layer->SetAttachment(kLocalBackgroundAttachment);
+      layer->SetAttachment(EFillAttachment::kLocal);
       break;
     default:
       return;
@@ -142,7 +142,7 @@
     return;
   }
 
-  CSSPropertyID property = layer->GetType() == kBackgroundFillLayer
+  CSSPropertyID property = layer->GetType() == EFillLayerType::kBackground
                                ? CSSPropertyBackgroundImage
                                : CSSPropertyWebkitMaskImage;
   layer->SetImage(state.GetStyleImage(property, value));
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index 0396f82..7c72279b 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -1904,10 +1904,10 @@
   FillLayer old_fill = cached_ua_style->background_layers;
   FillLayer new_fill = state.Style()->BackgroundLayers();
   // Exclude background-repeat from comparison by resetting it.
-  old_fill.SetRepeatX(kNoRepeatFill);
-  old_fill.SetRepeatY(kNoRepeatFill);
-  new_fill.SetRepeatX(kNoRepeatFill);
-  new_fill.SetRepeatY(kNoRepeatFill);
+  old_fill.SetRepeatX(EFillRepeat::kNoRepeatFill);
+  old_fill.SetRepeatY(EFillRepeat::kNoRepeatFill);
+  new_fill.SetRepeatX(EFillRepeat::kNoRepeatFill);
+  new_fill.SetRepeatY(EFillRepeat::kNoRepeatFill);
 
   return (old_fill != new_fill || cached_ua_style->background_color !=
                                       state.Style()->BackgroundColor());
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index f3c2f14..3c2fbd1 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -1969,13 +1969,13 @@
     // http://www.w3.org/TR/css3-background/#root-background
     // The root element background always have painting area of the whole
     // canvas.
-    current_layer->SetClip(kBorderFillBox);
+    current_layer->SetClip(EFillBox::kBorder);
 
     // The root element doesn't scroll. It always propagates its layout overflow
     // to the viewport. Positioning background against either box is equivalent
     // to positioning against the scrolled box of the viewport.
-    if (current_layer->Attachment() == kScrollBackgroundAttachment)
-      current_layer->SetAttachment(kLocalBackgroundAttachment);
+    if (current_layer->Attachment() == EFillAttachment::kScroll)
+      current_layer->SetAttachment(EFillAttachment::kLocal);
   }
   EImageRendering image_rendering = background_style->ImageRendering();
 
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
index d62a3dc..159c62a 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -338,14 +338,7 @@
       CompositionType() == kTextCompositionUpdate ? selection_start : end;
   const SelectionInDOMTree& selection =
       CreateSelection(start, end, EndingSelection().IsDirectional(), element);
-
-  if (selection == frame->Selection()
-                       .ComputeVisibleSelectionInDOMTreeDeprecated()
-                       .AsSelection())
-    return;
-
   SetEndingSelection(SelectionForUndoStep::From(selection));
-  frame->Selection().SetSelection(selection);
 }
 
 // FIXME: We shouldn't need to take selectionForInsertion. It should be
diff --git a/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
index a7090fb..0a056ab 100644
--- a/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
@@ -37,6 +37,7 @@
 #include "core/editing/SelectionTemplate.h"
 #include "core/editing/SetSelectionOptions.h"
 #include "core/editing/commands/TypingCommand.h"
+#include "core/editing/commands/UndoStack.h"
 #include "core/editing/markers/DocumentMarkerController.h"
 #include "core/editing/markers/SuggestionMarkerProperties.h"
 #include "core/editing/spellcheck/SpellChecker.h"
@@ -732,15 +733,26 @@
   // needs to be audited. see http://crbug.com/590369 for more details.
   GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
 
+  // The undo stack could become empty if a JavaScript event handler calls
+  // execCommand('undo') to pop elements off the stack. Or, the top element of
+  // the stack could end up not corresponding to the TypingCommand. Make sure we
+  // don't crash in these cases (it's unclear what the composition range should
+  // be set to in these cases, so we don't worry too much about that).
+  SelectionInDOMTree selection;
+  if (GetEditor().GetUndoStack().CanUndo()) {
+    const UndoStep* undo_step = *GetEditor().GetUndoStack().UndoSteps().begin();
+    const SelectionForUndoStep& undo_selection = undo_step->EndingSelection();
+    if (undo_selection.IsValidFor(GetDocument()))
+      selection = undo_selection.AsSelection();
+  }
+
   // Find out what node has the composition now.
-  Position base = MostForwardCaretPosition(
-      GetFrame().Selection().ComputeVisibleSelectionInDOMTree().Base());
+  const Position base = MostForwardCaretPosition(selection.Base());
   Node* base_node = base.AnchorNode();
   if (!base_node || !base_node->IsTextNode())
     return;
 
-  Position extent =
-      GetFrame().Selection().ComputeVisibleSelectionInDOMTree().Extent();
+  const Position extent = selection.Extent();
   Node* extent_node = extent.AnchorNode();
 
   unsigned extent_offset = extent.ComputeOffsetInContainerNode();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
index f302785..69bc575 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -42,6 +42,7 @@
 #include "core/css/CSSStyleRule.h"
 #include "core/css/CSSStyleSheet.h"
 #include "core/css/CSSVariableData.h"
+#include "core/css/FontSizeFunctions.h"
 #include "core/css/MediaList.h"
 #include "core/css/MediaQuery.h"
 #include "core/css/MediaValues.h"
@@ -2321,7 +2322,21 @@
       CSSComputedStyleDeclaration::Create(body, true);
   const CSSValue* body_font_size =
       computed_style_body->GetPropertyCSSValue(GetCSSPropertyFontSize());
-  *computed_body_font_size = body_font_size->CssText();
+  if (body_font_size) {
+    *computed_body_font_size = body_font_size->CssText();
+  } else {
+    // This is an extremely rare and pathological case -
+    // just return the baseline default to avoid a crash.
+    // crbug.com/738777
+    unsigned default_font_size_keyword =
+        FontSizeFunctions::InitialKeywordSize();
+    float default_font_size_pixels = FontSizeFunctions::FontSizeForKeyword(
+        &document, default_font_size_keyword, false);
+    *computed_body_font_size =
+        CSSPrimitiveValue::Create(default_font_size_pixels,
+                                  CSSPrimitiveValue::UnitType::kPixels)
+            ->CssText();
+  }
 
   return Response::OK();
 }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 2d41658d..ac3a63a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -912,7 +912,7 @@
 }
 
 LayoutRect LayoutBox::BackgroundRect(BackgroundRectType rect_type) const {
-  EFillBox background_box = kTextFillBox;
+  EFillBox background_box = EFillBox::kText;
   // Find the largest background rect of the given opaqueness.
   if (const FillLayer* current = &(Style()->BackgroundLayers())) {
     do {
@@ -926,8 +926,10 @@
         bool layer_known_opaque = false;
         // Check if the image is opaque and fills the clip.
         if (const StyleImage* image = cur->GetImage()) {
-          if ((cur->RepeatX() == kRepeatFill || cur->RepeatX() == kRoundFill) &&
-              (cur->RepeatY() == kRepeatFill || cur->RepeatY() == kRoundFill) &&
+          if ((cur->RepeatX() == EFillRepeat::kRepeatFill ||
+               cur->RepeatX() == EFillRepeat::kRoundFill) &&
+              (cur->RepeatY() == EFillRepeat::kRepeatFill ||
+               cur->RepeatY() == EFillRepeat::kRoundFill) &&
               image->KnownToBeOpaque(GetDocument(), StyleRef())) {
             layer_known_opaque = true;
           }
@@ -946,28 +948,29 @@
       }
       EFillBox current_clip = cur->Clip();
       // Restrict clip if attachment is local.
-      if (current_clip == kBorderFillBox &&
-          cur->Attachment() == kLocalBackgroundAttachment)
-        current_clip = kPaddingFillBox;
+      if (current_clip == EFillBox::kBorder &&
+          cur->Attachment() == EFillAttachment::kLocal)
+        current_clip = EFillBox::kPadding;
 
       // If we're asking for the clip rect, a content-box clipped fill layer can
       // be scrolled into the padding box of the overflow container.
-      if (rect_type == kBackgroundClipRect && current_clip == kContentFillBox &&
-          cur->Attachment() == kLocalBackgroundAttachment) {
-        current_clip = kPaddingFillBox;
+      if (rect_type == kBackgroundClipRect &&
+          current_clip == EFillBox::kContent &&
+          cur->Attachment() == EFillAttachment::kLocal) {
+        current_clip = EFillBox::kPadding;
       }
 
       background_box = EnclosingFillBox(background_box, current_clip);
     } while (current);
   }
   switch (background_box) {
-    case kBorderFillBox:
+    case EFillBox::kBorder:
       return BorderBoxRect();
       break;
-    case kPaddingFillBox:
+    case EFillBox::kPadding:
       return PaddingBoxRect();
       break;
-    case kContentFillBox:
+    case EFillBox::kContent:
       return ContentBoxRect();
       break;
     default:
@@ -5708,7 +5711,8 @@
   if (!img || !img->CanRender())
     return false;
 
-  if (layer.RepeatY() != kRepeatFill && layer.RepeatY() != kNoRepeatFill)
+  if (layer.RepeatY() != EFillRepeat::kRepeatFill &&
+      layer.RepeatY() != EFillRepeat::kNoRepeatFill)
     return true;
 
   // TODO(alancutter): Make this work correctly for calc lengths.
@@ -5748,7 +5752,8 @@
   if (!img || !img->CanRender())
     return false;
 
-  if (layer.RepeatX() != kRepeatFill && layer.RepeatX() != kNoRepeatFill)
+  if (layer.RepeatX() != EFillRepeat::kRepeatFill &&
+      layer.RepeatX() != EFillRepeat::kNoRepeatFill)
     return true;
 
   // TODO(alancutter): Make this work correctly for calc lengths.
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
index 36cb4b6..84d0be0 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -151,7 +151,7 @@
   BackgroundPaintLocation paint_location = kBackgroundPaintInScrollingContents;
   const FillLayer* layer = &(Style()->BackgroundLayers());
   for (; layer; layer = layer->Next()) {
-    if (layer->Attachment() == kLocalBackgroundAttachment)
+    if (layer->Attachment() == EFillAttachment::kLocal)
       continue;
 
     // Solid color layers with an effective background clip of the padding box
@@ -159,11 +159,11 @@
     if (!layer->GetImage() && !layer->Next() &&
         ResolveColor(CSSPropertyBackgroundColor).Alpha() > 0) {
       EFillBox clip = layer->Clip();
-      if (clip == kPaddingFillBox)
+      if (clip == EFillBox::kPadding)
         continue;
       // A border box can be treated as a padding box if the border is opaque or
       // there is no border and we don't have custom scrollbars.
-      if (clip == kBorderFillBox) {
+      if (clip == EFillBox::kBorder) {
         if (!has_custom_scrollbars &&
             (Style()->BorderTopWidth() == 0 ||
              !ResolveColor(CSSPropertyBorderTopColor).HasAlpha()) &&
@@ -186,7 +186,7 @@
       }
       // A content fill box can be treated as a padding fill box if there is no
       // padding.
-      if (clip == kContentFillBox && Style()->PaddingTop().IsZero() &&
+      if (clip == EFillBox::kContent && Style()->PaddingTop().IsZero() &&
           Style()->PaddingLeft().IsZero() && Style()->PaddingRight().IsZero() &&
           Style()->PaddingBottom().IsZero()) {
         continue;
diff --git a/third_party/WebKit/Source/core/layout/LayoutImage.cpp b/third_party/WebKit/Source/core/layout/LayoutImage.cpp
index afd0126..3e0cc70 100644
--- a/third_party/WebKit/Source/core/layout/LayoutImage.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutImage.cpp
@@ -230,12 +230,12 @@
     return false;
   EFillBox background_clip = Style()->BackgroundClip();
   // Background paints under borders.
-  if (background_clip == kBorderFillBox && Style()->HasBorder() &&
+  if (background_clip == EFillBox::kBorder && Style()->HasBorder() &&
       !Style()->BorderObscuresBackground())
     return false;
   // Background shows in padding area.
-  if ((background_clip == kBorderFillBox ||
-       background_clip == kPaddingFillBox) &&
+  if ((background_clip == EFillBox::kBorder ||
+       background_clip == EFillBox::kPadding) &&
       Style()->HasPadding())
     return false;
   // Object-position may leave parts of the content box empty, regardless of the
diff --git a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
index 2b1fd2f..e517e8e 100644
--- a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
+++ b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
@@ -423,7 +423,7 @@
     // on scroll of a page that has fixed background images.
     return false;
   }
-  return fill_layer.Attachment() == kFixedBackgroundAttachment;
+  return fill_layer.Attachment() == EFillAttachment::kFixed;
 }
 
 LayoutRect FixedAttachmentPositioningArea(const LayoutBoxModelObject& obj,
@@ -521,9 +521,9 @@
       positioning_area.SetSize(positioning_size_override_);
     else
       positioning_area = paint_rect;
-    if (fill_layer.Origin() != kBorderFillBox) {
+    if (fill_layer.Origin() != EFillBox::kBorder) {
       box_outset = positioning_box_.BorderBoxOutsets();
-      if (fill_layer.Origin() == kContentFillBox)
+      if (fill_layer.Origin() == EFillBox::kContent)
         box_outset += positioning_box_.PaddingOutsets();
     }
     positioning_area.Contract(box_outset);
@@ -565,7 +565,7 @@
   LayoutUnit computed_x_position =
       RoundedMinimumValueForLength(fill_layer.XPosition(), available_width) -
       offset_in_background_.X();
-  if (background_repeat_x == kRoundFill &&
+  if (background_repeat_x == EFillRepeat::kRoundFill &&
       positioning_area_size.Width() > LayoutUnit() &&
       fill_tile_size.Width() > LayoutUnit()) {
     int nr_tiles = std::max(
@@ -574,7 +574,7 @@
 
     // Maintain aspect ratio if background-size: auto is set
     if (fill_layer.Size().size.Height().IsAuto() &&
-        background_repeat_y != kRoundFill) {
+        background_repeat_y != EFillRepeat::kRoundFill) {
       fill_tile_size.SetHeight(fill_tile_size.Height() * rounded_width /
                                fill_tile_size.Width());
     }
@@ -594,7 +594,7 @@
   LayoutUnit computed_y_position =
       RoundedMinimumValueForLength(fill_layer.YPosition(), available_height) -
       offset_in_background_.Y();
-  if (background_repeat_y == kRoundFill &&
+  if (background_repeat_y == EFillRepeat::kRoundFill &&
       positioning_area_size.Height() > LayoutUnit() &&
       fill_tile_size.Height() > LayoutUnit()) {
     int nr_tiles = std::max(1, RoundToInt(positioning_area_size.Height() /
@@ -602,7 +602,7 @@
     LayoutUnit rounded_height = positioning_area_size.Height() / nr_tiles;
     // Maintain aspect ratio if background-size: auto is set
     if (fill_layer.Size().size.Width().IsAuto() &&
-        background_repeat_x != kRoundFill) {
+        background_repeat_x != EFillRepeat::kRoundFill) {
       fill_tile_size.SetWidth(fill_tile_size.Width() * rounded_height /
                               fill_tile_size.Height());
     }
@@ -619,20 +619,20 @@
     SetSpaceSize(LayoutSize());
   }
 
-  if (background_repeat_x == kRepeatFill) {
+  if (background_repeat_x == EFillRepeat::kRepeatFill) {
     SetRepeatX(fill_layer, fill_tile_size.Width(), available_width,
                unsnapped_available_width, box_outset.Left(),
                offset_in_background_.X());
-  } else if (background_repeat_x == kSpaceFill &&
+  } else if (background_repeat_x == EFillRepeat::kSpaceFill &&
              TileSize().Width() > LayoutUnit()) {
     LayoutUnit space = GetSpaceBetweenImageTiles(positioning_area_size.Width(),
                                                  TileSize().Width());
     if (space >= LayoutUnit())
       SetSpaceX(space, available_width, box_outset.Left());
     else
-      background_repeat_x = kNoRepeatFill;
+      background_repeat_x = EFillRepeat::kNoRepeatFill;
   }
-  if (background_repeat_x == kNoRepeatFill) {
+  if (background_repeat_x == EFillRepeat::kNoRepeatFill) {
     LayoutUnit x_offset = fill_layer.BackgroundXOrigin() == kRightEdge
                               ? available_width - computed_x_position
                               : computed_x_position;
@@ -641,20 +641,20 @@
       SetDestRect(LayoutRect());
   }
 
-  if (background_repeat_y == kRepeatFill) {
+  if (background_repeat_y == EFillRepeat::kRepeatFill) {
     SetRepeatY(fill_layer, fill_tile_size.Height(), available_height,
                unsnapped_available_height, box_outset.Top(),
                offset_in_background_.Y());
-  } else if (background_repeat_y == kSpaceFill &&
+  } else if (background_repeat_y == EFillRepeat::kSpaceFill &&
              TileSize().Height() > LayoutUnit()) {
     LayoutUnit space = GetSpaceBetweenImageTiles(positioning_area_size.Height(),
                                                  TileSize().Height());
     if (space >= LayoutUnit())
       SetSpaceY(space, available_height, box_outset.Top());
     else
-      background_repeat_y = kNoRepeatFill;
+      background_repeat_y = EFillRepeat::kNoRepeatFill;
   }
-  if (background_repeat_y == kNoRepeatFill) {
+  if (background_repeat_y == EFillRepeat::kNoRepeatFill) {
     LayoutUnit y_offset = fill_layer.BackgroundYOrigin() == kBottomEdge
                               ? available_height - computed_y_position
                               : computed_y_position;
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
index 0520504..9cf6418d 100644
--- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
@@ -200,8 +200,9 @@
     // that fully covers the overflow area.
     // TODO(pdr): Check all background layers instead of skipping this if there
     // are multiple backgrounds.
-    if (layers.Next() || layers.GetImage() || layers.RepeatX() != kRepeatFill ||
-        layers.RepeatY() != kRepeatFill)
+    if (layers.Next() || layers.GetImage() ||
+        layers.RepeatX() != EFillRepeat::kRepeatFill ||
+        layers.RepeatY() != EFillRepeat::kRepeatFill)
       return true;
   }
 
diff --git a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
index 3888163..ab75f2e 100644
--- a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
@@ -259,7 +259,7 @@
     // empty.  This occlusion check can be wrong.
     if (current_layer->ClipOccludesNextLayers() &&
         current_layer->ImageOccludesNextLayers(*document_, style_)) {
-      if (current_layer->Clip() == kBorderFillBox)
+      if (current_layer->Clip() == EFillBox::kBorder)
         is_non_associative = false;
       break;
     }
@@ -325,10 +325,9 @@
       include_left_edge(include_left),
       include_right_edge(include_right),
       is_bottom_layer(!layer.Next()),
-      is_border_fill(layer.Clip() == kBorderFillBox),
-      is_clipped_with_local_scrolling(has_overflow_clip &&
-                                      layer.Attachment() ==
-                                          kLocalBackgroundAttachment) {
+      is_border_fill(layer.Clip() == EFillBox::kBorder),
+      is_clipped_with_local_scrolling(
+          has_overflow_clip && layer.Attachment() == EFillAttachment::kLocal) {
   // When printing backgrounds is disabled or using economy mode,
   // change existing background colors and images to a solid white background.
   // If there's no bg color or image, leave it untouched to avoid affecting
@@ -569,7 +568,7 @@
     clip_to_border.emplace(display_item_, paint_info, rect, border_rect,
                            kApplyToContext);
   }
-  if (bg_layer.Clip() == kTextFillBox) {
+  if (bg_layer.Clip() == EFillBox::kText) {
     PaintFillLayerTextFillBox(context, info, image.get(), composite_op,
                               geometry, rect, scrolled_paint_rect);
     return;
@@ -577,24 +576,24 @@
 
   GraphicsContextStateSaver background_clip_state_saver(context, false);
   switch (bg_layer.Clip()) {
-    case kPaddingFillBox:
-    case kContentFillBox: {
+    case EFillBox::kPadding:
+    case EFillBox::kContent: {
       if (info.is_rounded_fill)
         break;
 
       // Clip to the padding or content boxes as necessary.
       LayoutRect clip_rect = scrolled_paint_rect;
       clip_rect.Contract(BorderOutsets(info));
-      if (bg_layer.Clip() == kContentFillBox)
+      if (bg_layer.Clip() == EFillBox::kContent)
         clip_rect.Contract(PaddingOutsets(info));
       background_clip_state_saver.Save();
       // TODO(chrishtr): this should be pixel-snapped.
       context.Clip(FloatRect(clip_rect));
       break;
     }
-    case kBorderFillBox:
+    case EFillBox::kBorder:
       break;
-    case kTextFillBox:  // fall through
+    case EFillBox::kText:  // fall through
     default:
       NOTREACHED();
       break;
@@ -622,11 +621,11 @@
                                      info.include_right_edge);
 
   // Clip to the padding or content boxes as necessary.
-  if (bg_layer.Clip() == kContentFillBox) {
+  if (bg_layer.Clip() == EFillBox::kContent) {
     border = style_.GetRoundedInnerBorderFor(
         LayoutRect(border.Rect()), border_padding_insets,
         info.include_left_edge, info.include_right_edge);
-  } else if (bg_layer.Clip() == kPaddingFillBox) {
+  } else if (bg_layer.Clip() == EFillBox::kPadding) {
     border = style_.GetRoundedInnerBorderFor(LayoutRect(border.Rect()),
                                              info.include_left_edge,
                                              info.include_right_edge);
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index 96904eb..e67ce6e 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -498,7 +498,7 @@
     // TODO(pdr): This invalidation can be removed if the local background
     // attachment is painted into the scrolling contents.
     if (ScrollsOverflow() && Box().Style()->BackgroundLayers().Attachment() ==
-                                 kLocalBackgroundAttachment) {
+                                 EFillAttachment::kLocal) {
       Box().SetShouldDoFullPaintInvalidation();
       return;
     }
@@ -535,7 +535,7 @@
     bool only_scrolled_composited_layers =
         ScrollsOverflow() && Layer()->IsAllScrollingContentComposited() &&
         Box().Style()->BackgroundLayers().Attachment() !=
-            kLocalBackgroundAttachment;
+            EFillAttachment::kLocal;
 
     if (UsesCompositedScrolling() || only_scrolled_composited_layers)
       requires_paint_invalidation = false;
diff --git a/third_party/WebKit/Source/core/paint/ViewPainter.cpp b/third_party/WebKit/Source/core/paint/ViewPainter.cpp
index 7a29001c..9dff754 100644
--- a/third_party/WebKit/Source/core/paint/ViewPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ViewPainter.cpp
@@ -234,10 +234,10 @@
   BoxModelObjectPainter box_model_painter(layout_view_);
   for (auto it = reversed_paint_list.rbegin(); it != reversed_paint_list.rend();
        ++it) {
-    DCHECK((*it)->Clip() == kBorderFillBox);
+    DCHECK((*it)->Clip() == EFillBox::kBorder);
 
     bool should_paint_in_viewport_space =
-        (*it)->Attachment() == kFixedBackgroundAttachment;
+        (*it)->Attachment() == EFillAttachment::kFixed;
     if (should_paint_in_viewport_space) {
       box_model_painter.PaintFillLayer(
           paint_info, Color(), **it, LayoutRect(LayoutRect::InfiniteIntRect()),
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index c7ffc19e..62a134e 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -1160,7 +1160,7 @@
   for (const FillLayer* curr_layer = &layer; curr_layer;
        curr_layer = curr_layer->Next()) {
     if (!curr_layer->GetImage() ||
-        curr_layer->Attachment() != kFixedBackgroundAttachment)
+        curr_layer->Attachment() != EFillAttachment::kFixed)
       return false;
   }
 
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index 62997d9a..3646038d 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -108,32 +108,28 @@
   kLength
 };
 
-enum EFillAttachment {
-  kScrollBackgroundAttachment,
-  kLocalBackgroundAttachment,
-  kFixedBackgroundAttachment
-};
+enum class EFillAttachment : unsigned { kScroll, kLocal, kFixed };
 
-enum EFillBox {
-  kBorderFillBox,
-  kPaddingFillBox,
-  kContentFillBox,
-  kTextFillBox
-};
+enum class EFillBox : unsigned { kBorder, kPadding, kContent, kText };
 
 inline EFillBox EnclosingFillBox(EFillBox box_a, EFillBox box_b) {
-  if (box_a == kBorderFillBox || box_b == kBorderFillBox)
-    return kBorderFillBox;
-  if (box_a == kPaddingFillBox || box_b == kPaddingFillBox)
-    return kPaddingFillBox;
-  if (box_a == kContentFillBox || box_b == kContentFillBox)
-    return kContentFillBox;
-  return kTextFillBox;
+  if (box_a == EFillBox::kBorder || box_b == EFillBox::kBorder)
+    return EFillBox::kBorder;
+  if (box_a == EFillBox::kPadding || box_b == EFillBox::kPadding)
+    return EFillBox::kPadding;
+  if (box_a == EFillBox::kContent || box_b == EFillBox::kContent)
+    return EFillBox::kContent;
+  return EFillBox::kText;
 }
 
-enum EFillRepeat { kRepeatFill, kNoRepeatFill, kRoundFill, kSpaceFill };
+enum class EFillRepeat : unsigned {
+  kRepeatFill,
+  kNoRepeatFill,
+  kRoundFill,
+  kSpaceFill
+};
 
-enum EFillLayerType { kBackgroundFillLayer, kMaskFillLayer };
+enum class EFillLayerType : unsigned { kBackground, kMask };
 
 // CSS3 Background Values
 enum EFillSizeType { kContain, kCover, kSizeLength, kSizeNone };
diff --git a/third_party/WebKit/Source/core/style/FillLayer.cpp b/third_party/WebKit/Source/core/style/FillLayer.cpp
index c546bf4..f1e278c 100644
--- a/third_party/WebKit/Source/core/style/FillLayer.cpp
+++ b/third_party/WebKit/Source/core/style/FillLayer.cpp
@@ -49,11 +49,12 @@
       x_position_(FillLayer::InitialFillXPosition(type)),
       y_position_(FillLayer::InitialFillYPosition(type)),
       size_length_(FillLayer::InitialFillSizeLength(type)),
-      attachment_(FillLayer::InitialFillAttachment(type)),
-      clip_(FillLayer::InitialFillClip(type)),
-      origin_(FillLayer::InitialFillOrigin(type)),
-      repeat_x_(FillLayer::InitialFillRepeatX(type)),
-      repeat_y_(FillLayer::InitialFillRepeatY(type)),
+      attachment_(
+          static_cast<unsigned>(FillLayer::InitialFillAttachment(type))),
+      clip_(static_cast<unsigned>(FillLayer::InitialFillClip(type))),
+      origin_(static_cast<unsigned>(FillLayer::InitialFillOrigin(type))),
+      repeat_x_(static_cast<unsigned>(FillLayer::InitialFillRepeatX(type))),
+      repeat_y_(static_cast<unsigned>(FillLayer::InitialFillRepeatY(type))),
       composite_(FillLayer::InitialFillComposite(type)),
       size_type_(use_initial_values ? FillLayer::InitialFillSizeType(type)
                                     : kSizeNone),
@@ -71,10 +72,10 @@
       y_pos_set_(use_initial_values),
       background_x_origin_set_(false),
       background_y_origin_set_(false),
-      composite_set_(use_initial_values || type == kMaskFillLayer),
+      composite_set_(use_initial_values || type == EFillLayerType::kMask),
       blend_mode_set_(use_initial_values),
       mask_source_type_set_(use_initial_values),
-      type_(type),
+      type_(static_cast<unsigned>(type)),
       this_or_next_layers_clip_max_(0),
       this_or_next_layers_use_content_box_(0),
       this_or_next_layers_have_local_attachment_(0),
@@ -333,17 +334,17 @@
 void FillLayer::ComputeCachedPropertiesIfNeeded() const {
   if (cached_properties_computed_)
     return;
-  this_or_next_layers_clip_max_ = Clip();
+  this_or_next_layers_clip_max_ = static_cast<unsigned>(Clip());
   this_or_next_layers_use_content_box_ =
-      Clip() == kContentFillBox || Origin() == kContentFillBox;
+      Clip() == EFillBox::kContent || Origin() == EFillBox::kContent;
   this_or_next_layers_have_local_attachment_ =
-      Attachment() == kLocalBackgroundAttachment;
+      Attachment() == EFillAttachment::kLocal;
   cached_properties_computed_ = true;
 
   if (next_) {
     next_->ComputeCachedPropertiesIfNeeded();
-    this_or_next_layers_clip_max_ = EnclosingFillBox(
-        ThisOrNextLayersClipMax(), next_->ThisOrNextLayersClipMax());
+    this_or_next_layers_clip_max_ = static_cast<unsigned>(EnclosingFillBox(
+        ThisOrNextLayersClipMax(), next_->ThisOrNextLayersClipMax()));
     this_or_next_layers_use_content_box_ |=
         next_->this_or_next_layers_use_content_box_;
     this_or_next_layers_have_local_attachment_ |=
@@ -391,8 +392,10 @@
   // TODO(schenney) We could relax the repeat mode requirement if we also knew
   // the rect we had to fill, and the portion of the image we need to use, and
   // know that the latter covers the former.
-  return (repeat_x_ == kRepeatFill || repeat_x_ == kRoundFill) &&
-         (repeat_y_ == kRepeatFill || repeat_y_ == kRoundFill);
+  return (static_cast<EFillRepeat>(repeat_x_) == EFillRepeat::kRepeatFill ||
+          static_cast<EFillRepeat>(repeat_x_) == EFillRepeat::kRoundFill) &&
+         (static_cast<EFillRepeat>(repeat_y_) == EFillRepeat::kRepeatFill ||
+          static_cast<EFillRepeat>(repeat_y_) == EFillRepeat::kRoundFill);
 }
 
 bool FillLayer::ImageOccludesNextLayers(const Document& document,
diff --git a/third_party/WebKit/Source/core/style/FillLayer.h b/third_party/WebKit/Source/core/style/FillLayer.h
index 7fa0bfc1..497fb6033 100644
--- a/third_party/WebKit/Source/core/style/FillLayer.h
+++ b/third_party/WebKit/Source/core/style/FillLayer.h
@@ -141,25 +141,25 @@
   }
   void SetAttachment(EFillAttachment attachment) {
     DCHECK(!cached_properties_computed_);
-    attachment_ = attachment;
+    attachment_ = static_cast<unsigned>(attachment);
     attachment_set_ = true;
   }
   void SetClip(EFillBox b) {
     DCHECK(!cached_properties_computed_);
-    clip_ = b;
+    clip_ = static_cast<unsigned>(b);
     clip_set_ = true;
   }
   void SetOrigin(EFillBox b) {
     DCHECK(!cached_properties_computed_);
-    origin_ = b;
+    origin_ = static_cast<unsigned>(b);
     origin_set_ = true;
   }
   void SetRepeatX(EFillRepeat r) {
-    repeat_x_ = r;
+    repeat_x_ = static_cast<unsigned>(r);
     repeat_x_set_ = true;
   }
   void SetRepeatY(EFillRepeat r) {
-    repeat_y_ = r;
+    repeat_y_ = static_cast<unsigned>(r);
     repeat_y_set_ = true;
   }
   void SetComposite(CompositeOperator c) {
@@ -222,7 +222,8 @@
   }
 
   bool HasFixedImage() const {
-    if (image_ && attachment_ == kFixedBackgroundAttachment)
+    if (image_ &&
+        static_cast<EFillAttachment>(attachment_) == EFillAttachment::kFixed)
       return true;
     return next_ ? next_->HasFixedImage() : false;
   }
@@ -253,14 +254,19 @@
   void ComputeCachedPropertiesIfNeeded() const;
 
   static EFillAttachment InitialFillAttachment(EFillLayerType) {
-    return kScrollBackgroundAttachment;
+    return EFillAttachment::kScroll;
   }
-  static EFillBox InitialFillClip(EFillLayerType) { return kBorderFillBox; }
+  static EFillBox InitialFillClip(EFillLayerType) { return EFillBox::kBorder; }
   static EFillBox InitialFillOrigin(EFillLayerType type) {
-    return type == kBackgroundFillLayer ? kPaddingFillBox : kBorderFillBox;
+    return type == EFillLayerType::kBackground ? EFillBox::kPadding
+                                               : EFillBox::kBorder;
   }
-  static EFillRepeat InitialFillRepeatX(EFillLayerType) { return kRepeatFill; }
-  static EFillRepeat InitialFillRepeatY(EFillLayerType) { return kRepeatFill; }
+  static EFillRepeat InitialFillRepeatX(EFillLayerType) {
+    return EFillRepeat::kRepeatFill;
+  }
+  static EFillRepeat InitialFillRepeatY(EFillLayerType) {
+    return EFillRepeat::kRepeatFill;
+  }
   static CompositeOperator InitialFillComposite(EFillLayerType) {
     return kCompositeSourceOver;
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css b/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
index 407370e8..ee61997 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
@@ -195,11 +195,6 @@
     margin: 0 0 0 10px !important;
 }
 
-.js_profiler.panel select.chrome-select,
-.heap_profiler.panel select.chrome-select {
-    width: 150px;
-}
-
 .profile-launcher-button {
     margin-top: 10px;
     margin-right: 8px;
diff --git a/third_party/WebKit/common/BUILD.gn b/third_party/WebKit/common/BUILD.gn
index 07c734b..773713e5 100644
--- a/third_party/WebKit/common/BUILD.gn
+++ b/third_party/WebKit/common/BUILD.gn
@@ -117,6 +117,7 @@
     "service_worker/service_worker_client.mojom",
     "service_worker/service_worker_error_type.mojom",
     "service_worker/service_worker_event_status.mojom",
+    "service_worker/service_worker_installed_scripts_manager.mojom",
     "service_worker/service_worker_object.mojom",
     "service_worker/service_worker_provider_type.mojom",
     "service_worker/service_worker_registration.mojom",
diff --git a/content/common/service_worker/service_worker_installed_scripts_manager.mojom b/third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom
similarity index 98%
rename from content/common/service_worker/service_worker_installed_scripts_manager.mojom
rename to third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom
index 4d815cb..ecc156e 100644
--- a/content/common/service_worker/service_worker_installed_scripts_manager.mojom
+++ b/third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-module content.mojom;
+module blink.mojom;
 
 import "url/mojo/url.mojom";
 
@@ -43,4 +43,4 @@
 interface ServiceWorkerInstalledScriptsManager {
   // Starts streaming the script to the renderer.
   TransferInstalledScript(ServiceWorkerScriptInfo script_info);
-};
\ No newline at end of file
+};
diff --git a/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom b/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
index ea650b3..e09f4fc 100644
--- a/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
+++ b/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
@@ -7,22 +7,23 @@
 import "media/capture/mojo/video_capture_types.mojom";
 import "media/mojo/interfaces/audio_parameters.mojom";
 
-[Native]
-enum MediaDeviceType;
-
-[Native]
-struct MediaDeviceInfo;
+enum MediaDeviceType {
+  MEDIA_AUDIO_INPUT,
+  MEDIA_VIDEO_INPUT,
+  MEDIA_AUDIO_OUTPUT,
+  NUM_MEDIA_DEVICE_TYPES
+};
 
 // The values for this enum match the ones defined in
 // https://w3c.github.io/mediacapture-main/#def-constraint-facingMode
 // with the addition of NONE, which would map to the empty string in
 // JavaScript.
-enum FacingMode {
-  NONE,
-  USER,
-  ENVIRONMENT,
-  LEFT,
-  RIGHT
+enum FacingMode { NONE, USER, ENVIRONMENT, LEFT, RIGHT };
+
+struct MediaDeviceInfo {
+  string device_id;
+  string label;
+  string group_id;
 };
 
 struct VideoInputDeviceCapabilities {
@@ -41,7 +42,7 @@
 // notifications.
 interface MediaDevicesDispatcherHost {
   // The reply always contains NUM_MEDIA_DEVICE_TYPES elements.
-  // The result is indexed by device type as defined in 
+  // The result is indexed by device type as defined in
   // content/common/media/media_devices.h.
   EnumerateDevices(bool request_audio_input,
                    bool request_video_input,
diff --git a/ui/accessibility/ax_action_data.cc b/ui/accessibility/ax_action_data.cc
index b5da425..bca145a 100644
--- a/ui/accessibility/ax_action_data.cc
+++ b/ui/accessibility/ax_action_data.cc
@@ -15,23 +15,9 @@
 
 namespace ui {
 
-AXActionData::AXActionData()
-    : action(AX_ACTION_NONE),
-      target_tree_id(-1),
-      target_node_id(-1),
-      request_id(-1),
-      flags(0),
-      anchor_node_id(-1),
-      anchor_offset(-1),
-      focus_node_id(-1),
-      focus_offset(-1),
-      custom_action_id(-1),
-      hit_test_event_to_fire(AX_EVENT_NONE) {}
-
+AXActionData::AXActionData() = default;
 AXActionData::AXActionData(const AXActionData& other) = default;
-
-AXActionData::~AXActionData() {
-}
+AXActionData::~AXActionData() = default;
 
 // Note that this includes an initial space character if nonempty, but
 // that works fine because this is normally printed by AXAction::ToString.
diff --git a/ui/accessibility/ax_action_data.h b/ui/accessibility/ax_action_data.h
index 299344906..5cd03ee 100644
--- a/ui/accessibility/ax_action_data.h
+++ b/ui/accessibility/ax_action_data.h
@@ -29,33 +29,33 @@
   // parameters apply.
 
   // The action to take.
-  AXAction action;
+  AXAction action = AX_ACTION_NONE;
 
   // The ID of the tree that this action should be performed on.
-  int target_tree_id;
+  int target_tree_id = -1;
 
   // The source extension id (if any) of this action.
   std::string source_extension_id;
 
   // The ID of the node that this action should be performed on.
-  int target_node_id;
+  int target_node_id = -1;
 
   // The request id of this action tracked by the client.
-  int request_id;
+  int request_id = -1;
 
   // Use enums from AXActionFlags
-  int flags;
+  int flags = 0;
 
   // For an action that creates a selection, the selection anchor and focus
   // (see ax_tree_data.h for definitions).
-  int anchor_node_id;
-  int anchor_offset;
+  int anchor_node_id = -1;
+  int anchor_offset = -1;
 
-  int focus_node_id;
-  int focus_offset;
+  int focus_node_id = -1;
+  int focus_offset = -1;
 
   // For custom action.
-  int custom_action_id;
+  int custom_action_id = -1;
 
   // The target rect for the action.
   gfx::Rect target_rect;
@@ -67,7 +67,7 @@
   base::string16 value;
 
   // The event to fire in response to a HIT_TEST action.
-  AXEvent hit_test_event_to_fire;
+  AXEvent hit_test_event_to_fire = AX_EVENT_NONE;
 };
 
 }  // namespace ui
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc
index 6cfd00c1..caa0384 100644
--- a/ui/accessibility/ax_event_generator.cc
+++ b/ui/accessibility/ax_event_generator.cc
@@ -51,7 +51,7 @@
   return AXEventGenerator::TargetedEvent(map_iter_->first, *set_iter_);
 }
 
-AXEventGenerator::AXEventGenerator() : tree_(nullptr) {}
+AXEventGenerator::AXEventGenerator() = default;
 
 AXEventGenerator::AXEventGenerator(AXTree* tree) : tree_(tree) {
   if (tree_)
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h
index 19d59f2..f4d9c26 100644
--- a/ui/accessibility/ax_event_generator.h
+++ b/ui/accessibility/ax_event_generator.h
@@ -170,7 +170,7 @@
   void FireLiveRegionEvents(AXNode* node);
   void FireActiveDescendantEvents();
 
-  AXTree* tree_;  // Not owned.
+  AXTree* tree_ = nullptr;  // Not owned.
   std::map<AXNode*, std::set<Event>> tree_events_;
 
   // Valid between the call to OnIntAttributeChanged and the call to
diff --git a/ui/accessibility/ax_mode_observer.h b/ui/accessibility/ax_mode_observer.h
index c1fa63c9..f517c36 100644
--- a/ui/accessibility/ax_mode_observer.h
+++ b/ui/accessibility/ax_mode_observer.h
@@ -20,4 +20,4 @@
 
 }  // namespace ui
 
-#endif  // UI_ACCESSIBILITY_PLATFORM_AX_MODE_OBSERVER_H_
\ No newline at end of file
+#endif  // UI_ACCESSIBILITY_PLATFORM_AX_MODE_OBSERVER_H_
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index f60b1d0..ce28139 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -59,16 +59,6 @@
   return str;
 }
 
-std::string StringVectorToString(const std::vector<std::string>& items) {
-  std::string str;
-  for (size_t i = 0; i < items.size(); ++i) {
-    if (i > 0)
-      str += ",";
-    str += items[i];
-  }
-  return str;
-}
-
 // Predicate that returns true if the first value of a pair is |first|.
 template<typename FirstType, typename SecondType>
 struct FirstIs {
@@ -194,15 +184,8 @@
   return false;
 }
 
-AXNodeData::AXNodeData()
-    : id(-1),
-      role(AX_ROLE_UNKNOWN),
-      state(AX_STATE_NONE),
-      actions(AX_ACTION_NONE),
-      offset_container_id(-1) {}
-
-AXNodeData::~AXNodeData() {
-}
+AXNodeData::AXNodeData() = default;
+AXNodeData::~AXNodeData() = default;
 
 AXNodeData::AXNodeData(const AXNodeData& other) {
   id = other.id;
@@ -1049,7 +1032,7 @@
     switch (stringlist_attributes[i].first) {
       case AX_ATTR_CUSTOM_ACTION_DESCRIPTIONS:
         result +=
-            " custom_action_descriptions: " + StringVectorToString(values);
+            " custom_action_descriptions: " + base::JoinString(values, ",");
         break;
       case AX_STRING_LIST_ATTRIBUTE_NONE:
         break;
diff --git a/ui/accessibility/ax_node_data.h b/ui/accessibility/ax_node_data.h
index 29e7998..0f2194e 100644
--- a/ui/accessibility/ax_node_data.h
+++ b/ui/accessibility/ax_node_data.h
@@ -127,10 +127,10 @@
 
   // As much as possible this should behave as a simple, serializable,
   // copyable struct.
-  int32_t id;
-  AXRole role;
-  uint32_t state;
-  uint32_t actions;
+  int32_t id = -1;
+  AXRole role = AX_ROLE_UNKNOWN;
+  uint32_t state = AX_STATE_NONE;
+  uint32_t actions = AX_ACTION_NONE;
   std::vector<std::pair<AXStringAttribute, std::string>> string_attributes;
   std::vector<std::pair<AXIntAttribute, int32_t>> int_attributes;
   std::vector<std::pair<AXFloatAttribute, float>> float_attributes;
@@ -147,7 +147,7 @@
 
   // The id of an ancestor node in the same AXTree that this object's
   // bounding box is relative to, or -1 if there's no offset container.
-  int offset_container_id;
+  int offset_container_id = -1;
 
   // The relative bounding box of this node.
   gfx::RectF location;
diff --git a/ui/accessibility/ax_serializable_tree.cc b/ui/accessibility/ax_serializable_tree.cc
index 17446e3..01cd5e52 100644
--- a/ui/accessibility/ax_serializable_tree.cc
+++ b/ui/accessibility/ax_serializable_tree.cc
@@ -44,13 +44,13 @@
     return node->parent();
   }
 
-  bool IsValid(const AXNode* node) const override { return node != NULL; }
+  bool IsValid(const AXNode* node) const override { return node != nullptr; }
 
   bool IsEqual(const AXNode* node1, const AXNode* node2) const override {
     return node1 == node2;
   }
 
-  const AXNode* GetNull() const override { return NULL; }
+  const AXNode* GetNull() const override { return nullptr; }
 
   void SerializeNode(const AXNode* node, AXNodeData* out_data) const override {
     *out_data = node->data();
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
index b185e52..f1bb4b7 100644
--- a/ui/accessibility/ax_tree.cc
+++ b/ui/accessibility/ax_tree.cc
@@ -119,14 +119,10 @@
   std::set<int> removed_node_ids;
 };
 
-AXTreeDelegate::AXTreeDelegate() {
-}
+AXTreeDelegate::AXTreeDelegate() = default;
+AXTreeDelegate::~AXTreeDelegate() = default;
 
-AXTreeDelegate::~AXTreeDelegate() {
-}
-
-AXTree::AXTree()
-    : delegate_(NULL), root_(NULL) {
+AXTree::AXTree() {
   AXNodeData root;
   root.id = -1;
 
@@ -136,8 +132,7 @@
   CHECK(Unserialize(initial_state)) << error();
 }
 
-AXTree::AXTree(const AXTreeUpdate& initial_state)
-    : delegate_(NULL), root_(NULL) {
+AXTree::AXTree(const AXTreeUpdate& initial_state) {
   CHECK(Unserialize(initial_state)) << error();
 }
 
@@ -151,8 +146,8 @@
 }
 
 AXNode* AXTree::GetFromId(int32_t id) const {
-  base::hash_map<int32_t, AXNode*>::const_iterator iter = id_map_.find(id);
-  return iter != id_map_.end() ? iter->second : NULL;
+  auto iter = id_map_.find(id);
+  return iter != id_map_.end() ? iter->second : nullptr;
 }
 
 void AXTree::UpdateData(const AXTreeData& new_data) {
@@ -349,10 +344,8 @@
 
   if (!update_state.pending_nodes.empty()) {
     error_ = "Nodes left pending by the update:";
-    for (std::set<AXNode*>::iterator iter = update_state.pending_nodes.begin();
-         iter != update_state.pending_nodes.end(); ++iter) {
-      error_ += base::StringPrintf(" %d", (*iter)->id());
-    }
+    for (const AXNode* pending : update_state.pending_nodes)
+      error_ += base::StringPrintf(" %d", pending->id());
     return false;
   }
 
@@ -441,7 +434,7 @@
       return false;
     }
 
-    update_state->new_root = CreateNode(NULL, src.id, 0, update_state);
+    update_state->new_root = CreateNode(nullptr, src.id, 0, update_state);
     node = update_state->new_root;
     update_state->new_nodes.insert(node);
     UpdateReverseRelations(node, src);
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h
index 9fc88b454..068ecad7 100644
--- a/ui/accessibility/ax_tree.h
+++ b/ui/accessibility/ax_tree.h
@@ -264,8 +264,8 @@
                             std::vector<AXNode*>* new_children,
                             AXTreeUpdateState* update_state);
 
-  AXTreeDelegate* delegate_;
-  AXNode* root_;
+  AXTreeDelegate* delegate_ = nullptr;
+  AXNode* root_ = nullptr;
   base::hash_map<int32_t, AXNode*> id_map_;
   std::string error_;
   AXTreeData data_;
diff --git a/ui/accessibility/ax_tree_data.cc b/ui/accessibility/ax_tree_data.cc
index 2b1bb9a..3639b8d 100644
--- a/ui/accessibility/ax_tree_data.cc
+++ b/ui/accessibility/ax_tree_data.cc
@@ -13,25 +13,9 @@
 
 namespace ui {
 
-AXTreeData::AXTreeData()
-    : tree_id(-1),
-      parent_tree_id(-1),
-      focused_tree_id(-1),
-      loaded(false),
-      loading_progress(0.0),
-      focus_id(-1),
-      sel_anchor_object_id(-1),
-      sel_anchor_offset(-1),
-      sel_anchor_affinity(AX_TEXT_AFFINITY_UPSTREAM),
-      sel_focus_object_id(-1),
-      sel_focus_offset(-1),
-      sel_focus_affinity(AX_TEXT_AFFINITY_DOWNSTREAM) {
-}
-
+AXTreeData::AXTreeData() = default;
 AXTreeData::AXTreeData(const AXTreeData& other) = default;
-
-AXTreeData::~AXTreeData() {
-}
+AXTreeData::~AXTreeData() = default;
 
 // Note that this includes an initial space character if nonempty, but
 // that works fine because this is normally printed by AXTree::ToString.
diff --git a/ui/accessibility/ax_tree_data.h b/ui/accessibility/ax_tree_data.h
index 36beba6..d637bf2b4 100644
--- a/ui/accessibility/ax_tree_data.h
+++ b/ui/accessibility/ax_tree_data.h
@@ -33,38 +33,38 @@
   // public and copyable.
 
   // The globally unique ID of this accessibility tree.
-  int32_t tree_id;
+  int32_t tree_id = -1;
 
   // The ID of the accessibility tree that this tree is contained in, if any.
-  int32_t parent_tree_id;
+  int32_t parent_tree_id = -1;
 
   // The ID of the accessibility tree that has focus. This is typically set
   // on the root frame in a frame tree.
-  int32_t focused_tree_id;
+  int32_t focused_tree_id = -1;
 
   // Attributes specific to trees that are web frames.
   std::string doctype;
-  bool loaded;
-  float loading_progress;
+  bool loaded = false;
+  float loading_progress = 0.0;
   std::string mimetype;
   std::string title;
   std::string url;
 
   // The node with keyboard focus within this tree, if any, or -1 if no node
   // in this tree has focus.
-  int32_t focus_id;
+  int32_t focus_id = -1;
 
   // The current text selection within this tree, if any, expressed as the
   // node ID and character offset of the anchor (selection start) and focus
   // (selection end). If the offset could correspond to a position on two
   // different lines, sel_upstream_affinity means the cursor is on the first
   // line, otherwise it's on the second line.
-  int32_t sel_anchor_object_id;
-  int32_t sel_anchor_offset;
-  ui::AXTextAffinity sel_anchor_affinity;
-  int32_t sel_focus_object_id;
-  int32_t sel_focus_offset;
-  ui::AXTextAffinity sel_focus_affinity;
+  int32_t sel_anchor_object_id = -1;
+  int32_t sel_anchor_offset = -1;
+  ui::AXTextAffinity sel_anchor_affinity = AX_TEXT_AFFINITY_UPSTREAM;
+  int32_t sel_focus_object_id = -1;
+  int32_t sel_focus_offset = -1;
+  ui::AXTextAffinity sel_focus_affinity = AX_TEXT_AFFINITY_DOWNSTREAM;
 };
 
 AX_EXPORT bool operator==(const AXTreeData& lhs, const AXTreeData& rhs);
diff --git a/ui/accessibility/ax_tree_serializer.h b/ui/accessibility/ax_tree_serializer.h
index 2b454d77..098ad4b6 100644
--- a/ui/accessibility/ax_tree_serializer.h
+++ b/ui/accessibility/ax_tree_serializer.h
@@ -98,7 +98,7 @@
 
  private:
   // Return the least common ancestor of a node in the source tree
-  // and a node in the client tree, or NULL if there is no such node.
+  // and a node in the client tree, or nullptr if there is no such node.
   // The least common ancestor is the closest ancestor to |node| (which
   // may be |node| itself) that's in both the source tree and client tree,
   // and for which both the source and client tree agree on their ancestor
@@ -166,14 +166,14 @@
   AXTreeData client_tree_data_;
 
   // Our representation of the client tree.
-  ClientTreeNode* client_root_;
+  ClientTreeNode* client_root_ = nullptr;
 
   // A map from IDs to nodes in the client tree.
   base::hash_map<int32_t, ClientTreeNode*> client_id_map_;
 
   // The maximum number of nodes to serialize in a given call to
   // SerializeChanges, or 0 if there's no maximum.
-  size_t max_node_count_;
+  size_t max_node_count_ = 0;
 };
 
 // In order to keep track of what nodes the client knows about, we keep a
@@ -190,7 +190,7 @@
 template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
 AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::AXTreeSerializer(
     AXTreeSource<AXSourceNode, AXNodeData, AXTreeData>* tree)
-    : tree_(tree), client_root_(NULL), max_node_count_(0) {}
+    : tree_(tree) {}
 
 template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
 AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::~AXTreeSerializer() {
@@ -206,7 +206,7 @@
   DeleteClientSubtree(client_root_);
   client_id_map_.erase(client_root_->id);
   delete client_root_;
-  client_root_ = NULL;
+  client_root_ = nullptr;
 }
 
 template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
@@ -221,7 +221,7 @@
 AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::LeastCommonAncestor(
     AXSourceNode node,
     ClientTreeNode* client_node) {
-  if (!tree_->IsValid(node) || client_node == NULL)
+  if (!tree_->IsValid(node) || client_node == nullptr)
     return tree_->GetNull();
 
   std::vector<AXSourceNode> ancestors;
@@ -314,8 +314,7 @@
       client_id_map_.find(id);
   if (iter != client_id_map_.end())
     return iter->second;
-  else
-    return NULL;
+  return nullptr;
 }
 
 template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
@@ -426,7 +425,7 @@
     client_root_ = new ClientTreeNode();
     client_node = client_root_;
     client_node->id = id;
-    client_node->parent = NULL;
+    client_node->parent = nullptr;
     client_id_map_[client_node->id] = client_node;
   }
 
diff --git a/ui/accessibility/ax_tree_serializer_unittest.cc b/ui/accessibility/ax_tree_serializer_unittest.cc
index 0c46eae..2596278 100644
--- a/ui/accessibility/ax_tree_serializer_unittest.cc
+++ b/ui/accessibility/ax_tree_serializer_unittest.cc
@@ -217,12 +217,12 @@
     return node->parent();
   }
   bool IsValid(const AXNode* node) const override {
-    return node != NULL && node->id() != invalid_id_;
+    return node != nullptr && node->id() != invalid_id_;
   }
   bool IsEqual(const AXNode* node1, const AXNode* node2) const override {
     return node1 == node2;
   }
-  const AXNode* GetNull() const override { return NULL; }
+  const AXNode* GetNull() const override { return nullptr; }
   void SerializeNode(const AXNode* node, AXNodeData* out_data) const override {
     *out_data = node->data();
     if (node->id() == invalid_id_)
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc
index f1b2780..7271ce3 100644
--- a/ui/accessibility/ax_tree_unittest.cc
+++ b/ui/accessibility/ax_tree_unittest.cc
@@ -265,7 +265,7 @@
   ASSERT_TRUE(dst_tree.Unserialize(update));
 
   const AXNode* root_node = dst_tree.root();
-  ASSERT_TRUE(root_node != NULL);
+  ASSERT_TRUE(root_node != nullptr);
   EXPECT_EQ(root.id, root_node->id());
   EXPECT_EQ(root.role, root_node->data().role);
 
@@ -464,7 +464,7 @@
 
   ASSERT_EQ(true, fake_delegate.root_changed());
 
-  tree.SetDelegate(NULL);
+  tree.SetDelegate(nullptr);
 }
 
 TEST(AXTreeTest, TreeDelegateIsCalledForTreeDataChanges) {
@@ -501,7 +501,7 @@
   EXPECT_TRUE(fake_delegate.tree_data_changed());
   EXPECT_EQ("New Title", tree.data().title);
 
-  tree.SetDelegate(NULL);
+  tree.SetDelegate(nullptr);
 }
 
 TEST(AXTreeTest, ReparentingDoesNotTriggerNodeCreated) {
@@ -578,7 +578,7 @@
 
   ASSERT_EQ(true, fake_delegate.root_changed());
 
-  tree.SetDelegate(NULL);
+  tree.SetDelegate(nullptr);
 }
 
 // UAF caught by ax_tree_fuzzer
@@ -658,7 +658,7 @@
   EXPECT_EQ("visited changed to true", change_log[1]);
   EXPECT_EQ("checkedState changed from 2 to 1", change_log[2]);
 
-  tree.SetDelegate(NULL);
+  tree.SetDelegate(nullptr);
 }
 
 TEST(AXTreeTest, AttributeChangeCallbacks) {
@@ -741,7 +741,7 @@
   EXPECT_EQ("scrollX changed from 6 to 7", change_log2[9]);
   EXPECT_EQ("scrollXMax changed from 0 to 10", change_log2[10]);
 
-  tree.SetDelegate(NULL);
+  tree.SetDelegate(nullptr);
 }
 
 TEST(AXTreeTest, IntListChangeCallbacks) {
@@ -800,7 +800,7 @@
   EXPECT_EQ("radioGroupIds changed from 3 to 2,2", change_log2[1]);
   EXPECT_EQ("flowtoIds changed from  to 3", change_log2[2]);
 
-  tree.SetDelegate(NULL);
+  tree.SetDelegate(nullptr);
 }
 
 // Create a very simple tree and make sure that we can get the bounds of
diff --git a/ui/accessibility/ax_tree_update.h b/ui/accessibility/ax_tree_update.h
index 283de44c..10a0ec5 100644
--- a/ui/accessibility/ax_tree_update.h
+++ b/ui/accessibility/ax_tree_update.h
@@ -45,12 +45,12 @@
 //        it's a fatal error. This guarantees the tree is always complete
 //        before or after an AXTreeUpdate.
 template<typename AXNodeData, typename AXTreeData> struct AXTreeUpdateBase {
-  AXTreeUpdateBase();
-  ~AXTreeUpdateBase();
+  AXTreeUpdateBase() = default;
+  ~AXTreeUpdateBase() = default;
 
   // If |has_tree_data| is true, the value of |tree_data| should be used
   // to update the tree data, otherwise it should be ignored.
-  bool has_tree_data;
+  bool has_tree_data = false;
   AXTreeData tree_data;
 
   // The id of a node to clear, before applying any updates,
@@ -58,13 +58,13 @@
   // all of its children and their descendants, but leaving that node in
   // the tree. It's an error to clear a node but not subsequently update it
   // as part of the tree update.
-  int node_id_to_clear;
+  int node_id_to_clear = 0;
 
   // The id of the root of the tree, if the root is changing. This is
   // required to be set if the root of the tree is changing or Unserialize
   // will fail. If the root of the tree is not changing this is optional
   // and it is allowed to pass 0.
-  int root_id;
+  int root_id = 0;
 
   // A vector of nodes to update, according to the rules above.
   std::vector<AXNodeData> nodes;
@@ -75,18 +75,7 @@
   // TODO(dmazzoni): location changes
 };
 
-typedef AXTreeUpdateBase<AXNodeData, AXTreeData> AXTreeUpdate;
-
-template<typename AXNodeData, typename AXTreeData>
-AXTreeUpdateBase<AXNodeData, AXTreeData>::AXTreeUpdateBase()
-    : has_tree_data(false),
-      node_id_to_clear(0),
-      root_id(0) {
-}
-
-template<typename AXNodeData, typename AXTreeData>
-AXTreeUpdateBase<AXNodeData, AXTreeData>::~AXTreeUpdateBase() {
-}
+using AXTreeUpdate = AXTreeUpdateBase<AXNodeData, AXTreeData>;
 
 template<typename AXNodeData, typename AXTreeData>
 std::string AXTreeUpdateBase<AXNodeData, AXTreeData>::ToString() const {
diff --git a/ui/accessibility/platform/ax_platform_node.h b/ui/accessibility/platform/ax_platform_node.h
index 56a0664..ca12603 100644
--- a/ui/accessibility/platform/ax_platform_node.h
+++ b/ui/accessibility/platform/ax_platform_node.h
@@ -33,7 +33,7 @@
   static AXPlatformNode* Create(AXPlatformNodeDelegate* delegate);
 
   // Cast a gfx::NativeViewAccessible to an AXPlatformNode if it is one,
-  // or return NULL if it's not an instance of this class.
+  // or return nullptr if it's not an instance of this class.
   static AXPlatformNode* FromNativeViewAccessible(
       gfx::NativeViewAccessible accessible);