author | Jim Chen <nchen@mozilla.com> |
Wed, 25 Jan 2017 18:53:57 -0500 | |
changeset 331056 | 2740c0e269054538fe69c6ed5b6afe82d9407370 |
parent 331055 | 6057588e27441ec4ce22e05b5a9f7eee7774995b |
child 331057 | 65b07eac83b329667ae01b036e7e5f5b067c31c4 |
push id | 86160 |
push user | nchen@mozilla.com |
push date | Wed, 25 Jan 2017 23:54:26 +0000 |
treeherder | mozilla-inbound@3c1089284c75 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sebastian |
bugs | 1330409 |
milestone | 54.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/mobile/android/base/java/org/mozilla/gecko/ChromeCastPlayer.java +++ b/mobile/android/base/java/org/mozilla/gecko/ChromeCastPlayer.java @@ -3,16 +3,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko; import java.io.IOException; import org.mozilla.gecko.util.EventCallback; +import org.mozilla.gecko.util.GeckoBundle; import org.json.JSONObject; import org.json.JSONException; import com.google.android.gms.cast.Cast.MessageReceivedCallback; import com.google.android.gms.cast.ApplicationMetadata; import com.google.android.gms.cast.Cast; import com.google.android.gms.cast.Cast.ApplicationConnectionResult; import com.google.android.gms.cast.CastDevice; @@ -84,25 +85,25 @@ class ChromeCastPlayer implements GeckoM } @Override public void onStatusUpdated() { MediaStatus mediaStatus = remoteMediaPlayer.getMediaStatus(); switch (mediaStatus.getPlayerState()) { case MediaStatus.PLAYER_STATE_PLAYING: - GeckoAppShell.notifyObservers("MediaPlayer:Playing", null); + EventDispatcher.getInstance().dispatch("MediaPlayer:Playing", null); break; case MediaStatus.PLAYER_STATE_PAUSED: - GeckoAppShell.notifyObservers("MediaPlayer:Paused", null); + EventDispatcher.getInstance().dispatch("MediaPlayer:Paused", null); break; case MediaStatus.PLAYER_STATE_IDLE: // TODO: Do we want to shutdown when there are errors? if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_FINISHED) { - GeckoAppShell.notifyObservers("Casting:Stop", null); + EventDispatcher.getInstance().dispatch("Casting:Stop", null); } break; default: // TODO: Do we need to handle other status such as buffering / unknown? break; } } @@ -383,17 +384,19 @@ class ChromeCastPlayer implements GeckoM } /* * Receive message from the receiver app */ @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { - GeckoAppShell.notifyObservers("MediaPlayer:Response", message); + final GeckoBundle data = new GeckoBundle(1); + data.putString("message", message); + EventDispatcher.getInstance().dispatch("MediaPlayer:Response", data); } public void sendMessage(String message) { if (apiClient != null && mMirrorChannel != null) { try { Cast.CastApi.sendMessage(apiClient, mMirrorChannel.getNamespace(), message) .setResultCallback( new ResultCallback<Status>() { @@ -432,17 +435,19 @@ class ChromeCastPlayer implements GeckoM mMirrorChannel .getNamespace(), mMirrorChannel); sendSuccess(callback, null); } catch (IOException e) { Log.e(LOGTAG, "Exception while creating channel", e); } - GeckoAppShell.notifyObservers("Casting:Mirror", route.getId()); + final GeckoBundle message = new GeckoBundle(1); + message.putString("id", route.getId()); + EventDispatcher.getInstance().dispatch("Casting:Mirror", message); } else { sendError(callback, status.toString()); } } } @Override public void message(String msg, final EventCallback callback) {
--- a/mobile/android/base/java/org/mozilla/gecko/MediaCastingBar.java +++ b/mobile/android/base/java/org/mozilla/gecko/MediaCastingBar.java @@ -1,44 +1,44 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko; import org.mozilla.gecko.GeckoApp; -import org.mozilla.gecko.util.GeckoEventListener; +import org.mozilla.gecko.util.BundleEventListener; +import org.mozilla.gecko.util.EventCallback; +import org.mozilla.gecko.util.GeckoBundle; import org.mozilla.gecko.util.ThreadUtils; -import org.json.JSONObject; - import android.content.Context; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageButton; import android.widget.RelativeLayout; import android.widget.TextView; -public class MediaCastingBar extends RelativeLayout implements View.OnClickListener, GeckoEventListener { +public class MediaCastingBar extends RelativeLayout implements View.OnClickListener, BundleEventListener { private static final String LOGTAG = "GeckoMediaCastingBar"; private TextView mCastingTo; private ImageButton mMediaPlay; private ImageButton mMediaPause; private ImageButton mMediaStop; private boolean mInflated; public MediaCastingBar(Context context, AttributeSet attrs) { super(context, attrs); - EventDispatcher.getInstance().registerGeckoThreadListener(this, + EventDispatcher.getInstance().registerUiThreadListener(this, "Casting:Started", "Casting:Paused", "Casting:Playing", "Casting:Stopped"); } public void inflateContent() { LayoutInflater inflater = LayoutInflater.from(getContext()); @@ -67,65 +67,55 @@ public class MediaCastingBar extends Rel setVisibility(VISIBLE); } public void hide() { setVisibility(GONE); } public void onDestroy() { - EventDispatcher.getInstance().unregisterGeckoThreadListener(this, + EventDispatcher.getInstance().unregisterUiThreadListener(this, "Casting:Started", "Casting:Paused", "Casting:Playing", "Casting:Stopped"); } // View.OnClickListener implementation @Override public void onClick(View v) { final int viewId = v.getId(); if (viewId == R.id.media_play) { - GeckoAppShell.notifyObservers("Casting:Play", ""); + EventDispatcher.getInstance().dispatch("Casting:Play", null); mMediaPlay.setVisibility(GONE); mMediaPause.setVisibility(VISIBLE); } else if (viewId == R.id.media_pause) { - GeckoAppShell.notifyObservers("Casting:Pause", ""); + EventDispatcher.getInstance().dispatch("Casting:Pause", null); mMediaPause.setVisibility(GONE); mMediaPlay.setVisibility(VISIBLE); } else if (viewId == R.id.media_stop) { - GeckoAppShell.notifyObservers("Casting:Stop", ""); + EventDispatcher.getInstance().dispatch("Casting:Stop", null); } } - // GeckoEventListener implementation - @Override - public void handleMessage(final String event, final JSONObject message) { - final String device = message.optString("device"); + @Override // BundleEventListener + public void handleMessage(final String event, final GeckoBundle message, + final EventCallback callback) { + if ("Casting:Started".equals(event)) { + show(); + mCastingTo.setText(message.getString("device", "")); + mMediaPlay.setVisibility(GONE); + mMediaPause.setVisibility(VISIBLE); - ThreadUtils.postToUiThread(new Runnable() { - @Override - public void run() { - if (event.equals("Casting:Started")) { - show(); - if (!TextUtils.isEmpty(device)) { - mCastingTo.setText(device); - } else { - // Should not happen - mCastingTo.setText(""); - Log.d(LOGTAG, "Device name is empty."); - } - mMediaPlay.setVisibility(GONE); - mMediaPause.setVisibility(VISIBLE); - } else if (event.equals("Casting:Paused")) { - mMediaPause.setVisibility(GONE); - mMediaPlay.setVisibility(VISIBLE); - } else if (event.equals("Casting:Playing")) { - mMediaPlay.setVisibility(GONE); - mMediaPause.setVisibility(VISIBLE); - } else if (event.equals("Casting:Stopped")) { - hide(); - } - } - }); + } else if ("Casting:Paused".equals(event)) { + mMediaPause.setVisibility(GONE); + mMediaPlay.setVisibility(VISIBLE); + + } else if ("Casting:Playing".equals(event)) { + mMediaPlay.setVisibility(GONE); + mMediaPause.setVisibility(VISIBLE); + + } else if ("Casting:Stopped".equals(event)) { + hide(); + } } }
--- a/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java +++ b/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java @@ -1,32 +1,25 @@ /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- * vim: ts=4 sw=4 expandtab: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko; -import org.json.JSONObject; -import org.json.JSONException; - -import org.json.JSONObject; import org.mozilla.gecko.AppConstants.Versions; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.PresentationView; import org.mozilla.gecko.R; import org.mozilla.gecko.ScreenManagerHelper; import org.mozilla.gecko.annotation.JNITarget; import org.mozilla.gecko.annotation.ReflectionTarget; import org.mozilla.gecko.annotation.WrapForJNI; import org.mozilla.gecko.gfx.LayerView; -import org.mozilla.gecko.util.EventCallback; -import org.mozilla.gecko.util.NativeEventListener; -import org.mozilla.gecko.util.NativeJSObject; import com.google.android.gms.cast.CastMediaControlIntent; import com.google.android.gms.cast.CastPresentation; import com.google.android.gms.cast.CastRemoteDisplayLocalService; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import android.app.Activity;
--- a/mobile/android/chrome/content/CastingApps.js +++ b/mobile/android/chrome/content/CastingApps.js @@ -83,20 +83,23 @@ var CastingApps = { SimpleServiceDiscovery.search(this._interval); this._castMenuId = NativeWindow.contextmenus.add( Strings.browser.GetStringFromName("contextmenu.sendToDevice"), this.filterCast, this.handleContextMenu.bind(this) ); - Services.obs.addObserver(this, "Casting:Play", false); - Services.obs.addObserver(this, "Casting:Pause", false); - Services.obs.addObserver(this, "Casting:Stop", false); - Services.obs.addObserver(this, "Casting:Mirror", false); + GlobalEventDispatcher.registerListener(this, [ + "Casting:Play", + "Casting:Pause", + "Casting:Stop", + "Casting:Mirror", + ]); + Services.obs.addObserver(this, "ssdp-service-found", false); Services.obs.addObserver(this, "ssdp-service-lost", false); Services.obs.addObserver(this, "application-background", false); Services.obs.addObserver(this, "application-foreground", false); BrowserApp.deck.addEventListener("TabSelect", this, true); BrowserApp.deck.addEventListener("pageshow", this, true); BrowserApp.deck.addEventListener("playing", this, true); @@ -167,18 +170,18 @@ var CastingApps = { isCastingEnabled: function isCastingEnabled() { return Services.prefs.getBoolPref("browser.casting.enabled"); }, isMirroringEnabled: function isMirroringEnabled() { return Services.prefs.getBoolPref("browser.mirroring.enabled"); }, - observe: function (aSubject, aTopic, aData) { - switch (aTopic) { + onEvent: function (event, message, callback) { + switch (event) { case "Casting:Play": if (this.session && this.session.remoteMedia.status == "paused") { this.session.remoteMedia.play(); } break; case "Casting:Pause": if (this.session && this.session.remoteMedia.status == "started") { this.session.remoteMedia.pause(); @@ -187,21 +190,26 @@ var CastingApps = { case "Casting:Stop": if (this.session) { this.closeExternal(); } break; case "Casting:Mirror": { Cu.import("resource://gre/modules/TabMirror.jsm"); - this.tabMirror = new TabMirror(aData, window); + this.tabMirror = new TabMirror(message.id, window); NativeWindow.menu.update(this.mirrorStartMenuId, { visible: false }); NativeWindow.menu.update(this.mirrorStopMenuId, { visible: true }); } break; + } + }, + + observe: function (aSubject, aTopic, aData) { + switch (aTopic) { case "ssdp-service-found": this.serviceAdded(SimpleServiceDiscovery.findServiceForID(aData)); break; case "ssdp-service-lost": this.serviceLost(SimpleServiceDiscovery.findServiceForID(aData)); break; case "application-background": // Turn off polling while in the background @@ -746,41 +754,44 @@ var CastingApps = { // RemoteMedia callback API methods onRemoteMediaStart: function(aRemoteMedia) { if (!this.session) { return; } aRemoteMedia.load(this.session.data); - Messaging.sendRequest({ type: "Casting:Started", device: this.session.service.friendlyName }); + GlobalEventDispatcher.sendRequest({ + type: "Casting:Started", + device: this.session.service.friendlyName, + }); let video = this.session.videoRef.get(); if (video) { this._sendEventToVideo(video, { active: true }); this._updatePageAction(video); } }, onRemoteMediaStop: function(aRemoteMedia) { - Messaging.sendRequest({ type: "Casting:Stopped" }); + GlobalEventDispatcher.sendRequest({ type: "Casting:Stopped" }); this._shutdown(); }, onRemoteMediaStatus: function(aRemoteMedia) { if (!this.session) { return; } let status = aRemoteMedia.status; switch (status) { case "started": - Messaging.sendRequest({ type: "Casting:Playing" }); + GlobalEventDispatcher.sendRequest({ type: "Casting:Playing" }); break; case "paused": - Messaging.sendRequest({ type: "Casting:Paused" }); + GlobalEventDispatcher.sendRequest({ type: "Casting:Paused" }); break; case "completed": this.closeExternal(); break; } } };
--- a/mobile/android/modules/MediaPlayerApp.jsm +++ b/mobile/android/modules/MediaPlayerApp.jsm @@ -78,18 +78,20 @@ function RemoteMedia(id, listener) { Services.tm.mainThread.dispatch((function() { this._listener.onRemoteMediaStart(this); }).bind(this), Ci.nsIThread.DISPATCH_NORMAL); } } RemoteMedia.prototype = { shutdown: function shutdown() { - Services.obs.removeObserver(this, "MediaPlayer:Playing"); - Services.obs.removeObserver(this, "MediaPlayer:Paused"); + EventDispatcher.instance.unregisterListener(this, [ + "MediaPlayer:Playing", + "MediaPlayer:Paused", + ]); this._send("MediaPlayer:End", {}, (result, err) => { this._status = "shutdown"; if ("onRemoteMediaStop" in this._listener) { this._listener.onRemoteMediaStop(this); } }); }, @@ -121,46 +123,46 @@ RemoteMedia.prototype = { load: function load(aData) { this._send("MediaPlayer:Load", aData, (result, err) => { if (err) { Cu.reportError("Can't load " + err); this.shutdown(); return; } - Services.obs.addObserver(this, "MediaPlayer:Playing", false); - Services.obs.addObserver(this, "MediaPlayer:Paused", false); + EventDispatcher.instance.registerListener(this, [ + "MediaPlayer:Playing", + "MediaPlayer:Paused", + ]); this._status = "started"; }) }, get status() { return this._status; }, - observe: function (aSubject, aTopic, aData) { - switch (aTopic) { + onEvent: function (event, message, callback) { + switch (event) { case "MediaPlayer:Playing": if (this._status !== "started") { this._status = "started"; if ("onRemoteMediaStatus" in this._listener) { this._listener.onRemoteMediaStatus(this); } } break; case "MediaPlayer:Paused": if (this._status !== "paused") { this._status = "paused"; if ("onRemoteMediaStatus" in this._listener) { this._listener.onRemoteMediaStatus(this); } } break; - default: - break; } }, _send: function(msg, data, callback) { data.id = this._id; send(msg, data, callback); } }
--- a/mobile/android/modules/TabMirror.jsm +++ b/mobile/android/modules/TabMirror.jsm @@ -18,17 +18,19 @@ var failure = function(x) { var TabMirror = function(deviceId, window) { this.deviceId = deviceId; // Save RTCSessionDescription and RTCIceCandidate for later when the window object is not available. this.RTCSessionDescription = window.RTCSessionDescription; this.RTCIceCandidate = window.RTCIceCandidate; - Services.obs.addObserver((aSubject, aTopic, aData) => this._processMessage(aData), "MediaPlayer:Response", false); + EventDispatcher.instance.registerListener( + (event, data, callback) => this._processMessage(data.message), "MediaPlayer:Response"); + this._sendMessage({ start: true }); this._window = window; this._pc = new window.RTCPeerConnection(CONFIG, {}); if (!this._pc) { throw "Failure creating Webrtc object"; } }; @@ -53,23 +55,17 @@ TabMirror.prototype = { { aspectRatio: this._screenSize.width / this._screenSize.height } ] } }; this._window.navigator.mozGetUserMedia(constraints, this._onGumSuccess.bind(this), this._onGumFailure.bind(this)); }, - _processMessage: function(data) { - if (!data) { - return; - } - - let msg = JSON.parse(data); - + _processMessage: function(msg) { if (!msg) { return; } if (msg.sdp && msg.type === "answer") { this._processAnswer(msg); } else if (msg.type == "size") { if (msg.height) { @@ -139,15 +135,15 @@ TabMirror.prototype = { }, stop: function() { if (this.deviceId) { let obj = { type: "MediaPlayer:End", id: this.deviceId }; - Services.androidBridge.handleGeckoMessage(obj); + EventDispatcher.instance.sendRequest(obj); } }, }; this.EXPORTED_SYMBOLS = ["TabMirror"];
--- a/widget/android/nsIAndroidBridge.idl +++ b/widget/android/nsIAndroidBridge.idl @@ -34,17 +34,17 @@ interface nsIAndroidBrowserApp : nsISupp [scriptable, uuid(e64c39b8-b8ec-477d-aef5-89d517ff9219)] interface nsIAndroidEventCallback : nsISupports { void onSuccess([optional] in jsval data); void onError([optional] in jsval data); }; -[scriptable, uuid(73569a75-78eb-4c7f-82b9-2d4f5ccf44c3)] +[scriptable, function, uuid(73569a75-78eb-4c7f-82b9-2d4f5ccf44c3)] interface nsIAndroidEventListener : nsISupports { void onEvent(in AString event, [optional] in jsval data, [optional] in nsIAndroidEventCallback callback); }; [scriptable, uuid(e98bf792-4145-411e-b298-8219d9b03817)]