Merge m-c to b2ginbound, a=merge

--HG--
extra : commitid : D2Y3M7mYh1H
This commit is contained in:
Wes Kocher 2015-11-16 17:27:40 -08:00
commit 3663e7217a
538 changed files with 8270 additions and 4681 deletions

View File

@ -478,14 +478,17 @@
attrs = { "font-family": kAbsentFontFamily };
testTextAttrs(ID, 18, attrs, defAttrs, 18, 22);
attrs = { };
testTextAttrs(ID, 22, attrs, defAttrs, 22, 27);
// bug 1224498 - this fails with 'cursive' fontconfig lookup
if (!LINUX) {
attrs = { };
testTextAttrs(ID, 22, attrs, defAttrs, 22, 27);
attrs = { "font-family": kCursiveFontFamily };
testTextAttrs(ID, 27, attrs, defAttrs, 27, 31);
attrs = { "font-family": kCursiveFontFamily };
testTextAttrs(ID, 27, attrs, defAttrs, 27, 31);
attrs = { };
testTextAttrs(ID, 31, attrs, defAttrs, 31, 44);
attrs = { };
testTextAttrs(ID, 31, attrs, defAttrs, 31, 44);
}
//////////////////////////////////////////////////////////////////////////
// area17, "text-decoration" tests

View File

@ -1,2 +1,19 @@
console.log('script evaluation');
console.log("Hello from serviceworker");
addEventListener('install', function(evt) {
console.log('install event');
});
addEventListener('activate', function(evt) {
console.log('activate event');
});
addEventListener('fetch', function(evt) {
console.log('fetch event: ' + evt.request.url);
evt.respondWith(new Response('Hello world'));
});
addEventListener('message', function(evt) {
console.log('message event: ' + evt.data.message);
evt.source.postMessage({ type: 'PONG' });
});

View File

@ -14,16 +14,40 @@
<script class="testbody" type="text/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();
let SERVICE_WORKER_URL = "https://example.com/chrome/devtools/shared/webconsole/test/helper_serviceworker.js";
let FRAME_URL = "https://example.com/chrome/devtools/shared/webconsole/test/sandboxed_iframe.html";
let BASE_URL = "https://example.com/chrome/devtools/shared/webconsole/test/";
let SERVICE_WORKER_URL = BASE_URL + "helper_serviceworker.js";
let SCOPE = BASE_URL + "foo/";
let NONSCOPE_FRAME_URL = BASE_URL + "sandboxed_iframe.html";
let SCOPE_FRAME_URL = SCOPE + "fake.html";
let SCOPE_FRAME_URL2 = SCOPE + "whatsit.html";
let MESSAGE = 'Tic Tock';
let swClosed = new Promise(() => {});
let expectedConsoleCalls = [
{
level: "log",
filename: /helper_serviceworker/,
arguments: ["Hello from serviceworker"],
}
arguments: ['script evaluation'],
},
{
level: "log",
filename: /helper_serviceworker/,
arguments: ['install event'],
},
{
level: "log",
filename: /helper_serviceworker/,
arguments: ['activate event'],
},
{
level: "log",
filename: /helper_serviceworker/,
arguments: ['fetch event: ' + SCOPE_FRAME_URL],
},
{
level: "log",
filename: /helper_serviceworker/,
arguments: ['fetch event: ' + SCOPE_FRAME_URL2],
},
];
let consoleCalls = [];
@ -40,55 +64,160 @@ let startTest = Task.async(function*() {
});
addEventListener("load", startTest);
function onAttach(state, response) {
onConsoleAPICall = onConsoleAPICall.bind(null, state);
state.dbgClient.addListener("consoleAPICall", onConsoleAPICall);
info("Loading a ServiceWorker that will use console API");
swClosed = new Promise(resolve => {
function withFrame(url) {
return new Promise(resolve => {
let iframe = document.createElement("iframe");
iframe.onload = function() {
let win = iframe.contentWindow;
info("Registering the service worker");
win.navigator.serviceWorker.register(SERVICE_WORKER_URL).then(swr => {
info("Service worker registered. Unregistering");
swr.unregister().then(() => {
resolve();
});
}, error => {
info("Error registering service worker: " + error);
});
resolve(iframe);
};
iframe.src = FRAME_URL;
iframe.src = url;
document.body.appendChild(iframe);
});
}
function navigateFrame(iframe, url) {
return new Promise(resolve => {
iframe.onload = function() {
resolve(iframe);
};
iframe.src = url;
});
}
function forceReloadFrame(iframe) {
return new Promise(resolve => {
iframe.onload = function() {
resolve(iframe);
};
iframe.contentWindow.location.reload(true);
});
}
function withActiveServiceWorker(win, url, scope) {
return win.navigator.serviceWorker.register(url, { scope: scope }).then(swr => {
if (swr.active) {
return swr;
}
// Unfortunately we can't just use navigator.serviceWorker.ready promise
// here. If the service worker is for a scope that does not cover the window
// then the ready promise will never resolve. Instead monitor the service
// workers state change events to determine when its activated.
return new Promise(resolve => {
let sw = swr.waiting || swr.installing;
sw.addEventListener('statechange', function stateHandler(evt) {
if (sw.state === 'activated') {
sw.removeEventListener('statechange', stateHandler);
resolve(swr);
}
});
});
});
}
function messageServiceWorker(win, scope, message) {
return win.navigator.serviceWorker.getRegistration(scope).then(swr => {
return new Promise(resolve => {
win.navigator.serviceWorker.onmessage = evt => {
resolve();
};
let sw = swr.active || swr.waiting || swr.installing;
sw.postMessage({ type: 'PING', message: message });
});
})
}
function unregisterServiceWorker(win) {
return win.navigator.serviceWorker.ready.then(swr => {
return swr.unregister();
});
}
let onAttach = Task.async(function*(state, response) {
onConsoleAPICall = onConsoleAPICall.bind(null, state);
state.dbgClient.addListener("consoleAPICall", onConsoleAPICall);
let currentFrame;
try {
// First, we need a frame from which to register our script. This
// will not trigger any console calls.
info("Loading a non-scope frame from which to register a service worker.");
currentFrame = yield withFrame(NONSCOPE_FRAME_URL);
// Now register the service worker and wait for it to become
// activate. This should trigger 3 console calls; 1 for script
// evaluation, 1 for the install event, and 1 for the activate
// event. These console calls are received because we called
// register(), not because we are in scope for the worker.
info("Registering the service worker");
yield withActiveServiceWorker(currentFrame.contentWindow,
SERVICE_WORKER_URL, SCOPE);
ok(!currentFrame.contentWindow.navigator.serviceWorker.controller,
'current frame should not be controlled');
// Now that the service worker is activate, lets navigate our frame.
// This will trigger 1 more console call for the fetch event.
info("Service worker registered. Navigating frame.");
yield navigateFrame(currentFrame, SCOPE_FRAME_URL);
ok(currentFrame.contentWindow.navigator.serviceWorker.controller,
'navigated frame should be controlled');
// We now have a controlled frame. Lets perform a non-navigation fetch.
// This should produce another console call for the fetch event.
info("Frame navigated. Calling fetch().");
yield currentFrame.contentWindow.fetch(SCOPE_FRAME_URL2);
// Now force refresh our controlled frame. This will cause the frame
// to bypass the service worker and become an uncontrolled frame. It
// also happens to make the frame display a 404 message because the URL
// does not resolve to a real resource. This is ok, as we really only
// care about the frame being non-controlled, but still having a location
// that matches our service worker scope so we can provide its not
// incorrectly getting console calls.
info("Completed fetch(). Force refreshing to get uncontrolled frame.");
yield forceReloadFrame(currentFrame);
ok(!currentFrame.contentWindow.navigator.serviceWorker.controller,
'current frame should not be controlled after force refresh');
is(currentFrame.contentWindow.location.toString(), SCOPE_FRAME_URL,
'current frame should still have in-scope location URL even though it got 404');
// Now postMessage() the service worker to trigger its message event
// handler. This will generate 1 or 2 to console.log() statements
// depending on if the worker thread needs to spin up again. In either
// case, though, we should not get any console calls because we don't
// have a controlled or registering document.
info("Completed force refresh. Messaging service worker.");
yield messageServiceWorker(currentFrame.contentWindow, SCOPE, MESSAGE);
info("Done messaging service worker. Unregistering service worker.");
yield unregisterServiceWorker(currentFrame.contentWindow);
info('Service worker unregistered. Checking console calls.');
state.dbgClient.removeListener("consoleAPICall", onConsoleAPICall);
is(consoleCalls.length, expectedConsoleCalls.length,
'received correct number of console calls');
expectedConsoleCalls.forEach(function(aMessage, aIndex) {
info("checking received console call #" + aIndex);
checkConsoleAPICall(consoleCalls[aIndex], expectedConsoleCalls[aIndex]);
});
} catch(error) {
ok(false, 'unexpected error: ' + error);
} finally {
if (currentFrame) {
currentFrame.remove();
currentFrame = null;
}
consoleCalls = [];
closeDebugger(state, function() {
SimpleTest.finish();
});
}
});
function onConsoleAPICall(state, type, packet) {
info("received message level: " + packet.message.level);
is(packet.from, state.actor, "console API call actor");
consoleCalls.push(packet.message);
if (consoleCalls.length != expectedConsoleCalls.length) {
return;
}
state.dbgClient.removeListener("consoleAPICall", onConsoleAPICall);
expectedConsoleCalls.forEach(function(aMessage, aIndex) {
info("checking received console call #" + aIndex);
checkConsoleAPICall(consoleCalls[aIndex], expectedConsoleCalls[aIndex]);
});
consoleCalls = [];
closeDebugger(state, function() {
swClosed.then(() => {
SimpleTest.finish();
});
});
}
</script>
</body>

View File

@ -18,6 +18,11 @@ loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
loader.lazyImporter(this, "VariablesView", "resource://devtools/client/shared/widgets/VariablesView.jsm");
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
XPCOMUtils.defineLazyServiceGetter(this,
"swm",
"@mozilla.org/serviceworkers/manager;1",
"nsIServiceWorkerManager");
// Match the function name from the result of toString() or toSource().
//
// Examples:
@ -126,29 +131,6 @@ var WebConsoleUtils = {
aTo.style.fontStyle = style.getPropertyCSSValue("font-style").cssText;
},
/**
* Recursively gather a list of window locations given
* a top level window.
*
* @param nsIDOMWindow aWindow
* @return Array
* list of window locations as strings
*/
getLocationsForFrames: function(aWindow)
{
let location = aWindow.location.toString();
let locations = [location];
if (aWindow.frames) {
for (let i = 0; i < aWindow.frames.length; i++) {
let frame = aWindow.frames[i];
locations = locations.concat(this.getLocationsForFrames(frame));
}
}
return locations;
},
/**
* Gets the ID of the inner window of this DOM window.
*
@ -994,9 +976,8 @@ ConsoleAPIListener.prototype =
// scope, which can be used to determine whether it's controlling
// a window.
let scope = message.ID;
let locations = WebConsoleUtils.getLocationsForFrames(this.window);
if (!locations.some(loc => loc.startsWith(scope))) {
if (!swm.shouldReportToWindow(this.window, scope)) {
return false;
}
}

View File

@ -13714,6 +13714,13 @@ nsDocShell::SetIsBrowserInsideApp(uint32_t aContainingAppId)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetIsSignedPackage(const nsAString& aSignedPkg)
{
mSignedPkg = aSignedPkg;
return NS_OK;
}
/* [infallible] */ NS_IMETHODIMP
nsDocShell::GetIsBrowserElement(bool* aIsBrowser)
{
@ -13821,6 +13828,9 @@ nsDocShell::GetOriginAttributes()
attrs.mInBrowser = true;
}
// Bug 1209162 will address the inheritance of each attributes.
attrs.mSignedPkg = mSignedPkg;
return attrs;
}

View File

@ -1005,6 +1005,10 @@ protected:
nsString GetInheritedPaymentRequestId();
// The packageId for a signed packaged iff this docShell is created
// for a signed package.
nsString mSignedPkg;
private:
nsCString mForcedCharset;
nsCString mParentCharset;

View File

@ -43,7 +43,7 @@ interface nsITabParent;
typedef unsigned long nsLoadFlags;
[scriptable, builtinclass, uuid(41b1cf17-b37b-4a62-9df8-5f67cfecab3f)]
[scriptable, builtinclass, uuid(63adb599-6dc9-4746-972e-c22e9018020b)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@ -824,6 +824,12 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
void setIsBrowserInsideApp(in unsigned long containingAppId);
/**
* Indicate that this docshell corresponds to a signed package with
* the given packageId.
*/
void setIsSignedPackage(in AString packageId);
/**
* Returns the id of the app associated with this docshell. If this docshell
* is an <iframe mozbrowser> inside an <iframe mozapp>, we return the app's

View File

@ -49,6 +49,8 @@ XPCOMUtils.defineLazyGetter(this, "powerManagerService", function() {
*/
this.AlarmService = {
lastChromeId: 0,
init: function init() {
debug("init()");
@ -205,6 +207,12 @@ this.AlarmService = {
};
}
// Is this a chrome alarm?
if (aId < 0) {
aRemoveSuccessCb();
return;
}
this._db.remove(aId, aManifestURL, aRemoveSuccessCb,
function removeErrorCb(aErrorMsg) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -241,11 +249,19 @@ this.AlarmService = {
_notifyAlarmObserver: function _notifyAlarmObserver(aAlarm) {
debug("_notifyAlarmObserver()");
if (aAlarm.manifestURL) {
this._fireSystemMessage(aAlarm);
} else if (typeof aAlarm.alarmFiredCb === "function") {
aAlarm.alarmFiredCb(this._publicAlarm(aAlarm));
}
let wakeLock = powerManagerService.newWakeLock("cpu");
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(() => {
debug("_notifyAlarmObserver - timeout()");
if (aAlarm.manifestURL) {
this._fireSystemMessage(aAlarm);
} else if (typeof aAlarm.alarmFiredCb === "function") {
aAlarm.alarmFiredCb(this._publicAlarm(aAlarm));
}
wakeLock.unlock();
}, 0, Ci.nsITimer.TYPE_ONE_SHOT);
},
_onAlarmFired: function _onAlarmFired() {
@ -265,8 +281,12 @@ this.AlarmService = {
}
this._removeAlarmFromDb(this._currentAlarm.id, null);
this._notifyAlarmObserver(this._currentAlarm);
// We need to clear the current alarm before notifying because chrome
// alarms may add a new alarm during their callback, and we do not want
// to clobber it.
let firingAlarm = this._currentAlarm;
this._currentAlarm = null;
this._notifyAlarmObserver(firingAlarm);
}
// Reset the next alarm from the queue.
@ -309,15 +329,25 @@ this.AlarmService = {
debug("Callback after getting alarms from database: " +
JSON.stringify(aAlarms));
// Clear any alarms set or queued in the cache.
// Clear any alarms set or queued in the cache if coming from db.
let alarmQueue = this._alarmQueue;
alarmQueue.length = 0;
this._currentAlarm = null;
if (this._currentAlarm) {
alarmQueue.unshift(this._currentAlarm);
this._currentAlarm = null;
}
for (let i = 0; i < alarmQueue.length;) {
if (alarmQueue[i]['id'] < 0) {
++i;
continue;
}
alarmQueue.splice(i, 1);
}
// Only restore the alarm that's not yet expired; otherwise, remove it
// from the database and notify the observer.
aAlarms.forEach(function addAlarm(aAlarm) {
if (this._getAlarmTime(aAlarm) > Date.now()) {
if ("manifestURL" in aAlarm && aAlarm.manifestURL &&
this._getAlarmTime(aAlarm) > Date.now()) {
alarmQueue.push(aAlarm);
} else {
this._removeAlarmFromDb(aAlarm.id, null);
@ -416,55 +446,65 @@ this.AlarmService = {
aNewAlarm['timezoneOffset'] = this._currentTimezoneOffset;
this._db.add(aNewAlarm,
function addSuccessCb(aNewId) {
debug("Callback after adding alarm in database.");
if ("manifestURL" in aNewAlarm) {
this._db.add(aNewAlarm,
function addSuccessCb(aNewId) {
debug("Callback after adding alarm in database.");
this.processNewAlarm(aNewAlarm, aNewId, aAlarmFiredCb, aSuccessCb);
}.bind(this),
function addErrorCb(aErrorMsg) {
aErrorCb(aErrorMsg);
}.bind(this));
} else {
// alarms without manifests are managed by chrome code. For them we use
// negative IDs.
this.processNewAlarm(aNewAlarm, --this.lastChromeId, aAlarmFiredCb,
aSuccessCb);
}
},
aNewAlarm['id'] = aNewId;
processNewAlarm: function(aNewAlarm, aNewId, aAlarmFiredCb, aSuccessCb) {
aNewAlarm['id'] = aNewId;
// Now that the alarm has been added to the database, we can tack on
// the non-serializable callback to the in-memory object.
aNewAlarm['alarmFiredCb'] = aAlarmFiredCb;
// Now that the alarm has been added to the database, we can tack on
// the non-serializable callback to the in-memory object.
aNewAlarm['alarmFiredCb'] = aAlarmFiredCb;
// If the new alarm already expired at this moment, we directly
// notify this alarm
let aNewAlarmTime = this._getAlarmTime(aNewAlarm);
if (aNewAlarmTime < Date.now()) {
aSuccessCb(aNewId);
this._removeAlarmFromDb(aNewAlarm.id, null);
this._notifyAlarmObserver(aNewAlarm);
return;
}
// If the new alarm already expired at this moment, we directly
// notify this alarm
let newAlarmTime = this._getAlarmTime(aNewAlarm);
if (newAlarmTime < Date.now()) {
aSuccessCb(aNewId);
this._removeAlarmFromDb(aNewAlarm.id, null);
this._notifyAlarmObserver(aNewAlarm);
return;
}
// If there is no alarm being set in system, set the new alarm.
if (this._currentAlarm == null) {
this._currentAlarm = aNewAlarm;
this._debugCurrentAlarm();
aSuccessCb(aNewId);
return;
}
// If there is no alarm being set in system, set the new alarm.
if (this._currentAlarm == null) {
this._currentAlarm = aNewAlarm;
this._debugCurrentAlarm();
aSuccessCb(aNewId);
return;
}
// If the new alarm is earlier than the current alarm, swap them and
// push the previous alarm back to the queue.
let alarmQueue = this._alarmQueue;
let currentAlarmTime = this._getAlarmTime(this._currentAlarm);
if (aNewAlarmTime < currentAlarmTime) {
alarmQueue.unshift(this._currentAlarm);
this._currentAlarm = aNewAlarm;
this._debugCurrentAlarm();
aSuccessCb(aNewId);
return;
}
// If the new alarm is earlier than the current alarm, swap them and
// push the previous alarm back to the queue.
let alarmQueue = this._alarmQueue;
let currentAlarmTime = this._getAlarmTime(this._currentAlarm);
if (newAlarmTime < currentAlarmTime) {
alarmQueue.unshift(this._currentAlarm);
this._currentAlarm = aNewAlarm;
this._debugCurrentAlarm();
aSuccessCb(aNewId);
return;
}
// Push the new alarm in the queue.
alarmQueue.push(aNewAlarm);
alarmQueue.sort(this._sortAlarmByTimeStamps.bind(this));
this._debugCurrentAlarm();
aSuccessCb(aNewId);
}.bind(this),
function addErrorCb(aErrorMsg) {
aErrorCb(aErrorMsg);
}.bind(this));
// Push the new alarm in the queue.
alarmQueue.push(aNewAlarm);
alarmQueue.sort(this._sortAlarmByTimeStamps.bind(this));
this._debugCurrentAlarm();
aSuccessCb(aNewId);
},
/*

View File

@ -601,6 +601,10 @@ Animation::DoCancel()
mStartTime.SetNull();
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
if (mTimeline) {
mTimeline->RemoveAnimation(this);
}
}
void

View File

@ -10,6 +10,7 @@
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Attributes.h"
#include "mozilla/LinkedList.h"
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
#include "mozilla/dom/AnimationBinding.h" // for AnimationPlayState
#include "mozilla/dom/AnimationTimeline.h" // for AnimationTimeline
@ -48,6 +49,7 @@ class CSSTransition;
class Animation
: public DOMEventTargetHelper
, public LinkedListElement<Animation>
{
protected:
virtual ~Animation() {}

View File

@ -6,12 +6,25 @@
#include "AnimationTimeline.h"
#include "mozilla/AnimationComparator.h"
#include "mozilla/dom/Animation.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationTimeline, mWindow,
mAnimationOrder)
NS_IMPL_CYCLE_COLLECTION_CLASS(AnimationTimeline)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AnimationTimeline)
tmp->mAnimationOrder.clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow, mAnimations)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AnimationTimeline)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow, mAnimations)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AnimationTimeline)
NS_IMPL_CYCLE_COLLECTING_ADDREF(AnimationTimeline)
NS_IMPL_CYCLE_COLLECTING_RELEASE(AnimationTimeline)
@ -32,9 +45,10 @@ AnimationTimeline::GetAnimations(AnimationSequence& aAnimations)
}
}
aAnimations.SetCapacity(mAnimationOrder.Length());
aAnimations.SetCapacity(mAnimations.Count());
for (Animation* animation : mAnimationOrder) {
for (Animation* animation = mAnimationOrder.getFirst(); animation;
animation = animation->getNext()) {
// Skip animations which are no longer relevant or which have been
// associated with another timeline. These animations will be removed
@ -69,8 +83,22 @@ AnimationTimeline::NotifyAnimationUpdated(Animation& aAnimation)
return;
}
if (aAnimation.GetTimeline() && aAnimation.GetTimeline() != this) {
aAnimation.GetTimeline()->RemoveAnimation(&aAnimation);
}
mAnimations.PutEntry(&aAnimation);
mAnimationOrder.AppendElement(&aAnimation);
mAnimationOrder.insertBack(&aAnimation);
}
void
AnimationTimeline::RemoveAnimation(Animation* aAnimation)
{
MOZ_ASSERT(!aAnimation->GetTimeline() || aAnimation->GetTimeline() == this);
if (aAnimation->isInList()) {
aAnimation->remove();
}
mAnimations.RemoveEntry(aAnimation);
}
} // namespace dom

View File

@ -40,7 +40,10 @@ public:
}
protected:
virtual ~AnimationTimeline() { }
virtual ~AnimationTimeline()
{
mAnimationOrder.clear();
}
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -91,6 +94,8 @@ public:
*/
virtual void NotifyAnimationUpdated(Animation& aAnimation);
void RemoveAnimation(Animation* aAnimation);
protected:
nsCOMPtr<nsIGlobalObject> mWindow;
@ -99,13 +104,11 @@ protected:
// We store them in (a) a hashset for quick lookup, and (b) an array
// to maintain a fixed sampling order.
//
// The array keeps a strong reference to each animation in order
// to save some addref/release traffic and because we never dereference
// the pointers in the hashset.
typedef nsTHashtable<nsPtrHashKey<dom::Animation>> AnimationSet;
typedef nsTArray<RefPtr<dom::Animation>> AnimationArray;
AnimationSet mAnimations;
AnimationArray mAnimationOrder;
// The hashset keeps a strong reference to each animation since
// dealing with addref/release with LinkedList is difficult.
typedef nsTHashtable<nsRefPtrHashKey<dom::Animation>> AnimationSet;
AnimationSet mAnimations;
LinkedList<dom::Animation> mAnimationOrder;
};
} // namespace dom

View File

@ -112,14 +112,18 @@ DocumentTimeline::WillRefresh(mozilla::TimeStamp aTime)
MOZ_ASSERT(mIsObservingRefreshDriver);
bool needsTicks = false;
AnimationArray animationsToKeep(mAnimationOrder.Length());
nsTArray<Animation*> animationsToRemove(mAnimations.Count());
nsAutoAnimationMutationBatch mb(mDocument);
for (Animation* animation : mAnimationOrder) {
for (Animation* animation = mAnimationOrder.getFirst(); animation;
animation = animation->getNext()) {
// Skip any animations that are longer need associated with this timeline.
if (animation->GetTimeline() != this) {
mAnimations.RemoveEntry(animation);
// If animation has some other timeline, it better not be also in the
// animation list of this timeline object!
MOZ_ASSERT(!animation->GetTimeline());
animationsToRemove.AppendElement(animation);
continue;
}
@ -129,14 +133,14 @@ DocumentTimeline::WillRefresh(mozilla::TimeStamp aTime)
// order to dispatch events.
animation->Tick();
if (animation->IsRelevant() || animation->NeedsTicks()) {
animationsToKeep.AppendElement(animation);
} else {
mAnimations.RemoveEntry(animation);
if (!animation->IsRelevant() && !animation->NeedsTicks()) {
animationsToRemove.AppendElement(animation);
}
}
mAnimationOrder.SwapElements(animationsToKeep);
for (Animation* animation : animationsToRemove) {
RemoveAnimation(animation);
}
if (!needsTicks) {
// If another refresh driver observer destroys the nsPresContext,
@ -155,7 +159,7 @@ DocumentTimeline::NotifyRefreshDriverCreated(nsRefreshDriver* aDriver)
"Timeline should not be observing the refresh driver before"
" it is created");
if (!mAnimationOrder.IsEmpty()) {
if (!mAnimationOrder.isEmpty()) {
aDriver->AddRefreshObserver(this, Flush_Style);
mIsObservingRefreshDriver = true;
}

View File

@ -10,8 +10,15 @@ function runTest()
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [ ["dom.archivereader.enabled", true] ]}, function() {
testGenerator = testSteps();
return testGenerator.next();
SpecialPowers.createFiles(filesToCreate(),
function (files) {
testGenerator = testSteps(files);
return testGenerator.next();
},
function (msg) {
ok(false, "File creation error: " + msg);
finishTest();
});
});
}

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s
support-files =
helpers.js

View File

@ -10,57 +10,7 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function createZipFileWithData(fileData) {
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", Ci.nsIFile);
testFile.append("fileArchiveReader.zip");
var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).value = testFile.path;
return fileList.files[0];
}
function createTextFileWithData(fileData) {
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", Ci.nsIFile);
testFile.append("fileArchiveReader.txt");
var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).value = testFile.path;
return fileList.files[0];
}
handleFinished = 0;
function markTestDone() {
++handleFinished;
if (isFinished()) {
finishTest();
}
}
function isFinished() {
return handleFinished == 6;
}
function testSteps()
{
function filesToCreate() {
var binaryString = '504B03040A00000000002E6BF14000000000000000000000000005001C00746573742F555409000337CA055039CA055075780B' +
'000104E803000004E8030000504B03041400000008002D6BF1401780E15015000000580200000A001C00746573742F612E7478' +
'74555409000336CA05503ACA055075780B000104E803000004E8030000CB48CDC9C95728CF2FCA49E1CA18658FB2A9C4060050' +
@ -78,8 +28,25 @@
binaryData += String.fromCharCode(parseInt(hex,16));
}
var binaryFile = createZipFileWithData(binaryData);
var textFile = createTextFileWithData("Hello World");
return [ {name: "fileArchiveReader.zip", data: binaryData},
{name: "fileArchiveReader.txt", data: "Hello World"}];
}
handleFinished = 0;
function markTestDone() {
++handleFinished;
if (isFinished()) {
finishTest();
}
}
function isFinished() {
return handleFinished == 6;
}
function testSteps(files)
{
var binaryFile = files[0];
var textFile = files[1];
var status;
@ -254,7 +221,6 @@
<body onload="runTest();">
<p id="display">
<input id="fileList" type="file"></input>
</p>
</body>

View File

@ -10,35 +10,17 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function createNonUnicodeData() {
const Cc = SpecialPowers.Cc;
const Ci = SpecialPowers.Ci;
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", Ci.nsIFile);
testFile.append("fileArchiveReader_nonUnicode.zip");
var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
function filesToCreate() {
var binaryData = "";
for (var i = 0, len = binaryString.length / 2; i < len; ++i) {
var hex = binaryString[i * 2] + binaryString[i * 2 + 1];
binaryData += String.fromCharCode(parseInt(hex,16));
}
outStream.write(binaryData, binaryData.length);
outStream.close();
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).value = testFile.path;
return fileList.files[0];
return [ {name: "fileArchiveReader_nonUnicode.zip", data: binaryData} ];
}
function test1()
function test1(binaryFile)
{
var binaryFile = createNonUnicodeData();
var r = new ArchiveReader(binaryFile, { encoding: "ISO-8859-1" });
isnot(r, null, "ArchiveReader cannot be null");
@ -51,14 +33,12 @@
is(this.result.length, 1, "ArchiveReader.getFilenames(): the array contains 1 item");
ok(this.reader, r, "ArchiveRequest.reader should be == ArchiveReader");
dump('Content: ' + this.result[0] + '\n');
test2();
test2(binaryFile);
}
}
function test2()
function test2(binaryFile)
{
var binaryFile = createNonUnicodeData();
try {
new ArchiveReader(binaryFile, { encoding: "random stuff" });
ok(false, "Should have thrown for bogus encoding label.");
@ -68,9 +48,9 @@
finishTest();
}
function testSteps()
function testSteps(files)
{
test1();
test1(files[0]);
yield undefined;
}
@ -82,7 +62,6 @@
<body onload="runTest();">
<p id="display">
<input id="fileList" type="file"></input>
</p>
<script type="text/javascript;version=1.7">
var binaryString = '' +

View File

@ -10,34 +10,18 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function createZipInZipData() {
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", Ci.nsIFile);
testFile.append("fileArchiveReader_42.zip");
var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
function filesToCreate() {
var binaryData = "";
for (var i = 0, len = binaryString.length / 2; i < len; ++i) {
var hex = binaryString[i * 2] + binaryString[i * 2 + 1];
binaryData += String.fromCharCode(parseInt(hex,16));
}
outStream.write(binaryData, binaryData.length);
outStream.close();
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).value = testFile.path;
return fileList.files[0];
return [ {name: "fileArchiveReader_42.zip", data: binaryData} ];
}
function testSteps()
function testSteps(files)
{
var binaryFile = createZipInZipData();
var binaryFile = files[0];
// The input is 4 nested zip archives:
doLoop(binaryFile, 4);
@ -96,7 +80,6 @@
<body onload="runTest();">
<p id="display">
<input id="fileList" type="file"></input>
</p>
<script type="text/javascript;version=1.7">
var binaryString = '' +

View File

@ -183,7 +183,10 @@ NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying()
("AudioChannelAgent, NotifyStoppedPlaying, this = %p\n", this));
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
service->UnregisterAudioChannelAgent(this, mNotifyPlayback);
if (service) {
service->UnregisterAudioChannelAgent(this, mNotifyPlayback);
}
mIsRegToService = false;
return NS_OK;
}
@ -210,7 +213,9 @@ AudioChannelAgent::WindowVolumeChanged()
bool muted = false;
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
service->GetState(mWindow, mAudioChannelType, &volume, &muted);
if (service) {
service->GetState(mWindow, mAudioChannelType, &volume, &muted);
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, WindowVolumeChanged, this = %p, mute = %d, "

View File

@ -40,6 +40,7 @@ namespace {
// If true, any new AudioChannelAgent will be muted when created.
bool sAudioChannelMutedByDefault = false;
bool sXPCOMShuttingDown = false;
class NotifyChannelActiveRunnable final : public nsRunnable
{
@ -178,6 +179,10 @@ AudioChannelService::CreateServiceIfNeeded()
/* static */ already_AddRefed<AudioChannelService>
AudioChannelService::GetOrCreate()
{
if (sXPCOMShuttingDown) {
return nullptr;
}
CreateServiceIfNeeded();
RefPtr<AudioChannelService> service = gAudioChannelService.get();
return service.forget();
@ -193,7 +198,7 @@ AudioChannelService::GetAudioChannelLog()
return gAudioChannelLog;
}
void
/* static */ void
AudioChannelService::Shutdown()
{
if (gAudioChannelService) {
@ -212,6 +217,12 @@ AudioChannelService::Shutdown()
}
}
gAudioChannelService->mWindows.Clear();
gAudioChannelService->mPlayingChildren.Clear();
#ifdef MOZ_WIDGET_GONK
gAudioChannelService->mSpeakerManager.Clear();
#endif
gAudioChannelService = nullptr;
}
}
@ -483,7 +494,7 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
if (!strcmp(aTopic, "xpcom-shutdown")) {
mWindows.Clear();
sXPCOMShuttingDown = true;
Shutdown();
} else if (!strcmp(aTopic, "outer-window-destroyed")) {
nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);

View File

@ -11,6 +11,7 @@
#include "nsIDocument.h"
#include "nsIDOMHTMLCollection.h"
#include "nsStyledElement.h"
#include "HTMLCanvasElement.h"
namespace mozilla {
namespace dom {
@ -112,6 +113,30 @@ AnonymousContent::RemoveAttributeForElement(const nsAString& aElementId,
element->RemoveAttribute(aName, aRv);
}
already_AddRefed<nsISupports>
AnonymousContent::GetCanvasContext(const nsAString& aElementId,
const nsAString& aContextId,
ErrorResult& aRv)
{
Element* element = GetElementById(aElementId);
if (!element) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr;
}
if (!element->IsHTMLElement(nsGkAtoms::canvas)) {
return nullptr;
}
nsCOMPtr<nsISupports> context;
HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(element);
canvas->GetContext(aContextId, getter_AddRefs(context));
return context.forget();
}
Element*
AnonymousContent::GetElementById(const nsAString& aElementId)
{

View File

@ -52,6 +52,10 @@ public:
const nsAString& aName,
ErrorResult& aRv);
already_AddRefed<nsISupports> GetCanvasContext(const nsAString& aElementId,
const nsAString& aContextId,
ErrorResult& aRv);
private:
~AnonymousContent();
Element* GetElementById(const nsAString& aElementId);

View File

@ -1760,6 +1760,23 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
}
SetParentIsContent(false);
}
// Ensure that CSS transitions don't continue on an element at a
// different place in the tree (even if reinserted before next
// animation refresh).
// We need to delete the properties while we're still in document
// (if we were in document).
// FIXME (Bug 522599): Need a test for this.
//XXXsmaug this looks slow.
if (HasFlag(NODE_HAS_PROPERTIES)) {
DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
DeleteProperty(nsGkAtoms::transitionsOfAfterProperty);
DeleteProperty(nsGkAtoms::transitionsProperty);
DeleteProperty(nsGkAtoms::animationsOfBeforeProperty);
DeleteProperty(nsGkAtoms::animationsOfAfterProperty);
DeleteProperty(nsGkAtoms::animationsProperty);
}
ClearInDocument();
// Editable descendant count only counts descendants that
@ -1794,19 +1811,6 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
}
}
// Ensure that CSS transitions don't continue on an element at a
// different place in the tree (even if reinserted before next
// animation refresh).
// FIXME (Bug 522599): Need a test for this.
if (HasFlag(NODE_HAS_PROPERTIES)) {
DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
DeleteProperty(nsGkAtoms::transitionsOfAfterProperty);
DeleteProperty(nsGkAtoms::transitionsProperty);
DeleteProperty(nsGkAtoms::animationsOfBeforeProperty);
DeleteProperty(nsGkAtoms::animationsOfAfterProperty);
DeleteProperty(nsGkAtoms::animationsProperty);
}
// Unset this since that's what the old code effectively did.
UnsetFlags(NODE_FORCE_XBL_BINDINGS);
bool clearBindingParent = true;

View File

@ -1051,7 +1051,7 @@ EventSource::DispatchCurrentMessageEvent()
message->mLastEventID.Assign(mLastEventID);
}
int32_t sizeBefore = mMessagesToDispatch.GetSize();
size_t sizeBefore = mMessagesToDispatch.GetSize();
mMessagesToDispatch.Push(message.forget());
NS_ENSURE_TRUE(mMessagesToDispatch.GetSize() == sizeBefore + 1,
NS_ERROR_OUT_OF_MEMORY);

View File

@ -2592,37 +2592,6 @@ Navigator::HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal)
}
#endif
/* static */
bool
Navigator::HasTVSupport(JSContext* aCx, JSObject* aGlobal)
{
JS::Rooted<JSObject*> global(aCx, aGlobal);
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(global);
if (!win) {
return false;
}
// Just for testing, we can enable TV for any kind of app.
if (Preferences::GetBool("dom.testing.tv_enabled_for_hosted_apps", false)) {
return true;
}
nsIDocument* doc = win->GetExtantDoc();
if (!doc || !doc->NodePrincipal()) {
return false;
}
nsIPrincipal* principal = doc->NodePrincipal();
uint16_t status;
if (NS_FAILED(principal->GetAppStatus(&status))) {
return false;
}
// Only support TV Manager API for certified apps for now.
return status == nsIPrincipal::APP_STATUS_CERTIFIED;
}
/* static */
bool
Navigator::HasPresentationSupport(JSContext* aCx, JSObject* aGlobal)

View File

@ -333,8 +333,6 @@ public:
static bool HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal);
#endif
static bool HasTVSupport(JSContext* aCx, JSObject* aGlobal);
static bool HasPresentationSupport(JSContext* aCx, JSObject* aGlobal);
static bool IsE10sEnabled(JSContext* aCx, JSObject* aGlobal);

View File

@ -253,8 +253,9 @@ namespace {
void SerializeString(const nsCString& aInput, nsAString& aValue)
{
const unsigned char* p = (const unsigned char*) aInput.get();
const unsigned char* end = p + aInput.Length();
while (p && *p) {
while (p != end) {
// ' ' to '+'
if (*p == 0x20) {
aValue.Append(0x2B);
@ -314,7 +315,7 @@ URLSearchParams::URLSearchParams(nsISupports* aParent,
const URLSearchParams& aOther)
: mParams(new URLParams(*aOther.mParams.get()))
, mParent(aParent)
, mObserver(aOther.mObserver)
, mObserver(nullptr)
{
}

View File

@ -3703,7 +3703,9 @@ void
nsPIDOMWindow::RefreshMediaElements()
{
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
service->RefreshAgentsVolume(GetOuterWindow());
if (service) {
service->RefreshAgentsVolume(GetOuterWindow());
}
}
bool
@ -3721,7 +3723,9 @@ nsPIDOMWindow::SetAudioCapture(bool aCapture)
mAudioCaptured = aCapture;
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
service->RefreshAgentsCapture(GetOuterWindow(), mWindowID);
if (service) {
service->RefreshAgentsCapture(GetOuterWindow(), mWindowID);
}
return NS_OK;
}

View File

@ -2809,11 +2809,15 @@ protected:
// True iff we've ever fired a DOMTitleChanged event for this document
bool mHaveFiredTitleChange : 1;
// True iff IsShowing() should be returning true
// State for IsShowing(). mIsShowing starts off false. It becomes true when
// OnPageShow happens and becomes false when OnPageHide happens. So it's false
// before the initial load completes and when we're in bfcache or unloaded,
// true otherwise.
bool mIsShowing : 1;
// True iff the document "page" is not hidden (i.e. currently in the
// bfcache)
// State for IsVisible(). mVisible starts off true. It becomes false when
// OnPageHide happens, and becomes true again when OnPageShow happens. So
// it's false only when we're in bfcache or unloaded.
bool mVisible : 1;
// True if our content viewer has been removed from the docshell

View File

@ -259,6 +259,8 @@ support-files =
[test_anonymousContent_api.html]
[test_anonymousContent_append_after_reflow.html]
[test_anonymousContent_canvas.html]
skip-if = buildapp == 'b2g' # Requires webgl support
[test_anonymousContent_insert.html]
[test_anonymousContent_manipulate_content.html]
[test_anonymousContent_style_csp.html]
@ -372,7 +374,6 @@ skip-if = toolkit != 'gonk'
[test_XHRDocURI.html]
[test_XHRResponseURL.html]
[test_XHRSendData.html]
skip-if = buildapp == 'b2g' || e10s # b2g(seems to stall) b2g-debug(seems to stall) b2g-desktop(seems to stall) e10s(Bug 1220304 - Creates a file)
[test_XHR_anon.html]
[test_XHR_header.html]
[test_XHR_onuploadprogress.html]
@ -794,7 +795,7 @@ skip-if = toolkit == 'android' || e10s #RANDOM
[test_w3element_traversal.xhtml]
[test_w3element_traversal_svg.html]
[test_websocket.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # TC: Bug 1144079 - Re-enable Mulet mochitests and reftests taskcluster-specific disables.
skip-if = buildapp == 'b2g' || toolkit == 'android' # TC: Bug 1144079 - Re-enable Mulet mochitests and reftests taskcluster-specific disables.
[test_websocket_basic.html]
skip-if = buildapp == 'b2g' || toolkit == 'android'
[test_websocket_hello.html]

View File

@ -5,27 +5,48 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=464848
-->
<head>
<title>XMLHttpRequest send data and headers</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="gen.next();">
<body onload="createFiles();">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=464848">Mozilla Bug 464848</a>
<p id="display">
<input id="fileList" type="file"></input>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();
var testData = "blahblahblahblahblahblahblaaaaaaaah. blah.";
var extensions = [".txt",".png",".jpg",".gif",".xml", "noext"];
var fileTypes = ["text/plain", "image/png", "image/jpeg", "image/gif", "text/xml", null];
var gen = runTests();
var testDOMFiles;
function createFiles() {
var filesToCreate = new Array();
extensions.forEach(function (extension) {
filesToCreate.push({name: "testfile" + extension, data: testData});
});
SpecialPowers.createFiles(filesToCreate,
function (files) {
testDOMFiles = files;
gen.next();
},
function (msg) {
testDOMFiles = new Array;
ok(false, "File creation error: " + msg);
gen.next();
});
};
function continueTest() { gen.next(); }
function runTests() {
xhr = new XMLHttpRequest();
xhr.open("GET", "file_XHRSendData_doc.xml", false);
xhr.send();
@ -38,12 +59,6 @@ testDoc2.appendChild(testDoc2.createElement("res"));
testDoc2.documentElement.appendChild(testDoc2.createTextNode("text"));
is(testDoc2.inputEncoding, "UTF-8", "wrong encoding");
var testData = "blahblahblahblahblahblahblaaaaaaaah. blah.";
var extensions = [".txt",".png",".jpg",".gif",".xml", "noext"];
var fileTypes = ["text/plain", "image/png", "image/jpeg", "image/gif", "text/xml", null];
var testFiles = new Array;
var testDOMFiles = new Array;
// arraybuffer test objects
var shortArray = new ArrayBuffer(1);
var shortInt8View = new Uint8Array(shortArray);
@ -64,28 +79,6 @@ var longInt16View2 = new Uint16Array(longArray, 256, 64)
var longInt8View1 = new Int8Array(longArraySlice)
var longInt8View2 = new Int8Array(longArray, 256, 128)
extensions.forEach(
function (extension) {
var testFile = createFileWithDataExt(testData, extension);
testFiles.push(testFile);
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).value = testFile.path;
testDOMFiles.push(fileList.files[0]);
}
);
function createFileWithDataExt(fileData, extension) {
var testFile = SpecialPowers.Services.dirsvc.get("ProfD", SpecialPowers.Ci.nsIFile);
testFile.append("testfile" + extension);
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].createInstance(SpecialPowers.Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, 0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
return testFile;
}
tests = [{ body: null,
resBody: "",
},
@ -253,19 +246,7 @@ try {
"Wrong page for redirect");
}
}
}
finally {
cleanUpData();
}
function cleanUpData() {
testFiles.forEach(
function (testFile) {
try {
testFile.remove(false);
} catch (e) {}
}
);
} catch (e) {
}
function is_identical_arraybuffer(ab1, ab2) {

View File

@ -45,7 +45,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1020244
let members = ["getTextContentForElement", "setTextContentForElement",
"getAttributeForElement", "setAttributeForElement",
"removeAttributeForElement"];
"removeAttributeForElement", "getCanvasContext"];
for (let member of members) {
ok(member in anonymousContent, "AnonymousContent object defines " + member);
}

View File

@ -0,0 +1,57 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1212477
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1212477 - Needs a way to access to &lt;canvas&gt;'s context (2d, webgl) from Anonymous Content API</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1212477">Mozilla Bug 1212477</a>
<div>
<div id="id" class="test">text content</div>
<canvas id="canvas2d"></canvas>
<canvas id="canvas-webgl"></canvas>
<canvas id="canvas-foo"></canvas>
</div>
<script type="application/javascript;version=1.8">
let chromeDocument = SpecialPowers.wrap(document);
let testElement = document.querySelector("div");
let anonymousContent = chromeDocument.insertAnonymousContent(testElement);
is(anonymousContent.getCanvasContext("id", "2d"), null,
"Context is null for non-canvas elements");
let context2d = anonymousContent.getCanvasContext("canvas2d", "2d");
is(context2d.toString(), "[object CanvasRenderingContext2D]",
"2D Context is returned properly");
is(context2d.canvas, null,
"context's canvas property is null in anonymous content");
is (anonymousContent.getCanvasContext("canvas-foo", "foo"), null,
"Context is null for unknown context type");
SimpleTest.doesThrow(
() => anonymousContent.getCanvasContext("foo", "2d"),
"NS_ERROR_NOT_AVAILABLE",
"Get a context using unexisting id should throw"
);
let webgl = anonymousContent.getCanvasContext("canvas-webgl", "webgl");
is(webgl.toString(), "[object WebGLRenderingContext]",
"WebGL Context is returned properly");
is(webgl.canvas, null,
"WebGL context's canvas property is null in anonymous content");
chromeDocument.removeAnonymousContent(anonymousContent);
</script>
</body>
</html>

View File

@ -289,6 +289,31 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=887836
runTest();
}
function testZeroHandling() {
var u = new URLSearchParams;
u.set("a", "b\0c");
u.set("d\0e", "f");
u.set("g\0h", "i\0j");
is(u.toString(), "a=b%00c&d%00e=f&g%00h=i%00j",
"Should encode U+0000 as %00");
runTest();
}
function testCopyConstructor() {
var url = new URL("http://example.com/");
var p = url.searchParams;
var q = new URLSearchParams(p);
q.set("a", "b");
is(url.href, "http://example.com/",
"Messing with copy of URLSearchParams should not affect URL");
p.set("c", "d");
is(url.href, "http://example.com/?c=d",
"Messing with URLSearchParams should affect URL");
runTest();
}
var tests = [
testSimpleURLSearchParams,
testCopyURLSearchParams,
@ -301,7 +326,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=887836
testDelete,
testGetNULL,
testSet,
testIterable
testIterable,
testZeroHandling,
testCopyConstructor,
];
function runTest() {

View File

@ -9,7 +9,6 @@
<body onload="testWebSocket()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=472529">Mozilla Bug </a>
<p id="display">
<input id="fileList" type="file"></input>
</p>
<div id="content">
</div>
@ -66,8 +65,8 @@
* 41. HSTS
* 42. non-char utf-8 sequences
* 43. Test setting binaryType attribute
* 44. Test sending/receving binary ArrayBuffer
* 45. Test sending/receving binary Blob
* 44. Test sending/receving binary ArrayBuffer
* 45. Test sending/receving binary Blob
* 46. Test that we don't dispatch incoming msgs once in CLOSING state
* 47. Make sure onerror/onclose aren't called during close()
*/
@ -77,13 +76,13 @@ var last_test = 47;
// Set this to >1 if you want to run the suite multiple times to probe for
// random orange failures.
// random orange failures.
// - Do NOT check into mozilla-central with a value != 1.
// - Too large a count will wind up causing tryserver to timeout the test (which
// is ok, but means all testruns will be orange). If I set first_test to >22
// (i.e don't run any of the tests that require waiting) I can get ~250-300
// iterations of the remaining tests w/o a timeout.
var testsuite_iterations = 1;
var testsuite_iterations = 1;
var current_test = first_test;
@ -113,7 +112,7 @@ function shouldNotReceiveCloseEvent(e)
extendedErrorInfo += (i + ": " + e[i] + "\n");
}
}
// FIXME: see bug 578276. This should be a test failure, but it's too flaky on the tbox.
ok(true, "onclose shouldn't be called on test " + ws._testNumber + "!" + extendedErrorInfo);
}
@ -191,7 +190,7 @@ function doTest(number)
}
if (testsuite_iteration > 1) {
$("feedback").innerHTML = "test suite iteration #" + testsuite_iteration + " of " + testsuite_iterations +
$("feedback").innerHTML = "test suite iteration #" + testsuite_iteration + " of " + testsuite_iterations +
": executing test: " + number + " of " + last_test + " tests.";
} else {
$("feedback").innerHTML = "executing test: " + number + " of " + last_test + " tests.";
@ -390,7 +389,7 @@ function test8()
{
shouldCloseCleanly(e);
// We called close() with no close code: so pywebsocket will also send no
// close code, which translates to code 1005
// close code, which translates to code 1005
ok(e.code == 1005, "test-8 close code has wrong value:" + e.code);
ok(e.reason == "", "test-8 close reason has wrong value:" + e.reason);
doTest(9);
@ -419,7 +418,7 @@ function test9()
};
ws.close();
// the server injects a delay, so proceed with this in the background
doTest(10);
}
@ -520,7 +519,7 @@ function test12()
function test13()
{
// previous versions of this test counted the number of protocol errors returned, but the
// previous versions of this test counted the number of protocol errors returned, but the
// protocol stack typically closes down after reporting a protocol level error - trying
// to resync is too dangerous
@ -1110,7 +1109,7 @@ function test37()
{
ok(e.code != 3101, "test 37c custom server code not present");
ok(e.reason == "", "test 37c custom server reason not present");
doTest(38);
doTest(38);
}
}
}
@ -1152,7 +1151,7 @@ function test39()
ws.onclose = function(e)
{
ok(true, "test 39 close");
ok(status_test39 == "opened", "test 39 did open");
ok(status_test39 == "opened", "test 39 did open");
doTest(40);
};
}
@ -1176,7 +1175,7 @@ function test40()
ws.onclose = function(e)
{
ok(true, "test 40 close");
ok(status_test40 == "started", "test 40 did not open");
ok(status_test40 == "started", "test 40 did not open");
doTest(41);
};
}
@ -1211,7 +1210,7 @@ function test41()
// try ws:// again, it should be done over wss:// now due to hsts
var wsc = CreateTestWS("ws://example.com/tests/dom/base/test/file_websocket", "test-41c");
wsc.onopen = function(e)
{
ok(true, "test 41c open");
@ -1328,35 +1327,21 @@ function test44()
{
ok(ws.readyState == 3, "onclose bad readyState in test-44!");
shouldCloseCleanly(e);
doTest(45);
SpecialPowers.createFiles([{name: "testBlobFile", data: "flob"}], function (files) {
blobFile = files[0];
doTest(45);
},
function (msg) {
testFailed("Failed to create file for test45: " + msg);
doTest(46);
});
}
}
function createDOMFile(fileName, fileData)
{
// create File in profile dir
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
.getService(SpecialPowers.Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
testFile.append(fileName);
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"]
.createInstance(SpecialPowers.Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, 0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
// Set filename into DOM <input> field, as if selected by user
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).value = testFile.path;
// return JS File object, aka Blob
return fileList.files[0];
}
var blobFile;
function test45()
{
var blobFile = createDOMFile("testBlobFile", "flob");
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-45");
ok(ws.readyState == 0, "bad readyState in test-45!");
@ -1387,7 +1372,7 @@ function test45()
var reader = new FileReader();
reader.onload = function(event)
{
ok(reader.result == "flob", "response should be 'flob': got '"
ok(reader.result == "flob", "response should be 'flob': got '"
+ reader.result + "'");
};
reader.onerror = function(event)
@ -1433,7 +1418,7 @@ function test47()
ws.onerror = function (e)
{
ok(ws.readyState == 3, "test-47: readyState should be CLOSED(3) in onerror: got "
ok(ws.readyState == 3, "test-47: readyState should be CLOSED(3) in onerror: got "
+ ws.readyState);
ok(!ws._withinClose, "onerror() called during close()!");
hasError = true;
@ -1443,7 +1428,7 @@ function test47()
{
shouldCloseNotCleanly(e);
ok(hasError, "test-47: should have called onerror before onclose");
ok(ws.readyState == 3, "test-47: readyState should be CLOSED(3) in onclose: got "
ok(ws.readyState == 3, "test-47: readyState should be CLOSED(3) in onclose: got "
+ ws.readyState);
ok(!ws._withinClose, "onclose() called during close()!");
ok(e.code == 1006, "test-47 close code should be 1006 but is:" + e.code);

View File

@ -10,4 +10,4 @@ skip-if = buildapp == 'b2g' || toolkit == 'android'
[test_send-arraybuffer.html]
skip-if = buildapp == 'b2g' || toolkit == 'android'
[test_send-blob.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
skip-if = buildapp == 'b2g' || toolkit == 'android'

View File

@ -7,7 +7,6 @@
<body>
<p id="display">
<input id="fileList" type="file"></input>
</p>
<div id="content" style="display: none">
</div>
@ -20,74 +19,51 @@ function startsWith(target, prefix)
return target.indexOf(prefix) === 0;
}
function createDOMFile(fileName, fileData)
{
// create File in profile dir
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
.getService(SpecialPowers.Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
testFile.append(fileName);
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"]
.createInstance(SpecialPowers.Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, 0666, 0);
if (fileData) {
outStream.write(fileData, fileData.length);
outStream.close();
}
// Set filename into DOM <input> field, as if selected by user
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).value = testFile.path;
// return JS File object, aka Blob
return fileList.files[0];
}
function createBlobContainingHelloWorld()
{
return createDOMFile("hellofile", "Hello, world!");
}
function createEmptyBlob()
{
return createDOMFile("emptyfile");
}
function createBlobContainingAllDistinctBytes()
function distinctBytes()
{
var array = new Array();
for (var i = 0; i < 256; ++i)
array[i] = i;
// Concatenates chars into a single binary string
binaryString = String.fromCharCode.apply(null, array);
return createDOMFile("allchars", binaryString);
// Concatenates chars into a single binary string
return String.fromCharCode.apply(null, array);
}
var ws = new WebSocket("ws://mochi.test:8888/tests/dom/base/test/websocket_hybi/file_check-binary-messages");
var closeEvent;
var filesToCreate = [
{name: "hellofile", data: "Hello, world!"},
{name: "emptyfile"},
{name: "allchars", data: distinctBytes()},
];
ws.onopen = function()
{
ws.send(createBlobContainingHelloWorld());
ws.send(createEmptyBlob());
ws.send(createBlobContainingAllDistinctBytes());
};
SpecialPowers.createFiles(filesToCreate, function (files) {
var ws = new WebSocket("ws://mochi.test:8888/tests/dom/base/test/websocket_hybi/file_check-binary-messages");
var closeEvent;
ws.onmessage = function(event)
{
var message = event.data;
if (startsWith(message, "PASS"))
ok(true, message);
else
ok(false, message);
};
ws.onopen = function()
{
ws.send(files[0]);
ws.send(files[1]);
ws.send(files[2]);
};
ws.onclose = function(event)
{
ws.onmessage = function(event)
{
var message = event.data;
if (startsWith(message, "PASS"))
ok(true, message);
else
ok(false, message);
};
ws.onclose = function(event)
{
ok(event.wasClean, "should have closed cleanly");
SimpleTest.finish();
};
};
},
function (msg) {
ok(false, "Failed to create files: " + msg);
SimpleTest.finish();
});
SimpleTest.waitForExplicitFinish();

View File

@ -83,3 +83,5 @@ MSG_DEF(MSG_NOTIFICATION_PERMISSION_DENIED, 0, JSEXN_TYPEERR, "Permission to sho
MSG_DEF(MSG_NOTIFICATION_NO_CONSTRUCTOR_IN_SERVICEWORKER, 0, JSEXN_TYPEERR, "Notification constructor cannot be used in ServiceWorkerGlobalScope. Use registration.showNotification() instead.")
MSG_DEF(MSG_INVALID_SCOPE, 2, JSEXN_TYPEERR, "Invalid scope trying to resolve {0} with base URL {1}.")
MSG_DEF(MSG_INVALID_KEYFRAME_OFFSETS, 0, JSEXN_TYPEERR, "Keyframes with specified offsets must be in order and all be in the range [0, 1].")
MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} encountered an error during installation.")
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")

View File

@ -203,7 +203,9 @@ public:
NS_IMETHODIMP Run() override
{
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
MOZ_ASSERT(service);
if (!service) {
return NS_OK;
}
AutoJSAPI jsapi;
if (!jsapi.Init(mParentWindow)) {
@ -400,9 +402,9 @@ BrowserElementAudioChannel::SetVolume(float aVolume, ErrorResult& aRv)
}
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
MOZ_ASSERT(service);
service->SetAudioChannelVolume(mFrameWindow, mAudioChannel, aVolume);
if (service) {
service->SetAudioChannelVolume(mFrameWindow, mAudioChannel, aVolume);
}
RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner());
nsCOMPtr<nsIRunnable> runnable = new FireSuccessRunnable(GetOwner(),
@ -459,9 +461,9 @@ BrowserElementAudioChannel::SetMuted(bool aMuted, ErrorResult& aRv)
}
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
MOZ_ASSERT(service);
service->SetAudioChannelMuted(mFrameWindow, mAudioChannel, aMuted);
if (service) {
service->SetAudioChannelMuted(mFrameWindow, mAudioChannel, aMuted);
}
RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner());
nsCOMPtr<nsIRunnable> runnable = new FireSuccessRunnable(GetOwner(),

View File

@ -71,6 +71,10 @@ public:
HTMLCanvasElement* GetCanvas() const
{
if (mCanvasElement->IsInNativeAnonymousSubtree()) {
return nullptr;
}
// corresponds to changes to the old bindings made in bug 745025
return mCanvasElement->GetOriginalCanvas();
}

View File

@ -1235,7 +1235,12 @@ WebGLContext::GetCanvas(Nullable<dom::OwningHTMLCanvasElementOrOffscreenCanvas>&
{
if (mCanvasElement) {
MOZ_RELEASE_ASSERT(!mOffscreenCanvas);
retval.SetValue().SetAsHTMLCanvasElement() = mCanvasElement;
if (mCanvasElement->IsInNativeAnonymousSubtree()) {
retval.SetNull();
} else {
retval.SetValue().SetAsHTMLCanvasElement() = mCanvasElement;
}
} else if (mOffscreenCanvas) {
retval.SetValue().SetAsOffscreenCanvas() = mOffscreenCanvas;
} else {

View File

@ -0,0 +1,2 @@
// Ensure the contacts service is running in the parent.
Components.utils.import("resource://gre/modules/ContactService.jsm");

View File

@ -1,6 +1,5 @@
[DEFAULT]
skip-if = e10s
support-files = shared.js
support-files = shared.js contacts_chromescript.js
[test_contacts_basics.html]
skip-if = (toolkit == 'gonk' && debug) #debug-only failure

View File

@ -3,6 +3,8 @@
// Fix the environment to run Contacts tests
if (SpecialPowers.isMainProcess()) {
SpecialPowers.Cu.import("resource://gre/modules/ContactService.jsm");
} else {
SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('contacts_chromescript.js'));
}
// Some helpful global vars

View File

@ -162,7 +162,7 @@ GetNotifyIMEMessageName(IMEMessage aMessage)
StaticRefPtr<nsIContent> IMEStateManager::sContent;
nsPresContext* IMEStateManager::sPresContext = nullptr;
StaticRefPtr<nsIWidget> IMEStateManager::sFocusedIMEWidget;
nsIWidget* IMEStateManager::sFocusedIMEWidget;
StaticRefPtr<TabParent> IMEStateManager::sActiveTabParent;
StaticRefPtr<IMEContentObserver> IMEStateManager::sActiveIMEContentObserver;
TextCompositionArray* IMEStateManager::sTextCompositions = nullptr;
@ -217,6 +217,15 @@ IMEStateManager::OnTabParentDestroying(TabParent* aTabParent)
// disable IME.
}
// static
void
IMEStateManager::WidgetDestroyed(nsIWidget* aWidget)
{
if (sFocusedIMEWidget == aWidget) {
sFocusedIMEWidget = nullptr;
}
}
// static
void
IMEStateManager::StopIMEStateManagement()
@ -1316,7 +1325,7 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
"aWidget=0x%p, aOriginIsRemote=%s), sFocusedIMEWidget=0x%p, "
"sRemoteHasFocus=%s",
GetNotifyIMEMessageName(aNotification.mMessage), aWidget,
GetBoolName(aOriginIsRemote), sFocusedIMEWidget.get(),
GetBoolName(aOriginIsRemote), sFocusedIMEWidget,
GetBoolName(sRemoteHasFocus)));
if (NS_WARN_IF(!aWidget)) {

View File

@ -64,6 +64,11 @@ public:
*/
static void OnTabParentDestroying(TabParent* aTabParent);
/**
* Called when aWidget is being deleted.
*/
static void WidgetDestroyed(nsIWidget* aWidget);
/**
* SetIMEContextForChildProcess() is called when aTabParent receives
* SetInputContext() from the remote process.
@ -225,7 +230,7 @@ protected:
static StaticRefPtr<nsIContent> sContent;
static nsPresContext* sPresContext;
static StaticRefPtr<nsIWidget> sFocusedIMEWidget;
static nsIWidget* sFocusedIMEWidget;
static StaticRefPtr<TabParent> sActiveTabParent;
// sActiveIMEContentObserver points to the currently active
// IMEContentObserver. This is null if there is no focused editor.

View File

@ -2773,7 +2773,9 @@ nsresult HTMLMediaElement::InitializeDecoderAsClone(MediaDecoder* aOriginal)
decoder->SetMediaSeekable(aOriginal->IsMediaSeekable());
RefPtr<MediaResource> resource = originalResource->CloneData(decoder);
RefPtr<MediaResource> resource =
originalResource->CloneData(decoder->GetResourceCallback());
if (!resource) {
LOG(LogLevel::Debug, ("%p Failed to cloned stream for decoder %p", this, decoder.get()));
return NS_ERROR_FAILURE;
@ -2805,7 +2807,9 @@ nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
LOG(LogLevel::Debug, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
RefPtr<MediaResource> resource = MediaResource::Create(decoder, aChannel);
RefPtr<MediaResource> resource =
MediaResource::Create(decoder->GetResourceCallback(), aChannel);
if (!resource)
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -59,7 +59,7 @@ interface nsIServiceWorkerManagerListener : nsISupports
void onUnregister(in nsIServiceWorkerRegistrationInfo aInfo);
};
[scriptable, builtinclass, uuid(2f61820a-1e9a-4c16-bf1c-ce182c5f5d6d)]
[scriptable, builtinclass, uuid(c945e2e6-30c2-48e6-a282-e69de0c7ebb1)]
interface nsIServiceWorkerManager : nsISupports
{
/**
@ -174,6 +174,8 @@ interface nsIServiceWorkerManager : nsISupports
void addListener(in nsIServiceWorkerManagerListener aListener);
void removeListener(in nsIServiceWorkerManagerListener aListener);
bool shouldReportToWindow(in nsIDOMWindow aWindow, in ACString aScope);
};
%{ C++

View File

@ -1108,7 +1108,7 @@ ParticularProcessPriorityManager::ComputePriority()
}
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
if (service->ProcessContentOrNormalChannelIsActive(ChildID())) {
if (service && service->ProcessContentOrNormalChannelIsActive(ChildID())) {
return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE;
}

View File

@ -833,6 +833,7 @@ TabChild::NotifyTabContextUpdated()
} else {
docShell->SetIsApp(OwnAppId());
}
docShell->SetIsSignedPackage(OriginAttributesRef().mSignedPkg);
}
}

View File

@ -25,7 +25,7 @@ namespace mozilla {
#undef LOG
#endif
PRLogModuleInfo* gAudioStreamLog = nullptr;
LazyLogModule gAudioStreamLog("AudioStream");
// For simple logs
#define LOG(x) MOZ_LOG(gAudioStreamLog, mozilla::LogLevel::Debug, x)

View File

@ -40,7 +40,7 @@ uint32_t sPreferredSampleRate;
} // namespace
extern PRLogModuleInfo* gAudioStreamLog;
extern LazyLogModule gAudioStreamLog;
static const uint32_t CUBEB_NORMAL_LATENCY_MS = 100;
@ -126,7 +126,6 @@ bool CubebLatencyPrefSet()
void InitLibrary()
{
gAudioStreamLog = PR_NewLogModule("AudioStream");
PrefChanged(PREF_VOLUME_SCALE, nullptr);
Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE);
PrefChanged(PREF_CUBEB_LATENCY, nullptr);

View File

@ -27,13 +27,13 @@
#undef LOG
#endif
static PRLogModuleInfo* gMediaStreamLog;
#define LOG(type, msg) MOZ_LOG(gMediaStreamLog, type, msg)
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layers;
static LazyLogModule gMediaStreamLog("MediaStream");
#define LOG(type, msg) MOZ_LOG(gMediaStreamLog, type, msg)
const TrackID TRACK_VIDEO_PRIMARY = 1;
@ -318,10 +318,6 @@ DOMMediaStream::DOMMediaStream()
nsCOMPtr<nsIUUIDGenerator> uuidgen =
do_GetService("@mozilla.org/uuid-generator;1", &rv);
if (!gMediaStreamLog) {
gMediaStreamLog = PR_NewLogModule("MediaStream");
}
if (NS_SUCCEEDED(rv) && uuidgen) {
nsID uuid;
memset(&uuid, 0, sizeof(uuid));

View File

@ -136,7 +136,7 @@ public:
}
bool Contains(int32_t aValue) {
for (int32_t i = 0; i < GetSize(); ++i) {
for (size_t i = 0; i < GetSize(); ++i) {
if (ObjectAt(i) == aValue) {
return true;
}
@ -149,7 +149,7 @@ public:
}
private:
int32_t ObjectAt(int32_t aIndex) {
int32_t ObjectAt(size_t aIndex) {
void* v = nsDeque::ObjectAt(aIndex);
return reinterpret_cast<uintptr_t>(v);
}

View File

@ -10,7 +10,7 @@
#include <sys/sysctl.h>
#endif
extern PRLogModuleInfo* gMediaStreamGraphLog;
extern mozilla::LazyLogModule gMediaStreamGraphLog;
#define STREAM_LOG(type, msg) MOZ_LOG(gMediaStreamGraphLog, type, msg)
// We don't use NSPR log here because we want this interleaved with adb logcat

View File

@ -37,17 +37,13 @@ const char* LatencyLogIndex2Strings[] = {
static StaticRefPtr<AsyncLatencyLogger> gAsyncLogger;
PRLogModuleInfo*
LogModule*
GetLatencyLog()
{
static PRLogModuleInfo* sLog;
if (!sLog) {
sLog = PR_NewLogModule("MediaLatency");
}
static LazyLogModule sLog("MediaLatency");
return sLog;
}
class LogEvent : public nsRunnable
{
public:
@ -111,6 +107,8 @@ void LogLatency(uint32_t aIndex, uint64_t aID, int64_t aValue)
void AsyncLatencyLogger::InitializeStatics()
{
NS_ASSERTION(NS_IsMainThread(), "Main thread only");
//Make sure that the underlying logger is allocated.
GetLatencyLog();
gAsyncLogger = new AsyncLatencyLogger();
}

View File

@ -17,7 +17,7 @@
class AsyncLatencyLogger;
PRLogModuleInfo* GetLatencyLog();
mozilla::LogModule* GetLatencyLog();
// This class is a singleton. It is refcounted.
class AsyncLatencyLogger : public nsIObserver

View File

@ -16,7 +16,7 @@
#include "prenv.h"
#ifdef PR_LOGGING
PRLogModuleInfo* gMP3DemuxerLog;
mozilla::LazyLogModule gMP3DemuxerLog("MP3Demuxer");
#define MP3LOG(msg, ...) \
MOZ_LOG(gMP3DemuxerLog, LogLevel::Debug, ("MP3Demuxer " msg, ##__VA_ARGS__))
#define MP3LOGV(msg, ...) \
@ -112,12 +112,6 @@ MP3TrackDemuxer::MP3TrackDemuxer(MediaResource* aSource)
, mChannels(0)
{
Reset();
#ifdef PR_LOGGING
if (!gMP3DemuxerLog) {
gMP3DemuxerLog = PR_NewLogModule("MP3Demuxer");
}
#endif
}
bool

View File

@ -24,7 +24,7 @@
namespace mozilla {
PRLogModuleInfo* gMediaCacheLog;
LazyLogModule gMediaCacheLog("MediaCache");
#define CACHE_LOG(type, msg) MOZ_LOG(gMediaCacheLog, type, msg)
// Readahead blocks for non-seekable streams will be limited to this
@ -580,10 +580,6 @@ MediaCache::Init()
rv = mFileCache->Open(fileDesc);
NS_ENSURE_SUCCESS(rv,rv);
if (!gMediaCacheLog) {
gMediaCacheLog = PR_NewLogModule("MediaCache");
}
MediaCacheFlusher::Init();
return NS_OK;

View File

@ -46,7 +46,7 @@ static const uint64_t ESTIMATED_DURATION_FUZZ_FACTOR_USECS = USECS_PER_S / 2;
// avoid redefined macro in unified build
#undef DECODER_LOG
PRLogModuleInfo* gMediaDecoderLog;
LazyLogModule gMediaDecoderLog("MediaDecoder");
#define DECODER_LOG(x, ...) \
MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, ("Decoder=%p " x, this, ##__VA_ARGS__))
@ -113,27 +113,169 @@ public:
StaticRefPtr<MediaMemoryTracker> MediaMemoryTracker::sUniqueInstance;
#if defined(PR_LOGGING)
PRLogModuleInfo* gMediaTimerLog;
PRLogModuleInfo* gMediaSampleLog;
LazyLogModule gMediaTimerLog("MediaTimer");
LazyLogModule gMediaSampleLog("MediaSample");
#endif
void
MediaDecoder::InitStatics()
{
MOZ_ASSERT(NS_IsMainThread());
#if defined(PR_LOGGING)
// Log modules.
gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
gMediaTimerLog = PR_NewLogModule("MediaTimer");
gMediaSampleLog = PR_NewLogModule("MediaSample");
#endif
}
NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
NS_IMPL_ISUPPORTS0(MediaDecoder)
void
MediaDecoder::ResourceCallback::Connect(MediaDecoder* aDecoder)
{
MOZ_ASSERT(NS_IsMainThread());
mDecoder = aDecoder;
}
void
MediaDecoder::ResourceCallback::Disconnect()
{
MOZ_ASSERT(NS_IsMainThread());
mDecoder = nullptr;
}
MediaDecoderOwner*
MediaDecoder::ResourceCallback::GetMediaOwner() const
{
MOZ_ASSERT(NS_IsMainThread());
return mDecoder ? mDecoder->GetOwner() : nullptr;
}
void
MediaDecoder::ResourceCallback::SetInfinite(bool aInfinite)
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->SetInfinite(aInfinite);
}
}
void
MediaDecoder::ResourceCallback::SetMediaSeekable(bool aMediaSeekable)
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->SetMediaSeekable(aMediaSeekable);
}
}
void
MediaDecoder::ResourceCallback::ResetConnectionState()
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->ResetConnectionState();
}
}
nsresult
MediaDecoder::ResourceCallback::FinishDecoderSetup(MediaResource* aResource)
{
MOZ_ASSERT(NS_IsMainThread());
return mDecoder ? mDecoder->FinishDecoderSetup(aResource) : NS_ERROR_FAILURE;
}
void
MediaDecoder::ResourceCallback::NotifyNetworkError()
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->NetworkError();
}
}
void
MediaDecoder::ResourceCallback::NotifyDecodeError()
{
RefPtr<ResourceCallback> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
if (self->mDecoder) {
self->mDecoder->DecodeError();
}
});
AbstractThread::MainThread()->Dispatch(r.forget());
}
void
MediaDecoder::ResourceCallback::NotifyDataArrived()
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->NotifyDataArrived();
}
}
void
MediaDecoder::ResourceCallback::NotifyBytesDownloaded()
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->NotifyBytesDownloaded();
}
}
void
MediaDecoder::ResourceCallback::NotifyDataEnded(nsresult aStatus)
{
RefPtr<ResourceCallback> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
if (!self->mDecoder) {
return;
}
self->mDecoder->NotifyDownloadEnded(aStatus);
if (NS_SUCCEEDED(aStatus)) {
HTMLMediaElement* element = self->GetMediaOwner()->GetMediaElement();
if (element) {
element->DownloadSuspended();
}
// NotifySuspendedStatusChanged will tell the element that download
// has been suspended "by the cache", which is true since we never
// download anything. The element can then transition to HAVE_ENOUGH_DATA.
self->mDecoder->NotifySuspendedStatusChanged();
}
});
AbstractThread::MainThread()->Dispatch(r.forget());
}
void
MediaDecoder::ResourceCallback::NotifyPrincipalChanged()
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->NotifyPrincipalChanged();
}
}
void
MediaDecoder::ResourceCallback::NotifySuspendedStatusChanged()
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->NotifySuspendedStatusChanged();
}
}
void
MediaDecoder::ResourceCallback::NotifyBytesConsumed(int64_t aBytes,
int64_t aOffset)
{
RefPtr<ResourceCallback> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
if (self->mDecoder) {
self->mDecoder->NotifyBytesConsumed(aBytes, aOffset);
}
});
AbstractThread::MainThread()->Dispatch(r.forget());
}
void
MediaDecoder::NotifyOwnerActivityChanged()
{
@ -334,6 +476,7 @@ void
MediaDecoder::SetInfinite(bool aInfinite)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mShuttingDown);
mInfiniteStream = aInfinite;
DurationChanged();
}
@ -350,6 +493,7 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
, mDormantSupported(false)
, mLogicalPosition(0.0)
, mDuration(std::numeric_limits<double>::quiet_NaN())
, mResourceCallback(new ResourceCallback())
#ifdef MOZ_EME
, mCDMProxyPromise(mCDMProxyPromiseHolder.Ensure(__func__))
#endif
@ -417,6 +561,7 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
MediaMemoryTracker::AddMediaDecoder(this);
mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
mResourceCallback->Connect(this);
//
// Initialize watchers.
@ -453,6 +598,8 @@ MediaDecoder::Shutdown()
mShuttingDown = true;
mResourceCallback->Disconnect();
#ifdef MOZ_EME
mCDMProxyPromiseHolder.RejectIfExists(true, __func__);
#endif
@ -486,6 +633,12 @@ MediaDecoder::~MediaDecoder()
MOZ_COUNT_DTOR(MediaDecoder);
}
MediaResourceCallback*
MediaDecoder::GetResourceCallback() const
{
return mResourceCallback;
}
nsresult
MediaDecoder::OpenResource(nsIStreamListener** aStreamListener)
{
@ -720,55 +873,18 @@ nsresult
MediaDecoder::FinishDecoderSetup(MediaResource* aResource)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mShuttingDown);
HTMLMediaElement* element = mOwner->GetMediaElement();
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
element->FinishDecoderSetup(this, aResource);
return NS_OK;
}
void
MediaDecoder::NotifyNetworkError()
{
NetworkError();
}
void
MediaDecoder::NotifyDecodeError()
{
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableMethod(this, &MediaDecoder::DecodeError);
AbstractThread::MainThread()->Dispatch(r.forget());
}
void
MediaDecoder::NotifyDataEnded(nsresult aStatus)
{
RefPtr<MediaDecoder> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
if (self->mShuttingDown) {
return;
}
self->NotifyDownloadEnded(aStatus);
if (NS_SUCCEEDED(aStatus)) {
HTMLMediaElement* element = self->mOwner->GetMediaElement();
if (element) {
element->DownloadSuspended();
}
// NotifySuspendedStatusChanged will tell the element that download
// has been suspended "by the cache", which is true since we never
// download anything. The element can then transition to HAVE_ENOUGH_DATA.
self->NotifySuspendedStatusChanged();
}
});
AbstractThread::MainThread()->Dispatch(r.forget());
}
void
MediaDecoder::ResetConnectionState()
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown)
return;
MOZ_ASSERT(!mShuttingDown);
// Notify the media element that connection gets lost.
mOwner->ResetConnectionState();
@ -912,9 +1028,7 @@ void
MediaDecoder::NotifySuspendedStatusChanged()
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown) {
return;
}
MOZ_ASSERT(!mShuttingDown);
if (mResource) {
bool suspended = mResource->IsSuspendedByCache();
mOwner->NotifySuspendedByCache(suspended);
@ -936,10 +1050,7 @@ void
MediaDecoder::NotifyDownloadEnded(nsresult aStatus)
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown) {
return;
}
MOZ_ASSERT(!mShuttingDown);
DECODER_LOG("NotifyDownloadEnded, status=%x", aStatus);
@ -965,25 +1076,17 @@ void
MediaDecoder::NotifyPrincipalChanged()
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown) {
return;
}
MOZ_ASSERT(!mShuttingDown);
mOwner->NotifyDecoderPrincipalChanged();
}
void
MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
{
if (!NS_IsMainThread()) {
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArgs<int64_t, int64_t>(
this, &MediaDecoder::NotifyBytesConsumed, aBytes, aOffset);
AbstractThread::MainThread()->Dispatch(r.forget());
return;
}
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mShuttingDown);
if (mShuttingDown || mIgnoreProgressData) {
if (mIgnoreProgressData) {
return;
}
@ -1367,12 +1470,6 @@ MediaDecoder::BreakCycles() {
SetStateMachine(nullptr);
}
MediaDecoderOwner*
MediaDecoder::GetMediaOwner() const
{
return mOwner;
}
void
MediaDecoder::FireTimeUpdate()
{

View File

@ -273,7 +273,7 @@ struct SeekTarget {
MediaDecoderEventVisibility mEventVisibility;
};
class MediaDecoder : public AbstractMediaDecoder, public MediaResourceCallback
class MediaDecoder : public AbstractMediaDecoder
{
public:
struct SeekResolveValue {
@ -283,6 +283,35 @@ public:
MediaDecoderEventVisibility mEventVisibility;
};
// Used to register with MediaResource to receive notifications which will
// be forwarded to MediaDecoder.
class ResourceCallback : public MediaResourceCallback {
public:
// Start to receive notifications from ResourceCallback.
void Connect(MediaDecoder* aDecoder);
// Called upon shutdown to stop receiving notifications.
void Disconnect();
private:
/* MediaResourceCallback functions */
MediaDecoderOwner* GetMediaOwner() const override;
void SetInfinite(bool aInfinite) override;
void SetMediaSeekable(bool aMediaSeekable) override;
void ResetConnectionState() override;
nsresult FinishDecoderSetup(MediaResource* aResource) override;
void NotifyNetworkError() override;
void NotifyDecodeError() override;
void NotifyDataArrived() override;
void NotifyBytesDownloaded() override;
void NotifyDataEnded(nsresult aStatus) override;
void NotifyPrincipalChanged() override;
void NotifySuspendedStatusChanged() override;
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) override;
// The decoder to send notifications. Main-thread only.
MediaDecoder* mDecoder = nullptr;
};
typedef MozPromise<SeekResolveValue, bool /* aIgnored */, /* IsExclusive = */ true> SeekPromise;
NS_DECL_THREADSAFE_ISUPPORTS
@ -302,9 +331,10 @@ public:
explicit MediaDecoder(MediaDecoderOwner* aOwner);
// Reset the decoder and notify the media element that
// server connection is closed.
virtual void ResetConnectionState() override;
// Return a callback object used to register with MediaResource to receive
// notifications.
MediaResourceCallback* GetResourceCallback() const;
// Create a new decoder of the same type as this one.
// Subclasses must implement this.
virtual MediaDecoder* Clone(MediaDecoderOwner* aOwner) = 0;
@ -325,7 +355,7 @@ public:
nsresult OpenResource(nsIStreamListener** aStreamListener);
// Called if the media file encounters a network error.
virtual void NetworkError();
void NetworkError();
// Get the current MediaResource being used. Its URI will be returned
// by currentSrc. Returns what was passed to Load(), if Load() has been called.
@ -403,47 +433,17 @@ public:
// Return the duration of the video in seconds.
virtual double GetDuration();
// A media stream is assumed to be infinite if the metadata doesn't
// contain the duration, and range requests are not supported, and
// no headers give a hint of a possible duration (Content-Length,
// Content-Duration, and variants), and we cannot seek in the media
// stream to determine the duration.
//
// When the media stream ends, we can know the duration, thus the stream is
// no longer considered to be infinite.
virtual void SetInfinite(bool aInfinite) override;
// Return true if the stream is infinite (see SetInfinite).
virtual bool IsInfinite();
// Called by MediaResource when the "cache suspended" status changes.
// If MediaResource::IsSuspendedByCache returns true, then the decoder
// should stop buffering or otherwise waiting for download progress and
// start consuming data, if possible, because the cache is full.
virtual void NotifySuspendedStatusChanged() override;
// Called by MediaResource when some data has been received.
// Call on the main thread only.
virtual void NotifyBytesDownloaded() override;
// Called by nsChannelToPipeListener or MediaResource when the
// download has ended. Called on the main thread only. aStatus is
// the result from OnStopRequest.
virtual void NotifyDownloadEnded(nsresult aStatus);
virtual void NotifyBytesDownloaded();
// Called as data arrives on the stream and is read into the cache. Called
// on the main thread only.
virtual void NotifyDataArrived() override;
// Called by MediaResource when the principal of the resource has
// changed. Called on main thread only.
virtual void NotifyPrincipalChanged() override;
// Called by the MediaResource to keep track of the number of bytes read
// from the resource. Called on the main by an event runner dispatched
// by the MediaResource read functions.
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) final override;
// Return true if we are currently seeking in the media resource.
// Call on the main thread only.
virtual bool IsSeeking() const;
@ -508,9 +508,6 @@ public:
// SetLoadInBackground() on mResource.
void SetLoadInBackground(bool aLoadInBackground);
// Returns a weak reference to the media decoder owner.
MediaDecoderOwner* GetMediaOwner() const override;
MediaDecoderStateMachine* GetStateMachine() const;
void SetStateMachine(MediaDecoderStateMachine* aStateMachine);
@ -673,7 +670,7 @@ private:
virtual void BreakCycles();
// Notifies the element that decoding has failed.
virtual void DecodeError();
void DecodeError();
// Indicate whether the media is same-origin with the element.
void UpdateSameOriginStatus(bool aSameOrigin);
@ -832,6 +829,8 @@ private:
// Explicitly prievate to force access via accessors.
RefPtr<MediaDecoderStateMachine> mDecoderStateMachine;
RefPtr<ResourceCallback> mResourceCallback;
#ifdef MOZ_EME
MozPromiseHolder<CDMProxyPromise> mCDMProxyPromiseHolder;
RefPtr<CDMProxyPromise> mCDMProxyPromise;
@ -1054,11 +1053,43 @@ public:
}
private:
/* MediaResourceCallback functions */
virtual nsresult FinishDecoderSetup(MediaResource* aResource) override;
virtual void NotifyNetworkError() override;
virtual void NotifyDecodeError() override;
virtual void NotifyDataEnded(nsresult aStatus) override;
/* Functions called by ResourceCallback */
// A media stream is assumed to be infinite if the metadata doesn't
// contain the duration, and range requests are not supported, and
// no headers give a hint of a possible duration (Content-Length,
// Content-Duration, and variants), and we cannot seek in the media
// stream to determine the duration.
//
// When the media stream ends, we can know the duration, thus the stream is
// no longer considered to be infinite.
void SetInfinite(bool aInfinite);
// Reset the decoder and notify the media element that
// server connection is closed.
void ResetConnectionState();
nsresult FinishDecoderSetup(MediaResource* aResource);
// Called by MediaResource when the principal of the resource has
// changed. Called on main thread only.
void NotifyPrincipalChanged();
// Called by MediaResource when the "cache suspended" status changes.
// If MediaResource::IsSuspendedByCache returns true, then the decoder
// should stop buffering or otherwise waiting for download progress and
// start consuming data, if possible, because the cache is full.
void NotifySuspendedStatusChanged();
// Called by the MediaResource to keep track of the number of bytes read
// from the resource. Called on the main by an event runner dispatched
// by the MediaResource read functions.
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) final override;
// Called by nsChannelToPipeListener or MediaResource when the
// download has ended. Called on the main thread only. aStatus is
// the result from OnStopRequest.
void NotifyDownloadEnded(nsresult aStatus);
};
} // namespace mozilla

View File

@ -22,7 +22,7 @@ namespace mozilla {
// Un-comment to enable logging of seek bisections.
//#define SEEK_LOGGING
extern PRLogModuleInfo* gMediaDecoderLog;
extern LazyLogModule gMediaDecoderLog;
#define DECODER_LOG(x, ...) \
MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, ("Decoder=%p " x, mDecoder, ##__VA_ARGS__))

View File

@ -472,6 +472,10 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
{
MOZ_ASSERT(OnTaskQueue());
if (VideoQueue().GetSize() == 0) {
return false;
}
if (VideoQueue().GetSize() - 1 < GetAmpleVideoFrames() * mPlaybackRate) {
return false;
}

View File

@ -107,8 +107,8 @@ class AudioSegment;
class DecodedStream;
class TaskQueue;
extern PRLogModuleInfo* gMediaDecoderLog;
extern PRLogModuleInfo* gMediaSampleLog;
extern LazyLogModule gMediaDecoderLog;
extern LazyLogModule gMediaSampleLog;
/*
The state machine class. This manages the decoding and seeking in the

View File

@ -28,15 +28,10 @@ using mozilla::layers::Image;
using mozilla::layers::LayerManager;
using mozilla::layers::LayersBackend;
PRLogModuleInfo* GetFormatDecoderLog() {
static PRLogModuleInfo* log = nullptr;
if (!log) {
log = PR_NewLogModule("MediaFormatReader");
}
return log;
}
#define LOG(arg, ...) MOZ_LOG(GetFormatDecoderLog(), mozilla::LogLevel::Debug, ("MediaFormatReader(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
#define LOGV(arg, ...) MOZ_LOG(GetFormatDecoderLog(), mozilla::LogLevel::Verbose, ("MediaFormatReader(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
static mozilla::LazyLogModule sFormatDecoderLog("MediaFormatReader");
#define LOG(arg, ...) MOZ_LOG(sFormatDecoderLog, mozilla::LogLevel::Debug, ("MediaFormatReader(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
#define LOGV(arg, ...) MOZ_LOG(sFormatDecoderLog, mozilla::LogLevel::Verbose, ("MediaFormatReader(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
namespace mozilla {

View File

@ -104,12 +104,10 @@ namespace mozilla {
#undef LOG
#endif
PRLogModuleInfo*
LogModule*
GetMediaManagerLog()
{
static PRLogModuleInfo *sLog;
if (!sLog)
sLog = PR_NewLogModule("MediaManager");
static LazyLogModule sLog("MediaManager");
return sLog;
}
#define LOG(msg) MOZ_LOG(GetMediaManagerLog(), mozilla::LogLevel::Debug, msg)

View File

@ -51,7 +51,7 @@ struct MediaTrackConstraints;
struct MediaTrackConstraintSet;
} // namespace dom
extern PRLogModuleInfo* GetMediaManagerLog();
extern LogModule* GetMediaManagerLog();
#define MM_LOG(msg) MOZ_LOG(GetMediaManagerLog(), mozilla::LogLevel::Debug, msg)
class MediaDevice : public nsIMediaDevice

View File

@ -330,7 +330,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIGETUSERMEDIADEVICESSUCCESSCALLBACK
MediaDeviceSuccessCallback(RefPtr<dom::GetUserMediaRequest> &aRequest)
explicit MediaDeviceSuccessCallback(RefPtr<dom::GetUserMediaRequest> &aRequest)
: mRequest(aRequest) {}
protected:
@ -395,7 +395,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMGETUSERMEDIAERRORCALLBACK
MediaDeviceErrorCallback(const nsAString &aCallID)
explicit MediaDeviceErrorCallback(const nsAString &aCallID)
: mCallID(aCallID) {}
protected:

View File

@ -36,7 +36,7 @@ public:
Reset();
}
inline int32_t GetSize() {
inline size_t GetSize() {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
return nsDeque::GetSize();
}
@ -124,9 +124,9 @@ public:
// Elements whose start time is before aTime are ignored.
void GetElementsAfter(int64_t aTime, nsTArray<RefPtr<T>>* aResult) {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!GetSize())
if (GetSize() == 0)
return;
int32_t i;
size_t i;
for (i = GetSize() - 1; i > 0; --i) {
T* v = static_cast<T*>(ObjectAt(i));
if (v->GetEndTime() < aTime)
@ -135,14 +135,14 @@ public:
// Elements less than i have a end time before aTime. It's also possible
// that the element at i has a end time before aTime, but that's OK.
for (; i < GetSize(); ++i) {
RefPtr<T> elem = static_cast<T*>(ObjectAt(i));
RefPtr<T> elem = static_cast<T*>(ObjectAt(static_cast<size_t>(i)));
aResult->AppendElement(elem);
}
}
void GetFirstElements(uint32_t aMaxElements, nsTArray<RefPtr<T>>* aResult) {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
for (int32_t i = 0; i < (int32_t)aMaxElements && i < GetSize(); ++i) {
for (size_t i = 0; i < aMaxElements && i < GetSize(); ++i) {
*aResult->AppendElement() = static_cast<T*>(ObjectAt(i));
}
}
@ -150,7 +150,7 @@ public:
uint32_t FrameCount() {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
uint32_t frames = 0;
for (int32_t i = 0; i < GetSize(); ++i) {
for (size_t i = 0; i < GetSize(); ++i) {
T* v = static_cast<T*>(ObjectAt(i));
frames += v->mFrames;
}

View File

@ -31,7 +31,7 @@
#undef LOG
#endif
PRLogModuleInfo* gMediaRecorderLog;
mozilla::LazyLogModule gMediaRecorderLog("MediaRecorder");
#define LOG(type, msg) MOZ_LOG(gMediaRecorderLog, type, msg)
namespace mozilla {
@ -776,9 +776,7 @@ MediaRecorder::MediaRecorder(DOMMediaStream& aSourceMediaStream,
MOZ_ASSERT(aOwnerWindow);
MOZ_ASSERT(aOwnerWindow->IsInnerWindow());
mDOMStream = &aSourceMediaStream;
if (!gMediaRecorderLog) {
gMediaRecorderLog = PR_NewLogModule("MediaRecorder");
}
RegisterActivityObserver();
}
@ -809,9 +807,7 @@ MediaRecorder::MediaRecorder(AudioNode& aSrcAudioNode,
}
}
mAudioNode = &aSrcAudioNode;
if (!gMediaRecorderLog) {
gMediaRecorderLog = PR_NewLogModule("MediaRecorder");
}
RegisterActivityObserver();
}

View File

@ -36,7 +36,7 @@
using mozilla::media::TimeUnit;
PRLogModuleInfo* gMediaResourceLog;
mozilla::LazyLogModule gMediaResourceLog("MediaResource");
#define RESOURCE_LOG(msg, ...) MOZ_LOG(gMediaResourceLog, mozilla::LogLevel::Debug, \
(msg, ##__VA_ARGS__))
// Debug logging macro with object pointer and class name.
@ -79,9 +79,6 @@ ChannelMediaResource::ChannelMediaResource(MediaResourceCallback* aCallback,
mIsTransportSeekable(true),
mSuspendAgent(mChannel)
{
if (!gMediaResourceLog) {
gMediaResourceLog = PR_NewLogModule("MediaResource");
}
}
ChannelMediaResource::~ChannelMediaResource()
@ -249,7 +246,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
// Content-Range header text should be parse-able.
CMLOG("Error processing \'Content-Range' for "
"HTTP_PARTIAL_RESPONSE_CODE: rv[%x] channel[%p] decoder[%p]",
rv, hc.get(), mCallback);
rv, hc.get(), mCallback.get());
mCallback->NotifyNetworkError();
CloseChannel();
return NS_OK;
@ -377,7 +374,7 @@ ChannelMediaResource::ParseContentRangeHeader(nsIHttpChannel * aHttpChan,
}
CMLOG("Received bytes [%lld] to [%lld] of [%lld] for decoder[%p]",
aRangeStart, aRangeEnd, aRangeTotal, mCallback);
aRangeStart, aRangeEnd, aRangeTotal, mCallback.get());
return NS_OK;
}
@ -461,7 +458,7 @@ ChannelMediaResource::CopySegmentToCache(nsIInputStream *aInStream,
RESOURCE_LOG("%p [ChannelMediaResource]: CopySegmentToCache at mOffset [%lld] add "
"[%d] bytes for decoder[%p]",
closure->mResource, closure->mResource->mOffset, aCount,
closure->mResource->mCallback);
closure->mResource->mCallback.get());
closure->mResource->mOffset += aCount;
closure->mResource->mCacheStream.NotifyDataReceived(aCount, aFromSegment,
@ -930,7 +927,7 @@ ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume)
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
CMLOG("CacheClientSeek requested for aOffset [%lld] for decoder [%p]",
aOffset, mCallback);
aOffset, mCallback.get());
CloseChannel();

View File

@ -16,6 +16,7 @@
#include "nsIInterfaceRequestor.h"
#include "MediaCache.h"
#include "MediaData.h"
#include "MediaResourceCallback.h"
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/TimeStamp.h"
@ -43,7 +44,6 @@ class nsIPrincipal;
namespace mozilla {
class MediaResourceCallback;
class MediaChannelStatistics;
/**
@ -513,10 +513,7 @@ protected:
// on the main thread. This is called automatically after every read.
void DispatchBytesConsumed(int64_t aNumBytes, int64_t aOffset);
// This is not an nsCOMPointer to prevent a circular reference
// between the decoder to the media stream object. The stream never
// outlives the lifetime of the decoder.
MediaResourceCallback* mCallback;
RefPtr<MediaResourceCallback> mCallback;
// Channel used to download the media data. Must be accessed
// from the main thread only.

View File

@ -8,9 +8,11 @@
#define MediaResourceCallback_h_
#include "nsError.h"
#include "nsISupportsImpl.h"
namespace mozilla {
class MediaDecoderOwner;
class MediaResource;
/**
@ -24,6 +26,8 @@ class MediaResource;
*/
class MediaResourceCallback {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaResourceCallback);
// Returns a weak reference to the media decoder owner.
virtual MediaDecoderOwner* GetMediaOwner() const { return nullptr; }
@ -67,6 +71,9 @@ public:
// Notify the number of bytes read from the resource.
virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) {}
protected:
virtual ~MediaResourceCallback() {}
};
} // namespace mozilla

View File

@ -12,7 +12,7 @@
namespace mozilla {
extern PRLogModuleInfo* gMediaDecoderLog;
extern LazyLogModule gMediaDecoderLog;
#define DECODER_LOG(type, msg) MOZ_LOG(gMediaDecoderLog, type, msg)
NS_IMPL_ISUPPORTS(MediaShutdownManager, nsIObserver)

View File

@ -39,7 +39,7 @@ using namespace mozilla::gfx;
namespace mozilla {
PRLogModuleInfo* gMediaStreamGraphLog;
LazyLogModule gMediaStreamGraphLog("MediaStreamGraph");
#define STREAM_LOG(type, msg) MOZ_LOG(gMediaStreamGraphLog, type, msg)
// #define ENABLE_LIFECYCLE_LOG
@ -2639,10 +2639,6 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
#endif
, mAudioChannel(aChannel)
{
if (!gMediaStreamGraphLog) {
gMediaStreamGraphLog = PR_NewLogModule("MediaStreamGraph");
}
if (mRealtime) {
if (aDriverRequested == AUDIO_THREAD_DRIVER) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this);

View File

@ -35,7 +35,7 @@ class nsAutoRefTraits<SpeexResamplerState> : public nsPointerRefTraits<SpeexResa
namespace mozilla {
extern PRLogModuleInfo* gMediaStreamGraphLog;
extern LazyLogModule gMediaStreamGraphLog;
namespace dom {
enum class AudioContextOperation;

View File

@ -18,7 +18,7 @@
namespace mozilla {
extern PRLogModuleInfo* gMediaTimerLog;
extern LazyLogModule gMediaTimerLog;
#define TIMER_LOG(x, ...) \
MOZ_ASSERT(gMediaTimerLog); \

View File

@ -21,7 +21,7 @@
using namespace mozilla::net;
using namespace mozilla::media;
PRLogModuleInfo* gRtspMediaResourceLog;
mozilla::LazyLogModule gRtspMediaResourceLog("RtspMediaResource");
#define RTSP_LOG(msg, ...) MOZ_LOG(gRtspMediaResourceLog, mozilla::LogLevel::Debug, \
(msg, ##__VA_ARGS__))
// Debug logging macro with object pointer and class name.
@ -505,9 +505,6 @@ RtspMediaResource::RtspMediaResource(MediaResourceCallback* aCallback,
MOZ_ASSERT(mMediaStreamController);
mListener = new Listener(this);
mMediaStreamController->AsyncOpen(mListener);
if (!gRtspMediaResourceLog) {
gRtspMediaResourceLog = PR_NewLogModule("RtspMediaResource");
}
#endif
}
@ -860,7 +857,7 @@ nsresult RtspMediaResource::SeekTime(int64_t aOffset)
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
RTSPMLOG("Seek requested for aOffset [%lld] for decoder [%p]",
aOffset, mCallback);
aOffset, mCallback.get());
// Clear buffer and raise the frametype flag.
for(uint32_t i = 0 ; i < mTrackBuffer.Length(); ++i) {
mTrackBuffer[i]->ResetWithFrameType(MEDIASTREAM_FRAMETYPE_DISCONTINUITY);

View File

@ -9,7 +9,7 @@
namespace mozilla {
extern PRLogModuleInfo* gMediaStreamGraphLog;
extern LazyLogModule gMediaStreamGraphLog;
#define STREAM_LOG(type, msg) MOZ_LOG(gMediaStreamGraphLog, type, msg)
#ifdef DEBUG

View File

@ -42,15 +42,12 @@ namespace mozilla {
#undef STREAM_LOG
#endif
PRLogModuleInfo* gTrackUnionStreamLog;
LazyLogModule gTrackUnionStreamLog("TrackUnionStream");
#define STREAM_LOG(type, msg) MOZ_LOG(gTrackUnionStreamLog, type, msg)
TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
ProcessedMediaStream(aWrapper), mNextAvailableTrackID(1)
{
if (!gTrackUnionStreamLog) {
gTrackUnionStreamLog = PR_NewLogModule("TrackUnionStream");
}
}
void TrackUnionStream::RemoveInput(MediaInputPort* aPort)

View File

@ -28,16 +28,13 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebVTTListener)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebVTTListener)
PRLogModuleInfo* gTextTrackLog;
LazyLogModule gTextTrackLog("TextTrack");
# define VTT_LOG(...) MOZ_LOG(gTextTrackLog, LogLevel::Debug, (__VA_ARGS__))
WebVTTListener::WebVTTListener(HTMLTrackElement* aElement)
: mElement(aElement)
{
MOZ_ASSERT(mElement, "Must pass an element to the callback");
if (!gTextTrackLog) {
gTextTrackLog = PR_NewLogModule("TextTrack");
}
VTT_LOG("WebVTTListener created.");
}

View File

@ -23,7 +23,7 @@ using namespace mozilla::media;
namespace mozilla {
extern PRLogModuleInfo* gMediaDecoderLog;
extern LazyLogModule gMediaDecoderLog;
#define LOGE(...) MOZ_LOG(gMediaDecoderLog, mozilla::LogLevel::Error, (__VA_ARGS__))
#define LOGW(...) MOZ_LOG(gMediaDecoderLog, mozilla::LogLevel::Warning, (__VA_ARGS__))
#define LOGD(...) MOZ_LOG(gMediaDecoderLog, mozilla::LogLevel::Debug, (__VA_ARGS__))

View File

@ -23,7 +23,7 @@ using namespace mozilla::media;
namespace mozilla {
PRLogModuleInfo* GetDirectShowLog();
extern LogModule* GetDirectShowLog();
#define LOG(...) MOZ_LOG(GetDirectShowLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
AudioSinkFilter::AudioSinkFilter(const wchar_t* aObjectName, HRESULT* aOutResult)

View File

@ -15,7 +15,7 @@ using namespace mozilla::media;
namespace mozilla {
PRLogModuleInfo* GetDirectShowLog();
extern LogModule* GetDirectShowLog();
#define LOG(...) MOZ_LOG(GetDirectShowLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
AudioSinkInputPin::AudioSinkInputPin(wchar_t* aObjectName,

View File

@ -18,13 +18,9 @@ using namespace mozilla::media;
namespace mozilla {
PRLogModuleInfo*
LogModule*
GetDirectShowLog() {
static PRLogModuleInfo* log = nullptr;
if (!log) {
log = PR_NewLogModule("DirectShowDecoder");
}
static LazyLogModule log("DirectShowDecoder");
return log;
}

View File

@ -14,7 +14,7 @@ using namespace mozilla::media;
namespace mozilla {
PRLogModuleInfo* GetDirectShowLog();
extern LogModule* GetDirectShowLog();
#define LOG(...) MOZ_LOG(GetDirectShowLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
SampleSink::SampleSink()

View File

@ -20,7 +20,7 @@ namespace mozilla {
//#define DEBUG_SOURCE_TRACE 1
#if defined (DEBUG_SOURCE_TRACE)
PRLogModuleInfo* GetDirectShowLog();
extern LogModule* GetDirectShowLog();
#define DIRECTSHOW_LOG(...) MOZ_LOG(GetDirectShowLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
#else
#define DIRECTSHOW_LOG(...)

View File

@ -8,19 +8,13 @@
namespace mozilla {
PRLogModuleInfo* GetEMELog() {
static PRLogModuleInfo* log = nullptr;
if (!log) {
log = PR_NewLogModule("EME");
}
LogModule* GetEMELog() {
static LazyLogModule log("EME");
return log;
}
PRLogModuleInfo* GetEMEVerboseLog() {
static PRLogModuleInfo* log = nullptr;
if (!log) {
log = PR_NewLogModule("EMEV");
}
LogModule* GetEMEVerboseLog() {
static LazyLogModule log("EMEV");
return log;
}

View File

@ -13,13 +13,13 @@
namespace mozilla {
#ifndef EME_LOG
PRLogModuleInfo* GetEMELog();
LogModule* GetEMELog();
#define EME_LOG(...) MOZ_LOG(GetEMELog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
#define EME_LOG_ENABLED() MOZ_LOG_TEST(GetEMELog(), mozilla::LogLevel::Debug)
#endif
#ifndef EME_VERBOSE_LOG
PRLogModuleInfo* GetEMEVerboseLog();
LogModule* GetEMEVerboseLog();
#define EME_VERBOSE_LOG(...) MOZ_LOG(GetEMEVerboseLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
#else
#ifndef EME_LOG

View File

@ -31,7 +31,7 @@
#undef LOG
#endif
PRLogModuleInfo* gMediaEncoderLog;
mozilla::LazyLogModule gMediaEncoderLog("MediaEncoder");
#define LOG(type, msg) MOZ_LOG(gMediaEncoderLog, type, msg)
namespace mozilla {
@ -79,9 +79,6 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint32_t aAudioBitrate,
uint32_t aVideoBitrate, uint32_t aBitrate,
uint8_t aTrackTypes)
{
if (!gMediaEncoderLog) {
gMediaEncoderLog = PR_NewLogModule("MediaEncoder");
}
PROFILER_LABEL("MediaEncoder", "CreateEncoder",
js::ProfileEntry::Category::OTHER);

View File

@ -18,7 +18,7 @@
namespace mozilla {
PRLogModuleInfo* gTrackEncoderLog;
LazyLogModule gTrackEncoderLog("TrackEncoder");
#define TRACK_LOG(type, msg) MOZ_LOG(gTrackEncoderLog, type, msg)
static const int DEFAULT_CHANNELS = 1;
@ -37,9 +37,6 @@ TrackEncoder::TrackEncoder()
, mAudioInitCounter(0)
, mVideoInitCounter(0)
{
if (!gTrackEncoderLog) {
gTrackEncoderLog = PR_NewLogModule("TrackEncoder");
}
}
void

View File

@ -17,7 +17,7 @@
namespace mozilla {
PRLogModuleInfo* gVP8TrackEncoderLog;
LazyLogModule gVP8TrackEncoderLog("VP8TrackEncoder");
#define VP8LOG(msg, ...) MOZ_LOG(gVP8TrackEncoderLog, mozilla::LogLevel::Debug, \
(msg, ##__VA_ARGS__))
// Debug logging macro with object pointer and class name.
@ -37,9 +37,6 @@ VP8TrackEncoder::VP8TrackEncoder()
, mVPXImageWrapper(new vpx_image_t())
{
MOZ_COUNT_CTOR(VP8TrackEncoder);
if (!gVP8TrackEncoderLog) {
gVP8TrackEncoderLog = PR_NewLogModule("VP8TrackEncoder");
}
}
VP8TrackEncoder::~VP8TrackEncoder()

View File

@ -17,7 +17,7 @@ static const float BASE_QUALITY = 0.4f;
namespace mozilla {
#undef LOG
PRLogModuleInfo* gVorbisTrackEncoderLog;
LazyLogModule gVorbisTrackEncoderLog("VorbisTrackEncoder");
#define VORBISLOG(msg, ...) MOZ_LOG(gVorbisTrackEncoderLog, mozilla::LogLevel::Debug, \
(msg, ##__VA_ARGS__))
@ -25,9 +25,6 @@ VorbisTrackEncoder::VorbisTrackEncoder()
: AudioTrackEncoder()
{
MOZ_COUNT_CTOR(VorbisTrackEncoder);
if (!gVorbisTrackEncoderLog) {
gVorbisTrackEncoderLog = PR_NewLogModule("VorbisTrackEncoder");
}
}
VorbisTrackEncoder::~VorbisTrackEncoder()

View File

@ -20,11 +20,8 @@
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
PRLogModuleInfo* GetDemuxerLog() {
static PRLogModuleInfo* log = nullptr;
if (!log) {
log = PR_NewLogModule("MP4Demuxer");
}
mozilla::LogModule* GetDemuxerLog() {
static mozilla::LazyLogModule log("MP4Demuxer");
return log;
}

View File

@ -17,7 +17,7 @@ namespace mozilla {
#undef LOG
#endif
extern PRLogModuleInfo* GetGMPLog();
extern LogModule* GetGMPLog();
#define LOGV(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Verbose, msg)
#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)

View File

@ -43,7 +43,7 @@ namespace mozilla {
#undef LOG
#undef LOGD
extern PRLogModuleInfo* GetGMPLog();
extern LogModule* GetGMPLog();
#define LOG(level, x, ...) MOZ_LOG(GetGMPLog(), (level), (x, ##__VA_ARGS__))
#define LOGD(x, ...) LOG(mozilla::LogLevel::Debug, "GMPChild[pid=%d] " x, (int)base::GetCurrentProcId(), ##__VA_ARGS__)

View File

@ -20,7 +20,7 @@ namespace mozilla {
#undef LOG
#endif
extern PRLogModuleInfo* GetGMPLog();
extern LogModule* GetGMPLog();
#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)
#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg)

View File

@ -14,7 +14,7 @@ namespace mozilla {
#undef LOG
#endif
extern PRLogModuleInfo* GetGMPLog();
extern LogModule* GetGMPLog();
#define LOGV(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Verbose, msg)
#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)

View File

@ -43,7 +43,7 @@ namespace mozilla {
#undef LOG
#undef LOGD
extern PRLogModuleInfo* GetGMPLog();
extern LogModule* GetGMPLog();
#define LOG(level, x, ...) MOZ_LOG(GetGMPLog(), (level), (x, ##__VA_ARGS__))
#define LOGD(x, ...) LOG(mozilla::LogLevel::Debug, "GMPParent[%p|childPid=%d] " x, this, mChildPid, ##__VA_ARGS__)

View File

@ -46,12 +46,10 @@ namespace mozilla {
#undef LOG
#endif
PRLogModuleInfo*
LogModule*
GetGMPLog()
{
static PRLogModuleInfo *sLog;
if (!sLog)
sLog = PR_NewLogModule("GMP");
static LazyLogModule sLog("GMP");
return sLog;
}

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