Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-04-07 15:47:40 -04:00
commit 9ca5e70312
329 changed files with 6350 additions and 3517 deletions

View File

@ -22,4 +22,5 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Merge day clobber
Hitting failures with Taskcluster-based jobs that seem like needs-clobber.

View File

@ -552,8 +552,7 @@ nsContextMenu.prototype = {
const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
if (aNode.namespaceURI == xulNS ||
aNode.nodeType == Node.DOCUMENT_NODE ||
this.isDisabledForEvents(aNode)) {
aNode.nodeType == Node.DOCUMENT_NODE) {
this.shouldDisplay = false;
return;
}
@ -1534,16 +1533,6 @@ nsContextMenu.prototype = {
"contextMenu.hasBGImage = " + this.hasBGImage + "\n";
},
isDisabledForEvents: function(aNode) {
let ownerDoc = aNode.ownerDocument;
return
ownerDoc.defaultView &&
ownerDoc.defaultView
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.isNodeDisabledForEvents(aNode);
},
isTargetATextBox: function(node) {
if (node instanceof HTMLInputElement)
return node.mozIsTextField(false);

View File

@ -50,7 +50,7 @@ _SUBDIR_CONFIG_ARGS="$ac_configure_args"
dnl Set the version number of the libs included with mozilla
dnl ========================================================
MOZJPEG=62
MOZPNG=10616
MOZPNG=10617
NSPR_VERSION=4
NSPR_MINVER=4.10.8
NSS_VERSION=3

View File

@ -46,32 +46,43 @@ function enableOfflineCacheForApp(aPrincipal) {
}
function storeCache(applicationCache, url, file, itemType) {
function storeCache(applicationCache, url, file, itemType, metadata) {
let storage =
Services.cache2.appCacheStorage(LoadContextInfo.default, applicationCache);
let uri = Services.io.newURI(url, null, null);
let nowGMT = new Date().toGMTString();
metadata = metadata || {};
metadata.lastFetched = metadata.lastFetched || nowGMT;
metadata.lastModified = metadata.lastModified || nowGMT;
storage.asyncOpenURI(uri, "", nsICacheStorage.OPEN_TRUNCATE, {
onCacheEntryAvailable:
function (cacheEntry, isNew, appCache, result) {
cacheEntry.setMetaDataElement('request-method', 'GET');
cacheEntry.setMetaDataElement('response-head', 'HTTP/1.1 200 OK\r\n');
cacheEntry.setMetaDataElement("request-method", "GET");
cacheEntry.setMetaDataElement("response-head",
"HTTP/1.1 200 OK\r\n" +
"Date: " + metadata.lastFetched + "\r\n" +
"Last-Modified: " + metadata.lastModified + "\r\n" +
"Cache-Control: no-cache\r\n");
let outputStream = cacheEntry.openOutputStream(0);
// Input-Output stream machinery in order to push nsIFile content into cache
let inputStream = Cc['@mozilla.org/network/file-input-stream;1']
// Input-Output stream machinery in order to push nsIFile content into
// cache
let inputStream = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
inputStream.init(file, 1, -1, null);
let bufferedOutputStream = Cc['@mozilla.org/network/buffered-output-stream;1']
.createInstance(Ci.nsIBufferedOutputStream);
let bufferedOutputStream =
Cc["@mozilla.org/network/buffered-output-stream;1"]
.createInstance(Ci.nsIBufferedOutputStream);
bufferedOutputStream.init(outputStream, 1024);
bufferedOutputStream.writeFrom(inputStream, inputStream.available());
bufferedOutputStream.flush();
bufferedOutputStream.close();
inputStream.close();
cacheEntry.setExpirationTime(0);
cacheEntry.markValid();
debug (file.path + ' -> ' + url + ' (' + itemType + ')');
debug (file.path + " -> " + url + " (" + itemType + ")");
applicationCache.markEntry(url, itemType);
cacheEntry.close();
}
@ -206,8 +217,12 @@ function installCache(app) {
return;
}
let cacheDir = makeFile(app.cachePath)
let cacheDir = makeFile(app.cachePath);
cacheDir.append(app.appId);
let resourcesMetadata = cacheDir.clone();
resourcesMetadata.append('resources_metadata.json');
cacheDir.append('cache');
if (!cacheDir.exists())
return;
@ -218,55 +233,72 @@ function installCache(app) {
return;
let principal = Services.scriptSecurityManager.getAppCodebasePrincipal(
app.origin, app.localId, false);
app.origin, app.localId, false);
enableOfflineCacheForApp(principal);
// If the build has been correctly configured, this should not happen!
// If we install the cache anyway, it won't be updateable. If we don't install
// it, the application won't be useable offline.
let metadataLoaded;
if (!resourcesMetadata.exists()) {
// Not debug, since this is something that should be logged always!
dump("OfflineCacheInstaller: App " + app.appId + " does have an app cache" +
" but does not have a resources_metadata.json file!");
metadataLoaded = Promise.resolve({});
} else {
metadataLoaded = new Promise(
(resolve, reject) =>
readFile(resourcesMetadata, principal, content => resolve(JSON.parse(content))));
}
// Get the url for the manifest.
let appcacheURL = app.appcache_path;
metadataLoaded.then(function(metadata) {
enableOfflineCacheForApp(principal);
// The group ID contains application id and 'f' for not being hosted in
// a browser element, but a mozbrowser iframe.
// See netwerk/cache/nsDiskCacheDeviceSQL.cpp: AppendJARIdentifier
let groupID = appcacheURL + '#' + app.localId+ '+f';
let applicationCache = applicationCacheService.createApplicationCache(groupID);
applicationCache.activate();
// Get the url for the manifest.
let appcacheURL = app.appcache_path;
readFile(cacheManifest, principal, function readAppCache(content) {
let entries = parseAppCache(app, cacheManifest.path, content);
// The group ID contains application id and 'f' for not being hosted in
// a browser element, but a mozbrowser iframe.
// See netwerk/cache/nsDiskCacheDeviceSQL.cpp: AppendJARIdentifier
let groupID = appcacheURL + '#' + app.localId+ '+f';
let applicationCache = applicationCacheService.createApplicationCache(groupID);
applicationCache.activate();
entries.urls.forEach(function processCachedFile(url) {
// Get this nsIFile from cache folder for this URL
// We have absolute urls, so remove the origin part to locate the
// files.
let path = url.replace(app.origin.spec, '');
let file = cacheDir.clone();
let paths = path.split('/');
paths.forEach(file.append);
readFile(cacheManifest, principal, function readAppCache(content) {
let entries = parseAppCache(app, cacheManifest.path, content);
if (!file.exists()) {
let msg = 'File ' + file.path + ' exists in the manifest but does ' +
'not points to a real file.';
throw new Error(msg);
}
entries.urls.forEach(function processCachedFile(url) {
// Get this nsIFile from cache folder for this URL
// We have absolute urls, so remove the origin part to locate the
// files.
let path = url.replace(app.origin.spec, '');
let file = cacheDir.clone();
let paths = path.split('/');
paths.forEach(file.append);
let itemType = nsIApplicationCache.ITEM_EXPLICIT;
if (entries.fallbacks.indexOf(url) > -1) {
debug('add fallback: ' + url + '\n');
itemType |= nsIApplicationCache.ITEM_FALLBACK;
}
storeCache(applicationCache, url, file, itemType);
if (!file.exists()) {
let msg = 'File ' + file.path + ' exists in the manifest but does ' +
'not points to a real file.';
throw new Error(msg);
}
let itemType = nsIApplicationCache.ITEM_EXPLICIT;
if (entries.fallbacks.indexOf(url) > -1) {
debug('add fallback: ' + url + '\n');
itemType |= nsIApplicationCache.ITEM_FALLBACK;
}
storeCache(applicationCache, url, file, itemType, metadata[path]);
});
let array = new MutableArray();
entries.namespaces.forEach(function processNamespace([type, spec, data]) {
debug('add namespace: ' + type + ' - ' + spec + ' - ' + data + '\n');
array.appendElement(new Namespace(type, spec, data), false);
});
applicationCache.addNamespaces(array);
storeCache(applicationCache, appcacheURL, cacheManifest,
nsIApplicationCache.ITEM_MANIFEST);
});
let array = new MutableArray();
entries.namespaces.forEach(function processNamespace([type, spec, data]) {
debug('add namespace: ' + type + ' - ' + spec + ' - ' + data + '\n');
array.appendElement(new Namespace(type, spec, data), false);
});
applicationCache.addNamespaces(array);
storeCache(applicationCache, appcacheURL, cacheManifest,
nsIApplicationCache.ITEM_MANIFEST);
});
}

View File

@ -125,8 +125,7 @@ public:
void FailConnection(uint16_t reasonCode,
const nsACString& aReasonString = EmptyCString());
nsresult CloseConnection(uint16_t reasonCode,
const nsACString& aReasonString = EmptyCString(),
bool aCanceling = false);
const nsACString& aReasonString = EmptyCString());
nsresult Disconnect();
void DisconnectInternal();
@ -385,38 +384,6 @@ WebSocketImpl::PrintErrorOnConsole(const char *aBundleURI,
namespace {
class CloseRunnable final : public WorkerMainThreadRunnable
{
public:
CloseRunnable(WebSocketImpl* aImpl, uint16_t aReasonCode,
const nsACString& aReasonString)
: WorkerMainThreadRunnable(aImpl->mWorkerPrivate)
, mImpl(aImpl)
, mReasonCode(aReasonCode)
, mReasonString(aReasonString)
, mRv(NS_ERROR_FAILURE)
{ }
bool MainThreadRun() override
{
mRv = mImpl->mChannel->Close(mReasonCode, mReasonString);
return true;
}
nsresult ErrorCode() const
{
return mRv;
}
private:
// A raw pointer because this runnable is sync.
WebSocketImpl* mImpl;
uint16_t mReasonCode;
const nsACString& mReasonString;
nsresult mRv;
};
class CancelWebSocketRunnable final : public nsRunnable
{
public:
@ -469,11 +436,9 @@ private:
nsresult
WebSocketImpl::CloseConnection(uint16_t aReasonCode,
const nsACString& aReasonString,
bool aCanceling)
const nsACString& aReasonString)
{
AssertIsOnTargetThread();
MOZ_ASSERT(!NS_IsMainThread() || !aCanceling);
if (mDisconnectingOrDisconnected) {
return NS_OK;
@ -500,16 +465,9 @@ WebSocketImpl::CloseConnection(uint16_t aReasonCode,
return mChannel->Close(aReasonCode, aReasonString);
}
if (aCanceling) {
nsRefPtr<CancelWebSocketRunnable> runnable =
new CancelWebSocketRunnable(mChannel, aReasonCode, aReasonString);
return NS_DispatchToMainThread(runnable);
}
nsRefPtr<CloseRunnable> runnable =
new CloseRunnable(this, aReasonCode, aReasonString);
runnable->Dispatch(mWorkerPrivate->GetJSContext());
return runnable->ErrorCode();
nsRefPtr<CancelWebSocketRunnable> runnable =
new CancelWebSocketRunnable(mChannel, aReasonCode, aReasonString);
return NS_DispatchToMainThread(runnable);
}
// No channel, but not disconnected: canceled or failed early
@ -2033,7 +1991,7 @@ public:
}
mWebSocketImpl->CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY,
EmptyCString(), true);
EmptyCString());
}
return true;

View File

@ -340,19 +340,18 @@ nsFrameLoader::ReallyStartLoadingInternal()
}
if (mRemoteFrame) {
if (!mRemoteBrowser) {
TryRemoteBrowser();
if (!mRemoteBrowser) {
if (!mRemoteBrowser && !TryRemoteBrowser()) {
NS_WARNING("Couldn't create child process for iframe.");
return NS_ERROR_FAILURE;
}
}
if (mRemoteBrowserShown || ShowRemoteFrame(ScreenIntSize(0, 0))) {
// FIXME get error codes from child
mRemoteBrowser->LoadURL(mURIToLoad);
} else {
// Execute pending frame scripts before loading URL
EnsureMessageManager();
// FIXME get error codes from child
mRemoteBrowser->LoadURL(mURIToLoad);
if (!mRemoteBrowserShown && !ShowRemoteFrame(ScreenIntSize(0, 0))) {
NS_WARNING("[nsFrameLoader] ReallyStartLoadingInternal tried but couldn't show remote browser.\n");
}
@ -832,13 +831,9 @@ nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
{
NS_ASSERTION(mRemoteFrame, "ShowRemote only makes sense on remote frames.");
if (!mRemoteBrowser) {
TryRemoteBrowser();
if (!mRemoteBrowser) {
NS_ERROR("Couldn't create child process.");
return false;
}
if (!mRemoteBrowser && !TryRemoteBrowser()) {
NS_ERROR("Couldn't create child process.");
return false;
}
// FIXME/bug 589337: Show()/Hide() is pretty expensive for
@ -2262,28 +2257,31 @@ nsFrameLoader::TryRemoteBrowser()
nsCOMPtr<Element> ownerElement = mOwnerContent;
mRemoteBrowser = ContentParent::CreateBrowserOrApp(context, ownerElement, openerContentParent);
if (mRemoteBrowser) {
mChildID = mRemoteBrowser->Manager()->ChildID();
nsCOMPtr<nsIDocShellTreeItem> rootItem;
parentDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsIDOMWindow> rootWin = rootItem->GetWindow();
nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin);
if (rootChromeWin) {
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
}
mContentParent = mRemoteBrowser->Manager();
if (mOwnerContent->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::mozpasspointerevents,
nsGkAtoms::_true,
eCaseMatters)) {
unused << mRemoteBrowser->SendSetUpdateHitRegion(true);
}
if (!mRemoteBrowser) {
return false;
}
mContentParent = mRemoteBrowser->Manager();
mChildID = mRemoteBrowser->Manager()->ChildID();
nsCOMPtr<nsIDocShellTreeItem> rootItem;
parentDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsIDOMWindow> rootWin = rootItem->GetWindow();
nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin);
if (rootChromeWin) {
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
}
if (mOwnerContent->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::mozpasspointerevents,
nsGkAtoms::_true,
eCaseMatters)) {
unused << mRemoteBrowser->SendSetUpdateHitRegion(true);
}
return true;
}
@ -2528,7 +2526,7 @@ nsFrameLoader::EnsureMessageManager()
bool useRemoteProcess = ShouldUseRemoteProcess();
if (mMessageManager) {
if (useRemoteProcess && mRemoteBrowserShown) {
if (useRemoteProcess && mRemoteBrowser) {
mMessageManager->InitWithCallback(this);
}
return NS_OK;
@ -2553,7 +2551,7 @@ nsFrameLoader::EnsureMessageManager()
}
if (useRemoteProcess) {
mMessageManager = new nsFrameMessageManager(mRemoteBrowserShown ? this : nullptr,
mMessageManager = new nsFrameMessageManager(mRemoteBrowser ? this : nullptr,
static_cast<nsFrameMessageManager*>(parentManager.get()),
MM_CHROME);
} else {

View File

@ -260,6 +260,7 @@ nsInProcessTabChildGlobal::GetOwnerContent()
nsresult
nsInProcessTabChildGlobal::PreHandleEvent(EventChainPreVisitor& aVisitor)
{
aVisitor.mForceContentDispatch = true;
aVisitor.mCanHandle = true;
#ifdef DEBUG

View File

@ -299,7 +299,7 @@ CanvasImageCache::Lookup(Element* aImage,
gImageCache->MarkUsed(entry->mData);
*aSize = gfx::ToIntSize(entry->mData->mSize);
*aSize = entry->mData->mSize;
return entry->mData->mSourceSurface;
}

View File

@ -4320,7 +4320,7 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
return;
}
imgSize = gfx::ToIntSize(res.mSize);
imgSize = res.mSize;
// Scale sw/sh based on aspect ratio
if (image.IsHTMLVideoElement()) {

View File

@ -55,7 +55,6 @@
#if defined(XP_WIN)
#define TARGET_SANDBOX_EXPORTS
#include "mozilla/sandboxTarget.h"
#include "nsDirectoryServiceDefs.h"
#elif defined(XP_LINUX)
#include "mozilla/Sandbox.h"
#include "mozilla/SandboxInfo.h"
@ -1080,76 +1079,6 @@ ContentChild::AllocPProcessHangMonitorChild(Transport* aTransport,
return CreateHangMonitorChild(aTransport, aOtherProcess);
}
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
static void
SetUpSandboxEnvironment()
{
// Set up a low integrity temp directory. This only makes sense if the
// delayed integrity level for the content process is INTEGRITY_LEVEL_LOW.
nsresult rv;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIFile> lowIntegrityTemp;
rv = directoryService->Get(NS_WIN_LOW_INTEGRITY_TEMP, NS_GET_IID(nsIFile),
getter_AddRefs(lowIntegrityTemp));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Undefine returns a failure if the property is not already set.
unused << directoryService->Undefine(NS_OS_TEMP_DIR);
rv = directoryService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Set TEMP and TMP environment variables.
nsAutoString lowIntegrityTempPath;
rv = lowIntegrityTemp->GetPath(lowIntegrityTempPath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
bool setOK = SetEnvironmentVariableW(L"TEMP", lowIntegrityTempPath.get());
NS_WARN_IF_FALSE(setOK, "Failed to set TEMP to low integrity temp path");
setOK = SetEnvironmentVariableW(L"TMP", lowIntegrityTempPath.get());
NS_WARN_IF_FALSE(setOK, "Failed to set TMP to low integrity temp path");
}
void
ContentChild::CleanUpSandboxEnvironment()
{
// Sandbox environment is only currently a low integrity temp, which only
// makes sense for sandbox pref level 1 (and will eventually not be needed
// at all, once all file access is via chrome/broker process).
if (Preferences::GetInt("security.sandbox.content.level") != 1) {
return;
}
nsresult rv;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIFile> lowIntegrityTemp;
rv = directoryService->Get(NS_WIN_LOW_INTEGRITY_TEMP, NS_GET_IID(nsIFile),
getter_AddRefs(lowIntegrityTemp));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Don't check the return value as the directory will only have been created
// if it has been used.
unused << lowIntegrityTemp->Remove(/* aRecursive */ true);
}
#endif
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
#include <stdlib.h>
@ -1268,12 +1197,6 @@ ContentChild::RecvSetProcessSandbox()
SetContentProcessSandbox();
#elif defined(XP_WIN)
mozilla::SandboxTarget::Instance()->StartSandbox();
// Sandbox environment is only currently a low integrity temp, which only
// makes sense for sandbox pref level 1 (and will eventually not be needed
// at all, once all file access is via chrome/broker process).
if (Preferences::GetInt("security.sandbox.content.level") == 1) {
SetUpSandboxEnvironment();
}
#elif defined(XP_MACOSX)
StartMacOSContentSandbox();
#endif

View File

@ -135,11 +135,6 @@ public:
AllocPProcessHangMonitorChild(Transport* aTransport,
ProcessId aOtherProcess) override;
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
// Cleans up any resources used by the process when sandboxed.
void CleanUpSandboxEnvironment();
#endif
virtual bool RecvSetProcessSandbox() override;
PBackgroundChild*

View File

@ -8,11 +8,87 @@
#include "ContentProcess.h"
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
#include "mozilla/Preferences.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#endif
using mozilla::ipc::IOThreadChild;
namespace mozilla {
namespace dom {
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
static already_AddRefed<nsIFile>
GetLowIntegrityTemp()
{
MOZ_ASSERT(nsDirectoryService::gService,
"GetLowIntegrityTemp relies on nsDirectoryService being initialized");
// A low integrity temp only currently makes sense for sandbox pref level 1.
if (Preferences::GetInt("security.sandbox.content.level") != 1) {
return nullptr;
}
nsCOMPtr<nsIFile> lowIntegrityTemp;
nsresult rv = nsDirectoryService::gService->Get(NS_WIN_LOW_INTEGRITY_TEMP,
NS_GET_IID(nsIFile),
getter_AddRefs(lowIntegrityTemp));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
return lowIntegrityTemp.forget();
}
static void
SetUpSandboxEnvironment()
{
MOZ_ASSERT(nsDirectoryService::gService,
"SetUpSandboxEnvironment relies on nsDirectoryService being initialized");
// Setup to use a low integrity temp if available.
nsCOMPtr<nsIFile> lowIntegrityTemp = GetLowIntegrityTemp();
if (!lowIntegrityTemp) {
return;
}
// Undefine returns a failure if the property is not already set.
unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR);
nsresult rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Set TEMP and TMP environment variables.
nsAutoString lowIntegrityTempPath;
rv = lowIntegrityTemp->GetPath(lowIntegrityTempPath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
bool setOK = SetEnvironmentVariableW(L"TEMP", lowIntegrityTempPath.get());
NS_WARN_IF_FALSE(setOK, "Failed to set TEMP to low integrity temp path");
setOK = SetEnvironmentVariableW(L"TMP", lowIntegrityTempPath.get());
NS_WARN_IF_FALSE(setOK, "Failed to set TMP to low integrity temp path");
}
static void
CleanUpSandboxEnvironment()
{
// Remove low integrity temp if it exists.
nsCOMPtr<nsIFile> lowIntegrityTemp = GetLowIntegrityTemp();
if (!lowIntegrityTemp) {
return;
}
// Don't check the return value as the directory will only have been created
// if it has been used.
unused << lowIntegrityTemp->Remove(/* aRecursive */ true);
}
#endif
void
ContentProcess::SetAppDir(const nsACString& aPath)
{
@ -27,6 +103,10 @@ ContentProcess::Init()
IOThreadChild::channel());
mXREEmbed.Start();
mContent.InitXPCOM();
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
SetUpSandboxEnvironment();
#endif
return true;
}
@ -35,7 +115,7 @@ void
ContentProcess::CleanUp()
{
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
mContent.CleanUpSandboxEnvironment();
CleanUpSandboxEnvironment();
#endif
mXREEmbed.Stop();
}

View File

@ -1693,6 +1693,10 @@ bool
TabChild::RecvLoadURL(const nsCString& aURI,
const BrowserConfiguration& aConfiguration)
{
if (!InitTabChildGlobal()) {
return false;
}
SetProcessNameToAppName();
nsresult rv = WebNavigation()->LoadURI(NS_ConvertUTF8toUTF16(aURI).get(),

View File

@ -266,7 +266,6 @@ TabParent::TabParent(nsIContentParent* aManager,
, mOrientation(0)
, mDPI(0)
, mDefaultScale(0)
, mShown(false)
, mUpdatedDimensions(false)
, mChromeOffset(0, 0)
, mManager(aManager)
@ -754,13 +753,6 @@ TabParent::LoadURL(nsIURI* aURI)
return;
}
if (!mShown) {
NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
"Show(). Ignoring LoadURL.\n",
spec.get()).get());
return;
}
uint32_t appId = OwnOrContainingAppId();
if (mSendOfflineStatus && NS_IsAppOffline(appId)) {
// If the app is offline in the parent process
@ -824,8 +816,6 @@ TabParent::LoadURL(nsIURI* aURI)
void
TabParent::Show(const ScreenIntSize& size, bool aParentIsActive)
{
// sigh
mShown = true;
mDimensions = size;
if (mIsDestroyed) {
return;

View File

@ -429,7 +429,6 @@ protected:
ScreenOrientation mOrientation;
float mDPI;
CSSToLayoutDeviceScale mDefaultScale;
bool mShown;
bool mUpdatedDimensions;
nsIntPoint mChromeOffset;

View File

@ -1,319 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "AVCCDecoderModule.h"
#include "ImageContainer.h"
#include "MediaTaskQueue.h"
#include "mp4_demuxer/DecoderData.h"
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
namespace mozilla
{
class AVCCMediaDataDecoder : public MediaDataDecoder {
public:
AVCCMediaDataDecoder(PlatformDecoderModule* aPDM,
const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback);
virtual ~AVCCMediaDataDecoder();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
virtual bool IsWaitingMediaResources() override;
virtual bool IsDormantNeeded() override;
virtual void AllocateMediaResources() override;
virtual void ReleaseMediaResources() override;
virtual bool IsHardwareAccelerated() const override;
private:
// Will create the required MediaDataDecoder if we have a AVC SPS.
// Returns NS_ERROR_FAILURE if error is permanent and can't be recovered and
// will set mError accordingly.
nsresult CreateDecoder();
nsresult CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample);
nsresult CheckForSPSChange(mp4_demuxer::MP4Sample* aSample);
void UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData);
nsRefPtr<PlatformDecoderModule> mPDM;
mp4_demuxer::VideoDecoderConfig mCurrentConfig;
layers::LayersBackend mLayersBackend;
nsRefPtr<layers::ImageContainer> mImageContainer;
nsRefPtr<FlushableMediaTaskQueue> mVideoTaskQueue;
MediaDataDecoderCallback* mCallback;
nsRefPtr<MediaDataDecoder> mDecoder;
nsresult mLastError;
};
AVCCMediaDataDecoder::AVCCMediaDataDecoder(PlatformDecoderModule* aPDM,
const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
: mPDM(aPDM)
, mCurrentConfig(aConfig)
, mLayersBackend(aLayersBackend)
, mImageContainer(aImageContainer)
, mVideoTaskQueue(aVideoTaskQueue)
, mCallback(aCallback)
, mDecoder(nullptr)
, mLastError(NS_OK)
{
CreateDecoder();
}
AVCCMediaDataDecoder::~AVCCMediaDataDecoder()
{
}
nsresult
AVCCMediaDataDecoder::Init()
{
if (mDecoder) {
return mDecoder->Init();
}
return mLastError;
}
nsresult
AVCCMediaDataDecoder::Input(mp4_demuxer::MP4Sample* aSample)
{
if (!mp4_demuxer::AnnexB::ConvertSampleToAVCC(aSample)) {
return NS_ERROR_FAILURE;
}
nsresult rv;
if (!mDecoder) {
// It is not possible to create an AVCC H264 decoder without SPS.
// As such, creation will fail if the extra_data just extracted doesn't
// contain a SPS.
rv = CreateDecoderAndInit(aSample);
if (rv == NS_ERROR_NOT_INITIALIZED) {
// We are missing the required SPS to create the decoder.
// Ignore for the time being, the MP4Sample will be dropped.
return NS_OK;
}
} else {
rv = CheckForSPSChange(aSample);
}
NS_ENSURE_SUCCESS(rv, rv);
aSample->extra_data = mCurrentConfig.extra_data;
return mDecoder->Input(aSample);
}
nsresult
AVCCMediaDataDecoder::Flush()
{
if (mDecoder) {
return mDecoder->Flush();
}
return mLastError;
}
nsresult
AVCCMediaDataDecoder::Drain()
{
if (mDecoder) {
return mDecoder->Drain();
}
return mLastError;
}
nsresult
AVCCMediaDataDecoder::Shutdown()
{
if (mDecoder) {
nsresult rv = mDecoder->Shutdown();
mDecoder = nullptr;
return rv;
}
return NS_OK;
}
bool
AVCCMediaDataDecoder::IsWaitingMediaResources()
{
if (mDecoder) {
return mDecoder->IsWaitingMediaResources();
}
return MediaDataDecoder::IsWaitingMediaResources();
}
bool
AVCCMediaDataDecoder::IsDormantNeeded()
{
return true;
}
void
AVCCMediaDataDecoder::AllocateMediaResources()
{
// Nothing to do, decoder will be allocated on the fly when required.
}
void
AVCCMediaDataDecoder::ReleaseMediaResources()
{
Shutdown();
}
nsresult
AVCCMediaDataDecoder::CreateDecoder()
{
if (!mp4_demuxer::AnnexB::HasSPS(mCurrentConfig.extra_data)) {
// nothing found yet, will try again later
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(mCurrentConfig.extra_data);
mDecoder = mPDM->CreateVideoDecoder(mCurrentConfig,
mLayersBackend,
mImageContainer,
mVideoTaskQueue,
mCallback);
if (!mDecoder) {
mLastError = NS_ERROR_FAILURE;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
AVCCMediaDataDecoder::CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(extra_data);
nsresult rv = CreateDecoder();
NS_ENSURE_SUCCESS(rv, rv);
return Init();
}
bool
AVCCMediaDataDecoder::IsHardwareAccelerated() const
{
if (mDecoder) {
return mDecoder->IsHardwareAccelerated();
}
return MediaDataDecoder::IsHardwareAccelerated();
}
nsresult
AVCCMediaDataDecoder::CheckForSPSChange(mp4_demuxer::MP4Sample* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data) ||
mp4_demuxer::AnnexB::CompareExtraData(extra_data,
mCurrentConfig.extra_data)) {
return NS_OK;
}
// The SPS has changed, signal to flush the current decoder and create a
// new one.
mDecoder->Flush();
ReleaseMediaResources();
return CreateDecoderAndInit(aSample);
}
void
AVCCMediaDataDecoder::UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData)
{
mp4_demuxer::SPSData spsdata;
if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtraData, spsdata) &&
spsdata.pic_width > 0 && spsdata.pic_height > 0) {
mp4_demuxer::H264::EnsureSPSIsSane(spsdata);
mCurrentConfig.image_width = spsdata.pic_width;
mCurrentConfig.image_height = spsdata.pic_height;
mCurrentConfig.display_width = spsdata.display_width;
mCurrentConfig.display_height = spsdata.display_height;
}
mCurrentConfig.extra_data = aExtraData;
}
// AVCCDecoderModule
AVCCDecoderModule::AVCCDecoderModule(PlatformDecoderModule* aPDM)
: mPDM(aPDM)
{
MOZ_ASSERT(aPDM);
}
AVCCDecoderModule::~AVCCDecoderModule()
{
}
nsresult
AVCCDecoderModule::Startup()
{
return mPDM->Startup();
}
already_AddRefed<MediaDataDecoder>
AVCCDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
{
nsRefPtr<MediaDataDecoder> decoder;
if ((!aConfig.mime_type.EqualsLiteral("video/avc") &&
!aConfig.mime_type.EqualsLiteral("video/mp4")) ||
!mPDM->DecoderNeedsAVCC(aConfig)) {
// There is no need for an AVCC wrapper for non-AVC content.
decoder = mPDM->CreateVideoDecoder(aConfig,
aLayersBackend,
aImageContainer,
aVideoTaskQueue,
aCallback);
} else {
decoder = new AVCCMediaDataDecoder(mPDM,
aConfig,
aLayersBackend,
aImageContainer,
aVideoTaskQueue,
aCallback);
}
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
AVCCDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
return mPDM->CreateAudioDecoder(aConfig,
aAudioTaskQueue,
aCallback);
}
bool
AVCCDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType)
{
return mPDM->SupportsAudioMimeType(aMimeType);
}
bool
AVCCDecoderModule::SupportsVideoMimeType(const nsACString& aMimeType)
{
return mPDM->SupportsVideoMimeType(aMimeType);
}
} // namespace mozilla

View File

@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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_AVCCDecoderModule_h
#define mozilla_AVCCDecoderModule_h
#include "PlatformDecoderModule.h"
namespace mozilla {
class AVCCMediaDataDecoder;
// AVCCDecoderModule is a PlatformDecoderModule wrapper used to ensure that
// only AVCC format is fed to the underlying PlatformDecoderModule.
// The AVCCDecoderModule allows playback of content where the SPS NAL may not be
// provided in the init segment (e.g. AVC3 or Annex B)
// AVCCDecoderModule will monitor the input data, and will delay creation of the
// MediaDataDecoder until a SPS and PPS NALs have been extracted.
//
// AVCC-only decoder modules are AppleVideoDecoder and EMEH264Decoder.
class AVCCDecoderModule : public PlatformDecoderModule {
public:
explicit AVCCDecoderModule(PlatformDecoderModule* aPDM);
virtual ~AVCCDecoderModule();
virtual nsresult Startup() override;
virtual already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual bool SupportsAudioMimeType(const nsACString& aMimeType) override;
virtual bool SupportsVideoMimeType(const nsACString& aMimeType) override;
private:
nsRefPtr<PlatformDecoderModule> mPDM;
};
} // namespace mozilla
#endif // mozilla_AVCCDecoderModule_h

View File

@ -238,11 +238,17 @@ public:
}
virtual bool
SupportsAudioMimeType(const nsACString& aMimeType) override
SupportsMimeType(const nsACString& aMimeType) override
{
return true;
}
ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
return kNeedNone;
}
};
already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule()

View File

@ -158,6 +158,7 @@ MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder)
, mIsEncrypted(false)
, mAreDecodersSetup(false)
, mIndexReady(false)
, mLastSeenEnd(-1)
, mDemuxerMonitor("MP4 Demuxer")
#if defined(MP4_READER_DORMANT_HEURISTIC)
, mDormantEnabled(Preferences::GetBool("media.decoder.heuristic.dormant.enabled", false))
@ -343,7 +344,7 @@ MP4Reader::IsSupportedAudioMimeType(const nsACString& aMimeType)
{
return (aMimeType.EqualsLiteral("audio/mpeg") ||
aMimeType.EqualsLiteral("audio/mp4a-latm")) &&
mPlatform->SupportsAudioMimeType(aMimeType);
mPlatform->SupportsMimeType(aMimeType);
}
bool
@ -352,7 +353,7 @@ MP4Reader::IsSupportedVideoMimeType(const nsACString& aMimeType)
return (aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc") ||
aMimeType.EqualsLiteral("video/x-vnd.on2.vp6")) &&
mPlatform->SupportsVideoMimeType(aMimeType);
mPlatform->SupportsMimeType(aMimeType);
}
void
@ -513,9 +514,10 @@ MP4Reader::EnsureDecodersSetup()
NS_ENSURE_TRUE(IsSupportedAudioMimeType(mDemuxer->AudioConfig().mime_type),
false);
mAudio.mDecoder = mPlatform->CreateAudioDecoder(mDemuxer->AudioConfig(),
mAudio.mTaskQueue,
mAudio.mCallback);
mAudio.mDecoder =
mPlatform->CreateDecoder(mDemuxer->AudioConfig(),
mAudio.mTaskQueue,
mAudio.mCallback);
NS_ENSURE_TRUE(mAudio.mDecoder != nullptr, false);
nsresult rv = mAudio.mDecoder->Init();
NS_ENSURE_SUCCESS(rv, false);
@ -534,11 +536,12 @@ MP4Reader::EnsureDecodersSetup()
mVideo.mTaskQueue,
mVideo.mCallback);
} else {
mVideo.mDecoder = mPlatform->CreateVideoDecoder(mDemuxer->VideoConfig(),
mLayersBackendType,
mDecoder->GetImageContainer(),
mVideo.mTaskQueue,
mVideo.mCallback);
mVideo.mDecoder =
mPlatform->CreateDecoder(mDemuxer->VideoConfig(),
mVideo.mTaskQueue,
mVideo.mCallback,
mLayersBackendType,
mDecoder->GetImageContainer());
}
NS_ENSURE_TRUE(mVideo.mDecoder != nullptr, false);
nsresult rv = mVideo.mDecoder->Init();
@ -600,7 +603,7 @@ MP4Reader::DisableHardwareAcceleration()
mSharedDecoderManager->DisableHardwareAcceleration();
const VideoDecoderConfig& video = mDemuxer->VideoConfig();
if (!mSharedDecoderManager->Recreate(video, mLayersBackendType, mDecoder->GetImageContainer())) {
if (!mSharedDecoderManager->Recreate(video)) {
MonitorAutoLock mon(mVideo.mMonitor);
mVideo.mError = true;
if (mVideo.HasPromise()) {
@ -1158,4 +1161,39 @@ MP4Reader::VideoIsHardwareAccelerated() const
return mVideo.mDecoder && mVideo.mDecoder->IsHardwareAccelerated();
}
void
MP4Reader::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
{
MOZ_ASSERT(NS_IsMainThread());
if (mShutdown) {
return;
}
if (mLastSeenEnd < 0) {
MonitorAutoLock mon(mDemuxerMonitor);
mLastSeenEnd = mDecoder->GetResource()->GetLength();
if (mLastSeenEnd < 0) {
// We dont have a length. Demuxer would have been blocking already.
return;
}
}
int64_t end = aOffset + aLength;
if (end <= mLastSeenEnd) {
return;
}
mLastSeenEnd = end;
if (HasVideo()) {
auto& decoder = GetDecoderData(kVideo);
MonitorAutoLock lock(decoder.mMonitor);
decoder.mDemuxEOS = false;
}
if (HasAudio()) {
auto& decoder = GetDecoderData(kAudio);
MonitorAutoLock lock(decoder.mMonitor);
decoder.mDemuxEOS = false;
}
}
} // namespace mozilla

View File

@ -77,6 +77,7 @@ public:
virtual bool IsMediaSeekable() override;
virtual int64_t GetEvictionOffset(double aTime) override;
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) override;
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) override;
@ -287,6 +288,7 @@ private:
bool mAreDecodersSetup;
bool mIndexReady;
int64_t mLastSeenEnd;
Monitor mDemuxerMonitor;
nsRefPtr<SharedDecoderManager> mSharedDecoderManager;

View File

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PlatformDecoderModule.h"
#include "AVCCDecoderModule.h"
#ifdef XP_WIN
#include "WMFDecoderModule.h"
@ -32,6 +31,9 @@
#include "SharedThreadPool.h"
#include "MediaTaskQueue.h"
#include "mp4_demuxer/DecoderData.h"
#include "H264Converter.h"
namespace mozilla {
extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
@ -107,10 +109,7 @@ PlatformDecoderModule::CreateCDMWrapper(CDMProxy* aProxy,
}
nsRefPtr<PlatformDecoderModule> emepdm(
new AVCCDecoderModule(new EMEDecoderModule(aProxy,
pdm,
cdmDecodesAudio,
cdmDecodesVideo)));
new EMEDecoderModule(aProxy, pdm, cdmDecodesAudio, cdmDecodesVideo));
return emepdm.forget();
}
#endif
@ -151,13 +150,12 @@ PlatformDecoderModule::CreatePDM()
if (sFFmpegDecoderEnabled) {
nsRefPtr<PlatformDecoderModule> m = FFmpegRuntimeLinker::CreateDecoderModule();
if (m) {
nsRefPtr<PlatformDecoderModule> m2(new AVCCDecoderModule(m));
return m2.forget();
return m.forget();
}
}
#endif
#ifdef MOZ_APPLEMEDIA
nsRefPtr<PlatformDecoderModule> m(new AVCCDecoderModule(new AppleDecoderModule()));
nsRefPtr<PlatformDecoderModule> m(new AppleDecoderModule());
return m.forget();
#endif
#ifdef MOZ_GONK_MEDIACODEC
@ -173,28 +171,55 @@ PlatformDecoderModule::CreatePDM()
}
#endif
if (sGMPDecoderEnabled) {
nsRefPtr<PlatformDecoderModule> m(new AVCCDecoderModule(new GMPDecoderModule()));
nsRefPtr<PlatformDecoderModule> m(new GMPDecoderModule());
return m.forget();
}
return nullptr;
}
bool
PlatformDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType)
already_AddRefed<MediaDataDecoder>
PlatformDecoderModule::CreateDecoder(const mp4_demuxer::TrackConfig& aConfig,
FlushableMediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer)
{
return aMimeType.EqualsLiteral("audio/mp4a-latm");
nsRefPtr<MediaDataDecoder> m;
if (aConfig.IsAudioConfig()) {
m = CreateAudioDecoder(static_cast<const mp4_demuxer::AudioDecoderConfig&>(aConfig),
aTaskQueue,
aCallback);
return m.forget();
}
if (!aConfig.IsVideoConfig()) {
return nullptr;
}
if (H264Converter::IsH264(aConfig)) {
m = new H264Converter(this,
static_cast<const mp4_demuxer::VideoDecoderConfig&>(aConfig),
aLayersBackend,
aImageContainer,
aTaskQueue,
aCallback);
} else {
m = CreateVideoDecoder(static_cast<const mp4_demuxer::VideoDecoderConfig&>(aConfig),
aLayersBackend,
aImageContainer,
aTaskQueue,
aCallback);
}
return m.forget();
}
bool
PlatformDecoderModule::SupportsVideoMimeType(const nsACString& aMimeType)
PlatformDecoderModule::SupportsMimeType(const nsACString& aMimeType)
{
return aMimeType.EqualsLiteral("video/mp4") || aMimeType.EqualsLiteral("video/avc");
}
bool
PlatformDecoderModule::DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig)
{
return false;
return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc");
}
} // namespace mozilla

View File

@ -14,6 +14,7 @@
#include <queue>
namespace mp4_demuxer {
class TrackConfig;
class VideoDecoderConfig;
class AudioDecoderConfig;
class MP4Sample;
@ -86,7 +87,44 @@ public:
bool aHasVideo);
#endif
// Creates an H.264 decoder. The layers backend is passed in so that
// Creates a decoder.
// See CreateVideoDecoder and CreateAudioDecoder for implementation details.
virtual already_AddRefed<MediaDataDecoder>
CreateDecoder(const mp4_demuxer::TrackConfig& aConfig,
FlushableMediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
layers::LayersBackend aLayersBackend = layers::LayersBackend::LAYERS_NONE,
layers::ImageContainer* aImageContainer = nullptr);
// An audio decoder module must support AAC by default.
// A video decoder must support H264 by default.
// If more codecs are to be supported, SupportsMimeType will have
// to be extended
virtual bool SupportsMimeType(const nsACString& aMimeType);
enum ConversionRequired {
kNeedNone,
kNeedAVCC,
kNeedAnnexB,
};
// Indicates that the decoder requires a specific format.
// The PlatformDecoderModule will convert the demuxed data accordingly before
// feeding it to MediaDataDecoder::Input.
virtual ConversionRequired DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const = 0;
virtual void DisableHardwareAcceleration() {}
virtual bool SupportsSharedDecoders(const mp4_demuxer::VideoDecoderConfig& aConfig) const {
return true;
}
protected:
PlatformDecoderModule() {}
virtual ~PlatformDecoderModule() {}
friend class H264Converter;
// Creates a Video decoder. The layers backend is passed in so that
// decoders can determine whether hardware accelerated decoding can be used.
// Asynchronous decoding of video should be done in runnables dispatched
// to aVideoTaskQueue. If the task queue isn't needed, the decoder should
@ -99,10 +137,10 @@ public:
// This is called on the decode task queue.
virtual already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
// Creates an Audio decoder with the specified properties.
// Asynchronous decoding of audio should be done in runnables dispatched to
@ -119,24 +157,6 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
// An audio decoder module must support AAC by default.
// If more audio codec is to be supported, SupportsAudioMimeType will have
// to be extended
virtual bool SupportsAudioMimeType(const nsACString& aMimeType);
virtual bool SupportsVideoMimeType(const nsACString& aMimeType);
// Indicates if the video decoder requires AVCC format.
virtual bool DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig);
virtual void DisableHardwareAcceleration() {}
virtual bool SupportsSharedDecoders(const mp4_demuxer::VideoDecoderConfig& aConfig) const {
return true;
}
protected:
PlatformDecoderModule() {}
virtual ~PlatformDecoderModule() {}
// Caches pref media.fragmented-mp4.use-blank-decoder
static bool sUseBlankDecoder;
static bool sFFmpegDecoderEnabled;
@ -213,7 +233,6 @@ public:
// The MP4Reader will not call Input() while it's calling Flush().
virtual nsresult Flush() = 0;
// Causes all complete samples in the pipeline that can be decoded to be
// output. If the decoder can't produce samples from the current output,
// it drops the input samples. The decoder may be holding onto samples
@ -244,6 +263,15 @@ public:
virtual void AllocateMediaResources() {}
virtual void ReleaseMediaResources() {}
virtual bool IsHardwareAccelerated() const { return false; }
// ConfigurationChanged will be called to inform the video or audio decoder
// that the format of the next input sample is about to change.
// If video decoder, aConfig will be a VideoDecoderConfig object.
// If audio decoder, aConfig will be a AudioDecoderConfig object.
virtual nsresult ConfigurationChanged(const mp4_demuxer::TrackConfig& aConfig)
{
return NS_OK;
}
};
} // namespace mozilla

View File

@ -83,15 +83,18 @@ SharedDecoderManager::CreateVideoDecoder(
MediaDataDecoderCallback* aCallback)
{
if (!mDecoder) {
mLayersBackend = aLayersBackend;
mImageContainer = aImageContainer;
// We use the manager's task queue for the decoder, rather than the one
// passed in, so that none of the objects sharing the decoder can shutdown
// the task queue while we're potentially still using it for a *different*
// object also sharing the decoder.
mDecoder = aPDM->CreateVideoDecoder(aConfig,
aLayersBackend,
aImageContainer,
mTaskQueue,
mCallback);
mDecoder =
aPDM->CreateDecoder(aConfig,
mTaskQueue,
mCallback,
mLayersBackend,
mImageContainer);
if (!mDecoder) {
mPDM = nullptr;
return nullptr;
@ -113,17 +116,15 @@ SharedDecoderManager::DisableHardwareAcceleration()
}
bool
SharedDecoderManager::Recreate(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer)
SharedDecoderManager::Recreate(const mp4_demuxer::VideoDecoderConfig& aConfig)
{
mDecoder->Flush();
mDecoder->Shutdown();
mDecoder = mPDM->CreateVideoDecoder(aConfig,
aLayersBackend,
aImageContainer,
mTaskQueue,
mCallback);
mDecoder = mPDM->CreateDecoder(aConfig,
mTaskQueue,
mCallback,
mLayersBackend,
mImageContainer);
if (!mDecoder) {
return false;
}

View File

@ -42,9 +42,7 @@ public:
friend class SharedDecoderCallback;
void DisableHardwareAcceleration();
bool Recreate(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer);
bool Recreate(const mp4_demuxer::VideoDecoderConfig& aConfig);
private:
virtual ~SharedDecoderManager();
@ -52,6 +50,8 @@ private:
nsRefPtr<PlatformDecoderModule> mPDM;
nsRefPtr<MediaDataDecoder> mDecoder;
layers::LayersBackend mLayersBackend;
nsRefPtr<layers::ImageContainer> mImageContainer;
nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
SharedDecoderProxy* mActiveProxy;
MediaDataDecoderCallback* mActiveCallback;

View File

@ -63,10 +63,6 @@ public:
}
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override {
if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return MediaCodecDataDecoder::Input(aSample);
}
@ -248,8 +244,13 @@ public:
};
bool AndroidDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType) {
return static_cast<bool>(CreateDecoder(aMimeType));
bool AndroidDecoderModule::SupportsMimeType(const nsACString& aMimeType)
{
if (aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc")) {
return true;
}
return static_cast<bool>(mozilla::CreateDecoder(aMimeType));
}
already_AddRefed<MediaDataDecoder>
@ -296,6 +297,16 @@ AndroidDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig&
}
PlatformDecoderModule::ConversionRequired
AndroidDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
if (aConfig.IsVideoConfig()) {
return kNeedAnnexB;
} else {
return kNeedNone;
}
}
MediaCodecDataDecoder::MediaCodecDataDecoder(MediaData::Type aType,
const nsACString& aMimeType,
MediaFormat::Param aFormat,

View File

@ -35,7 +35,10 @@ public:
AndroidDecoderModule() {}
virtual ~AndroidDecoderModule() {}
virtual bool SupportsAudioMimeType(const nsACString& aMimeType) override;
virtual bool SupportsMimeType(const nsACString& aMimeType) override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
};
class MediaCodecDataDecoder : public MediaDataDecoder {

View File

@ -192,15 +192,20 @@ AppleDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aC
}
bool
AppleDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType)
AppleDecoderModule::SupportsMimeType(const nsACString& aMimeType)
{
return aMimeType.EqualsLiteral("audio/mp4a-latm") || aMimeType.EqualsLiteral("audio/mpeg");
return aMimeType.EqualsLiteral("audio/mpeg") ||
PlatformDecoderModule::SupportsMimeType(aMimeType);
}
bool
AppleDecoderModule::DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig)
PlatformDecoderModule::ConversionRequired
AppleDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
return true;
if (aConfig.IsVideoConfig()) {
return kNeedAVCC;
} else {
return kNeedNone;
}
}
} // namespace mozilla

View File

@ -32,9 +32,10 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual bool SupportsAudioMimeType(const nsACString& aMimeType) override;
virtual bool
DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) override;
virtual bool SupportsMimeType(const nsACString& aMimeType) override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
static void Init();
static nsresult CanDecode();

View File

@ -253,11 +253,12 @@ EMEDecoderModule::CreateVideoDecoder(const VideoDecoderConfig& aConfig,
return wrapper.forget();
}
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateVideoDecoder(aConfig,
aLayersBackend,
aImageContainer,
aVideoTaskQueue,
aCallback));
nsRefPtr<MediaDataDecoder> decoder(
mPDM->CreateDecoder(aConfig,
aVideoTaskQueue,
aCallback,
aLayersBackend,
aImageContainer));
if (!decoder) {
return nullptr;
}
@ -286,9 +287,8 @@ EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig,
return wrapper.forget();
}
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateAudioDecoder(aConfig,
aAudioTaskQueue,
aCallback));
nsRefPtr<MediaDataDecoder> decoder(
mPDM->CreateDecoder(aConfig, aAudioTaskQueue, aCallback));
if (!decoder) {
return nullptr;
}
@ -303,10 +303,14 @@ EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig,
return emeDecoder.forget();
}
bool
EMEDecoderModule::DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig)
PlatformDecoderModule::ConversionRequired
EMEDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
return mCDMDecodesVideo && aConfig.crypto.valid;
if (aConfig.IsVideoConfig()) {
return kNeedAVCC;
} else {
return kNeedNone;
}
}
} // namespace mozilla

View File

@ -42,8 +42,8 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual bool
DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
private:
nsRefPtr<CDMProxy> mProxy;

View File

@ -51,19 +51,22 @@ public:
return decoder.forget();
}
virtual bool SupportsAudioMimeType(const nsACString& aMimeType) override
virtual bool SupportsMimeType(const nsACString& aMimeType) override
{
return FFmpegAudioDecoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
return FFmpegAudioDecoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE ||
FFmpegH264Decoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
}
virtual bool SupportsVideoMimeType(const nsACString& aMimeType) override
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override
{
return FFmpegH264Decoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
}
virtual bool DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) override
{
return true;
if (aConfig.IsVideoConfig() &&
(aConfig.mime_type.EqualsLiteral("video/avc") ||
aConfig.mime_type.EqualsLiteral("video/mp4"))) {
return PlatformDecoderModule::kNeedAVCC;
} else {
return kNeedNone;
}
}
};

View File

@ -75,11 +75,15 @@ GMPDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aCon
return wrapper.forget();
}
bool
GMPDecoderModule::DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig)
PlatformDecoderModule::ConversionRequired
GMPDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
// GMPVideoCodecType::kGMPVideoCodecH264 specifies that encoded frames must be in AVCC format.
return true;
if (aConfig.IsVideoConfig()) {
return kNeedAVCC;
} else {
return kNeedNone;
}
}
} // namespace mozilla

View File

@ -31,7 +31,8 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual bool DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
};
} // namespace mozilla

View File

@ -51,4 +51,14 @@ GonkDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aCo
return decoder.forget();
}
PlatformDecoderModule::ConversionRequired
GonkDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
if (aConfig.IsVideoConfig()) {
return kNeedAVCC;
} else {
return kNeedNone;
}
}
} // namespace mozilla

View File

@ -31,6 +31,9 @@ public:
MediaDataDecoderCallback* aCallback) override;
static void Init();
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
};
} // namespace mozilla

View File

@ -452,20 +452,6 @@ GonkVideoDecoderManager::SendSampleToOMX(mp4_demuxer::MP4Sample* aSample)
0);
}
bool
GonkVideoDecoderManager::PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample)
{
if (aSample != nullptr) {
// We must prepare samples in AVC Annex B.
if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
GVDM_LOG("Failed to convert sample to annex B!");
return false;
}
}
return true;
}
void
GonkVideoDecoderManager::ClearQueueFrameTime()
{

View File

@ -58,8 +58,6 @@ public:
static void RecycleCallback(TextureClient* aClient, void* aClosure);
protected:
virtual bool PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample) override;
virtual android::status_t SendSampleToOMX(mp4_demuxer::MP4Sample* aSample) override;
private:

View File

@ -5,21 +5,21 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'AVCCDecoderModule.h',
'MP4Decoder.h',
'MP4Reader.h',
'MP4Stream.h',
'PlatformDecoderModule.h',
'SharedDecoderManager.h',
'wrappers/H264Converter.h'
]
UNIFIED_SOURCES += [
'AVCCDecoderModule.cpp',
'BlankDecoderModule.cpp',
'MP4Decoder.cpp',
'MP4Stream.cpp',
'PlatformDecoderModule.cpp',
'SharedDecoderManager.cpp',
'wrappers/H264Converter.cpp'
]
SOURCES += [

View File

@ -121,19 +121,26 @@ WMFDecoderModule::SupportsSharedDecoders(const mp4_demuxer::VideoDecoderConfig&
}
bool
WMFDecoderModule::SupportsVideoMimeType(const nsACString& aMimeType)
WMFDecoderModule::SupportsMimeType(const nsACString& aMimeType)
{
return aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc") ||
aMimeType.EqualsLiteral("video/webm; codecs=vp8") ||
aMimeType.EqualsLiteral("video/webm; codecs=vp9");
aMimeType.EqualsLiteral("video/webm; codecs=vp9") ||
aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("audio/mpeg");
}
bool
WMFDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType)
PlatformDecoderModule::ConversionRequired
WMFDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("audio/mpeg");
if (aConfig.IsVideoConfig() &&
(aConfig.mime_type.EqualsLiteral("video/avc") ||
aConfig.mime_type.EqualsLiteral("video/mp4"))) {
return kNeedAnnexB;
} else {
return kNeedNone;
}
}
static bool

View File

@ -31,8 +31,7 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
bool SupportsVideoMimeType(const nsACString& aMimeType) override;
bool SupportsAudioMimeType(const nsACString& aMimeType) override;
bool SupportsMimeType(const nsACString& aMimeType) override;
virtual void DisableHardwareAcceleration() override
{
@ -41,6 +40,9 @@ public:
virtual bool SupportsSharedDecoders(const mp4_demuxer::VideoDecoderConfig& aConfig) const override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
// Accessors that report whether we have the required MFTs available
// on the system to play various codecs. Windows Vista doesn't have the
// H.264/AAC decoders if the "Platform Update Supplement for Windows Vista"

View File

@ -241,12 +241,6 @@ WMFVideoMFTManager::Input(mp4_demuxer::MP4Sample* aSample)
// This can happen during shutdown.
return E_FAIL;
}
if (mStreamType != VP8 && mStreamType != VP9) {
// We must prepare samples in AVC Annex B.
if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
return E_FAIL;
}
}
// Forward sample data to the decoder.
const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
uint32_t length = aSample->size;

View File

@ -0,0 +1,249 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "H264Converter.h"
#include "ImageContainer.h"
#include "MediaTaskQueue.h"
#include "mp4_demuxer/DecoderData.h"
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
namespace mozilla
{
// H264 AnnexB or AVCC handler
#include "mp4_demuxer/DecoderData.h"
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
H264Converter::H264Converter(PlatformDecoderModule* aPDM,
const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
: mPDM(aPDM)
, mCurrentConfig(aConfig)
, mLayersBackend(aLayersBackend)
, mImageContainer(aImageContainer)
, mVideoTaskQueue(aVideoTaskQueue)
, mCallback(aCallback)
, mDecoder(nullptr)
, mNeedAVCC(aPDM->DecoderNeedsConversion(aConfig) == PlatformDecoderModule::kNeedAVCC)
, mLastError(NS_OK)
{
CreateDecoder();
}
H264Converter::~H264Converter()
{
}
nsresult
H264Converter::Init()
{
if (mDecoder) {
return mDecoder->Init();
}
return mLastError;
}
nsresult
H264Converter::Input(mp4_demuxer::MP4Sample* aSample)
{
if (!mNeedAVCC) {
if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
return NS_ERROR_FAILURE;
}
} else {
if (!mp4_demuxer::AnnexB::ConvertSampleToAVCC(aSample)) {
return NS_ERROR_FAILURE;
}
}
nsresult rv;
if (!mDecoder) {
// It is not possible to create an AVCC H264 decoder without SPS.
// As such, creation will fail if the extra_data just extracted doesn't
// contain a SPS.
rv = CreateDecoderAndInit(aSample);
if (rv == NS_ERROR_NOT_INITIALIZED) {
// We are missing the required SPS to create the decoder.
// Ignore for the time being, the MP4Sample will be dropped.
return NS_OK;
}
} else {
rv = CheckForSPSChange(aSample);
}
NS_ENSURE_SUCCESS(rv, rv);
aSample->extra_data = mCurrentConfig.extra_data;
return mDecoder->Input(aSample);
}
nsresult
H264Converter::Flush()
{
if (mDecoder) {
return mDecoder->Flush();
}
return mLastError;
}
nsresult
H264Converter::Drain()
{
if (mDecoder) {
return mDecoder->Drain();
}
return mLastError;
}
nsresult
H264Converter::Shutdown()
{
if (mDecoder) {
nsresult rv = mDecoder->Shutdown();
mDecoder = nullptr;
return rv;
}
return NS_OK;
}
bool
H264Converter::IsWaitingMediaResources()
{
if (mDecoder) {
return mDecoder->IsWaitingMediaResources();
}
return MediaDataDecoder::IsWaitingMediaResources();
}
bool
H264Converter::IsDormantNeeded()
{
if (mNeedAVCC) {
return true;
}
return mDecoder ?
mDecoder->IsDormantNeeded() : MediaDataDecoder::IsDormantNeeded();
}
void
H264Converter::AllocateMediaResources()
{
if (mNeedAVCC) {
// Nothing to do, decoder will be allocated on the fly when required.
return;
}
if (mDecoder) {
mDecoder->AllocateMediaResources();
}
}
void
H264Converter::ReleaseMediaResources()
{
if (mNeedAVCC) {
Shutdown();
return;
}
if (mDecoder) {
mDecoder->ReleaseMediaResources();
}
}
bool
H264Converter::IsHardwareAccelerated() const
{
if (mDecoder) {
return mDecoder->IsHardwareAccelerated();
}
return MediaDataDecoder::IsHardwareAccelerated();
}
nsresult
H264Converter::CreateDecoder()
{
if (mNeedAVCC && !mp4_demuxer::AnnexB::HasSPS(mCurrentConfig.extra_data)) {
// nothing found yet, will try again later
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(mCurrentConfig.extra_data);
mDecoder = mPDM->CreateVideoDecoder(mCurrentConfig,
mLayersBackend,
mImageContainer,
mVideoTaskQueue,
mCallback);
if (!mDecoder) {
mLastError = NS_ERROR_FAILURE;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
H264Converter::CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(extra_data);
nsresult rv = CreateDecoder();
NS_ENSURE_SUCCESS(rv, rv);
return Init();
}
nsresult
H264Converter::CheckForSPSChange(mp4_demuxer::MP4Sample* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data) ||
mp4_demuxer::AnnexB::CompareExtraData(extra_data,
mCurrentConfig.extra_data)) {
return NS_OK;
}
if (!mNeedAVCC) {
UpdateConfigFromExtraData(extra_data);
mDecoder->ConfigurationChanged(mCurrentConfig);
return NS_OK;
}
// The SPS has changed, signal to flush the current decoder and create a
// new one.
mDecoder->Flush();
ReleaseMediaResources();
return CreateDecoderAndInit(aSample);
}
void
H264Converter::UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData)
{
mp4_demuxer::SPSData spsdata;
if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtraData, spsdata) &&
spsdata.pic_width > 0 && spsdata.pic_height > 0) {
mp4_demuxer::H264::EnsureSPSIsSane(spsdata);
mCurrentConfig.image_width = spsdata.pic_width;
mCurrentConfig.image_height = spsdata.pic_height;
mCurrentConfig.display_width = spsdata.display_width;
mCurrentConfig.display_height = spsdata.display_height;
}
mCurrentConfig.extra_data = aExtraData;
}
/* static */
bool
H264Converter::IsH264(const mp4_demuxer::TrackConfig& aConfig)
{
return aConfig.mime_type.EqualsLiteral("video/avc") ||
aConfig.mime_type.EqualsLiteral("video/mp4");
}
} // namespace mozilla

View File

@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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_H264Converter_h
#define mozilla_H264Converter_h
#include "PlatformDecoderModule.h"
namespace mozilla {
// H264Converter is a MediaDataDecoder wrapper used to ensure that
// only AVCC or AnnexB is fed to the underlying MediaDataDecoder.
// The H264Converter allows playback of content where the SPS NAL may not be
// provided in the init segment (e.g. AVC3 or Annex B)
// H264Converter will monitor the input data, and will delay creation of the
// MediaDataDecoder until a SPS and PPS NALs have been extracted.
class H264Converter : public MediaDataDecoder {
public:
H264Converter(PlatformDecoderModule* aPDM,
const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback);
virtual ~H264Converter();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
virtual bool IsWaitingMediaResources() override;
virtual bool IsDormantNeeded() override;
virtual void AllocateMediaResources() override;
virtual void ReleaseMediaResources() override;
virtual bool IsHardwareAccelerated() const override;
// Return true if mimetype is H.264.
static bool IsH264(const mp4_demuxer::TrackConfig& aConfig);
private:
// Will create the required MediaDataDecoder if need AVCC and we have a SPS NAL.
// Returns NS_ERROR_FAILURE if error is permanent and can't be recovered and
// will set mError accordingly.
nsresult CreateDecoder();
nsresult CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample);
nsresult CheckForSPSChange(mp4_demuxer::MP4Sample* aSample);
void UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData);
nsRefPtr<PlatformDecoderModule> mPDM;
mp4_demuxer::VideoDecoderConfig mCurrentConfig;
layers::LayersBackend mLayersBackend;
nsRefPtr<layers::ImageContainer> mImageContainer;
nsRefPtr<FlushableMediaTaskQueue> mVideoTaskQueue;
MediaDataDecoderCallback* mCallback;
nsRefPtr<MediaDataDecoder> mDecoder;
bool mNeedAVCC;
nsresult mLastError;
};
} // namespace mozilla
#endif // mozilla_H264Converter_h

View File

@ -565,8 +565,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
EXPECT_TRUE(IsGMPStorageIsEmpty());
const nsString origin1 = NS_LITERAL_STRING("example1.com");
const nsString origin2 = NS_LITERAL_STRING("example2.org");
const nsString origin1 = NS_LITERAL_STRING("http://example1.com");
const nsString origin2 = NS_LITERAL_STRING("http://example2.org");
nsCString PBnodeId1 = GetNodeId(origin1, origin2, true);
nsCString PBnodeId2 = GetNodeId(origin1, origin2, true);
@ -602,8 +602,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
// Once we clear storage, the node ids generated for the same origin-pair
// should be different.
const nsString origin1 = NS_LITERAL_STRING("example1.com");
const nsString origin2 = NS_LITERAL_STRING("example2.org");
const nsString origin1 = NS_LITERAL_STRING("http://example1.com");
const nsString origin2 = NS_LITERAL_STRING("http://example2.org");
nsCString nodeId3 = GetNodeId(origin1, origin2, false);
EXPECT_TRUE(!aNodeId1.Equals(nodeId3));
@ -707,8 +707,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
Expect(NS_LITERAL_CSTRING("test-storage complete"),
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
NS_LITERAL_STRING("http://example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
}
@ -728,8 +728,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
this, &GMPStorageTest::TestForgetThisSite_AnotherSite);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
NS_LITERAL_STRING("http://example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
}
@ -742,8 +742,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
this, &GMPStorageTest::TestForgetThisSite_CollectSiteInfo);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
NS_LITERAL_STRING("example4.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example3.com"),
NS_LITERAL_STRING("http://example4.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
}
@ -771,7 +771,7 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
void TestForgetThisSite_CollectSiteInfo() {
nsAutoPtr<NodeInfo> siteInfo(
new NodeInfo(NS_LITERAL_CSTRING("example1.com")));
new NodeInfo(NS_LITERAL_CSTRING("http://example1.com")));
// Collect nodeIds that are expected to remain for later comparison.
EnumerateGMPStorageDir(NS_LITERAL_CSTRING("id"), NodeIdCollector(siteInfo));
// Invoke "Forget this site" on the main thread.
@ -861,8 +861,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
this, &GMPStorageTest::TestClearRecentHistory1_Clear);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
NS_LITERAL_STRING("http://example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
}
@ -883,8 +883,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
this, &GMPStorageTest::TestClearRecentHistory2_Clear);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
NS_LITERAL_STRING("http://example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
}
@ -905,8 +905,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
this, &GMPStorageTest::TestClearRecentHistory3_Clear);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
NS_LITERAL_STRING("http://example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
}
@ -1019,8 +1019,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
// Open decryptor on one, origin, write a record, and test that that
// record can't be read on another origin.
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
NS_LITERAL_STRING("example4.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example3.com"),
NS_LITERAL_STRING("http://example4.com"),
false,
update);
}
@ -1033,8 +1033,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
Expect(NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId succeeded (length 0 bytes)"),
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
CreateDecryptor(NS_LITERAL_STRING("example5.com"),
NS_LITERAL_STRING("example6.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example5.com"),
NS_LITERAL_STRING("http://example6.com"),
false,
NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId"));
}
@ -1050,8 +1050,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
// open another, and test that record can be read, close decryptor,
// then send pb-last-context-closed notification, then open decryptor
// and check that it can't read that data; it should have been purged.
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
NS_LITERAL_STRING("pb2.com"),
CreateDecryptor(NS_LITERAL_STRING("http://pb1.com"),
NS_LITERAL_STRING("http://pb2.com"),
true,
NS_LITERAL_CSTRING("store pbdata test-pb-data"));
}
@ -1063,8 +1063,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
NS_NewRunnableMethod(this,
&GMPStorageTest::TestPBStorage_RecordRetrievedContinuation));
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
NS_LITERAL_STRING("pb2.com"),
CreateDecryptor(NS_LITERAL_STRING("http://pb1.com"),
NS_LITERAL_STRING("http://pb2.com"),
true,
NS_LITERAL_CSTRING("retrieve pbdata"));
}
@ -1077,8 +1077,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
NS_NewRunnableMethod(this,
&GMPStorageTest::SetFinished));
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
NS_LITERAL_STRING("pb2.com"),
CreateDecryptor(NS_LITERAL_STRING("http://pb1.com"),
NS_LITERAL_STRING("http://pb2.com"),
true,
NS_LITERAL_CSTRING("retrieve pbdata"));
}
@ -1108,20 +1108,20 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
void TestAsyncShutdownTimeout() {
// Create decryptors that timeout in their async shutdown.
// If the gtest hangs on shutdown, test fails!
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example7.com"),
NS_LITERAL_STRING("example8.com"),
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("http://example7.com"),
NS_LITERAL_STRING("http://example8.com"),
&GMPStorageTest::TestAsyncShutdownTimeout2);
};
void TestAsyncShutdownTimeout2() {
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example9.com"),
NS_LITERAL_STRING("example10.com"),
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("http://example9.com"),
NS_LITERAL_STRING("http://example10.com"),
&GMPStorageTest::TestAsyncShutdownTimeout3);
};
void TestAsyncShutdownTimeout3() {
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example11.com"),
NS_LITERAL_STRING("example12.com"),
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("http://example11.com"),
NS_LITERAL_STRING("http://example12.com"),
&GMPStorageTest::SetFinished);
};
@ -1144,8 +1144,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
// Test that a GMP can write to storage during shutdown, and retrieve
// that written data in a subsequent session.
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
NS_LITERAL_STRING("example14.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example13.com"),
NS_LITERAL_STRING("http://example14.com"),
false,
update);
}
@ -1163,8 +1163,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
Expect(response,
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
NS_LITERAL_STRING("example14.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example13.com"),
NS_LITERAL_STRING("http://example14.com"),
false,
NS_LITERAL_CSTRING("retrieve-shutdown-token"));
}
@ -1176,8 +1176,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
Expect(NS_LITERAL_CSTRING("OP tests completed"),
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
CreateDecryptor(NS_LITERAL_STRING("example15.com"),
NS_LITERAL_STRING("example16.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example15.com"),
NS_LITERAL_STRING("http://example16.com"),
false,
NS_LITERAL_CSTRING("test-op-apis"));
}
@ -1187,8 +1187,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
Expect(NS_LITERAL_CSTRING("retrieved plugin-voucher: gmp-fake placeholder voucher"),
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
CreateDecryptor(NS_LITERAL_STRING("example17.com"),
NS_LITERAL_STRING("example18.com"),
CreateDecryptor(NS_LITERAL_STRING("http://example17.com"),
NS_LITERAL_STRING("http://example18.com"),
false,
NS_LITERAL_CSTRING("retrieve-plugin-voucher"));
}
@ -1237,8 +1237,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
Expect(response, continuation);
}
CreateDecryptor(NS_LITERAL_STRING("foo.com"),
NS_LITERAL_STRING("bar.com"),
CreateDecryptor(NS_LITERAL_STRING("http://foo.com"),
NS_LITERAL_STRING("http://bar.com"),
aPrivateBrowsing,
Move(updates));
}
@ -1290,8 +1290,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
update.Append(longRecordName);
update.AppendLiteral(" ");
update.Append(data);
CreateDecryptor(NS_LITERAL_STRING("fuz.com"),
NS_LITERAL_STRING("baz.com"),
CreateDecryptor(NS_LITERAL_STRING("http://fuz.com"),
NS_LITERAL_STRING("http://baz.com"),
false,
update);
}

View File

@ -168,12 +168,16 @@ MediaSourceReader::RequestAudioData()
&MediaSourceReader::CompleteAudioSeekAndRejectPromise));
break;
case SOURCE_NONE:
if (mLastAudioTime) {
if (!mLastAudioTime) {
// This is the first call to RequestAudioData.
// Fallback to using decoder with earliest data.
mAudioSourceDecoder = FirstDecoder(MediaData::AUDIO_DATA);
}
if (mLastAudioTime || !mAudioSourceDecoder) {
CheckForWaitOrEndOfStream(MediaData::AUDIO_DATA, mLastAudioTime);
break;
}
// Fallback to using first reader
mAudioSourceDecoder = mAudioTrack->Decoders()[0];
// Fallback to getting first frame from first decoder.
default:
DoAudioRequest();
break;
@ -338,12 +342,16 @@ MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThres
&MediaSourceReader::CompleteVideoSeekAndRejectPromise));
break;
case SOURCE_NONE:
if (mLastVideoTime) {
if (!mLastVideoTime) {
// This is the first call to RequestVideoData.
// Fallback to using decoder with earliest data.
mVideoSourceDecoder = FirstDecoder(MediaData::VIDEO_DATA);
}
if (mLastVideoTime || !mVideoSourceDecoder) {
CheckForWaitOrEndOfStream(MediaData::VIDEO_DATA, mLastVideoTime);
break;
}
// Fallback to using first reader.
mVideoSourceDecoder = mVideoTrack->Decoders()[0];
// Fallback to getting first frame from first decoder.
default:
DoVideoRequest();
break;
@ -1033,6 +1041,36 @@ MediaSourceReader::GetBuffered(dom::TimeRanges* aBuffered)
return NS_OK;
}
already_AddRefed<SourceBufferDecoder>
MediaSourceReader::FirstDecoder(MediaData::Type aType)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
TrackBuffer* trackBuffer =
aType == MediaData::AUDIO_DATA ? mAudioTrack : mVideoTrack;
MOZ_ASSERT(trackBuffer);
const nsTArray<nsRefPtr<SourceBufferDecoder>>& decoders = trackBuffer->Decoders();
if (decoders.IsEmpty()) {
return nullptr;
}
nsRefPtr<SourceBufferDecoder> firstDecoder;
double lowestStartTime = PositiveInfinity<double>();
for (uint32_t i = 0; i < decoders.Length(); ++i) {
nsRefPtr<TimeRanges> r = new TimeRanges();
decoders[i]->GetBuffered(r);
double start = r->GetStartTime();
if (start < 0) {
continue;
}
if (start < lowestStartTime) {
firstDecoder = decoders[i];
lowestStartTime = start;
}
}
return firstDecoder.forget();
}
nsRefPtr<MediaDecoderReader::WaitForDataPromise>
MediaSourceReader::WaitForData(MediaData::Type aType)
{
@ -1053,13 +1091,23 @@ MediaSourceReader::MaybeNotifyHaveData()
// The next Request*Data will handle END_OF_STREAM or going back into waiting
// mode.
if (!IsSeeking() && mAudioTrack) {
haveAudio = HaveData(mLastAudioTime, MediaData::AUDIO_DATA);
if (!mLastAudioTime) {
nsRefPtr<SourceBufferDecoder> d = FirstDecoder(MediaData::AUDIO_DATA);
haveAudio = !!d;
} else {
haveAudio = HaveData(mLastAudioTime, MediaData::AUDIO_DATA);
}
if (ended || haveAudio) {
WaitPromise(MediaData::AUDIO_DATA).ResolveIfExists(MediaData::AUDIO_DATA, __func__);
}
}
if (!IsSeeking() && mVideoTrack) {
haveVideo = HaveData(mLastVideoTime, MediaData::VIDEO_DATA);
if (!mLastVideoTime) {
nsRefPtr<SourceBufferDecoder> d = FirstDecoder(MediaData::VIDEO_DATA);
haveVideo = !!d;
} else {
haveVideo = HaveData(mLastVideoTime, MediaData::VIDEO_DATA);
}
if (ended || haveVideo) {
WaitPromise(MediaData::VIDEO_DATA).ResolveIfExists(MediaData::VIDEO_DATA, __func__);
}

View File

@ -223,6 +223,7 @@ private:
int64_t aTolerance /* microseconds */,
const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders);
bool HaveData(int64_t aTarget, MediaData::Type aType);
already_AddRefed<SourceBufferDecoder> FirstDecoder(MediaData::Type aType);
void AttemptSeek();
bool IsSeeking() { return mPendingSeekTime != -1; }

View File

@ -116,7 +116,7 @@ IntelWebMVideoDecoder::IsSupportedVideoMimeType(const nsACString& aMimeType)
{
return (aMimeType.EqualsLiteral("video/webm; codecs=vp8") ||
aMimeType.EqualsLiteral("video/webm; codecs=vp9")) &&
mPlatform->SupportsVideoMimeType(aMimeType);
mPlatform->SupportsMimeType(aMimeType);
}
nsresult
@ -147,11 +147,12 @@ IntelWebMVideoDecoder::Init(unsigned int aWidth, unsigned int aHeight)
if (!IsSupportedVideoMimeType(video.mime_type)) {
return NS_ERROR_FAILURE;
}
mMediaDataDecoder = mPlatform->CreateVideoDecoder(video,
mReader->GetLayersBackendType(),
mReader->GetDecoder()->GetImageContainer(),
mTaskQueue,
this);
mMediaDataDecoder =
mPlatform->CreateDecoder(video,
mTaskQueue,
this,
mReader->GetLayersBackendType(),
mReader->GetDecoder()->GetImageContainer());
if (!mMediaDataDecoder) {
return NS_ERROR_FAILURE;
}

View File

@ -470,8 +470,9 @@ MediaEngineGonkVideoSource::StartImpl(webrtc::CaptureCapability aCapability) {
config.mMode = ICameraControl::kPictureMode;
config.mPreviewSize.width = aCapability.width;
config.mPreviewSize.height = aCapability.height;
config.mPictureSize.width = aCapability.width;
config.mPictureSize.height = aCapability.height;
mCameraControl->Start(&config);
mCameraControl->Set(CAMERA_PARAM_PICTURE_SIZE, config.mPreviewSize);
hal::RegisterScreenConfigurationObserver(this);
}

View File

@ -321,6 +321,9 @@ function testOpenWithoutClose() {
closed.push(socket.closed);
}
SpecialPowers.gc();
info('all unrefereced socket should be closed right after GC');
return Promise.all(closed);
}

View File

@ -113,7 +113,7 @@ CreateDrawTargetForSurface(gfxASurface *aSurface)
}
RefPtr<DrawTarget> drawTarget =
Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(),
ToIntSize(gfxIntSize(aSurface->GetSize())),
aSurface->GetSize(),
&format);
aSurface->SetData(&kDrawTarget, drawTarget, nullptr);
return drawTarget;

View File

@ -1441,35 +1441,13 @@ PromiseWorkerProxy::StoreISupports(nsISupports* aSupports)
mSupportsArray.AppendElement(supports);
}
namespace {
class PromiseWorkerProxyControlRunnable final
: public WorkerControlRunnable
bool
PromiseWorkerProxyControlRunnable::WorkerRun(JSContext* aCx,
WorkerPrivate* aWorkerPrivate)
{
nsRefPtr<PromiseWorkerProxy> mProxy;
public:
PromiseWorkerProxyControlRunnable(WorkerPrivate* aWorkerPrivate,
PromiseWorkerProxy* aProxy)
: WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
, mProxy(aProxy)
{
MOZ_ASSERT(aProxy);
}
virtual bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
mProxy->CleanUp(aCx);
return true;
}
private:
~PromiseWorkerProxyControlRunnable()
{}
};
} // anonymous namespace
mProxy->CleanUp(aCx);
return true;
}
void
PromiseWorkerProxy::RunCallback(JSContext* aCx,

View File

@ -11,6 +11,8 @@
#include "mozilla/dom/workers/bindings/WorkerFeature.h"
#include "nsProxyRelease.h"
#include "WorkerRunnable.h"
namespace mozilla {
namespace dom {
@ -53,8 +55,12 @@ class WorkerPrivate;
// dispatch a runnable to the worker. Use GetWorkerPrivate() to acquire the
// worker. This might be null! In the WorkerRunnable's WorkerRun() use
// GetWorkerPromise() to access the Promise and resolve/reject it. Then call
// CleanUp() on the worker
// thread.
// CleanUp() on the worker thread.
//
// IMPORTANT: Dispatching the runnable to the worker thread may fail causing
// the promise to leak. To successfully release the promise on the
// worker thread in this case, use |PromiseWorkerProxyControlRunnable| to
// dispatch a control runnable that will deref the object on the correct thread.
class PromiseWorkerProxy : public PromiseNativeHandler,
public workers::WorkerFeature
@ -78,6 +84,17 @@ public:
void CleanUp(JSContext* aCx);
Mutex& GetCleanUpLock()
{
return mCleanUpLock;
}
bool IsClean() const
{
mCleanUpLock.AssertCurrentThreadOwns();
return mCleanedUp;
}
protected:
virtual void ResolvedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue) override;
@ -119,6 +136,30 @@ private:
Mutex mCleanUpLock;
};
// Helper runnable used for releasing the proxied promise when the worker
// is not accepting runnables and the promise object would leak.
// See the instructions above.
class PromiseWorkerProxyControlRunnable final : public workers::WorkerControlRunnable
{
nsRefPtr<PromiseWorkerProxy> mProxy;
public:
PromiseWorkerProxyControlRunnable(workers::WorkerPrivate* aWorkerPrivate,
PromiseWorkerProxy* aProxy)
: WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
, mProxy(aProxy)
{
MOZ_ASSERT(aProxy);
}
virtual bool
WorkerRun(JSContext* aCx, workers::WorkerPrivate* aWorkerPrivate) override;
private:
~PromiseWorkerProxyControlRunnable()
{}
};
} // namespace dom
} // namespace mozilla

View File

@ -22,6 +22,8 @@ interface WindowClient : Client {
readonly attribute VisibilityState visibilityState;
readonly attribute boolean focused;
readonly attribute FrameType frameType;
[Throws]
Promise<WindowClient> focus();
};

View File

@ -50,10 +50,10 @@ public:
ServiceWorkerClient(nsISupports* aOwner,
const ServiceWorkerClientInfo& aClientInfo)
: mOwner(aOwner),
mId(aClientInfo.mClientId),
mWindowId(aClientInfo.mWindowId),
mUrl(aClientInfo.mUrl)
: mOwner(aOwner)
, mId(aClientInfo.mClientId)
, mUrl(aClientInfo.mUrl)
, mWindowId(aClientInfo.mWindowId)
{
MOZ_ASSERT(aOwner);
}
@ -89,8 +89,10 @@ protected:
private:
nsCOMPtr<nsISupports> mOwner;
nsString mId;
uint64_t mWindowId;
nsString mUrl;
protected:
uint64_t mWindowId;
};
} // namespace workers

View File

@ -4,6 +4,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseWorkerProxy.h"
#include "ServiceWorkerClient.h"
#include "ServiceWorkerClients.h"
@ -41,96 +42,17 @@ ServiceWorkerClients::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenPro
namespace {
// Helper class used for passing the promise between threads while
// keeping the worker alive.
class PromiseHolder final : public WorkerFeature
{
friend class MatchAllRunnable;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PromiseHolder)
public:
PromiseHolder(WorkerPrivate* aWorkerPrivate,
Promise* aPromise)
: mWorkerPrivate(aWorkerPrivate),
mPromise(aPromise),
mCleanUpLock("promiseHolderCleanUpLock"),
mClean(false)
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(mPromise);
if (NS_WARN_IF(!mWorkerPrivate->AddFeature(mWorkerPrivate->GetJSContext(), this))) {
// Worker has been canceled and will go away.
// The ResolvePromiseWorkerRunnable won't run, so we can set mPromise to
// nullptr.
mPromise = nullptr;
mClean = true;
}
}
Promise*
GetPromise() const
{
return mPromise;
}
void
Clean()
{
mWorkerPrivate->AssertIsOnWorkerThread();
MutexAutoLock lock(mCleanUpLock);
if (mClean) {
return;
}
mPromise = nullptr;
mWorkerPrivate->RemoveFeature(mWorkerPrivate->GetJSContext(), this);
mClean = true;
}
bool
Notify(JSContext* aCx, Status aStatus)
{
mWorkerPrivate->AssertIsOnWorkerThread();
if (aStatus > Running) {
Clean();
}
return true;
}
private:
~PromiseHolder()
{
MOZ_ASSERT(mClean);
}
WorkerPrivate* mWorkerPrivate;
nsRefPtr<Promise> mPromise;
// Used to prevent race conditions on |mClean| and to ensure that either a
// Notify() call or a dispatch back to the worker thread occurs before
// this object is released.
Mutex mCleanUpLock;
bool mClean;
};
class ResolvePromiseWorkerRunnable final : public WorkerRunnable
{
nsRefPtr<PromiseHolder> mPromiseHolder;
nsRefPtr<PromiseWorkerProxy> mPromiseProxy;
nsTArray<ServiceWorkerClientInfo> mValue;
public:
ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate,
PromiseHolder* aPromiseHolder,
PromiseWorkerProxy* aPromiseProxy,
nsTArray<ServiceWorkerClientInfo>& aValue)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
mPromiseHolder(aPromiseHolder)
mPromiseProxy(aPromiseProxy)
{
AssertIsOnMainThread();
mValue.SwapElements(aValue);
@ -142,7 +64,7 @@ public:
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
Promise* promise = mPromiseHolder->GetPromise();
Promise* promise = mPromiseProxy->GetWorkerPromise();
MOZ_ASSERT(promise);
nsTArray<nsRefPtr<ServiceWorkerClient>> ret;
@ -154,51 +76,23 @@ public:
promise->MaybeResolve(ret);
// release the reference on the worker thread.
mPromiseHolder->Clean();
mPromiseProxy->CleanUp(aCx);
return true;
}
};
class ReleasePromiseRunnable final : public MainThreadWorkerControlRunnable
{
nsRefPtr<PromiseHolder> mPromiseHolder;
public:
ReleasePromiseRunnable(WorkerPrivate* aWorkerPrivate,
PromiseHolder* aPromiseHolder)
: MainThreadWorkerControlRunnable(aWorkerPrivate),
mPromiseHolder(aPromiseHolder)
{ }
private:
~ReleasePromiseRunnable()
{ }
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
mPromiseHolder->Clean();
return true;
}
};
class MatchAllRunnable final : public nsRunnable
{
WorkerPrivate* mWorkerPrivate;
nsRefPtr<PromiseHolder> mPromiseHolder;
nsRefPtr<PromiseWorkerProxy> mPromiseProxy;
nsCString mScope;
public:
MatchAllRunnable(WorkerPrivate* aWorkerPrivate,
PromiseHolder* aPromiseHolder,
PromiseWorkerProxy* aPromiseProxy,
const nsCString& aScope)
: mWorkerPrivate(aWorkerPrivate),
mPromiseHolder(aPromiseHolder),
mPromiseProxy(aPromiseProxy),
mScope(aScope)
{
MOZ_ASSERT(aWorkerPrivate);
@ -210,8 +104,8 @@ public:
{
AssertIsOnMainThread();
MutexAutoLock lock(mPromiseHolder->mCleanUpLock);
if (mPromiseHolder->mClean) {
MutexAutoLock lock(mPromiseProxy->GetCleanUpLock());
if (mPromiseProxy->IsClean()) {
// Don't resolve the promise if it was already released.
return NS_OK;
}
@ -221,7 +115,7 @@ public:
swm->GetAllClients(mScope, result);
nsRefPtr<ResolvePromiseWorkerRunnable> r =
new ResolvePromiseWorkerRunnable(mWorkerPrivate, mPromiseHolder, result);
new ResolvePromiseWorkerRunnable(mWorkerPrivate, mPromiseProxy, result);
AutoSafeJSContext cx;
if (r->Dispatch(cx)) {
@ -230,11 +124,11 @@ public:
// Dispatch to worker thread failed because the worker is shutting down.
// Use a control runnable to release the runnable on the worker thread.
nsRefPtr<ReleasePromiseRunnable> releaseRunnable =
new ReleasePromiseRunnable(mWorkerPrivate, mPromiseHolder);
nsRefPtr<PromiseWorkerProxyControlRunnable> releaseRunnable =
new PromiseWorkerProxyControlRunnable(mWorkerPrivate, mPromiseProxy);
if (!releaseRunnable->Dispatch(cx)) {
NS_RUNTIMEABORT("Failed to dispatch PromiseHolder control runnable.");
NS_RUNTIMEABORT("Failed to dispatch MatchAll promise control runnable.");
}
return NS_OK;
@ -264,16 +158,16 @@ ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions,
return nullptr;
}
nsRefPtr<PromiseHolder> promiseHolder = new PromiseHolder(workerPrivate,
promise);
if (!promiseHolder->GetPromise()) {
nsRefPtr<PromiseWorkerProxy> promiseProxy =
PromiseWorkerProxy::Create(workerPrivate, promise);
if (!promiseProxy->GetWorkerPromise()) {
// Don't dispatch if adding the worker feature failed.
return promise.forget();
}
nsRefPtr<MatchAllRunnable> r =
new MatchAllRunnable(workerPrivate,
promiseHolder,
promiseProxy,
NS_ConvertUTF16toUTF8(scope));
nsresult rv = NS_DispatchToMainThread(r);

View File

@ -7,6 +7,7 @@
#include "ServiceWorkerWindowClient.h"
#include "mozilla/dom/ClientBinding.h"
#include "mozilla/dom/PromiseWorkerProxy.h"
using namespace mozilla::dom;
using namespace mozilla::dom::workers;
@ -17,18 +18,135 @@ ServiceWorkerWindowClient::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGiv
return WindowClientBinding::Wrap(aCx, this, aGivenProto);
}
already_AddRefed<Promise>
ServiceWorkerWindowClient::Focus() const
namespace {
// Passing a null clientInfo will reject the promise with InvalidAccessError.
class ResolveOrRejectPromiseRunnable final : public WorkerRunnable
{
ErrorResult result;
nsRefPtr<PromiseWorkerProxy> mPromiseProxy;
UniquePtr<ServiceWorkerClientInfo> mClientInfo;
public:
ResolveOrRejectPromiseRunnable(WorkerPrivate* aWorkerPrivate,
PromiseWorkerProxy* aPromiseProxy,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount)
, mPromiseProxy(aPromiseProxy)
, mClientInfo(Move(aClientInfo))
{
AssertIsOnMainThread();
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
Promise* promise = mPromiseProxy->GetWorkerPromise();
MOZ_ASSERT(promise);
if (mClientInfo) {
nsRefPtr<ServiceWorkerWindowClient> client =
new ServiceWorkerWindowClient(promise->GetParentObject(), *mClientInfo);
promise->MaybeResolve(client);
} else {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
}
// Release the reference on the worker thread.
mPromiseProxy->CleanUp(aCx);
return true;
}
};
class ClientFocusRunnable final : public nsRunnable
{
uint64_t mWindowId;
nsRefPtr<PromiseWorkerProxy> mPromiseProxy;
public:
ClientFocusRunnable(uint64_t aWindowId, PromiseWorkerProxy* aPromiseProxy)
: mWindowId(aWindowId)
, mPromiseProxy(aPromiseProxy)
{
MOZ_ASSERT(mPromiseProxy);
MOZ_ASSERT(mPromiseProxy->GetWorkerPromise());
}
NS_IMETHOD
Run() override
{
AssertIsOnMainThread();
nsGlobalWindow* window = nsGlobalWindow::GetOuterWindowWithId(mWindowId);
UniquePtr<ServiceWorkerClientInfo> clientInfo;
if (window) {
ErrorResult result;
//FIXME(catalinb): Bug 1144660 - check if we are allowed to focus here.
window->Focus(result);
clientInfo.reset(new ServiceWorkerClientInfo(window->GetDocument()));
}
DispatchResult(Move(clientInfo));
return NS_OK;
}
private:
void
DispatchResult(UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
{
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
MOZ_ASSERT(workerPrivate);
nsRefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable =
new ResolveOrRejectPromiseRunnable(workerPrivate, mPromiseProxy,
Move(aClientInfo));
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
if (!resolveRunnable->Dispatch(cx)) {
nsRefPtr<PromiseWorkerProxyControlRunnable> controlRunnable =
new PromiseWorkerProxyControlRunnable(workerPrivate, mPromiseProxy);
if (!controlRunnable->Dispatch(cx)) {
NS_RUNTIMEABORT("Failed to dispatch Focus promise control runnable.");
}
}
}
};
} // anonymous namespace
already_AddRefed<Promise>
ServiceWorkerWindowClient::Focus(ErrorResult& aRv) const
{
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
MOZ_ASSERT(global);
nsRefPtr<Promise> promise = Promise::Create(global, result);
if (NS_WARN_IF(result.Failed())) {
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
nsRefPtr<PromiseWorkerProxy> promiseProxy =
PromiseWorkerProxy::Create(workerPrivate, promise);
if (!promiseProxy->GetWorkerPromise()) {
// Don't dispatch if adding the worker feature failed.
return promise.forget();
}
nsRefPtr<ClientFocusRunnable> r = new ClientFocusRunnable(mWindowId,
promiseProxy);
aRv = NS_DispatchToMainThread(r);
if (NS_WARN_IF(aRv.Failed())) {
promise->MaybeReject(aRv.ErrorCode());
}
return promise.forget();
}

View File

@ -47,7 +47,7 @@ public:
}
already_AddRefed<Promise>
Focus() const;
Focus(ErrorResult& aRv) const;
private:
~ServiceWorkerWindowClient()

View File

@ -5898,11 +5898,10 @@ WorkerPrivate::NotifyFeatures(JSContext* aCx, Status aStatus)
CancelAllTimeouts(aCx);
}
nsAutoTArray<WorkerFeature*, 30> features;
features.AppendElements(mFeatures);
for (uint32_t index = 0; index < features.Length(); index++) {
if (!features[index]->Notify(aCx, aStatus)) {
nsTObserverArray<WorkerFeature*>::ForwardIterator iter(mFeatures);
while (iter.HasMore()) {
WorkerFeature* feature = iter.GetNext();
if (!feature->Notify(aCx, aStatus)) {
NS_WARNING("Failed to notify feature!");
}
}

View File

@ -25,6 +25,7 @@
#include "nsString.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "nsTObserverArray.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "Queue.h"
@ -852,7 +853,7 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
nsRefPtr<WorkerGlobalScope> mScope;
nsRefPtr<WorkerDebuggerGlobalScope> mDebuggerScope;
nsTArray<ParentType*> mChildWorkers;
nsTArray<WorkerFeature*> mFeatures;
nsTObserverArray<WorkerFeature*> mFeatures;
nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
uint32_t mDebuggerEventLoopLevel;

View File

@ -0,0 +1,15 @@
onmessage = function(e) {
if (!e.source) {
dump("ERROR: message doesn't have a source.");
}
// The client should be a window client
if (e.source instanceof WindowClient) {
// this will dispatch a focus event on the client
e.source.focus().then(function(client) {
client.postMessage(client.focused);
});
} else {
dump("ERROR: client should be a WindowClient");
}
};

View File

@ -17,6 +17,7 @@ support-files =
workerUpdate/update.html
sw_clients/simple.html
sw_clients/service_worker_controlled.html
sw_clients/focus_stealing_client.html
match_all_worker.js
match_all_advanced_worker.js
worker_unregister.js
@ -63,6 +64,7 @@ support-files =
redirect_serviceworker.sjs
importscript.sjs
importscript_worker.js
client_focus_worker.js
[test_unregister.html]
[test_installation_simple.html]
@ -89,3 +91,4 @@ skip-if = true # Bug 1136780
[test_sandbox_intercept.html]
[test_request_context.html]
[test_importscript.html]
[test_client_focus.html]

View File

@ -0,0 +1,33 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1130686 - Test service worker client.focus: client </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<!--
We load this as an iframe to blur the main test window.
-->
</head>
<body>/
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
if (!parent) {
info("error: sw_clients/focus_stealing_client.html shouldn't be launched directly!");
}
window.onload = function() {
navigator.serviceWorker.ready.then(function() {
parent.postMessage("READY", "*");
});
}
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,94 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1130686 - Test service worker client.focus </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<!--
This test checks that client.focus is able to restore focus to the main window
when an iframe is holding the focus.
-->
</head>
<body>
<p id="display"></p>
<div id="content"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var registration;
var worker;
function start() {
return navigator.serviceWorker.register("client_focus_worker.js",
{ scope: "./sw_clients/focus_stealing_client.html" })
.then((swr) => registration = swr);
}
function unregister() {
return registration.unregister().then(function(result) {
ok(result, "Unregister should return true.");
});
}
function loseFocus() {
var p = new Promise(function(res, rej) {
window.onmessage = function(e) {
if (e.data == "READY") {
ok(true, "iframe created.");
iframe.contentWindow.focus();
}
}
window.onblur = function() {
ok(true, "blurred");
res();
}
});
content = document.getElementById("content");
ok(content, "parent exists.");
iframe = document.createElement("iframe");
content.appendChild(iframe);
iframe.setAttribute('src', "sw_clients/focus_stealing_client.html");
return p;
}
function testFocus() {
var p = new Promise(function(res, rej) {
navigator.serviceWorker.onmessage = function(e) {
ok(e.data, "client object is marked as focused.");
ok(document.hasFocus(), "document has focus.");
res();
}
});
ok(registration.active, "active worker exists.");
registration.active.postMessage("go");
return p;
}
function runTest() {
start()
.then(loseFocus)
.then(testFocus)
.then(unregister)
.catch(function(e) {
ok(false, "Some test failed with error " + e);
}).then(SimpleTest.finish);
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
]}, runTest);
</script>
</pre>
</body>
</html>

View File

@ -296,7 +296,7 @@ GLContextProviderCGL::CreateOffscreen(const gfxIntSize& size,
bool requireCompatProfile)
{
nsRefPtr<GLContext> glContext = CreateHeadless(requireCompatProfile);
if (!glContext->InitOffscreen(ToIntSize(size), caps))
if (!glContext->InitOffscreen(size, caps))
return nullptr;
return glContext.forget();

View File

@ -904,7 +904,7 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& size,
if (!glContext)
return nullptr;
if (!glContext->InitOffscreen(ToIntSize(size), caps))
if (!glContext->InitOffscreen(size, caps))
return nullptr;
return glContext.forget();

View File

@ -1234,7 +1234,7 @@ GLContextProviderGLX::CreateOffscreen(const gfxIntSize& size,
if (!glContext)
return nullptr;
if (!glContext->InitOffscreen(ToIntSize(size), caps))
if (!glContext->InitOffscreen(size, caps))
return nullptr;
return glContext.forget();

View File

@ -640,7 +640,7 @@ GLContextProviderWGL::CreateHeadless(bool)
}
already_AddRefed<GLContext>
GLContextProviderWGL::CreateOffscreen(const gfxIntSize& size,
GLContextProviderWGL::CreateOffscreen(const IntSize& size,
const SurfaceCaps& caps,
bool requireCompatProfile)
{
@ -648,7 +648,7 @@ GLContextProviderWGL::CreateOffscreen(const gfxIntSize& size,
if (!glContext)
return nullptr;
if (!glContext->InitOffscreen(ToIntSize(size), caps))
if (!glContext->InitOffscreen(size, caps))
return nullptr;
return glContext.forget();

View File

@ -126,7 +126,7 @@ DIBTextureHost::DIBTextureHost(TextureFlags aFlags,
dont_AddRef(reinterpret_cast<gfxWindowsSurface*>(aDescriptor.surface()));
MOZ_ASSERT(mSurface);
mSize = ToIntSize(mSurface->GetSize());
mSize = mSurface->GetSize();
mFormat = ImageFormatToSurfaceFormat(
gfxPlatform::GetPlatform()->OptimalFormatForContent(mSurface->GetContentType()));
}

View File

@ -5,7 +5,6 @@
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include <string.h> // for memcpy
#include "gfx2DGlue.h" // for ToIntSize
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Logging.h" // for gfxDebug

View File

@ -639,7 +639,7 @@ Transform(const gfxImageSurface* aDest,
return;
}
IntSize destSize = ToIntSize(aDest->GetSize());
IntSize destSize = aDest->GetSize();
SkImageInfo destInfo = SkImageInfo::Make(destSize.width,
destSize.height,
kBGRA_8888_SkColorType,
@ -697,7 +697,7 @@ Transform(const gfxImageSurface* aDest,
const gfx3DMatrix& aTransform,
gfxPoint aDestOffset)
{
IntSize destSize = ToIntSize(aDest->GetSize());
IntSize destSize = aDest->GetSize();
pixman_image_t* dest = pixman_image_create_bits(aDest->Format() == gfxImageFormat::ARGB32 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8,
destSize.width,
destSize.height,

View File

@ -144,7 +144,7 @@ TextureClientX11::BorrowDrawTarget()
}
if (!mDrawTarget) {
IntSize size = ToIntSize(mSurface->GetSize());
IntSize size = mSurface->GetSize();
mDrawTarget = Factory::CreateDrawTargetForCairoSurface(mSurface->CairoSurface(), size);
}

View File

@ -21,7 +21,7 @@ X11TextureSourceBasic::X11TextureSourceBasic(BasicCompositor* aCompositor, gfxXl
IntSize
X11TextureSourceBasic::GetSize() const
{
return ToIntSize(mSurface->GetSize());
return mSurface->GetSize();
}
SurfaceFormat

View File

@ -258,17 +258,15 @@ ClientTiledPaintedLayer::UseProgressiveDraw() {
return false;
}
// XXX We probably want to disable progressive drawing for non active APZ layers in the future
// but we should wait for a proper test case before making this change.
#if 0 //!defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ)
LayerMetricsWrapper scrollAncestor;
GetAncestorLayers(&scrollAncestor, nullptr, nullptr);
MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is non-empty
const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
if (!IsScrollingOnCompositor(parentMetrics)) {
return false;
if (gfxPrefs::AsyncPanZoomEnabled()) {
LayerMetricsWrapper scrollAncestor;
GetAncestorLayers(&scrollAncestor, nullptr, nullptr);
MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is non-empty
const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
if (!IsScrollingOnCompositor(parentMetrics)) {
return false;
}
}
#endif
return true;
}

View File

@ -805,7 +805,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
scrollbarTransform.PostTranslate(xTranslation, 0, 0);
}
Matrix4x4 transform = scrollbarTransform * aScrollbar->GetTransform();
Matrix4x4 transform = aScrollbar->GetLocalTransform() * scrollbarTransform;
if (aScrollbarIsDescendant) {
// If the scrollbar layer is a child of the content it is a scrollbar for,

View File

@ -344,7 +344,8 @@ RenderLayers(ContainerT* aContainer,
Layer* layer = layerToRender->GetLayer();
gfxRGBA color;
if (LayerHasCheckerboardingAPZC(layer, &color)) {
if ((layer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
LayerHasCheckerboardingAPZC(layer, &color)) {
// Ideally we would want to intersect the checkerboard region from the APZ with the layer bounds
// and only fill in that area. However the layer bounds takes into account the base translation
// for the painted layer whereas the checkerboard region does not. One does not simply

View File

@ -7,7 +7,6 @@
#include "CompositableHost.h" // for CompositableHost
#include "LayersLogging.h" // for AppendToString
#include "gfx2DGlue.h" // for ToIntSize
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
#include "mozilla/ipc/Shmem.h" // for Shmem
#include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager

View File

@ -83,7 +83,7 @@ X11TextureHost::GetFormat() const
IntSize
X11TextureHost::GetSize() const
{
return ToIntSize(mSurface->GetSize());
return mSurface->GetSize();
}
}

View File

@ -1458,18 +1458,24 @@ CompositorD3D11::HandleError(HRESULT hr, Severity aSeverity)
if (SUCCEEDED(hr)) {
return;
}
// XXX - It would be nice to use gfxCriticalError, but it needs to
// be made to work off the main thread first.
//MOZ_ASSERT(aSeverity != DebugAssert);
if (aSeverity == Critical) {
MOZ_CRASH("Unrecoverable D3D11 error");
}
if (mDevice && hr == DXGI_ERROR_DEVICE_REMOVED) {
bool deviceRemoved = hr == DXGI_ERROR_DEVICE_REMOVED;
if (deviceRemoved && mDevice) {
hr = mDevice->GetDeviceRemovedReason();
}
// Device reset may not be an error on our side, but can mess things up so
// it's useful to see it in the reports.
gfxCriticalError(CriticalLog::DefaultOptions(!deviceRemoved))
<< (deviceRemoved ? "[CompositorD3D11] device removed with error code: "
: "[CompositorD3D11] error code: ")
<< hexa(hr);
// Always crash if we are making invalid calls
if (hr == DXGI_ERROR_INVALID_CALL) {
MOZ_CRASH("Invalid D3D11 api call");

View File

@ -167,7 +167,7 @@ private:
void SetPSForEffect(Effect *aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat);
void PaintToTarget();
virtual gfx::IntSize GetWidgetSize() const override { return gfx::ToIntSize(mSize); }
virtual gfx::IntSize GetWidgetSize() const override { return mSize; }
RefPtr<ID3D11DeviceContext> mContext;
RefPtr<ID3D11Device> mDevice;
@ -179,7 +179,7 @@ private:
nsIWidget* mWidget;
nsIntSize mSize;
gfx::IntSize mSize;
HWND mHwnd;

View File

@ -152,7 +152,7 @@ private:
virtual gfx::IntSize GetWidgetSize() const override
{
return gfx::ToIntSize(mSize);
return mSize;
}
/* Device manager instance for this compositor */

View File

@ -240,7 +240,7 @@ DeviceManagerD3D9::Init()
mD3D9 = dont_AddRef(d3d9Create(D3D_SDK_VERSION));
if (!mD3D9) {
gfxCriticalError() << "[D3D9] Failed to create the device";
gfxCriticalError() << "[D3D9] Failed to create the IDirect3D9 object";
return false;
}
}
@ -249,7 +249,7 @@ DeviceManagerD3D9::Init()
hr = mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &ident);
if (FAILED(hr)) {
gfxCriticalError() << "[D3D9] Failed to create the environment";
gfxCriticalError() << "[D3D9] Failed to create the environment code: " << gfx::hexa(hr);
return false;
}
@ -331,13 +331,13 @@ DeviceManagerD3D9::Init()
mNv3DVUtils->SetDeviceInfo(devUnknown);
}
auto failCreateShaderMsg = "[D3D9] failed to create a critical resource (shader)";
auto failCreateShaderMsg = "[D3D9] failed to create a critical resource (shader) code: ";
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
getter_AddRefs(mLayerVS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -345,7 +345,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBPS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -353,7 +353,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBAPS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -361,7 +361,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mComponentPass1PS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -369,7 +369,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mComponentPass2PS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -377,7 +377,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mYCbCrPS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -393,14 +393,14 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mLayerVSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask3D,
getter_AddRefs(mLayerVSMask3D));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -408,7 +408,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBPSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -416,7 +416,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBAPSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -424,7 +424,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBAPSMask3D));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -432,7 +432,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mComponentPass1PSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -448,7 +448,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mYCbCrPSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -456,7 +456,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mSolidColorPSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
gfxCriticalError() << failCreateShaderMsg << gfx::hexa(hr);
return false;
}
@ -467,7 +467,7 @@ DeviceManagerD3D9::Init()
hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
if (FAILED(hr)) {
gfxCriticalError() << "[D3D9] Failed to set the stream source";
gfxCriticalError() << "[D3D9] Failed to set the stream source code: " << gfx::hexa(hr);
return false;
}

View File

@ -447,7 +447,7 @@ DataTextureSourceD3D9::Update(gfxWindowsSurface* aSurface)
NS_WARNING("No D3D device to update the texture.");
return false;
}
mSize = ToIntSize(aSurface->GetSize());
mSize = aSurface->GetSize();
uint32_t bpp = 0;

View File

@ -49,8 +49,7 @@ CreateSharedRGBImage(ImageContainer *aImageContainer,
}
nsRefPtr<SharedRGBImage> rgbImage = static_cast<SharedRGBImage*>(image.get());
if (!rgbImage->Allocate(gfx::ToIntSize(aSize),
gfx::ImageFormatToSurfaceFormat(aImageFormat))) {
if (!rgbImage->Allocate(aSize, gfx::ImageFormatToSurfaceFormat(aImageFormat))) {
NS_WARNING("Failed to allocate a shared image");
return nullptr;
}

View File

@ -307,7 +307,7 @@ public:
private:
virtual gfx::IntSize GetWidgetSize() const override
{
return gfx::ToIntSize(mWidgetSize);
return mWidgetSize;
}
bool InitializeVR();
@ -321,7 +321,7 @@ private:
/** Widget associated with this compositor */
nsIWidget *mWidget;
nsIntSize mWidgetSize;
gfx::IntSize mWidgetSize;
nsRefPtr<GLContext> mGLContext;
UniquePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
gfx::Matrix4x4 mProjMatrix;

View File

@ -60,7 +60,7 @@ X11TextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
IntSize
X11TextureSourceOGL::GetSize() const
{
return ToIntSize(mSurface->GetSize());
return mSurface->GetSize();
}
SurfaceFormat

View File

@ -69,6 +69,9 @@ TestIterator()
EXPECT_TRUE(iter1.GetSkippedOffset() == 0) <<
"[3] Check initial skipped offset";
EXPECT_TRUE(iter1.IsOriginalCharSkipped() == false) <<
"[3a] Check IsOriginalCharSkipped for initial position";
uint32_t expectSkipped1[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
@ -89,6 +92,18 @@ TestIterator()
"[5] Check mapping of skipped to original for " << i;
}
bool expectIsOriginalSkipped1[] =
{ false, false, false, false, false, false, false, false, false, true,
false, false, false, false, false, false, false, false, false, true,
false, false, false, false, false, false, false, false, false
};
for (uint32_t i = 0; i < mozilla::ArrayLength(expectIsOriginalSkipped1); i++) {
iter1.SetOriginalOffset(i);
EXPECT_TRUE(iter1.IsOriginalCharSkipped() == expectIsOriginalSkipped1[i]) <<
"[5.a] Check IsOriginalCharSkipped for " << i;
}
// Test a gfxSkipChars that starts with skipped chars
gfxSkipChars skipChars2;
@ -108,6 +123,9 @@ TestIterator()
EXPECT_TRUE(iter2.GetSkippedOffset() == 0) <<
"[8] Check initial skipped offset";
EXPECT_TRUE(iter2.IsOriginalCharSkipped() == true) <<
"[8a] Check IsOriginalCharSkipped for initial position";
uint32_t expectSkipped2[] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -125,6 +143,18 @@ TestIterator()
"[10] Check mapping of skipped to original for " << i;
}
bool expectIsOriginalSkipped2[] =
{ true, true, true, true, true, true, true, true, true, false,
true, true, true, true, true, true, true, true, true, false,
true, true, true, true, true, true, true, true, true
};
for (uint32_t i = 0; i < mozilla::ArrayLength(expectIsOriginalSkipped2); i++) {
iter2.SetOriginalOffset(i);
EXPECT_TRUE(iter2.IsOriginalCharSkipped() == expectIsOriginalSkipped2[i]) <<
"[10.a] Check IsOriginalCharSkipped for " << i;
}
return true;
}

View File

@ -148,7 +148,7 @@ void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface)
// client allocation
ASSERT_TRUE(texture->CanExposeDrawTarget());
texture->AllocateForSurface(ToIntSize(surface->GetSize()));
texture->AllocateForSurface(surface->GetSize());
ASSERT_TRUE(texture->IsAllocated());
ASSERT_TRUE(texture->Lock(OpenMode::OPEN_READ_WRITE));

View File

@ -81,11 +81,6 @@ inline Size ToSize(const gfxSize &aSize)
return Size(Float(aSize.width), Float(aSize.height));
}
inline IntSize ToIntSize(const gfxIntSize &aSize)
{
return IntSize(aSize.width, aSize.height);
}
inline Filter ToFilter(GraphicsFilter aFilter)
{
switch (aFilter) {

View File

@ -837,7 +837,7 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
surf.mFormat = format;
surf.mType = NativeSurfaceType::CAIRO_SURFACE;
surf.mSurface = aSurface->CairoSurface();
surf.mSize = ToIntSize(aSurface->GetSize());
surf.mSize = aSurface->GetSize();
// We return here regardless of whether CreateSourceSurfaceFromNativeSurface
// succeeds or not since we don't expect to be able to do any better below
// if it fails.
@ -862,7 +862,7 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
surf.mFormat = format;
surf.mType = NativeSurfaceType::D3D10_TEXTURE;
surf.mSurface = static_cast<gfxD2DSurface*>(aSurface)->GetTexture();
surf.mSize = ToIntSize(aSurface->GetSize());
surf.mSize = aSurface->GetSize();
mozilla::gfx::DrawTarget *dt = static_cast<mozilla::gfx::DrawTarget*>(aSurface->GetData(&kDrawTarget));
if (dt) {
dt->Flush();
@ -910,7 +910,7 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
surf.mFormat = format;
surf.mType = NativeSurfaceType::CAIRO_SURFACE;
surf.mSurface = aSurface->CairoSurface();
surf.mSize = ToIntSize(aSurface->GetSize());
surf.mSize = aSurface->GetSize();
RefPtr<DrawTarget> drawTarget =
Factory::CreateDrawTarget(BackendType::CAIRO, IntSize(1, 1), format);
if (!drawTarget) {
@ -956,7 +956,7 @@ gfxPlatform::GetWrappedDataSourceSurface(gfxASurface* aSurface)
RefPtr<DataSourceSurface> result =
Factory::CreateWrappingDataSourceSurface(image->Data(),
image->Stride(),
ToIntSize(image->GetSize()),
image->GetSize(),
ImageFormatToSurfaceFormat(image->Format()));
if (!result) {

View File

@ -177,7 +177,7 @@ public:
mCurrentRangeIndex(-1),
mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset)
{
SetOriginalOffset(aOriginalStringOffset);
SetOriginalOffset(aOriginalStringOffset);
}
explicit gfxSkipCharsIterator(const gfxSkipChars& aSkipChars,
@ -185,9 +185,12 @@ public:
: mSkipChars(&aSkipChars),
mOriginalStringOffset(0),
mSkippedStringOffset(0),
mCurrentRangeIndex(-1),
mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset)
{ }
{
mCurrentRangeIndex =
mSkipChars->mRanges.IsEmpty() ||
mSkipChars->mRanges[0].Start() > 0 ? -1 : 0;
}
gfxSkipCharsIterator(const gfxSkipCharsIterator& aIterator)
: mSkipChars(aIterator.mSkipChars),

View File

@ -441,8 +441,7 @@ CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable,
gfxIntSize size(int32_t(needed.Width()), int32_t(needed.Height()));
RefPtr<DrawTarget> target =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(ToIntSize(size),
aFormat);
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(size, aFormat);
if (!target) {
return nullptr;
}
@ -869,7 +868,7 @@ gfxUtils::GetYCbCrToRGBDestFormatAndSize(const PlanarYCbCrData& aData,
// 'prescale' is true if the scaling is to be done as part of the
// YCbCr to RGB conversion rather than on the RGB data when rendered.
bool prescale = aSuggestedSize.width > 0 && aSuggestedSize.height > 0 &&
ToIntSize(aSuggestedSize) != aData.mPicSize;
aSuggestedSize != aData.mPicSize;
if (aSuggestedFormat == gfxImageFormat::RGB16_565) {
#if defined(HAVE_YCBCR_TO_RGB565)
@ -905,7 +904,7 @@ gfxUtils::GetYCbCrToRGBDestFormatAndSize(const PlanarYCbCrData& aData,
prescale = false;
}
if (!prescale) {
ToIntSize(aSuggestedSize) = aData.mPicSize;
aSuggestedSize = aData.mPicSize;
}
}
@ -929,7 +928,7 @@ gfxUtils::ConvertYCbCrToRGB(const PlanarYCbCrData& aData,
aData.mCbCrSize.height);
// Convert from YCbCr to RGB now, scaling the image if needed.
if (ToIntSize(aDestSize) != aData.mPicSize) {
if (aDestSize != aData.mPicSize) {
#if defined(HAVE_YCBCR_TO_RGB565)
if (aDestFormat == gfxImageFormat::RGB16_565) {
ScaleYCbCrToRGB565(aData.mYChannel,

View File

@ -272,7 +272,7 @@ gfxWindowsNativeDrawing::PaintToContext()
RefPtr<DataSourceSurface> source =
Factory::CreateWrappingDataSourceSurface(black->Data(),
black->Stride(),
ToIntSize(black->GetSize()),
black->GetSize(),
SurfaceFormat::B8G8R8A8);
mContext->Save();

View File

@ -573,7 +573,7 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
native.mFormat = moz2DFormat;
native.mType = NativeSurfaceType::CAIRO_SURFACE;
native.mSurface = tempXlibSurface;
native.mSize = ToIntSize(size);
native.mSize = size;
RefPtr<SourceSurface> sourceSurface =
drawTarget->CreateSourceSurfaceFromNativeSurface(native);
if (sourceSurface) {
@ -615,7 +615,7 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
native.mFormat = moz2DFormat;
native.mType = NativeSurfaceType::CAIRO_SURFACE;
native.mSurface = paintSurface->CairoSurface();
native.mSize = ToIntSize(size);
native.mSize = size;
RefPtr<SourceSurface> sourceSurface =
drawTarget->CreateSourceSurfaceFromNativeSurface(native);
if (sourceSurface) {

View File

@ -281,7 +281,7 @@ nsPNGDecoder::InitInternal()
(int)sizeof(unused_chunks)/5);
#endif
#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (mCMSMode != eCMSMode_Off) {
png_set_chunk_malloc_max(mPNG, 4000000L);
}

View File

@ -98,7 +98,7 @@ OrientedImage::GetFrame(uint32_t aWhichFrame,
// Create a surface to draw into.
RefPtr<DrawTarget> target =
gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(ToIntSize(size), surfaceFormat);
CreateOffscreenContentDrawTarget(size, surfaceFormat);
if (!target) {
NS_ERROR("Could not create a DrawTarget");
return nullptr;

View File

@ -2622,6 +2622,9 @@ void imgCacheValidator::AddProxy(imgRequestProxy *aProxy)
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt)
{
// We may be holding on to a document, so ensure that it's released.
nsCOMPtr<nsISupports> context = mContext.forget();
// If for some reason we don't still have an existing request (probably
// because OnStartRequest got delivered more than once), just bail.
if (!mRequest) {
@ -2670,7 +2673,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
// We don't need to load this any more.
aRequest->Cancel(NS_BINDING_ABORTED);
mRequest->SetLoadId(mContext);
mRequest->SetLoadId(context);
mRequest->SetValidator(nullptr);
mRequest = nullptr;
@ -2711,7 +2714,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
nsCOMPtr<nsIURI> originalURI;
channel->GetOriginalURI(getter_AddRefs(originalURI));
mNewRequest->Init(originalURI, uri, mHadInsecureRedirect, aRequest, channel,
mNewEntry, mContext, loadingPrincipal, corsmode, refpol);
mNewEntry, context, loadingPrincipal, corsmode, refpol);
mDestListener = new ProxyListener(mNewRequest);
@ -2740,6 +2743,9 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */
NS_IMETHODIMP imgCacheValidator::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status)
{
// Be sure we've released the document that we may have been holding on to.
mContext = nullptr;
if (!mDestListener)
return NS_OK;

View File

@ -4,7 +4,7 @@
# 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/.
DIRS += ['internal']
DIRS += ['internal', 'standalone']
EXPORTS += [
'GreekCasing.h',

View File

@ -0,0 +1,23 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
if CONFIG['OS_TARGET'] != 'WINNT' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
Library('unicharutil_standalone')
intl_unicharutil_util_lcppsrcs = [
'nsUnicodeProperties.cpp',
]
intl_unicharutil_util_cppsrcs = [
'%s/intl/unicharutil/util/%s' % (TOPSRCDIR, s) \
for s in intl_unicharutil_util_lcppsrcs
]
UNIFIED_SOURCES += intl_unicharutil_util_cppsrcs
for var in ('MOZILLA_INTERNAL_API', 'MOZILLA_XPCOMRT_API', 'MOZILLA_EXTERNAL_LINKAGE',
'NR_SOCKET_IS_VOID_PTR', 'HAVE_STRDUP'):
DEFINES[var] = True

View File

@ -682,6 +682,12 @@ BuiltinToName(AsmJSExit::BuiltinKind builtin)
#if defined(JS_CODEGEN_ARM)
case AsmJSExit::Builtin_IDivMod: return "software idivmod (in asm.js)";
case AsmJSExit::Builtin_UDivMod: return "software uidivmod (in asm.js)";
case AsmJSExit::Builtin_AtomicCmpXchg: return "Atomics.compareExchange (in asm.js)";
case AsmJSExit::Builtin_AtomicFetchAdd: return "Atomics.add (in asm.js)";
case AsmJSExit::Builtin_AtomicFetchSub: return "Atomics.sub (in asm.js)";
case AsmJSExit::Builtin_AtomicFetchAnd: return "Atomics.and (in asm.js)";
case AsmJSExit::Builtin_AtomicFetchOr: return "Atomics.or (in asm.js)";
case AsmJSExit::Builtin_AtomicFetchXor: return "Atomics.xor (in asm.js)";
#endif
case AsmJSExit::Builtin_ModD: return "fmod (in asm.js)";
case AsmJSExit::Builtin_SinD: return "Math.sin (in asm.js)";

View File

@ -80,6 +80,12 @@ namespace AsmJSExit
#if defined(JS_CODEGEN_ARM)
Builtin_IDivMod,
Builtin_UDivMod,
Builtin_AtomicCmpXchg,
Builtin_AtomicFetchAdd,
Builtin_AtomicFetchSub,
Builtin_AtomicFetchAnd,
Builtin_AtomicFetchOr,
Builtin_AtomicFetchXor,
#endif
Builtin_ModD,
Builtin_SinD,

Some files were not shown because too many files have changed in this diff Show More