Remove DIAL MRP

PiperOrigin-RevId: 289499538
diff --git a/init.js b/init.js
index fb0a5b1..fdb16a7 100644
--- a/init.js
+++ b/init.js
@@ -159,11 +159,6 @@
     mr.Init.logger_.info(`Native Cast MRP is ${
         config.enable_cast_sink_query ? 'disabled' : 'enabled'}.`);
   }
-  if (config.enable_dial_sink_query !== undefined) {
-    // Native DIAL MRP usage is the opposite of |enable_dial_sink_query|.
-    mr.Init.logger_.info(`Native DIAL MRP is ${
-        config.enable_dial_sink_query ? 'disabled' : 'enabled'}.`);
-  }
   if (config.use_mirroring_service !== undefined) {
     mr.Init.logger_.info(`Native Mirroring Service is ${
         config.use_mirroring_service ? 'enabled' : 'disabled'}.`);
diff --git a/init_helper.js b/init_helper.js
index 320629a..3322f28 100644
--- a/init_helper.js
+++ b/init_helper.js
@@ -7,7 +7,6 @@
 goog.module('mr.InitHelper');
 goog.module.declareLegacyNamespace();
 
-const DialProvider = goog.require('mr.DialProvider');
 const EventListener = goog.require('mr.EventListener');
 const Provider = goog.require('mr.Provider');
 const ProviderManager = goog.forwardDeclare('mr.ProviderManager');
@@ -18,7 +17,7 @@
  * @return {!Array<!Provider>}
  */
 function getProviders(providerManager) {
-  return [new DialProvider(providerManager)];
+  return [];
 }
 
 
diff --git a/init_test.js b/init_test.js
index bf60f2f..28c7c9e 100644
--- a/init_test.js
+++ b/init_test.js
@@ -32,7 +32,6 @@
       'mrInstanceId': 'mrInstanceId',
       'mrConfig': {
         'enable_dial_discovery': true,
-        'enable_dial_sink_query': true,
         'enable_cast_discovery': true,
         'enable_cast_sink_query': true,
         'use_views_dialog': true
diff --git a/manager/provider.js b/manager/provider.js
index fe0217e..7ae1c73 100644
--- a/manager/provider.js
+++ b/manager/provider.js
@@ -18,7 +18,6 @@
  */
 mr.ProviderName = {
   CAST: 'cast',
-  DIAL: 'dial',
   CLOUD: 'cloud',
   TEST: 'test'
 };
diff --git a/mojo_externs.js b/mojo_externs.js
index f01e3b0..6fbcdf7 100644
--- a/mojo_externs.js
+++ b/mojo_externs.js
@@ -130,28 +130,6 @@
 /** @type {string} */
 mojo.Url.prototype.url;
 
-
-
-/**
- * @constructor
- * @struct
- */
-mojo.DialMediaSink = function() {};
-
-
-/** @type {mojo.IPAddress} */
-mojo.DialMediaSink.prototype.ip_address;
-
-
-/** @type {string} */
-mojo.DialMediaSink.prototype.model_name;
-
-
-/** @type {mojo.Url} */
-mojo.DialMediaSink.prototype.app_url;
-
-
-
 /**
  * @constructor
  * @struct
@@ -188,9 +166,6 @@
 mojo.SinkExtraData = function() {};
 
 
-/** @type {mojo.DialMediaSink} */
-mojo.SinkExtraData.prototype.dial_media_sink;
-
 
 /** @type {mojo.CastMediaSink} */
 mojo.SinkExtraData.prototype.cast_media_sink;
diff --git a/providers/common/net_utils.js b/providers/common/net_utils.js
index d23e209..08c372d 100644
--- a/providers/common/net_utils.js
+++ b/providers/common/net_utils.js
@@ -11,7 +11,6 @@
 goog.module.declareLegacyNamespace();
 
 
-
 /** @const @private {!RegExp} */
 exports.IPV4_REGEXP_ =
     new RegExp('^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$');
diff --git a/providers/common/sink_utils.js b/providers/common/sink_utils.js
index d854f38..0874d1b 100644
--- a/providers/common/sink_utils.js
+++ b/providers/common/sink_utils.js
@@ -72,7 +72,7 @@
    * Generates ID from the receiver UUID and a per-profile token saved in
    * localStorage.
    *
-   * Both DIAL and mDNS use this to generate receiver ID so that it is
+   * Cast uses this to generate a receiver ID that is
    * consistent and can be used to deduplicate receivers. For a given token, the
    * ID is the same for the same device no matter when it is discovered.
    *
diff --git a/providers/dial/dial_activity.js b/providers/dial/dial_activity.js
deleted file mode 100644
index 264e209..0000000
--- a/providers/dial/dial_activity.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview DIAL activity (locally launched or discovered).
- */
-
-goog.provide('mr.dial.Activity');
-
-mr.dial.Activity = class {
-  /**
-   * @param {!mr.Route} route
-   * @param {!string} appName
-   */
-  constructor(route, appName) {
-    /** @type {!mr.Route} */
-    this.route = route;
-    /** @type {string} */
-    this.appName = appName;
-  }
-};
diff --git a/providers/dial/dial_activity_records.js b/providers/dial/dial_activity_records.js
deleted file mode 100644
index 112ec31..0000000
--- a/providers/dial/dial_activity_records.js
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.ActivityRecords');
-
-const ActivityCallbacks = goog.require('mr.dial.ActivityCallbacks');
-const PersistentData = goog.require('mr.PersistentData');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-
-
-/**
- * Keeps track of DIAL activities.
- * @implements {PersistentData}
- */
-const ActivityRecords = class {
-  /**
-   * @param {!ActivityCallbacks} activityCallbacks
-   */
-  constructor(activityCallbacks) {
-    /**
-     * Maps route ID to the corresponding Activity.
-     * @private {!Map<string, !mr.dial.Activity>}
-     */
-    this.routeIdToAppInfo_ = new Map();
-
-    /** @private @const {!ActivityCallbacks} */
-    this.activityCallbacks_ = activityCallbacks;
-  }
-
-  /**
-   * Restores routeIdToAppInfo_ from saved data.
-   */
-  init() {
-    PersistentDataManager.register(this);
-  }
-
-  /**
-   * Removes all activities.
-   */
-  clear() {
-    this.routeIdToAppInfo_.clear();
-  }
-
-  /**
-   * Adds a new activity. If the activity already exists, this is no-op.
-   * @param {!mr.dial.Activity} activity
-   */
-  add(activity) {
-    if (this.getByRouteId(activity.route.id)) {
-      return;
-    }
-    this.routeIdToAppInfo_.set(activity.route.id, activity);
-    this.activityCallbacks_.onActivityAdded(activity);
-  }
-
-  /**
-   * Returns the activity corresponding to the given route ID, or null if there
-   * is none.
-   * @param {string} routeId
-   * @return {?mr.dial.Activity}
-   */
-  getByRouteId(routeId) {
-    return this.routeIdToAppInfo_.get(routeId) || null;
-  }
-
-  /**
-   * Returns the activity corresponding to the given sink ID, or null if there
-   * is none.
-   * @param {string} sinkId
-   * @return {?mr.dial.Activity}
-   */
-  getBySinkId(sinkId) {
-    for (let [routeId, activity] of this.routeIdToAppInfo_) {
-      if (activity.route.sinkId == sinkId) {
-        return /** @type {!mr.dial.Activity} */ (activity);
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Removes the activity associated with the given sink ID.
-   * @param {string} sinkId
-   */
-  removeBySinkId(sinkId) {
-    const activity = this.getBySinkId(sinkId);
-    if (activity) {
-      this.routeIdToAppInfo_.delete(activity.route.id);
-      this.activityCallbacks_.onActivityRemoved(activity);
-    }
-  }
-
-  /**
-   * Removes the activity associated with the given route ID.
-   * @param {string} routeId
-   */
-  removeByRouteId(routeId) {
-    const activity = this.routeIdToAppInfo_.get(routeId);
-    if (activity) {
-      this.routeIdToAppInfo_.delete(routeId);
-      this.activityCallbacks_.onActivityRemoved(activity);
-    }
-  }
-
-  /**
-   * Returns the list of routes associated with the current list of activities.
-   * @return {!Array<!mr.Route>}
-   */
-  getRoutes() {
-    return Array.from(
-        this.routeIdToAppInfo_.values(), activity => activity.route);
-  }
-
-  /**
-   * Returns the current list of acitvities.
-   * @return {!Array<!mr.dial.Activity>}
-   */
-  getActivities() {
-    return Array.from(this.routeIdToAppInfo_.values());
-  }
-
-  /**
-   * Returns the number of activities.
-   * @return {number}
-   */
-  getActivityCount() {
-    return this.routeIdToAppInfo_.size;
-  }
-
-  /**
-   * @override
-   */
-  getStorageKey() {
-    return 'dial.ActivityRecords';
-  }
-
-  /**
-   * @override
-   */
-  getData() {
-    return [Array.from(this.routeIdToAppInfo_)];
-  }
-
-  /**
-   * @override
-   */
-  loadSavedData() {
-    const savedData = PersistentDataManager.getTemporaryData(this);
-    if (savedData) {
-      this.routeIdToAppInfo_ = new Map(savedData);
-    }
-  }
-};
-
-exports = ActivityRecords;
diff --git a/providers/dial/dial_activity_records_test.js b/providers/dial/dial_activity_records_test.js
deleted file mode 100644
index 38ff262..0000000
--- a/providers/dial/dial_activity_records_test.js
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.ActivityRecordsTest');
-goog.setTestOnly('mr.dial.ActivityRecordsTest');
-
-const Activity = goog.require('mr.dial.Activity');
-const ActivityRecords = goog.require('mr.dial.ActivityRecords');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const Route = goog.require('mr.Route');
-const UnitTestUtils = goog.require('mr.UnitTestUtils');
-
-describe('DIAL ActivityRecords Tests', function() {
-  let records;
-  let mockCallbacks;
-  let activity1;
-  let activity2;
-
-  beforeEach(function() {
-    UnitTestUtils.mockMojoApi();
-    UnitTestUtils.mockChromeApi();
-    let route = new Route(
-        'routeId1', 'presentationId1', 'sinkId1', null, false, 'description1',
-        'imageUrl1');
-    activity1 = new Activity(route, 'app1');
-    route = new Route(
-        'routeId2', 'presentationId2', 'sinkId2', null, true, 'description2',
-        'imageUrl2');
-    activity2 = new Activity(route, 'app2');
-    mockCallbacks = jasmine.createSpyObj(
-        'ActivityCallbacks',
-        ['onActivityAdded', 'onActivityRemoved', 'onActivityUpdated']);
-    records = new ActivityRecords(mockCallbacks);
-    records.init();
-  });
-
-  afterEach(function() {
-    PersistentDataManager.clear();
-    UnitTestUtils.restoreChromeApi();
-  });
-
-  it('Add activity', function() {
-    records.add(activity1);
-    expect(records.getByRouteId(activity1.route.id)).toEqual(activity1);
-    expect(mockCallbacks.onActivityAdded.calls.count()).toBe(1);
-    expect(mockCallbacks.onActivityAdded).toHaveBeenCalledWith(activity1);
-    records.add(activity1);
-    expect(mockCallbacks.onActivityAdded.calls.count()).toBe(1);
-  });
-
-  it('Get activity and route', function() {
-    records.add(activity1);
-    expect(records.getByRouteId(activity1.route.id)).toEqual(activity1);
-    expect(records.getBySinkId(activity1.route.sinkId)).toEqual(activity1);
-    expect(records.getRoutes()).toEqual([activity1.route]);
-    records.add(activity2);
-    expect(records.getByRouteId(activity2.route.id)).toEqual(activity2);
-    expect(records.getBySinkId(activity2.route.sinkId)).toEqual(activity2);
-    expect(records.getRoutes()).toEqual([activity1.route, activity2.route]);
-  });
-
-  it('Remove activity', function() {
-    records.add(activity1);
-    records.add(activity2);
-    records.removeByRouteId(activity2.route.id);
-    expect(mockCallbacks.onActivityRemoved.calls.count()).toBe(1);
-    expect(mockCallbacks.onActivityRemoved).toHaveBeenCalledWith(activity2);
-    records.removeByRouteId(activity2.route.id);
-    expect(mockCallbacks.onActivityRemoved.calls.count()).toBe(1);
-    expect(records.getByRouteId(activity2.route.id)).toEqual(null);
-    expect(records.getBySinkId(activity2.route.sinkId)).toEqual(null);
-    expect(records.getRoutes()).toEqual([activity1.route]);
-
-    records.removeBySinkId(activity1.route.sinkId);
-    expect(mockCallbacks.onActivityRemoved.calls.count()).toBe(2);
-    expect(mockCallbacks.onActivityRemoved).toHaveBeenCalledWith(activity1);
-    expect(records.getRoutes()).toEqual([]);
-  });
-
-  it('Save without any data', function() {
-    expect(records.getRoutes()).toEqual([]);
-    PersistentDataManager.suspendForTest();
-    records = new ActivityRecords(mockCallbacks);
-    records.loadSavedData();
-    expect(records.getRoutes()).toEqual([]);
-  });
-
-  it('Save with data', function() {
-    records.add(activity1);
-    records.add(activity2);
-    PersistentDataManager.suspendForTest();
-    records = new ActivityRecords(mockCallbacks);
-    records.loadSavedData();
-    expect(JSON.stringify(records.getRoutes())).toEqual(JSON.stringify([
-      activity1.route, activity2.route
-    ]));
-  });
-
-});
diff --git a/providers/dial/dial_analytics.js b/providers/dial/dial_analytics.js
deleted file mode 100644
index 549cc49..0000000
--- a/providers/dial/dial_analytics.js
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview Defines UMA analytics specific to the DIAL provider.
- */
-
-goog.provide('mr.DialAnalytics');
-
-goog.require('mr.Analytics');
-
-
-/** @enum {string} */
-mr.DialAnalytics.Metric = {
-  DEVICE_DESCRIPTION_FAILURE: 'MediaRouter.Dial.Device.Description.Failure',
-  DEVICE_DESCRIPTION_FROM_CACHE: 'MediaRouter.Dial.Device.Description.Cached',
-  DIAL_CREATE_ROUTE: 'MediaRouter.Dial.CreateRoute',
-  DIAL_TERMINATE_ROUTE: 'MediaRouter.Dial.TerminateRoute',
-  NON_CAST_DISCOVERY: 'MediaRouter.Dial.Sink.Discovered.NonCast',
-  PARSE_MESSAGE: 'MediaRouter.Dial.ParseMessage'
-};
-
-
-/**
- * Possible values for the route creation analytics.
- * @enum {number}
- */
-mr.DialAnalytics.DialCreateRouteResult = {
-  SUCCESS: 0,
-  SINK_NOT_FOUND: 1,
-  APP_INFO_NOT_FOUND: 2,
-  APP_LAUNCH_FAILED: 3,
-  UNSUPPORTED_SOURCE: 4,
-  ROUTE_ALREADY_EXISTS: 5
-};
-
-
-/** @enum {number} */
-mr.DialAnalytics.DialTerminateRouteResult = {
-  SUCCESS: 0,
-  ROUTE_NOT_FOUND: 1,
-  SINK_NOT_FOUND: 2,
-  STOP_APP_FAILED: 3,
-};
-
-
-/**
- * Possible values for device description failures.
- * @enum {number}
- */
-mr.DialAnalytics.DeviceDescriptionFailures = {
-  ERROR: 0,
-  PARSE: 1,
-  EMPTY: 2
-};
-
-
-/** @enum {number} */
-mr.DialAnalytics.DialParseMessageResult = {
-  SUCCESS: 0,
-  PARSE_ERROR: 1,
-  INVALID_MESSAGE: 2
-};
-
-
-/**
- * Records analytics around route creation.
- * @param {!mr.DialAnalytics.DialCreateRouteResult} value
- */
-mr.DialAnalytics.recordCreateRoute = function(value) {
-  mr.Analytics.recordEnum(
-      mr.DialAnalytics.Metric.DIAL_CREATE_ROUTE, value,
-      mr.DialAnalytics.DialCreateRouteResult);
-};
-
-
-/** @param {!mr.DialAnalytics.DialTerminateRouteResult} value */
-mr.DialAnalytics.recordTerminateRoute = function(value) {
-  mr.Analytics.recordEnum(
-      mr.DialAnalytics.Metric.DIAL_TERMINATE_ROUTE, value,
-      mr.DialAnalytics.DialTerminateRouteResult);
-};
-
-/**
- * Records a failure with the device description.
- * @param {!mr.DialAnalytics.DeviceDescriptionFailures} value The failure
- * reason.
- */
-mr.DialAnalytics.recordDeviceDescriptionFailure = function(value) {
-  mr.Analytics.recordEnum(
-      mr.DialAnalytics.Metric.DEVICE_DESCRIPTION_FAILURE, value,
-      mr.DialAnalytics.DeviceDescriptionFailures);
-};
-
-
-/**
- * Records that device description was retreived from the cache.
- */
-mr.DialAnalytics.recordDeviceDescriptionFromCache = function() {
-  mr.Analytics.recordEvent(
-      mr.DialAnalytics.Metric.DEVICE_DESCRIPTION_FROM_CACHE);
-};
-
-
-/**
- * Records that a device was discovered by DIAL that didn't support the cast
- * protocol.
- */
-mr.DialAnalytics.recordNonCastDiscovery = function() {
-  mr.Analytics.recordEvent(mr.DialAnalytics.Metric.NON_CAST_DISCOVERY);
-};
-
-
-/** @param {!mr.DialAnalytics.DialParseMessageResult} value */
-mr.DialAnalytics.recordParseMessageResult = function(value) {
-  mr.Analytics.recordEnum(
-      mr.DialAnalytics.Metric.PARSE_MESSAGE, value,
-      mr.DialAnalytics.DialParseMessageResult);
-};
-
-
-/**
- * Histogram name for available DIAL devices count.
- * @private @const {string}
- */
-mr.DialAnalytics.AVAILABLE_DEVICES_COUNT_ =
-    'MediaRouter.Dial.AvailableDevicesCount';
-
-
-/**
- * Histogram name for known DIAL devices count.
- * @private @const {string}
- */
-mr.DialAnalytics.KNOWN_DEVICES_COUNT_ = 'MediaRouter.Dial.KnownDevicesCount';
-
-
-/**
- * Records device counts.
- * @param {!mr.DeviceCounts} deviceCounts
- */
-mr.DialAnalytics.recordDeviceCounts = function(deviceCounts) {
-  mr.Analytics.recordSmallCount(
-      mr.DialAnalytics.AVAILABLE_DEVICES_COUNT_,
-      deviceCounts.availableDeviceCount);
-  mr.Analytics.recordSmallCount(
-      mr.DialAnalytics.KNOWN_DEVICES_COUNT_, deviceCounts.knownDeviceCount);
-};
diff --git a/providers/dial/dial_analytics_test.js b/providers/dial/dial_analytics_test.js
deleted file mode 100644
index faa3c36..0000000
--- a/providers/dial/dial_analytics_test.js
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.setTestOnly();
-goog.require('mr.DialAnalytics');
-
-describe('Dial Analytics', function() {
-
-  beforeEach(function() {
-    chrome.metricsPrivate = jasmine.createSpyObj(
-        ['recordSmallCount', 'recordUserAction', 'recordValue']);
-  });
-
-  it('should record a Dial.CreateRoute result', function() {
-    const testConfig = {
-      'metricName': 'MediaRouter.Dial.CreateRoute',
-      'type': 'histogram-linear',
-      'min': 1,
-      'max': 6,
-      'buckets': 7
-    };
-    let numCalls = 0;
-    for (key in mr.DialAnalytics.DialCreateRouteResult) {
-      const value = mr.DialAnalytics.DialCreateRouteResult[key];
-      mr.DialAnalytics.recordCreateRoute(value);
-      expect(chrome.metricsPrivate.recordValue.calls.count()).toBe(++numCalls);
-      expect(chrome.metricsPrivate.recordValue)
-          .toHaveBeenCalledWith(testConfig, value);
-    }
-  });
-
-  it('should not record an unknown Dial.CreateRoute result', function() {
-    mr.DialAnalytics.recordCreateRoute('test');
-    expect(chrome.metricsPrivate.recordValue).not.toHaveBeenCalled();
-  });
-
-  it('should record a Dial.TerminateRoute result', function() {
-    const testConfig = {
-      'metricName': 'MediaRouter.Dial.TerminateRoute',
-      'type': 'histogram-linear',
-      'min': 1,
-      'max': 4,
-      'buckets': 5
-    };
-    let numCalls = 0;
-    for (key in mr.DialAnalytics.DialTerminateRouteResult) {
-      const value = mr.DialAnalytics.DialTerminateRouteResult[key];
-      mr.DialAnalytics.recordTerminateRoute(value);
-      expect(chrome.metricsPrivate.recordValue.calls.count()).toBe(++numCalls);
-      expect(chrome.metricsPrivate.recordValue)
-          .toHaveBeenCalledWith(testConfig, value);
-    }
-  });
-
-  it('should not record an unknown Dial.TerminateRoute result', function() {
-    mr.DialAnalytics.recordTerminateRoute('test');
-    expect(chrome.metricsPrivate.recordValue).not.toHaveBeenCalled();
-  });
-
-  it('should record a Dial.Device.Description.Failure result', function() {
-    const testConfig = {
-      'metricName': 'MediaRouter.Dial.Device.Description.Failure',
-      'type': 'histogram-linear',
-      'min': 1,
-      'max': 3,
-      'buckets': 4
-    };
-    let numCalls = 0;
-    for (key in mr.DialAnalytics.DeviceDescriptionFailures) {
-      const value = mr.DialAnalytics.DeviceDescriptionFailures[key];
-      mr.DialAnalytics.recordDeviceDescriptionFailure(value);
-      expect(chrome.metricsPrivate.recordValue.calls.count()).toBe(++numCalls);
-      expect(chrome.metricsPrivate.recordValue)
-          .toHaveBeenCalledWith(testConfig, value);
-    }
-  });
-
-  it('should not record an unknown Dial.Device.Description.Failure',
-     function() {
-       mr.DialAnalytics.recordDeviceDescriptionFailure('test');
-       expect(chrome.metricsPrivate.recordValue).not.toHaveBeenCalled();
-     });
-
-  it('should record a Device Description From Cache action', function() {
-    mr.DialAnalytics.recordDeviceDescriptionFromCache();
-    expect(chrome.metricsPrivate.recordUserAction.calls.count()).toBe(1);
-    expect(chrome.metricsPrivate.recordUserAction)
-        .toHaveBeenCalledWith('MediaRouter.Dial.Device.Description.Cached');
-  });
-
-  it('should record a non-Cast Sink Discovery action', function() {
-    mr.DialAnalytics.recordNonCastDiscovery();
-    expect(chrome.metricsPrivate.recordUserAction.calls.count()).toBe(1);
-    expect(chrome.metricsPrivate.recordUserAction)
-        .toHaveBeenCalledWith('MediaRouter.Dial.Sink.Discovered.NonCast');
-  });
-
-  it('DeviceCounts is recorded with recordSmallCount', () => {
-    const deviceCounts = {availableDeviceCount: 5, knownDeviceCount: 8};
-    mr.DialAnalytics.recordDeviceCounts(deviceCounts);
-    expect(chrome.metricsPrivate.recordSmallCount.calls.count()).toBe(2);
-    let args = chrome.metricsPrivate.recordSmallCount.calls.argsFor(0);
-    expect(args[0]).toBe(mr.DialAnalytics.AVAILABLE_DEVICES_COUNT_);
-    expect(args[1]).toBe(deviceCounts.availableDeviceCount);
-
-    args = chrome.metricsPrivate.recordSmallCount.calls.argsFor(1);
-    expect(args[0]).toBe(mr.DialAnalytics.KNOWN_DEVICES_COUNT_);
-    expect(args[1]).toBe(deviceCounts.knownDeviceCount);
-  });
-});
diff --git a/providers/dial/dial_app_discovery_service.js b/providers/dial/dial_app_discovery_service.js
deleted file mode 100644
index d612fa9..0000000
--- a/providers/dial/dial_app_discovery_service.js
+++ /dev/null
@@ -1,480 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.AppDiscoveryService');
-
-const ActivityRecords = goog.require('mr.dial.ActivityRecords');
-const DialClient = goog.require('mr.dial.Client');
-const DialSink = goog.require('mr.dial.Sink');
-const DialSinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const Logger = goog.require('mr.Logger');
-const PersistentData = goog.require('mr.PersistentData');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const PromiseUtils = goog.require('mr.PromiseUtils');
-const SinkDiscoveryService = goog.require('mr.dial.SinkDiscoveryService');
-
-
-/**
- * Service for determining whether a sink supports a given DIAL app.
- * @implements {PersistentData}
- */
-const AppDiscoveryService = class {
-  /**
-   * @param {!SinkDiscoveryService} discoveryService
-   * @param {!ActivityRecords} activityRecords
-   */
-  constructor(discoveryService, activityRecords) {
-    /** @private @const {?Logger} */
-    this.logger_ = Logger.getInstance('mr.dial.AppDiscoveryService');
-
-    /**
-     * Names of applications that are actively being queried for.
-     * @private {!Set<string>}
-     */
-    this.registeredApps_ = new Set();
-
-    /**
-     * @private @const {!SinkDiscoveryService}
-     */
-    this.discoveryService_ = discoveryService;
-
-    /**
-     * @private @const {!ActivityRecords}
-     */
-    this.activityRecords_ = activityRecords;
-
-    /**
-     * Keeps track of pending requests to avoid duplication.  Values are
-     * Promises returning strings of the form <sink.getId()>:<appName>.
-     * @private @const {!Map<string, !Promise<!DialClient.AppInfo>>}
-     */
-    this.pendingRequests_ = new Map();
-
-    /**
-     * DIAL clients used by this service.  Keys are sink ids.
-     * @private @const {!Map<string, !DialClient.Client>}
-     */
-    this.clientsBySinkId_ = new Map();
-
-    /**
-     * The timeout ID for the next scan.
-     * @private {?number}
-     */
-    this.timeoutId_ = null;
-
-    /**
-     * Whether the service is running.
-     * @private {boolean}
-     */
-    this.running_ = false;
-  }
-
-  init() {
-    PersistentDataManager.register(this);
-  }
-
-  /**
-   * Starts discovery.
-   */
-  start() {
-    this.logger_.info('Starting periodic scanning.');
-    if (!this.running_) {
-      this.running_ = true;
-      this.doScan_();
-    }
-  }
-
-  /**
-   * Stops discovery. Also aborts all outstanding discovery requests.
-   */
-  stop() {
-    this.logger_.info('Stopping periodic scanning.');
-    if (!this.running_) return;
-    this.running_ = false;
-    if (this.timeoutId_) {
-      clearTimeout(this.timeoutId_);
-      this.timeoutId_ = null;
-    }
-    this.pendingRequests_.clear();
-  }
-
-  /**
-   * Registers an application name that should be queried. Starts periodic
-   * scanning if it hasn't already started. Otherwise, issues an out-of-band
-   * query for the app against all discovered sinks.
-   * @param {string} appName
-   */
-  registerApp(appName) {
-    if (this.registeredApps_.has(appName) &&
-        !this.anyUnknownAppStatus_(appName)) {
-      // No need to scan since status for appName is known for all sinks.
-      return;
-    }
-
-    this.registeredApps_.add(appName);
-
-    if (this.discoveryService_.getSinkCount() == 0) {
-      // No sinks, no need to scan.
-      return;
-    }
-    if (!this.running_) {
-      this.start();
-    } else {
-      this.discoveryService_.getSinks().forEach(
-          this.doScanSinkForApp_.bind(this, appName));
-    }
-  }
-
-  /**
-   * Unregisters an application name.
-   * @param {string} appName
-   */
-  unregisterApp(appName) {
-    this.registeredApps_.delete(appName);
-  }
-
-  /**
-   * @return {!Array<string>}
-   */
-  getRegisteredApps() {
-    return Array.from(this.registeredApps_);
-  }
-
-  /**
-   * @return {number}
-   */
-  getAppCount() {
-    return this.registeredApps_.size;
-  }
-
-  /**
-   * Issues app info queries and updates sink app status and activities
-   * according to results. Queries will be made for the following:
-   * 1) All registered apps, against all discovered sinks. Note that a (app,
-   * sink) combination is only queried if its status is unknown, or if enough
-   * time has elapsed since its previous status was known.
-   * 2) Each activity's app against its sink.
-   * Once all queries have returned and all updates have been made, schedules a
-   * scan in the future.
-   * @private
-   */
-  doScan_() {
-    this.logger_.info('Start app status scan.');
-    const promises = [];
-
-    // Scans all sinks against all registered apps.
-    this.discoveryService_.getSinks().forEach(sink => {
-      promises.push.apply(promises, this.scanSink(sink));
-    });
-
-    // Scans all activities.
-    this.activityRecords_.getActivities().forEach(activity => {
-      promises.push(this.scanActivity_(activity));
-    });
-
-    PromiseUtils.allSettled(promises).then(() => {
-      if (this.running_ && !this.timeoutId_) {
-        this.logger_.fine('Scan complete; scheduling for next scan.');
-        // NOTE(imcheng): setTimeout with a large delay does not work well in
-        // event pages. Instead we should be using chrome.alarms API, but note
-        // that it is subject to a minmum delay of 1 minute.
-        this.timeoutId_ = setTimeout(() => {
-          this.doRescan_();
-        }, AppDiscoveryService.CHECK_INTERVAL_MILLIS);
-      }
-    });
-  }
-
-  /**
-   * Clears the timer and starts a round of scanning. Only valid when called
-   * from a timer.
-   * @private
-   */
-  doRescan_() {
-    this.logger_.fine('Start app status scan (timer-based)');
-    this.timeoutId_ = null;
-    this.doScan_();
-  }
-
-  /**
-   * Asynchronously scans a sink against all registered apps and updates its app
-   * status map if needed.
-   * @param {!DialSink} sink
-   * @return {!Array<!Promise<void>>} If the sink does not support app
-   *     the getting app info, returns an empty array. Otherwise, returns a list
-   *     of Promises, each corresponding to a registered app, resolved when the
-   *     sink's app status has been updated.
-   */
-  scanSink(sink) {
-    if (!sink.supportsAppAvailability()) {
-      return [];
-    }
-
-    const promises = [];
-    for (let appName of this.registeredApps_) {
-      promises.push(this.doScanSinkForApp_(appName, sink));
-    }
-    return promises;
-  }
-
-  /**
-   * Issues an app info query for the given app to the given sink, and updates
-   * the sink's app status map with the response.
-   * @param {string} appName
-   * @param {!DialSink} sink
-   * @return {!Promise<void>} Resolved when the sink's app status has been
-   *     updated.
-   * @private
-   */
-  doScanSinkForApp_(appName, sink) {
-    if (sink.getAppStatus(appName) != DialSinkAppStatus.UNKNOWN &&
-        Date.now() - sink.getAppStatusTimeStamp(appName) <
-            AppDiscoveryService.CACHE_PERIOD_) {
-      // App status already known and not expired.
-      return Promise.resolve();
-    }
-    if (!sink.supportsAppAvailability()) {
-      return Promise.resolve();
-    }
-    this.logger_.fine(
-        'Querying ' + sink.getId() + ' for ' + appName +
-        ' to update app status');
-    return this.getAppInfo_(sink, appName)
-        .then(
-            appInfo => {
-              const newAppStatus = this.getAvailabilityFromAppInfo_(appInfo);
-              this.maybeUpdateAppStatus_(sink, appName, newAppStatus);
-            },
-            e => {
-              // Some devices return NOT_FOUND for GetAppInfo to indicate the
-              // app is unavailable.
-              if (e instanceof DialClient.AppInfoNotFoundError) {
-                this.maybeUpdateAppStatus_(
-                    sink, appName, DialSinkAppStatus.UNAVAILABLE);
-                return;
-              }
-              this.logger_.warning(
-                  'Failed to process app availability; ' + sink.getId() +
-                  ' does not support app availability');
-              sink.setSupportsAppAvailability(false);
-            });
-  }
-
-  /**
-   * Issues an app info query for the given activity's app to the activity's
-   * sink, and updates the activity records if the app is no longer running.
-   * @param {!mr.dial.Activity} activity
-   * @return {!Promise<void>} Resolved when the activity record has possibly
-   *     been updated.
-   * @private
-   */
-  scanActivity_(activity) {
-    const sink = this.discoveryService_.getSinkById(activity.route.sinkId);
-    if (!sink) {
-      this.logger_.warning(
-          'Activity refers to nonexistent sink: ' + activity.route.id);
-      return Promise.resolve();
-    }
-    if (!sink.supportsAppAvailability()) {
-      return Promise.resolve();
-    }
-    const appName = activity.appName;
-    this.logger_.fine(
-        'Querying ' + sink.getId() + ' for ' + appName + ' to update activity');
-    return this.getAppInfo_(sink, appName)
-        .then(
-            appInfo => this.maybeUpdateActivityRecord_(
-                /** @type {!DialSink} */ (sink), appName, appInfo),
-            e => this.doRemoveActivityRecord_(
-                /** @type {!DialSink} */ (sink), appName));
-  }
-
-  /**
-   * Gets the DIAL client associated with the given sink, or creates one if it
-   * does not exist.
-   * @param {!DialSink} sink
-   * @return {!DialClient.Client} A client instance for the given sink.
-   * @private
-   */
-  getDialClient_(sink) {
-    let client = this.clientsBySinkId_.get(sink.getId());
-    if (!client) {
-      client = new DialClient.Client(sink);
-      this.logger_.fine('Created DIAL client for ' + sink.getId());
-      this.clientsBySinkId_.set(sink.getId(), client);
-    }
-    return client;
-  }
-
-  /**
-   * Issues an app info query with the given sink's DIAL client. A query will
-   * not be issued if there is already a same one pending.
-   * @param {!DialSink} sink
-   * @param {string} appName
-   * @return {!Promise<!DialClient.AppInfo>} Resolved with the query response,
-   *     or rejected on error.
-   * @private
-   */
-  getAppInfo_(sink, appName) {
-    const requestId = AppDiscoveryService.getRequestId_(sink, appName);
-    let promise = this.pendingRequests_.get(requestId);
-    if (promise) {
-      return promise;
-    }
-
-    promise = this.getDialClient_(sink).getAppInfo(appName);
-    this.pendingRequests_.set(requestId, promise);
-    const cleanup = () => {
-      this.pendingRequests_.delete(requestId);
-    };
-    promise.then(cleanup, cleanup);
-    return promise;
-  }
-
-  /**
-   * Translates the given app info result into a DialSinkAppStatus value.
-   * @param {!DialClient.AppInfo} appInfo
-   * @return {DialSinkAppStatus}
-   * @private
-   */
-  getAvailabilityFromAppInfo_(appInfo) {
-    if (appInfo.name == 'Netflix') {
-      return this.getAppStatusFromNetflixAppInfo_(appInfo);
-    } else {
-      switch (appInfo.state) {
-        case DialClient.DialAppState.RUNNING:
-        case DialClient.DialAppState.STOPPED:
-          return DialSinkAppStatus.AVAILABLE;
-        default:
-          return DialSinkAppStatus.UNAVAILABLE;
-      }
-    }
-  }
-
-  /**
-   * Returns app status from a Netflix app info.
-   * @param {!DialClient.AppInfo} appInfo The app info from DIAL GET.
-   * @return {DialSinkAppStatus}
-   * @private
-   */
-  getAppStatusFromNetflixAppInfo_(appInfo) {
-    const isNetflixWebsocket =
-        appInfo.extraData && appInfo.extraData['capabilities'] == 'websocket';
-    if (isNetflixWebsocket &&
-        (appInfo.state == DialClient.DialAppState.RUNNING ||
-         appInfo.state == DialClient.DialAppState.STOPPED)) {
-      return DialSinkAppStatus.AVAILABLE;
-    } else {
-      return DialSinkAppStatus.UNAVAILABLE;
-    }
-  }
-
-  /**
-   * Returns the request ID to use for an app info request.
-   * @param {!DialSink} sink
-   * @param {string} appName
-   * @return {string}
-   * @private
-   */
-  static getRequestId_(sink, appName) {
-    return sink.getId() + ':' + appName;
-  }
-
-  /**
-   * Checks whether the status of an app on a sink has changed, and if so
-   * notifies discovery service.
-   * @param {!DialSink} sink
-   * @param {string} appName
-   * @param {DialSinkAppStatus} newAppStatus
-   * @private
-   */
-  maybeUpdateAppStatus_(sink, appName, newAppStatus) {
-    this.logger_.fine(
-        'Got app status ' + newAppStatus + ' from ' + sink.getId() + ' for ' +
-        appName);
-    const oldAppStatus = sink.getAppStatus(appName);
-    sink.setAppStatus(appName, newAppStatus);
-    if (newAppStatus != oldAppStatus) {
-      this.discoveryService_.onAppStatusChanged(appName, sink);
-    }
-  }
-
-  /**
-   * Checks whether the given app is no longer running on the given sink, and if
-   * so notifies activity records.
-   * @param {!DialSink} sink
-   * @param {string} appName
-   * @param {!DialClient.AppInfo} appInfo
-   * @private
-   */
-  maybeUpdateActivityRecord_(sink, appName, appInfo) {
-    if (appInfo.state != DialClient.DialAppState.RUNNING) {
-      this.doRemoveActivityRecord_(sink, appName);
-    }
-  }
-
-  /**
-   * Removes the activity record with the given sink and app name, if it exists.
-   * @param {!DialSink} sink
-   * @param {string} appName
-   * @private
-   */
-  doRemoveActivityRecord_(sink, appName) {
-    const activity = this.activityRecords_.getBySinkId(sink.getId());
-    if (activity && activity.appName == appName) {
-      this.activityRecords_.removeByRouteId(activity.route.id);
-    }
-  }
-
-  /**
-   * Checks if there is a sink whose status of appName is unknown.
-   * @param {string} appName
-   * @return {boolean}
-   * @private
-   */
-  anyUnknownAppStatus_(appName) {
-    return this.discoveryService_.getSinks().some(
-        s => s.getAppStatus(appName) == DialSinkAppStatus.UNKNOWN);
-  }
-
-  /**
-   * @override
-   */
-  getStorageKey() {
-    return 'dial.AppDiscoveryService';
-  }
-
-  /**
-   * @override
-   */
-  getData() {
-    return [this.getRegisteredApps()];
-  }
-
-  /**
-   * @override
-   */
-  loadSavedData() {
-    const savedData = PersistentDataManager.getTemporaryData(this);
-    this.registeredApps_ = new Set(savedData || []);
-  }
-};
-
-
-/**
- * The interval for periodic scanning.
- * @package @const {number}
- */
-AppDiscoveryService.CHECK_INTERVAL_MILLIS = 60 * 1000;
-
-
-/**
- * The amount of time an availability result for an app (both AVAILABLE and
- * UNAVAILABLE) will be cached for.
- * @private @const {number}
- */
-AppDiscoveryService.CACHE_PERIOD_ = 60 * 60 * 1000;
-
-
-exports = AppDiscoveryService;
diff --git a/providers/dial/dial_app_discovery_service_test.js b/providers/dial/dial_app_discovery_service_test.js
deleted file mode 100644
index cd7edea..0000000
--- a/providers/dial/dial_app_discovery_service_test.js
+++ /dev/null
@@ -1,362 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.AppDiscoveryServiceTest');
-goog.setTestOnly('mr.dial.AppDiscoveryServiceTest');
-
-const Activity = goog.require('mr.dial.Activity');
-const ActivityRecords = goog.require('mr.dial.ActivityRecords');
-const AppDiscoveryService = goog.require('mr.dial.AppDiscoveryService');
-const DialClient = goog.require('mr.dial.Client');
-const DialSink = goog.require('mr.dial.Sink');
-const DialSinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const Route = goog.require('mr.Route');
-const UnitTestUtils = goog.require('mr.UnitTestUtils');
-
-describe('DIAL AppDiscoveryService Tests', function() {
-  let activityRecords;
-  let service;
-  let mockClock;
-  let mockDiscoveryService;
-  let mockActivityCallbacks;
-  let sink1;
-  let sink2;
-  let sink3;
-  let mockDialClient;
-  let stoppedAppInfo;
-  let runningAppInfo;
-  let installableAppInfo;
-  let stoppedAppInfoWithWebsocket;
-
-  const setUpGetAppInfoResponse = function(appInfo) {
-    mockDialClient.getAppInfo.and.callFake(() => Promise.resolve(appInfo));
-  };
-
-  const setUpGetAppInfoError = function() {
-    mockDialClient.getAppInfo.and.callFake(
-        () => Promise.reject(new Error('getAppInfo failed')));
-  };
-
-  const setUpGetAppInfoNotFoundError = function() {
-    mockDialClient.getAppInfo.and.callFake(
-        () => Promise.reject(new DialClient.AppInfoNotFoundError()));
-  };
-
-  beforeEach(function() {
-    mockClock = UnitTestUtils.useMockClockAndPromises();
-
-    mockDiscoveryService = jasmine.createSpyObj(
-        'discoveryService',
-        ['getSinks', 'getSinkById', 'getSinkCount', 'onAppStatusChanged']);
-    mockActivityCallbacks = jasmine.createSpyObj(
-        'activityCallbacks',
-        ['onActivityAdded', 'onActivityRemoved', 'onActivityUpdated']);
-    activityRecords = new ActivityRecords(mockActivityCallbacks);
-    service = new AppDiscoveryService(mockDiscoveryService, activityRecords);
-
-    sink1 = new DialSink('sink1', '1').setSupportsAppAvailability(true);
-    sink2 = new DialSink('sink2', '2').setSupportsAppAvailability(true);
-    sink3 = new DialSink('sink3', '3').setSupportsAppAvailability(false);
-    mockDialClient = jasmine.createSpyObj('dialClient', ['getAppInfo']);
-    spyOn(AppDiscoveryService.prototype, 'getDialClient_')
-        .and.returnValue(mockDialClient);
-    stoppedAppInfo = {'state': DialClient.DialAppState.STOPPED};
-    runningAppInfo = {'state': DialClient.DialAppState.RUNNING};
-    installableAppInfo = {'state': DialClient.DialAppState.INSTALLABLE};
-    stoppedAppInfoWithWebsocket = {
-      'name': 'Netflix',
-      'state': DialClient.DialAppState.STOPPED,
-      'extraData': {'capabilities': 'websocket'}
-    };
-
-    chrome.runtime = {
-      id: 'fakeId',
-      getManifest: function() {
-        return {version: 'fakeVersion'};
-      }
-    };
-  });
-
-  afterEach(function() {
-    service.stop();
-    UnitTestUtils.restoreRealClockAndPromises();
-    PersistentDataManager.clear();
-  });
-
-  describe('Tests registerApp', function() {
-    beforeEach(function() {
-      mockDiscoveryService.getSinks.and.returnValue([sink1, sink2, sink3]);
-      mockDiscoveryService.getSinkCount.and.returnValue(3);
-    });
-
-    const expectAppStatus = function(expectedAppStatus, appName) {
-      service.init();
-
-      expect(sink1.getAppStatus(appName)).toEqual(DialSinkAppStatus.UNKNOWN);
-      expect(sink2.getAppStatus(appName)).toEqual(DialSinkAppStatus.UNKNOWN);
-      expect(sink3.getAppStatus(appName)).toEqual(DialSinkAppStatus.UNKNOWN);
-
-      service.registerApp(appName);
-
-      service.start();
-      // Let internal promises to resolve or reject.
-      mockClock.tick(1);
-
-      expect(sink1.getAppStatus(appName)).toEqual(expectedAppStatus);
-      expect(sink2.getAppStatus(appName)).toEqual(expectedAppStatus);
-      expect(sink3.getAppStatus(appName)).toEqual(DialSinkAppStatus.UNKNOWN);
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
-    };
-
-    it('Response indicates app was stopped', function() {
-      setUpGetAppInfoResponse(stoppedAppInfo);
-      expectAppStatus(DialSinkAppStatus.AVAILABLE, 'YouTube');
-    });
-
-    it('Response indicates app was running', function() {
-      setUpGetAppInfoResponse(runningAppInfo);
-      expectAppStatus(DialSinkAppStatus.AVAILABLE, 'YouTube');
-    });
-
-    it('Response indicates app was installable', function() {
-      setUpGetAppInfoResponse(installableAppInfo);
-      expectAppStatus(DialSinkAppStatus.UNAVAILABLE, 'YouTube');
-    });
-
-    it('Response has invalid app info', function() {
-      setUpGetAppInfoError();
-      expectAppStatus(DialSinkAppStatus.UNKNOWN, 'YouTube');
-      expect(sink1.supportsAppAvailability()).toBe(false);
-      expect(sink2.supportsAppAvailability()).toBe(false);
-    });
-
-    it('Response indicates not found', function() {
-      setUpGetAppInfoNotFoundError();
-      expectAppStatus(DialSinkAppStatus.UNAVAILABLE, 'YouTube');
-    });
-
-    it('Netflix with special stopped info', function() {
-      setUpGetAppInfoResponse(stoppedAppInfoWithWebsocket);
-      expectAppStatus(DialSinkAppStatus.AVAILABLE, 'Netflix');
-    });
-
-    it('Netflix with normal stopped info', function() {
-      stoppedAppInfo.name = 'Netflix';
-      setUpGetAppInfoResponse(stoppedAppInfo);
-      expectAppStatus(DialSinkAppStatus.UNAVAILABLE, 'Netflix');
-    });
-
-    it('No new query generated when registering existing app with known status',
-       function() {
-         setUpGetAppInfoResponse(stoppedAppInfo);
-         expectAppStatus(DialSinkAppStatus.AVAILABLE, 'YouTube');
-         // register again
-         service.registerApp('YouTube');
-         mockClock.tick(1);
-         expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
-         // unregister does nothing because sink already had the app status.
-         service.unregisterApp('YouTube');
-         service.registerApp('YouTube');
-         mockClock.tick(1);
-         expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
-         // unless clear app status first.
-         sink1.clearAppStatus();
-         sink2.clearAppStatus();
-         service.unregisterApp('YouTube');
-         service.registerApp('YouTube');
-         mockClock.tick(1);
-         expect(mockDialClient.getAppInfo.calls.count()).toBe(4);
-       });
-
-    it('No new query generated when register existing app with unknown status',
-       function() {
-         setUpGetAppInfoError();
-         expectAppStatus(DialSinkAppStatus.UNKNOWN, 'YouTube');
-         // Make sink1 have known status. But sink2 has unknown status.
-         sink1.setAppStatus('YouTube', DialSinkAppStatus.UNAVAILABLE);
-         // register again
-         service.registerApp('YouTube');
-         mockClock.tick(1);
-         // No re-query
-         expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
-       });
-  });
-
-  describe('Tests app status caching and onAppStatusChanged', function() {
-    beforeEach(function() {
-      mockDiscoveryService.getSinks.and.returnValue([sink1]);
-      mockDiscoveryService.getSinkCount.and.returnValue(1);
-    });
-
-    it('Known app status does not change during caching period', function() {
-      service.init();
-      setUpGetAppInfoResponse(stoppedAppInfo);
-      expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
-      service.registerApp('YouTube');
-      service.start();
-      mockClock.tick(1);
-      expect(sink1.getAppStatus('YouTube'))
-          .toEqual(DialSinkAppStatus.AVAILABLE);
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
-      expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
-
-      // Make app unavailable
-      setUpGetAppInfoNotFoundError();
-      service.doScan_();
-      mockClock.tick(1);
-      // No new query and app is still available since cache is not expired.
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
-      expect(sink1.getAppStatus('YouTube'))
-          .toEqual(DialSinkAppStatus.AVAILABLE);
-      expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
-    });
-
-    it('Does not re-query app status when getAppInfo throws error', function() {
-      service.init();
-      setUpGetAppInfoError();
-      expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
-      service.registerApp('YouTube');
-      service.start();
-      mockClock.tick(1);
-      expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
-      expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(0);
-
-      service.doScan_();
-      mockClock.tick(1);
-      // No new query
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
-      expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
-      expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(0);
-    });
-
-    it('Cache expires, re-query, different status', function() {
-      service.init();
-      setUpGetAppInfoResponse(stoppedAppInfo);
-      expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
-      service.registerApp('YouTube');
-      service.start();
-      mockClock.tick(1);
-      expect(sink1.getAppStatus('YouTube'))
-          .toEqual(DialSinkAppStatus.AVAILABLE);
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
-      expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
-
-      // Make app unavailable
-      setUpGetAppInfoNotFoundError();
-      // Make cache expire
-      mockClock.tick(AppDiscoveryService.CACHE_PERIOD_);
-      service.doScan_();
-      mockClock.tick(1);
-      // new query and app becomes unavailable
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
-      expect(sink1.getAppStatus('YouTube'))
-          .toEqual(DialSinkAppStatus.UNAVAILABLE);
-      expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(2);
-    });
-
-    it('Cache expires, re-query, same status', function() {
-      service.init();
-      setUpGetAppInfoResponse(stoppedAppInfo);
-      expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
-      service.registerApp('YouTube');
-      service.start();
-      mockClock.tick(1);
-      expect(sink1.getAppStatus('YouTube'))
-          .toEqual(DialSinkAppStatus.AVAILABLE);
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
-      expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
-
-      // Make cache expire
-      mockClock.tick(AppDiscoveryService.CACHE_PERIOD_);
-      service.doScan_();
-      mockClock.tick(1);
-      // New query and app becomes unavailable
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
-      expect(sink1.getAppStatus('YouTube'))
-          .toEqual(DialSinkAppStatus.AVAILABLE);
-      // Did not trigger app status changed event
-      expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
-    });
-  });
-
-  describe('Tests activity scanning', function() {
-    beforeEach(function() {
-      mockDiscoveryService.getSinks.and.returnValue([sink1, sink2, sink3]);
-      mockDiscoveryService.getSinkCount.and.returnValue(3);
-      mockDiscoveryService.getSinkById.and.returnValue(sink1);
-
-      service.init();
-      const route = Route.createRoute(
-          'presentationId', 'providerName', sink1.getId(), 'source', true,
-          'description', null);
-      const activity = new Activity(route, 'YouTube');
-      activityRecords.add(activity);
-      expect(mockActivityCallbacks.onActivityAdded).toHaveBeenCalled();
-    });
-
-    it('Activity is removed when app is no longer running', function() {
-      setUpGetAppInfoResponse(stoppedAppInfo);
-      service.start();
-      mockClock.tick(1);
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
-      expect(mockActivityCallbacks.onActivityRemoved.calls.count()).toBe(1);
-      expect(activityRecords.getActivityCount()).toBe(0);
-    });
-
-    it('Activity is not removed when app is still running', function() {
-      setUpGetAppInfoResponse(runningAppInfo);
-      service.start();
-      mockClock.tick(1);
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
-      expect(mockActivityCallbacks.onActivityRemoved).not.toHaveBeenCalled();
-      expect(activityRecords.getActivityCount()).toBe(1);
-
-      // Trigger periodic rescan
-      mockClock.tick(AppDiscoveryService.CHECK_INTERVAL_MILLIS + 1);
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
-      expect(mockActivityCallbacks.onActivityRemoved).not.toHaveBeenCalled();
-      expect(activityRecords.getActivityCount()).toBe(1);
-
-      // No more periodic rescan.
-      service.stop();
-      mockClock.tick(AppDiscoveryService.CHECK_INTERVAL_MILLIS + 1);
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
-    });
-
-    it('Activity scanning not duplicated with app scanning', function() {
-      setUpGetAppInfoResponse(stoppedAppInfo);
-      service.registerApp('YouTube');
-      mockClock.tick(1);
-      // One for sink1 and one for sink2. Activity scanning does not issue a
-      // duplicated request. Both app status and activity status can be updated
-      // with the same response.
-      expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
-      expect(sink1.getAppStatus('YouTube'))
-          .toEqual(DialSinkAppStatus.AVAILABLE);
-      expect(sink2.getAppStatus('YouTube'))
-          .toEqual(DialSinkAppStatus.AVAILABLE);
-      expect(mockActivityCallbacks.onActivityRemoved.calls.count()).toBe(1);
-      expect(activityRecords.getActivityCount()).toBe(0);
-    });
-  });
-
-  it('Persistent with data', function() {
-    mockDiscoveryService.getSinks.and.returnValue([]);
-    mockDiscoveryService.getSinkCount.and.returnValue(0);
-    const mockServiceToSuspend = new AppDiscoveryService(
-        mockDiscoveryService, new ActivityRecords(mockActivityCallbacks));
-    mockServiceToSuspend.init();
-    mockServiceToSuspend.registerApp('app1');
-    mockServiceToSuspend.registerApp('app2');
-    PersistentDataManager.suspendForTest();
-
-    const mockServiceToLoad = new AppDiscoveryService(
-        mockDiscoveryService, new ActivityRecords(mockActivityCallbacks));
-    mockServiceToLoad.loadSavedData();
-    expect(mockServiceToLoad.getRegisteredApps()).toEqual(['app1', 'app2']);
-    expect(mockServiceToLoad.getAppCount()).toEqual(2);
-  });
-});
diff --git a/providers/dial/dial_client.js b/providers/dial/dial_client.js
deleted file mode 100644
index 443b700..0000000
--- a/providers/dial/dial_client.js
+++ /dev/null
@@ -1,355 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview Client wrapper for interacting with DIAL devices and data
- * structures for responses.
- */
-
-goog.module('mr.dial.Client');
-goog.module.declareLegacyNamespace();
-
-const Assertions = goog.require('mr.Assertions');
-const Logger = goog.require('mr.Logger');
-const NetUtils = goog.require('mr.NetUtils');
-const XhrManager = goog.require('mr.XhrManager');
-const XhrUtils = goog.require('mr.XhrUtils');
-
-/**
- * Possible states of a DIAL application.
- * @enum {string}
- */
-const DialAppState = {
-  /** The app is running. */
-  RUNNING: 'running',
-  /** The app is not running.  */
-  STOPPED: 'stopped',
-  /** The app can be installed. */
-  INSTALLABLE: 'installable',
-  /**
-   * An error was encountered getting the state.
-
-   */
-  ERROR: 'error'
-};
-
-/**
- * The fallback path to use for DELETE requests in case the device does not
- * provide one.
- * @private @const {string}
- */
-const DEFAULT_RESOURCE_PATH_ = 'run';
-
-/**
- * Holds data parsed from a DIAL GET response.
- */
-const AppInfo = class {
-  constructor() {
-    /**
-     * The application name.  Mandatory.
-     * @type {string}
-     */
-    this.name = 'unknown';
-
-    /**
-     * The reported state of the application.
-     * @type {DialAppState}
-     */
-    this.state = DialAppState.ERROR;
-
-    /**
-     * If the application's state is INSTALLABLE, then the URL where the app
-     * can be installed.
-     * @type {?string}
-     */
-    this.installUrl = null;
-
-    /**
-     * Whether the DELETE operation is supported.
-     * @type {boolean}
-     */
-    this.allowStop = true;
-
-    /**
-     * If the applications's state is RUNNING, a resource identifier for the
-     * running application.
-     * @type {?string}
-     */
-    this.resource = null;
-
-    /**
-     * Application-specific data included with the GET response that is not part
-     * of the official specifciations.
-     * @type {!Object<string, string>}
-     */
-    this.extraData = {};
-  }
-};
-
-
-/**
- * Indicates that the DIAL sink returned NOT_FOUND in response to a GET request.
- */
-const AppInfoNotFoundError = class extends Error {
-  constructor() {
-    super();
-  }
-};
-
-
-/**
- * Wrapper for a DIAL sink used for communicating with it.
- */
-const Client = class {
-  /**
-   * @param {!mr.dial.Sink} sink
-   * @param {!XhrManager=} xhrManager Manager for all requests.
-   */
-  constructor(sink, xhrManager = Client.getXhrManager_()) {
-    // NOTE(mfoltz,haibinlu): We do not assert if the sink supports DIAL,
-    // since combined discovery uses DialClient to check app info to see if a
-    // mDNS-discovered sink is also a DIAL sink.
-    Assertions.assert(
-        sink.getDialAppUrl(), 'Receiver must have a DIAL app URL set.');
-
-    /** @private @const {!mr.dial.Sink} */
-    this.sink_ = sink;
-
-    /** @private @const {!XhrManager} */
-    this.xhrManager_ = xhrManager;
-
-    /** @private @const {?Logger} */
-    this.logger_ = Logger.getInstance('mr.dial.Client');
-  }
-
-  /**
-   * @param {!mr.dial.Sink} sink
-   * @return {!Client}
-   */
-  static create(sink) {
-    return new Client(sink);
-  }
-
-  /**
-   * Returns the default XhrManager, creating it if necessary.
-   * @return {!XhrManager}
-   * @private
-   */
-  static getXhrManager_() {
-    if (!Client.xhrManager_) {
-      Client.xhrManager_ = new XhrManager(
-          /* maxRequests */ 10,
-          /* defaultTimeoutMillis */ 2000,
-          /* defaultNumAttempts */ 1);
-    }
-    return Client.xhrManager_;
-  }
-
-  /**
-   * @param {string} state A string representing a DIAL application state.
-   * @return {DialAppState} The corresponding state or ERROR if the
-   *     state is invalid.
-   * @private
-   */
-  static parseDialAppState_(state) {
-    switch (state) {
-      case 'running':
-        return DialAppState.RUNNING;
-      case 'stopped':
-        return DialAppState.STOPPED;
-      default:
-        return DialAppState.ERROR;
-    }
-  }
-
-  /**
-   * Launches an application on the sink.
-   * @param {string} appName Name of the DIAL application to launch.
-   * @param {string} postData Data to include in the HTTP POST request.
-   * @return {!Promise<void>} Fulfilled when the operation completes
-   *     successfully. Rejected otherwise.
-   */
-  launchApp(appName, postData) {
-    return this.xhrManager_
-        .send(
-            this.getAppUrl_(appName), 'POST', postData, {timeoutMillis: 15000})
-        .then(xhr => this.handleResponse_('launchApp', 'POST', xhr));
-  }
-
-  /**
-   * Stops a running application on the sink.
-   * @param {string} appName Name of the DIAL application to stop.
-   * @return {!Promise<void>} Fulfilled when the operation completes
-   *     successfully. Rejected otherwise.
-   */
-  stopApp(appName) {
-    return this.getAppInfo(appName)
-        .then(
-            appInfo => {
-              // The URL used for stop is obtained from appending resource path
-              // to the app URL. If the resource path is not available, then it
-              // means the app is not running. It could also be that the device
-              // is non-compliant. To account for this case, we will try to stop
-              // the app anyway with a fallback path.
-              if (!appInfo.resource) {
-                this.logger_.warning(
-                    'stopApp: Resource path for not available for app ' +
-                    appName + ': using fallback path.');
-                return DEFAULT_RESOURCE_PATH_;
-              }
-              return appInfo.resource;
-            },
-            e => {
-              // If getAppInfo fails, use a fallback path.
-              this.logger_.warning(
-                  'stopApp: getAppInfo failed: using fallback path.');
-              return DEFAULT_RESOURCE_PATH_;
-            })
-        .then(
-            path => this.xhrManager_.send(
-                this.getAppUrl_(appName) + '/' + path, 'DELETE'))
-        .then(xhr => this.handleResponse_('stopApp', 'DELETE', xhr));
-  }
-
-  /**
-   * Gets information about a running application on the sink.
-   * @param {string} appName Name of the DIAL application to get info from.
-   * @return {!Promise<!AppInfo>} Fulfilled with AppInfo. Rejected if the
-   *     operation did not complete successfully. In the case of the sink
-   *     returning NOT_FOUND for the request, AppInfoNotFoundError will be
-   *     thrown.
-   */
-  getAppInfo(appName) {
-    return this.xhrManager_
-        .send(this.getAppUrl_(appName), 'GET', undefined, {numAttempts: 3})
-        .then(xhr => this.handleGetAppInfoResponse_(appName, xhr));
-  }
-
-  /**
-   * Parses the response from a Xhr GET request.
-   * @param {string} appName App nam used in the request.
-   * @param {!XMLHttpRequest} xhr
-   * @return {!AppInfo}
-   * @private
-   */
-  handleGetAppInfoResponse_(appName, xhr) {
-    XhrUtils.logRawXhr(this.logger_, 'GetAppInfo', 'GET', xhr);
-    if (!XhrUtils.isSuccess(xhr)) {
-      if (xhr.status == NetUtils.HttpStatus.NOT_FOUND) {
-        throw new AppInfoNotFoundError();
-      } else {
-        throw new Error(`Response error: ${xhr.status}`);
-      }
-    }
-
-    const xml = XhrUtils.parseXml(xhr.responseText);
-    if (!xml) {
-      this.logger_.info('Invalid or empty response');
-      throw new Error('Invalid or empty response');
-    }
-
-    const service = xml.getElementsByTagName('service');
-    if (!service || service.length != 1) {
-      this.logger_.info('Invalid GET response (invalid service)');
-      throw new Error('Invalid GET response (invalid service)');
-    }
-    const appInfo = new AppInfo();
-    for (var i = 0, l = service[0].childNodes.length; i < l; i++) {
-      const node = service[0].childNodes[i];
-      if (node.nodeName == 'state') {
-        appInfo.state = Client.parseDialAppState_(node.textContent);
-      } else if (node.nodeName == 'name') {
-        appInfo.name = node.textContent;
-      } else if (node.localName == 'link') {
-        appInfo.resource = node.getAttribute('href');
-      } else if (node.nodeName == 'options') {
-        // The default value for allowStop is true per DIAL spec.
-        appInfo.allowStop = (node.getAttribute('allowStop') != 'false');
-      } else {
-        appInfo.extraData[node.nodeName] = node.innerHTML;
-      }
-    }
-
-    // Validate mandatory fields (name, state).
-    if (appInfo.name == 'unknown') {
-      this.logger_.info('GET response missing name value');
-      throw new Error('GET response missing name value');
-    }
-
-    if (appInfo.name != appName) {
-      this.logger_.info('GET app name mismatch');
-      throw new Error('GET app name mismatch');
-    }
-
-    if (appInfo.state == DialAppState.ERROR) {
-      this.logger_.info('GET response missing state value');
-      throw new Error('GET response missing state value');
-    }
-
-    // Parse state.
-    const installable = /installable=(.+)/.exec(appInfo.state);
-    if (installable && installable[1]) {
-      appInfo.state = DialAppState.INSTALLABLE;
-      appInfo.installUrl = installable[1];
-    } else if (
-        appInfo.state == DialAppState.RUNNING ||
-        appInfo.state == DialAppState.STOPPED) {
-      // Valid state.  Continue.
-    } else {
-      this.logger_.info('GET response has invalid state value');
-      throw new Error('GET response has invalid state value');
-    }
-
-    // Success!
-    return appInfo;
-  }
-
-  /**
-   * Returns the URL used to communicate with a given DIAL application.
-   * @param {string} appName The name of the DIAL application.
-   * @return {string} The URL for the activity.
-   * @private
-   */
-  getAppUrl_(appName) {
-    let appUrl = this.sink_.getDialAppUrl();
-    if (appUrl.charAt(appUrl.length - 1) != '/') {
-      appUrl += '/';
-    }
-    return appUrl + appName;
-  }
-
-  /**
-   * Logs the given response and returns a Promise that resolves if it indicates
-   * success.
-   * @param {string} action Name of the operation that created the request.
-   * @param {string} method The HTTP method.
-   * @param {!XMLHttpRequest} xhr
-   * @return {!Promise<void>} Resolves if the response indicates success,
-   *     rejected otherwise.
-   * @private
-   */
-  handleResponse_(action, method, xhr) {
-    return new Promise((resolve, reject) => {
-      XhrUtils.logRawXhr(this.logger_, action, method, xhr);
-      if (XhrUtils.isSuccess(xhr)) {
-        resolve();
-      } else {
-        reject(Error(xhr.statusText));
-      }
-    });
-  }
-};
-
-
-/**
- * Lazily instantiated and shared between DialClient instances.
- * @private {?XhrManager}
- */
-Client.xhrManager_ = null;
-
-
-exports.AppInfo = AppInfo;
-exports.AppInfoNotFoundError = AppInfoNotFoundError;
-exports.Client = Client;
-exports.DialAppState = DialAppState;
diff --git a/providers/dial/dial_client_test.js b/providers/dial/dial_client_test.js
deleted file mode 100644
index fa7d77f..0000000
--- a/providers/dial/dial_client_test.js
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.ClientTest');
-goog.setTestOnly('mr.dial.ClientTest');
-
-const DialClient = goog.require('mr.dial.Client');
-const DialSink = goog.require('mr.dial.Sink');
-const XhrUtils = goog.require('mr.XhrUtils');
-
-describe('Dial Client Tests', function() {
-  let client;
-  let mockXhrManager;
-  let sink;
-  const appUrl = 'http://198.0.0.100/apps';
-
-
-  beforeEach(function() {
-    sink = new DialSink('sink', 'sinkid');
-    sink.setDialAppUrl(appUrl);
-    mockXhrManager = jasmine.createSpyObj('XhrManager', ['send']);
-    spyOn(XhrUtils, 'logRawXhr');
-    client = new DialClient.Client(sink, mockXhrManager);
-  });
-
-  const setMockXhrResponse = function(xml) {
-    mockXhrManager.send.and.returnValue(
-        Promise.resolve({responseText: xml, status: 200}));
-  };
-
-  const setMockXhrErrorResponse = function() {
-    mockXhrManager.send.and.returnValue(
-        Promise.resolve({responseText: null, status: 403 /* Forbidden */}));
-  };
-
-  const setMockXhrNotFoundResponse = function() {
-    mockXhrManager.send.and.returnValue(
-        Promise.resolve({responseText: null, status: 404}));
-  };
-
-  const setMockXhrReject = function() {
-    mockXhrManager.send.and.returnValue(
-        Promise.reject(new Error('send failed')));
-  };
-
-  // Suppress Jasmine warning about a spec with no expectations.
-  const noExpectations = function() {
-    expect(true).toBe(true);
-  };
-
-  describe('Tests launchApp', function() {
-    const expectLaunchAppFails = function(done) {
-      client.launchApp('YouTube', 'v=12345678').then(() => {
-        fail('launchApp unexpectedly succeeded.');
-      }, () => done());
-    };
-
-    it('Resolves', done => {
-      setMockXhrResponse('');
-      client.launchApp('YouTube', 'v=12345678').then(() => {
-        expect(mockXhrManager.send)
-            .toHaveBeenCalledWith(
-                appUrl + '/YouTube', 'POST', 'v=12345678', jasmine.any(Object));
-        done();
-      });
-    });
-
-    it('Rejects on error response', done => {
-      setMockXhrErrorResponse();
-      expectLaunchAppFails(done);
-      noExpectations();
-    });
-
-    it('Rejects on send rejection', done => {
-      setMockXhrReject();
-      expectLaunchAppFails(done);
-      noExpectations();
-    });
-  });
-
-  describe('Tests stopApp', function() {
-    const expectStopAppFails = function(done) {
-      client.stopApp('YouTube').then(() => {
-        fail('stopApp unexpectedly succeeded.');
-      }, () => done());
-    };
-
-    it('Resolves', done => {
-      // Set up the mock response for the GET request.
-      setMockXhrResponse(VALID_GET_RESPONSE_);
-      client.stopApp('YouTube').then(() => {
-        expect(mockXhrManager.send.calls.count()).toEqual(2);
-        expect(mockXhrManager.send.calls.argsFor(0)[0])
-            .toEqual(appUrl + '/YouTube');
-        expect(mockXhrManager.send.calls.argsFor(0)[1]).toEqual('GET');
-        expect(mockXhrManager.send.calls.argsFor(1)[0])
-            .toEqual(appUrl + '/YouTube/run');
-        expect(mockXhrManager.send.calls.argsFor(1)[1]).toEqual('DELETE');
-        done();
-      });
-    });
-
-    it('Resolves with fallback path', done => {
-      mockXhrManager.send.and.callFake((url, method) => {
-        if (method === 'GET') {
-          return Promise.reject(new Error('GET failed'));
-        } else {
-          return Promise.resolve({status: 200});
-        }
-      });
-      client.stopApp('YouTube').then(() => {
-        expect(mockXhrManager.send.calls.count()).toEqual(2);
-        expect(mockXhrManager.send.calls.argsFor(1)[0])
-            .toEqual(appUrl + '/YouTube/run');
-        expect(mockXhrManager.send.calls.argsFor(1)[1]).toEqual('DELETE');
-        done();
-      });
-    });
-
-    it('Rejects on error response', done => {
-      setMockXhrErrorResponse();
-      expectStopAppFails(done);
-      noExpectations();
-    });
-
-    it('Rejects on send rejection', done => {
-      setMockXhrReject();
-      expectStopAppFails(done);
-      noExpectations();
-    });
-  });
-
-  const expectMockSendGet = function() {
-    expect(mockXhrManager.send)
-        .toHaveBeenCalledWith(
-            'http://198.0.0.100/apps/YouTube', 'GET', undefined,
-            jasmine.any(Object));
-  };
-
-  const VALID_GET_RESPONSE_ = '<?xml version="1.0" encoding="UTF-8"?>' +
-      '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
-      '<name>YouTube</name>' +
-      '<options allowStop="false"/>' +
-      '<state>running</state>' +
-      '<link rel="run" href="run"/>' +
-      '</service>';
-
-  const VALID_GET_RESPONSE_EXTRA_DATA_ =
-      '<?xml version="1.0" encoding="UTF-8"?>' +
-      '<service xmlns="urn:dial-multiscreen-org:schemas:dial" xmlns:atom="http://www.w3.org/2005/Atom">' +
-      '<name>YouTube</name>' +
-      '<state>running</state>' +
-      '<atom:link rel="run" href="run"/>' +
-      '<port>8080</port>' +
-      '<additionalData>' +
-      '<screenId>e5n3112oskr42pg0td55b38nh4</screenId>' +
-      '<otherField>2</otherField>' +
-      '</additionalData>' +
-      '</service>';
-
-  const INVALID_GET_RESPONSE_NO_SERVICE_ =
-      '<?xml version="1.0" encoding="UTF-8"?>';
-
-  const INVALID_GET_RESPONSE_NO_STATE_ =
-      '<?xml version="1.0" encoding="UTF-8"?>' +
-      '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
-      '<name>YouTube</name>' +
-      '<options allowStop="true"/>' +
-      '<link rel="run" href="run"/>' +
-      '</service>';
-
-  const INVALID_GET_RESPONSE_INVALID_STATE_ =
-      '<?xml version="1.0" encoding="UTF-8"?>' +
-      '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
-      '<name>YouTube</name>' +
-      '<options allowStop="true"/>' +
-      '<state>xyzzy</state>' +
-      '<link rel="run" href="run"/>' +
-      '</service>';
-
-  const INVALID_GET_RESPONSE_INSTALLABLE_ =
-      '<?xml version="1.0" encoding="UTF-8"?>' +
-      '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
-      '<name>YouTube</name>' +
-      '<options allowStop="true"/>' +
-      '<state>installable=http://play.google.com/youtube</state>' +
-      '<link rel="run" href="run"/>' +
-      '</service>';
-
-  const INVALID_GET_RESPONSE_NO_NAME_ =
-      '<?xml version="1.0" encoding="UTF-8"?>' +
-      '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
-      '<options allowStop="true"/>' +
-      '<state>running</state>' +
-      '<link rel="run" href="run"/>' +
-      '</service>';
-
-  const INVALID_GET_RESPONSE_WRONG_APP_NAME_ =
-      '<?xml version="1.0" encoding="UTF-8"?>' +
-      '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
-      '<name>WrongAppName</name>' +
-      '<options allowStop="true"/>' +
-      '<state>running</state>' +
-      '<link rel="run" href="run"/>' +
-      '</service>';
-
-  describe('Tests getAppInfo', function() {
-    it('Returns info from valid response', done => {
-      setMockXhrResponse(VALID_GET_RESPONSE_);
-      client.getAppInfo('YouTube').then(appInfo => {
-        expect(appInfo.name).toEqual('YouTube');
-        expect(appInfo.state).toEqual('running');
-        expect(appInfo.allowStop).toBe(false);
-        expect(appInfo.resource).toEqual('run');
-        expectMockSendGet();
-        done();
-      });
-    });
-
-    it('Returns info with extraData', done => {
-      setMockXhrResponse(VALID_GET_RESPONSE_EXTRA_DATA_);
-      client.getAppInfo('YouTube').then(appInfo => {
-        expect(appInfo.name).toEqual('YouTube');
-        expect(appInfo.state).toEqual('running');
-        expect(appInfo.allowStop).toBe(true);
-        expect(appInfo.resource).toEqual('run');
-        expect(appInfo.extraData.port).toEqual('8080');
-        expect(appInfo.extraData.additionalData)
-            .toEqual(
-                '<screenId xmlns="urn:dial-multiscreen-org:schemas:dial">' +
-                'e5n3112oskr42pg0td55b38nh4</screenId>' +
-                '<otherField xmlns="urn:dial-multiscreen-org:schemas:dial">2' +
-                '</otherField>');
-        expectMockSendGet();
-        done();
-      });
-    });
-
-    const expectGetAppInfoFails = function(done) {
-      client.getAppInfo('YouTube').then(
-          _ => {
-            fail('getAppInfo unexpectedly succeeded.');
-          },
-          e => {
-            expectMockSendGet();
-            done();
-          });
-    };
-
-    const testInvalidResponse = function(response, done) {
-      setMockXhrResponse(response);
-      expectGetAppInfoFails(done);
-    };
-
-    it('Rejects on invalid response 1', done => {
-      testInvalidResponse('blarg', done);
-    });
-
-    it('Rejects on invalid response 2', done => {
-      testInvalidResponse(INVALID_GET_RESPONSE_NO_SERVICE_, done);
-    });
-
-    it('Rejects on invalid response 3', done => {
-      testInvalidResponse(INVALID_GET_RESPONSE_NO_STATE_, done);
-    });
-
-    it('Rejects on invalid response 4', done => {
-      testInvalidResponse(INVALID_GET_RESPONSE_NO_NAME_, done);
-    });
-
-    it('Rejects on invalid response 5', done => {
-      testInvalidResponse(INVALID_GET_RESPONSE_INVALID_STATE_, done);
-    });
-
-    it('Rejects on invalid response 6', done => {
-      testInvalidResponse(INVALID_GET_RESPONSE_INSTALLABLE_, done);
-    });
-
-    it('Rejects on mismatched app name', done => {
-      testInvalidResponse(INVALID_GET_RESPONSE_WRONG_APP_NAME_, done);
-    });
-
-    it('Rejects on error response', done => {
-      setMockXhrErrorResponse();
-      expectGetAppInfoFails(done);
-    });
-
-    it('Rejects on send rejection', done => {
-      setMockXhrReject();
-      expectGetAppInfoFails(done);
-    });
-
-    it('Rejects with AppInfoNotFoundError', done => {
-      setMockXhrNotFoundResponse();
-      client.getAppInfo('YouTube').then(
-          _ => {
-            fail('getAppInfo unexpectedly succeeded.');
-          },
-          e => {
-            expect(e instanceof DialClient.AppInfoNotFoundError).toBe(true);
-            expectMockSendGet();
-            done();
-          });
-    });
-  });
-});
diff --git a/providers/dial/dial_provider.js b/providers/dial/dial_provider.js
deleted file mode 100644
index dfd6535..0000000
--- a/providers/dial/dial_provider.js
+++ /dev/null
@@ -1,491 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.DialProvider');
-goog.module.declareLegacyNamespace();
-
-const Activity = goog.require('mr.dial.Activity');
-const ActivityRecords = goog.require('mr.dial.ActivityRecords');
-const AppDiscoveryService = goog.require('mr.dial.AppDiscoveryService');
-const Assertions = goog.require('mr.Assertions');
-const CancellablePromise = goog.require('mr.CancellablePromise');
-const DeviceCountsProvider = goog.require('mr.DeviceCountsProvider');
-const DialAnalytics = goog.require('mr.DialAnalytics');
-const DialClient = goog.require('mr.dial.Client');
-const DialPresentationUrl = goog.require('mr.dial.PresentationUrl');
-const DialSink = goog.require('mr.dial.Sink');
-const Logger = goog.require('mr.Logger');
-const MediaSourceUtils = goog.require('mr.MediaSourceUtils');
-const PresentationConnectionState = goog.require('mr.PresentationConnectionState');
-const Provider = goog.require('mr.Provider');
-const ProviderCallbacks = goog.require('mr.dial.ProviderCallbacks');
-const ProviderManagerCallbacks = goog.require('mr.ProviderManagerCallbacks');
-const ProviderName = goog.require('mr.ProviderName');
-const Route = goog.require('mr.Route');
-const RouteRequestError = goog.require('mr.RouteRequestError');
-const RouteRequestResultCode = goog.require('mr.RouteRequestResultCode');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const SinkAvailability = goog.require('mr.SinkAvailability');
-const SinkDiscoveryService = goog.require('mr.dial.SinkDiscoveryService');
-const SinkList = goog.require('mr.SinkList');
-const SinkUtils = goog.require('mr.SinkUtils');
-
-/**
- * DIAL implementation of Media Route Provider.
- * @implements {Provider}
- * @implements {ProviderCallbacks}
- * @implements {DeviceCountsProvider}
- */
-const DialProvider = class {
-  /**
-   * @param {!ProviderManagerCallbacks} providerManagerCallbacks
-   * @param {!SinkDiscoveryService=} sinkDiscoveryService
-   * @param {!AppDiscoveryService=} appDiscoveryService
-   * @final
-   */
-  constructor(
-      providerManagerCallbacks, sinkDiscoveryService = undefined,
-      appDiscoveryService = undefined) {
-    /** @private @const {!ProviderManagerCallbacks} */
-    this.providerManagerCallbacks_ = providerManagerCallbacks;
-
-    /** @private @const {!SinkDiscoveryService} */
-    this.sinkDiscoveryService_ =
-        sinkDiscoveryService || new SinkDiscoveryService(this);
-
-    /** @private @const {!ActivityRecords} */
-    this.activityRecords_ = new ActivityRecords(this);
-
-    /** @private {?AppDiscoveryService} */
-    this.appDiscoveryService_ = appDiscoveryService || null;
-
-    /** @private @const {?Logger} */
-    this.logger_ = Logger.getInstance('mr.DialProvider');
-  }
-
-  /**
-   * @override
-   */
-  getName() {
-    return ProviderName.DIAL;
-  }
-
-  /**
-   * @override
-   */
-  getDeviceCounts() {
-    return this.sinkDiscoveryService_.getDeviceCounts();
-  }
-
-  /**
-   * @override
-   */
-  initialize(config) {
-    const sinkQueryEnabled =
-        (config && config.enable_dial_sink_query == false) ? false : true;
-    this.logger_.info('Dial sink query enabled: ' + sinkQueryEnabled + '...');
-
-    this.activityRecords_.init();
-    this.sinkDiscoveryService_.init();
-
-    if (sinkQueryEnabled) {
-      this.appDiscoveryService_ = this.appDiscoveryService_ ||
-          new AppDiscoveryService(this.sinkDiscoveryService_,
-                                  this.activityRecords_);
-      this.appDiscoveryService_.init();
-    } else {
-      this.appDiscoveryService_ = null;
-    }
-
-    this.maybeStartAppDiscovery_();
-  }
-
-  /**
-   * @override
-   */
-  getAvailableSinks(sourceUrn) {
-    // Prevent SinkDiscoveryService to return cached available sinks.
-    if (!this.appDiscoveryService_) {
-      return SinkList.EMPTY;
-    }
-
-    this.logger_.fine('GetAvailableSinks for ' + sourceUrn);
-    const dialMediaSource = DialPresentationUrl.create(sourceUrn);
-    return dialMediaSource ?
-        this.sinkDiscoveryService_.getSinksByAppName(dialMediaSource.appName) :
-        SinkList.EMPTY;
-  }
-
-  /**
-   * @override
-   */
-  startObservingMediaSinks(sourceUrn) {
-    if (!this.appDiscoveryService_) {
-      return;
-    }
-
-    const dialMediaSource = DialPresentationUrl.create(sourceUrn);
-    if (dialMediaSource) {
-      this.appDiscoveryService_.registerApp(dialMediaSource.appName);
-      this.maybeStartAppDiscovery_();
-    }
-  }
-
-  /**
-   * @override
-   */
-  stopObservingMediaSinks(sourceUrn) {
-    if (!this.appDiscoveryService_) {
-      return;
-    }
-
-    const dialMediaSource = DialPresentationUrl.create(sourceUrn);
-    if (dialMediaSource) {
-      this.appDiscoveryService_.unregisterApp(dialMediaSource.appName);
-      this.maybeStopAppDiscovery_();
-    }
-  }
-
-  /**
-   * @override
-   */
-  startObservingMediaRoutes(sourceUrn) {
-    this.maybeStartAppDiscovery_();
-  }
-
-  /**
-   * @override
-   */
-  stopObservingMediaRoutes(sourceUrn) {
-    this.maybeStopAppDiscovery_();
-  }
-
-  /**
-   * @private
-   */
-  maybeStopAppDiscovery_() {
-    if (!this.appDiscoveryService_) {
-      return;
-    }
-
-    if (this.sinkDiscoveryService_.getSinkCount() == 0 ||
-        (this.appDiscoveryService_.getAppCount() == 0 &&
-         this.activityRecords_.getActivityCount() == 0)) {
-      this.appDiscoveryService_.stop();
-    }
-  }
-
-  /**
-   * @private
-   */
-  maybeStartAppDiscovery_() {
-    if (!this.appDiscoveryService_) {
-      return;
-    }
-
-    if (this.sinkDiscoveryService_.getSinkCount() > 0 &&
-        (this.appDiscoveryService_.getAppCount() > 0 ||
-         this.activityRecords_.getActivityCount() > 0)) {
-      this.appDiscoveryService_.start();
-    }
-  }
-
-  /**
-   * @override
-   */
-  getSinkById(id) {
-    const dialSink = this.sinkDiscoveryService_.getSinkById(id);
-    return dialSink ? dialSink.getMrSink() : null;
-  }
-
-  /**
-   * @override
-   */
-  getRoutes() {
-    return this.activityRecords_.getRoutes();
-  }
-
-  /**
-   * @override
-   */
-  createRoute(
-      sourceUrn, sinkId, presentationId, offTheRecord, timeoutMillis,
-      opt_origin, opt_tabId) {
-    const sink = this.sinkDiscoveryService_.getSinkById(sinkId);
-    if (!sink) {
-      DialAnalytics.recordCreateRoute(
-          DialAnalytics.DialCreateRouteResult.SINK_NOT_FOUND);
-      return CancellablePromise.reject(Error('Unkown sink: ' + sinkId));
-    }
-    SinkUtils.getInstance().recentLaunchedDevice =
-        new SinkUtils.DeviceData(sink.getModelName(), sink.getIpAddress());
-    const dialMediaSource = DialPresentationUrl.create(sourceUrn);
-    if (!dialMediaSource) {
-      DialAnalytics.recordCreateRoute(
-          DialAnalytics.DialCreateRouteResult.UNSUPPORTED_SOURCE);
-      return CancellablePromise.reject(Error('No app name set.'));
-    }
-    const appName = dialMediaSource.appName;
-    const dialClient = this.newClient_(sink);
-
-    return CancellablePromise.forPromise(
-        /** @type {!Promise<!Route>} */
-        (dialClient.getAppInfo(appName)
-             .then(appInfo => {
-               if (appInfo.state == DialClient.DialAppState.RUNNING) {
-                 return dialClient.stopApp(appName);
-               }
-             })
-             .then(() => {
-               return dialClient.launchApp(
-                   appName, dialMediaSource.launchParameter);
-             })
-             .then(() => {
-               DialAnalytics.recordCreateRoute(
-                   DialAnalytics.DialCreateRouteResult.SUCCESS);
-               return this.addRoute(
-                   sinkId, sourceUrn, true, appName, presentationId,
-                   offTheRecord);
-             })
-             .catch(err => {
-               DialAnalytics.recordCreateRoute(
-                   DialAnalytics.DialCreateRouteResult.APP_LAUNCH_FAILED);
-               throw err;
-             })));
-  }
-
-  /**
-   * @override
-   */
-  joinRoute(
-      sourceUrn, presentationId, offTheRecord, timeoutMillis, origin, tabId) {
-    return CancellablePromise.reject(Error('Not supported'));
-  }
-
-  /**
-   * @override
-   */
-  connectRouteByRouteId(sourceUrn, routeId, presentationId, origin, tabId) {
-    return CancellablePromise.reject(Error('Not supported'));
-  }
-
-  /**
-   * @override
-   */
-  detachRoute(routeId) {}
-
-  /**
-   * @param {string} sinkId
-   * @param {?string} sourceUrn
-   * @param {boolean} isLocal
-   * @param {string} appName
-   * @param {string} presentationId
-   * @param {boolean} offTheRecord
-   * @return {!Route} The route that was just added.
-   */
-  addRoute(sinkId, sourceUrn, isLocal, appName, presentationId, offTheRecord) {
-    const route = Route.createRoute(
-        presentationId, this.getName(), sinkId, sourceUrn, isLocal, appName,
-        null);
-    route.offTheRecord = offTheRecord;
-    this.activityRecords_.add(new Activity(route, appName));
-    return route;
-  }
-
-  /**
-   * @override
-   */
-  onSinkAdded(sink) {
-    this.providerManagerCallbacks_.onSinkAvailabilityUpdated(
-        this, SinkAvailability.PER_SOURCE);
-    if (this.appDiscoveryService_) {
-      this.maybeStartAppDiscovery_();
-      this.appDiscoveryService_.scanSink(sink);
-    }
-    this.providerManagerCallbacks_.onSinksUpdated();
-    SinkUtils.getInstance().recentDiscoveredDevice =
-        new SinkUtils.DeviceData(sink.getModelName(), sink.getIpAddress());
-  }
-
-  /**
-   * @override
-   */
-  onSinksRemoved(sinks) {
-    if (this.sinkDiscoveryService_.getSinkCount() == 0) {
-      this.providerManagerCallbacks_.onSinkAvailabilityUpdated(
-          this, SinkAvailability.UNAVAILABLE);
-    }
-    this.maybeStopAppDiscovery_();
-    sinks.forEach(sink => {
-      this.activityRecords_.removeBySinkId(sink.getId());
-    });
-    this.providerManagerCallbacks_.onSinksUpdated();
-  }
-
-  /**
-   * @override
-   */
-  onSinkUpdated(sink) {
-    this.providerManagerCallbacks_.onSinksUpdated();
-  }
-
-  /**
-   * @override
-   */
-  onActivityAdded(activity) {
-    this.maybeStartAppDiscovery_();
-    this.providerManagerCallbacks_.onRouteAdded(this, activity.route);
-  }
-
-  /**
-   * @override
-   */
-  onActivityRemoved(activity) {
-    const route = activity.route;
-    if (route.isLocal) {
-      this.providerManagerCallbacks_.onPresentationConnectionStateChanged(
-          route.id, PresentationConnectionState.TERMINATED);
-    }
-    this.maybeStopAppDiscovery_();
-    this.providerManagerCallbacks_.onRouteRemoved(this, route);
-  }
-
-  /**
-   * @override
-   */
-  onActivityUpdated(activity) {
-    this.providerManagerCallbacks_.onRouteUpdated(this, activity.route);
-  }
-
-  /**
-   * @override
-   */
-  terminateRoute(routeId) {
-    const activity = this.activityRecords_.getByRouteId(routeId);
-    if (!activity) {
-      DialAnalytics.recordTerminateRoute(
-          DialAnalytics.DialTerminateRouteResult.ROUTE_NOT_FOUND);
-      return Promise.reject(new RouteRequestError(
-          RouteRequestResultCode.ROUTE_NOT_FOUND,
-          'Route in DIAL provider not found for routeId ' + routeId));
-    }
-    this.activityRecords_.removeByRouteId(routeId);
-    const sink = this.sinkDiscoveryService_.getSinkById(activity.route.sinkId);
-    if (!sink) {
-      DialAnalytics.recordTerminateRoute(
-          DialAnalytics.DialTerminateRouteResult.ROUTE_NOT_FOUND);
-      return Promise.reject(new RouteRequestError(
-          RouteRequestResultCode.ROUTE_NOT_FOUND,
-          'Sink in DIAL provider not found for sinkId ' +
-              activity.route.sinkId));
-    }
-    return this.newClient_(sink)
-        .stopApp(activity.appName)
-        .then(() => {
-          DialAnalytics.recordTerminateRoute(
-              DialAnalytics.DialTerminateRouteResult.SUCCESS);
-          return Promise.resolve();
-        })
-        .catch(error => {
-          DialAnalytics.recordTerminateRoute(
-              DialAnalytics.DialTerminateRouteResult.STOP_APP_FAILED);
-          return Promise.reject(error);
-        });
-  }
-
-  /**
-   * @override
-   */
-  getMirrorSettings(sinkId) {
-    throw new Error('Not implemented.');
-  }
-
-  /**
-   * @override
-   */
-  getMirrorServiceName(sinkId) {
-    return null;
-  }
-
-  /**
-   * @override
-   */
-  onMirrorActivityUpdated(routeId) {}
-
-  /**
-   * @override
-   */
-  sendRouteMessage(routeId, message, opt_extraInfo) {
-    return Promise.reject(Error('DIAL sending messages is not supported'));
-  }
-
-  /**
-   * @override
-   */
-  sendRouteBinaryMessage(routeId, message) {
-    return Promise.reject(Error('DIAL sending messages is not supported'));
-  }
-
-  /**
-   * @override
-   */
-  canRoute(sourceUrn, sinkId) {
-    const sink = this.sinkDiscoveryService_.getSinkById(sinkId);
-    if (!sink) {
-      return false;
-    }
-
-    if (MediaSourceUtils.isMirrorSource(sourceUrn)) {
-      return false;
-    }
-
-    const dialMediaSource = DialPresentationUrl.create(sourceUrn);
-    if (!dialMediaSource) {
-      return false;
-    }
-    return sink.getAppStatus(dialMediaSource.appName) ==
-        SinkAppStatus.AVAILABLE;
-  }
-
-  /**
-   * @override
-   */
-  canJoin(sourceUrn, presentationId, route) {
-    return false;
-  }
-
-  /**
-   * @override
-   */
-  searchSinks(sourceUrn, searchCriteria) {
-    // Not implemented.
-    return Assertions.rejectNotImplemented();
-  }
-
-  /**
-   * @override
-   */
-  createMediaRouteController(routeId, controllerRequest, observer) {
-    // Not implemented.
-    return Assertions.rejectNotImplemented();
-  }
-
-  /**
-   * @override
-   */
-  provideSinks(sinks) {
-    this.sinkDiscoveryService_.addSinks(sinks);
-  }
-
-  /**
-   * @param {!DialSink} sink
-   * @return {!DialClient.Client}
-   * @private
-   */
-  newClient_(sink) {
-    return new DialClient.Client(sink);
-  }
-};
-
-exports = DialProvider;
diff --git a/providers/dial/dial_provider_callbacks.js b/providers/dial/dial_provider_callbacks.js
deleted file mode 100644
index 2c72849..0000000
--- a/providers/dial/dial_provider_callbacks.js
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview DIAL provider callbacks used for other DIAL services to inform
- *  activity or sink updates.
- */
-
-goog.provide('mr.dial.ActivityCallbacks');
-goog.provide('mr.dial.ProviderCallbacks');
-goog.provide('mr.dial.SinkDiscoveryCallbacks');
-
-
-
-/**
- * @record
- */
-mr.dial.ActivityCallbacks = class {
-  /**
-   * @param {!mr.dial.Activity } activity
-   */
-  onActivityAdded(activity) {}
-
-  /**
-   * @param {!mr.dial.Activity } activity
-   */
-  onActivityRemoved(activity) {}
-
-  /**
-   * @param {!mr.dial.Activity } activity
-   */
-  onActivityUpdated(activity) {}
-};
-
-
-
-/**
- * @record
- */
-mr.dial.SinkDiscoveryCallbacks = class {
-  /**
-   * @param {!mr.dial.Sink} sink Sink that has been added.
-   */
-  onSinkAdded(sink) {}
-
-  /**
-   * @param {!Array.<!mr.dial.Sink>} sinks Sinks that have been removed.
-   */
-  onSinksRemoved(sinks) {}
-
-  /**
-   * @param {!mr.dial.Sink} sink Sink that has been updated.
-   */
-  onSinkUpdated(sink) {}
-};
-
-
-
-/**
- * @record
- * @extends {mr.dial.ActivityCallbacks}
- * @extends {mr.dial.SinkDiscoveryCallbacks}
- */
-mr.dial.ProviderCallbacks = class {};
diff --git a/providers/dial/dial_provider_test.js b/providers/dial/dial_provider_test.js
deleted file mode 100644
index 6661437..0000000
--- a/providers/dial/dial_provider_test.js
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.DialProviderTest');
-goog.setTestOnly('mr.DialProviderTest');
-
-const Activity = goog.require('mr.dial.Activity');
-const DialAnalytics = goog.require('mr.DialAnalytics');
-const DialClient = goog.require('mr.dial.Client');
-const DialProvider = goog.require('mr.DialProvider');
-const DialSink = goog.require('mr.dial.Sink');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const PresentationConnectionState = goog.require('mr.PresentationConnectionState');
-const Route = goog.require('mr.Route');
-const SinkAvailability = goog.require('mr.SinkAvailability');
-
-
-describe('DialProvider tests', function() {
-  let provider;
-  let mockPmCallbacks;
-  const pmCallbackMethods = [
-    'getRouteMessageEventTarget', 'getProviderFromRouteId',
-    'onPresentationConnectionClosed', 'onPresentationConnectionStateChanged',
-    'onRouteMessage', 'onRouteRemoved', 'onRouteAdded', 'onSinksUpdated',
-    'onSinkAvailabilityUpdated'
-  ];
-  let mockSinkDiscoveryService;
-  const sinkDiscoveryServiceMethods =
-      ['init', 'getSinkCount', 'init', 'getSinksByAppName', 'getSinkById'];
-  let mockAppDiscoveryService;
-  const appDiscoveryServiceMethods = [
-    'init', 'start', 'stop', 'registerApp', 'unregisterApp', 'getAppCount',
-    'scanSink'
-  ];
-  let mockDialClient;
-
-  const appInfo = new DialClient.AppInfo();
-  const youTubeUrl = 'dial:YouTube?postData=dj0xMjM=';
-
-  beforeEach(function() {
-    mockPmCallbacks =
-        jasmine.createSpyObj('ProviderManagerCallbacks', pmCallbackMethods);
-
-    mockSinkDiscoveryService = jasmine.createSpyObj(
-        'SinkDiscoveryService', sinkDiscoveryServiceMethods);
-    mockAppDiscoveryService =
-        jasmine.createSpyObj('AppDiscoveryService', appDiscoveryServiceMethods);
-
-    provider = new DialProvider(
-        mockPmCallbacks, mockSinkDiscoveryService, mockAppDiscoveryService);
-    provider.initialize({enable_dial_discovery: true});
-    expect(mockAppDiscoveryService.init).toHaveBeenCalled();
-
-    const fakeDialSink = new DialSink('Fake DIAL sink', 'uniqueId');
-    fakeDialSink.setDialAppUrl(youTubeUrl);
-    mockDialClient = jasmine.createSpyObj(
-        'dialClient', ['getAppInfo', 'launchApp', 'stopApp']);
-    spyOn(DialProvider.prototype, 'newClient_').and.returnValue(mockDialClient);
-    mockSinkDiscoveryService.getSinkById.and.returnValue(fakeDialSink);
-    appInfo.name = 'YouTube';
-    appInfo.state = DialClient.DialAppState.STOPPED;
-    DialAnalytics.recordCreateRoute = jasmine.createSpy('recordCreateRoute');
-  });
-
-  afterEach(function() {
-    PersistentDataManager.clear();
-  });
-
-  describe('startObservingMediaSinks Test', function() {
-    it('Handles non-dial sink query', function() {
-      provider.startObservingMediaSinks('urn:not-dial:YouTube');
-      expect(mockAppDiscoveryService.registerApp).not.toHaveBeenCalled();
-    });
-
-    it('Handles valid dial sink query, no sinks', function() {
-      mockSinkDiscoveryService.getSinkCount.and.returnValue(0);
-      mockAppDiscoveryService.getAppCount.and.returnValue(1);
-      provider.startObservingMediaSinks(youTubeUrl);
-      expect(mockAppDiscoveryService.registerApp)
-          .toHaveBeenCalledWith('YouTube');
-      expect(mockAppDiscoveryService.start).not.toHaveBeenCalled();
-    });
-
-    it('Handles valid dial sink query, at least one sink', function() {
-      mockSinkDiscoveryService.getSinkCount.and.returnValue(1);
-      mockAppDiscoveryService.getAppCount.and.returnValue(1);
-      provider.startObservingMediaSinks(youTubeUrl);
-      expect(mockAppDiscoveryService.registerApp)
-          .toHaveBeenCalledWith('YouTube');
-      expect(mockAppDiscoveryService.start).toHaveBeenCalled();
-    });
-  });
-
-  describe('stopObservingMediaSinks Test', function() {
-    it('Handles non-dial sink query', function() {
-      provider.stopObservingMediaSinks('urn:not-dial:YouTube');
-      expect(mockAppDiscoveryService.unregisterApp).not.toHaveBeenCalled();
-    });
-
-    it('Handles valid dial sink query', function() {
-      mockAppDiscoveryService.getAppCount.and.returnValue(0);
-      provider.stopObservingMediaSinks(youTubeUrl);
-      expect(mockAppDiscoveryService.unregisterApp)
-          .toHaveBeenCalledWith('YouTube');
-    });
-
-    it('Handles valid dial sink query, app query remains', function() {
-      mockAppDiscoveryService.getAppCount.and.returnValue(1);
-      provider.stopObservingMediaSinks(youTubeUrl);
-      expect(mockAppDiscoveryService.unregisterApp)
-          .toHaveBeenCalledWith('YouTube');
-    });
-  });
-
-  describe('onPresentationConnectionStateChanged Test', function() {
-    it('Changes presentation state to terminated', function() {
-      const route = provider.addRoute(
-          'sink1', youTubeUrl, true, 'app1', 'presentationId1');
-      provider.onActivityRemoved(new Activity(route, 'app1'));
-      expect(mockPmCallbacks.onPresentationConnectionStateChanged)
-          .toHaveBeenCalledWith(
-              route.id, PresentationConnectionState.TERMINATED);
-      expect(mockPmCallbacks.onRouteRemoved).toHaveBeenCalled();
-    });
-
-    it('Does not change state for non-local presentation', function() {
-      const route = provider.addRoute(
-          'sink1', youTubeUrl, false, 'app1', 'presentationId1');
-      provider.onActivityRemoved(new Activity(route, 'app1'));
-      expect(mockPmCallbacks.onPresentationConnectionStateChanged)
-          .not.toHaveBeenCalled();
-      expect(mockPmCallbacks.onRouteRemoved).toHaveBeenCalled();
-    });
-  });
-
-  describe('createRoute Test', function() {
-    it('Creates a route', function(done) {
-      mockDialClient.getAppInfo.and.returnValue(Promise.resolve(appInfo));
-      mockDialClient.launchApp.and.returnValue(Promise.resolve());
-      provider.createRoute(youTubeUrl, 'sink1', 'presentationId1', false)
-          .promise.then(
-              route => {
-                expect(route.sinkId).toBe('sink1');
-                expect(route.mediaSource).toBe(youTubeUrl);
-                expect(route.offTheRecord).toBe(false);
-                expect(DialAnalytics.recordCreateRoute)
-                    .toHaveBeenCalledWith(
-                        DialAnalytics.DialCreateRouteResult.SUCCESS);
-                done();
-              },
-              e => {
-                done.fail('Unexpected error: ' + e.message);
-              });
-    });
-
-    it('Creates an off-the-record route', function(done) {
-      mockDialClient.getAppInfo.and.returnValue(Promise.resolve(appInfo));
-      mockDialClient.launchApp.and.returnValue(Promise.resolve());
-      provider.createRoute(youTubeUrl, 'sink1', 'presentationId1', true)
-          .promise.then(
-              route => {
-                expect(route.sinkId).toBe('sink1');
-                expect(route.mediaSource).toBe(youTubeUrl);
-                expect(route.offTheRecord).toBe(true);
-                expect(DialAnalytics.recordCreateRoute)
-                    .toHaveBeenCalledWith(
-                        DialAnalytics.DialCreateRouteResult.SUCCESS);
-                done();
-              },
-              e => {
-                done.fail('Unexpected error: ' + e.message);
-              });
-    });
-
-    it('Fails to create a route when get app info fails', function(done) {
-      mockDialClient.getAppInfo.and.returnValue(Promise.reject('fail'));
-      provider.createRoute(youTubeUrl, 'sink1', 'presentationId1', true)
-          .promise.then(done.fail, e => {
-            expect(DialAnalytics.recordCreateRoute)
-                .toHaveBeenCalledWith(
-                    DialAnalytics.DialCreateRouteResult.APP_LAUNCH_FAILED);
-            done();
-          });
-    });
-
-    it('Fails to create a route when launch app fails', function(done) {
-      mockDialClient.getAppInfo.and.returnValue(Promise.resolve(appInfo));
-      mockDialClient.launchApp.and.returnValue(Promise.reject('fail'));
-      provider.createRoute(youTubeUrl, 'sink1', 'presentationId1', true)
-          .promise.then(done.fail, e => {
-            expect(DialAnalytics.recordCreateRoute)
-                .toHaveBeenCalledWith(
-                    DialAnalytics.DialCreateRouteResult.APP_LAUNCH_FAILED);
-            done();
-          });
-    });
-
-    it('Starts and stop app discovery', function() {
-      mockSinkDiscoveryService.getSinkCount.and.returnValue(1);
-      let appCount = 0;
-      mockAppDiscoveryService.getAppCount.and.callFake(() => appCount);
-      const route = Route.createRoute(
-          'presentationId', 'providerName', 'sinkId', 'source', true,
-          'description', null);
-      const activity = new Activity(route, 'YouTube');
-      provider.activityRecords_.add(activity);
-      expect(mockAppDiscoveryService.start).toHaveBeenCalled();
-
-      appCount++;
-      provider.startObservingMediaSinks(youTubeUrl);
-      expect(mockAppDiscoveryService.registerApp)
-          .toHaveBeenCalledWith('YouTube');
-
-      appCount--;
-      provider.stopObservingMediaSinks(youTubeUrl);
-      expect(mockAppDiscoveryService.stop).not.toHaveBeenCalled();
-
-      provider.activityRecords_.removeByRouteId(route.id);
-      expect(mockAppDiscoveryService.stop).toHaveBeenCalled();
-    });
-
-    it('Sets SinkAvailability to UNAVAILABLE if no more sinks', () => {
-      mockSinkDiscoveryService.getSinkCount.and.returnValue(0);
-      // Note: This should also work if an non-empty list if passed in. For
-      // simplicity, an empty list is used here.
-      provider.onSinksRemoved([]);
-      expect(mockPmCallbacks.onSinkAvailabilityUpdated)
-          .toHaveBeenCalledWith(provider, SinkAvailability.UNAVAILABLE);
-    });
-  });
-
-  describe('terminateRoute Test', function() {
-    it('Terminates an existing route', function(done) {
-      const route = provider.addRoute(
-          'sink1', youTubeUrl, false, 'app1', 'presentationId1');
-      mockDialClient.stopApp.and.returnValue(Promise.resolve());
-      provider.terminateRoute(route.id).then(() => done());
-    });
-
-    it('Fails to terminate when DialClient returns an error', function(done) {
-      const route = provider.addRoute(
-          'sink1', youTubeUrl, false, 'app1', 'presentationId1');
-      const errorMsg = 'Failed to stop';
-      mockDialClient.stopApp.and.returnValue(Promise.reject(errorMsg));
-      provider.terminateRoute(route.id)
-          .then(() => done.fail('terminateRoute() succeeded unexpectedly'))
-          .catch(error => {
-            if (error == errorMsg) {
-              done();
-            } else {
-              done.fail('Got an unexpected error: ' + error);
-            }
-          });
-    });
-  });
-
-  describe('Disables Dial sink query', function() {
-    beforeEach(function() {
-      PersistentDataManager.clear();
-      provider.initialize({enable_dial_sink_query: false});
-      expect(mockAppDiscoveryService.start).not.toHaveBeenCalled();
-    });
-
-    it('Starting and stopping observing media sinks does nothing', function() {
-      provider.startObservingMediaSinks(youTubeUrl);
-      expect(mockAppDiscoveryService.registerApp).not.toHaveBeenCalled();
-
-      provider.stopObservingMediaSinks(youTubeUrl);
-      expect(mockAppDiscoveryService.unregisterApp).not.toHaveBeenCalled();
-    });
-
-    it('onSinkAdded does not start app discovery', function() {
-      const sink = new DialSink('s1', 'sink1');
-      provider.onSinkAdded(sink);
-      expect(mockAppDiscoveryService.scanSink).not.toHaveBeenCalled();
-
-      const sinkList = provider.getAvailableSinks();
-      expect(sinkList.sinks.length).toBe(0);
-    });
-  });
-});
diff --git a/providers/dial/dial_sink.js b/providers/dial/dial_sink.js
deleted file mode 100644
index 8cf0e1f..0000000
--- a/providers/dial/dial_sink.js
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.Sink');
-goog.module.declareLegacyNamespace();
-
-const Sink = goog.require('mr.Sink');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-
-
-/**
- * A wrapper for Sink containing DIAL specific data.
- */
-const DialSink = class {
-  /**
-   * @param {string} friendlyName
-   * @param {string} uniqueId
-   * @final
-   */
-  constructor(friendlyName, uniqueId) {
-    /** @private {?string} */
-    this.ipAddress_ = null;
-
-    /** @private {?number} */
-    this.port_ = null;
-
-    /** @private {?string} */
-    this.dialAppUrl_ = null;
-
-    /** @private {?string} */
-    this.deviceDescriptionUrl_ = null;
-
-    /** @private {?string} */
-    this.modelName_ = null;
-
-    /** @private @const {!Sink} */
-    this.mrSink_ = new Sink(uniqueId, friendlyName);
-
-    /**
-     * Holds the status of applications that may be available on the sink.
-     * Keys are application Names.
-     * @private {!Object<string, SinkAppStatus>}
-     */
-    this.appStatusMap_ = {};
-
-    /**
-     * Holds the timestamp when the status of applications was set.
-     * @private {!Object<string, number>}
-     */
-    this.appStatusTimeStamp_ = {};
-
-    /** @private {boolean} */
-    this.supportsAppAvailability_ = false;
-  }
-
-  /**
-   * @return {!Sink}
-   */
-  getMrSink() {
-    return this.mrSink_;
-  }
-
-  /**
-   * @return {string} A human readable name for the sink.
-   */
-  getFriendlyName() {
-    return this.mrSink_.friendlyName;
-  }
-
-  /**
-   * @param {string} friendlyName
-   * @return {!mr.dial.Sink} This sink.
-   */
-  setFriendlyName(friendlyName) {
-    this.mrSink_.friendlyName = friendlyName;
-    return this;
-  }
-
-  /**
-   * @return {?string} sink model name if known.
-   */
-  getModelName() {
-    return this.modelName_;
-  }
-
-  /**
-   * @param {?string} modelName
-   * @return {!mr.dial.Sink} This sink.
-   */
-  setModelName(modelName) {
-    this.modelName_ = modelName;
-    return this;
-  }
-
-  /**
-   * @return {string} An identifier for this sink.
-   */
-  getId() {
-    return this.mrSink_.id;
-  }
-
-  /**
-   * @param {string} id
-   * @return {!mr.dial.Sink} This sink.
-   */
-  setId(id) {
-    this.mrSink_.id = id;
-    return this;
-  }
-
-  /**
-   * @return {boolean} Whether this sink supports queries for DIAL app
-   *     availability.
-   */
-  supportsAppAvailability() {
-    return this.supportsAppAvailability_;
-  }
-
-  /**
-   * Sets whether this sink supports DIAL app availability queries.
-   * @param {boolean} availability
-   * @return {!mr.dial.Sink} This sink.
-   */
-  setSupportsAppAvailability(availability) {
-    this.supportsAppAvailability_ = availability;
-    return this;
-  }
-
-  /**
-   * Updates sink properties.
-   * Fields that can be updated: friendlyName, dialAppUrl_,
-   * deviceDescriptionUrl_, ipAddress_, port_.
-   * @param {!mr.dial.Sink} sink
-   * @return {boolean} Whether the update resulted in changes to the sink.
-   */
-  update(sink) {
-    if (this.getId() != sink.getId()) {
-      return false;
-    }
-
-    let updated = false;
-
-    if (this.mrSink_.friendlyName != sink.mrSink_.friendlyName) {
-      this.mrSink_.friendlyName = sink.mrSink_.friendlyName;
-      updated = true;
-    }
-
-    if (this.dialAppUrl_ != sink.dialAppUrl_) {
-      this.dialAppUrl_ = sink.dialAppUrl_;
-      updated = true;
-    }
-
-    if (this.deviceDescriptionUrl_ != sink.deviceDescriptionUrl_) {
-      this.deviceDescriptionUrl_ = sink.deviceDescriptionUrl_;
-      updated = true;
-    }
-
-    if (this.ipAddress_ != sink.ipAddress_) {
-      this.ipAddress_ = sink.ipAddress_;
-      updated = true;
-    }
-
-    if (this.port_ != sink.port_) {
-      this.port_ = sink.port_;
-      updated = true;
-    }
-
-    return updated;
-  }
-
-  /**
-   * @return {?string} The IP address of the sink, if any.
-   */
-  getIpAddress() {
-    return this.ipAddress_;
-  }
-
-  /**
-   * @param {?string} ipAddress The sink IP address.
-   * @return {!mr.dial.Sink} This sink.
-   */
-  setIpAddress(ipAddress) {
-    this.ipAddress_ = ipAddress;
-    return this;
-  }
-
-  /**
-   * @return {?number} The port number of the secure channel service.
-   */
-  getPort() {
-    return this.port_;
-  }
-
-  /**
-   * @param {?number} port
-   * @return {!mr.dial.Sink} This sink.
-   */
-  setPort(port) {
-    this.port_ = port;
-    return this;
-  }
-
-  /**
-   * @return {?string} The DIAL application URL, if any.
-   */
-  getDialAppUrl() {
-    return this.dialAppUrl_;
-  }
-
-  /**
-   * @param {string} url The DIAL app URL.
-   * @return {!mr.dial.Sink} This sink.
-   */
-  setDialAppUrl(url) {
-    this.dialAppUrl_ = url;
-    return this;
-  }
-
-  /**
-   * @return {?string} The DIAL device description URL, if any.
-   */
-  getDeviceDescriptionUrl() {
-    return this.deviceDescriptionUrl_;
-  }
-
-  /**
-   * @param {string} url The DIAL device description URL.
-   * @return {!mr.dial.Sink} This sink.
-   */
-  setDeviceDescriptionUrl(url) {
-    this.deviceDescriptionUrl_ = url;
-    return this;
-  }
-
-  /**
-   * Gets the availability of an application.
-   * @param {string} appName
-   * @return {SinkAppStatus} The status of the application, or null if it was
-   *     not set.
-   */
-  getAppStatus(appName) {
-    return this.appStatusMap_[appName] || SinkAppStatus.UNKNOWN;
-  }
-
-  /**
-   * Gets the time stamp of the availability of an application was set.
-   * @param {string} appName
-   * @return {?number} the number of milliseconds between midnight, January 1,
-   *     1970 and the current time, or null if availability was not set.
-   */
-  getAppStatusTimeStamp(appName) {
-    return this.appStatusTimeStamp_[appName] || null;
-  }
-
-  /**
-   * Sets the availability of an application.
-   * @param {string} appName
-   * @param {SinkAppStatus} status
-   * @return {!mr.dial.Sink} This sink.
-   */
-  setAppStatus(appName, status) {
-    this.appStatusMap_[appName] = status;
-    this.appStatusTimeStamp_[appName] = Date.now();
-    return this;
-  }
-
-  /**
-   * Clears all app status from the sink.
-   * @return {!mr.dial.Sink} This sink.
-   */
-  clearAppStatus() {
-    this.appStatusMap_ = {};
-    this.appStatusTimeStamp_ = {};
-    return this;
-  }
-
-  /**
-   * @return {string} String suitable for fine logging.
-   */
-  toDebugString() {
-    return 'name = ' + this.mrSink_.friendlyName +
-        (this.ipAddress_ ? ', ip = ' + this.ipAddress_ : '') +
-        (this.modelName_ ? ', model = ' + this.modelName_ : '') +
-        ', apps = ' + JSON.stringify(this.appStatusMap_);
-  }
-
-  /**
-   * Creates a new sink and copies the fields of the input sink to this.
-   * @param {!Object<string, *>} sink The object containing data fields.
-   * @return {!mr.dial.Sink} A newly created sink.
-   */
-  static createFrom(sink) {
-    const newSink = new DialSink(sink.mrSink_.friendlyName, '');
-    newSink.mrSink_.id = sink.mrSink_.id;  // Override the sink ID.
-    newSink.ipAddress_ = sink.ipAddress_;
-    newSink.port_ = sink.port_;
-    newSink.dialAppUrl_ = sink.dialAppUrl_;
-    newSink.deviceDescriptionUrl_ = sink.deviceDescriptionUrl_;
-    newSink.modelName_ = sink.modelName_;
-    newSink.appStatusMap_ = sink.appStatusMap_;
-    newSink.appStatusTimeStamp_ = sink.appStatusTimeStamp_;
-    newSink.supportsAppAvailability_ = sink.supportsAppAvailability_;
-    return newSink;
-  }
-};
-
-
-exports = DialSink;
diff --git a/providers/dial/dial_sink_discovery_service.js b/providers/dial/dial_sink_discovery_service.js
deleted file mode 100644
index 93d062e..0000000
--- a/providers/dial/dial_sink_discovery_service.js
+++ /dev/null
@@ -1,334 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.SinkDiscoveryService');
-goog.module.declareLegacyNamespace();
-
-const DeviceCounts = goog.require('mr.DeviceCounts');
-const DeviceCountsProvider = goog.require('mr.DeviceCountsProvider');
-const DialAnalytics = goog.require('mr.DialAnalytics');
-const DialSink = goog.require('mr.dial.Sink');
-const Logger = goog.require('mr.Logger');
-const PersistentData = goog.require('mr.PersistentData');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const SinkDiscoveryCallbacks = goog.require('mr.dial.SinkDiscoveryCallbacks');
-const SinkList = goog.require('mr.SinkList');
-
-
-/**
- * Implements local discovery using DIAL.
- * DIAL specification:
- * http://www.dial-multiscreen.org/dial-protocol-specification
- * @implements {PersistentData}
- * @implements {DeviceCountsProvider}
- */
-class SinkDiscoveryService {
-  /**
-   * @param {!SinkDiscoveryCallbacks} sinkCallBacks
-   * @final
-   */
-  constructor(sinkCallBacks) {
-    /**
-     * @private @const {!SinkDiscoveryCallbacks}
-     */
-    this.sinkCallBacks_ = sinkCallBacks;
-
-    /**
-     * @private @const {?Logger}
-     */
-    this.logger_ = Logger.getInstance('mr.dial.SinkDiscoveryService');
-
-    /**
-     * The current set of *accessible* receivers, indexed by id.
-     * @private @const {!Map<string, !DialSink>}
-     */
-    this.sinkMap_ = new Map();
-
-    /**
-     * The most recent snapshot of device counts.
-     * Updated when a DIAL onDeviceList or onError event is received.
-     * Part of PersistentData.
-     * @private {!DeviceCounts}
-     */
-    this.deviceCounts_ = {availableDeviceCount: 0, knownDeviceCount: 0};
-
-    /**
-     * The last time device counts were recorded in DialAnalytics.
-     * Persistent data.
-     * @private {number}
-     */
-    this.deviceCountMetricsRecordTime_ = 0;
-  }
-
-  /**
-   * Initializes the service. Must be called before any other methods.
-   */
-  init() {
-    PersistentDataManager.register(this);
-  }
-
-  /**
-   * Add |sinks| to sink map. Remove outdated sinks that are in sink map but not
-   * in |sinks|.
-   * @param {!Array<!mojo.Sink>} sinks list of sinks discovered by Media Router.
-   */
-  addSinks(sinks) {
-    this.logger_.info('addSinks returned ' + sinks.length + ' sinks');
-    this.logger_.fine(() => '....the list is: ' + JSON.stringify(sinks));
-
-    const oldSinkIds = new Set(this.sinkMap_.keys());
-    sinks.forEach(mojoSink => {
-      const dialSink = SinkDiscoveryService.convertSink_(mojoSink);
-      this.mayAddSink_(dialSink);
-      oldSinkIds.delete(dialSink.getId());
-    });
-
-    let removedSinks = [];
-    oldSinkIds.forEach(sinkId => {
-      const sink = this.sinkMap_.get(sinkId);
-      removedSinks.push(sink);
-      this.sinkMap_.delete(sinkId);
-    });
-
-    if (removedSinks.length > 0) {
-      this.sinkCallBacks_.onSinksRemoved(removedSinks);
-    }
-
-    // Record device count for feedback.
-    const sinkCount = this.getSinkCount();
-    this.deviceCounts_ = {
-      availableDeviceCount: sinkCount,
-      knownDeviceCount: sinkCount
-    };
-  }
-
-  /**
-   * Updates deviceCounts_ with the given counts, and reports to analytics if
-   * applicable.
-   * @param {number} availableDeviceCount
-   * @param {number} knownDeviceCount
-   * @private
-   */
-  recordDeviceCounts_(availableDeviceCount, knownDeviceCount) {
-    this.deviceCounts_ = {
-      availableDeviceCount: availableDeviceCount,
-      knownDeviceCount: knownDeviceCount
-    };
-    if (Date.now() - this.deviceCountMetricsRecordTime_ <
-        SinkDiscoveryService.DEVICE_COUNT_METRIC_THRESHOLD_MS_) {
-      return;
-    }
-    DialAnalytics.recordDeviceCounts(this.deviceCounts_);
-    this.deviceCountMetricsRecordTime_ = Date.now();
-  }
-
-  /**
-   * Adds or updates an existing sink with the given sink.
-   * @param {!DialSink} sink The new or updated sink.
-   * @private
-   */
-  mayAddSink_(sink) {
-    this.logger_.fine('mayAddSink, id = ' + sink.getId());
-    const sinkToUpdate = this.sinkMap_.get(sink.getId());
-    if (sinkToUpdate) {
-      if (sinkToUpdate.update(sink)) {
-        this.logger_.fine('Updated sink ' + sinkToUpdate.getId());
-        this.sinkCallBacks_.onSinkUpdated(sinkToUpdate);
-      }
-    } else {
-      this.logger_.fine(
-          () => `Adding new sink ${sink.getId()}: ${sink.toDebugString()}`);
-      this.sinkMap_.set(sink.getId(), sink);
-      this.sinkCallBacks_.onSinkAdded(sink);
-    }
-  }
-
-  /**
-   * Converts a mojo.Sink to a DialSink.
-   * @param {!mojo.Sink} mojoSink returned by Media Router at browser side.
-   * @return {!DialSink} DIAL sink.
-   * @private
-   */
-  static convertSink_(mojoSink) {
-
-    const uniqueId = mojoSink.sink_id;
-    const extraData = mojoSink.extra_data.dial_media_sink;
-    const isDiscoveryOnly =
-        SinkDiscoveryService.isDiscoveryOnly_(extraData.model_name);
-
-    const ip_address = extraData.ip_address.address_bytes ?
-        extraData.ip_address.address_bytes.join('.') :
-        extraData.ip_address.address.join('.');
-    return new DialSink(mojoSink.name, uniqueId)
-        .setIpAddress(ip_address)
-        .setDialAppUrl(extraData.app_url.url)
-        .setModelName(extraData.model_name)
-        .setSupportsAppAvailability(!isDiscoveryOnly);
-  }
-
-  /**
-   * Returns true if DIAL (SSDP) was only used to discover this sink, and it is
-   * not expected to support other DIAL features (app discovery, activity
-   * discovery, etc.)
-   * @param {string} modelName
-   * @return {boolean}
-   * @private
-   */
-  static isDiscoveryOnly_(modelName) {
-    return SinkDiscoveryService.DISCOVERY_ONLY_RE_.test(modelName);
-  }
-
-  /**
-   * Returns the sink with the given ID, or null if not found.
-   * @param {string} sinkId
-   * @return {?DialSink}
-   */
-  getSinkById(sinkId) {
-    return this.sinkMap_.get(sinkId) || null;
-  }
-
-  /**
-   * Returns sinks that report availability of the given app name.
-   * @param {string} appName
-   * @return {!SinkList}
-   */
-  getSinksByAppName(appName) {
-    const sinks = [];
-    this.sinkMap_.forEach(dialSink => {
-      if (dialSink.getAppStatus(appName) == SinkAppStatus.AVAILABLE)
-        sinks.push(dialSink.getMrSink());
-    });
-    return new SinkList(
-        sinks, SinkDiscoveryService.APP_ORIGIN_WHITELIST_[appName]);
-  }
-
-  /**
-   * Returns current sinks.
-   * @return {!Array<!DialSink>}
-   */
-  getSinks() {
-    return Array.from(this.sinkMap_.values());
-  }
-
-  /**
-   * @override
-   */
-  getDeviceCounts() {
-    return this.deviceCounts_;
-  }
-
-  /**
-   * @return {number}
-   */
-  getSinkCount() {
-    return this.sinkMap_.size;
-  }
-
-  /**
-   * Invoked when the app status of a sink changes.
-   * @param {string} appName
-   * @param {!DialSink} sink The sink whose status changed.
-   */
-  onAppStatusChanged(appName, sink) {
-    this.sinkCallBacks_.onSinkUpdated(sink);
-  }
-
-  /**
-   * @override
-   */
-  getStorageKey() {
-    return 'dial.DialSinkDiscoveryService';
-  }
-
-  /**
-   * @override
-   */
-  getData() {
-    return [
-      new SinkDiscoveryService.PersistentData_(
-          Array.from(this.sinkMap_), this.deviceCounts_),
-      {'deviceCountMetricsRecordTime': this.deviceCountMetricsRecordTime_}
-    ];
-  }
-
-  /**
-   * @override
-   */
-  loadSavedData() {
-    const tempData =
-        /** @type {?SinkDiscoveryService.PersistentData_} */ (
-            PersistentDataManager.getTemporaryData(this));
-    if (tempData) {
-      for (const entry of tempData.sinks) {
-        this.sinkMap_.set(entry[0], DialSink.createFrom(entry[1]));
-      }
-      this.deviceCounts_ = tempData.deviceCounts;
-    }
-
-    const permanentData = PersistentDataManager.getPersistentData(this);
-    if (permanentData) {
-      this.deviceCountMetricsRecordTime_ =
-          permanentData['deviceCountMetricsRecordTime'];
-    }
-  }
-}
-
-
-/**
- * @private @const {!Object<string, !Array<string>>}
- */
-SinkDiscoveryService.APP_ORIGIN_WHITELIST_ = {
-  'YouTube': [
-    'https://tv.youtube.com', 'https://tv-green-qa.youtube.com',
-    'https://tv-release-qa.youtube.com', 'https://web-green-qa.youtube.com',
-    'https://web-release-qa.youtube.com', 'https://www.youtube.com'
-  ],
-  'Netflix': ['https://www.netflix.com'],
-  'Pandora': ['https://www.pandora.com'],
-  'Radio': ['https://www.pandora.com'],
-  'Hulu': ['https://www.hulu.com'],
-  'Vimeo': ['https://www.vimeo.com'],
-  'Dailymotion': ['https://www.dailymotion.com'],
-  'com.dailymotion': ['https://www.dailymotion.com'],
-};
-
-
-/**
- * Matches DIAL model names that only support discovery.
-
- * @private @const {!RegExp}
- */
-SinkDiscoveryService.DISCOVERY_ONLY_RE_ =
-    new RegExp('Eureka Dongle|Chromecast Audio|Chromecast Ultra', 'i');
-
-/**
- * How long to wait between device counts metrics are recorded. Set to 1 hour.
- * @private @const {number}
- */
-SinkDiscoveryService.DEVICE_COUNT_METRIC_THRESHOLD_MS_ = 60 * 60 * 1000;
-
-
-/**
- * @private
- */
-SinkDiscoveryService.PersistentData_ = class {
-  /**
-   * @param {!Array} sinks
-   * @param {!DeviceCounts} deviceCounts
-   */
-  constructor(sinks, deviceCounts) {
-    /**
-     * @const {!Array}
-     */
-    this.sinks = sinks;
-
-    /**
-     * @const {!DeviceCounts}
-     */
-    this.deviceCounts = deviceCounts;
-  }
-};
-
-exports = SinkDiscoveryService;
diff --git a/providers/dial/dial_sink_discovery_service_test.js b/providers/dial/dial_sink_discovery_service_test.js
deleted file mode 100644
index 1aad198..0000000
--- a/providers/dial/dial_sink_discovery_service_test.js
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.SinkDiscoveryServiceTest');
-goog.setTestOnly('mr.dial.SinkDiscoveryServiceTest');
-
-const DialAnalytics = goog.require('mr.DialAnalytics');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const SinkDiscoveryService = goog.require('mr.dial.SinkDiscoveryService');
-const UnitTestUtils = goog.require('mr.UnitTestUtils');
-
-describe('DIAL SinkDiscoveryService Tests', function() {
-  let service;
-  let mockClock;
-  let mockSinkCallbacks;
-
-  beforeEach(function() {
-    mockClock = UnitTestUtils.useMockClockAndPromises();
-    mockSinkCallbacks = jasmine.createSpyObj(
-        'SinkCallbacks', ['onSinkAdded', 'onSinksRemoved', 'onSinkUpdated']);
-
-    chrome.metricsPrivate = {
-      recordTime: jasmine.createSpy('recordTime'),
-      recordMediumTime: jasmine.createSpy('recordMediumTime'),
-      recordLongTime: jasmine.createSpy('recordLongTime'),
-      recordUserAction: jasmine.createSpy('recordUserAction')
-    };
-
-    service = new SinkDiscoveryService(mockSinkCallbacks);
-    spyOn(DialAnalytics, 'recordDeviceCounts');
-  });
-
-  afterEach(function() {
-    UnitTestUtils.restoreRealClockAndPromises();
-    PersistentDataManager.clear();
-  });
-
-
-  /**
-   * Creates mojo sink instances.
-   * @param {number} numSinks The number of mojo sinks to create.
-   * @return {!Array<!mojo.Sink>} The mojo sinks.
-   */
-  function createMojoSinks(numSinks) {
-    const mojoSinks = [];
-    for (var i = 1; i <= numSinks; i++) {
-      const dialMediaSink = {
-        ip_address: {address_bytes: [127, 0, 0, i]},
-        model_name: 'Eureka Dongle',
-        app_url: {url: 'http://127.0.0.' + i + ':8008/apps'}
-      };
-
-      mojoSinks.push({
-        sink_id: 'sinkId ' + i,
-        name: 'TV ' + i,
-        extra_data: {dial_media_sink: dialMediaSink}
-      });
-    }
-    return mojoSinks;
-  }
-
-  describe('addSinks tests', function() {
-    beforeEach(function() {
-      service.init();
-    });
-
-    it('add mojo sinks to sink map', function() {
-      expect(service.getSinks().length).toBe(0);
-      const mojoSinks = createMojoSinks(1);
-      service.addSinks(mojoSinks);
-
-      // sinks were added
-      const actualSinks = service.getSinks();
-      expect(actualSinks.length).toBe(1);
-
-      const actualSink = actualSinks[0];
-      const mojoSink = mojoSinks[0];
-      const extraData = mojoSink.extra_data.dial_media_sink;
-      expect(actualSink.getFriendlyName()).toEqual(mojoSink.name);
-      expect(actualSink.getIpAddress())
-          .toEqual(extraData.ip_address.address_bytes.join('.'));
-      expect(actualSink.getDialAppUrl()).toEqual(extraData.app_url.url);
-      expect(actualSink.getModelName()).toEqual(extraData.model_name);
-      expect(actualSink.supportsAppAvailability()).toEqual(false);
-
-      // add-sink-events were fired.
-      expect(mockSinkCallbacks.onSinkAdded.calls.count()).toBe(1);
-      expect(mockSinkCallbacks.onSinksRemoved.calls.count()).toBe(0);
-    });
-
-    it('remove outdated sinks', function() {
-      expect(service.getSinks().length).toBe(0);
-      const mojoSinks = createMojoSinks(3);
-      // First round discover sink 1, 2, 3
-      service.addSinks(mojoSinks);
-
-      // Second round discover sink 1
-      const mojoSinks2 = createMojoSinks(1);
-      service.addSinks(mojoSinks2);
-      expect(mockSinkCallbacks.onSinkAdded.calls.count()).toBe(3);
-
-      // 2 devices were removed
-      expect(mockSinkCallbacks.onSinksRemoved.calls.count()).toBe(1);
-      const sinks = mockSinkCallbacks.onSinksRemoved.calls.argsFor(0)[0];
-      expect(sinks.length).toBe(2);
-      expect(sinks[0].getFriendlyName()).toEqual(mojoSinks[1].name);
-      expect(sinks[1].getFriendlyName()).toEqual(mojoSinks[2].name);
-
-      expect(mockSinkCallbacks.onSinkUpdated.calls.count()).toBe(0);
-    });
-
-    it('Gets sinks by app name', function() {
-      const mojoSinks = createMojoSinks(3);
-      service.addSinks(mojoSinks);
-      service.getSinkById(mojoSinks[0].sink_id)
-          .setAppStatus('YouTube', SinkAppStatus.AVAILABLE);
-      service.getSinkById(mojoSinks[1].sink_id)
-          .setAppStatus('Netflix', SinkAppStatus.AVAILABLE);
-      service.getSinkById(mojoSinks[1].sink_id)
-          .setAppStatus('YouTube', SinkAppStatus.AVAILABLE);
-      service.getSinkById(mojoSinks[2].sink_id)
-          .setAppStatus('Pandora', SinkAppStatus.UNAVAILABLE);
-      expect(service.getSinksByAppName('YouTube').sinks.length).toBe(2);
-      expect(service.getSinksByAppName('Netflix').sinks.length).toBe(1);
-      expect(service.getSinksByAppName('Netflix').sinks[0].id)
-          .toEqual(mojoSinks[1].sink_id);
-      expect(service.getSinksByAppName('Pandora').sinks.length).toBe(0);
-    });
-
-  });
-
-  it('Saves PersistentData without any data', function() {
-    service.init();
-    expect(service.getSinks()).toEqual([]);
-    PersistentDataManager.suspendForTest();
-    service = new SinkDiscoveryService(mockSinkCallbacks);
-    service.loadSavedData();
-    expect(service.getSinks()).toEqual([]);
-  });
-
-  it('Saves PersistentData with data', function() {
-    service.init();
-    service.addSinks(createMojoSinks(3));
-    mockClock.tick(1);
-    const sinks = service.getSinks();
-    expect(sinks.length).toBe(3);
-    const expectedDeviceCounts = {availableDeviceCount: 3, knownDeviceCount: 3};
-    expect(service.getDeviceCounts()).toEqual(expectedDeviceCounts);
-
-    PersistentDataManager.suspendForTest();
-    service = new SinkDiscoveryService(mockSinkCallbacks);
-    service.loadSavedData();
-    const restoredSinks = service.getSinks();
-    expect(restoredSinks.length).toBe(3);
-    expect(service.getDeviceCounts()).toEqual(expectedDeviceCounts);
-    for (let index = 0; index < 3; index++) {
-      expect(sinks[0].getId()).toEqual(restoredSinks[0].getId());
-    }
-  });
-
-});
diff --git a/providers/dial/dial_sink_test.js b/providers/dial/dial_sink_test.js
deleted file mode 100644
index 03a4675..0000000
--- a/providers/dial/dial_sink_test.js
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.SinkTest');
-goog.setTestOnly('mr.dial.SinkTest');
-
-const DialSink = goog.require('mr.dial.Sink');
-const MockClock = goog.require('mr.MockClock');
-const Sink = goog.require('mr.Sink');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-
-describe('DIAL Sink Tests', function() {
-  let mockClock;
-
-  beforeEach(function() {
-    mockClock = new MockClock(true);
-  });
-
-  afterEach(function() {
-    mockClock.uninstall();
-  });
-
-  it('Gets and sets fields', function() {
-    const sink = new DialSink('name', 'id1');
-    expect(sink.getMrSink()).toEqual(new Sink('id1', 'name'));
-
-    expect(sink.getId()).toEqual('id1');
-    sink.setId('id2');
-    expect(sink.getId()).toEqual('id2');
-
-    expect(sink.getIpAddress()).toBeNull();
-    sink.setIpAddress('192.168.111.1');
-    expect(sink.getIpAddress()).toEqual('192.168.111.1');
-
-    expect(sink.getDialAppUrl()).toBeNull();
-    sink.setDialAppUrl('http://192.168.111.1/apps');
-    expect(sink.getDialAppUrl()).toEqual('http://192.168.111.1/apps');
-
-    expect(sink.getDeviceDescriptionUrl()).toBeNull();
-    sink.setDeviceDescriptionUrl('http://192.168.111.1/desc');
-    expect(sink.getDeviceDescriptionUrl()).toEqual('http://192.168.111.1/desc');
-
-    expect(sink.getModelName()).toBeNull();
-    sink.setModelName('chromecast');
-    expect(sink.getModelName()).toEqual('chromecast');
-
-    expect(sink.getFriendlyName()).toEqual('name');
-    sink.setFriendlyName('newname');
-    expect(sink.getFriendlyName()).toEqual('newname');
-
-    expect(sink.getPort()).toEqual(null);
-    sink.setPort(8009);
-    expect(sink.getPort()).toEqual(8009);
-  });
-
-  it('Gets and sets sink app status', function() {
-    const sink = new DialSink('name', 'uniqueId');
-    expect(sink.getAppStatus('youtube')).toBe(SinkAppStatus.UNKNOWN);
-    expect(sink.getAppStatusTimeStamp('youtube')).toBe(null);
-
-    mockClock.tick(10);
-    const now1 = Date.now();
-    sink.setAppStatus('youtube', SinkAppStatus.AVAILABLE);
-    mockClock.tick(10);
-    const now2 = Date.now();
-    sink.setAppStatus('app2', SinkAppStatus.UNAVAILABLE);
-    expect(sink.getAppStatus('youtube')).toBe(SinkAppStatus.AVAILABLE);
-    expect(sink.getAppStatusTimeStamp('youtube')).toBe(now1);
-    expect(sink.getAppStatus('app2')).toBe(SinkAppStatus.UNAVAILABLE);
-    expect(sink.getAppStatusTimeStamp('app2')).toBe(now2);
-
-    sink.clearAppStatus();
-    expect(sink.getAppStatus('youtube')).toBe(SinkAppStatus.UNKNOWN);
-    expect(sink.getAppStatusTimeStamp('youtube')).toBe(null);
-    expect(sink.getAppStatus('app2')).toBe(SinkAppStatus.UNKNOWN);
-    expect(sink.getAppStatusTimeStamp('app2')).toBe(null);
-  });
-
-  it('Updates sink from another sink', function() {
-    const sink = new DialSink('name', 'uniqueId')
-                     .setDialAppUrl('http://192.168.111.1/apps')
-                     .setPort(8009)
-                     .setDeviceDescriptionUrl('http://192.168.111.1/desc');
-
-    let updatedSink = new DialSink('name2', 'uniqueId');
-    expect(sink.update(updatedSink)).toBe(true);
-    expect(sink.getFriendlyName()).toEqual('name2');
-
-    updatedSink = new DialSink('name', 'uniqueId')
-                      .setDialAppUrl('http://192.168.111.1/apps/app2');
-    expect(sink.update(updatedSink)).toBe(true);
-    expect(sink.getDialAppUrl()).toEqual('http://192.168.111.1/apps/app2');
-
-    updatedSink = new DialSink('name', 'uniqueId').setId('id2');
-    expect(sink.update(updatedSink)).toBe(false);
-  });
-
-  it('Updates ip address', function() {
-    const sink = new DialSink('name', 'uniqueId').setIpAddress('192.168.111.1');
-    const updatedSink =
-        new DialSink('name', 'uniqueId').setIpAddress('192.168.111.2');
-    expect(sink.update(updatedSink)).toBe(true);
-    expect(sink.getIpAddress()).toEqual('192.168.111.2');
-  });
-
-  it('Updates device description url', function() {
-    const sink = new DialSink('name', 'uniqueId')
-                     .setDeviceDescriptionUrl('http://192.168.111.1/desc');
-    const updatedSink =
-        new DialSink('name', 'uniqueId')
-            .setDeviceDescriptionUrl('http://192.168.111.2/desc');
-    expect(sink.update(updatedSink)).toBe(true);
-    expect(sink.getDeviceDescriptionUrl()).toEqual('http://192.168.111.2/desc');
-  });
-
-  it('Creates sink from an Object', function() {
-    const sink = new DialSink('name', 'uniqueId')
-                     .setDialAppUrl('http://192.168.111.1/apps')
-                     .setPort(8009)
-                     .setDeviceDescriptionUrl('http://192.168.111.1/desc')
-                     .setAppStatus('youtube', SinkAppStatus.AVAILABLE)
-                     .setIpAddress('192.168.111.1')
-                     .setModelName('chromecast');
-    expect(DialSink.createFrom(sink)).toEqual(sink);
-  });
-});
diff --git a/providers/dial/presentation_url.js b/providers/dial/presentation_url.js
deleted file mode 100644
index 203b40e..0000000
--- a/providers/dial/presentation_url.js
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('mr.dial.PresentationUrl');
-
-const Logger = goog.require('mr.Logger');
-const base64 = goog.require('mr.base64');
-
-
-/**
- * Represents a DIAL media source containing information specific to a DIAL
- * launch.
- */
-const PresentationUrl = class {
-  /**
-   * @param {string} appName The DIAL application name.
-   * @param {string=} launchParameter DIAL application launch parameter.
-   */
-  constructor(appName, launchParameter = '') {
-    /** @const {string} */
-    this.appName = appName;
-    /** @const {string} */
-    this.launchParameter = launchParameter;
-  }
-
-  /**
-   * Generates a DIAL Presentation URL using given parameters.
-   * @param {string} dialAppName Name of the DIAL app.
-   * @param {?string} dialPostData base-64 encoded string of the data for the
-   *     DIAL launch.
-   * @return {string}
-   */
-  static getPresentationUrlAsString(dialAppName, dialPostData) {
-    const url = new URL('dial:' + dialAppName);
-    if (dialPostData) {
-      url.searchParams.set('postData', dialPostData);
-    }
-    return url.toString();
-  }
-
-  /**
-   * Constructs a DIAL media source from a URL. The URL can take on the new
-   * format (with dial: protocol) or the old format (with https: protocol).
-   * @param {string} urlString The media source URL.
-   * @return {?PresentationUrl} A DIAL media source if the parse was
-   *     successful, null otherwise.
-   */
-  static create(urlString) {
-    let url;
-    try {
-      url = new URL(urlString);
-    } catch (err) {
-      PresentationUrl.logger_.info('Invalid URL: ' + urlString);
-      return null;
-    }
-    switch (url.protocol) {
-      case 'dial:':
-        return PresentationUrl.parseDialUrl_(url);
-      case 'https:':
-
-        return PresentationUrl.parseLegacyUrl_(url);
-      default:
-        PresentationUrl.logger_.fine('Unhandled protocol: ' + url.protocol);
-        return null;
-    }
-  }
-
-  /**
-   * Parses the given URL using the new DIAL URL format, which takes the form:
-   * dial:<App name>?postData=<base64-encoded launch parameters>
-   * @param {!URL} url
-   * @return {?PresentationUrl}
-   * @private
-   */
-  static parseDialUrl_(url) {
-    const appName = url.pathname;
-    if (!appName.match(/^\w+$/)) {
-      PresentationUrl.logger_.warning('Invalid app name: ' + appName);
-      return null;
-    }
-    let postData = url.searchParams.get('postData') || undefined;
-    if (postData) {
-      try {
-        postData = base64.decodeString(postData);
-      } catch (err) {
-        PresentationUrl.logger_.warning(
-            'Invalid base64 encoded postData:' + postData);
-        return null;
-      }
-    }
-    return new PresentationUrl(appName, postData);
-  }
-
-  /**
-   * Parses the given URL using the legacy format specified in
-   * http://goo.gl/8qKAE7
-   * Example:
-   * http://www.youtube.com/tv#__dialAppName__=YouTube/__dialPostData__=dj0xMjM=
-   * @param {!URL} url
-   * @return {?PresentationUrl}
-   * @private
-   */
-  static parseLegacyUrl_(url) {
-    // Parse URI and get fragment.
-    const fragment = url.hash;
-    if (!fragment) return null;
-    let appName = PresentationUrl.APP_NAME_REGEX_.exec(fragment);
-    appName = appName ? appName[1] : null;
-    if (!appName) return null;
-    appName = decodeURIComponent(appName);
-
-    let postData = PresentationUrl.LAUNCH_PARAM_REGEX_.exec(fragment);
-    postData = postData ? postData[1] : undefined;
-    if (postData) {
-      try {
-        postData = base64.decodeString(postData);
-      } catch (err) {
-        PresentationUrl.logger_.warning(
-            'Invalid base64 encoded postData:' + postData);
-        return null;
-      }
-    }
-    return new PresentationUrl(appName, postData);
-  }
-};
-
-
-/** @const @private {?Logger} */
-PresentationUrl.logger_ = Logger.getInstance('mr.dial.PresentationUrl');
-
-
-/** @const {string} */
-PresentationUrl.URN_PREFIX = 'urn:dial-multiscreen-org:dial:application:';
-
-
-/** @private @const {!RegExp} */
-PresentationUrl.APP_NAME_REGEX_ =
-    /__dialAppName__=([A-Za-z0-9-._~!$&'()*+,;=%]+)/;
-
-
-/** @private @const {!RegExp} */
-PresentationUrl.LAUNCH_PARAM_REGEX_ = /__dialPostData__=([A-Za-z0-9]+={0,2})/;
-
-
-exports = PresentationUrl;
diff --git a/providers/dial/presentation_url_test.js b/providers/dial/presentation_url_test.js
deleted file mode 100644
index 4477e5e..0000000
--- a/providers/dial/presentation_url_test.js
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.module('PresentationUrlTest');
-goog.setTestOnly('PresentationUrlTest');
-
-const PresentationUrl = goog.require('mr.dial.PresentationUrl');
-
-describe('Tests PresentationUrl', function() {
-  it('Does not create from empty input', function() {
-    expect(PresentationUrl.create('')).toBeNull();
-  });
-
-  it('Creates from a valid URL', function() {
-    expect(PresentationUrl.create(
-               'https://www.youtube.com/tv#__dialAppName__=YouTube'))
-        .toEqual(new PresentationUrl('YouTube'));
-  });
-
-  it('Creates from a valid URL with launch parameters', function() {
-    expect(PresentationUrl.create(
-               'https://www.youtube.com/tv#' +
-               '__dialAppName__=YouTube/__dialPostData__=dj0xMjM='))
-        .toEqual(new PresentationUrl('YouTube', 'v=123'));
-    expect(PresentationUrl.create(
-               'https://www.youtube.com/tv#' +
-               '__dialAppName__=YouTube/__dialPostData__=dj1NSnlKS3d6eEZwWQ=='))
-        .toEqual(new PresentationUrl('YouTube', 'v=MJyJKwzxFpY'));
-  });
-
-  it('Does not create from an invalid URL', function() {
-    expect(PresentationUrl.create(
-               'https://www.youtube.com/tv#___emanPpaLiad__=YouTube'))
-        .toBeNull();
-  });
-
-  it('Does not create from an invalid postData', function() {
-    expect(PresentationUrl.create(
-               'https://www.youtube.com/tv#___emanPpaLiad__=YouTube' +
-               '/__dialPostData__=dj1=N'))
-        .toBeNull();
-  });
-
-  it('Creates from DIAL URL', () => {
-    expect(PresentationUrl.create('dial:YouTube'))
-        .toEqual(new PresentationUrl('YouTube'));
-    expect(PresentationUrl.create('dial:YouTube?foo=bar'))
-        .toEqual(new PresentationUrl('YouTube'));
-    expect(PresentationUrl.create('dial:YouTube?foo=bar&postData=dj0xMjM='))
-        .toEqual(new PresentationUrl('YouTube', 'v=123'));
-    expect(PresentationUrl.create('dial:YouTube?postData=dj0xMjM%3D'))
-        .toEqual(new PresentationUrl('YouTube', 'v=123'));
-  });
-
-  it('Does not create from invalid DIAL URL', () => {
-    expect(PresentationUrl.create('dial:')).toBeNull();
-    expect(PresentationUrl.create('dial://')).toBeNull();
-    expect(PresentationUrl.create('dial://YouTube')).toBeNull();
-    expect(
-        PresentationUrl.create('dial:YouTube?postData=notEncodedProperly111'))
-        .toBeNull();
-  });
-
-  it('Does not create from URL of unknown protocol', () => {
-    expect(PresentationUrl.create('unknown:YouTube')).toBeNull();
-  });
-
-  it('getPresentationUrl returns DIAL presentation URLs', () => {
-    expect(PresentationUrl.getPresentationUrlAsString('YouTube', null))
-        .toEqual('dial:YouTube');
-    expect(PresentationUrl.getPresentationUrlAsString('YouTube', 'dj0xMjM='))
-        .toEqual('dial:YouTube?postData=dj0xMjM%3D');
-  });
-});
diff --git a/providers/dial/sink_app_status.js b/providers/dial/sink_app_status.js
deleted file mode 100644
index 5acd9a9..0000000
--- a/providers/dial/sink_app_status.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview The availability of an app on a sink.
- */
-
-goog.provide('mr.dial.SinkAppStatus');
-
-
-/**
- * Tracks the availability of an app on a sink.  Apps start out in an
- * UNKNOWN status and are changed to AVAILABLE or UNAVAILABLE once the status is
- * known, i.e. after we query the sink for the app.
- *
- * @enum {string}
- */
-mr.dial.SinkAppStatus = {
-  AVAILABLE: 'available',
-  UNAVAILABLE: 'unavailable',
-  UNKNOWN: 'unknown'
-};
diff --git a/utils/event_analytics.js b/utils/event_analytics.js
index f9fbde5..ce105f0 100644
--- a/utils/event_analytics.js
+++ b/utils/event_analytics.js
@@ -23,8 +23,8 @@
   MEDIA_ROUTER: 0,
   CAST_CHANNEL_ON_ERROR: 1,
   CAST_CHANNEL_ON_MESSAGE: 2,
-  DIAL_ON_DEVICE_LIST: 3,
-  DIAL_ON_ERROR: 4,
+  DIAL_ON_DEVICE_LIST: 3,  // Obsolete
+  DIAL_ON_ERROR: 4,        // Obsolete
   GCM_ON_MESSAGE: 5,
   IDENTITY_ON_SIGN_IN_CHANGED: 6,
   MDNS_ON_SERVICE_LIST: 7,
diff --git a/utils/event_analytics_test.js b/utils/event_analytics_test.js
index 5be671d..b0b7bec 100644
--- a/utils/event_analytics_test.js
+++ b/utils/event_analytics_test.js
@@ -15,13 +15,12 @@
   describe('Test recordEvent', () => {
     it('should record only the first event', () => {
       spyOn(mr.Analytics, 'recordEnum');
-      mr.EventAnalytics.recordEvent(mr.EventAnalytics.Event.DIAL_ON_ERROR);
       mr.EventAnalytics.recordEvent(mr.EventAnalytics.Event.TABS_ON_UPDATED);
       expect(mr.Analytics.recordEnum.calls.count()).toEqual(1);
       expect(mr.Analytics.recordEnum)
           .toHaveBeenCalledWith(
               'MediaRouter.Provider.WakeEvent',
-              mr.EventAnalytics.Event.DIAL_ON_ERROR, mr.EventAnalytics.Event);
+              mr.EventAnalytics.Event.TABS_ON_UPDATED, mr.EventAnalytics.Event);
     });
   });
 });
diff --git a/utils/media_source_utils.js b/utils/media_source_utils.js
index 2b29b3a..e24ac97 100644
--- a/utils/media_source_utils.js
+++ b/utils/media_source_utils.js
@@ -11,8 +11,6 @@
 goog.require('mr.Config');
 
 
-
-
 /**
  * @param {string} sourceUrn
  * @return {boolean} True if it is a mirror URN.