Backout aa955afe7507:49f1c6fa27f8 (bug 953381) for robocop orange on this CLOSED TREE
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 953381 requires a clobber due to bug 961339.
|
||||
Bug 917896 requires a clobber due to bug 961339.
|
||||
|
|
|
@ -274,9 +274,6 @@ pref("browser.search.noCurrentEngine", true);
|
|||
pref("browser.search.official", true);
|
||||
#endif
|
||||
|
||||
// Control media casting feature
|
||||
pref("browser.casting.enabled", false);
|
||||
|
||||
// Enable sparse localization by setting a few package locale overrides
|
||||
pref("chrome.override_package.global", "browser");
|
||||
pref("chrome.override_package.mozapps", "browser");
|
||||
|
|
|
@ -156,7 +156,6 @@ abstract public class BrowserApp extends GeckoApp
|
|||
};
|
||||
|
||||
private FindInPageBar mFindInPageBar;
|
||||
private MediaCastingBar mMediaCastingBar;
|
||||
|
||||
private boolean mAccessibilityEnabled = false;
|
||||
|
||||
|
@ -531,7 +530,6 @@ abstract public class BrowserApp extends GeckoApp
|
|||
}
|
||||
|
||||
mFindInPageBar = (FindInPageBar) findViewById(R.id.find_in_page);
|
||||
mMediaCastingBar = (MediaCastingBar) findViewById(R.id.media_casting);
|
||||
|
||||
registerEventListener("CharEncoding:Data");
|
||||
registerEventListener("CharEncoding:State");
|
||||
|
@ -832,11 +830,6 @@ abstract public class BrowserApp extends GeckoApp
|
|||
mFindInPageBar = null;
|
||||
}
|
||||
|
||||
if (mMediaCastingBar != null) {
|
||||
mMediaCastingBar.onDestroy();
|
||||
mMediaCastingBar = null;
|
||||
}
|
||||
|
||||
if (mSharedPreferencesHelper != null) {
|
||||
mSharedPreferencesHelper.uninit();
|
||||
mSharedPreferencesHelper = null;
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
/* 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.util.GeckoEventListener;
|
||||
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 {
|
||||
private static final String LOGTAG = "MediaCastingBar";
|
||||
|
||||
private TextView mCastingTo;
|
||||
private ImageButton mMediaPlay;
|
||||
private ImageButton mMediaPause;
|
||||
private ImageButton mMediaStop;
|
||||
|
||||
private boolean mInflated = false;
|
||||
|
||||
public MediaCastingBar(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
GeckoAppShell.getEventDispatcher().registerEventListener("Casting:Started", this);
|
||||
GeckoAppShell.getEventDispatcher().registerEventListener("Casting:Stopped", this);
|
||||
}
|
||||
|
||||
public void inflateContent() {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
View content = inflater.inflate(R.layout.media_casting, this);
|
||||
|
||||
mMediaPlay = (ImageButton) content.findViewById(R.id.media_play);
|
||||
mMediaPlay.setOnClickListener(this);
|
||||
mMediaPause = (ImageButton) content.findViewById(R.id.media_pause);
|
||||
mMediaPause.setOnClickListener(this);
|
||||
mMediaStop = (ImageButton) content.findViewById(R.id.media_stop);
|
||||
mMediaStop.setOnClickListener(this);
|
||||
|
||||
mCastingTo = (TextView) content.findViewById(R.id.media_casting_to);
|
||||
|
||||
// Capture clicks on the rest of the view to prevent them from
|
||||
// leaking into other views positioned below.
|
||||
content.setOnClickListener(this);
|
||||
|
||||
mInflated = true;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (!mInflated)
|
||||
inflateContent();
|
||||
|
||||
setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
setVisibility(GONE);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
GeckoAppShell.getEventDispatcher().unregisterEventListener("Casting:Started", this);
|
||||
GeckoAppShell.getEventDispatcher().unregisterEventListener("Casting:Stopped", this);
|
||||
}
|
||||
|
||||
// View.OnClickListener implementation
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final int viewId = v.getId();
|
||||
|
||||
if (viewId == R.id.media_play) {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Casting:Play", ""));
|
||||
mMediaPlay.setVisibility(GONE);
|
||||
mMediaPause.setVisibility(VISIBLE);
|
||||
} else if (viewId == R.id.media_pause) {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Casting:Pause", ""));
|
||||
mMediaPause.setVisibility(GONE);
|
||||
mMediaPlay.setVisibility(VISIBLE);
|
||||
} else if (viewId == R.id.media_stop) {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Casting:Stop", ""));
|
||||
}
|
||||
}
|
||||
|
||||
// GeckoEventListener implementation
|
||||
@Override
|
||||
public void handleMessage(final String event, final JSONObject message) {
|
||||
final String device = message.optString("device");
|
||||
|
||||
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:Stopped")) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -219,13 +219,6 @@ size. -->
|
|||
<!ENTITY find_next "Next">
|
||||
<!ENTITY find_close "Close">
|
||||
|
||||
<!-- Localization note (media_casting_to, media_play, media_pause, media_stop) : These strings are used
|
||||
as alternate text for accessibility. They are not visible in the UI. -->
|
||||
<!ENTITY media_casting_to "Casting to Device">
|
||||
<!ENTITY media_play "Play">
|
||||
<!ENTITY media_pause "Pause">
|
||||
<!ENTITY media_stop "Stop">
|
||||
|
||||
<!ENTITY contextmenu_open_new_tab "Open in New Tab">
|
||||
<!ENTITY contextmenu_open_private_tab "Open in Private Tab">
|
||||
<!ENTITY contextmenu_open_in_reader "Open in Reader">
|
||||
|
|
|
@ -248,7 +248,6 @@ gbjar.sources += [
|
|||
'LightweightTheme.java',
|
||||
'LightweightThemeDrawable.java',
|
||||
'LocaleManager.java',
|
||||
'MediaCastingBar.java',
|
||||
'MemoryMonitor.java',
|
||||
'menu/GeckoMenu.java',
|
||||
'menu/GeckoMenuInflater.java',
|
||||
|
|
Двоичные данные
mobile/android/base/resources/drawable-hdpi/media_bar_pause.png
До Ширина: | Высота: | Размер: 362 B |
Двоичные данные
mobile/android/base/resources/drawable-hdpi/media_bar_play.png
До Ширина: | Высота: | Размер: 670 B |
Двоичные данные
mobile/android/base/resources/drawable-hdpi/media_bar_stop.png
До Ширина: | Высота: | Размер: 763 B |
Двоичные данные
mobile/android/base/resources/drawable-mdpi/media_bar_pause.png
До Ширина: | Высота: | Размер: 252 B |
Двоичные данные
mobile/android/base/resources/drawable-mdpi/media_bar_play.png
До Ширина: | Высота: | Размер: 463 B |
Двоичные данные
mobile/android/base/resources/drawable-mdpi/media_bar_stop.png
До Ширина: | Высота: | Размер: 497 B |
Двоичные данные
mobile/android/base/resources/drawable-xhdpi/media_bar_pause.png
До Ширина: | Высота: | Размер: 389 B |
Двоичные данные
mobile/android/base/resources/drawable-xhdpi/media_bar_play.png
До Ширина: | Высота: | Размер: 853 B |
Двоичные данные
mobile/android/base/resources/drawable-xhdpi/media_bar_stop.png
До Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -48,13 +48,6 @@
|
|||
style="@style/FindBar"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<org.mozilla.gecko.MediaCastingBar android:id="@+id/media_casting"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
style="@style/FindBar"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<RelativeLayout android:id="@+id/camera_layout"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<RelativeLayout android:id="@+id/media_controls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true">
|
||||
|
||||
<ImageButton android:id="@+id/media_play"
|
||||
style="@style/FindBar.ImageButton"
|
||||
android:contentDescription="@string/media_play"
|
||||
android:src="@drawable/media_bar_play"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageButton android:id="@+id/media_pause"
|
||||
style="@style/FindBar.ImageButton"
|
||||
android:contentDescription="@string/media_pause"
|
||||
android:src="@drawable/media_bar_pause"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView android:id="@+id/media_casting_to"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginRight="5dip"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_toLeftOf="@id/media_controls"
|
||||
android:layout_centerVertical="true"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:textColor="#FFFFFFFF"
|
||||
android:contentDescription="@string/media_casting_to"/>
|
||||
|
||||
<ImageButton android:id="@+id/media_stop"
|
||||
style="@style/FindBar.ImageButton"
|
||||
android:contentDescription="@string/media_stop"
|
||||
android:layout_alignParentRight="true"
|
||||
android:src="@drawable/media_bar_stop"/>
|
||||
|
||||
</merge>
|
|
@ -83,11 +83,6 @@
|
|||
<string name="find_next">&find_next;</string>
|
||||
<string name="find_close">&find_close;</string>
|
||||
|
||||
<string name="media_casting_to">&media_casting_to;</string>
|
||||
<string name="media_play">&media_play;</string>
|
||||
<string name="media_pause">&media_pause;</string>
|
||||
<string name="media_stop">&media_stop;</string>
|
||||
|
||||
<string name="settings">&settings;</string>
|
||||
<string name="settings_title">&settings_title;</string>
|
||||
<string name="pref_category_advanced">&pref_category_advanced;</string>
|
||||
|
|
|
@ -79,7 +79,6 @@ skip-if = processor == "x86"
|
|||
[testSharedPreferences]
|
||||
[testSimpleDiscovery]
|
||||
[testUITelemetry]
|
||||
[testVideoDiscovery]
|
||||
|
||||
# Used for Talos, please don't use in mochitest
|
||||
#[testPan]
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
|
||||
public class testVideoDiscovery extends JavascriptTest {
|
||||
public testVideoDiscovery() {
|
||||
super("testVideoDiscovery.js");
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function ok(passed, text) {
|
||||
do_report_result(passed, text, Components.stack.caller, false);
|
||||
}
|
||||
|
||||
// The chrome window
|
||||
let chromeWin;
|
||||
|
||||
// Track the <browser> where the tests are happening
|
||||
let browser;
|
||||
|
||||
function middle(element) {
|
||||
let rect = element.getBoundingClientRect();
|
||||
let x = (rect.right - rect.left) / 2 + rect.left;
|
||||
let y = (rect.bottom - rect.top) / 2 + rect.top;
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
add_test(function setup_browser() {
|
||||
chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let BrowserApp = chromeWin.BrowserApp;
|
||||
|
||||
do_register_cleanup(function cleanup() {
|
||||
BrowserApp.closeTab(BrowserApp.getTabForBrowser(browser));
|
||||
});
|
||||
|
||||
let url = "http://mochi.test:8888/tests/robocop/video_discovery.html";
|
||||
browser = BrowserApp.addTab(url, { selected: true, parentId: BrowserApp.selectedTab.id }).browser;
|
||||
browser.addEventListener("load", function startTests(event) {
|
||||
browser.removeEventListener("load", startTests, true);
|
||||
Services.tm.mainThread.dispatch(run_next_test, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}, true);
|
||||
});
|
||||
|
||||
let videoDiscoveryTests = [
|
||||
{ id: "simple-mp4", source: "http://mochi.test:8888/simple.mp4", poster: "http://mochi.test:8888/simple.png", text: "simple video with mp4 src" },
|
||||
{ id: "simple-fail", pass: false, text: "simple video with no mp4 src" },
|
||||
{ id: "with-sources-mp4", source: "http://mochi.test:8888/simple.mp4", text: "video with mp4 extension source child" },
|
||||
{ id: "with-sources-fail", pass: false, text: "video with no mp4 extension source child" },
|
||||
{ id: "with-sources-mimetype", source: "http://mochi.test:8888/simple-video-mp4", text: "video with mp4 mimetype source child" },
|
||||
{ id: "video-overlay", source: "http://mochi.test:8888/simple.mp4", text: "div overlay covering a simple video with mp4 src" }
|
||||
];
|
||||
|
||||
function execute_video_test(test) {
|
||||
let element = browser.contentDocument.getElementById(test.id);
|
||||
if (element) {
|
||||
let [x, y] = middle(element);
|
||||
let video = chromeWin.CastApps.getVideo(element, x, y);
|
||||
if (video) {
|
||||
let matchPoster = (test.poster == video.poster);
|
||||
let matchSource = (test.source == video.source);
|
||||
ok(matchPoster && matchSource && test.pass, test.text);
|
||||
} else {
|
||||
ok(!test.pass, test.text);
|
||||
}
|
||||
} else {
|
||||
ok(false, "test element not found: [" + test.id + "]");
|
||||
}
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
let videoTest;
|
||||
while ((videoTest = videoDiscoveryTests.shift())) {
|
||||
if (!("poster" in videoTest)) {
|
||||
videoTest.poster = "";
|
||||
}
|
||||
if (!("pass" in videoTest)) {
|
||||
videoTest.pass = true;
|
||||
}
|
||||
|
||||
add_test(execute_video_test.bind(this, videoTest));
|
||||
}
|
||||
|
||||
run_next_test();
|
|
@ -1,60 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Video Discovery Test</title>
|
||||
<style type="text/css">
|
||||
#video-box {
|
||||
float: left;
|
||||
}
|
||||
#video-overlay, #video-player {
|
||||
width: 640px;
|
||||
min-height: 370px;
|
||||
}
|
||||
#video-overlay {
|
||||
position: absolute;
|
||||
float: left;
|
||||
background-color:#f00;
|
||||
z-index:10;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- PASS: src uses a mp4 extension -->
|
||||
<video id="simple-mp4" poster="/simple.png" src="/simple.mp4"></video>
|
||||
|
||||
<!-- FAIL: src uses a ogg extension -->
|
||||
<video id="simple-fail" src="/simple.ogg"></video>
|
||||
|
||||
<!-- PASS: source list uses a mp4 extension -->
|
||||
<video id="with-sources-mp4">
|
||||
<source src="/simple.ogg">
|
||||
<source src="/simple.mp4">
|
||||
</video>
|
||||
|
||||
<!-- FAIL: source list uses a mp4 extension -->
|
||||
<video id="with-sources-fail">
|
||||
<source src="/simple.ogg">
|
||||
<source src="/simple.webm">
|
||||
</video>
|
||||
|
||||
<!-- PASS: source list uses a mp4 mimetype -->
|
||||
<video id="with-sources-mimetype">
|
||||
<source src="/simple-video-ogg" type="video/ogg">
|
||||
<source src="/simple-video-mp4" type="video/mp4">
|
||||
</video>
|
||||
|
||||
<!-- PASS: source list uses a mp4 mimetype and extra data -->
|
||||
<video id="with-sources-mimetype-plus">
|
||||
<source src="/simple-video-ogg" type="video/ogg">
|
||||
<source src="/simple-video-mp4" type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'">
|
||||
</video>
|
||||
|
||||
<!-- PASS: div overlay covers a video with mp4 src -->
|
||||
<div id="video-box">
|
||||
<div id="video-overlay"></div>
|
||||
<div>
|
||||
<video id="video-player" src="/simple.mp4"></video>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,243 +0,0 @@
|
|||
/* 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/. */
|
||||
"use strict";
|
||||
|
||||
var CastingApps = {
|
||||
_castMenuId: -1,
|
||||
|
||||
init: function ca_init() {
|
||||
if (!this.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Search for devices continuously every 120 seconds
|
||||
SimpleServiceDiscovery.search(120 * 1000);
|
||||
|
||||
this._castMenuId = NativeWindow.contextmenus.add(
|
||||
Strings.browser.GetStringFromName("contextmenu.castToScreen"),
|
||||
this.filterCast,
|
||||
this.openExternal.bind(this)
|
||||
);
|
||||
|
||||
Services.obs.addObserver(this, "Casting:Play", false);
|
||||
Services.obs.addObserver(this, "Casting:Pause", false);
|
||||
Services.obs.addObserver(this, "Casting:Stop", false);
|
||||
},
|
||||
|
||||
uninit: function ca_uninit() {
|
||||
Services.obs.removeObserver(this, "Casting:Play");
|
||||
Services.obs.removeObserver(this, "Casting:Pause");
|
||||
Services.obs.removeObserver(this, "Casting:Stop");
|
||||
|
||||
NativeWindow.contextmenus.remove(this._castMenuId);
|
||||
},
|
||||
|
||||
isEnabled: function isEnabled() {
|
||||
return Services.prefs.getBoolPref("browser.casting.enabled");
|
||||
},
|
||||
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
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();
|
||||
}
|
||||
break;
|
||||
case "Casting:Stop":
|
||||
if (this.session) {
|
||||
this.closeExternal();
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
makeURI: function makeURI(aURL, aOriginCharset, aBaseURI) {
|
||||
return Services.io.newURI(aURL, aOriginCharset, aBaseURI);
|
||||
},
|
||||
|
||||
getVideo: function(aElement, aX, aY) {
|
||||
// Fast path: Is the given element a video element
|
||||
let video = this._getVideo(aElement);
|
||||
if (video) {
|
||||
return video;
|
||||
}
|
||||
|
||||
// The context menu system will keep walking up the DOM giving us a chance
|
||||
// to find an element we match. When it hits <html> things can go BOOM.
|
||||
try {
|
||||
// Maybe this is an overlay, with the video element under it
|
||||
// Use the (x, y) location to guess at a <video> element
|
||||
let elements = aElement.ownerDocument.querySelectorAll("video");
|
||||
for (let element of elements) {
|
||||
// Look for a video element contained in the overlay bounds
|
||||
let rect = element.getBoundingClientRect();
|
||||
if (aY >= rect.top && aX >= rect.left && aY <= rect.bottom && aX <= rect.right) {
|
||||
video = this._getVideo(element);
|
||||
if (video) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
// Could be null
|
||||
return video;
|
||||
},
|
||||
|
||||
_getVideo: function(aElement) {
|
||||
// Given the hardware support for H264, let's only look for 'mp4' sources
|
||||
if (!aElement instanceof HTMLVideoElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function allowableExtension(aURI) {
|
||||
if (aURI && aURI instanceof Ci.nsIURL) {
|
||||
return (aURI.fileExtension == "mp4");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the poster attribute from the <video>
|
||||
let posterURL = aElement.poster;
|
||||
|
||||
// First, look to see if the <video> has a src attribute
|
||||
let sourceURL = aElement.src;
|
||||
|
||||
// If empty, try the currentSrc
|
||||
if (!sourceURL) {
|
||||
sourceURL = aElement.currentSrc;
|
||||
}
|
||||
|
||||
if (sourceURL) {
|
||||
// Use the file extension to guess the mime type
|
||||
let sourceURI = this.makeURI(sourceURL, null, this.makeURI(aElement.baseURI));
|
||||
if (allowableExtension(sourceURI)) {
|
||||
return { video: aElement, source: sourceURI.spec, poster: posterURL };
|
||||
}
|
||||
}
|
||||
|
||||
// Next, look to see if there is a <source> child element that meets
|
||||
// our needs
|
||||
let sourceNodes = aElement.getElementsByTagName("source");
|
||||
for (let sourceNode of sourceNodes) {
|
||||
let sourceURI = this.makeURI(sourceNode.src, null, this.makeURI(sourceNode.baseURI));
|
||||
|
||||
// Using the type attribute is our ideal way to guess the mime type. Otherwise,
|
||||
// fallback to using the file extension to guess the mime type
|
||||
if (sourceNode.type == "video/mp4" || allowableExtension(sourceURI)) {
|
||||
return { video: aElement, source: sourceURI.spec, poster: posterURL };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
filterCast: {
|
||||
matches: function(aElement, aX, aY) {
|
||||
if (SimpleServiceDiscovery.services.length == 0)
|
||||
return false;
|
||||
let video = CastingApps.getVideo(aElement, aX, aY);
|
||||
if (CastingApps.session) {
|
||||
return (video && CastingApps.session.data.source != video.source);
|
||||
}
|
||||
return (video != null);
|
||||
}
|
||||
},
|
||||
|
||||
prompt: function(aCallback) {
|
||||
let items = [];
|
||||
SimpleServiceDiscovery.services.forEach(function(aService) {
|
||||
let item = {
|
||||
label: aService.friendlyName,
|
||||
selected: false
|
||||
};
|
||||
items.push(item);
|
||||
});
|
||||
|
||||
let prompt = new Prompt({
|
||||
title: Strings.browser.GetStringFromName("casting.prompt")
|
||||
}).setSingleChoiceItems(items).show(function(data) {
|
||||
let selected = data.button;
|
||||
let service = selected == -1 ? null : SimpleServiceDiscovery.services[selected];
|
||||
if (aCallback)
|
||||
aCallback(service);
|
||||
});
|
||||
},
|
||||
|
||||
openExternal: function(aElement, aX, aY) {
|
||||
// Start a second screen media service
|
||||
let video = this.getVideo(aElement, aX, aY);
|
||||
if (!video) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.prompt(function(aService) {
|
||||
if (!aService)
|
||||
return;
|
||||
|
||||
// Make sure we have a player app for the given service
|
||||
let app = SimpleServiceDiscovery.findAppForService(aService, "video-sharing");
|
||||
if (!app)
|
||||
return;
|
||||
|
||||
video.title = aElement.ownerDocument.defaultView.top.document.title;
|
||||
if (video.element) {
|
||||
// If the video is currently playing on the device, pause it
|
||||
if (!video.element.paused) {
|
||||
video.element.pause();
|
||||
}
|
||||
}
|
||||
|
||||
app.stop(function() {
|
||||
app.start("", function() {
|
||||
app.remoteMedia(function(aRemoteMedia) {
|
||||
this.session = {
|
||||
service: aService,
|
||||
app: app,
|
||||
remoteMedia: aRemoteMedia,
|
||||
data: {
|
||||
title: video.title,
|
||||
source: video.source,
|
||||
poster: video.poster
|
||||
}
|
||||
};
|
||||
}.bind(this), this);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// RemoteMedia callback API methods
|
||||
onRemoteMediaStart: function(aRemoteMedia) {
|
||||
if (!this.session) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRemoteMedia.load(this.session.data);
|
||||
sendMessageToJava({ type: "Casting:Started", device: this.session.service.friendlyName });
|
||||
},
|
||||
|
||||
onRemoteMediaStop: function(aRemoteMedia) {
|
||||
sendMessageToJava({ type: "Casting:Stopped" });
|
||||
},
|
||||
|
||||
onRemoteMediaStatus: function(aRemoteMedia) {
|
||||
if (!this.session) {
|
||||
return;
|
||||
}
|
||||
|
||||
let status = aRemoteMedia.status;
|
||||
if (status == "completed") {
|
||||
aRemoteMedia.shutdown();
|
||||
this.session.app.stop();
|
||||
delete this.session;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -63,9 +63,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
|||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SimpleServiceDiscovery",
|
||||
"resource://gre/modules/SimpleServiceDiscovery.jsm");
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ShumwayUtils",
|
||||
"resource://shumway/ShumwayUtils.jsm");
|
||||
|
@ -85,7 +82,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "WebappManager",
|
|||
["PluginHelper", "chrome://browser/content/PluginHelper.js"],
|
||||
["OfflineApps", "chrome://browser/content/OfflineApps.js"],
|
||||
["Linkifier", "chrome://browser/content/Linkify.js"],
|
||||
["CastingApps", "chrome://browser/content/CastingApps.js"],
|
||||
].forEach(function (aScript) {
|
||||
let [name, script] = aScript;
|
||||
XPCOMUtils.defineLazyGetter(window, name, function() {
|
||||
|
@ -390,7 +386,6 @@ var BrowserApp = {
|
|||
Reader.init();
|
||||
UserAgentOverrides.init();
|
||||
DesktopUserAgent.init();
|
||||
CastingApps.init();
|
||||
Distribution.init();
|
||||
Tabs.init();
|
||||
#ifdef ACCESSIBILITY
|
||||
|
@ -732,7 +727,6 @@ var BrowserApp = {
|
|||
UserAgentOverrides.uninit();
|
||||
DesktopUserAgent.uninit();
|
||||
ExternalApps.uninit();
|
||||
CastingApps.uninit();
|
||||
Distribution.uninit();
|
||||
Tabs.uninit();
|
||||
},
|
||||
|
|
|
@ -53,7 +53,6 @@ chrome.jar:
|
|||
content/FeedHandler.js (content/FeedHandler.js)
|
||||
content/Feedback.js (content/Feedback.js)
|
||||
content/Linkify.js (content/Linkify.js)
|
||||
content/CastingApps.js (content/CastingApps.js)
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
content/aboutHealthReport.xhtml (content/aboutHealthReport.xhtml)
|
||||
* content/aboutHealthReport.js (content/aboutHealthReport.js)
|
||||
|
|
|
@ -159,9 +159,6 @@ intl.charsetmenu.browser.static=iso-8859-1,utf-8,big5,iso-2022-jp,shift_jis,euc-
|
|||
# Text Selection
|
||||
selectionHelper.textCopied=Text copied to clipboard
|
||||
|
||||
# Casting
|
||||
casting.prompt=Cast to Device
|
||||
|
||||
# Context menu
|
||||
contextmenu.openInNewTab=Open Link in New Tab
|
||||
contextmenu.openInPrivateTab=Open Link in Private Tab
|
||||
|
@ -194,7 +191,6 @@ contextmenu.unmute=Unmute
|
|||
contextmenu.saveVideo=Save Video
|
||||
contextmenu.saveAudio=Save Audio
|
||||
contextmenu.addToContacts=Add to Contacts
|
||||
contextmenu.castToScreen=Cast to Screen
|
||||
|
||||
contextmenu.copy=Copy
|
||||
contextmenu.cut=Cut
|
||||
|
|