Merge inbound to central, a=merge

MozReview-Commit-ID: JIAGB82GtAS
This commit is contained in:
Wes Kocher 2016-04-26 14:19:01 -07:00
Родитель c0ae627a40 024f874c4b
Коммит f20e8d0047
143 изменённых файлов: 2940 добавлений и 1827 удалений

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -226,7 +226,11 @@ pref("lightweightThemes.update.enabled", true);
pref("lightweightThemes.getMoreURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes");
pref("lightweightThemes.recommendedThemes", "[{\"id\":\"recommended-1\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/a-web-browser-renaissance/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.header.jpg\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.footer.jpg\",\"textcolor\":\"#000000\",\"accentcolor\":\"#f2d9b1\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.preview.jpg\",\"author\":\"Sean.Martell\",\"version\":\"0\"},{\"id\":\"recommended-2\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/space-fantasy/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.header.jpg\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.footer.jpg\",\"textcolor\":\"#ffffff\",\"accentcolor\":\"#d9d9d9\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.preview.jpg\",\"author\":\"fx5800p\",\"version\":\"1.0\"},{\"id\":\"recommended-3\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/linen-light/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.footer.png\",\"accentcolor\":\"#ada8a8\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.preview.png\",\"author\":\"DVemer\",\"version\":\"1.0\"},{\"id\":\"recommended-4\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/pastel-gradient/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.footer.png\",\"textcolor\":\"#000000\",\"accentcolor\":\"#000000\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.preview.png\",\"author\":\"darrinhenein\",\"version\":\"1.0\"},{\"id\":\"recommended-5\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/carbon-light/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.footer.png\",\"textcolor\":\"#3b3b3b\",\"accentcolor\":\"#2e2e2e\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.preview.jpg\",\"author\":\"Jaxivo\",\"version\":\"1.0\"}]");
#if defined(MOZ_ADOBE_EME) || defined(MOZ_WIDEVINE_EME)
pref("browser.eme.ui.enabled", true);
#else
pref("browser.eme.ui.enabled", false);
#endif
// UI tour experience.
pref("browser.uitour.enabled", true);
@ -1378,10 +1382,6 @@ pref("media.gmp.decoder.h264", 2);
// decode H.264.
pref("media.gmp.trial-create.enabled", true);
#if defined(MOZ_ADOBE_EME) || defined(MOZ_WIDEVINE_EME)
pref("browser.eme.ui.enabled", true);
#endif
#ifdef MOZ_ADOBE_EME
pref("media.gmp-eme-adobe.enabled", true);
#endif

Просмотреть файл

@ -18,7 +18,7 @@
let meNode, msNode, mdNode;
navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia;
navigator.getUserMedia({ audio: true }, stream => {
navigator.getUserMedia({ audio: true, fake: true }, stream => {
meNode = ctx.createMediaElementSource(audio);
msNode = ctx.createMediaStreamSource(stream);
mdNode = ctx.createMediaStreamDestination();

Просмотреть файл

@ -13232,7 +13232,7 @@ nsDocShell::SetBaseUrlForWyciwyg(nsIContentViewer* aContentViewer)
if (baseURI) {
nsIDocument* document = aContentViewer->GetDocument();
if (document) {
rv = document->SetBaseURI(baseURI);
document->SetBaseURI(baseURI);
}
}
return rv;

Просмотреть файл

@ -3574,11 +3574,11 @@ nsIDocument::GetBaseURI(bool aTryUseXHRDocBaseURI) const
return uri.forget();
}
nsresult
void
nsDocument::SetBaseURI(nsIURI* aURI)
{
if (!aURI && !mDocumentBaseURI) {
return NS_OK;
return;
}
// Don't do anything if the URI wasn't actually changed.
@ -3586,25 +3586,7 @@ nsDocument::SetBaseURI(nsIURI* aURI)
bool equalBases = false;
mDocumentBaseURI->Equals(aURI, &equalBases);
if (equalBases) {
return NS_OK;
}
}
// Check if CSP allows this base-uri
nsCOMPtr<nsIContentSecurityPolicy> csp;
nsresult rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp && aURI) {
bool permitsBaseURI = false;
// base-uri is only enforced if explicitly defined in the
// policy - do *not* consult default-src, see:
// http://www.w3.org/TR/CSP2/#directive-default-src
rv = csp->Permits(aURI, nsIContentSecurityPolicy::BASE_URI_DIRECTIVE,
true, &permitsBaseURI);
NS_ENSURE_SUCCESS(rv, rv);
if (!permitsBaseURI) {
return NS_OK;
return;
}
}
@ -3614,8 +3596,6 @@ nsDocument::SetBaseURI(nsIURI* aURI)
mDocumentBaseURI = nullptr;
}
RefreshLinkHrefs();
return NS_OK;
}
void

Просмотреть файл

@ -735,7 +735,7 @@ public:
*/
virtual void SetContentType(const nsAString& aContentType) override;
virtual nsresult SetBaseURI(nsIURI* aURI) override;
virtual void SetBaseURI(nsIURI* aURI) override;
/**
* Get/Set the base target of a link in a document.

Просмотреть файл

@ -32,6 +32,7 @@
#include "nsBindingManager.h"
#include "nsCCUncollectableMarker.h"
#include "mozAutoDocUpdate.h"
#include "nsTextNode.h"
#include "PLDHashTable.h"
#include "mozilla/Snprintf.h"

Просмотреть файл

@ -9356,7 +9356,7 @@ nsGlobalWindow::AddEventListener(const nsAString& aType,
void
nsGlobalWindow::AddEventListener(const nsAString& aType,
EventListener* aListener,
bool aUseCapture,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
@ -9378,7 +9378,8 @@ nsGlobalWindow::AddEventListener(const nsAString& aType,
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
manager->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
manager->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
}
NS_IMETHODIMP

Просмотреть файл

@ -402,7 +402,7 @@ public:
using mozilla::dom::EventTarget::RemoveEventListener;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,
bool aUseCapture,
const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
const mozilla::dom::Nullable<bool>& aWantsUntrusted,
mozilla::ErrorResult& aRv) override;
virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;

Просмотреть файл

@ -388,7 +388,7 @@ public:
}
virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
virtual nsresult SetBaseURI(nsIURI* aURI) = 0;
virtual void SetBaseURI(nsIURI* aURI) = 0;
/**
* Get/Set the base target of a link in a document.

Просмотреть файл

@ -1178,7 +1178,7 @@ nsINode::AddEventListener(const nsAString& aType,
void
nsINode::AddEventListener(const nsAString& aType,
EventListener* aListener,
bool aUseCapture,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
@ -1194,7 +1194,8 @@ nsINode::AddEventListener(const nsAString& aType,
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
listener_manager->AddEventListener(aType, aListener, aUseCapture,
listener_manager->AddEventListener(aType, aListener, aOptions,
wantsUntrusted);
}

Просмотреть файл

@ -938,7 +938,7 @@ public:
using nsIDOMEventTarget::AddEventListener;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,
bool aUseCapture,
const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
const mozilla::dom::Nullable<bool>& aWantsUntrusted,
mozilla::ErrorResult& aRv) override;
using nsIDOMEventTarget::AddSystemEventListener;

Просмотреть файл

@ -117,7 +117,7 @@ nsWindowRoot::AddEventListener(const nsAString& aType,
void
nsWindowRoot::AddEventListener(const nsAString& aType,
EventListener* aListener,
bool aUseCapture,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
@ -127,7 +127,7 @@ nsWindowRoot::AddEventListener(const nsAString& aType,
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
elm->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
}
@ -287,7 +287,7 @@ nsWindowRoot::GetControllerForCommand(const char * aCommand,
nsGlobalWindow *win = nsGlobalWindow::Cast(focusedWindow);
focusedWindow = win->GetPrivateParent();
}
return NS_OK;
}

Просмотреть файл

@ -35,7 +35,7 @@ public:
using mozilla::dom::EventTarget::RemoveEventListener;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,
bool aUseCapture,
const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
const mozilla::dom::Nullable<bool>& aWantsUntrusted,
mozilla::ErrorResult& aRv) override;

Просмотреть файл

@ -593,11 +593,11 @@ BroadcastChannel::SetOnmessage(EventHandlerNonNull* aCallback)
void
BroadcastChannel::AddEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
const AddEventListenerOptionsOrBoolean& aOptions,
const dom::Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
DOMEventTargetHelper::AddEventListener(aType, aCallback, aCapture,
DOMEventTargetHelper::AddEventListener(aType, aCallback, aOptions,
aWantsUntrusted, aRv);
if (aRv.Failed()) {
@ -610,10 +610,10 @@ BroadcastChannel::AddEventListener(const nsAString& aType,
void
BroadcastChannel::RemoveEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
const EventListenerOptionsOrBoolean& aOptions,
ErrorResult& aRv)
{
DOMEventTargetHelper::RemoveEventListener(aType, aCallback, aCapture, aRv);
DOMEventTargetHelper::RemoveEventListener(aType, aCallback, aOptions, aRv);
if (aRv.Failed()) {
return;

Просмотреть файл

@ -74,12 +74,12 @@ public:
virtual void AddEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv) override;
virtual void RemoveEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
const EventListenerOptionsOrBoolean& aOptions,
ErrorResult& aRv) override;
void Shutdown();

Просмотреть файл

@ -1616,18 +1616,16 @@ CanvasRenderingContext2D::ReturnTarget()
}
NS_IMETHODIMP
CanvasRenderingContext2D::InitializeWithSurface(nsIDocShell* aShell,
gfxASurface* aSurface,
int32_t aWidth,
int32_t aHeight)
CanvasRenderingContext2D::InitializeWithDrawTarget(nsIDocShell* aShell,
gfx::DrawTarget* aTarget)
{
RemovePostRefreshObserver();
mDocShell = aShell;
AddPostRefreshObserverIfNecessary();
SetDimensions(aWidth, aHeight);
mTarget = gfxPlatform::GetPlatform()->
CreateDrawTargetForSurface(aSurface, IntSize(aWidth, aHeight));
IntSize size = aTarget->GetSize();
SetDimensions(size.width, size.height);
mTarget = aTarget;
if (!mTarget) {
EnsureErrorTarget();

Просмотреть файл

@ -443,7 +443,8 @@ public:
return nullptr;
}
NS_IMETHOD SetDimensions(int32_t aWidth, int32_t aHeight) override;
NS_IMETHOD InitializeWithSurface(nsIDocShell* aShell, gfxASurface* aSurface, int32_t aWidth, int32_t aHeight) override;
NS_IMETHOD InitializeWithDrawTarget(nsIDocShell* aShell,
gfx::DrawTarget* aTarget) override;
NS_IMETHOD GetInputStream(const char* aMimeType,
const char16_t* aEncoderOptions,

Просмотреть файл

@ -82,10 +82,8 @@ ImageBitmapRenderingContext::SetDimensions(int32_t aWidth, int32_t aHeight)
}
NS_IMETHODIMP
ImageBitmapRenderingContext::InitializeWithSurface(nsIDocShell* aDocShell,
gfxASurface* aSurface,
int32_t aWidth,
int32_t aHeight)
ImageBitmapRenderingContext::InitializeWithDrawTarget(nsIDocShell* aDocShell,
gfx::DrawTarget* aTarget)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

Просмотреть файл

@ -12,6 +12,7 @@ namespace mozilla {
namespace gfx {
class DataSourceSurface;
class DrawTarget;
class SourceSurface;
}
@ -53,10 +54,8 @@ public:
NS_IMETHOD SetDimensions(int32_t aWidth, int32_t aHeight) override;
NS_IMETHOD InitializeWithSurface(nsIDocShell* aDocShell,
gfxASurface* aSurface,
int32_t aWidth,
int32_t aHeight) override;
NS_IMETHOD InitializeWithDrawTarget(nsIDocShell* aDocShell,
gfx::DrawTarget* aTarget) override;
virtual mozilla::UniquePtr<uint8_t[]> GetImageBuffer(int32_t* aFormat) override;
NS_IMETHOD GetInputStream(const char* aMimeType,

Просмотреть файл

@ -240,8 +240,7 @@ public:
virtual int32_t GetHeight() const override;
NS_IMETHOD SetDimensions(int32_t width, int32_t height) override;
NS_IMETHOD InitializeWithSurface(nsIDocShell*, gfxASurface*, int32_t,
int32_t) override
NS_IMETHOD InitializeWithDrawTarget(nsIDocShell*, gfx::DrawTarget*) override
{
return NS_ERROR_NOT_IMPLEMENTED;
}

Просмотреть файл

@ -96,7 +96,10 @@ public:
// whenever the size of the element changes.
NS_IMETHOD SetDimensions(int32_t width, int32_t height) = 0;
NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, int32_t width, int32_t height) = 0;
// Initializes with an nsIDocShell and DrawTarget. The size is taken from the
// DrawTarget.
NS_IMETHOD InitializeWithDrawTarget(nsIDocShell *aDocShell,
mozilla::gfx::DrawTarget* aTarget) = 0;
// Creates an image buffer. Returns null on failure.
virtual mozilla::UniquePtr<uint8_t[]> GetImageBuffer(int32_t* format) = 0;

Просмотреть файл

@ -222,7 +222,7 @@ DOMEventTargetHelper::AddEventListener(const nsAString& aType,
void
DOMEventTargetHelper::AddEventListener(const nsAString& aType,
EventListener* aListener,
bool aUseCapture,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
@ -242,7 +242,8 @@ DOMEventTargetHelper::AddEventListener(const nsAString& aType,
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
elm->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
}
NS_IMETHODIMP

Просмотреть файл

@ -72,7 +72,7 @@ public:
using dom::EventTarget::RemoveEventListener;
virtual void AddEventListener(const nsAString& aType,
dom::EventListener* aListener,
bool aCapture,
const dom::AddEventListenerOptionsOrBoolean& aOptions,
const dom::Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv) override;

Просмотреть файл

@ -25,6 +25,7 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/EventTargetBinding.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/EventTimelineMarker.h"
@ -1332,6 +1333,21 @@ EventListenerManager::AddEventListener(
return AddEventListenerByType(aListenerHolder, aType, flags);
}
void
EventListenerManager::AddEventListener(
const nsAString& aType,
const EventListenerHolder& aListenerHolder,
const dom::AddEventListenerOptionsOrBoolean& aOptions,
bool aWantsUntrusted)
{
EventListenerFlags flags;
flags.mCapture =
aOptions.IsBoolean() ? aOptions.GetAsBoolean()
: aOptions.GetAsAddEventListenerOptions().mCapture;
flags.mAllowUntrustedEvents = aWantsUntrusted;
return AddEventListenerByType(aListenerHolder, aType, flags);
}
void
EventListenerManager::RemoveEventListener(
const nsAString& aType,
@ -1343,6 +1359,19 @@ EventListenerManager::RemoveEventListener(
RemoveEventListenerByType(aListenerHolder, aType, flags);
}
void
EventListenerManager::RemoveEventListener(
const nsAString& aType,
const EventListenerHolder& aListenerHolder,
const dom::EventListenerOptionsOrBoolean& aOptions)
{
EventListenerFlags flags;
flags.mCapture =
aOptions.IsBoolean() ? aOptions.GetAsBoolean()
: aOptions.GetAsEventListenerOptions().mCapture;
RemoveEventListenerByType(aListenerHolder, aType, flags);
}
void
EventListenerManager::AddListenerForAllEvents(nsIDOMEventListener* aDOMListener,
bool aUseCapture,

Просмотреть файл

@ -248,11 +248,11 @@ public:
}
void AddEventListener(const nsAString& aType,
dom::EventListener* aListener,
bool aUseCapture,
const dom::AddEventListenerOptionsOrBoolean& aOptions,
bool aWantsUntrusted)
{
EventListenerHolder holder(aListener);
AddEventListener(aType, holder, aUseCapture, aWantsUntrusted);
AddEventListener(aType, holder, aOptions, aWantsUntrusted);
}
void RemoveEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
@ -263,10 +263,10 @@ public:
}
void RemoveEventListener(const nsAString& aType,
dom::EventListener* aListener,
bool aUseCapture)
const dom::EventListenerOptionsOrBoolean& aOptions)
{
EventListenerHolder holder(aListener);
RemoveEventListener(aType, holder, aUseCapture);
RemoveEventListener(aType, holder, aOptions);
}
void AddListenerForAllEvents(nsIDOMEventListener* aListener,
@ -553,10 +553,17 @@ protected:
const TypedEventHandler* GetTypedEventHandler(nsIAtom* aEventName,
const nsAString& aTypeString);
void AddEventListener(const nsAString& aType,
const EventListenerHolder& aListener,
const dom::AddEventListenerOptionsOrBoolean& aOptions,
bool aWantsUntrusted);
void AddEventListener(const nsAString& aType,
const EventListenerHolder& aListener,
bool aUseCapture,
bool aWantsUntrusted);
void RemoveEventListener(const nsAString& aType,
const EventListenerHolder& aListener,
const dom::EventListenerOptionsOrBoolean& aOptions);
void RemoveEventListener(const nsAString& aType,
const EventListenerHolder& aListener,
bool aUseCapture);

Просмотреть файл

@ -6,6 +6,7 @@
#include "mozilla/EventListenerManager.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/EventTargetBinding.h"
#include "nsThreadUtils.h"
namespace mozilla {
@ -14,12 +15,12 @@ namespace dom {
void
EventTarget::RemoveEventListener(const nsAString& aType,
EventListener* aListener,
bool aUseCapture,
const EventListenerOptionsOrBoolean& aOptions,
ErrorResult& aRv)
{
EventListenerManager* elm = GetExistingListenerManager();
if (elm) {
elm->RemoveEventListener(aType, aListener, aUseCapture);
elm->RemoveEventListener(aType, aListener, aOptions);
}
}

Просмотреть файл

@ -21,9 +21,12 @@ class EventListenerManager;
namespace dom {
class AddEventListenerOptionsOrBoolean;
class Event;
class EventListener;
class EventListenerOptionsOrBoolean;
class EventHandlerNonNull;
template <class T> struct Nullable;
// IID for the dom::EventTarget interface
@ -43,12 +46,12 @@ public:
using nsIDOMEventTarget::DispatchEvent;
virtual void AddEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv) = 0;
virtual void RemoveEventListener(const nsAString& aType,
EventListener* aCallback,
bool aCapture,
const EventListenerOptionsOrBoolean& aOptions,
ErrorResult& aRv);
bool DispatchEvent(JSContext* aCx, Event& aEvent, ErrorResult& aRv);

Просмотреть файл

@ -2039,7 +2039,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
OutputMediaStream* out = mOutputStreams.AppendElement();
MediaStreamTrackSourceGetter* getter = new CaptureStreamTrackSourceGetter(this);
out->mStream = DOMMediaStream::CreateTrackUnionStream(window, aGraph, getter);
out->mStream = DOMMediaStream::CreateTrackUnionStreamAsInput(window, aGraph, getter);
out->mFinishWhenEnded = aFinishWhenEnded;
mAudioCaptured = true;
@ -3933,16 +3933,16 @@ HTMLMediaElement::UpdateReadyStateInternal()
}
if (mSrcStream && mReadyState < nsIDOMHTMLMediaElement::HAVE_METADATA) {
bool hasAudio = !AudioTracks()->IsEmpty();
bool hasVideo = !VideoTracks()->IsEmpty();
bool hasAudioTracks = !AudioTracks()->IsEmpty();
bool hasVideoTracks = !VideoTracks()->IsEmpty();
if (!hasAudio && !hasVideo) {
if (!hasAudioTracks && !hasVideoTracks) {
LOG(LogLevel::Debug, ("MediaElement %p UpdateReadyStateInternal() "
"Stream with no tracks", this));
return;
}
if (IsVideo() && hasVideo && !HasVideo()) {
if (IsVideo() && hasVideoTracks && !HasVideo()) {
LOG(LogLevel::Debug, ("MediaElement %p UpdateReadyStateInternal() "
"Stream waiting for video", this));
return;
@ -3956,10 +3956,10 @@ HTMLMediaElement::UpdateReadyStateInternal()
// We are playing a stream that has video and a video frame is now set.
// This means we have all metadata needed to change ready state.
MediaInfo mediaInfo = mMediaInfo;
if (hasAudio) {
if (hasAudioTracks) {
mediaInfo.EnableAudio();
}
if (hasVideo) {
if (hasVideoTracks) {
mediaInfo.EnableVideo();
}
MetadataLoaded(&mediaInfo, nsAutoPtr<const MetadataTags>(nullptr));

Просмотреть файл

@ -17,6 +17,7 @@
#include "nsRuleData.h"
#include "nsMappedAttributes.h"
#include "nsContentUtils.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIURI.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Shared)
@ -176,12 +177,28 @@ SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch)
getter_AddRefs(newBaseURI), href, aDocument,
aDocument->GetFallbackBaseURI());
// Try to set our base URI. If that fails, try to set base URI to null
nsresult rv = aDocument->SetBaseURI(newBaseURI);
aDocument->SetChromeXHRDocBaseURI(nullptr);
// Check if CSP allows this base-uri
nsCOMPtr<nsIContentSecurityPolicy> csp;
nsresult rv = aDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ASSERTION(NS_SUCCEEDED(rv), "Getting CSP Failed");
// For all the different error cases we assign a nullptr to
// newBaseURI, so we basically call aDocument->SetBaseURI(nullptr);
if (NS_FAILED(rv)) {
aDocument->SetBaseURI(nullptr);
newBaseURI = nullptr;
}
if (csp && newBaseURI) {
// base-uri is only enforced if explicitly defined in the
// policy - do *not* consult default-src, see:
// http://www.w3.org/TR/CSP2/#directive-default-src
bool cspPermitsBaseURI = true;
rv = csp->Permits(newBaseURI, nsIContentSecurityPolicy::BASE_URI_DIRECTIVE,
true, &cspPermitsBaseURI);
if (NS_FAILED(rv) || !cspPermitsBaseURI) {
newBaseURI = nullptr;
}
}
aDocument->SetBaseURI(newBaseURI);
aDocument->SetChromeXHRDocBaseURI(nullptr);
return;
}
}

Просмотреть файл

@ -64,7 +64,7 @@ InputPort::Init(nsIInputPortData* aData, nsIInputPortListener* aListener, ErrorR
MediaStreamGraph* graph =
MediaStreamGraph::GetInstance(MediaStreamGraph::SYSTEM_THREAD_DRIVER,
AudioChannel::Normal);
mStream = DOMMediaStream::CreateSourceStream(GetOwner(), graph);
mStream = DOMMediaStream::CreateSourceStreamAsInput(GetOwner(), graph);
}
void

Просмотреть файл

@ -71,7 +71,7 @@ AudioCaptureStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
}
uint32_t inputCount = mInputs.Length();
StreamBuffer::Track* track = EnsureTrack(mTrackId);
StreamTracks::Track* track = EnsureTrack(mTrackId);
// Notify the DOM everything is in order.
if (!mTrackCreated) {
for (uint32_t i = 0; i < mListeners.Length(); i++) {
@ -101,7 +101,7 @@ AudioCaptureStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
AudioSegment output;
for (uint32_t i = 0; i < inputCount; i++) {
MediaStream* s = mInputs[i]->GetSource();
StreamBuffer::TrackIter tracks(s->GetStreamBuffer(), MediaSegment::AUDIO);
StreamTracks::TrackIter tracks(s->GetStreamTracks(), MediaSegment::AUDIO);
while (!tracks.IsEnded()) {
AudioSegment* inputSegment = tracks->Get<AudioSegment>();
StreamTime inputStart = s->GraphTimeToStreamTimeWithBlocking(aFrom);
@ -121,7 +121,7 @@ AudioCaptureStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
}
// Regardless of the status of the input tracks, we go foward.
mBuffer.AdvanceKnownTracksTime(GraphTimeToStreamTimeWithBlocking((aTo)));
mTracks.AdvanceKnownTracksTime(GraphTimeToStreamTimeWithBlocking((aTo)));
}
void

Просмотреть файл

@ -8,7 +8,7 @@
#include "MediaStreamGraph.h"
#include "AudioMixer.h"
#include "StreamBuffer.h"
#include "StreamTracks.h"
#include <algorithm>
namespace mozilla

Просмотреть файл

@ -8,7 +8,7 @@
#include "DOMMediaStream.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "StreamBuffer.h"
#include "StreamTracks.h"
class nsIPrincipal;

Просмотреть файл

@ -71,9 +71,8 @@ DOMMediaStream::TrackPort::~TrackPort()
{
MOZ_COUNT_DTOR(TrackPort);
if (mOwnership == InputPortOwnership::OWNED && mInputPort) {
mInputPort->Destroy();
mInputPort = nullptr;
if (mOwnership == InputPortOwnership::OWNED) {
DestroyInputPort();
}
}
@ -853,9 +852,9 @@ DOMMediaStream::InitPlaybackStreamCommon(MediaStreamGraph* aGraph)
}
already_AddRefed<DOMMediaStream>
DOMMediaStream::CreateSourceStream(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
DOMMediaStream::CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
{
RefPtr<DOMMediaStream> stream = new DOMMediaStream(aWindow, aTrackSourceGetter);
stream->InitSourceStream(aGraph);
@ -863,9 +862,9 @@ DOMMediaStream::CreateSourceStream(nsPIDOMWindowInner* aWindow,
}
already_AddRefed<DOMMediaStream>
DOMMediaStream::CreateTrackUnionStream(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
DOMMediaStream::CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
{
RefPtr<DOMMediaStream> stream = new DOMMediaStream(aWindow, aTrackSourceGetter);
stream->InitTrackUnionStream(aGraph);
@ -873,9 +872,9 @@ DOMMediaStream::CreateTrackUnionStream(nsPIDOMWindowInner* aWindow,
}
already_AddRefed<DOMMediaStream>
DOMMediaStream::CreateAudioCaptureStream(nsPIDOMWindowInner* aWindow,
nsIPrincipal* aPrincipal,
MediaStreamGraph* aGraph)
DOMMediaStream::CreateAudioCaptureStreamAsInput(nsPIDOMWindowInner* aWindow,
nsIPrincipal* aPrincipal,
MediaStreamGraph* aGraph)
{
// Audio capture doesn't create tracks dynamically
MediaStreamTrackSourceGetter* getter = nullptr;
@ -1300,9 +1299,9 @@ DOMLocalMediaStream::StopImpl()
}
already_AddRefed<DOMLocalMediaStream>
DOMLocalMediaStream::CreateSourceStream(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
DOMLocalMediaStream::CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
{
RefPtr<DOMLocalMediaStream> stream =
new DOMLocalMediaStream(aWindow, aTrackSourceGetter);
@ -1311,9 +1310,9 @@ DOMLocalMediaStream::CreateSourceStream(nsPIDOMWindowInner* aWindow,
}
already_AddRefed<DOMLocalMediaStream>
DOMLocalMediaStream::CreateTrackUnionStream(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
DOMLocalMediaStream::CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
{
RefPtr<DOMLocalMediaStream> stream =
new DOMLocalMediaStream(aWindow, aTrackSourceGetter);
@ -1332,9 +1331,9 @@ DOMAudioNodeMediaStream::~DOMAudioNodeMediaStream()
}
already_AddRefed<DOMAudioNodeMediaStream>
DOMAudioNodeMediaStream::CreateTrackUnionStream(nsPIDOMWindowInner* aWindow,
AudioNode* aNode,
MediaStreamGraph* aGraph)
DOMAudioNodeMediaStream::CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow,
AudioNode* aNode,
MediaStreamGraph* aGraph)
{
RefPtr<DOMAudioNodeMediaStream> stream = new DOMAudioNodeMediaStream(aWindow, aNode);
stream->InitTrackUnionStream(aGraph);
@ -1443,7 +1442,7 @@ DOMHwMediaStream::SetImageSize(uint32_t width, uint32_t height)
#endif
SourceMediaStream* srcStream = GetInputStream()->AsSourceStream();
StreamBuffer::Track* track = srcStream->FindTrack(TRACK_VIDEO_PRIMARY);
StreamTracks::Track* track = srcStream->FindTrack(TRACK_VIDEO_PRIMARY);
if (!track || !track->GetSegment()) {
return;
@ -1479,7 +1478,7 @@ DOMHwMediaStream::SetOverlayImage(OverlayImage* aImage)
#endif
SourceMediaStream* srcStream = GetInputStream()->AsSourceStream();
StreamBuffer::Track* track = srcStream->FindTrack(TRACK_VIDEO_PRIMARY);
StreamTracks::Track* track = srcStream->FindTrack(TRACK_VIDEO_PRIMARY);
if (!track || !track->GetSegment()) {
return;

Просмотреть файл

@ -10,7 +10,7 @@
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "StreamBuffer.h"
#include "StreamTracks.h"
#include "nsIDOMWindow.h"
#include "nsIPrincipal.h"
#include "mozilla/DOMEventTargetHelper.h"
@ -484,25 +484,25 @@ public:
/**
* Create a DOMMediaStream whose underlying input stream is a SourceMediaStream.
*/
static already_AddRefed<DOMMediaStream> CreateSourceStream(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
static already_AddRefed<DOMMediaStream> CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
/**
* Create a DOMMediaStream whose underlying input stream is a TrackUnionStream.
*/
static already_AddRefed<DOMMediaStream> CreateTrackUnionStream(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
static already_AddRefed<DOMMediaStream> CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
/**
* Create an DOMMediaStream whose underlying input stream is an
* AudioCaptureStream.
*/
static already_AddRefed<DOMMediaStream>
CreateAudioCaptureStream(nsPIDOMWindowInner* aWindow,
nsIPrincipal* aPrincipal,
MediaStreamGraph* aGraph);
CreateAudioCaptureStreamAsInput(nsPIDOMWindowInner* aWindow,
nsIPrincipal* aPrincipal,
MediaStreamGraph* aGraph);
void SetLogicalStreamStartTime(StreamTime aTime)
{
@ -719,17 +719,17 @@ public:
* Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
*/
static already_AddRefed<DOMLocalMediaStream>
CreateSourceStream(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
/**
* Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream.
*/
static already_AddRefed<DOMLocalMediaStream>
CreateTrackUnionStream(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
protected:
virtual ~DOMLocalMediaStream();
@ -753,9 +753,9 @@ public:
* Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream.
*/
static already_AddRefed<DOMAudioNodeMediaStream>
CreateTrackUnionStream(nsPIDOMWindowInner* aWindow,
AudioNode* aNode,
MediaStreamGraph* aGraph);
CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow,
AudioNode* aNode,
MediaStreamGraph* aGraph);
protected:
~DOMAudioNodeMediaStream();

Просмотреть файл

@ -14,7 +14,7 @@
#include "nsTArray.h"
#include "ImageTypes.h"
#include "MediaData.h"
#include "StreamBuffer.h" // for TrackID
#include "StreamTracks.h" // for TrackID
#include "TimeUnits.h"
namespace mozilla {

Просмотреть файл

@ -833,7 +833,7 @@ public:
// not a problem here, we got explicit user content.
nsCOMPtr<nsIPrincipal> principal = window->GetExtantDoc()->NodePrincipal();
domStream =
DOMMediaStream::CreateAudioCaptureStream(window, principal, msg);
DOMMediaStream::CreateAudioCaptureStreamAsInput(window, principal, msg);
stream = msg->CreateSourceStream(nullptr); // Placeholder
msg->RegisterCaptureStreamForWindow(
@ -919,8 +919,8 @@ public:
// avoid us blocking. Pass a simple TrackSourceGetter for potential
// fake tracks. Apart from them gUM never adds tracks dynamically.
domStream =
DOMLocalMediaStream::CreateSourceStream(window, msg,
new FakeTrackSourceGetter(principal));
DOMLocalMediaStream::CreateSourceStreamAsInput(window, msg,
new FakeTrackSourceGetter(principal));
if (mAudioDevice) {
nsString audioDeviceName;

Просмотреть файл

@ -45,7 +45,7 @@ typedef int64_t MediaTime;
const int64_t MEDIA_TIME_MAX = TRACK_TICKS_MAX;
/**
* Media time relative to the start of a StreamBuffer.
* Media time relative to the start of a StreamTracks.
*/
typedef MediaTime StreamTime;
const StreamTime STREAM_TIME_MAX = MEDIA_TIME_MAX;

Просмотреть файл

@ -81,7 +81,7 @@ MediaStreamGraphImpl::FinishStream(MediaStream* aStream)
return;
STREAM_LOG(LogLevel::Debug, ("MediaStream %p will finish", aStream));
#ifdef DEBUG
for (StreamBuffer::TrackIter track(aStream->mBuffer);
for (StreamTracks::TrackIter track(aStream->mTracks);
!track.IsEnded(); track.Next()) {
if (!track->IsEnded()) {
STREAM_LOG(LogLevel::Error,
@ -92,7 +92,7 @@ MediaStreamGraphImpl::FinishStream(MediaStream* aStream)
}
#endif
aStream->mFinished = true;
aStream->mBuffer.AdvanceKnownTracksTime(STREAM_TIME_MAX);
aStream->mTracks.AdvanceKnownTracksTime(STREAM_TIME_MAX);
SetStreamOrderDirty();
}
@ -100,7 +100,7 @@ MediaStreamGraphImpl::FinishStream(MediaStream* aStream)
void
MediaStreamGraphImpl::AddStreamGraphThread(MediaStream* aStream)
{
aStream->mBufferStartTime = mProcessedTime;
aStream->mTracksStartTime = mProcessedTime;
if (aStream->IsSuspended()) {
mSuspendedStreams.AppendElement(aStream);
STREAM_LOG(LogLevel::Debug, ("Adding media stream %p to the graph, in the suspended stream array", aStream));
@ -160,14 +160,14 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
StreamTime t = aStream->GraphTimeToStreamTime(aDesiredUpToTime);
STREAM_LOG(LogLevel::Verbose, ("Calling NotifyPull aStream=%p t=%f current end=%f", aStream,
MediaTimeToSeconds(t),
MediaTimeToSeconds(aStream->mBuffer.GetEnd())));
if (t > aStream->mBuffer.GetEnd()) {
MediaTimeToSeconds(aStream->mTracks.GetEnd())));
if (t > aStream->mTracks.GetEnd()) {
*aEnsureNextIteration = true;
#ifdef DEBUG
if (aStream->mListeners.Length() == 0) {
STREAM_LOG(LogLevel::Error, ("No listeners in NotifyPull aStream=%p desired=%f current end=%f",
aStream, MediaTimeToSeconds(t),
MediaTimeToSeconds(aStream->mBuffer.GetEnd())));
MediaTimeToSeconds(aStream->mTracks.GetEnd())));
aStream->DumpTrackInfo();
}
#endif
@ -181,12 +181,12 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
}
}
finished = aStream->mUpdateFinished;
bool notifiedTrackCreated = false;
bool shouldNotifyTrackCreated = false;
for (int32_t i = aStream->mUpdateTracks.Length() - 1; i >= 0; --i) {
SourceMediaStream::TrackData* data = &aStream->mUpdateTracks[i];
aStream->ApplyTrackDisabling(data->mID, data->mData);
StreamTime offset = (data->mCommands & SourceMediaStream::TRACK_CREATE)
? data->mStart : aStream->mBuffer.FindTrack(data->mID)->GetSegment()->GetDuration();
? data->mStart : aStream->mTracks.FindTrack(data->mID)->GetSegment()->GetDuration();
for (MediaStreamListener* l : aStream->mListeners) {
l->NotifyQueuedTrackChanges(this, data->mID,
offset, data->mCommands, *data->mData);
@ -207,14 +207,14 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
int64_t(segment->GetDuration())));
data->mEndOfFlushedData += segment->GetDuration();
aStream->mBuffer.AddTrack(data->mID, data->mStart, segment);
aStream->mTracks.AddTrack(data->mID, data->mStart, segment);
// The track has taken ownership of data->mData, so let's replace
// data->mData with an empty clone.
data->mData = segment->CreateEmptyClone();
data->mCommands &= ~SourceMediaStream::TRACK_CREATE;
notifiedTrackCreated = true;
shouldNotifyTrackCreated = true;
} else if (data->mData->GetDuration() > 0) {
MediaSegment* dest = aStream->mBuffer.FindTrack(data->mID)->GetSegment();
MediaSegment* dest = aStream->mTracks.FindTrack(data->mID)->GetSegment();
STREAM_LOG(LogLevel::Verbose, ("SourceMediaStream %p track %d, advancing end from %lld to %lld",
aStream, data->mID,
int64_t(dest->GetDuration()),
@ -223,20 +223,20 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
dest->AppendFrom(data->mData);
}
if (data->mCommands & SourceMediaStream::TRACK_END) {
aStream->mBuffer.FindTrack(data->mID)->SetEnded();
aStream->mTracks.FindTrack(data->mID)->SetEnded();
aStream->mUpdateTracks.RemoveElementAt(i);
}
}
if (notifiedTrackCreated) {
if (shouldNotifyTrackCreated) {
for (MediaStreamListener* l : aStream->mListeners) {
l->NotifyFinishedTrackCreation(this);
}
}
if (!aStream->mFinished) {
aStream->mBuffer.AdvanceKnownTracksTime(aStream->mUpdateKnownTracksTime);
aStream->mTracks.AdvanceKnownTracksTime(aStream->mUpdateKnownTracksTime);
}
}
if (aStream->mBuffer.GetEnd() > 0) {
if (aStream->mTracks.GetEnd() > 0) {
aStream->mHasCurrentData = true;
}
if (finished) {
@ -251,7 +251,7 @@ MediaStreamGraphImpl::GraphTimeToStreamTimeWithBlocking(MediaStream* aStream,
MOZ_ASSERT(aTime <= mStateComputedTime,
"Don't ask about times where we haven't made blocking decisions yet");
return std::max<StreamTime>(0,
std::min(aTime, aStream->mStartBlocking) - aStream->mBufferStartTime);
std::min(aTime, aStream->mStartBlocking) - aStream->mTracksStartTime);
}
GraphTime
@ -274,7 +274,7 @@ MediaStreamGraphImpl::UpdateCurrentTimeForStreams(GraphTime aPrevCurrentTime)
blockedTime);
STREAM_LOG(LogLevel::Verbose,
("MediaStream %p bufferStartTime=%f blockedTime=%f", stream,
MediaTimeToSeconds(stream->mBufferStartTime),
MediaTimeToSeconds(stream->mTracksStartTime),
MediaTimeToSeconds(blockedTime)));
stream->mStartBlocking = mStateComputedTime;
@ -306,7 +306,7 @@ MediaStreamGraphImpl::UpdateCurrentTimeForStreams(GraphTime aPrevCurrentTime)
// out.
if (stream->mFinished && !stream->mNotifiedFinished &&
mProcessedTime >=
stream->StreamTimeToGraphTime(stream->GetStreamBuffer().GetAllTracksEnd())) {
stream->StreamTimeToGraphTime(stream->GetStreamTracks().GetAllTracksEnd())) {
stream->mNotifiedFinished = true;
SetStreamOrderDirty();
for (uint32_t j = 0; j < stream->mListeners.Length(); ++j) {
@ -362,7 +362,7 @@ MediaStreamGraphImpl::ProcessChunkMetadata(GraphTime aPrevCurrentTime)
for (MediaStream* stream : AllStreams()) {
StreamTime iterationStart = stream->GraphTimeToStreamTime(aPrevCurrentTime);
StreamTime iterationEnd = stream->GraphTimeToStreamTime(mProcessedTime);
for (StreamBuffer::TrackIter tracks(stream->mBuffer);
for (StreamTracks::TrackIter tracks(stream->mTracks);
!tracks.IsEnded(); tracks.Next()) {
MediaSegment* segment = tracks->GetSegment();
if (!segment) {
@ -396,13 +396,13 @@ MediaStreamGraphImpl::WillUnderrun(MediaStream* aStream,
// This stream isn't finished or suspended. We don't need to call
// StreamTimeToGraphTime since an underrun is the only thing that can block
// it.
GraphTime bufferEnd = aStream->GetBufferEnd() + aStream->mBufferStartTime;
GraphTime bufferEnd = aStream->GetTracksEnd() + aStream->mTracksStartTime;
#ifdef DEBUG
if (bufferEnd < mProcessedTime) {
STREAM_LOG(LogLevel::Error, ("MediaStream %p underrun, "
"bufferEnd %f < mProcessedTime %f (%lld < %lld), Streamtime %lld",
aStream, MediaTimeToSeconds(bufferEnd), MediaTimeToSeconds(mProcessedTime),
bufferEnd, mProcessedTime, aStream->GetBufferEnd()));
bufferEnd, mProcessedTime, aStream->GetTracksEnd()));
aStream->DumpTrackInfo();
NS_ASSERTION(bufferEnd >= mProcessedTime, "Buffer underran");
}
@ -435,7 +435,7 @@ MediaStreamGraphImpl::AudioTrackPresent(bool& aNeedsAEC)
if (stream->AsAudioNodeStream()) {
audioTrackPresent = true;
} else {
for (StreamBuffer::TrackIter tracks(stream->GetStreamBuffer(), MediaSegment::AUDIO);
for (StreamTracks::TrackIter tracks(stream->GetStreamTracks(), MediaSegment::AUDIO);
!tracks.IsEnded(); tracks.Next()) {
audioTrackPresent = true;
}
@ -729,7 +729,7 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(MediaStream* aStream)
return;
}
if (!aStream->GetStreamBuffer().GetAndResetTracksDirty() &&
if (!aStream->GetStreamTracks().GetAndResetTracksDirty() &&
!aStream->mAudioOutputStreams.IsEmpty()) {
return;
}
@ -741,7 +741,7 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(MediaStream* aStream)
audioOutputStreamsFound.AppendElement(false);
}
for (StreamBuffer::TrackIter tracks(aStream->GetStreamBuffer(), MediaSegment::AUDIO);
for (StreamTracks::TrackIter tracks(aStream->GetStreamTracks(), MediaSegment::AUDIO);
!tracks.IsEnded(); tracks.Next()) {
uint32_t i;
for (i = 0; i < audioOutputStreamsFound.Length(); ++i) {
@ -800,13 +800,13 @@ MediaStreamGraphImpl::PlayAudio(MediaStream* aStream)
ticksWritten = 0;
MediaStream::AudioOutputStream& audioOutput = aStream->mAudioOutputStreams[i];
StreamBuffer::Track* track = aStream->mBuffer.FindTrack(audioOutput.mTrackID);
StreamTracks::Track* track = aStream->mTracks.FindTrack(audioOutput.mTrackID);
AudioSegment* audio = track->Get<AudioSegment>();
AudioSegment output;
StreamTime offset = aStream->GraphTimeToStreamTime(mProcessedTime);
// We don't update aStream->mBufferStartTime here to account for time spent
// We don't update aStream->mTracksStartTime here to account for time spent
// blocked. Instead, we'll update it in UpdateCurrentTimeForStreams after
// the blocked period has completed. But we do need to make sure we play
// from the right offsets in the stream buffer, even if we've already
@ -925,7 +925,7 @@ MediaStreamGraphImpl::PlayVideo(MediaStream* aStream)
PrincipalHandle lastPrincipalHandle = PRINCIPAL_HANDLE_NONE;
RefPtr<Image> blackImage;
MOZ_ASSERT(mProcessedTime >= aStream->mBufferStartTime, "frame position before buffer?");
MOZ_ASSERT(mProcessedTime >= aStream->mTracksStartTime, "frame position before buffer?");
// We only look at the non-blocking interval
StreamTime frameBufferTime = aStream->GraphTimeToStreamTime(mProcessedTime);
StreamTime bufferEndTime = aStream->GraphTimeToStreamTime(aStream->mStartBlocking);
@ -937,7 +937,7 @@ MediaStreamGraphImpl::PlayVideo(MediaStream* aStream)
// Pick the last track that has a video chunk for the time, and
// schedule its frame.
chunk = nullptr;
for (StreamBuffer::TrackIter tracks(aStream->GetStreamBuffer(),
for (StreamTracks::TrackIter tracks(aStream->GetStreamTracks(),
MediaSegment::VIDEO);
!tracks.IsEnded();
tracks.Next()) {
@ -1368,14 +1368,14 @@ MediaStreamGraphImpl::UpdateGraph(GraphTime aEndBlockingDecisions)
// The stream's not suspended, and since it's finished, underruns won't
// stop it playing out. So there's no blocking other than what we impose
// here.
GraphTime endTime = stream->GetStreamBuffer().GetAllTracksEnd() +
stream->mBufferStartTime;
GraphTime endTime = stream->GetStreamTracks().GetAllTracksEnd() +
stream->mTracksStartTime;
if (endTime <= mStateComputedTime) {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p is blocked due to being finished", stream));
stream->mStartBlocking = mStateComputedTime;
} else {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p is finished, but not blocked yet (end at %f, with blocking at %f)",
stream, MediaTimeToSeconds(stream->GetBufferEnd()),
stream, MediaTimeToSeconds(stream->GetTracksEnd()),
MediaTimeToSeconds(endTime)));
// Data can't be added to a finished stream, so underruns are irrelevant.
stream->mStartBlocking = std::min(endTime, aEndBlockingDecisions);
@ -1439,7 +1439,7 @@ MediaStreamGraphImpl::Process()
} else {
ps->ProcessInput(mProcessedTime, mStateComputedTime,
ProcessedMediaStream::ALLOW_FINISH);
NS_WARN_IF_FALSE(stream->mBuffer.GetEnd() >=
NS_WARN_IF_FALSE(stream->mTracks.GetEnd() >=
GraphTimeToStreamTimeWithBlocking(stream, mStateComputedTime),
"Stream did not produce enough data");
}
@ -1922,7 +1922,7 @@ MediaStreamGraphImpl::AppendMessage(UniquePtr<ControlMessage> aMessage)
}
MediaStream::MediaStream(DOMMediaStream* aWrapper)
: mBufferStartTime(0)
: mTracksStartTime(0)
, mStartBlocking(GRAPH_TIME_MAX)
, mSuspendedCount(0)
, mFinished(false)
@ -1962,7 +1962,7 @@ MediaStream::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
// - mListeners - elements
// - mAudioOutputStream - elements
amount += mBuffer.SizeOfExcludingThis(aMallocSizeOf);
amount += mTracks.SizeOfExcludingThis(aMallocSizeOf);
amount += mAudioOutputs.ShallowSizeOfExcludingThis(aMallocSizeOf);
amount += mVideoOutputs.ShallowSizeOfExcludingThis(aMallocSizeOf);
amount += mListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
@ -1997,7 +1997,7 @@ MediaStream::SetGraphImpl(MediaStreamGraphImpl* aGraph)
MOZ_ASSERT(!mGraph, "Should only be called once");
mGraph = aGraph;
mAudioChannelType = aGraph->AudioChannel();
mBuffer.InitGraphRate(aGraph->GraphRate());
mTracks.InitGraphRate(aGraph->GraphRate());
}
void
@ -2013,16 +2013,16 @@ MediaStream::GraphTimeToStreamTime(GraphTime aTime)
NS_ASSERTION(mStartBlocking == GraphImpl()->mStateComputedTime ||
aTime <= mStartBlocking,
"Incorrectly ignoring blocking!");
return aTime - mBufferStartTime;
return aTime - mTracksStartTime;
}
GraphTime
MediaStream::StreamTimeToGraphTime(StreamTime aTime)
{
NS_ASSERTION(mStartBlocking == GraphImpl()->mStateComputedTime ||
aTime + mBufferStartTime <= mStartBlocking,
aTime + mTracksStartTime <= mStartBlocking,
"Incorrectly ignoring blocking!");
return aTime + mBufferStartTime;
return aTime + mTracksStartTime;
}
StreamTime
@ -2037,16 +2037,16 @@ MediaStream::FinishOnGraphThread()
GraphImpl()->FinishStream(this);
}
StreamBuffer::Track*
StreamTracks::Track*
MediaStream::FindTrack(TrackID aID)
{
return mBuffer.FindTrack(aID);
return mTracks.FindTrack(aID);
}
StreamBuffer::Track*
StreamTracks::Track*
MediaStream::EnsureTrack(TrackID aTrackId)
{
StreamBuffer::Track* track = mBuffer.FindTrack(aTrackId);
StreamTracks::Track* track = mTracks.FindTrack(aTrackId);
if (!track) {
nsAutoPtr<MediaSegment> segment(new AudioSegment());
for (uint32_t j = 0; j < mListeners.Length(); ++j) {
@ -2058,7 +2058,7 @@ MediaStream::EnsureTrack(TrackID aTrackId)
// change this.
l->NotifyFinishedTrackCreation(Graph());
}
track = &mBuffer.AddTrack(aTrackId, 0, segment.forget());
track = &mTracks.AddTrack(aTrackId, 0, segment.forget());
}
return track;
}
@ -2374,7 +2374,7 @@ MediaStream::AddTrackListenerImpl(already_AddRefed<MediaStreamTrackListener> aLi
l->mListener = aListener;
l->mTrackID = aTrackID;
StreamBuffer::Track* track = FindTrack(aTrackID);
StreamTracks::Track* track = FindTrack(aTrackID);
if (!track) {
return;
}
@ -2933,20 +2933,22 @@ SourceMediaStream::FinishWithLockHeld()
void
SourceMediaStream::SetTrackEnabledImpl(TrackID aTrackID, bool aEnabled)
{
MutexAutoLock lock(mMutex);
for (TrackBound<MediaStreamTrackDirectListener>& l: mDirectTrackListeners) {
if (l.mTrackID == aTrackID) {
bool oldEnabled = !mDisabledTrackIDs.Contains(aTrackID);
if (!oldEnabled && aEnabled) {
STREAM_LOG(LogLevel::Debug, ("SourceMediaStream %p track %d setting "
"direct listener enabled",
this, aTrackID));
l.mListener->DecreaseDisabled();
} else if (oldEnabled && !aEnabled) {
STREAM_LOG(LogLevel::Debug, ("SourceMediaStream %p track %d setting "
"direct listener disabled",
this, aTrackID));
l.mListener->IncreaseDisabled();
{
MutexAutoLock lock(mMutex);
for (TrackBound<MediaStreamTrackDirectListener>& l: mDirectTrackListeners) {
if (l.mTrackID == aTrackID) {
bool oldEnabled = !mDisabledTrackIDs.Contains(aTrackID);
if (!oldEnabled && aEnabled) {
STREAM_LOG(LogLevel::Debug, ("SourceMediaStream %p track %d setting "
"direct listener enabled",
this, aTrackID));
l.mListener->DecreaseDisabled();
} else if (oldEnabled && !aEnabled) {
STREAM_LOG(LogLevel::Debug, ("SourceMediaStream %p track %d setting "
"direct listener disabled",
this, aTrackID));
l.mListener->IncreaseDisabled();
}
}
}
}

Просмотреть файл

@ -16,7 +16,7 @@
#include "AudioStream.h"
#include "nsTArray.h"
#include "nsIRunnable.h"
#include "StreamBuffer.h"
#include "StreamTracks.h"
#include "VideoFrameContainer.h"
#include "VideoSegment.h"
#include "MainThreadUtils.h"
@ -265,7 +265,7 @@ protected:
/**
* This is a base class for media graph thread listener direct callbacks
* from within AppendToTrack(). Note that your regular listener will
* from within AppendToTrack(). Note that your regular listener will
* still get NotifyQueuedTrackChanges() callbacks from the MSG thread, so
* you must be careful to ignore them if AddDirectListener was successful.
*/
@ -311,13 +311,12 @@ public:
/*
* This will be called on any MediaStreamTrackDirectListener added to a
* SourceMediaStream when AppendToTrack() is called for the listener's bound
* track. The MediaSegment will be the RawSegment (unresampled) if available
* in AppendToTrack().
* track, using the thread of the AppendToTrack() caller. The MediaSegment
* will be the RawSegment (unresampled) if available in AppendToTrack().
* If the track is enabled at the source but has been disabled in one of the
* streams in between the source and where it was originally added, aMedia
* will be a disabled version of the one passed to AppendToTrack() as well.
* Note that NotifyQueuedTrackChanges() calls will also
* still occur.
* Note that NotifyQueuedTrackChanges() calls will also still occur.
*/
virtual void NotifyRealtimeTrackData(MediaStreamGraph* aGraph,
StreamTime aTrackOffset,
@ -477,7 +476,7 @@ struct TrackBound
* time. To ensure video plays in sync with audio, make sure that the same
* stream is playing both the audio and video.
*
* The data in a stream is managed by StreamBuffer. It consists of a set of
* The data in a stream is managed by StreamTracks. It consists of a set of
* tracks of various types that can start and end over time.
*
* Streams are explicitly managed. The client creates them via
@ -495,8 +494,8 @@ struct TrackBound
* wrapper; the DOM wrappers own their associated MediaStreams. When a DOM
* wrapper is destroyed, it sends a Destroy message for the associated
* MediaStream and clears its reference (the last main-thread reference to
* the object). When the Destroy message is processed on the graph
* manager thread we immediately release the affected objects (disentangling them
* the object). When the Destroy message is processed on the graph manager
* thread we immediately release the affected objects (disentangling them
* from other objects as necessary).
*
* This could cause problems for media processing if a MediaStream is
@ -541,7 +540,7 @@ public:
/**
* Returns sample rate of the graph.
*/
TrackRate GraphRate() { return mBuffer.GraphRate(); }
TrackRate GraphRate() { return mTracks.GraphRate(); }
// Control API.
// Since a stream can be played multiple ways, we need to combine independent
@ -674,9 +673,9 @@ public:
* This must be idempotent.
*/
virtual void DestroyImpl();
StreamTime GetBufferEnd() { return mBuffer.GetEnd(); }
StreamTime GetTracksEnd() { return mTracks.GetEnd(); }
#ifdef DEBUG
void DumpTrackInfo() { return mBuffer.DumpTrackInfo(); }
void DumpTrackInfo() { return mTracks.DumpTrackInfo(); }
#endif
void SetAudioOutputVolumeImpl(void* aKey, float aVolume);
void AddAudioOutputImpl(void* aKey);
@ -713,36 +712,36 @@ public:
{
return mConsumers.Length();
}
StreamBuffer& GetStreamBuffer() { return mBuffer; }
GraphTime GetStreamBufferStartTime() { return mBufferStartTime; }
StreamTracks& GetStreamTracks() { return mTracks; }
GraphTime GetStreamTracksStartTime() { return mTracksStartTime; }
double StreamTimeToSeconds(StreamTime aTime)
{
NS_ASSERTION(0 <= aTime && aTime <= STREAM_TIME_MAX, "Bad time");
return static_cast<double>(aTime)/mBuffer.GraphRate();
return static_cast<double>(aTime)/mTracks.GraphRate();
}
int64_t StreamTimeToMicroseconds(StreamTime aTime)
{
NS_ASSERTION(0 <= aTime && aTime <= STREAM_TIME_MAX, "Bad time");
return (aTime*1000000)/mBuffer.GraphRate();
return (aTime*1000000)/mTracks.GraphRate();
}
StreamTime SecondsToNearestStreamTime(double aSeconds)
{
NS_ASSERTION(0 <= aSeconds && aSeconds <= TRACK_TICKS_MAX/TRACK_RATE_MAX,
"Bad seconds");
return mBuffer.GraphRate() * aSeconds + 0.5;
return mTracks.GraphRate() * aSeconds + 0.5;
}
StreamTime MicrosecondsToStreamTimeRoundDown(int64_t aMicroseconds) {
return (aMicroseconds*mBuffer.GraphRate())/1000000;
return (aMicroseconds*mTracks.GraphRate())/1000000;
}
TrackTicks TimeToTicksRoundUp(TrackRate aRate, StreamTime aTime)
{
return RateConvertTicksRoundUp(aRate, mBuffer.GraphRate(), aTime);
return RateConvertTicksRoundUp(aRate, mTracks.GraphRate(), aTime);
}
StreamTime TicksToTimeRoundDown(TrackRate aRate, TrackTicks aTicks)
{
return RateConvertTicksRoundDown(mBuffer.GraphRate(), aRate, aTicks);
return RateConvertTicksRoundDown(mTracks.GraphRate(), aRate, aTicks);
}
/**
* Convert graph time to stream time. aTime must be <= mStateComputedTime
@ -773,9 +772,9 @@ public:
/**
* Find track by track id.
*/
StreamBuffer::Track* FindTrack(TrackID aID);
StreamTracks::Track* FindTrack(TrackID aID);
StreamBuffer::Track* EnsureTrack(TrackID aTrack);
StreamTracks::Track* EnsureTrack(TrackID aTrack);
virtual void ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment, MediaSegment* aRawSegment = nullptr);
@ -808,8 +807,8 @@ public:
protected:
void AdvanceTimeVaryingValuesToCurrentTime(GraphTime aCurrentTime, GraphTime aBlockedTime)
{
mBufferStartTime += aBlockedTime;
mBuffer.ForgetUpTo(aCurrentTime - mBufferStartTime);
mTracksStartTime += aBlockedTime;
mTracks.ForgetUpTo(aCurrentTime - mTracksStartTime);
}
void NotifyMainThreadListeners()
@ -836,14 +835,14 @@ protected:
// This state is all initialized on the main thread but
// otherwise modified only on the media graph thread.
// Buffered data. The start of the buffer corresponds to mBufferStartTime.
// Buffered data. The start of the buffer corresponds to mTracksStartTime.
// Conceptually the buffer contains everything this stream has ever played,
// but we forget some prefix of the buffered data to bound the space usage.
StreamBuffer mBuffer;
StreamTracks mTracks;
// The time when the buffered data could be considered to have started playing.
// This increases over time to account for time the stream was blocked before
// mCurrentTime.
GraphTime mBufferStartTime;
GraphTime mTracksStartTime;
// Client-set volume of this stream
struct AudioOutput {
@ -863,7 +862,7 @@ protected:
// GraphTime at which this stream starts blocking.
// This is only valid up to mStateComputedTime. The stream is considered to
// have not been blocked before mCurrentTime (its mBufferStartTime is increased
// have not been blocked before mCurrentTime (its mTracksStartTime is increased
// as necessary to account for that time instead).
GraphTime mStartBlocking;
@ -1078,16 +1077,6 @@ public:
friend class MediaStreamGraphImpl;
protected:
struct ThreadAndRunnable {
void Init(TaskQueue* aTarget, nsIRunnable* aRunnable)
{
mTarget = aTarget;
mRunnable = aRunnable;
}
RefPtr<TaskQueue> mTarget;
nsCOMPtr<nsIRunnable> mRunnable;
};
enum TrackCommands {
TRACK_CREATE = MediaStreamListener::TRACK_EVENT_CREATED,
TRACK_END = MediaStreamListener::TRACK_EVENT_ENDED
@ -1455,7 +1444,6 @@ public:
// IdealAudioBlockSize()/AudioStream::PreferredSampleRate(). A stream that
// never blocks and has a track with the ideal audio rate will produce audio
// in multiples of the block size.
//
// Initializing an graph that outputs audio can be quite long on some
// platforms. Code that want to output audio at some point can express the

Просмотреть файл

@ -91,8 +91,9 @@ public:
* file. It's not in the anonymous namespace because MediaStream needs to
* be able to friend it.
*
* Currently we have one global instance per process, and one per each
* OfflineAudioContext object.
* There can be multiple MediaStreamGraph per process: one per AudioChannel.
* Additionaly, each OfflineAudioContext object creates its own MediaStreamGraph
* object too.
*/
class MediaStreamGraphImpl : public MediaStreamGraph,
public nsIMemoryReporter
@ -104,10 +105,10 @@ public:
/**
* Use aGraphDriverRequested with SYSTEM_THREAD_DRIVER or AUDIO_THREAD_DRIVER
* to create a MediaStreamGraph which provides support for real-time audio
* and/or video. Set it to false in order to create a non-realtime instance
* which just churns through its inputs and produces output. Those objects
* currently only support audio, and are used to implement
* OfflineAudioContext. They do not support MediaStream inputs.
* and/or video. Set it to OFFLINE_THREAD_DRIVER in order to create a
* non-realtime instance which just churns through its inputs and produces
* output. Those objects currently only support audio, and are used to
* implement OfflineAudioContext. They do not support MediaStream inputs.
*/
explicit MediaStreamGraphImpl(GraphDriverType aGraphDriverRequested,
TrackRate aSampleRate,
@ -403,7 +404,7 @@ public:
void PlayVideo(MediaStream* aStream);
/**
* No more data will be forthcoming for aStream. The stream will end
* at the current buffer end point. The StreamBuffer's tracks must be
* at the current buffer end point. The StreamTracks's tracks must be
* explicitly set to finished by the caller.
*/
void OpenAudioInputImpl(int aID,

Просмотреть файл

@ -10,7 +10,7 @@
#include "nsError.h"
#include "nsID.h"
#include "nsIPrincipal.h"
#include "StreamBuffer.h"
#include "StreamTracks.h"
#include "MediaTrackConstraints.h"
#include "mozilla/CORSMode.h"
#include "PrincipalChangeObserver.h"

117
dom/media/StreamTracks.cpp Normal file
Просмотреть файл

@ -0,0 +1,117 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "StreamTracks.h"
#include "mozilla/Logging.h"
#include <algorithm>
namespace mozilla {
extern LazyLogModule gMediaStreamGraphLog;
#define STREAM_LOG(type, msg) MOZ_LOG(gMediaStreamGraphLog, type, msg)
#ifdef DEBUG
void
StreamTracks::DumpTrackInfo() const
{
STREAM_LOG(LogLevel::Info, ("DumpTracks: mTracksKnownTime %lld", mTracksKnownTime));
for (uint32_t i = 0; i < mTracks.Length(); ++i) {
Track* track = mTracks[i];
if (track->IsEnded()) {
STREAM_LOG(LogLevel::Info, ("Track[%d] %d: ended", i, track->GetID()));
} else {
STREAM_LOG(LogLevel::Info, ("Track[%d] %d: %lld", i, track->GetID(),
track->GetEnd()));
}
}
}
#endif
StreamTime
StreamTracks::GetEnd() const
{
StreamTime t = mTracksKnownTime;
for (uint32_t i = 0; i < mTracks.Length(); ++i) {
Track* track = mTracks[i];
if (!track->IsEnded()) {
t = std::min(t, track->GetEnd());
}
}
return t;
}
StreamTime
StreamTracks::GetAllTracksEnd() const
{
if (mTracksKnownTime < STREAM_TIME_MAX) {
// A track might be added.
return STREAM_TIME_MAX;
}
StreamTime t = 0;
for (uint32_t i = 0; i < mTracks.Length(); ++i) {
Track* track = mTracks[i];
if (!track->IsEnded()) {
return STREAM_TIME_MAX;
}
t = std::max(t, track->GetEnd());
}
return t;
}
StreamTracks::Track*
StreamTracks::FindTrack(TrackID aID)
{
if (aID == TRACK_NONE || mTracks.IsEmpty()) {
return nullptr;
}
// The tracks are sorted by ID. We can use a binary search.
uint32_t left = 0, right = mTracks.Length() - 1;
while (left <= right) {
uint32_t middle = (left + right) / 2;
if (mTracks[middle]->GetID() == aID) {
return mTracks[middle];
}
if (mTracks[middle]->GetID() > aID) {
if (middle == 0) {
break;
}
right = middle - 1;
} else {
left = middle + 1;
}
}
return nullptr;
}
void
StreamTracks::ForgetUpTo(StreamTime aTime)
{
// Only prune if there is a reasonable chunk (50ms @ 48kHz) to forget, so we
// don't spend too much time pruning segments.
const StreamTime minChunkSize = 2400;
if (aTime < mForgottenTime + minChunkSize) {
return;
}
mForgottenTime = aTime;
for (uint32_t i = 0; i < mTracks.Length(); ++i) {
Track* track = mTracks[i];
if (track->IsEnded() && track->GetEnd() <= aTime) {
mTracks.RemoveElementAt(i);
mTracksDirty = true;
--i;
continue;
}
StreamTime forgetTo = std::min(track->GetEnd() - 1, aTime);
track->ForgetUpTo(forgetTo);
}
}
} // namespace mozilla

343
dom/media/StreamTracks.h Normal file
Просмотреть файл

@ -0,0 +1,343 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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_STREAMTRACKS_H_
#define MOZILLA_STREAMTRACKS_H_
#include "MediaSegment.h"
#include "nsAutoPtr.h"
namespace mozilla {
/**
* Unique ID for track within a StreamTracks. Tracks from different
* StreamTrackss may have the same ID; this matters when appending StreamTrackss,
* since tracks with the same ID are matched. Only IDs greater than 0 are allowed.
*/
typedef int32_t TrackID;
const TrackID TRACK_NONE = 0;
const TrackID TRACK_INVALID = -1;
const TrackID TRACK_ANY = -2;
inline bool IsTrackIDExplicit(const TrackID& aId) {
return aId > TRACK_NONE;
}
inline TrackTicks RateConvertTicksRoundDown(TrackRate aOutRate,
TrackRate aInRate,
TrackTicks aTicks)
{
NS_ASSERTION(0 < aOutRate && aOutRate <= TRACK_RATE_MAX, "Bad out rate");
NS_ASSERTION(0 < aInRate && aInRate <= TRACK_RATE_MAX, "Bad in rate");
NS_WARN_IF_FALSE(0 <= aTicks && aTicks <= TRACK_TICKS_MAX, "Bad ticks"); // bug 957691
return (aTicks * aOutRate) / aInRate;
}
inline TrackTicks RateConvertTicksRoundUp(TrackRate aOutRate,
TrackRate aInRate, TrackTicks aTicks)
{
NS_ASSERTION(0 < aOutRate && aOutRate <= TRACK_RATE_MAX, "Bad out rate");
NS_ASSERTION(0 < aInRate && aInRate <= TRACK_RATE_MAX, "Bad in rate");
NS_ASSERTION(0 <= aTicks && aTicks <= TRACK_TICKS_MAX, "Bad ticks");
return (aTicks * aOutRate + aInRate - 1) / aInRate;
}
/**
* This object contains the decoded data for a stream's tracks.
* A StreamTracks can be appended to. Logically a StreamTracks only gets longer,
* but we also have the ability to "forget" data before a certain time that
* we know won't be used again. (We prune a whole number of seconds internally.)
*
* StreamTrackss should only be used from one thread at a time.
*
* A StreamTracks has a set of tracks that can be of arbitrary types ---
* the data for each track is a MediaSegment. The set of tracks can vary
* over the timeline of the StreamTracks.
*/
class StreamTracks
{
public:
/**
* Every track has a start time --- when it started in the StreamTracks.
* It has an end flag; when false, no end point is known; when true,
* the track ends when the data we have for the track runs out.
* Tracks have a unique ID assigned at creation. This allows us to identify
* the same track across StreamTrackss. A StreamTracks should never have
* two tracks with the same ID (even if they don't overlap in time).
* TODO Tracks can also be enabled and disabled over time.
* Takes ownership of aSegment.
*/
class Track final
{
Track(TrackID aID, StreamTime aStart, MediaSegment* aSegment)
: mStart(aStart),
mSegment(aSegment),
mID(aID),
mEnded(false)
{
MOZ_COUNT_CTOR(Track);
NS_ASSERTION(aID > TRACK_NONE, "Bad track ID");
NS_ASSERTION(0 <= aStart && aStart <= aSegment->GetDuration(), "Bad start position");
}
public:
~Track()
{
MOZ_COUNT_DTOR(Track);
}
template <class T> T* Get() const
{
if (mSegment->GetType() == T::StaticType()) {
return static_cast<T*>(mSegment.get());
}
return nullptr;
}
MediaSegment* GetSegment() const { return mSegment; }
TrackID GetID() const { return mID; }
bool IsEnded() const { return mEnded; }
StreamTime GetStart() const { return mStart; }
StreamTime GetEnd() const { return mSegment->GetDuration(); }
MediaSegment::Type GetType() const { return mSegment->GetType(); }
void SetEnded() { mEnded = true; }
void AppendFrom(Track* aTrack)
{
NS_ASSERTION(!mEnded, "Can't append to ended track");
NS_ASSERTION(aTrack->mID == mID, "IDs must match");
NS_ASSERTION(aTrack->mStart == 0, "Source track must start at zero");
NS_ASSERTION(aTrack->mSegment->GetType() == GetType(), "Track types must match");
mSegment->AppendFrom(aTrack->mSegment);
mEnded = aTrack->mEnded;
}
MediaSegment* RemoveSegment()
{
return mSegment.forget();
}
void ForgetUpTo(StreamTime aTime)
{
mSegment->ForgetUpTo(aTime);
}
void FlushAfter(StreamTime aNewEnd)
{
// Forget everything after a given endpoint
// a specified amount
mSegment->FlushAfter(aNewEnd);
}
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t amount = aMallocSizeOf(this);
if (mSegment) {
amount += mSegment->SizeOfIncludingThis(aMallocSizeOf);
}
return amount;
}
private:
friend class StreamTracks;
// Start offset is in ticks at rate mRate
StreamTime mStart;
// The segment data starts at the start of the owning StreamTracks, i.e.,
// there's mStart silence/no video at the beginning.
nsAutoPtr<MediaSegment> mSegment;
// Unique ID
TrackID mID;
// True when the track ends with the data in mSegment
bool mEnded;
};
class MOZ_STACK_CLASS CompareTracksByID final
{
public:
bool Equals(Track* aA, Track* aB) const {
return aA->GetID() == aB->GetID();
}
bool LessThan(Track* aA, Track* aB) const {
return aA->GetID() < aB->GetID();
}
};
StreamTracks()
: mGraphRate(0)
, mTracksKnownTime(0)
, mForgottenTime(0)
, mTracksDirty(false)
#ifdef DEBUG
, mGraphRateIsSet(false)
#endif
{
MOZ_COUNT_CTOR(StreamTracks);
}
~StreamTracks()
{
MOZ_COUNT_DTOR(StreamTracks);
}
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t amount = 0;
amount += mTracks.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (size_t i = 0; i < mTracks.Length(); i++) {
amount += mTracks[i]->SizeOfIncludingThis(aMallocSizeOf);
}
return amount;
}
/**
* Initialize the graph rate for use in calculating StreamTimes from track
* ticks. Called when a MediaStream's graph pointer is initialized.
*/
void InitGraphRate(TrackRate aGraphRate)
{
mGraphRate = aGraphRate;
#if DEBUG
MOZ_ASSERT(!mGraphRateIsSet);
mGraphRateIsSet = true;
#endif
}
TrackRate GraphRate() const
{
MOZ_ASSERT(mGraphRateIsSet);
return mGraphRate;
}
/**
* Takes ownership of aSegment. Don't do this while iterating, or while
* holding a Track reference.
* aSegment must have aStart worth of null data.
*/
Track& AddTrack(TrackID aID, StreamTime aStart, MediaSegment* aSegment)
{
NS_ASSERTION(!FindTrack(aID), "Track with this ID already exists");
Track* track = new Track(aID, aStart, aSegment);
mTracks.InsertElementSorted(track, CompareTracksByID());
mTracksDirty = true;
if (mTracksKnownTime == STREAM_TIME_MAX) {
// There exists code like
// http://mxr.mozilla.org/mozilla-central/source/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp?rev=96b197deb91e&mark=1292-1297#1292
NS_WARNING("Adding track to StreamTracks that should have no more tracks");
} else {
NS_ASSERTION(mTracksKnownTime <= aStart, "Start time too early");
}
return *track;
}
void AdvanceKnownTracksTime(StreamTime aKnownTime)
{
NS_ASSERTION(aKnownTime >= mTracksKnownTime, "Can't move tracks-known time earlier");
mTracksKnownTime = aKnownTime;
}
/**
* The end time for the StreamTracks is the latest time for which we have
* data for all tracks that haven't ended by that time.
*/
StreamTime GetEnd() const;
/**
* Returns the earliest time >= 0 at which all tracks have ended
* and all their data has been played out and no new tracks can be added,
* or STREAM_TIME_MAX if there is no such time.
*/
StreamTime GetAllTracksEnd() const;
#ifdef DEBUG
void DumpTrackInfo() const;
#endif
Track* FindTrack(TrackID aID);
class MOZ_STACK_CLASS TrackIter final
{
public:
/**
* Iterate through the tracks of aBuffer in order of ID.
*/
explicit TrackIter(const StreamTracks& aBuffer) :
mBuffer(&aBuffer.mTracks), mIndex(0), mMatchType(false) {}
/**
* Iterate through the tracks of aBuffer with type aType, in order of ID.
*/
TrackIter(const StreamTracks& aBuffer, MediaSegment::Type aType) :
mBuffer(&aBuffer.mTracks), mIndex(0), mType(aType), mMatchType(true) { FindMatch(); }
bool IsEnded() { return mIndex >= mBuffer->Length(); }
void Next()
{
++mIndex;
FindMatch();
}
Track* get() { return mBuffer->ElementAt(mIndex); }
Track& operator*() { return *mBuffer->ElementAt(mIndex); }
Track* operator->() { return mBuffer->ElementAt(mIndex); }
private:
void FindMatch()
{
if (!mMatchType)
return;
while (mIndex < mBuffer->Length() &&
mBuffer->ElementAt(mIndex)->GetType() != mType) {
++mIndex;
}
}
const nsTArray<nsAutoPtr<Track> >* mBuffer;
uint32_t mIndex;
MediaSegment::Type mType;
bool mMatchType;
};
friend class TrackIter;
/**
* Forget stream data before aTime; they will no longer be needed.
* Also can forget entire tracks that have ended at or before aTime.
* Can't be used to forget beyond GetEnd().
*/
void ForgetUpTo(StreamTime aTime);
/**
* Returns the latest time passed to ForgetUpTo.
*/
StreamTime GetForgottenDuration()
{
return mForgottenTime;
}
bool GetAndResetTracksDirty()
{
if (!mTracksDirty) {
return false;
}
mTracksDirty = false;
return true;
}
protected:
TrackRate mGraphRate; // StreamTime per second
// Any new tracks added will start at or after this time. In other words, the track
// list is complete and correct for all times less than this time.
StreamTime mTracksKnownTime;
StreamTime mForgottenTime;
private:
// All known tracks for this StreamTracks
nsTArray<nsAutoPtr<Track>> mTracks;
bool mTracksDirty;
#ifdef DEBUG
bool mGraphRateIsSet;
#endif
};
} // namespace mozilla
#endif /* MOZILLA_STREAMTRACKS_H_ */

Просмотреть файл

@ -87,14 +87,14 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
allHaveCurrentData = false;
}
bool trackAdded = false;
for (StreamBuffer::TrackIter tracks(stream->GetStreamBuffer());
for (StreamTracks::TrackIter tracks(stream->GetStreamTracks());
!tracks.IsEnded(); tracks.Next()) {
bool found = false;
for (uint32_t j = 0; j < mTrackMap.Length(); ++j) {
TrackMapEntry* map = &mTrackMap[j];
if (map->mInputPort == mInputs[i] && map->mInputTrackID == tracks->GetID()) {
bool trackFinished;
StreamBuffer::Track* outputTrack = mBuffer.FindTrack(map->mOutputTrackID);
bool trackFinished = false;
StreamTracks::Track* outputTrack = mTracks.FindTrack(map->mOutputTrackID);
found = true;
if (!outputTrack || outputTrack->IsEnded() ||
!mInputs[i]->PassTrackThrough(tracks->GetID())) {
@ -138,7 +138,7 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
// so we're finished now.
FinishOnGraphThread();
} else {
mBuffer.AdvanceKnownTracksTime(GraphTimeToStreamTimeWithBlocking(aTo));
mTracks.AdvanceKnownTracksTime(GraphTimeToStreamTimeWithBlocking(aTo));
}
if (allHaveCurrentData) {
// We can make progress if we're not blocked
@ -146,7 +146,7 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
}
}
uint32_t TrackUnionStream::AddTrack(MediaInputPort* aPort, StreamBuffer::Track* aTrack,
uint32_t TrackUnionStream::AddTrack(MediaInputPort* aPort, StreamTracks::Track* aTrack,
GraphTime aFrom)
{
STREAM_LOG(LogLevel::Verbose, ("TrackUnionStream %p adding track %d for "
@ -205,8 +205,8 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
aPort->GetSource(), aTrack->GetID());
}
segment->AppendNullData(outputStart);
StreamBuffer::Track* track =
&mBuffer.AddTrack(id, outputStart, segment.forget());
StreamTracks::Track* track =
&mTracks.AddTrack(id, outputStart, segment.forget());
STREAM_LOG(LogLevel::Debug, ("TrackUnionStream %p added track %d for input stream %p track %d, start ticks %lld",
this, track->GetID(), aPort->GetSource(), aTrack->GetID(),
(long long)outputStart));
@ -246,7 +246,7 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
void TrackUnionStream::EndTrack(uint32_t aIndex)
{
StreamBuffer::Track* outputTrack = mBuffer.FindTrack(mTrackMap[aIndex].mOutputTrackID);
StreamTracks::Track* outputTrack = mTracks.FindTrack(mTrackMap[aIndex].mOutputTrackID);
if (!outputTrack || outputTrack->IsEnded())
return;
STREAM_LOG(LogLevel::Debug, ("TrackUnionStream %p ending track %d", this, outputTrack->GetID()));
@ -269,12 +269,12 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
outputTrack->SetEnded();
}
void TrackUnionStream::CopyTrackData(StreamBuffer::Track* aInputTrack,
void TrackUnionStream::CopyTrackData(StreamTracks::Track* aInputTrack,
uint32_t aMapIndex, GraphTime aFrom, GraphTime aTo,
bool* aOutputTrackFinished)
{
TrackMapEntry* map = &mTrackMap[aMapIndex];
StreamBuffer::Track* outputTrack = mBuffer.FindTrack(map->mOutputTrackID);
StreamTracks::Track* outputTrack = mTracks.FindTrack(map->mOutputTrackID);
MOZ_ASSERT(outputTrack && !outputTrack->IsEnded(), "Can't copy to ended track");
MediaSegment* segment = map->mSegment;

Просмотреть файл

@ -41,7 +41,7 @@ protected:
// We keep track IDs instead of track pointers because
// tracks can be removed without us being notified (e.g.
// when a finished track is forgotten.) When we need a Track*,
// we call StreamBuffer::FindTrack, which will return null if
// we call StreamTracks::FindTrack, which will return null if
// the track has been deleted.
TrackID mInputTrackID;
TrackID mOutputTrackID;
@ -54,10 +54,10 @@ protected:
// Add the track to this stream, retaining its TrackID if it has never
// been previously used in this stream, allocating a new TrackID otherwise.
uint32_t AddTrack(MediaInputPort* aPort, StreamBuffer::Track* aTrack,
uint32_t AddTrack(MediaInputPort* aPort, StreamTracks::Track* aTrack,
GraphTime aFrom);
void EndTrack(uint32_t aIndex);
void CopyTrackData(StreamBuffer::Track* aInputTrack,
void CopyTrackData(StreamTracks::Track* aInputTrack,
uint32_t aMapIndex, GraphTime aFrom, GraphTime aTo,
bool* aOutputTrackFinished);

Просмотреть файл

@ -10,7 +10,7 @@
#include "AudioSegment.h"
#include "EncodedFrameContainer.h"
#include "StreamBuffer.h"
#include "StreamTracks.h"
#include "TrackMetadataBase.h"
#include "VideoSegment.h"
#include "MediaStreamGraph.h"

Просмотреть файл

@ -140,7 +140,7 @@ EXPORTS += [
'SeekTask.h',
'SelfRef.h',
'SharedBuffer.h',
'StreamBuffer.h',
'StreamTracks.h',
'ThreadPoolCOMListener.h',
'TimeUnits.h',
'TrackUnionStream.h',
@ -244,7 +244,7 @@ UNIFIED_SOURCES += [
'RtspMediaResource.cpp',
'SeekJob.cpp',
'SeekTask.cpp',
'StreamBuffer.cpp',
'StreamTracks.cpp',
'TextTrack.cpp',
'TextTrackCue.cpp',
'TextTrackCueList.cpp',

Просмотреть файл

@ -685,7 +685,7 @@ skip-if = (os != 'win' || os_version == '5.1') # Only gmp-clearkey on Windows Vi
skip-if = os == 'win' && !debug # bug 1228605
tags=msg
[test_mediarecorder_bitrate.html]
skip-if = (toolkit == 'gonk' || toolkit == 'android') # B2G emulator is too slow to run this without timing out and Fennec does not support video recording
skip-if = (toolkit == 'gonk') # B2G emulator is too slow to run this without timing out.
tags=msg
[test_mediarecorder_creation.html]
tags=msg capturestream

Просмотреть файл

@ -152,9 +152,9 @@ AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
MediaStream* source = mInputs[0]->GetSource();
AutoTArray<AudioSegment,1> audioSegments;
uint32_t inputChannels = 0;
for (StreamBuffer::TrackIter tracks(source->mBuffer, MediaSegment::AUDIO);
for (StreamTracks::TrackIter tracks(source->mTracks, MediaSegment::AUDIO);
!tracks.IsEnded(); tracks.Next()) {
const StreamBuffer::Track& inputTrack = *tracks;
const StreamTracks::Track& inputTrack = *tracks;
if (!mInputs[0]->PassTrackThrough(tracks->GetID())) {
continue;
}

Просмотреть файл

@ -384,9 +384,9 @@ public:
void Run() override
{
auto ns = static_cast<AudioNodeStream*>(mStream);
ns->mBufferStartTime -= mAdvance;
ns->mTracksStartTime -= mAdvance;
StreamBuffer::Track* track = ns->EnsureTrack(AUDIO_TRACK);
StreamTracks::Track* track = ns->EnsureTrack(AUDIO_TRACK);
track->Get<AudioSegment>()->AppendNullData(mAdvance);
ns->GraphImpl()->DecrementSuspendCount(mStream);
@ -631,9 +631,9 @@ AudioNodeStream::ProduceOutputBeforeInput(GraphTime aFrom)
void
AudioNodeStream::AdvanceOutputSegment()
{
StreamBuffer::Track* track = EnsureTrack(AUDIO_TRACK);
StreamTracks::Track* track = EnsureTrack(AUDIO_TRACK);
// No more tracks will be coming
mBuffer.AdvanceKnownTracksTime(STREAM_TIME_MAX);
mTracks.AdvanceKnownTracksTime(STREAM_TIME_MAX);
AudioSegment* segment = track->Get<AudioSegment>();
@ -656,7 +656,7 @@ AudioNodeStream::AdvanceOutputSegment()
void
AudioNodeStream::FinishOutput()
{
StreamBuffer::Track* track = EnsureTrack(AUDIO_TRACK);
StreamTracks::Track* track = EnsureTrack(AUDIO_TRACK);
track->SetEnded();
for (uint32_t j = 0; j < mListeners.Length(); ++j) {

Просмотреть файл

@ -30,9 +30,9 @@ MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(AudioContext* a
ChannelCountMode::Explicit,
ChannelInterpretation::Speakers)
, mDOMStream(
DOMAudioNodeMediaStream::CreateTrackUnionStream(GetOwner(),
this,
aContext->Graph()))
DOMAudioNodeMediaStream::CreateTrackUnionStreamAsInput(GetOwner(),
this,
aContext->Graph()))
{
// Ensure an audio track with the correct ID is exposed to JS
nsIDocument* doc = aContext->GetParentObject()->GetExtantDoc();

Просмотреть файл

@ -16,7 +16,7 @@
#include "MediaEngine.h"
#include "VideoSegment.h"
#include "AudioSegment.h"
#include "StreamBuffer.h"
#include "StreamTracks.h"
#include "MediaStreamGraph.h"
#include "MediaTrackConstraints.h"
@ -134,7 +134,7 @@ public:
const PrincipalHandle& aPrincipalHandle) override
{
#ifdef DEBUG
StreamBuffer::Track* data = aSource->FindTrack(aId);
StreamTracks::Track* data = aSource->FindTrack(aId);
NS_WARN_IF_FALSE(!data || data->IsEnded() ||
aDesiredTime <= aSource->GetEndOfAppendedData(aId),
"MediaEngineDefaultAudioSource data underrun");

Просмотреть файл

@ -24,7 +24,7 @@
#include "MediaEngineCameraVideoSource.h"
#include "VideoSegment.h"
#include "AudioSegment.h"
#include "StreamBuffer.h"
#include "StreamTracks.h"
#include "MediaStreamGraph.h"
#include "MediaEngineWrapper.h"

Просмотреть файл

@ -12,6 +12,9 @@
#include "prenv.h"
#include "mozilla/Logging.h"
#ifdef XP_WIN
#include "mozilla/WindowsVersion.h"
#endif
static mozilla::LogModule*
GetUserMediaLog()
@ -298,6 +301,16 @@ MediaEngineWebRTC::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource,
#endif
}
bool
MediaEngineWebRTC::SupportsDuplex()
{
#ifndef XP_WIN
return mFullDuplex;
#else
return IsVistaOrLater() && mFullDuplex;
#endif
}
void
MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource,
nsTArray<RefPtr<MediaEngineAudioSource> >* aASources)
@ -350,7 +363,7 @@ MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource,
}
if (!mAudioInput) {
if (mFullDuplex) {
if (SupportsDuplex()) {
// The platform_supports_full_duplex.
mAudioInput = new mozilla::AudioInputCubeb(mVoiceEngine);
} else {
@ -394,7 +407,7 @@ MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource,
aASources->AppendElement(aSource.get());
} else {
AudioInput* audioinput = mAudioInput;
if (mFullDuplex) {
if (SupportsDuplex()) {
// The platform_supports_full_duplex.
// For cubeb, it has state (the selected ID)

Просмотреть файл

@ -27,7 +27,7 @@
#include "MediaEngineCameraVideoSource.h"
#include "VideoSegment.h"
#include "AudioSegment.h"
#include "StreamBuffer.h"
#include "StreamTracks.h"
#include "MediaStreamGraph.h"
#include "cubeb/cubeb.h"
#include "CubebUtils.h"
@ -569,6 +569,9 @@ public:
// before invoking Shutdown on this class.
void Shutdown() override;
// Returns whether the host supports duplex audio stream.
bool SupportsDuplex();
void EnumerateVideoDevices(dom::MediaSourceEnum,
nsTArray<RefPtr<MediaEngineVideoSource>>*) override;
void EnumerateAudioDevices(dom::MediaSourceEnum,

Просмотреть файл

@ -1,10 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1045897 - Test CSP base-uri directive</title>
<base href="http://mochi.test">
</head>
<body onload='window.parent.postMessage({result: document.baseURI}, "*");'>
<!-- just making use of the 'base' tag for this test -->
</body>
</html>

Просмотреть файл

@ -0,0 +1,61 @@
// Custom *.sjs file specifically for the needs of
// https://bugzilla.mozilla.org/show_bug.cgi?id=1263286
"use strict";
Components.utils.importGlobalProperties(["URLSearchParams"]);
const PRE_BASE = `
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1045897 - Test CSP base-uri directive</title>`;
const REGULAR_POST_BASE =`
</head>
<body onload='window.parent.postMessage({result: document.baseURI}, "*");'>
<!-- just making use of the 'base' tag for this test -->
</body>
</html>`;
const SCRIPT_POST_BASE = `
</head>
<body>
<script>
document.getElementById("base1").removeAttribute("href");
window.parent.postMessage({result: document.baseURI}, "*");
</script>
</body>
</html>`;
function handleRequest(request, response) {
const query = new URLSearchParams(request.queryString);
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
// Deliver the CSP policy encoded in the URL
response.setHeader("Content-Security-Policy", query.get("csp"), false);
// Send HTML to test allowed/blocked behaviors
response.setHeader("Content-Type", "text/html", false);
response.write(PRE_BASE);
var base1 =
"<base id=\"base1\" href=\"" + query.get("base1") + "\">";
var base2 =
"<base id=\"base2\" href=\"" + query.get("base2") + "\">";
response.write(base1 + base2);
if (query.get("action") === "enforce-csp") {
response.write(REGULAR_POST_BASE);
return;
}
if (query.get("action") === "remove-base1") {
response.write(SCRIPT_POST_BASE);
return;
}
// we should never get here, but just in case
// return something unexpected
response.write("do'h");
}

Просмотреть файл

@ -1,6 +1,6 @@
[DEFAULT]
support-files =
file_base-uri.html
file_base_uri_server.sjs
file_blob_data_schemes.html
file_connect-src.html
file_connect-src-fetch.html

Просмотреть файл

@ -16,30 +16,64 @@
/*
* Description of the test:
* We load a page in an iframe (served over http://example.com) that tries to set the 'base'
* to (http://mochi.test). We load that page using different policies and verify that
* setting the base-uri is correctly blocked by CSP.
* We load a page in an iframe (served over http://example.com) that tries to
* modify the 'base' either through setting or also removing the base-uri. We
* load that page using different policies and verify that setting the base-uri
* is correctly blocked by CSP.
*/
SimpleTest.waitForExplicitFinish();
var tests = [
{
policy: "base-uri http://mochi.test;",
result: "http://mochi.test"
{ csp: "base-uri http://mochi.test;",
base1: "http://mochi.test",
base2: "",
action: "enforce-csp",
result: "http://mochi.test",
desc: "CSP allows base uri"
},
{
policy: "base-uri http://example.com;",
result: "http://example.com"
{ csp: "base-uri http://example.com;",
base1: "http://mochi.test",
base2: "",
action: "enforce-csp",
result: "http://example.com",
desc: "CSP blocks base uri"
},
{
policy: "base-uri https:",
result: "http://example.com"
{ csp: "base-uri https:",
base1: "http://mochi.test",
base2: "",
action: "enforce-csp",
result: "http://example.com",
desc: "CSP blocks http base"
},
{ csp: "base-uri 'none'",
base1: "http://mochi.test",
base2: "",
action: "enforce-csp",
result: "http://example.com",
desc: "CSP allows no base modification"
},
{ csp: "",
base1: "http://foo:foo/",
base2: "",
action: "enforce-csp",
result: "http://example.com",
desc: "Invalid base should be ignored"
},
{ csp: "base-uri http://mochi.test",
base1: "http://mochi.test",
base2: "http://test1.example.com",
action: "remove-base1",
result: "http://example.com",
desc: "Removing first base should result in fallback base"
},
{ csp: "",
base1: "http://mochi.test",
base2: "http://test1.example.com",
action: "remove-base1",
result: "http://test1.example.com",
desc: "Removing first base should result in the second base"
},
{
policy: "base-uri 'none'",
result: "http://example.com"
}
];
// initializing to -1 so we start at index 0 when we start the test
@ -57,7 +91,9 @@ function receiveMessage(event) {
var result = event.data.result;
// we only care about the base uri, so instead of comparing the complete uri
// we just make sure that the base is correct which is sufficient here.
ok(result.startsWith(tests[counter].result), "Restricting base-uri in test " + counter + "!");
ok(result.startsWith(tests[counter].result),
`${tests[counter].desc}: Expected a base URI that starts
with ${tests[counter].result} but got ${result}`);
loadNextTest();
}
@ -67,12 +103,16 @@ function loadNextTest() {
finishTest();
return;
}
var src = "http://example.com/tests/dom/security/test/csp/file_testserver.sjs";
// append the file that should be served
src += "?file=" + escape("tests/dom/security/test/csp/file_base-uri.html");
var src = "http://example.com/tests/dom/security/test/csp/file_base_uri_server.sjs";
// append the CSP that should be used to serve the file
// please note that we have to include 'unsafe-inline' to permit sending the postMessage
src += "&csp=" + escape("script-src 'unsafe-inline'; " + tests[counter].policy);
src += "?csp=" + escape("script-src 'unsafe-inline'; " + tests[counter].csp);
// append potential base tags
src += "&base1=" + escape(tests[counter].base1);
src += "&base2=" + escape(tests[counter].base2);
// append potential action
src += "&action=" + escape(tests[counter].action);
document.getElementById("testframe").src = src;
}

Просмотреть файл

@ -4,6 +4,10 @@
<title>Test for Utility Methods for other FIDO Universal Second Factor tests</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/dom/u2f/tests/u2futil.js"></script>
<script type="text/javascript" src="pkijs/common.js"></script>
<script type="text/javascript" src="pkijs/asn1.js"></script>
<script type="text/javascript" src="pkijs/x509_schema.js"></script>
<script type="text/javascript" src="pkijs/x509_simpl.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>

Просмотреть файл

@ -130,29 +130,33 @@ function assembleRegistrationSignedData(appParam, challengeParam, keyHandle, pub
return signedData;
}
function verifySignature(key, data, derSig) {
if (derSig.byteLength < 70) {
console.log("bad sig: " + hexEncode(derSig))
throw "Invalid signature length: " + derSig.byteLength;
function sanitizeSigArray(arr) {
// ECDSA signature fields into WebCrypto must be exactly 32 bytes long, so
// this method strips leading padding bytes, if added, and also appends
// padding zeros, if needed.
if (arr.length > 32) {
arr = arr.slice(arr.length - 32)
}
var ret = new Uint8Array(32);
ret.set(arr, ret.length - arr.length);
return ret;
}
// Poor man's ASN.1 decode
// R and S are always 32 bytes. If ether has a DER
// length > 32, it's just zeros we can chop off.
var lenR = derSig[3];
var lenS = derSig[3 + lenR + 2];
var padR = lenR - 32;
var padS = lenS - 32;
var sig = new Uint8Array(64);
derSig.slice(4 + padR, 4 + lenR).map((x, i) => sig[i] = x);
derSig.slice(4 + lenR + 2 + padS, 4 + lenR + 2 + lenS).map(
(x, i) => sig[32 + i] = x
);
function verifySignature(key, data, derSig) {
var sigAsn1 = org.pkijs.fromBER(derSig.buffer);
var sigR = new Uint8Array(sigAsn1.result.value_block.value[0].value_block.value_hex);
var sigS = new Uint8Array(sigAsn1.result.value_block.value[1].value_block.value_hex);
console.log("data: " + hexEncode(data));
console.log("der: " + hexEncode(derSig));
console.log("raw: " + hexEncode(sig));
// The resulting R and S values from the ASN.1 Sequence must be fit into 32
// bytes. Sometimes they have leading zeros, sometimes they're too short, it
// all depends on what lib generated the signature.
var R = sanitizeSigArray(sigR);
var S = sanitizeSigArray(sigS);
var sigData = new Uint8Array(R.length + S.length);
sigData.set(R);
sigData.set(S, R.length);
var alg = {name: "ECDSA", hash: "SHA-256"};
return crypto.subtle.verify(alg, key, sig, data);
return crypto.subtle.verify(alg, key, sigData, data);
}

Просмотреть файл

@ -10,6 +10,16 @@
* liability, trademark and document use rules apply.
*/
dictionary EventListenerOptions {
boolean capture = false;
};
dictionary AddEventListenerOptions : EventListenerOptions {
boolean passive = false;
boolean once = false;
};
[Exposed=(Window,Worker,WorkerDebugger,System)]
interface EventTarget {
/* Passing null for wantsUntrusted means "default behavior", which
@ -19,12 +29,12 @@ interface EventTarget {
[Throws]
void addEventListener(DOMString type,
EventListener? listener,
optional boolean capture = false,
optional (AddEventListenerOptions or boolean) options,
optional boolean? wantsUntrusted = null);
[Throws]
void removeEventListener(DOMString type,
EventListener? listener,
optional boolean capture = false);
optional (EventListenerOptions or boolean) options);
[Throws]
boolean dispatchEvent(Event event);
};

Просмотреть файл

@ -0,0 +1,2 @@
// a contains a ZERO WIDTH JOINER (0x200D)
var a = "";

Просмотреть файл

@ -127,6 +127,7 @@ support-files =
importscript_worker.js
bug1151916_worker.js
bug1151916_driver.html
bug1240436_worker.js
notificationclick.html
notificationclick-otherwindow.html
notificationclick.js
@ -204,6 +205,7 @@ support-files =
!/dom/tests/mochitest/notification/NotificationTest.js
[test_bug1151916.html]
[test_bug1240436.html]
[test_claim.html]
[test_claim_fetch.html]
[test_claim_oninstall.html]

Просмотреть файл

@ -0,0 +1,34 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test for encoding of service workers</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function runTest() {
navigator.serviceWorker.register("bug1240436_worker.js")
.then(reg => reg.unregister())
.then(() => ok(true, "service worker register script succeed"))
.catch(err => ok(false, "service worker register script faled " + err))
.then(() => SimpleTest.finish());
}
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -1035,7 +1035,7 @@ nsHTMLEditor::UpdateBaseURL()
// If no base tag, then set baseURL to the document's URL. This is very
// important, else relative URLs for links and images are wrong
if (!nodeList || !nodeList->Item(0)) {
return doc->SetBaseURI(doc->GetDocumentURI());
doc->SetBaseURI(doc->GetDocumentURI());
}
return NS_OK;
}

Просмотреть файл

@ -195,6 +195,31 @@ BufferTextureData::CreateForYCbCr(ClientIPCAllocator* aAllocator,
aTextureFlags);
}
void
BufferTextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = GetSize();
aInfo.format = GetFormat();
aInfo.hasSynchronization = false;
aInfo.canExposeMappedData = true;
if (mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor) {
aInfo.hasIntermediateBuffer = true;
} else {
aInfo.hasIntermediateBuffer = mDescriptor.get_RGBDescriptor().hasIntermediateBuffer();
}
switch (aInfo.format) {
case gfx::SurfaceFormat::YUV:
case gfx::SurfaceFormat::NV12:
case gfx::SurfaceFormat::UNKNOWN:
aInfo.supportsMoz2D = false;
break;
default:
aInfo.supportsMoz2D = true;
}
}
gfx::IntSize
BufferTextureData::GetSize() const
{
@ -207,29 +232,6 @@ BufferTextureData::GetFormat() const
return ImageDataSerializer::FormatFromBufferDescriptor(mDescriptor);
}
bool
BufferTextureData::HasIntermediateBuffer() const
{
if (mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor) {
return true;
}
return mDescriptor.get_RGBDescriptor().hasIntermediateBuffer();
}
bool
BufferTextureData::SupportsMoz2D() const
{
switch (GetFormat()) {
case gfx::SurfaceFormat::YUV:
case gfx::SurfaceFormat::NV12:
case gfx::SurfaceFormat::UNKNOWN:
return false;
default:
return true;
}
}
already_AddRefed<gfx::DrawTarget>
BufferTextureData::BorrowDrawTarget()
{

Просмотреть файл

@ -41,22 +41,14 @@ public:
virtual void Unlock() override {}
virtual gfx::IntSize GetSize() const override;
virtual gfx::SurfaceFormat GetFormat() const override;
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
virtual bool CanExposeMappedData() const override { return true; }
virtual bool BorrowMappedData(MappedTextureData& aMap) override;
virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) override;
virtual bool SupportsMoz2D() const override;
virtual bool HasIntermediateBuffer() const override;
// use TextureClient's default implementation
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
@ -64,6 +56,10 @@ public:
void SetDesciptor(const BufferDescriptor& aDesc);
protected:
gfx::IntSize GetSize() const;
gfx::SurfaceFormat GetFormat() const;
static BufferTextureData* CreateInternal(ClientIPCAllocator* aAllocator,
const BufferDescriptor& aDesc,
gfx::BackendType aMoz2DBackend,

Просмотреть файл

@ -117,6 +117,17 @@ public:
HBITMAP mBitmap;
};
void
DIBTextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = mSize;
aInfo.format = mFormat;
aInfo.hasIntermediateBuffer = true;
aInfo.hasSynchronization = false;
aInfo.supportsMoz2D = true;
aInfo.canExposeMappedData = false;
}
already_AddRefed<gfx::DrawTarget>
DIBTextureData::BorrowDrawTarget()
{
@ -257,7 +268,7 @@ ShmemDIBTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
bool
ShmemDIBTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
return false;
}

Просмотреть файл

@ -22,16 +22,10 @@ public:
virtual void Unlock() override {}
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
virtual bool SupportsMoz2D() const override { return true; }
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
virtual bool HasIntermediateBuffer() const override { return true; }
static
DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
ClientIPCAllocator* aAllocator);

Просмотреть файл

@ -36,14 +36,6 @@ public:
*/
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0;
/**
* Acknowledges the recipt of a scroll offset update for the scrollable
* frame with the given scroll id. This is used to maintain consistency
* between APZ and other sources of scroll changes.
*/
virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration) = 0;
/**
* Requests handling of a double tap. |aPoint| is in CSS pixels, relative to
* the current scroll offset. This should eventually round-trip back to

Просмотреть файл

@ -3456,9 +3456,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
CancelAnimation();
mScrollMetadata = aScrollMetadata;
if (scrollOffsetUpdated) {
AcknowledgeScrollUpdate();
}
mExpectedGeckoMetrics = aLayerMetrics;
ShareCompositorFrameMetrics();
@ -3532,7 +3529,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
// correct this we need to update mExpectedGeckoMetrics to be the
// last thing we know was painted by Gecko.
mFrameMetrics.CopyScrollInfoFrom(aLayerMetrics);
AcknowledgeScrollUpdate();
mExpectedGeckoMetrics = aLayerMetrics;
// Cancel the animation (which might also trigger a repaint request)
@ -3564,7 +3560,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
// See comment on the similar code in the |if (scrollOffsetUpdated)| block
// above.
mFrameMetrics.CopySmoothScrollInfoFrom(aLayerMetrics);
AcknowledgeScrollUpdate();
needContentRepaint = true;
mExpectedGeckoMetrics = aLayerMetrics;
SmoothScrollTo(mFrameMetrics.GetSmoothScrollOffset());
@ -3576,21 +3572,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
UpdateSharedCompositorFrameMetrics();
}
void
AsyncPanZoomController::AcknowledgeScrollUpdate() const
{
// Once layout issues a scroll offset update, it becomes impervious to
// scroll offset updates from APZ until we acknowledge the update it sent.
// This prevents APZ updates from clobbering scroll updates from other
// more "legitimate" sources like content scripts.
RefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
APZC_LOG("%p sending scroll update acknowledgement with gen %u\n", this, mFrameMetrics.GetScrollGeneration());
controller->AcknowledgeScrollUpdate(mFrameMetrics.GetScrollId(),
mFrameMetrics.GetScrollGeneration());
}
}
const FrameMetrics& AsyncPanZoomController::GetFrameMetrics() const {
mMonitor.AssertCurrentThreadIn();
return mFrameMetrics;

Просмотреть файл

@ -896,8 +896,6 @@ private:
// Returns whether overscroll is allowed during an event.
bool AllowScrollHandoffInCurrentBlock() const;
void AcknowledgeScrollUpdate() const;
/* ===================================================================
* The functions and members in this section are used to make ancestor chains
* out of APZC instances. These chains can only be walked or manipulated

Просмотреть файл

@ -124,9 +124,9 @@ ScrollFrame(nsIContent* aContent,
// Scroll the window to the desired spot
nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
if (sf) {
sf->ResetScrollInfoIfGeneration(aMetrics.GetScrollGeneration());
sf->SetScrollableByAPZ(!aMetrics.IsScrollInfoLayer());
}
bool scrollUpdated = false;
CSSPoint apzScrollOffset = aMetrics.GetScrollOffset();
CSSPoint actualScrollOffset = ScrollFrameTo(sf, apzScrollOffset, scrollUpdated);
@ -330,54 +330,6 @@ APZCCallbackHelper::InitializeRootDisplayport(nsIPresShell* aPresShell)
}
}
class AcknowledgeScrollUpdateEvent : public Runnable
{
typedef mozilla::layers::FrameMetrics::ViewID ViewID;
public:
AcknowledgeScrollUpdateEvent(const ViewID& aScrollId, const uint32_t& aScrollGeneration)
: mScrollId(aScrollId)
, mScrollGeneration(aScrollGeneration)
{
}
NS_IMETHOD Run() override {
MOZ_ASSERT(NS_IsMainThread());
nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(mScrollId);
if (sf) {
sf->ResetScrollInfoIfGeneration(mScrollGeneration);
}
// Since the APZ and content are in sync, we need to clear any callback transform
// that might have been set on the last repaint request (which might have failed
// due to the inflight scroll update that this message is acknowledging).
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(mScrollId);
if (content) {
content->SetProperty(nsGkAtoms::apzCallbackTransform, new CSSPoint(),
nsINode::DeleteProperty<CSSPoint>);
}
return NS_OK;
}
protected:
ViewID mScrollId;
uint32_t mScrollGeneration;
};
void
APZCCallbackHelper::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
nsCOMPtr<nsIRunnable> r1 = new AcknowledgeScrollUpdateEvent(aScrollId, aScrollGeneration);
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(r1);
} else {
r1->Run();
}
}
nsIPresShell*
APZCCallbackHelper::GetRootContentDocumentPresShellForContent(nsIContent* aContent)
{

Просмотреть файл

@ -66,11 +66,6 @@ public:
given presShell. */
static void InitializeRootDisplayport(nsIPresShell* aPresShell);
/* Tell layout that we received the scroll offset update for the given view ID, so
that it accepts future scroll offset updates from APZ. */
static void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration);
/* Get the pres shell associated with the root content document enclosing |aContent|. */
static nsIPresShell* GetRootContentDocumentPresShellForContent(nsIContent* aContent);

Просмотреть файл

@ -68,13 +68,6 @@ ChromeProcessController::PostDelayedTask(Task* aTask, int aDelayMs)
MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
}
void
ChromeProcessController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
}
void
ChromeProcessController::Destroy()
{

Просмотреть файл

@ -40,9 +40,6 @@ public:
// GeckoContentController interface
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
virtual void PostDelayedTask(Task* aTask, int aDelayMs) override;
virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration) override;
virtual void HandleDoubleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual void HandleSingleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers,

Просмотреть файл

@ -47,6 +47,16 @@ X11TextureData::Unlock()
}
}
void
X11TextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = mSize;
aInfo.format = mFormat;
aInfo.supportsMoz2D = true;
aInfo.hasIntermediateBuffer = false;
aInfo.hasSynchronization = false;
aInfo.canExposeMappedData = false;
}
bool
X11TextureData::Serialize(SurfaceDescriptor& aOutDescriptor)

Просмотреть файл

@ -25,16 +25,10 @@ public:
virtual void Unlock() override;
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
virtual bool SupportsMoz2D() const override { return true; }
virtual bool HasIntermediateBuffer() const override { return false; }
virtual void Deallocate(ClientIPCAllocator*) override;
virtual TextureData*

Просмотреть файл

@ -73,7 +73,7 @@ ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
#ifdef XP_WIN
if (backend == LayersBackend::LAYERS_D3D11) {
useDoubleBuffering = gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
useDoubleBuffering = gfxWindowsPlatform::GetPlatform()->IsDirect2DBackend();
} else
#endif
#ifdef MOZ_WIDGET_GTK

Просмотреть файл

@ -97,7 +97,6 @@ public:
TextureChild()
: mForwarder(nullptr)
, mMonitor("TextureChild")
, mTextureClient(nullptr)
, mTextureData(nullptr)
, mDestroyed(false)
@ -117,10 +116,10 @@ public:
void WaitForCompositorRecycle()
{
{
MonitorAutoLock mon(mMonitor);
mWaitForRecycle = mDestroyed ? nullptr : mTextureClient;
}
Lock();
mWaitForRecycle = mDestroyed ? nullptr : mTextureClient;
Unlock();
RECYCLE_LOG("[CLIENT] Wait for recycle %p\n", mWaitForRecycle.get());
MOZ_ASSERT(CanSend());
SendClientRecycle();
@ -129,10 +128,10 @@ public:
void CancelWaitForCompositorRecycle()
{
RECYCLE_LOG("[CLIENT] Cancelling wait for recycle %p\n", mWaitForRecycle.get());
{
MonitorAutoLock mon(mMonitor);
mWaitForRecycle = nullptr;
}
Lock();
mWaitForRecycle = nullptr;
Unlock();
}
CompositableForwarder* GetForwarder() { return mForwarder; }
@ -143,6 +142,10 @@ public:
bool IPCOpen() const { return mIPCOpen; }
void Lock() const { mLock.Enter(); }
void Unlock() const { mLock.Leave(); }
private:
// AddIPDLReference and ReleaseIPDLReference are only to be called by CreateIPDLActor
@ -160,16 +163,11 @@ private:
Release();
}
void SetTextureClient(TextureClient* aTextureClient) {
MonitorAutoLock mon(mMonitor);
mTextureClient = aTextureClient;
}
mutable gfx::CriticalSection mLock;
RefPtr<CompositableForwarder> mForwarder;
RefPtr<TextureClient> mWaitForRecycle;
// Monitor protecting mTextureClient.
Monitor mMonitor;
TextureClient* mTextureClient;
TextureData* mTextureData;
Atomic<bool> mDestroyed;
@ -320,12 +318,15 @@ DeallocateTextureClient(TextureDeallocParams params)
void TextureClient::Destroy(bool aForceSync)
{
MOZ_ASSERT(!IsLocked());
if (mActor) {
mActor->Lock();
}
RefPtr<TextureChild> actor = mActor;
mActor = nullptr;
if (actor && !actor->mDestroyed.compareExchange(false, true)) {
actor->Unlock();
actor = nullptr;
}
@ -349,6 +350,14 @@ void TextureClient::Destroy(bool aForceSync)
// client side, but having asynchronous deallocate in some of the cases will
// be a worthwhile optimization.
params.syncDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT) || aForceSync;
// Release the lock before calling DeallocateTextureClient because the latter
// may wait for the main thread which could create a dead-lock.
if (actor) {
actor->Unlock();
}
DeallocateTextureClient(params);
}
}
@ -361,6 +370,22 @@ TextureClient::DestroyFallback(PTextureChild* aActor)
return aActor->SendDestroySync();
}
void
TextureClient::LockActor() const
{
if (mActor) {
mActor->Lock();
}
}
void
TextureClient::UnlockActor() const
{
if (mActor) {
mActor->Unlock();
}
}
bool
TextureClient::Lock(OpenMode aMode)
{
@ -375,6 +400,8 @@ TextureClient::Lock(OpenMode aMode)
mRemoveFromCompositableWaiter = nullptr;
}
LockActor();
mIsLocked = mData->Lock(aMode, mReleaseFenceHandle.IsValid() ? &mReleaseFenceHandle : nullptr);
mOpenMode = aMode;
@ -396,6 +423,10 @@ TextureClient::Lock(OpenMode aMode)
}
}
if (!mIsLocked) {
UnlockActor();
}
return mIsLocked;
}
@ -426,27 +457,8 @@ TextureClient::Unlock()
mData->Unlock();
mIsLocked = false;
mOpenMode = OpenMode::OPEN_NONE;
}
bool
TextureClient::HasIntermediateBuffer() const
{
MOZ_ASSERT(IsValid());
return mData->HasIntermediateBuffer();
}
gfx::IntSize
TextureClient::GetSize() const
{
MOZ_ASSERT(IsValid());
return mData->GetSize();
}
gfx::SurfaceFormat
TextureClient::GetFormat() const
{
MOZ_ASSERT(IsValid());
return mData->GetFormat();
UnlockActor();
}
TextureClient::~TextureClient()
@ -491,7 +503,16 @@ already_AddRefed<TextureClient>
TextureClient::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(!mIsLocked);
if (mIsLocked) {
return nullptr;
}
LockActor();
TextureData* data = mData->CreateSimilar(mAllocator, aFlags, aAllocFlags);
UnlockActor();
if (!data) {
return nullptr;
}
@ -539,21 +560,23 @@ TextureClient::BorrowMappedData(MappedTextureData& aMap)
// return nullptr;
//}
return mData->BorrowMappedData(aMap);
return mData ? mData->BorrowMappedData(aMap) : false;
}
bool
TextureClient::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap)
{
MOZ_ASSERT(IsValid());
return mData->BorrowMappedYCbCrData(aMap);
return mData ? mData->BorrowMappedYCbCrData(aMap) : false;
}
bool
TextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
return mData->Serialize(aOutDescriptor);
return mData ? mData->Serialize(aOutDescriptor) : false;
}
void
@ -590,18 +613,29 @@ TextureClient::DestroyIPDLActor(PTextureChild* actor)
}
// static
TextureClient*
already_AddRefed<TextureClient>
TextureClient::AsTextureClient(PTextureChild* actor)
{
if (!actor) {
return nullptr;
}
TextureChild* tc = static_cast<TextureChild*>(actor);
// TODO: This is not entirely race-free because TextureClient's ref count
// can reach zero on another thread and AsTextureClient gets called before
// Destroy.
tc->Lock();
if (tc->mDestroyed) {
tc->Unlock();
return nullptr;
}
return tc->mTextureClient;
RefPtr<TextureClient> texture = tc->mTextureClient;
tc->Unlock();
return texture.forget();
}
bool
@ -635,6 +669,12 @@ void
TextureClient::RecycleTexture(TextureFlags aFlags)
{
MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE);
MOZ_ASSERT(!mIsLocked);
if (mIsLocked) {
return;
}
LockActor();
mAddedToCompositableClient = false;
if (mFlags != aFlags) {
@ -643,6 +683,8 @@ TextureClient::RecycleTexture(TextureFlags aFlags)
mActor->SendRecycleTexture(mFlags);
}
}
UnlockActor();
}
void
@ -706,6 +748,13 @@ TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
mActor->mForwarder = aForwarder;
mActor->mTextureClient = this;
mActor->mMainThreadOnly = !!(mFlags & TextureFlags::DEALLOCATE_MAIN_THREAD);
// If the TextureClient is already locked, we have to lock TextureChild's mutex
// since it will be unlocked in TextureClient::Unlock.
if (mIsLocked) {
LockActor();
}
return mActor->IPCOpen();
}
@ -922,6 +971,7 @@ TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags, ClientIPCA
, mPoolTracker(nullptr)
#endif
{
mData->FillInfo(mInfo);
mFlags |= mData->GetTextureFlags();
}
@ -984,6 +1034,22 @@ TextureClient::SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter)
mRemoveFromCompositableWaiter = aWaiter;
}
already_AddRefed<gfx::DataSourceSurface>
TextureClient::GetAsSurface()
{
Lock(OpenMode::OPEN_READ);
RefPtr<gfx::DataSourceSurface> data;
RefPtr<gfx::DrawTarget> dt = BorrowDrawTarget();
if (dt) {
RefPtr<gfx::SourceSurface> surf = dt->Snapshot();
if (surf) {
data = surf->GetDataSurface();
}
}
Unlock();
return data.forget();
}
void
TextureClient::PrintInfo(std::stringstream& aStream, const char* aPrefix)
{

Просмотреть файл

@ -24,6 +24,7 @@
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/mozalloc.h" // for operator delete
#include "mozilla/gfx/CriticalSection.h"
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsISupportsImpl.h" // for TextureImage::AddRef, etc
@ -181,26 +182,33 @@ class D3D11TextureData;
class TextureData {
public:
struct Info {
gfx::IntSize size;
gfx::SurfaceFormat format;
bool hasIntermediateBuffer;
bool hasSynchronization;
bool supportsMoz2D;
bool canExposeMappedData;
Info()
: format(gfx::SurfaceFormat::UNKNOWN)
, hasIntermediateBuffer(false)
, hasSynchronization(false)
, supportsMoz2D(false)
, canExposeMappedData(false)
{}
};
TextureData() { MOZ_COUNT_CTOR(TextureData); }
virtual ~TextureData() { MOZ_COUNT_DTOR(TextureData); }
virtual gfx::IntSize GetSize() const = 0;
virtual gfx::SurfaceFormat GetFormat() const = 0;
virtual void FillInfo(TextureData::Info& aInfo) const = 0;
virtual bool Lock(OpenMode aMode, FenceHandle* aFence) = 0;
virtual void Unlock() = 0;
virtual bool SupportsMoz2D() const { return false; }
virtual bool CanExposeMappedData() const { return false; }
virtual bool HasIntermediateBuffer() const = 0;
virtual bool HasSynchronization() const { return false; }
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() { return nullptr; }
virtual bool BorrowMappedData(MappedTextureData&) { return false; }
@ -327,9 +335,29 @@ public:
bool IsLocked() const { return mIsLocked; }
bool CanExposeDrawTarget() const { return mData->SupportsMoz2D(); }
gfx::IntSize GetSize() const { return mInfo.size; }
bool CanExposeMappedData() const { return mData->CanExposeMappedData(); }
gfx::SurfaceFormat GetFormat() const { return mInfo.format; }
/**
* Returns true if this texture has a synchronization mechanism (mutex, fence, etc.).
* Textures that do not implement synchronization should be immutable or should
* use immediate uploads (see TextureFlags in CompositorTypes.h)
* Even if a texture does not implement synchronization, Lock and Unlock need
* to be used appropriately since the latter are also there to map/numap data.
*/
bool HasSynchronization() const { return mInfo.hasSynchronization; }
/**
* Indicates whether the TextureClient implementation is backed by an
* in-memory buffer. The consequence of this is that locking the
* TextureClient does not contend with locking the texture on the host side.
*/
bool HasIntermediateBuffer() const { return mInfo.hasIntermediateBuffer; }
bool CanExposeDrawTarget() const { return mInfo.supportsMoz2D; }
bool CanExposeMappedData() const { return mInfo.canExposeMappedData; }
/**
* Returns a DrawTarget to draw into the TextureClient.
@ -372,25 +400,11 @@ public:
*/
void UpdateFromSurface(gfx::SourceSurface* aSurface);
virtual gfx::SurfaceFormat GetFormat() const;
/**
* This method is strictly for debugging. It causes locking and
* needless copies.
*/
already_AddRefed<gfx::DataSourceSurface> GetAsSurface() {
Lock(OpenMode::OPEN_READ);
RefPtr<gfx::DataSourceSurface> data;
RefPtr<gfx::DrawTarget> dt = BorrowDrawTarget();
if (dt) {
RefPtr<gfx::SourceSurface> surf = dt->Snapshot();
if (surf) {
data = surf->GetDataSurface();
}
}
Unlock();
return data.forget();
}
already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
@ -403,22 +417,6 @@ public:
const gfx::IntRect* aRect,
const gfx::IntPoint* aPoint);
/**
* Returns true if this texture has a synchronization mechanism (mutex, fence, etc.).
* Textures that do not implement synchronization should be immutable or should
* use immediate uploads (see TextureFlags in CompositorTypes.h)
* Even if a texture does not implement synchronization, Lock and Unlock need
* to be used appropriately since the latter are also there to map/numap data.
*/
bool HasSynchronization() const { return false; }
/**
* Indicates whether the TextureClient implementation is backed by an
* in-memory buffer. The consequence of this is that locking the
* TextureClient does not contend with locking the texture on the host side.
*/
bool HasIntermediateBuffer() const;
/**
* Allocate and deallocate a TextureChild actor.
*
@ -435,9 +433,7 @@ public:
/**
* Get the TextureClient corresponding to the actor passed in parameter.
*/
static TextureClient* AsTextureClient(PTextureChild* actor);
gfx::IntSize GetSize() const;
static already_AddRefed<TextureClient> AsTextureClient(PTextureChild* actor);
/**
* TextureFlags contain important information about various aspects
@ -456,6 +452,7 @@ public:
void RemoveFlags(TextureFlags aFlags);
// The TextureClient must not be locked when calling this method.
void RecycleTexture(TextureFlags aFlags);
/**
@ -505,6 +502,7 @@ public:
* Create and init the TextureChild/Parent IPDL actor pair.
*
* Should be called only once per TextureClient.
* The TextureClient must not be locked when calling this method.
*/
bool InitIPDLActor(CompositableForwarder* aForwarder);
@ -618,6 +616,10 @@ protected:
*/
bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor);
void LockActor() const;
void UnlockActor() const;
TextureData::Info mInfo;
RefPtr<ClientIPCAllocator> mAllocator;
RefPtr<TextureChild> mActor;

Просмотреть файл

@ -35,10 +35,15 @@ void
SharedSurfaceTextureData::Deallocate(ClientIPCAllocator*)
{}
gfx::IntSize
SharedSurfaceTextureData::GetSize() const
void
SharedSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const
{
return mSurf->mSize;
aInfo.size = mSurf->mSize;
aInfo.format = gfx::SurfaceFormat::UNKNOWN;
aInfo.hasIntermediateBuffer = false;
aInfo.hasSynchronization = false;
aInfo.supportsMoz2D = false;
aInfo.canExposeMappedData = false;
}
bool

Просмотреть файл

@ -44,13 +44,7 @@ public:
virtual void Unlock() override {}
virtual bool HasIntermediateBuffer() const override { return false; }
virtual gfx::SurfaceFormat GetFormat() const override {
return gfx::SurfaceFormat::UNKNOWN;
}
virtual gfx::IntSize GetSize() const override;
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;

Просмотреть файл

@ -283,11 +283,11 @@ DXGITextureData::PrepareDrawTargetInLock(OpenMode aMode)
}
if (mNeedsClear) {
mDrawTarget->ClearRect(Rect(0, 0, GetSize().width, GetSize().height));
mDrawTarget->ClearRect(Rect(0, 0, mSize.width, mSize.height));
mNeedsClear = false;
}
if (mNeedsClearWhite) {
mDrawTarget->FillRect(Rect(0, 0, GetSize().width, GetSize().height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
mDrawTarget->FillRect(Rect(0, 0, mSize.width, mSize.height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
mNeedsClearWhite = false;
}
@ -300,6 +300,17 @@ D3D11TextureData::Unlock()
UnlockD3DTexture(mTexture.get());
}
void
DXGITextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = mSize;
aInfo.format = mFormat;
aInfo.supportsMoz2D = true;
aInfo.hasIntermediateBuffer = false;
aInfo.hasSynchronization = mHasSynchronization;
}
void
D3D11TextureData::SyncWithObject(SyncObject* aSyncObject)
{
@ -498,12 +509,22 @@ DXGIYCbCrTextureData::Create(ClientIPCAllocator* aAllocator,
aSize, aSizeY, aSizeCbCr);
}
void
DXGIYCbCrTextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = mSize;
aInfo.format = gfx::SurfaceFormat::YUV;
aInfo.supportsMoz2D = false;
aInfo.hasIntermediateBuffer = false;
aInfo.hasSynchronization = false;
}
bool
DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
aOutDescriptor = SurfaceDescriptorDXGIYCbCr(
(WindowsHandle)mHandles[0], (WindowsHandle)mHandles[1], (WindowsHandle)mHandles[2],
GetSize(), mSizeY, mSizeCbCr
mSize, mSizeY, mSizeCbCr
);
return true;
}

Просмотреть файл

@ -24,15 +24,7 @@ class CompositorD3D11;
class DXGITextureData : public TextureData
{
public:
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
virtual bool SupportsMoz2D() const override { return true; }
virtual bool HasIntermediateBuffer() const override { return false; }
virtual bool HasSynchronization() const override { return mHasSynchronization; }
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual bool Serialize(SurfaceDescriptor& aOutDescrptor) override;
@ -139,17 +131,10 @@ public:
virtual void Unlock() override {}
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
// TODO - DXGIYCbCrTextureClient returned true but that looks like a mistake
virtual bool HasIntermediateBuffer() const override{ return false; }
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const override { return gfx::SurfaceFormat::YUV; }
virtual bool SupportsMoz2D() const override { return false; }
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override { return nullptr; }
// This TextureData should not be used in a context where we use CreateSimilar

Просмотреть файл

@ -592,6 +592,17 @@ D3D9TextureData::CreateSimilar(ClientIPCAllocator*, TextureFlags aFlags, Texture
return D3D9TextureData::Create(mSize, mFormat, aAllocFlags);
}
void
D3D9TextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = mSize;
aInfo.format = mFormat;
aInfo.hasIntermediateBuffer = true;
aInfo.supportsMoz2D = true;
aInfo.canExposeMappedData = false;
aInfo.hasSynchronization = false;
}
bool
D3D9TextureData::Lock(OpenMode aMode, FenceHandle*)
{
@ -668,11 +679,11 @@ D3D9TextureData::BorrowDrawTarget()
}
if (mNeedsClear) {
dt->ClearRect(Rect(0, 0, GetSize().width, GetSize().height));
dt->ClearRect(Rect(0, 0, mSize.width, mSize.height));
mNeedsClear = false;
}
if (mNeedsClearWhite) {
dt->FillRect(Rect(0, 0, GetSize().width, GetSize().height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
dt->FillRect(Rect(0, 0, mSize.width, mSize.height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
mNeedsClearWhite = false;
}
@ -774,6 +785,17 @@ DXGID3D9TextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
return data;
}
void
DXGID3D9TextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = GetSize();
aInfo.format = mFormat;
aInfo.supportsMoz2D = false;
aInfo.canExposeMappedData = false;
aInfo.hasIntermediateBuffer = false;
aInfo.hasSynchronization = false;
}
already_AddRefed<IDirect3DSurface9>
DXGID3D9TextureData::GetD3D9Surface() const
{

Просмотреть файл

@ -182,22 +182,16 @@ class D3D9TextureData : public TextureData
public:
~D3D9TextureData();
virtual bool SupportsMoz2D() const override { return true; }
virtual bool HasIntermediateBuffer() const override { return true; }
virtual bool Serialize(SurfaceDescriptor& aOutDescrptor) override;
virtual bool Lock(OpenMode aMode, FenceHandle*) override;
virtual void Unlock() override;
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
virtual TextureData*
@ -236,9 +230,7 @@ public:
~DXGID3D9TextureData();
virtual gfx::IntSize GetSize() const override { return gfx::IntSize(mDesc.Width, mDesc.Height); }
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual bool Lock(OpenMode, FenceHandle*) override { return true; }
@ -246,8 +238,6 @@ public:
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
virtual bool HasIntermediateBuffer() const override { return false; }
virtual void Deallocate(ClientIPCAllocator* aAllocator) override {}
IDirect3DDevice9* GetD3D9Device() { return mDevice; }
@ -260,6 +250,8 @@ public:
return mDesc;
}
gfx::IntSize GetSize() const { return gfx::IntSize(mDesc.Width, mDesc.Height); }
protected:
DXGID3D9TextureData(gfx::SurfaceFormat aFormat,
IDirect3DTexture9* aTexture, HANDLE aHandle,

Просмотреть файл

@ -99,14 +99,6 @@ APZChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
return mBrowser->UpdateFrame(aFrameMetrics);
}
bool
APZChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
return true;
}
bool
APZChild::RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,

Просмотреть файл

@ -28,9 +28,6 @@ public:
virtual bool RecvUpdateFrame(const FrameMetrics& frame) override;
virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration) override;
virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid) override;

Просмотреть файл

@ -39,12 +39,9 @@ LayerTransactionChild::Destroy()
const ManagedContainer<PTextureChild>& textures = ManagedPTextureChild();
for (auto iter = textures.ConstIter(); !iter.Done(); iter.Next()) {
TextureClient* texture = TextureClient::AsTextureClient(iter.Get()->GetKey());
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(iter.Get()->GetKey());
if (texture) {
// TODO: cf bug 1242448.
//gfxDevCrash(gfx::LogReason::TextureAliveAfterShutdown)
// << "A texture is held alive after shutdown (PCompositorBridge)";
texture->Destroy();
}
}

Просмотреть файл

@ -91,7 +91,6 @@ child:
// The following methods correspond to functions on the GeckoContentController
// interface in gfx/layers/apz/public/GeckoContentController.h. Refer to documentation
// in that file for these functions.
async AcknowledgeScrollUpdate(ViewID aScrollId, uint32_t aScrollGeneration);
async HandleDoubleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
async HandleSingleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid, bool aCallTakeFocusForClickFromTap);
async HandleLongTap(CSSPoint point, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);

Просмотреть файл

@ -50,24 +50,6 @@ RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics
}
}
void
RemoteContentController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::AcknowledgeScrollUpdate,
aScrollId, aScrollGeneration));
return;
}
if (CanSend()) {
Unused << SendAcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
}
}
void
RemoteContentController::HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,

Просмотреть файл

@ -42,9 +42,6 @@ public:
// Needs to be called on the main thread.
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration) override;
virtual void HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;

Просмотреть файл

@ -133,6 +133,17 @@ GrallocTextureData::Forget(ClientIPCAllocator* aAllocator)
mGraphicBuffer = nullptr;
}
void
GrallocTextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = mSize;
aInfo.format = mFormat;
aInfo.hasIntermediateBuffer = false;
aInfo.hasSynchronization = true;
aInfo.supportsMoz2D = true;
aInfo.canExposeMappedData = true;
}
bool
GrallocTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{

Просмотреть файл

@ -45,22 +45,12 @@ public:
virtual void Unlock() override;
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
virtual bool CanExposeMappedData() const override { return true; }
virtual bool BorrowMappedData(MappedTextureData& aMap) override;
virtual bool SupportsMoz2D() const override { return true; }
virtual bool HasIntermediateBuffer() const override { return false; }
virtual bool HasSynchronization() const override { return true; }
virtual void Deallocate(ClientIPCAllocator*) override;
virtual void Forget(ClientIPCAllocator*) override;

Просмотреть файл

@ -39,16 +39,15 @@ MacIOSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
return true;
}
gfx::IntSize
MacIOSurfaceTextureData::GetSize() const
void
MacIOSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const
{
return gfx::IntSize(mSurface->GetDevicePixelWidth(), mSurface->GetDevicePixelHeight());
}
gfx::SurfaceFormat
MacIOSurfaceTextureData::GetFormat() const
{
return mSurface->GetFormat();
aInfo.size = gfx::IntSize(mSurface->GetDevicePixelWidth(), mSurface->GetDevicePixelHeight());
aInfo.format = mSurface->GetFormat();
aInfo.hasIntermediateBuffer = false;
aInfo.hasSynchronization = false;
aInfo.supportsMoz2D = false;
aInfo.canExposeMappedData = false;
}
already_AddRefed<gfx::DataSourceSurface>

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше