зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c a=merge
This commit is contained in:
Коммит
499bab536a
|
@ -8,6 +8,7 @@ package org.mozilla.gecko;
|
|||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.lang.Override;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.EnumSet;
|
||||
|
@ -16,6 +17,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Vector;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
@ -651,16 +653,6 @@ public class BrowserApp extends GeckoApp
|
|||
// Set the maximum bits-per-pixel the favicon system cares about.
|
||||
IconDirectoryEntry.setMaxBPP(GeckoAppShell.getScreenDepth());
|
||||
|
||||
Class<?> mediaManagerClass = getMediaPlayerManager();
|
||||
if (mediaManagerClass != null) {
|
||||
try {
|
||||
Method init = mediaManagerClass.getMethod("init", Context.class);
|
||||
init.invoke(null, this);
|
||||
} catch(Exception ex) {
|
||||
Log.e(LOGTAG, "Error initializing media manager", ex);
|
||||
}
|
||||
}
|
||||
|
||||
mTilesRecorder = new TilesRecorder();
|
||||
}
|
||||
|
||||
|
@ -1163,16 +1155,6 @@ public class BrowserApp extends GeckoApp
|
|||
}
|
||||
}
|
||||
|
||||
Class<?> mediaManagerClass = getMediaPlayerManager();
|
||||
if (mediaManagerClass != null) {
|
||||
try {
|
||||
Method destroy = mediaManagerClass.getMethod("onDestroy", (Class[]) null);
|
||||
destroy.invoke(null);
|
||||
} catch(Exception ex) {
|
||||
Log.e(LOGTAG, "Error destroying media manager", ex);
|
||||
}
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
@ -1599,6 +1581,29 @@ public class BrowserApp extends GeckoApp
|
|||
}
|
||||
});
|
||||
|
||||
if (AppConstants.MOZ_MEDIA_PLAYER) {
|
||||
// Check if the fragment is already added. This should never be true here, but this is
|
||||
// a nice safety check.
|
||||
// If casting is disabled, these classes aren't built. We use reflection to initialize them.
|
||||
final Class<?> mediaManagerClass = getMediaPlayerManager();
|
||||
|
||||
if (mediaManagerClass != null) {
|
||||
try {
|
||||
final String tag = "";
|
||||
mediaManagerClass.getDeclaredField("MEDIA_PLAYER_TAG").get(tag);
|
||||
Log.i(LOGTAG, "Found tag " + tag);
|
||||
final Fragment frag = getSupportFragmentManager().findFragmentByTag(tag);
|
||||
if (frag == null) {
|
||||
final Method getInstance = mediaManagerClass.getMethod("newInstance", (Class[]) null);
|
||||
final Fragment mpm = (Fragment) getInstance.invoke(null);
|
||||
getSupportFragmentManager().beginTransaction().disallowAddToBackStack().add(mpm, tag).commit();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.e(LOGTAG, "Error initializing media manager", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED) {
|
||||
// Start (this acts as ping if started already) the stumbler lib; if the stumbler has queued data it will upload it.
|
||||
// Stumbler operates on its own thread, and startup impact is further minimized by delaying work (such as upload) a few seconds.
|
||||
|
@ -1611,6 +1616,7 @@ public class BrowserApp extends GeckoApp
|
|||
}
|
||||
}, oneSecondInMillis);
|
||||
}
|
||||
|
||||
super.handleMessage(event, message);
|
||||
} else if (event.equals("Gecko:Ready")) {
|
||||
// Handle this message in GeckoApp, but also enable the Settings
|
||||
|
|
|
@ -161,7 +161,7 @@ class ChromeCast implements GeckoMediaPlayer {
|
|||
public ChromeCast(Context context, RouteInfo route) {
|
||||
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
|
||||
if (status != ConnectionResult.SUCCESS) {
|
||||
throw new IllegalStateException("Play services are required for Chromecast support (go status code " + status + ")");
|
||||
throw new IllegalStateException("Play services are required for Chromecast support (got status code " + status + ")");
|
||||
}
|
||||
|
||||
this.context = context;
|
||||
|
|
|
@ -1914,7 +1914,7 @@ public abstract class GeckoApp
|
|||
}
|
||||
|
||||
if (mAppStateListeners != null) {
|
||||
for (GeckoAppShell.AppStateListener listener: mAppStateListeners) {
|
||||
for (GeckoAppShell.AppStateListener listener : mAppStateListeners) {
|
||||
listener.onResume();
|
||||
}
|
||||
}
|
||||
|
@ -1946,7 +1946,7 @@ public abstract class GeckoApp
|
|||
Log.w(LOGTAG, "Can't record session: rec is null.");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1996,7 +1996,7 @@ public abstract class GeckoApp
|
|||
});
|
||||
|
||||
if (mAppStateListeners != null) {
|
||||
for(GeckoAppShell.AppStateListener listener: mAppStateListeners) {
|
||||
for (GeckoAppShell.AppStateListener listener : mAppStateListeners) {
|
||||
listener.onPause();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1175,7 +1175,7 @@ public class GeckoAppShell
|
|||
}
|
||||
|
||||
final Uri uri = normalizeUriScheme(targetURI.indexOf(':') >= 0 ? Uri.parse(targetURI) : new Uri.Builder().scheme(targetURI).build());
|
||||
if (mimeType.length() > 0) {
|
||||
if (!TextUtils.isEmpty(mimeType)) {
|
||||
Intent intent = getIntentForActionString(action);
|
||||
intent.setDataAndType(uri, mimeType);
|
||||
return intent;
|
||||
|
@ -1191,8 +1191,10 @@ public class GeckoAppShell
|
|||
// custom handlers that would apply.
|
||||
// Start with the original URI. If we end up modifying it, we'll
|
||||
// overwrite it.
|
||||
final String extension = MimeTypeMap.getFileExtensionFromUrl(targetURI);
|
||||
final String mimeType2 = getMimeTypeFromExtension(extension);
|
||||
final Intent intent = getIntentForActionString(action);
|
||||
intent.setData(uri);
|
||||
intent.setDataAndType(uri, mimeType2);
|
||||
|
||||
if ("vnd.youtube".equals(scheme) &&
|
||||
!hasHandlersForIntent(intent) &&
|
||||
|
|
|
@ -5,35 +5,44 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.mozglue.JNITarget;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.media.MediaControlIntent;
|
||||
import android.support.v7.media.MediaRouteSelector;
|
||||
import android.support.v7.media.MediaRouter;
|
||||
import android.support.v7.media.MediaRouter.RouteInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.cast.CastMediaControlIntent;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.mozglue.JNITarget;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/* Manages a list of GeckoMediaPlayers methods (i.e. Chromecast/Miracast). Routes messages
|
||||
* from Gecko to the correct caster based on the id of the display
|
||||
*/
|
||||
class MediaPlayerManager implements NativeEventListener,
|
||||
GeckoAppShell.AppStateListener {
|
||||
public class MediaPlayerManager extends Fragment implements NativeEventListener {
|
||||
/**
|
||||
* Create a new instance of DetailsFragment, initialized to
|
||||
* show the text at 'index'.
|
||||
*/
|
||||
@JNITarget
|
||||
public static MediaPlayerManager newInstance() {
|
||||
return new MediaPlayerManager();
|
||||
}
|
||||
|
||||
private static final String LOGTAG = "GeckoMediaPlayerManager";
|
||||
|
||||
@JNITarget
|
||||
public static final String MEDIA_PLAYER_TAG = "MPManagerFragment";
|
||||
|
||||
private static final boolean SHOW_DEBUG = false;
|
||||
// Simplified debugging interfaces
|
||||
private static void debug(String msg, Exception e) {
|
||||
|
@ -48,62 +57,36 @@ class MediaPlayerManager implements NativeEventListener,
|
|||
}
|
||||
}
|
||||
|
||||
private final Context context;
|
||||
private final MediaRouter mediaRouter;
|
||||
private MediaRouter mediaRouter = null;
|
||||
private final Map<String, GeckoMediaPlayer> displays = new HashMap<String, GeckoMediaPlayer>();
|
||||
private static MediaPlayerManager instance;
|
||||
|
||||
@JNITarget
|
||||
public static void init(Context context) {
|
||||
if (instance != null) {
|
||||
debug("MediaPlayerManager initialized twice");
|
||||
return;
|
||||
}
|
||||
|
||||
instance = new MediaPlayerManager(context);
|
||||
}
|
||||
|
||||
private MediaPlayerManager(Context context) {
|
||||
this.context = context;
|
||||
|
||||
if (context instanceof GeckoApp) {
|
||||
GeckoApp app = (GeckoApp) context;
|
||||
app.addAppStateListener(this);
|
||||
}
|
||||
|
||||
mediaRouter = MediaRouter.getInstance(context);
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
"MediaPlayer:Load",
|
||||
"MediaPlayer:Start",
|
||||
"MediaPlayer:Stop",
|
||||
"MediaPlayer:Play",
|
||||
"MediaPlayer:Pause",
|
||||
"MediaPlayer:Get",
|
||||
"MediaPlayer:End",
|
||||
"MediaPlayer:Mirror",
|
||||
"MediaPlayer:Message");
|
||||
"MediaPlayer:Load",
|
||||
"MediaPlayer:Start",
|
||||
"MediaPlayer:Stop",
|
||||
"MediaPlayer:Play",
|
||||
"MediaPlayer:Pause",
|
||||
"MediaPlayer:End",
|
||||
"MediaPlayer:Mirror",
|
||||
"MediaPlayer:Message");
|
||||
}
|
||||
|
||||
@Override
|
||||
@JNITarget
|
||||
public static void onDestroy() {
|
||||
if (instance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(instance,
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
|
||||
"MediaPlayer:Load",
|
||||
"MediaPlayer:Start",
|
||||
"MediaPlayer:Stop",
|
||||
"MediaPlayer:Play",
|
||||
"MediaPlayer:Pause",
|
||||
"MediaPlayer:Get",
|
||||
"MediaPlayer:End",
|
||||
"MediaPlayer:Mirror",
|
||||
"MediaPlayer:Message");
|
||||
if (instance.context instanceof GeckoApp) {
|
||||
GeckoApp app = (GeckoApp) instance.context;
|
||||
app.removeAppStateListener(instance);
|
||||
}
|
||||
}
|
||||
|
||||
// GeckoEventListener implementation
|
||||
|
@ -111,37 +94,6 @@ class MediaPlayerManager implements NativeEventListener,
|
|||
public void handleMessage(String event, final NativeJSObject message, final EventCallback callback) {
|
||||
debug(event);
|
||||
|
||||
if ("MediaPlayer:Get".equals(event)) {
|
||||
final JSONObject result = new JSONObject();
|
||||
final JSONArray disps = new JSONArray();
|
||||
|
||||
final Iterator<GeckoMediaPlayer> items = displays.values().iterator();
|
||||
while (items.hasNext()) {
|
||||
GeckoMediaPlayer disp = items.next();
|
||||
try {
|
||||
JSONObject json = disp.toJSON();
|
||||
if (json == null) {
|
||||
items.remove();
|
||||
} else {
|
||||
disps.put(json);
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
// This may happen if the device isn't a real Chromecast,
|
||||
// for example Matchstick casting devices.
|
||||
Log.e(LOGTAG, "Couldn't create JSON for display", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
result.put("displays", disps);
|
||||
} catch(JSONException ex) {
|
||||
Log.i(LOGTAG, "Error sending displays", ex);
|
||||
}
|
||||
|
||||
callback.sendSuccess(result);
|
||||
return;
|
||||
}
|
||||
|
||||
final GeckoMediaPlayer display = displays.get(message.getString("id"));
|
||||
if (display == null) {
|
||||
Log.e(LOGTAG, "Couldn't find a display for this id: " + message.getString("id") + " for message: " + event);
|
||||
|
@ -179,6 +131,8 @@ class MediaPlayerManager implements NativeEventListener,
|
|||
public void onRouteRemoved(MediaRouter router, RouteInfo route) {
|
||||
debug("onRouteRemoved: route=" + route);
|
||||
displays.remove(route.getId());
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(
|
||||
"MediaPlayer:Removed", route.getId()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
@ -201,18 +155,22 @@ class MediaPlayerManager implements NativeEventListener,
|
|||
@Override
|
||||
public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) {
|
||||
debug("onRouteAdded: route=" + route);
|
||||
GeckoMediaPlayer display = getMediaPlayerForRoute(route);
|
||||
final GeckoMediaPlayer display = getMediaPlayerForRoute(route);
|
||||
if (display != null) {
|
||||
displays.put(route.getId(), display);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(
|
||||
"MediaPlayer:Added", display.toJSON().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
|
||||
debug("onRouteChanged: route=" + route);
|
||||
GeckoMediaPlayer display = displays.get(route.getId());
|
||||
final GeckoMediaPlayer display = displays.get(route.getId());
|
||||
if (display != null) {
|
||||
displays.put(route.getId(), display);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(
|
||||
"MediaPlayer:Changed", display.toJSON().toString()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -220,7 +178,7 @@ class MediaPlayerManager implements NativeEventListener,
|
|||
private GeckoMediaPlayer getMediaPlayerForRoute(MediaRouter.RouteInfo route) {
|
||||
try {
|
||||
if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
|
||||
return new ChromeCast(context, route);
|
||||
return new ChromeCast(getActivity(), route);
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
debug("Error handling presentation", ex);
|
||||
|
@ -229,23 +187,28 @@ class MediaPlayerManager implements NativeEventListener,
|
|||
return null;
|
||||
}
|
||||
|
||||
/* Implementing GeckoAppShell.AppStateListener */
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mediaRouter.removeCallback(callback);
|
||||
mediaRouter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
MediaRouteSelector selectorBuilder = new MediaRouteSelector.Builder()
|
||||
super.onResume();
|
||||
|
||||
// The mediaRouter shouldn't exist here, but this is a nice safety check.
|
||||
if (mediaRouter != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mediaRouter = MediaRouter.getInstance(getActivity());
|
||||
final MediaRouteSelector selectorBuilder = new MediaRouteSelector.Builder()
|
||||
.addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
|
||||
.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
|
||||
.addControlCategory(CastMediaControlIntent.categoryForCast(ChromeCast.MIRROR_RECEIVER_APP_ID))
|
||||
.build();
|
||||
mediaRouter.addCallback(selectorBuilder, callback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOrientationChanged() { }
|
||||
|
||||
}
|
||||
|
|
|
@ -43,7 +43,35 @@ var mediaPlayerDevice = {
|
|||
return new MediaPlayerApp(aService);
|
||||
},
|
||||
types: ["video/mp4", "video/webm", "application/x-mpegurl"],
|
||||
extensions: ["mp4", "webm", "m3u", "m3u8"]
|
||||
extensions: ["mp4", "webm", "m3u", "m3u8"],
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, "MediaPlayer:Added", false);
|
||||
Services.obs.addObserver(this, "MediaPlayer:Changed", false);
|
||||
Services.obs.addObserver(this, "MediaPlayer:Removed", false);
|
||||
},
|
||||
observe: function(subject, topic, data) {
|
||||
if (topic === "MediaPlayer:Added") {
|
||||
let service = this.toService(JSON.parse(data));
|
||||
SimpleServiceDiscovery.addService(service);
|
||||
} else if (topic === "MediaPlayer:Changed") {
|
||||
let service = this.toService(JSON.parse(data));
|
||||
SimpleServiceDiscovery.updateService(service);
|
||||
} else if (topic === "MediaPlayer:Removed") {
|
||||
SimpleServiceDiscovery.removeService(data);
|
||||
}
|
||||
},
|
||||
toService: function(display) {
|
||||
// Convert the native data into something matching what is created in _processService()
|
||||
return {
|
||||
location: display.location,
|
||||
target: "media:router",
|
||||
friendlyName: display.friendlyName,
|
||||
uuid: display.uuid,
|
||||
manufacturer: display.manufacturer,
|
||||
modelName: display.modelName,
|
||||
mirror: display.mirror
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var CastingApps = {
|
||||
|
@ -59,6 +87,9 @@ var CastingApps = {
|
|||
// Register targets
|
||||
SimpleServiceDiscovery.registerDevice(rokuDevice);
|
||||
SimpleServiceDiscovery.registerDevice(matchstickDevice);
|
||||
|
||||
// MediaPlayerDevice will notify us any time the native device list changes.
|
||||
mediaPlayerDevice.init();
|
||||
SimpleServiceDiscovery.registerDevice(mediaPlayerDevice);
|
||||
|
||||
// Search for devices continuously every 120 seconds
|
||||
|
|
|
@ -339,6 +339,7 @@ var BrowserApp = {
|
|||
Services.tm.mainThread.dispatch(function() {
|
||||
// Init LoginManager
|
||||
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
CastingApps.init();
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
|
@ -440,7 +441,6 @@ var BrowserApp = {
|
|||
RemoteDebugger.init();
|
||||
UserAgentOverrides.init();
|
||||
DesktopUserAgent.init();
|
||||
CastingApps.init();
|
||||
Distribution.init();
|
||||
Tabs.init();
|
||||
#ifdef ACCESSIBILITY
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-@ANDROID_TARGET_SDK@
|
||||
target=android-L
|
||||
@IDE_PROJECT_LIBRARY_SETTING@
|
||||
@IDE_PROJECT_LIBRARY_REFERENCES@
|
||||
|
|
|
@ -285,7 +285,8 @@ BrowserTabList.prototype._getBrowsers = function*() {
|
|||
};
|
||||
|
||||
BrowserTabList.prototype._getChildren = function(aWindow) {
|
||||
return aWindow.gBrowser ? aWindow.gBrowser.browsers : [];
|
||||
let children = aWindow.gBrowser ? aWindow.gBrowser.browsers : [];
|
||||
return children ? children : [];
|
||||
};
|
||||
|
||||
BrowserTabList.prototype._isRemoteBrowser = function(browser) {
|
||||
|
|
|
@ -43,6 +43,7 @@ EXTRA_JS_MODULES += [
|
|||
'RemoteSecurityUI.jsm',
|
||||
'RemoteWebNavigation.jsm',
|
||||
'RemoteWebProgress.jsm',
|
||||
'secondscreen/SimpleServiceDiscovery.jsm',
|
||||
'SelectContentHelper.jsm',
|
||||
'SelectParentHelper.jsm',
|
||||
'sessionstore/FormData.jsm',
|
||||
|
@ -63,7 +64,6 @@ EXTRA_PP_JS_MODULES += [
|
|||
'CertUtils.jsm',
|
||||
'ResetProfile.jsm',
|
||||
'secondscreen/RokuApp.jsm',
|
||||
'secondscreen/SimpleServiceDiscovery.jsm',
|
||||
'Services.jsm',
|
||||
'Troubleshoot.jsm',
|
||||
'UpdateChannel.jsm',
|
||||
|
|
|
@ -12,17 +12,8 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
#ifdef ANDROID
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
#endif
|
||||
|
||||
// Define the "log" function as a binding of the Log.d function so it specifies
|
||||
// the "debug" priority and a log tag.
|
||||
#ifdef ANDROID
|
||||
let log = Cu.import("resource://gre/modules/AndroidLog.jsm",{}).AndroidLog.d.bind(null, "SSDP");
|
||||
#else
|
||||
let log = Cu.reportError;
|
||||
#endif
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "converter", function () {
|
||||
let conv = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
|
@ -188,36 +179,8 @@ var SimpleServiceDiscovery = {
|
|||
timeout += SSDP_TRANSMISSION_INTERVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
// We also query Java directly here for any devices that Android might support natively (i.e. Chromecast or Miracast)
|
||||
this.getAndroidDevices();
|
||||
#endif
|
||||
},
|
||||
|
||||
#ifdef ANDROID
|
||||
getAndroidDevices: function() {
|
||||
Messaging.sendRequestForResult({ type: "MediaPlayer:Get" }).then((result) => {
|
||||
for (let id in result.displays) {
|
||||
let display = result.displays[id];
|
||||
|
||||
// Convert the native data into something matching what is created in _processService()
|
||||
let service = {
|
||||
location: display.location,
|
||||
target: "media:router",
|
||||
friendlyName: display.friendlyName,
|
||||
uuid: display.uuid,
|
||||
manufacturer: display.manufacturer,
|
||||
modelName: display.modelName,
|
||||
mirror: display.mirror
|
||||
};
|
||||
|
||||
this._addService(service);
|
||||
}
|
||||
});
|
||||
},
|
||||
#endif
|
||||
|
||||
_searchFixedDevices: function _searchFixedDevices() {
|
||||
let fixedDevices = null;
|
||||
try {
|
||||
|
@ -259,8 +222,7 @@ var SimpleServiceDiscovery = {
|
|||
// Clean out any stale services
|
||||
for (let [key, service] of this._services) {
|
||||
if (service.lastPing != this._searchTimestamp) {
|
||||
Services.obs.notifyObservers(null, EVENT_SERVICE_LOST, service.uuid);
|
||||
this._services.delete(service.uuid);
|
||||
this.removeService(service.uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -399,29 +361,52 @@ var SimpleServiceDiscovery = {
|
|||
aService.manufacturer = doc.querySelector("manufacturer").textContent;
|
||||
aService.modelName = doc.querySelector("modelName").textContent;
|
||||
|
||||
this._addService(aService);
|
||||
this.addService(aService);
|
||||
}
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.send(null);
|
||||
},
|
||||
|
||||
// Add a service to the WeakMap, even if one already exists with this id.
|
||||
// Returns true if this succeeded or false if it failed
|
||||
_addService: function(service) {
|
||||
// Filter out services that do not match the device filter
|
||||
if (!this._filterService(service)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
let device = this._devices.get(service.target);
|
||||
if (device && device.mirror) {
|
||||
service.mirror = true;
|
||||
}
|
||||
this._services.set(service.uuid, service);
|
||||
return true;
|
||||
},
|
||||
|
||||
addService: function(service) {
|
||||
// Only add and notify if we don't already know about this service
|
||||
if (!this._services.has(service.uuid)) {
|
||||
let device = this._devices.get(service.target);
|
||||
if (device && device.mirror) {
|
||||
service.mirror = true;
|
||||
if (!this._addService(service)) {
|
||||
return;
|
||||
}
|
||||
this._services.set(service.uuid, service);
|
||||
Services.obs.notifyObservers(null, EVENT_SERVICE_FOUND, service.uuid);
|
||||
}
|
||||
|
||||
// Make sure we remember this service is not stale
|
||||
this._services.get(service.uuid).lastPing = this._searchTimestamp;
|
||||
},
|
||||
|
||||
removeService: function(uuid) {
|
||||
Services.obs.notifyObservers(null, EVENT_SERVICE_LOST, uuid);
|
||||
this._services.delete(uuid);
|
||||
},
|
||||
|
||||
updateService: function(service) {
|
||||
if (!this._addService(service)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we remember this service is not stale
|
||||
this._services.get(service.uuid).lastPing = this._searchTimestamp;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче