Index: chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java |
index 766bf5940b27cc64622d062a6c24f3c1787a79d0..6da50106078781f0826f945b76d1452c87924d3c 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java |
@@ -12,6 +12,7 @@ import android.support.v7.media.MediaRouter.RouteInfo; |
import org.chromium.chrome.browser.media.router.ChromeMediaRouter; |
import org.chromium.chrome.browser.media.router.DiscoveryDelegate; |
+import org.chromium.chrome.browser.media.router.MediaRoute; |
import org.chromium.chrome.browser.media.router.MediaRouteManager; |
import org.chromium.chrome.browser.media.router.MediaRouteProvider; |
import org.chromium.chrome.browser.media.router.RouteController; |
@@ -41,10 +42,12 @@ public class CastMediaRouteProvider |
private final MediaRouteManager mManager; |
private final Map<String, DiscoveryCallback> mDiscoveryCallbacks = |
new HashMap<String, DiscoveryCallback>(); |
- private final Map<String, CastRouteController> mRoutes = |
- new HashMap<String, CastRouteController>(); |
- private final Map<String, String> mClientIdsToRouteIds = new HashMap<String, String>(); |
+ private final Map<String, MediaRoute> mRoutes = new HashMap<String, MediaRoute>(); |
+ private ClientRecord mLastRemovedRouteRecord; |
+ private final List<ClientRecord> mClientRecords = new ArrayList<ClientRecord>(); |
+ // There can be only one Cast session at the same time on Android. |
+ private SessionRecord mSession; |
private CreateRouteRequest mPendingCreateRouteRequest; |
private Handler mHandler = new Handler(); |
@@ -76,15 +79,33 @@ public class CastMediaRouteProvider |
} |
@Override |
- public void onRouteCreated(int requestId, RouteController route, boolean wasLaunched) { |
- assert route instanceof CastRouteController; |
+ public void onRouteCreated(int requestId, MediaRoute route, RouteController routeController) { |
+ String routeId = route.id; |
+ |
+ MediaSource source = MediaSource.from(route.sourceId); |
+ final String clientId = source.getClientId(); |
+ if (clientId != null && !mClientRecords.contains(clientId)) { |
mlamouri (slow - plz ping)
2015/11/27 14:23:39
I'm not sure I understand how you can check if Lis
whywhat
2015/11/27 19:44:39
Java for you... ¯\_(ツ)_/¯
Fixed.
|
+ mClientRecords.add(new ClientRecord( |
+ routeId, |
+ clientId, |
+ source.getApplicationId(), |
+ source.getAutoJoinPolicy(), |
+ routeController.getOrigin(), |
+ routeController.getTabId())); |
+ } |
+ |
+ if (mSession == null) { |
+ mSession = new SessionRecord(route.sinkId, (CastRouteController) routeController); |
+ } |
+ mSession.routeIds.add(routeId); |
- String routeId = route.getRouteId(); |
+ if (clientId != null && !mSession.clientIds.contains(clientId)) { |
+ mSession.clientIds.add(clientId); |
+ } |
- mRoutes.put(routeId, (CastRouteController) route); |
- mClientIdsToRouteIds.put(MediaSource.from(route.getSourceId()).getClientId(), routeId); |
+ mRoutes.put(routeId, route); |
- mManager.onRouteCreated(routeId, route.getSinkId(), requestId, this, wasLaunched); |
+ mManager.onRouteCreated(routeId, route.sinkId, requestId, this, true); |
} |
@Override |
@@ -93,8 +114,20 @@ public class CastMediaRouteProvider |
} |
@Override |
- public void onRouteClosed(RouteController route) { |
- mClientIdsToRouteIds.remove(MediaSource.from(route.getSourceId()).getClientId()); |
+ public void onRouteClosed(String routeId) { |
+ mLastRemovedRouteRecord = getClientRecordByRouteId(routeId); |
+ mClientRecords.remove(mLastRemovedRouteRecord); |
+ |
+ mManager.onRouteClosed(routeId); |
+ if (mSession != null) { |
+ for (String sessionRouteId : mSession.routeIds) { |
+ if (sessionRouteId.equals(routeId)) continue; |
+ |
+ mManager.onRouteClosed(routeId); |
+ } |
+ } |
+ |
+ mSession = null; |
if (mPendingCreateRouteRequest != null) { |
mPendingCreateRouteRequest.start(mApplicationContext); |
@@ -102,7 +135,6 @@ public class CastMediaRouteProvider |
} else if (mAndroidMediaRouter != null) { |
mAndroidMediaRouter.selectRoute(mAndroidMediaRouter.getDefaultRoute()); |
} |
- mManager.onRouteClosed(route.getRouteId()); |
} |
@Override |
@@ -194,111 +226,130 @@ public class CastMediaRouteProvider |
} |
@Override |
- public void createRoute(String sourceId, String sinkId, String routeId, String origin, |
+ public void createRoute(String sourceId, String sinkId, String presentationId, String origin, |
int tabId, int nativeRequestId) { |
if (mAndroidMediaRouter == null) { |
mManager.onRouteRequestError("Not supported", nativeRequestId); |
return; |
} |
- MediaSource source = MediaSource.from(sourceId); |
- if (source == null || source.getClientId() == null) { |
- mManager.onRouteRequestError("Unsupported presentation URL", nativeRequestId); |
- return; |
- } |
- |
MediaSink sink = MediaSink.fromSinkId(sinkId, mAndroidMediaRouter); |
if (sink == null) { |
mManager.onRouteRequestError("No sink", nativeRequestId); |
return; |
} |
+ MediaSource source = MediaSource.from(sourceId); |
+ if (source == null) { |
+ mManager.onRouteRequestError("Unsupported presentation URL", nativeRequestId); |
+ return; |
+ } |
+ |
CreateRouteRequest createRouteRequest = new CreateRouteRequest( |
- source, sink, routeId, origin, tabId, nativeRequestId, this); |
- String existingRouteId = mClientIdsToRouteIds.get(source.getClientId()); |
- if (existingRouteId == null) { |
- createRouteRequest.start(mApplicationContext); |
+ source, sink, presentationId, origin, tabId, nativeRequestId, this); |
+ |
+ // TODO(avayvod): Implement ReceiverAction.CAST, https://crbug.com/561470. |
+ |
+ // Since we only have one session, close it before starting a new one. |
+ if (mSession != null && !mSession.isStopping) { |
+ mPendingCreateRouteRequest = createRouteRequest; |
+ mSession.isStopping = true; |
+ mSession.session.close(); |
return; |
} |
- mPendingCreateRouteRequest = createRouteRequest; |
- closeRoute(existingRouteId); |
+ createRouteRequest.start(mApplicationContext); |
} |
@Override |
public void joinRoute(String sourceId, String presentationId, String origin, int tabId, |
int nativeRequestId) { |
+ if (mSession == null) { |
+ mManager.onRouteRequestError("No presentation", nativeRequestId); |
+ return; |
+ } |
+ |
MediaSource source = MediaSource.from(sourceId); |
if (source == null || source.getClientId() == null) { |
mManager.onRouteRequestError("Unsupported presentation URL", nativeRequestId); |
return; |
} |
- CastRouteController routeToJoin = null; |
+ // TODO(avayvod): Implement _receiver-action route for ReceiverAction messages, |
+ // https://crbug.com/561470. |
+ |
+ boolean canJoinExistingSession = false; |
if (AUTO_JOIN_PRESENTATION_ID.equals(presentationId)) { |
- routeToJoin = autoJoinRoute(source, origin, tabId); |
+ canJoinExistingSession = canAutoJoin(source, origin, tabId); |
} else if (presentationId.startsWith(PRESENTATION_ID_SESSION_ID_PREFIX)) { |
String sessionId = presentationId.substring(PRESENTATION_ID_SESSION_ID_PREFIX.length()); |
- for (CastRouteController route : mRoutes.values()) { |
- if (sessionId.equals(route.getSessionId())) { |
- routeToJoin = route; |
- break; |
- } |
- } |
- } else { |
- for (CastRouteController route : mRoutes.values()) { |
- String[] routeIdComponents = ChromeMediaRouter |
- .parseMediaRouteId(route.getRouteId()); |
- assert routeIdComponents != null; |
- if (presentationId.equals(routeIdComponents[0])) { |
- routeToJoin = route; |
+ if (mSession.session.getSessionId().equals(sessionId)) canJoinExistingSession = true; |
+ } else { |
+ for (String routeId : mSession.routeIds) { |
+ MediaRoute route = mRoutes.get(routeId); |
+ if (route != null && route.presentationId.equals(presentationId)) { |
+ canJoinExistingSession = true; |
break; |
} |
} |
} |
mlamouri (slow - plz ping)
2015/11/27 14:23:39
Do you tihnk you can have a method called "canJoin
whywhat
2015/11/27 19:44:39
Done.
|
- if (routeToJoin == null) { |
+ if (!canJoinExistingSession) { |
mManager.onRouteRequestError("No matching route", nativeRequestId); |
return; |
} |
- String mediaRouteId = ChromeMediaRouter.createMediaRouteId( |
- presentationId, routeToJoin.getSinkId(), sourceId); |
- CastRouteController joinedController = routeToJoin.createJoinedController(mediaRouteId, |
- origin, tabId, MediaSource.from(sourceId)); |
- mRoutes.put(mediaRouteId, joinedController); |
+ MediaRoute route = new MediaRoute(mSession.session.getSinkId(), sourceId, presentationId); |
+ mRoutes.put(route.id, route); |
- this.onRouteCreated(nativeRequestId, joinedController, false); |
- |
- if (routeToJoin.isDetached()) mManager.onRouteClosed(routeToJoin.getRouteId()); |
+ this.onRouteCreated(nativeRequestId, route, mSession.session); |
} |
@Override |
public void closeRoute(String routeId) { |
- RouteController route = mRoutes.remove(routeId); |
- if (route == null) return; |
+ MediaRoute route = mRoutes.get(routeId); |
+ |
+ if (route == null) { |
+ onRouteClosed(routeId); |
+ return; |
+ } |
+ |
+ if (mSession == null || !mSession.routeIds.contains(routeId)) { |
+ mRoutes.remove(routeId); |
+ |
+ onRouteClosed(routeId); |
+ return; |
+ } |
- route.close(); |
+ // TODO(avayvod): Implement ReceiverAction.STOP. |
+ |
+ if (mSession.isStopping) return; |
+ |
+ mSession.isStopping = true; |
+ mSession.session.close(); |
} |
@Override |
public void detachRoute(String routeId) { |
- RouteController route = mRoutes.get(routeId); |
- if (route == null) return; |
+ mRoutes.remove(routeId); |
+ if (mSession != null) mSession.routeIds.remove(routeId); |
- route.markDetached(); |
+ for (int i = mClientRecords.size() - 1; i >= 0; --i) { |
mlamouri (slow - plz ping)
2015/11/27 14:23:39
Maybe you can use a reverse iterator?
whywhat
2015/11/27 19:44:39
Is there such a thing in Java? Do you have an exam
|
+ ClientRecord client = mClientRecords.get(i); |
+ if (client.routeId.equals(routeId)) mClientRecords.remove(i); |
+ if (mSession != null) mSession.clientIds.remove(client.clientId); |
+ } |
} |
@Override |
public void sendStringMessage(String routeId, String message, int nativeCallbackId) { |
- RouteController route = mRoutes.get(routeId); |
- if (route == null) { |
+ if (mSession == null || !mSession.routeIds.contains(routeId)) { |
mManager.onMessageSentResult(false, nativeCallbackId); |
return; |
} |
- route.sendStringMessage(message, nativeCallbackId); |
+ mSession.session.sendStringMessage(message, nativeCallbackId); |
} |
@Override |
@@ -317,29 +368,45 @@ public class CastMediaRouteProvider |
mManager = manager; |
} |
@Nullable |
- private CastRouteController autoJoinRoute(MediaSource source, String origin, int tabId) { |
- CastRouteController matchingRoute = null; |
- for (CastRouteController route : mRoutes.values()) { |
- MediaSource routeSource = MediaSource.from(route.getSourceId()); |
- if (routeSource.getApplicationId().equals(source.getApplicationId())) { |
- matchingRoute = route; |
- break; |
- } |
+ private boolean canAutoJoin(MediaSource source, String origin, int tabId) { |
+ MediaSource currentSource = MediaSource.from(mSession.session.getSourceId()); |
+ if (!currentSource.getApplicationId().equals(source.getApplicationId())) return false; |
+ |
+ ClientRecord client = null; |
+ if (!mSession.clientIds.isEmpty()) { |
+ String clientId = mSession.clientIds.iterator().next(); |
+ client = getClientRecordByClientId(clientId); |
+ } else if (mLastRemovedRouteRecord != null) { |
+ client = mLastRemovedRouteRecord; |
+ return origin.equals(client.origin) && tabId == client.tabId; |
} |
- if (matchingRoute == null) return null; |
+ if (client == null) return false; |
- String autoJoinPolicy = source.getAutoJoinPolicy(); |
+ if (source.getAutoJoinPolicy().equals(MediaSource.AUTOJOIN_PAGE_SCOPED)) { |
+ return false; |
+ } else if (source.getAutoJoinPolicy().equals(MediaSource.AUTOJOIN_ORIGIN_SCOPED)) { |
+ return origin.equals(client.origin); |
+ } else if (source.getAutoJoinPolicy().equals(MediaSource.AUTOJOIN_TAB_AND_ORIGIN_SCOPED)) { |
+ return origin.equals(client.origin) && tabId == client.tabId; |
+ } |
- if (MediaSource.AUTOJOIN_ORIGIN_SCOPED.equals(autoJoinPolicy)) { |
- if (!matchingRoute.getOrigin().equals(origin)) return null; |
- } else if (MediaSource.AUTOJOIN_TAB_AND_ORIGIN_SCOPED.equals(autoJoinPolicy)) { |
- if (!matchingRoute.getOrigin().equals(origin) |
- || matchingRoute.getTabId() != tabId) { |
- return null; |
- } |
+ return false; |
+ } |
+ |
+ @Nullable |
+ private ClientRecord getClientRecordByClientId(String clientId) { |
+ for (ClientRecord record : mClientRecords) { |
+ if (record.clientId.equals(clientId)) return record; |
} |
+ return null; |
+ } |
- return matchingRoute; |
+ @Nullable |
+ private ClientRecord getClientRecordByRouteId(String routeId) { |
+ for (ClientRecord record : mClientRecords) { |
+ if (record.routeId.equals(routeId)) return record; |
+ } |
+ return null; |
} |
} |