--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2226,17 +2226,16 @@ GK_ATOM(scrollbar_start_forward, "scroll
GK_ATOM(scrollbar_end_backward, "scrollbar-end-backward")
GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward")
GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional")
GK_ATOM(images_in_menus, "images-in-menus")
GK_ATOM(images_in_buttons, "images-in-buttons")
GK_ATOM(overlay_scrollbars, "overlay-scrollbars")
GK_ATOM(windows_default_theme, "windows-default-theme")
GK_ATOM(mac_graphite_theme, "mac-graphite-theme")
-GK_ATOM(mac_lion_theme, "mac-lion-theme")
GK_ATOM(mac_yosemite_theme, "mac-yosemite-theme")
GK_ATOM(windows_compositor, "windows-compositor")
GK_ATOM(windows_glass, "windows-glass")
GK_ATOM(touch_enabled, "touch-enabled")
GK_ATOM(menubar_drag, "menubar-drag")
GK_ATOM(swipe_animation_enabled, "swipe-animation-enabled")
GK_ATOM(physical_home_button, "physical-home-button")
@@ -2258,17 +2257,16 @@ GK_ATOM(_moz_scrollbar_start_forward, "-
GK_ATOM(_moz_scrollbar_end_backward, "-moz-scrollbar-end-backward")
GK_ATOM(_moz_scrollbar_end_forward, "-moz-scrollbar-end-forward")
GK_ATOM(_moz_scrollbar_thumb_proportional, "-moz-scrollbar-thumb-proportional")
GK_ATOM(_moz_images_in_menus, "-moz-images-in-menus")
GK_ATOM(_moz_images_in_buttons, "-moz-images-in-buttons")
GK_ATOM(_moz_overlay_scrollbars, "-moz-overlay-scrollbars")
GK_ATOM(_moz_windows_default_theme, "-moz-windows-default-theme")
GK_ATOM(_moz_mac_graphite_theme, "-moz-mac-graphite-theme")
-GK_ATOM(_moz_mac_lion_theme, "-moz-mac-lion-theme")
GK_ATOM(_moz_mac_yosemite_theme, "-moz-mac-yosemite-theme")
GK_ATOM(_moz_windows_compositor, "-moz-windows-compositor")
GK_ATOM(_moz_windows_classic, "-moz-windows-classic")
GK_ATOM(_moz_windows_glass, "-moz-windows-glass")
GK_ATOM(_moz_windows_theme, "-moz-windows-theme")
GK_ATOM(_moz_os_version, "-moz-os-version")
GK_ATOM(_moz_touch_enabled, "-moz-touch-enabled")
GK_ATOM(_moz_menubar_drag, "-moz-menubar-drag")
--- a/dom/media/AudioStream.h
+++ b/dom/media/AudioStream.h
@@ -216,17 +216,16 @@ public:
int64_t GetPosition();
// Return the position, measured in audio frames played since the stream
// was opened, of the audio hardware. Thread-safe.
int64_t GetPositionInFrames();
static uint32_t GetPreferredRate()
{
- CubebUtils::InitPreferredSampleRate();
return CubebUtils::PreferredSampleRate();
}
uint32_t GetOutChannels() { return mOutChannels; }
// Set playback rate as a multiple of the intrinsic playback rate. This is to
// be called only with aPlaybackRate > 0.0.
nsresult SetPlaybackRate(double aPlaybackRate);
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -25,17 +25,16 @@ namespace mozilla {
namespace {
// This mutex protects the variables below.
StaticMutex sMutex;
enum class CubebState {
Uninitialized = 0,
Initialized,
- Error,
Shutdown
} sCubebState = CubebState::Uninitialized;
cubeb* sCubebContext;
double sVolumeScale;
uint32_t sCubebLatency;
bool sCubebLatencyPrefSet;
bool sAudioStreamInitEverSucceeded = false;
StaticAutoPtr<char> sBrandName;
@@ -124,29 +123,42 @@ double GetVolumeScale()
}
cubeb* GetCubebContext()
{
StaticMutexAutoLock lock(sMutex);
return GetCubebContextUnlocked();
}
-void InitPreferredSampleRate()
+bool InitPreferredSampleRate()
{
StaticMutexAutoLock lock(sMutex);
- if (sPreferredSampleRate == 0) {
- cubeb* context = GetCubebContextUnlocked();
- if (context) {
- if (cubeb_get_preferred_sample_rate(context,
- &sPreferredSampleRate) != CUBEB_OK) {
- // Query failed, use a sensible default.
- sPreferredSampleRate = 44100;
- }
- }
+ if (sPreferredSampleRate != 0) {
+ return true;
+ }
+ cubeb* context = GetCubebContextUnlocked();
+ if (!context) {
+ return false;
+ }
+ if (cubeb_get_preferred_sample_rate(context,
+ &sPreferredSampleRate) != CUBEB_OK) {
+
+ return false;
}
+ MOZ_ASSERT(sPreferredSampleRate);
+ return true;
+}
+
+uint32_t PreferredSampleRate()
+{
+ if (!InitPreferredSampleRate()) {
+ return 44100;
+ }
+ MOZ_ASSERT(sPreferredSampleRate);
+ return sPreferredSampleRate;
}
void InitBrandName()
{
if (sBrandName) {
return;
}
nsXPIDLString brandName;
@@ -183,17 +195,17 @@ cubeb* GetCubebContextUnlocked()
InitBrandName();
} else {
NS_WARNING_ASSERTION(
sBrandName, "Did not initialize sbrandName, and not on the main thread?");
}
int rv = cubeb_init(&sCubebContext, sBrandName);
NS_WARNING_ASSERTION(rv == CUBEB_OK, "Could not get a cubeb context.");
- sCubebState = (rv == CUBEB_OK) ? CubebState::Initialized : CubebState::Error;
+ sCubebState = (rv == CUBEB_OK) ? CubebState::Initialized : CubebState::Uninitialized;
return sCubebContext;
}
void ReportCubebBackendUsed()
{
StaticMutexAutoLock lock(sMutex);
@@ -272,23 +284,16 @@ uint32_t MaxNumberOfChannels()
cubeb_get_max_channel_count(cubebContext,
&maxNumberOfChannels) == CUBEB_OK) {
return maxNumberOfChannels;
}
return 0;
}
-uint32_t PreferredSampleRate()
-{
- MOZ_ASSERT(sPreferredSampleRate,
- "sPreferredSampleRate has not been initialized!");
- return sPreferredSampleRate;
-}
-
#if defined(__ANDROID__) && defined(MOZ_B2G)
cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel)
{
switch(aChannel) {
case dom::AudioChannel::Normal:
/* FALLTHROUGH */
case dom::AudioChannel::Content:
return CUBEB_STREAM_TYPE_MUSIC;
--- a/dom/media/CubebUtils.h
+++ b/dom/media/CubebUtils.h
@@ -21,22 +21,17 @@ void InitLibrary();
// Shutdown Audio Library. Some Audio backends require shutting down the
// library after using it.
void ShutdownLibrary();
// Returns the maximum number of channels supported by the audio hardware.
uint32_t MaxNumberOfChannels();
-// Queries the samplerate the hardware/mixer runs at, and stores it.
-// Can be called on any thread. When this returns, it is safe to call
-// PreferredSampleRate.
-void InitPreferredSampleRate();
-
-// Get the aforementioned sample rate. Thread safe.
+// Get the sample rate the hardware/mixer runs at. Thread safe.
uint32_t PreferredSampleRate();
void PrefChanged(const char* aPref, void* aClosure);
double GetVolumeScale();
bool GetFirstStream();
cubeb* GetCubebContext();
cubeb* GetCubebContextUnlocked();
void ReportCubebStreamInitFailure(bool aIsFirstStream);
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -3403,18 +3403,16 @@ MediaStreamGraph::GetInstance(MediaStrea
nsCOMPtr<nsIAsyncShutdownClient> barrier = MediaStreamGraphImpl::GetShutdownBarrier();
nsresult rv = barrier->
AddBlocker(gMediaStreamGraphShutdownBlocker,
NS_LITERAL_STRING(__FILE__), __LINE__,
NS_LITERAL_STRING("MediaStreamGraph shutdown"));
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
}
- CubebUtils::InitPreferredSampleRate();
-
graph = new MediaStreamGraphImpl(aGraphDriverRequested,
CubebUtils::PreferredSampleRate(),
aChannel);
gGraphs.Put(channel, graph);
STREAM_LOG(LogLevel::Debug,
("Starting up MediaStreamGraph %p for channel %s",
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -85,17 +85,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
static float GetSampleRateForAudioContext(bool aIsOffline, float aSampleRate)
{
if (aIsOffline) {
return aSampleRate;
} else {
- CubebUtils::InitPreferredSampleRate();
return static_cast<float>(CubebUtils::PreferredSampleRate());
}
}
AudioContext::AudioContext(nsPIDOMWindowInner* aWindow,
bool aIsOffline,
AudioChannel aChannel,
uint32_t aNumberOfChannels,
--- a/dom/presentation/PresentationConnection.cpp
+++ b/dom/presentation/PresentationConnection.cpp
@@ -4,16 +4,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/. */
#include "PresentationConnection.h"
#include "ControllerConnectionCollection.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/dom/DOMException.h"
+#include "mozilla/dom/File.h"
#include "mozilla/dom/MessageEvent.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/PresentationConnectionClosedEvent.h"
#include "mozilla/ErrorNames.h"
#include "mozilla/DebugOnly.h"
#include "nsContentUtils.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIPresentationService.h"
@@ -49,16 +50,17 @@ PresentationConnection::PresentationConn
const nsAString& aUrl,
const uint8_t aRole,
PresentationConnectionList* aList)
: DOMEventTargetHelper(aWindow)
, mId(aId)
, mUrl(aUrl)
, mState(PresentationConnectionState::Connecting)
, mOwningConnectionList(aList)
+ , mBinaryType(PresentationConnectionBinaryType::Arraybuffer)
{
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
aRole == nsIPresentationService::ROLE_RECEIVER);
mRole = aRole;
}
/* virtual */ PresentationConnection::~PresentationConnection()
{
@@ -164,36 +166,142 @@ PresentationConnection::GetUrl(nsAString
}
PresentationConnectionState
PresentationConnection::State() const
{
return mState;
}
+PresentationConnectionBinaryType
+PresentationConnection::BinaryType() const
+{
+ return mBinaryType;
+}
+
+void
+PresentationConnection::SetBinaryType(PresentationConnectionBinaryType aType)
+{
+ mBinaryType = aType;
+}
+
void
PresentationConnection::Send(const nsAString& aData,
ErrorResult& aRv)
{
// Sending is not allowed if the session is not connected.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if(NS_WARN_IF(!service)) {
- aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
+ AsyncCloseConnectionWithErrorMsg(
+ NS_LITERAL_STRING("Unable to send message due to an internal error."));
return;
}
nsresult rv = service->SendSessionMessage(mId, mRole, aData);
if(NS_WARN_IF(NS_FAILED(rv))) {
- aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
+ const uint32_t kMaxMessageLength = 256;
+ nsAutoString data(Substring(aData, 0, kMaxMessageLength));
+
+ AsyncCloseConnectionWithErrorMsg(
+ NS_LITERAL_STRING("Unable to send message: \"") + data +
+ NS_LITERAL_STRING("\""));
+ }
+}
+
+void
+PresentationConnection::Send(Blob& aData,
+ ErrorResult& aRv)
+{
+ if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
+
+ nsCOMPtr<nsIPresentationService> service =
+ do_GetService(PRESENTATION_SERVICE_CONTRACTID);
+ if(NS_WARN_IF(!service)) {
+ AsyncCloseConnectionWithErrorMsg(
+ NS_LITERAL_STRING("Unable to send message due to an internal error."));
+ return;
+ }
+
+ nsresult rv = service->SendSessionBlob(mId, mRole, &aData);
+ if(NS_WARN_IF(NS_FAILED(rv))) {
+ AsyncCloseConnectionWithErrorMsg(
+ NS_LITERAL_STRING("Unable to send binary message for Blob message."));
+ }
+}
+
+void
+PresentationConnection::Send(const ArrayBuffer& aData,
+ ErrorResult& aRv)
+{
+ if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
+
+ nsCOMPtr<nsIPresentationService> service =
+ do_GetService(PRESENTATION_SERVICE_CONTRACTID);
+ if(NS_WARN_IF(!service)) {
+ AsyncCloseConnectionWithErrorMsg(
+ NS_LITERAL_STRING("Unable to send message due to an internal error."));
+ return;
+ }
+
+ aData.ComputeLengthAndData();
+
+ static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
+
+ uint32_t length = aData.Length();
+ char* data = reinterpret_cast<char*>(aData.Data());
+ nsDependentCSubstring msgString(data, length);
+
+ nsresult rv = service->SendSessionBinaryMsg(mId, mRole, msgString);
+ if(NS_WARN_IF(NS_FAILED(rv))) {
+ AsyncCloseConnectionWithErrorMsg(
+ NS_LITERAL_STRING("Unable to send binary message for ArrayBuffer message."));
+ }
+}
+
+void
+PresentationConnection::Send(const ArrayBufferView& aData,
+ ErrorResult& aRv)
+{
+ if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
+
+ nsCOMPtr<nsIPresentationService> service =
+ do_GetService(PRESENTATION_SERVICE_CONTRACTID);
+ if(NS_WARN_IF(!service)) {
+ AsyncCloseConnectionWithErrorMsg(
+ NS_LITERAL_STRING("Unable to send message due to an internal error."));
+ return;
+ }
+
+ aData.ComputeLengthAndData();
+
+ static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
+
+ uint32_t length = aData.Length();
+ char* data = reinterpret_cast<char*>(aData.Data());
+ nsDependentCSubstring msgString(data, length);
+
+ nsresult rv = service->SendSessionBinaryMsg(mId, mRole, msgString);
+ if(NS_WARN_IF(NS_FAILED(rv))) {
+ AsyncCloseConnectionWithErrorMsg(
+ NS_LITERAL_STRING("Unable to send binary message for ArrayBufferView message."));
}
}
void
PresentationConnection::Close(ErrorResult& aRv)
{
// It only works when the state is CONNECTED or CONNECTING.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected &&
@@ -347,41 +455,75 @@ PresentationConnection::ProcessStateChan
default:
MOZ_CRASH("Unknown presentation session state.");
return NS_ERROR_INVALID_ARG;
}
}
NS_IMETHODIMP
PresentationConnection::NotifyMessage(const nsAString& aSessionId,
- const nsACString& aData)
+ const nsACString& aData,
+ bool aIsBinary)
{
PRES_DEBUG("connection %s:id[%s], data[%s], role[%d]\n", __func__,
NS_ConvertUTF16toUTF8(aSessionId).get(),
nsPromiseFlatCString(aData).get(), mRole);
if (!aSessionId.Equals(mId)) {
return NS_ERROR_INVALID_ARG;
}
// No message should be expected when the session is not connected.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
+ if (NS_WARN_IF(NS_FAILED(DoReceiveMessage(aData, aIsBinary)))) {
+ AsyncCloseConnectionWithErrorMsg(
+ NS_LITERAL_STRING("Unable to receive a message."));
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+PresentationConnection::DoReceiveMessage(const nsACString& aData, bool aIsBinary)
+{
// Transform the data.
AutoJSAPI jsapi;
if (!jsapi.Init(GetOwner())) {
return NS_ERROR_FAILURE;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> jsData(cx);
- NS_ConvertUTF8toUTF16 utf16Data(aData);
- if(NS_WARN_IF(!ToJSValue(cx, utf16Data, &jsData))) {
- return NS_ERROR_FAILURE;
+
+ nsresult rv;
+ if (aIsBinary) {
+ if (mBinaryType == PresentationConnectionBinaryType::Blob) {
+ rv = nsContentUtils::CreateBlobBuffer(cx, GetOwner(), aData, &jsData);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ } else if (mBinaryType == PresentationConnectionBinaryType::Arraybuffer) {
+ JS::Rooted<JSObject*> arrayBuf(cx);
+ rv = nsContentUtils::CreateArrayBuffer(cx, aData, arrayBuf.address());
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ jsData.setObject(*arrayBuf);
+ } else {
+ NS_RUNTIMEABORT("Unknown binary type!");
+ return NS_ERROR_UNEXPECTED;
+ }
+ } else {
+ NS_ConvertUTF8toUTF16 utf16Data(aData);
+ if(NS_WARN_IF(!ToJSValue(cx, utf16Data, &jsData))) {
+ return NS_ERROR_FAILURE;
+ }
}
return DispatchMessageEvent(jsData);
}
NS_IMETHODIMP
PresentationConnection::NotifyReplaced()
{
@@ -391,33 +533,39 @@ PresentationConnection::NotifyReplaced()
return NotifyStateChange(mId,
nsIPresentationSessionListener::STATE_CLOSED,
NS_OK);
}
nsresult
PresentationConnection::DispatchConnectionClosedEvent(
PresentationConnectionClosedReason aReason,
- const nsAString& aMessage)
+ const nsAString& aMessage,
+ bool aDispatchNow)
{
if (mState != PresentationConnectionState::Closed) {
MOZ_ASSERT(false, "The connection state should be closed.");
return NS_ERROR_FAILURE;
}
PresentationConnectionClosedEventInit init;
init.mReason = aReason;
init.mMessage = aMessage;
RefPtr<PresentationConnectionClosedEvent> closedEvent =
PresentationConnectionClosedEvent::Constructor(this,
NS_LITERAL_STRING("close"),
init);
closedEvent->SetTrusted(true);
+ if (aDispatchNow) {
+ bool ignore;
+ return DOMEventTargetHelper::DispatchEvent(closedEvent, &ignore);
+ }
+
RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, static_cast<Event*>(closedEvent));
return asyncDispatcher->PostDOMEvent();
}
nsresult
PresentationConnection::DispatchMessageEvent(JS::Handle<JS::Value> aData)
{
@@ -574,8 +722,44 @@ PresentationConnection::RemoveFromLoadGr
nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakLoadGroup);
if (loadGroup) {
mWeakLoadGroup = nullptr;
return loadGroup->RemoveRequest(this, nullptr, NS_OK);
}
return NS_OK;
}
+
+void
+PresentationConnection::AsyncCloseConnectionWithErrorMsg(const nsAString& aMessage)
+{
+ if (mState == PresentationConnectionState::Terminated) {
+ return;
+ }
+
+ nsString message = nsString(aMessage);
+ nsCOMPtr<nsIRunnable> r =
+ NS_NewRunnableFunction([this, message]() -> void {
+ // Set |mState| to |PresentationConnectionState::Closed| here to avoid
+ // calling |ProcessStateChanged|.
+ mState = PresentationConnectionState::Closed;
+
+ // Make sure dispatching the event and closing the connection are invoked
+ // at the same time by setting |aDispatchNow| to true.
+ Unused << NS_WARN_IF(NS_FAILED(
+ DispatchConnectionClosedEvent(PresentationConnectionClosedReason::Error,
+ message,
+ true)));
+
+ nsCOMPtr<nsIPresentationService> service =
+ do_GetService(PRESENTATION_SERVICE_CONTRACTID);
+ if(NS_WARN_IF(!service)) {
+ return;
+ }
+
+ Unused << NS_WARN_IF(NS_FAILED(
+ service->CloseSession(mId,
+ mRole,
+ nsIPresentationService::CLOSED_REASON_ERROR)));
+ });
+
+ Unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(r)));
+}
--- a/dom/presentation/PresentationConnection.h
+++ b/dom/presentation/PresentationConnection.h
@@ -3,26 +3,28 @@
/* 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/. */
#ifndef mozilla_dom_PresentationConnection_h
#define mozilla_dom_PresentationConnection_h
#include "mozilla/DOMEventTargetHelper.h"
+#include "mozilla/dom/TypedArray.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/PresentationConnectionBinding.h"
#include "mozilla/dom/PresentationConnectionClosedEventBinding.h"
#include "nsIPresentationListener.h"
#include "nsIRequest.h"
#include "nsWeakReference.h"
namespace mozilla {
namespace dom {
+class Blob;
class PresentationConnectionList;
class PresentationConnection final : public DOMEventTargetHelper
, public nsIPresentationSessionListener
, public nsIRequest
, public SupportsWeakPtr<PresentationConnection>
{
public:
@@ -47,19 +49,32 @@ public:
// WebIDL (public APIs)
void GetId(nsAString& aId) const;
void GetUrl(nsAString& aUrl) const;
PresentationConnectionState State() const;
+ PresentationConnectionBinaryType BinaryType() const;
+
+ void SetBinaryType(PresentationConnectionBinaryType aType);
+
void Send(const nsAString& aData,
ErrorResult& aRv);
+ void Send(Blob& aData,
+ ErrorResult& aRv);
+
+ void Send(const ArrayBuffer& aData,
+ ErrorResult& aRv);
+
+ void Send(const ArrayBufferView& aData,
+ ErrorResult& aRv);
+
void Close(ErrorResult& aRv);
void Terminate(ErrorResult& aRv);
bool
Equals(uint64_t aWindowId, const nsAString& aId);
IMPL_EVENT_HANDLER(connect);
@@ -78,30 +93,36 @@ private:
bool Init();
void Shutdown();
nsresult ProcessStateChanged(nsresult aReason);
nsresult DispatchConnectionClosedEvent(PresentationConnectionClosedReason aReason,
- const nsAString& aMessage);
+ const nsAString& aMessage,
+ bool aDispatchNow = false);
nsresult DispatchMessageEvent(JS::Handle<JS::Value> aData);
nsresult ProcessConnectionWentAway();
nsresult AddIntoLoadGroup();
nsresult RemoveFromLoadGroup();
+ void AsyncCloseConnectionWithErrorMsg(const nsAString& aMessage);
+
+ nsresult DoReceiveMessage(const nsACString& aData, bool aIsBinary);
+
nsString mId;
nsString mUrl;
uint8_t mRole;
PresentationConnectionState mState;
RefPtr<PresentationConnectionList> mOwningConnectionList;
- nsWeakPtr mWeakLoadGroup;;
+ nsWeakPtr mWeakLoadGroup;
+ PresentationConnectionBinaryType mBinaryType;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PresentationConnection_h
--- a/dom/presentation/PresentationDataChannelSessionTransport.js
+++ b/dom/presentation/PresentationDataChannelSessionTransport.js
@@ -22,17 +22,17 @@ const PRESENTATIONTRANSPORTBUILDER_CONTR
function PresentationDataChannelDescription(aDataChannelSDP) {
this._dataChannelSDP = JSON.stringify(aDataChannelSDP);
}
PresentationDataChannelDescription.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationChannelDescription]),
get type() {
- return nsIPresentationChannelDescription.TYPE_DATACHANNEL;
+ return Ci.nsIPresentationChannelDescription.TYPE_DATACHANNEL;
},
get tcpAddress() {
return null;
},
get tcpPort() {
return null;
},
get dataChannelSDP() {
@@ -89,16 +89,18 @@ PresentationTransportBuilder.prototype =
case Ci.nsIPresentationService.ROLE_CONTROLLER:
this._dataChannel = this._peerConnection.createDataChannel("presentationAPI");
this._setDataChannel();
break;
case Ci.nsIPresentationService.ROLE_RECEIVER:
this._peerConnection.ondatachannel = aEvent => {
this._dataChannel = aEvent.channel;
+ // Ensure the binaryType of dataChannel is blob.
+ this._dataChannel.binaryType = "blob";
this._setDataChannel();
}
break;
default:
throw Cr.NS_ERROR_ILLEGAL_VALUE;
}
// TODO bug 1228235 we should have a way to let device providers customize
@@ -129,17 +131,17 @@ PresentationTransportBuilder.prototype =
_setDataChannel: function() {
this._dataChannel.onopen = () => {
log("data channel is open, notify the listener, role " + this._role);
// Handoff the ownership of _peerConnection and _dataChannel to
// _sessionTransport
this._sessionTransport = new PresentationTransport();
- this._sessionTransport.init(this._peerConnection, this._dataChannel);
+ this._sessionTransport.init(this._peerConnection, this._dataChannel, this._window);
this._peerConnection = this._dataChannel = null;
this._listener.onSessionTransport(this._sessionTransport);
this._sessionTransport.callback.notifyTransportReady();
this._cleanup(Cr.NS_OK);
};
@@ -238,21 +240,22 @@ function PresentationTransport() {
this._closeReason = Cr.NS_OK;
}
PresentationTransport.prototype = {
classID: PRESENTATIONTRANSPORT_CID,
contractID: PRESENTATIONTRANSPORT_CONTRACTID,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransport]),
- init: function(aPeerConnection, aDataChannel) {
+ init: function(aPeerConnection, aDataChannel, aWindow) {
log("initWithDataChannel");
this._enableDataNotification = false;
this._dataChannel = aDataChannel;
this._peerConnection = aPeerConnection;
+ this._window = aWindow;
this._dataChannel.onopen = () => {
log("data channel reopen. Should never touch here");
};
this._dataChannel.onclose = () => {
log("data channel onclose");
if (this._callback) {
@@ -264,17 +267,17 @@ PresentationTransport.prototype = {
this._dataChannel.onmessage = aEvent => {
log("data channel onmessage " + aEvent.data);
if (!this._enableDataNotification || !this._callback) {
log("queue message");
this._messageQueue.push(aEvent.data);
return;
}
- this._callback.notifyData(aEvent.data);
+ this._doNotifyData(aEvent.data);
};
this._dataChannel.onerror = aError => {
log("data channel onerror " + aError.name + ":" + aError.message);
if (this._callback) {
this._callback.notifyTransportClosed(Cr.NS_ERROR_FAILURE);
}
this._cleanup();
@@ -294,29 +297,46 @@ PresentationTransport.prototype = {
this._callback = aCallback;
},
send: function(aData) {
log("send " + aData);
this._dataChannel.send(aData);
},
+ sendBinaryMsg: function(aData) {
+ log("sendBinaryMsg");
+
+ let array = new Uint8Array(aData.length);
+ for (let i = 0; i < aData.length; i++) {
+ array[i] = aData.charCodeAt(i);
+ }
+
+ this._dataChannel.send(array);
+ },
+
+ sendBlob: function(aBlob) {
+ log("sendBlob");
+
+ this._dataChannel.send(aBlob);
+ },
+
enableDataNotification: function() {
log("enableDataNotification");
if (this._enableDataNotification) {
return;
}
if (!this._callback) {
throw NS_ERROR_NOT_AVAILABLE;
}
this._enableDataNotification = true;
- this._messageQueue.forEach(aData => this._callback.notifyData(aData));
+ this._messageQueue.forEach(aData => this._doNotifyData(aData));
this._messageQueue = [];
},
close: function(aReason) {
this._closeReason = aReason;
this._dataChannel.close();
},
@@ -325,13 +345,30 @@ PresentationTransport.prototype = {
this._dataChannel = null;
if (this._peerConnection) {
this._peerConnection.close();
this._peerConnection = null;
}
this._callback = null;
this._messageQueue = [];
+ this._window = null;
+ },
+
+ _doNotifyData: function(aData) {
+ if (!this._callback) {
+ throw NS_ERROR_NOT_AVAILABLE;
+ }
+
+ if (aData instanceof this._window.Blob) {
+ let reader = new this._window.FileReader();
+ reader.addEventListener("load", (aEvent) => {
+ this._callback.notifyData(aEvent.target.result, true);
+ });
+ reader.readAsBinaryString(aData);
+ } else {
+ this._callback.notifyData(aData, false);
+ }
},
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PresentationTransportBuilder,
PresentationTransport]);
--- a/dom/presentation/PresentationService.cpp
+++ b/dom/presentation/PresentationService.cpp
@@ -772,16 +772,54 @@ PresentationService::SendSessionMessage(
if (NS_WARN_IF(!info)) {
return NS_ERROR_NOT_AVAILABLE;
}
return info->Send(aData);
}
NS_IMETHODIMP
+PresentationService::SendSessionBinaryMsg(const nsAString& aSessionId,
+ uint8_t aRole,
+ const nsACString &aData)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!aData.IsEmpty());
+ MOZ_ASSERT(!aSessionId.IsEmpty());
+ MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
+ aRole == nsIPresentationService::ROLE_RECEIVER);
+
+ RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole);
+ if (NS_WARN_IF(!info)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ return info->SendBinaryMsg(aData);
+}
+
+NS_IMETHODIMP
+PresentationService::SendSessionBlob(const nsAString& aSessionId,
+ uint8_t aRole,
+ nsIDOMBlob* aBlob)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!aSessionId.IsEmpty());
+ MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
+ aRole == nsIPresentationService::ROLE_RECEIVER);
+ MOZ_ASSERT(aBlob);
+
+ RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole);
+ if (NS_WARN_IF(!info)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ return info->SendBlob(aBlob);
+}
+
+NS_IMETHODIMP
PresentationService::CloseSession(const nsAString& aSessionId,
uint8_t aRole,
uint8_t aClosedReason)
{
PRES_DEBUG("%s:id[%s], reason[%x], role[%d]\n", __func__,
NS_ConvertUTF16toUTF8(aSessionId).get(), aClosedReason, aRole);
MOZ_ASSERT(NS_IsMainThread());
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -280,16 +280,44 @@ PresentationSessionInfo::Send(const nsAS
if (NS_WARN_IF(!mTransport)) {
return NS_ERROR_NOT_AVAILABLE;
}
return mTransport->Send(aData);
}
nsresult
+PresentationSessionInfo::SendBinaryMsg(const nsACString& aData)
+{
+ if (NS_WARN_IF(!IsSessionReady())) {
+ return NS_ERROR_DOM_INVALID_STATE_ERR;
+ }
+
+ if (NS_WARN_IF(!mTransport)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ return mTransport->SendBinaryMsg(aData);
+}
+
+nsresult
+PresentationSessionInfo::SendBlob(nsIDOMBlob* aBlob)
+{
+ if (NS_WARN_IF(!IsSessionReady())) {
+ return NS_ERROR_DOM_INVALID_STATE_ERR;
+ }
+
+ if (NS_WARN_IF(!mTransport)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ return mTransport->SendBlob(aBlob);
+}
+
+nsresult
PresentationSessionInfo::Close(nsresult aReason,
uint32_t aState)
{
if (NS_WARN_IF(!IsSessionReady())) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
// Do nothing if session is already terminated.
@@ -470,29 +498,29 @@ PresentationSessionInfo::NotifyTransport
// Directly untrack the session info from the service.
return UntrackFromService();
}
return NS_OK;
}
NS_IMETHODIMP
-PresentationSessionInfo::NotifyData(const nsACString& aData)
+PresentationSessionInfo::NotifyData(const nsACString& aData, bool aIsBinary)
{
MOZ_ASSERT(NS_IsMainThread());
if (NS_WARN_IF(!IsSessionReady())) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
if (NS_WARN_IF(!mListener)) {
return NS_ERROR_NOT_AVAILABLE;
}
- return mListener->NotifyMessage(mSessionId, aData);
+ return mListener->NotifyMessage(mSessionId, aData, aIsBinary);
}
// nsIPresentationSessionTransportBuilderListener
NS_IMETHODIMP
PresentationSessionInfo::OnSessionTransport(nsIPresentationSessionTransport* transport)
{
PRES_DEBUG("%s:id[%s], role[%d], state[%d]\n", __func__,
NS_ConvertUTF16toUTF8(mSessionId).get(), mRole, mState);
--- a/dom/presentation/PresentationSessionInfo.h
+++ b/dom/presentation/PresentationSessionInfo.h
@@ -94,16 +94,20 @@ public:
mControlChannel = aControlChannel;
if (mControlChannel) {
mControlChannel->SetListener(this);
}
}
nsresult Send(const nsAString& aData);
+ nsresult SendBinaryMsg(const nsACString& aData);
+
+ nsresult SendBlob(nsIDOMBlob* aBlob);
+
nsresult Close(nsresult aReason,
uint32_t aState);
nsresult OnTerminate(nsIPresentationControlChannel* aControlChannel);
nsresult ReplyError(nsresult aReason);
virtual bool IsAccessible(base::ProcessId aProcessId);
--- a/dom/presentation/PresentationTCPSessionTransport.cpp
+++ b/dom/presentation/PresentationTCPSessionTransport.cpp
@@ -413,16 +413,28 @@ PresentationTCPSessionTransport::Send(co
mMultiplexStream->AppendStream(stream);
EnsureCopying();
return NS_OK;
}
NS_IMETHODIMP
+PresentationTCPSessionTransport::SendBinaryMsg(const nsACString& aData)
+{
+ return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+}
+
+NS_IMETHODIMP
+PresentationTCPSessionTransport::SendBlob(nsIDOMBlob* aBlob)
+{
+ return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+}
+
+NS_IMETHODIMP
PresentationTCPSessionTransport::Close(nsresult aReason)
{
PRES_DEBUG("%s:reason[%x]\n", __func__, aReason);
if (mReadyState == ReadyState::CLOSED || mReadyState == ReadyState::CLOSING) {
return NS_OK;
}
@@ -568,10 +580,10 @@ PresentationTCPSessionTransport::OnDataA
nsCString data;
nsresult rv = mInputStreamScriptable->ReadBytes(aCount, data);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Pass the incoming data to the listener.
- return mCallback->NotifyData(data);
+ return mCallback->NotifyData(data, false);
}
--- a/dom/presentation/interfaces/nsIPresentationListener.idl
+++ b/dom/presentation/interfaces/nsIPresentationListener.idl
@@ -27,17 +27,18 @@ interface nsIPresentationSessionListener
void notifyStateChange(in DOMString sessionId,
in unsigned short state,
in nsresult reason);
/*
* Called when receive messages.
*/
void notifyMessage(in DOMString sessionId,
- in ACString data);
+ in ACString data,
+ in boolean isBinary);
/*
* Called when this listener is replaced by another one.
*/
void notifyReplaced();
};
[scriptable, uuid(27f101d7-9ed1-429e-b4f8-43b00e8e111c)]
--- a/dom/presentation/interfaces/nsIPresentationService.idl
+++ b/dom/presentation/interfaces/nsIPresentationService.idl
@@ -1,14 +1,15 @@
/* 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/. */
#include "nsISupports.idl"
+interface nsIDOMBlob;
interface nsIDOMEventTarget;
interface nsIInputStream;
interface nsIPresentationAvailabilityListener;
interface nsIPresentationRespondingListener;
interface nsIPresentationSessionListener;
interface nsIPresentationTransportBuilderConstructor;
%{C++
@@ -91,16 +92,38 @@ interface nsIPresentationService : nsISu
* @param role: Identify the function called by controller or receiver.
* @param data: the message being sent out.
*/
void sendSessionMessage(in DOMString sessionId,
in uint8_t role,
in DOMString data);
/*
+ * Send the binary message to the session.
+ *
+ * @param sessionId: An ID to identify presentation session.
+ * @param role: Identify the function called by controller or receiver.
+ * @param data: the message being sent out.
+ */
+ void sendSessionBinaryMsg(in DOMString sessionId,
+ in uint8_t role,
+ in ACString data);
+
+ /*
+ * Send the blob to the session.
+ *
+ * @param sessionId: An ID to identify presentation session.
+ * @param role: Identify the function called by controller or receiver.
+ * @param blob: The input blob to be sent.
+ */
+ void sendSessionBlob(in DOMString sessionId,
+ in uint8_t role,
+ in nsIDOMBlob blob);
+
+ /*
* Close the session.
*
* @param sessionId: An ID to identify presentation session.
* @param role: Identify the function called by controller or receiver.
*/
void closeSession(in DOMString sessionId,
in uint8_t role,
in uint8_t closedReason);
--- a/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
+++ b/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
@@ -1,31 +1,32 @@
/* 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/. */
#include "nsISupports.idl"
+interface nsIDOMBlob;
interface nsIInputStream;
interface nsINetAddr;
%{C++
#define PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID \
"@mozilla.org/presentation/presentationtcpsessiontransport;1"
%}
/*
* The callback for session transport events.
*/
[scriptable, uuid(9f158786-41a6-4a10-b29b-9497f25d4b67)]
interface nsIPresentationSessionTransportCallback : nsISupports
{
void notifyTransportReady();
void notifyTransportClosed(in nsresult reason);
- void notifyData(in ACString data);
+ void notifyData(in ACString data, in boolean isBinary);
};
/*
* App-to-App transport channel for the presentation session.
*/
[scriptable, uuid(670b7e1b-65be-42b6-a596-be571907fa18)]
interface nsIPresentationSessionTransport : nsISupports
{
@@ -44,13 +45,25 @@ interface nsIPresentationSessionTranspor
/*
* Send message to the remote endpoint.
* @param data The message to send.
*/
void send(in DOMString data);
/*
+ * Send the binary message to the remote endpoint.
+ * @param data: the message being sent out.
+ */
+ void sendBinaryMsg(in ACString data);
+
+ /*
+ * Send the blob to the remote endpoint.
+ * @param blob: The input blob to be sent.
+ */
+ void sendBlob(in nsIDOMBlob blob);
+
+ /*
* Close this session transport.
* @param reason The reason for closing this session transport.
*/
void close(in nsresult reason);
};
--- a/dom/presentation/ipc/PPresentation.ipdl
+++ b/dom/presentation/ipc/PPresentation.ipdl
@@ -74,17 +74,17 @@ sync protocol PPresentation
manages PPresentationBuilder;
manages PPresentationRequest;
child:
async NotifyAvailableChange(bool aAvailable);
async NotifySessionStateChange(nsString aSessionId,
uint16_t aState,
nsresult aReason);
- async NotifyMessage(nsString aSessionId, nsCString aData);
+ async NotifyMessage(nsString aSessionId, nsCString aData, bool aIsBinary);
async NotifySessionConnect(uint64_t aWindowId, nsString aSessionId);
async PPresentationBuilder(nsString aSessionId, uint8_t aRole);
parent:
async __delete__();
async RegisterAvailabilityHandler();
--- a/dom/presentation/ipc/PresentationChild.cpp
+++ b/dom/presentation/ipc/PresentationChild.cpp
@@ -107,20 +107,23 @@ PresentationChild::RecvNotifySessionStat
aState,
aReason)));
}
return true;
}
bool
PresentationChild::RecvNotifyMessage(const nsString& aSessionId,
- const nsCString& aData)
+ const nsCString& aData,
+ const bool& aIsBinary)
{
if (mService) {
- Unused << NS_WARN_IF(NS_FAILED(mService->NotifyMessage(aSessionId, aData)));
+ Unused << NS_WARN_IF(NS_FAILED(mService->NotifyMessage(aSessionId,
+ aData,
+ aIsBinary)));
}
return true;
}
bool
PresentationChild::RecvNotifySessionConnect(const uint64_t& aWindowId,
const nsString& aSessionId)
{
--- a/dom/presentation/ipc/PresentationChild.h
+++ b/dom/presentation/ipc/PresentationChild.h
@@ -47,17 +47,18 @@ public:
virtual bool
RecvNotifySessionStateChange(const nsString& aSessionId,
const uint16_t& aState,
const nsresult& aReason) override;
virtual bool
RecvNotifyMessage(const nsString& aSessionId,
- const nsCString& aData) override;
+ const nsCString& aData,
+ const bool& aIsBinary) override;
virtual bool
RecvNotifySessionConnect(const uint64_t& aWindowId,
const nsString& aSessionId) override;
private:
virtual ~PresentationChild();
--- a/dom/presentation/ipc/PresentationContentSessionInfo.cpp
+++ b/dom/presentation/ipc/PresentationContentSessionInfo.cpp
@@ -31,16 +31,36 @@ PresentationContentSessionInfo::Send(con
if (!mTransport) {
return NS_ERROR_NOT_AVAILABLE;
}
return mTransport->Send(aData);
}
nsresult
+PresentationContentSessionInfo::SendBinaryMsg(const nsACString& aData)
+{
+ if (NS_WARN_IF(!mTransport)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ return mTransport->SendBinaryMsg(aData);
+}
+
+nsresult
+PresentationContentSessionInfo::SendBlob(nsIDOMBlob* aBlob)
+{
+ if (NS_WARN_IF(!mTransport)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ return mTransport->SendBlob(aBlob);
+}
+
+nsresult
PresentationContentSessionInfo::Close(nsresult aReason)
{
if (!mTransport) {
return NS_ERROR_NOT_AVAILABLE;
}
return mTransport->Close(aReason);
}
@@ -66,23 +86,24 @@ PresentationContentSessionInfo::NotifyTr
if (NS_WARN_IF(!service)) {
return NS_ERROR_NOT_AVAILABLE;
}
return static_cast<PresentationIPCService*>(service.get())->
NotifyTransportClosed(mSessionId, mRole, aReason);
}
NS_IMETHODIMP
-PresentationContentSessionInfo::NotifyData(const nsACString& aData)
+PresentationContentSessionInfo::NotifyData(const nsACString& aData,
+ bool aIsBinary)
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return NS_ERROR_NOT_AVAILABLE;
}
return static_cast<PresentationIPCService*>(service.get())->
- NotifyMessage(mSessionId, aData);
+ NotifyMessage(mSessionId, aData, aIsBinary);
}
} // namespace dom
} // namespace mozilla
--- a/dom/presentation/ipc/PresentationContentSessionInfo.h
+++ b/dom/presentation/ipc/PresentationContentSessionInfo.h
@@ -37,16 +37,20 @@ public:
aRole == nsIPresentationService::ROLE_RECEIVER);
MOZ_ASSERT(aTransport);
}
nsresult Init();
nsresult Send(const nsAString& aData);
+ nsresult SendBinaryMsg(const nsACString& aData);
+
+ nsresult SendBlob(nsIDOMBlob* aBlob);
+
nsresult Close(nsresult aReason);
private:
virtual ~PresentationContentSessionInfo() {}
nsString mSessionId;
uint8_t mRole;
nsCOMPtr<nsIPresentationSessionTransport> mTransport;
--- a/dom/presentation/ipc/PresentationIPCService.cpp
+++ b/dom/presentation/ipc/PresentationIPCService.cpp
@@ -97,16 +97,56 @@ PresentationIPCService::SendSessionMessa
}
return SendRequest(nullptr, SendSessionMessageRequest(nsString(aSessionId),
aRole,
nsString(aData)));
}
NS_IMETHODIMP
+PresentationIPCService::SendSessionBinaryMsg(const nsAString& aSessionId,
+ uint8_t aRole,
+ const nsACString &aData)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!aData.IsEmpty());
+ MOZ_ASSERT(!aSessionId.IsEmpty());
+ MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
+ aRole == nsIPresentationService::ROLE_RECEIVER);
+
+ RefPtr<PresentationContentSessionInfo> info;
+ // data channel session transport is maintained by content process
+ if (mSessionInfos.Get(aSessionId, getter_AddRefs(info))) {
+ return info->SendBinaryMsg(aData);
+ }
+
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+PresentationIPCService::SendSessionBlob(const nsAString& aSessionId,
+ uint8_t aRole,
+ nsIDOMBlob* aBlob)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!aSessionId.IsEmpty());
+ MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
+ aRole == nsIPresentationService::ROLE_RECEIVER);
+ MOZ_ASSERT(aBlob);
+
+ RefPtr<PresentationContentSessionInfo> info;
+ // data channel session transport is maintained by content process
+ if (mSessionInfos.Get(aSessionId, getter_AddRefs(info))) {
+ return info->SendBlob(aBlob);
+ }
+
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
PresentationIPCService::CloseSession(const nsAString& aSessionId,
uint8_t aRole,
uint8_t aClosedReason)
{
MOZ_ASSERT(!aSessionId.IsEmpty());
nsresult rv = SendRequest(nullptr, CloseSessionRequest(nsString(aSessionId),
aRole,
@@ -327,24 +367,25 @@ PresentationIPCService::NotifySessionSta
}
return listener->NotifyStateChange(aSessionId, aState, aReason);
}
// Only used for OOP RTCDataChannel session transport case.
nsresult
PresentationIPCService::NotifyMessage(const nsAString& aSessionId,
- const nsACString& aData)
+ const nsACString& aData,
+ const bool& aIsBinary)
{
nsCOMPtr<nsIPresentationSessionListener> listener;
if (NS_WARN_IF(!mSessionListeners.Get(aSessionId, getter_AddRefs(listener)))) {
return NS_OK;
}
- return listener->NotifyMessage(aSessionId, aData);
+ return listener->NotifyMessage(aSessionId, aData, aIsBinary);
}
// Only used for OOP RTCDataChannel session transport case.
nsresult
PresentationIPCService::NotifyTransportClosed(const nsAString& aSessionId,
uint8_t aRole,
nsresult aReason)
{
--- a/dom/presentation/ipc/PresentationIPCService.h
+++ b/dom/presentation/ipc/PresentationIPCService.h
@@ -32,17 +32,18 @@ public:
nsresult NotifyAvailableChange(bool aAvailable);
nsresult NotifySessionStateChange(const nsAString& aSessionId,
uint16_t aState,
nsresult aReason);
nsresult NotifyMessage(const nsAString& aSessionId,
- const nsACString& aData);
+ const nsACString& aData,
+ const bool& aIsBinary);
nsresult NotifySessionConnect(uint64_t aWindowId,
const nsAString& aSessionId);
void NotifyPresentationChildDestroyed();
nsresult MonitorResponderLoading(const nsAString& aSessionId,
nsIDocShell* aDocShell);
--- a/dom/presentation/ipc/PresentationParent.cpp
+++ b/dom/presentation/ipc/PresentationParent.cpp
@@ -310,20 +310,23 @@ PresentationParent::NotifyReplaced()
{
// Do nothing here, since |PresentationIPCService::RegisterSessionListener|
// already dealt with this in content process.
return NS_OK;
}
NS_IMETHODIMP
PresentationParent::NotifyMessage(const nsAString& aSessionId,
- const nsACString& aData)
+ const nsACString& aData,
+ bool aIsBinary)
{
if (NS_WARN_IF(mActorDestroyed ||
- !SendNotifyMessage(nsString(aSessionId), nsCString(aData)))) {
+ !SendNotifyMessage(nsString(aSessionId),
+ nsCString(aData),
+ aIsBinary))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
PresentationParent::NotifySessionConnect(uint64_t aWindowId,
const nsAString& aSessionId)
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
@@ -291,17 +291,17 @@ const mockedSessionTransport = {
close: function(reason) {
sendAsyncMessage('data-transport-closed', reason);
this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportClosed(reason);
},
simulateTransportReady: function() {
this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportReady();
},
simulateIncomingMessage: function(message) {
- this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyData(message);
+ this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyData(message, false);
},
onOffer: function(aOffer) {
},
onAnswer: function(aAnswer) {
}
};
const mockedNetworkInfo = {
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
@@ -72,16 +72,28 @@ const mockControlChannelOfSender = {
mockControlChannelOfReceiver.disconnect();
},
terminate: function(presentationId) {
sendAsyncMessage('sender-terminate');
},
reconnect: function(presentationId, url) {
sendAsyncMessage('start-reconnect', url);
},
+ sendIceCandidate: function(candidate) {
+ mockControlChannelOfReceiver.notifyIceCandidate(candidate);
+ },
+ notifyIceCandidate: function(candidate) {
+ if (!this._listener) {
+ return;
+ }
+
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .onIceCandidate(candidate);
+ },
};
// control channel of receiver
const mockControlChannelOfReceiver = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
set listener(listener) {
// PresentationPresentingInfo::SetControlChannel
if (listener) {
@@ -125,17 +137,29 @@ const mockControlChannelOfReceiver = {
}
this._listener
.QueryInterface(Ci.nsIPresentationControlChannelListener)
.notifyDisconnected(reason);
sendAsyncMessage('control-channel-receiver-closed', reason);
},
terminate: function(presentaionId) {
- }
+ },
+ sendIceCandidate: function(candidate) {
+ mockControlChannelOfReceiver.notifyIceCandidate(candidate);
+ },
+ notifyIceCandidate: function(candidate) {
+ if (!this._listener) {
+ return;
+ }
+
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .onIceCandidate(candidate);
+ },
};
const mockDevice = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice]),
id: 'id',
name: 'name',
type: 'type',
establishControlChannel: function(url, presentationId) {
--- a/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
@@ -129,17 +129,17 @@ function loadPrivilegedScriptTest() {
sendMessage('data-transport-closed', reason);
this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportClosed(reason);
this._callback = null;
},
simulateTransportReady: function() {
this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportReady();
},
simulateIncomingMessage: function(message) {
- this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyData(message);
+ this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyData(message, false);
},
onOffer: function(aOffer) {
this._listener.sendAnswer(mockedChannelDescription);
this._onSessionTransport();
},
onAnswer: function(aAnswer) {
this._onSessionTransport();
},
--- a/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
+++ b/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
@@ -31,16 +31,37 @@ function command(name, data) {
alert('COMMAND ' + JSON.stringify({name: name, data: data}));
}
function finish() {
alert('DONE');
}
var connection;
+const DATA_ARRAY = [0, 255, 254, 0, 1, 2, 3, 0, 255, 255, 254, 0];
+const DATA_ARRAY_BUFFER = new ArrayBuffer(DATA_ARRAY.length);
+const TYPED_DATA_ARRAY = new Uint8Array(DATA_ARRAY_BUFFER);
+TYPED_DATA_ARRAY.set(DATA_ARRAY);
+
+function is_same_buffer(recv_data, expect_data) {
+ let recv_dataview = new Uint8Array(recv_data);
+ let expected_dataview = new Uint8Array(expect_data);
+
+ if (recv_dataview.length !== expected_dataview.length) {
+ return false;
+ }
+
+ for (let i = 0; i < recv_dataview.length; i++) {
+ if (recv_dataview[i] != expected_dataview[i]) {
+ info('discover byte differenct at ' + i);
+ return false;
+ }
+ }
+ return true;
+}
function testConnectionAvailable() {
return new Promise(function(aResolve, aReject) {
info('Receiver: --- testConnectionAvailable ---');
ok(navigator.presentation, "Receiver: navigator.presentation should be available.");
ok(navigator.presentation.receiver, "Receiver: navigator.presentation.receiver should be available.");
navigator.presentation.receiver.connectionList
@@ -100,16 +121,29 @@ function testSendMessage() {
if (message.type === 'message-from-receiver-received') {
window.removeEventListener('hashchange', hashchangeHandler);
aResolve();
}
});
});
}
+function testIncomingBlobMessage() {
+ return new Promise(function(aResolve, aReject) {
+ info('Receiver: --- testIncomingBlobMessage ---');
+ connection.send('testIncomingBlobMessage');
+ connection.addEventListener('message', function messageHandler(evt) {
+ connection.removeEventListener('message', messageHandler);
+ let recvData= String.fromCharCode.apply(null, new Uint8Array(evt.data));
+ is(recvData, "Hello World", 'expected same string data');
+ aResolve();
+ });
+ });
+}
+
function testConnectionClosed() {
return new Promise(function(aResolve, aReject) {
info('Receiver: --- testConnectionClosed ---');
connection.onclose = function() {
connection.onclose = null;
is(connection.state, "closed", "Receiver: Connection should be closed.");
command('forward-command', JSON.stringify({ name: 'receiver-closed' }));
aResolve();
@@ -125,23 +159,56 @@ function testReconnectConnection() {
connection.onconnect = function() {
connection.onconnect = null;
ok(true, "The connection is reconnected.")
aResolve();
};
});
}
+function testIncomingArrayBuffer() {
+ return new Promise(function(aResolve, aReject) {
+ info('Receiver: --- testIncomingArrayBuffer ---');
+ connection.binaryType = "blob";
+ connection.send('testIncomingArrayBuffer');
+ connection.addEventListener('message', function messageHandler(evt) {
+ connection.removeEventListener('message', messageHandler);
+ var fileReader = new FileReader();
+ fileReader.onload = function() {
+ ok(is_same_buffer(DATA_ARRAY_BUFFER, this.result), "expected same buffer data");
+ aResolve();
+ };
+ fileReader.readAsArrayBuffer(evt.data);
+ });
+ });
+}
+
+function testIncomingArrayBufferView() {
+ return new Promise(function(aResolve, aReject) {
+ info('Receiver: --- testIncomingArrayBufferView ---');
+ connection.binaryType = "arraybuffer";
+ connection.send('testIncomingArrayBufferView');
+ connection.addEventListener('message', function messageHandler(evt) {
+ connection.removeEventListener('message', messageHandler);
+ ok(is_same_buffer(evt.data, TYPED_DATA_ARRAY), "expected same buffer data");
+ aResolve();
+ });
+ });
+}
+
function runTests() {
testConnectionAvailable()
.then(testConnectionReady)
.then(testIncomingMessage)
.then(testSendMessage)
+ .then(testIncomingBlobMessage)
.then(testConnectionClosed)
.then(testReconnectConnection)
+ .then(testIncomingArrayBuffer)
+ .then(testIncomingArrayBufferView)
.then(testConnectionClosed);
}
runTests();
</script>
</body>
</html>
--- a/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js
@@ -10,16 +10,20 @@ function debug(str) {
}
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript1UA.js'));
var receiverUrl = SimpleTest.getTestFileURL('file_presentation_1ua_receiver.html');
var request;
var connection;
var receiverIframe;
var presentationId;
+const DATA_ARRAY = [0, 255, 254, 0, 1, 2, 3, 0, 255, 255, 254, 0];
+const DATA_ARRAY_BUFFER = new ArrayBuffer(DATA_ARRAY.length);
+const TYPED_DATA_ARRAY = new Uint8Array(DATA_ARRAY_BUFFER);
+TYPED_DATA_ARRAY.set(DATA_ARRAY);
function postMessageToIframe(aType) {
receiverIframe.src = receiverUrl + "#" +
encodeURIComponent(JSON.stringify({ type: aType }));
}
function setup() {
@@ -154,16 +158,56 @@ function testIncomingMessage() {
is(msg, "msg-receiver-to-sender", "Sender: Sender should receive message from Receiver");
postMessageToIframe('message-from-receiver-received');
aResolve();
});
postMessageToIframe('trigger-message-from-receiver');
});
}
+function testSendBlobMessage() {
+ return new Promise(function(aResolve, aReject) {
+ info('Sender: --- testSendBlobMessage ---');
+ connection.addEventListener('message', function messageHandler(evt) {
+ connection.removeEventListener('message', messageHandler);
+ let msg = evt.data;
+ is(msg, "testIncomingBlobMessage", "Sender: Sender should receive message from Receiver");
+ let blob = new Blob(["Hello World"], {type : 'text/plain'});
+ connection.send(blob);
+ aResolve();
+ });
+ });
+}
+
+function testSendArrayBuffer() {
+ return new Promise(function(aResolve, aReject) {
+ info('Sender: --- testSendArrayBuffer ---');
+ connection.addEventListener('message', function messageHandler(evt) {
+ connection.removeEventListener('message', messageHandler);
+ let msg = evt.data;
+ is(msg, "testIncomingArrayBuffer", "Sender: Sender should receive message from Receiver");
+ connection.send(DATA_ARRAY_BUFFER);
+ aResolve();
+ });
+ });
+}
+
+function testSendArrayBufferView() {
+ return new Promise(function(aResolve, aReject) {
+ info('Sender: --- testSendArrayBufferView ---');
+ connection.addEventListener('message', function messageHandler(evt) {
+ connection.removeEventListener('message', messageHandler);
+ let msg = evt.data;
+ is(msg, "testIncomingArrayBufferView", "Sender: Sender should receive message from Receiver");
+ connection.send(TYPED_DATA_ARRAY);
+ aResolve();
+ });
+ });
+}
+
function testCloseConnection() {
info('Sender: --- testCloseConnection ---');
// Test terminate immediate after close.
function controlChannelEstablishedHandler()
{
gScript.removeMessageListener('control-channel-established',
controlChannelEstablishedHandler);
ok(false, "terminate after close should do nothing");
@@ -264,31 +308,35 @@ function teardown() {
gScript.sendAsyncMessage('teardown');
}
function runTests() {
setup().then(testCreateRequest)
.then(testStartConnection)
.then(testSendMessage)
.then(testIncomingMessage)
+ .then(testSendBlobMessage)
.then(testCloseConnection)
.then(testReconnect)
+ .then(testSendArrayBuffer)
+ .then(testSendArrayBufferView)
.then(testCloseConnection)
.then(testTerminateAfterClose)
.then(teardown);
}
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout('Test for guarantee not firing async event');
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: "browser", allow: true, context: document},
], () => {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
/* Mocked TCP session transport builder in the test */
- ["dom.presentation.session_transport.data_channel.enable", false],
+ ["dom.presentation.session_transport.data_channel.enable", true],
["dom.presentation.controller.enabled", true],
["dom.presentation.receiver.enabled", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0],
- ["dom.mozBrowserFramesEnabled", true]]},
+ ["dom.mozBrowserFramesEnabled", true],
+ ["media.navigator.permission.disabled", true]]},
runTests);
});
--- a/dom/webidl/PresentationConnection.webidl
+++ b/dom/webidl/PresentationConnection.webidl
@@ -15,16 +15,22 @@ enum PresentationConnectionState
// Existing presentation, but the communication channel is inactive.
"closed",
// The presentation is nonexistent anymore. It could be terminated manually,
// or either controlling or receiving browsing context is no longer available.
"terminated"
};
+enum PresentationConnectionBinaryType
+{
+ "blob",
+ "arraybuffer"
+};
+
[Pref="dom.presentation.enabled"]
interface PresentationConnection : EventTarget {
/*
* Unique id for all existing connections.
*/
[Constant]
readonly attribute DOMString id;
@@ -36,30 +42,37 @@ interface PresentationConnection : Event
/*
* @value "connected", "closed", or "terminated".
*/
readonly attribute PresentationConnectionState state;
attribute EventHandler onconnect;
attribute EventHandler onclose;
attribute EventHandler onterminate;
+ attribute PresentationConnectionBinaryType binaryType;
/*
* After a communication channel has been established between the controlling
* and receiving context, this function is called to send message out, and the
* event handler "onmessage" will be invoked at the remote side.
*
* This function only works when the state is "connected".
- *
- * TODO bug 1228474 Implement PresentationSessionTransport with DataChannel to
- * support other binary types.
*/
[Throws]
void send(DOMString data);
+ [Throws]
+ void send(Blob data);
+
+ [Throws]
+ void send(ArrayBuffer data);
+
+ [Throws]
+ void send(ArrayBufferView data);
+
/*
* It is triggered when receiving messages.
*/
attribute EventHandler onmessage;
/*
* Both the controlling and receiving browsing context can close the
* connection. Then the connection state should turn into "closed".
--- a/gfx/ipc/VsyncBridgeChild.cpp
+++ b/gfx/ipc/VsyncBridgeChild.cpp
@@ -130,13 +130,13 @@ void
VsyncBridgeChild::DeallocPVsyncBridgeChild()
{
Release();
}
void
VsyncBridgeChild::ProcessingError(Result aCode, const char* aReason)
{
- MOZ_RELEASE_ASSERT(aCode != MsgDropped, "Processing error in VsyncBridgeChild");
+ MOZ_RELEASE_ASSERT(aCode == MsgDropped, "Processing error in VsyncBridgeChild");
}
} // namespace gfx
} // namespace mozilla
--- a/gfx/layers/ipc/APZCTreeManagerParent.cpp
+++ b/gfx/layers/ipc/APZCTreeManagerParent.cpp
@@ -177,24 +177,20 @@ APZCTreeManagerParent::RecvSetTargetAPZC
{
for (size_t i = 0; i < aTargets.Length(); i++) {
if (aTargets[i].mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in RecvSetTargetAPZC; dropping message...");
return false;
}
}
-
- void (IAPZCTreeManager::*setTargetApzcFunc)(uint64_t, const nsTArray<ScrollableLayerGuid>&)
- = &IAPZCTreeManager::SetTargetAPZC;
-
APZThreadUtils::RunOnControllerThread(NewRunnableMethod
<uint64_t,
StoreCopyPassByRRef<nsTArray<ScrollableLayerGuid>>>
- (mTreeManager, setTargetApzcFunc, aInputBlockId, aTargets));
+ (mTreeManager, &IAPZCTreeManager::SetTargetAPZC, aInputBlockId, aTargets));
return true;
}
bool
APZCTreeManagerParent::RecvUpdateZoomConstraints(
const ScrollableLayerGuid& aGuid,
const MaybeZoomConstraints& aConstraints)
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1619,25 +1619,25 @@ fuzzy-if(Android,8,20) == 602200-3.html
== 605138-1.html 605138-1-ref.html
== 605157-1.xhtml 605157-1-ref.xhtml
== 607267-1.html 607267-1-ref.html
== 608636-1.html 608636-1-ref.html
== 608756-1a.html 608756-1-ref.html
== 608756-1b.html 608756-1-ref.html
== 608756-2.html 608756-2-ref.html
fuzzy-if(Android,4,196) == 609272-1.html 609272-1-ref.html
-needs-focus == 613433-1.html 613433-1-ref.html
-needs-focus == 613433-1.html 613433-2-ref.html
-needs-focus == 613433-1.html 613433-3-ref.html
-needs-focus == 613433-2.html 613433-1-ref.html
-needs-focus == 613433-2.html 613433-2-ref.html
-needs-focus == 613433-2.html 613433-3-ref.html
-needs-focus == 613433-3.html 613433-1-ref.html
-needs-focus == 613433-3.html 613433-2-ref.html
-needs-focus == 613433-3.html 613433-3-ref.html
+needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-1.html 613433-1-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
+needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-1.html 613433-2-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
+needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-1.html 613433-3-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
+needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-2.html 613433-1-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
+needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-2.html 613433-2-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
+needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-2.html 613433-3-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
+needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-3.html 613433-1-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
+needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-3.html 613433-2-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
+needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-3.html 613433-3-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
== 614272-1.svg 614272-1-ref.svg
HTTP(..) == 615121-1.html 615121-1-ref.html
HTTP(..) != 615121-2.html 615121-2-notref.html
== 617242-1.html 617242-1-ref.html
!= 618071.html 618071-notref.html
== 619117-1.html 619117-1-ref.html
HTTP(..) == 619511-1.html 619511-1-ref.html
skip-if(Android) HTTP(..) == 621253-1-externalFilter.html 621253-1-ref.html
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -1131,21 +1131,16 @@ InitSystemMetrics()
sSystemMetrics->AppendElement(nsGkAtoms::windows_default_theme);
}
rv = LookAndFeel::GetInt(LookAndFeel::eIntID_MacGraphiteTheme, &metricResult);
if (NS_SUCCEEDED(rv) && metricResult) {
sSystemMetrics->AppendElement(nsGkAtoms::mac_graphite_theme);
}
- rv = LookAndFeel::GetInt(LookAndFeel::eIntID_MacLionTheme, &metricResult);
- if (NS_SUCCEEDED(rv) && metricResult) {
- sSystemMetrics->AppendElement(nsGkAtoms::mac_lion_theme);
- }
-
rv = LookAndFeel::GetInt(LookAndFeel::eIntID_MacYosemiteTheme, &metricResult);
if (NS_SUCCEEDED(rv) && metricResult) {
sSystemMetrics->AppendElement(nsGkAtoms::mac_yosemite_theme);
}
rv = LookAndFeel::GetInt(LookAndFeel::eIntID_DWMCompositor, &metricResult);
if (NS_SUCCEEDED(rv) && metricResult) {
sSystemMetrics->AppendElement(nsGkAtoms::windows_compositor);
--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
@@ -712,24 +712,16 @@ nsMediaFeatures::features[] = {
&nsGkAtoms::_moz_mac_graphite_theme,
nsMediaFeature::eMinMaxNotAllowed,
nsMediaFeature::eBoolInteger,
nsMediaFeature::eNoRequirements,
{ &nsGkAtoms::mac_graphite_theme },
GetSystemMetric
},
{
- &nsGkAtoms::_moz_mac_lion_theme,
- nsMediaFeature::eMinMaxNotAllowed,
- nsMediaFeature::eBoolInteger,
- nsMediaFeature::eNoRequirements,
- { &nsGkAtoms::mac_lion_theme },
- GetSystemMetric
- },
- {
&nsGkAtoms::_moz_mac_yosemite_theme,
nsMediaFeature::eMinMaxNotAllowed,
nsMediaFeature::eBoolInteger,
nsMediaFeature::eNoRequirements,
{ &nsGkAtoms::mac_yosemite_theme },
GetSystemMetric
},
{
--- a/layout/style/test/test_media_queries.html
+++ b/layout/style/test/test_media_queries.html
@@ -624,17 +624,16 @@ function run() {
expression_should_be_parseable("-moz-scrollbar-end-backward");
expression_should_be_parseable("-moz-scrollbar-end-forward");
expression_should_be_parseable("-moz-scrollbar-thumb-proportional");
expression_should_be_parseable("-moz-images-in-menus");
expression_should_be_parseable("-moz-images-in-buttons");
expression_should_be_parseable("-moz-overlay-scrollbars");
expression_should_be_parseable("-moz-windows-default-theme");
expression_should_be_parseable("-moz-mac-graphite-theme");
- expression_should_be_parseable("-moz-mac-lion-theme");
expression_should_be_parseable("-moz-mac-yosemite-theme");
expression_should_be_parseable("-moz-windows-compositor");
expression_should_be_parseable("-moz-windows-classic");
expression_should_be_parseable("-moz-windows-glass");
expression_should_be_parseable("-moz-touch-enabled");
expression_should_be_parseable("-moz-swipe-animation-enabled");
expression_should_be_parseable("-moz-scrollbar-start-backward: 0");
@@ -642,17 +641,16 @@ function run() {
expression_should_be_parseable("-moz-scrollbar-end-backward: 0");
expression_should_be_parseable("-moz-scrollbar-end-forward: 0");
expression_should_be_parseable("-moz-scrollbar-thumb-proportional: 0");
expression_should_be_parseable("-moz-images-in-menus: 0");
expression_should_be_parseable("-moz-images-in-buttons: 0");
expression_should_be_parseable("-moz-overlay-scrollbars: 0");
expression_should_be_parseable("-moz-windows-default-theme: 0");
expression_should_be_parseable("-moz-mac-graphite-theme: 0");
- expression_should_be_parseable("-moz-mac-lion-theme: 0");
expression_should_be_parseable("-moz-mac-yosemite-theme: 0");
expression_should_be_parseable("-moz-windows-compositor: 0");
expression_should_be_parseable("-moz-windows-classic: 0");
expression_should_be_parseable("-moz-windows-glass: 0");
expression_should_be_parseable("-moz-touch-enabled: 0");
expression_should_be_parseable("-moz-swipe-animation-enabled: 0");
expression_should_be_parseable("-moz-scrollbar-start-backward: 1");
@@ -660,17 +658,16 @@ function run() {
expression_should_be_parseable("-moz-scrollbar-end-backward: 1");
expression_should_be_parseable("-moz-scrollbar-end-forward: 1");
expression_should_be_parseable("-moz-scrollbar-thumb-proportional: 1");
expression_should_be_parseable("-moz-images-in-menus: 1");
expression_should_be_parseable("-moz-images-in-buttons: 1");
expression_should_be_parseable("-moz-overlay-scrollbars: 1");
expression_should_be_parseable("-moz-windows-default-theme: 1");
expression_should_be_parseable("-moz-mac-graphite-theme: 1");
- expression_should_be_parseable("-moz-mac-lion-theme: 1");
expression_should_be_parseable("-moz-mac-yosemite-theme: 1");
expression_should_be_parseable("-moz-windows-compositor: 1");
expression_should_be_parseable("-moz-windows-classic: 1");
expression_should_be_parseable("-moz-windows-glass: 1");
expression_should_be_parseable("-moz-touch-enabled: 1");
expression_should_be_parseable("-moz-swipe-animation-enabled: 1");
expression_should_not_be_parseable("-moz-scrollbar-start-backward: -1");
@@ -678,17 +675,16 @@ function run() {
expression_should_not_be_parseable("-moz-scrollbar-end-backward: -1");
expression_should_not_be_parseable("-moz-scrollbar-end-forward: -1");
expression_should_not_be_parseable("-moz-scrollbar-thumb-proportional: -1");
expression_should_not_be_parseable("-moz-images-in-menus: -1");
expression_should_not_be_parseable("-moz-images-in-buttons: -1");
expression_should_not_be_parseable("-moz-overlay-scrollbars: -1");
expression_should_not_be_parseable("-moz-windows-default-theme: -1");
expression_should_not_be_parseable("-moz-mac-graphite-theme: -1");
- expression_should_not_be_parseable("-moz-mac-lion-theme: -1");
expression_should_not_be_parseable("-moz-mac-yosemite-theme: -1");
expression_should_not_be_parseable("-moz-windows-compositor: -1");
expression_should_not_be_parseable("-moz-windows-classic: -1");
expression_should_not_be_parseable("-moz-windows-glass: -1");
expression_should_not_be_parseable("-moz-touch-enabled: -1");
expression_should_not_be_parseable("-moz-swipe-animation-enabled: -1");
expression_should_not_be_parseable("-moz-scrollbar-start-backward: true");
@@ -696,17 +692,16 @@ function run() {
expression_should_not_be_parseable("-moz-scrollbar-end-backward: true");
expression_should_not_be_parseable("-moz-scrollbar-end-forward: true");
expression_should_not_be_parseable("-moz-scrollbar-thumb-proportional: true");
expression_should_not_be_parseable("-moz-images-in-menus: true");
expression_should_not_be_parseable("-moz-images-in-buttons: true");
expression_should_not_be_parseable("-moz-overlay-scrollbars: true");
expression_should_not_be_parseable("-moz-windows-default-theme: true");
expression_should_not_be_parseable("-moz-mac-graphite-theme: true");
- expression_should_not_be_parseable("-moz-mac-lion-theme: true");
expression_should_not_be_parseable("-moz-mac-yosemite-theme: true");
expression_should_not_be_parseable("-moz-windows-compositor: true");
expression_should_not_be_parseable("-moz-windows-classic: true");
expression_should_not_be_parseable("-moz-windows-glass: true");
expression_should_not_be_parseable("-moz-touch-enabled: true");
expression_should_not_be_parseable("-moz-swipe-animation-enabled: true");
// windows theme media queries
--- a/toolkit/content/aboutSupport.xhtml
+++ b/toolkit/content/aboutSupport.xhtml
@@ -150,17 +150,17 @@
&aboutSupport.appBasicsProfileDir;
#endif
#endif
</th>
<td>
<button id="profile-dir-button">
#ifdef XP_WIN
- &aboutSupport.showWin.label;
+ &aboutSupport.showWin2.label;
#else
#ifdef XP_MACOSX
&aboutSupport.showMac.label;
#else
&aboutSupport.showDir.label;
#endif
#endif
</button>
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
@@ -67,19 +67,19 @@ Windows/Mac use the term "Folder" instea
<!ENTITY aboutSupport.appBasicsSafeMode "Safe Mode">
<!ENTITY aboutSupport.showDir.label "Open Directory">
<!-- LOCALIZATION NOTE (aboutSupport.showMac.label): This is the Mac-specific
variant of aboutSupport.showDir.label. This allows us to use the preferred
"Finder" terminology on Mac. -->
<!ENTITY aboutSupport.showMac.label "Show in Finder">
-<!-- LOCALIZATION NOTE (aboutSupport.showWin.label): This is the Windows-specific
+<!-- LOCALIZATION NOTE (aboutSupport.showWin2.label): This is the Windows-specific
variant of aboutSupport.showDir.label. -->
-<!ENTITY aboutSupport.showWin.label "Show Folder">
+<!ENTITY aboutSupport.showWin2.label "Open Folder">
<!ENTITY aboutSupport.modifiedKeyPrefsTitle "Important Modified Preferences">
<!ENTITY aboutSupport.modifiedPrefsName "Name">
<!ENTITY aboutSupport.modifiedPrefsValue "Value">
<!-- LOCALIZATION NOTE (aboutSupport.userJSTitle, aboutSupport.userJSDescription): user.js is the name of the preference override file being checked. -->
<!ENTITY aboutSupport.userJSTitle "user.js Preferences">
<!ENTITY aboutSupport.userJSDescription "Your profile folder contains a <a id='prefs-user-js-link'>user.js file</a>, which includes preferences that were not created by &brandShortName;.">
--- a/widget/LookAndFeel.h
+++ b/widget/LookAndFeel.h
@@ -286,26 +286,16 @@ public:
* A Boolean value to determine whether the Mac graphite theme is
* being used.
*
* The value of this metric is not used on other platforms. These platforms
* should return NS_ERROR_NOT_IMPLEMENTED when queried for this metric.
*/
eIntID_MacGraphiteTheme,
- /*
- * A Boolean value to determine whether the Mac OS X Lion-specific theming
- * should be used.
- *
- * The value of this metric is not used on non-Mac platforms. These
- * platforms should return NS_ERROR_NOT_IMPLEMENTED when queried for this
- * metric.
- */
- eIntID_MacLionTheme,
-
/*
* A Boolean value to determine whether the Mac OS X Yosemite-specific theming
* should be used.
*
* The value of this metric is not used on non-Mac platforms. These
* platforms should return NS_ERROR_NOT_IMPLEMENTED when queried for this
* metric.
*/
--- a/widget/cocoa/nsLookAndFeel.mm
+++ b/widget/cocoa/nsLookAndFeel.mm
@@ -405,19 +405,16 @@ nsLookAndFeel::GetIntImpl(IntID aID, int
case eIntID_WindowsThemeIdentifier:
case eIntID_OperatingSystemVersionIdentifier:
aResult = 0;
res = NS_ERROR_NOT_IMPLEMENTED;
break;
case eIntID_MacGraphiteTheme:
aResult = [NSColor currentControlTint] == NSGraphiteControlTint;
break;
- case eIntID_MacLionTheme:
- aResult = 1;
- break;
case eIntID_MacYosemiteTheme:
aResult = nsCocoaFeatures::OnYosemiteOrLater();
break;
case eIntID_AlertNotificationOrigin:
aResult = NS_ALERT_TOP;
break;
case eIntID_TabFocusModel:
{
@@ -591,9 +588,9 @@ nsLookAndFeel::RefreshImpl()
{
// We should only clear the cache if we're in the main browser process.
// Otherwise, we should wait for the parent to inform us of new values
// to cache via LookAndFeel::SetIntCache.
if (XRE_IsParentProcess()) {
mUseOverlayScrollbarsCached = false;
mAllowOverlayScrollbarsOverlapCached = false;
}
-}
\ No newline at end of file
+}
--- a/widget/gtk/nsLookAndFeel.cpp
+++ b/widget/gtk/nsLookAndFeel.cpp
@@ -762,17 +762,16 @@ nsLookAndFeel::GetIntImpl(IntID aID, int
aResult = mozilla::widget::WidgetUtils::IsTouchDeviceSupportPresent();
break;
#else
aResult = 0;
res = NS_ERROR_NOT_IMPLEMENTED;
#endif
break;
case eIntID_MacGraphiteTheme:
- case eIntID_MacLionTheme:
aResult = 0;
res = NS_ERROR_NOT_IMPLEMENTED;
break;
case eIntID_AlertNotificationOrigin:
aResult = NS_ALERT_TOP;
break;
case eIntID_IMERawInputUnderlineStyle:
case eIntID_IMEConvertedTextUnderlineStyle:
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -1016,22 +1016,19 @@ void nsBaseWidget::ConfigureAPZControlle
// By default the controller thread is the main thread.
APZThreadUtils::SetControllerThread(MessageLoop::current());
}
void
nsBaseWidget::SetConfirmedTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const
{
- // Need to specifically bind this since it's overloaded.
- void (IAPZCTreeManager::*setTargetApzcFunc)(uint64_t, const nsTArray<ScrollableLayerGuid>&)
- = &IAPZCTreeManager::SetTargetAPZC;
APZThreadUtils::RunOnControllerThread(NewRunnableMethod
<uint64_t, StoreCopyPassByRRef<nsTArray<ScrollableLayerGuid>>>(mAPZC,
- setTargetApzcFunc,
+ &IAPZCTreeManager::SetTargetAPZC,
aInputBlockId, aTargets));
}
void
nsBaseWidget::UpdateZoomConstraints(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const Maybe<ZoomConstraints>& aConstraints)
{
--- a/widget/windows/nsLookAndFeel.cpp
+++ b/widget/windows/nsLookAndFeel.cpp
@@ -408,17 +408,16 @@ nsLookAndFeel::GetIntImpl(IntID aID, int
case eIntID_OperatingSystemVersionIdentifier:
{
aResult = GetOperatingSystemVersion();
break;
}
case eIntID_MacGraphiteTheme:
- case eIntID_MacLionTheme:
aResult = 0;
res = NS_ERROR_NOT_IMPLEMENTED;
break;
case eIntID_DWMCompositor:
aResult = nsUXThemeData::CheckForCompositor();
break;
case eIntID_WindowsGlass:
// Aero Glass is only available prior to Windows 8 when DWM is used.