зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c a=merge
This commit is contained in:
Коммит
8cc1c6b2ac
|
@ -12,9 +12,6 @@ Cu.import("resource://gre/modules/FxAccounts.jsm");
|
||||||
let fxAccountsCommon = {};
|
let fxAccountsCommon = {};
|
||||||
Cu.import("resource://gre/modules/FxAccountsCommon.js", fxAccountsCommon);
|
Cu.import("resource://gre/modules/FxAccountsCommon.js", fxAccountsCommon);
|
||||||
|
|
||||||
// for master-password utilities
|
|
||||||
Cu.import("resource://services-sync/util.js");
|
|
||||||
|
|
||||||
const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
|
const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
|
||||||
const PREF_SYNC_SHOW_CUSTOMIZATION = "services.sync.ui.showCustomizationDialog";
|
const PREF_SYNC_SHOW_CUSTOMIZATION = "services.sync.ui.showCustomizationDialog";
|
||||||
|
|
||||||
|
@ -107,12 +104,6 @@ let wrapper = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a master-password is enabled, we want to encourage the user to
|
|
||||||
// unlock it. Things still work if not, but the user will probably need
|
|
||||||
// to re-auth next startup (in which case we will get here again and
|
|
||||||
// re-prompt)
|
|
||||||
Utils.ensureMPUnlocked();
|
|
||||||
|
|
||||||
let iframe = document.getElementById("remote");
|
let iframe = document.getElementById("remote");
|
||||||
this.iframe = iframe;
|
this.iframe = iframe;
|
||||||
iframe.addEventListener("load", this);
|
iframe.addEventListener("load", this);
|
||||||
|
|
|
@ -4,6 +4,20 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
let service = Cc["@mozilla.org/weave/service;1"]
|
||||||
|
.getService(Ci.nsISupports)
|
||||||
|
.wrappedJSObject;
|
||||||
|
|
||||||
|
if (!service.allowPasswordsEngine) {
|
||||||
|
let checkbox = document.getElementById("fxa-pweng-chk");
|
||||||
|
checkbox.checked = false;
|
||||||
|
checkbox.disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
addEventListener("dialogaccept", function () {
|
addEventListener("dialogaccept", function () {
|
||||||
let pane = document.getElementById("sync-customize-pane");
|
let pane = document.getElementById("sync-customize-pane");
|
||||||
pane.writePreferences(true);
|
pane.writePreferences(true);
|
||||||
|
|
|
@ -45,7 +45,8 @@
|
||||||
<checkbox label="&engine.bookmarks.label;"
|
<checkbox label="&engine.bookmarks.label;"
|
||||||
accesskey="&engine.bookmarks.accesskey;"
|
accesskey="&engine.bookmarks.accesskey;"
|
||||||
preference="engine.bookmarks"/>
|
preference="engine.bookmarks"/>
|
||||||
<checkbox label="&engine.passwords.label;"
|
<checkbox id="fxa-pweng-chk"
|
||||||
|
label="&engine.passwords.label;"
|
||||||
accesskey="&engine.passwords.accesskey;"
|
accesskey="&engine.passwords.accesskey;"
|
||||||
preference="engine.passwords"/>
|
preference="engine.passwords"/>
|
||||||
<checkbox label="&engine.history.label;"
|
<checkbox label="&engine.history.label;"
|
||||||
|
|
|
@ -87,6 +87,12 @@ let gSyncUtils = {
|
||||||
this._openLink(Weave.Svc.Prefs.get(root + "privacyURL"));
|
this._openLink(Weave.Svc.Prefs.get(root + "privacyURL"));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
openMPInfoPage: function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
|
||||||
|
this._openLink(baseURL + "sync-master-password");
|
||||||
|
},
|
||||||
|
|
||||||
openFirstSyncProgressPage: function () {
|
openFirstSyncProgressPage: function () {
|
||||||
this._openLink("about:sync-progress");
|
this._openLink("about:sync-progress");
|
||||||
},
|
},
|
||||||
|
|
|
@ -154,6 +154,17 @@ let gSyncPane = {
|
||||||
for (let checkbox of engines.querySelectorAll("checkbox")) {
|
for (let checkbox of engines.querySelectorAll("checkbox")) {
|
||||||
checkbox.disabled = enginesListDisabled;
|
checkbox.disabled = enginesListDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let checkbox = document.getElementById("fxa-pweng-chk");
|
||||||
|
let help = document.getElementById("fxa-pweng-help");
|
||||||
|
let allowPasswordsEngine = service.allowPasswordsEngine;
|
||||||
|
|
||||||
|
if (!allowPasswordsEngine) {
|
||||||
|
checkbox.checked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox.disabled = !allowPasswordsEngine || enginesListDisabled;
|
||||||
|
help.hidden = allowPasswordsEngine || enginesListDisabled;
|
||||||
});
|
});
|
||||||
// If fxAccountEnabled is false and we are in a "not configured" state,
|
// If fxAccountEnabled is false and we are in a "not configured" state,
|
||||||
// then fxAccounts is probably fully disabled rather than just unconfigured,
|
// then fxAccounts is probably fully disabled rather than just unconfigured,
|
||||||
|
|
|
@ -283,9 +283,20 @@
|
||||||
<checkbox label="&engine.bookmarks.label;"
|
<checkbox label="&engine.bookmarks.label;"
|
||||||
accesskey="&engine.bookmarks.accesskey;"
|
accesskey="&engine.bookmarks.accesskey;"
|
||||||
preference="engine.bookmarks"/>
|
preference="engine.bookmarks"/>
|
||||||
<checkbox label="&engine.passwords.label;"
|
<hbox>
|
||||||
|
<checkbox id="fxa-pweng-chk"
|
||||||
|
label="&engine.passwords.label;"
|
||||||
accesskey="&engine.passwords.accesskey;"
|
accesskey="&engine.passwords.accesskey;"
|
||||||
preference="engine.passwords"/>
|
preference="engine.passwords"/>
|
||||||
|
|
||||||
|
<vbox id="fxa-pweng-help">
|
||||||
|
<spacer flex="1"/>
|
||||||
|
<hbox id="fxa-pweng-help-link">
|
||||||
|
<image onclick="gSyncUtils.openMPInfoPage(event);" />
|
||||||
|
</hbox>
|
||||||
|
<spacer flex="1"/>
|
||||||
|
</vbox>
|
||||||
|
</hbox>
|
||||||
<checkbox label="&engine.history.label;"
|
<checkbox label="&engine.history.label;"
|
||||||
accesskey="&engine.history.accesskey;"
|
accesskey="&engine.history.accesskey;"
|
||||||
preference="engine.history"/>
|
preference="engine.history"/>
|
||||||
|
|
|
@ -154,6 +154,17 @@ let gSyncPane = {
|
||||||
for (let checkbox of engines.querySelectorAll("checkbox")) {
|
for (let checkbox of engines.querySelectorAll("checkbox")) {
|
||||||
checkbox.disabled = enginesListDisabled;
|
checkbox.disabled = enginesListDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let checkbox = document.getElementById("fxa-pweng-chk");
|
||||||
|
let help = document.getElementById("fxa-pweng-help");
|
||||||
|
let allowPasswordsEngine = service.allowPasswordsEngine;
|
||||||
|
|
||||||
|
if (!allowPasswordsEngine) {
|
||||||
|
checkbox.checked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox.disabled = !allowPasswordsEngine || enginesListDisabled;
|
||||||
|
help.hidden = allowPasswordsEngine || enginesListDisabled;
|
||||||
});
|
});
|
||||||
// If fxAccountEnabled is false and we are in a "not configured" state,
|
// If fxAccountEnabled is false and we are in a "not configured" state,
|
||||||
// then fxAccounts is probably fully disabled rather than just unconfigured,
|
// then fxAccounts is probably fully disabled rather than just unconfigured,
|
||||||
|
|
|
@ -265,9 +265,20 @@
|
||||||
<checkbox label="&engine.bookmarks.label;"
|
<checkbox label="&engine.bookmarks.label;"
|
||||||
accesskey="&engine.bookmarks.accesskey;"
|
accesskey="&engine.bookmarks.accesskey;"
|
||||||
preference="engine.bookmarks"/>
|
preference="engine.bookmarks"/>
|
||||||
<checkbox label="&engine.passwords.label;"
|
<hbox>
|
||||||
|
<checkbox id="fxa-pweng-chk"
|
||||||
|
label="&engine.passwords.label;"
|
||||||
accesskey="&engine.passwords.accesskey;"
|
accesskey="&engine.passwords.accesskey;"
|
||||||
preference="engine.passwords"/>
|
preference="engine.passwords"/>
|
||||||
|
|
||||||
|
<vbox id="fxa-pweng-help">
|
||||||
|
<spacer flex="1"/>
|
||||||
|
<hbox id="fxa-pweng-help-link">
|
||||||
|
<image onclick="gSyncUtils.openMPInfoPage(event);" />
|
||||||
|
</hbox>
|
||||||
|
<spacer flex="1"/>
|
||||||
|
</vbox>
|
||||||
|
</hbox>
|
||||||
<checkbox label="&engine.history.label;"
|
<checkbox label="&engine.history.label;"
|
||||||
accesskey="&engine.history.accesskey;"
|
accesskey="&engine.history.accesskey;"
|
||||||
preference="engine.history"/>
|
preference="engine.history"/>
|
||||||
|
|
|
@ -171,4 +171,12 @@ label.small {
|
||||||
margin-bottom: 0.6em;
|
margin-bottom: 0.6em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fxa-pweng-help-link > label {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fxa-pweng-help-link > image {
|
||||||
|
list-style-image: url("chrome://global/skin/icons/question-16.png");
|
||||||
|
}
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
|
|
|
@ -233,4 +233,20 @@ html|a.inline-link:-moz-focusring {
|
||||||
margin-bottom: 0.6em;
|
margin-bottom: 0.6em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fxa-pweng-help-link > label {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fxa-pweng-help-link > image {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
list-style-image: url("chrome://global/skin/icons/question-16.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-resolution: 2dppx) {
|
||||||
|
#fxa-pweng-help-link > image {
|
||||||
|
list-style-image: url("chrome://global/skin/icons/question-32.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
|
|
|
@ -161,4 +161,12 @@ label.small {
|
||||||
margin-bottom: 0.6em;
|
margin-bottom: 0.6em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fxa-pweng-help-link > label {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fxa-pweng-help-link > image {
|
||||||
|
list-style-image: url("chrome://global/skin/icons/question-16.png");
|
||||||
|
}
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
#include "mozilla/dom/TreeWalker.h"
|
#include "mozilla/dom/TreeWalker.h"
|
||||||
|
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
|
#include "nsIServiceWorkerManager.h"
|
||||||
|
|
||||||
#include "nsContentCID.h"
|
#include "nsContentCID.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
|
@ -4465,6 +4466,24 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
||||||
if (mTemplateContentsOwner && mTemplateContentsOwner != this) {
|
if (mTemplateContentsOwner && mTemplateContentsOwner != this) {
|
||||||
mTemplateContentsOwner->SetScriptGlobalObject(aScriptGlobalObject);
|
mTemplateContentsOwner->SetScriptGlobalObject(aScriptGlobalObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIChannel> channel = GetChannel();
|
||||||
|
if (!mMaybeServiceWorkerControlled && channel) {
|
||||||
|
nsLoadFlags loadFlags = 0;
|
||||||
|
channel->GetLoadFlags(&loadFlags);
|
||||||
|
// If we are shift-reloaded, don't associate with a ServiceWorker.
|
||||||
|
// FIXME(nsm): Bug 1041339.
|
||||||
|
if (loadFlags & nsIRequest::LOAD_BYPASS_CACHE) {
|
||||||
|
NS_WARNING("Page was shift reloaded, skipping ServiceWorker control");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||||
|
if (swm) {
|
||||||
|
swm->MaybeStartControlling(this);
|
||||||
|
mMaybeServiceWorkerControlled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIScriptGlobalObject*
|
nsIScriptGlobalObject*
|
||||||
|
@ -8483,6 +8502,11 @@ nsDocument::Destroy()
|
||||||
|
|
||||||
mRegistry = nullptr;
|
mRegistry = nullptr;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||||
|
if (swm) {
|
||||||
|
swm->MaybeStopControlling(this);
|
||||||
|
}
|
||||||
|
|
||||||
// XXX We really should let cycle collection do this, but that currently still
|
// XXX We really should let cycle collection do this, but that currently still
|
||||||
// leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
|
// leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
|
||||||
ReleaseWrapper(static_cast<nsINode*>(this));
|
ReleaseWrapper(static_cast<nsINode*>(this));
|
||||||
|
|
|
@ -1742,6 +1742,10 @@ private:
|
||||||
nsCOMPtr<nsIDocument> mMasterDocument;
|
nsCOMPtr<nsIDocument> mMasterDocument;
|
||||||
nsRefPtr<mozilla::dom::ImportManager> mImportManager;
|
nsRefPtr<mozilla::dom::ImportManager> mImportManager;
|
||||||
|
|
||||||
|
// Set to true when the document is possibly controlled by the ServiceWorker.
|
||||||
|
// Used to prevent multiple requests to ServiceWorkerManager.
|
||||||
|
bool mMaybeServiceWorkerControlled;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
public:
|
public:
|
||||||
bool mWillReparent;
|
bool mWillReparent;
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "nsJSNPRuntime.h"
|
#include "nsJSNPRuntime.h"
|
||||||
#include "nsINestedURI.h"
|
#include "nsINestedURI.h"
|
||||||
#include "nsIPresShell.h"
|
#include "nsIPresShell.h"
|
||||||
#include "nsIScriptGlobalObject.h"
|
|
||||||
#include "nsScriptSecurityManager.h"
|
#include "nsScriptSecurityManager.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
#include "nsIScriptSecurityManager.h"
|
||||||
#include "nsIStreamConverterService.h"
|
#include "nsIStreamConverterService.h"
|
||||||
|
@ -80,6 +79,7 @@
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/Event.h"
|
#include "mozilla/dom/Event.h"
|
||||||
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "mozilla/EventDispatcher.h"
|
#include "mozilla/EventDispatcher.h"
|
||||||
#include "mozilla/EventStates.h"
|
#include "mozilla/EventStates.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
@ -2914,21 +2914,9 @@ nsObjectLoadingContent::NotifyContentObjectWrapper()
|
||||||
nsCOMPtr<nsIContent> thisContent =
|
nsCOMPtr<nsIContent> thisContent =
|
||||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> doc = thisContent->GetDocument();
|
AutoJSAPI jsapi;
|
||||||
if (!doc)
|
jsapi.Init();
|
||||||
return;
|
JSContext* cx = jsapi.cx();
|
||||||
|
|
||||||
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(doc->GetScopeObject());
|
|
||||||
if (!sgo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nsIScriptContext *scx = sgo->GetContext();
|
|
||||||
if (!scx)
|
|
||||||
return;
|
|
||||||
|
|
||||||
JSContext *cx = scx->GetNativeContext();
|
|
||||||
nsCxPusher pusher;
|
|
||||||
pusher.Push(cx);
|
|
||||||
|
|
||||||
JS::Rooted<JSObject*> obj(cx, thisContent->GetWrapper());
|
JS::Rooted<JSObject*> obj(cx, thisContent->GetWrapper());
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
|
@ -3297,12 +3285,7 @@ nsObjectLoadingContent::SetupProtoChain(JSContext* aCx,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nsContentUtils::IsSafeToRunScript()) {
|
if (!nsContentUtils::IsSafeToRunScript()) {
|
||||||
// This may be null if the JS context is not a DOM context. That's ok, we'll
|
nsRefPtr<SetupProtoChainRunner> runner = new SetupProtoChainRunner(this);
|
||||||
// use the safe context from XPConnect in the runnable.
|
|
||||||
nsCOMPtr<nsIScriptContext> scriptContext = GetScriptContextFromJSContext(aCx);
|
|
||||||
|
|
||||||
nsRefPtr<SetupProtoChainRunner> runner =
|
|
||||||
new SetupProtoChainRunner(scriptContext, this);
|
|
||||||
nsContentUtils::AddScriptRunner(runner);
|
nsContentUtils::AddScriptRunner(runner);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3510,10 +3493,8 @@ nsObjectLoadingContent::GetOwnPropertyNames(JSContext* aCx,
|
||||||
|
|
||||||
// SetupProtoChainRunner implementation
|
// SetupProtoChainRunner implementation
|
||||||
nsObjectLoadingContent::SetupProtoChainRunner::SetupProtoChainRunner(
|
nsObjectLoadingContent::SetupProtoChainRunner::SetupProtoChainRunner(
|
||||||
nsIScriptContext* scriptContext,
|
|
||||||
nsObjectLoadingContent* aContent)
|
nsObjectLoadingContent* aContent)
|
||||||
: mContext(scriptContext)
|
: mContent(aContent)
|
||||||
, mContent(aContent)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3524,12 +3505,9 @@ nsObjectLoadingContent::SetupProtoChainRunner::~SetupProtoChainRunner()
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsObjectLoadingContent::SetupProtoChainRunner::Run()
|
nsObjectLoadingContent::SetupProtoChainRunner::Run()
|
||||||
{
|
{
|
||||||
// XXXbz Does it really matter what JSContext we use here? Seems
|
AutoJSAPI jsapi;
|
||||||
// like we could just always use the safe context....
|
jsapi.Init();
|
||||||
nsCxPusher pusher;
|
JSContext* cx = jsapi.cx();
|
||||||
JSContext* cx = mContext ? mContext->GetNativeContext()
|
|
||||||
: nsContentUtils::GetSafeJSContext();
|
|
||||||
pusher.Push(cx);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> content;
|
nsCOMPtr<nsIContent> content;
|
||||||
CallQueryInterface(mContent.get(), getter_AddRefs(content));
|
CallQueryInterface(mContent.get(), getter_AddRefs(content));
|
||||||
|
|
|
@ -477,13 +477,11 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
SetupProtoChainRunner(nsIScriptContext* scriptContext,
|
SetupProtoChainRunner(nsObjectLoadingContent* aContent);
|
||||||
nsObjectLoadingContent* aContent);
|
|
||||||
|
|
||||||
NS_IMETHOD Run() MOZ_OVERRIDE;
|
NS_IMETHOD Run() MOZ_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIScriptContext> mContext;
|
|
||||||
// We store an nsIObjectLoadingContent because we can
|
// We store an nsIObjectLoadingContent because we can
|
||||||
// unambiguously refcount that.
|
// unambiguously refcount that.
|
||||||
nsRefPtr<nsIObjectLoadingContent> mContent;
|
nsRefPtr<nsIObjectLoadingContent> mContent;
|
||||||
|
|
|
@ -21,20 +21,7 @@ SOURCES += [
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['MOZ_WMF']:
|
if CONFIG['MOZ_WMF']:
|
||||||
EXPORTS += [
|
PARALLEL_DIRS += [ 'wmf' ];
|
||||||
'wmf/MFTDecoder.h',
|
|
||||||
'wmf/WMFAudioMFTManager.h',
|
|
||||||
'wmf/WMFDecoderModule.h',
|
|
||||||
'wmf/WMFMediaDataDecoder.h',
|
|
||||||
'wmf/WMFVideoMFTManager.h',
|
|
||||||
]
|
|
||||||
UNIFIED_SOURCES += [
|
|
||||||
'wmf/MFTDecoder.cpp',
|
|
||||||
'wmf/WMFAudioMFTManager.cpp',
|
|
||||||
'wmf/WMFDecoderModule.cpp',
|
|
||||||
'wmf/WMFMediaDataDecoder.cpp',
|
|
||||||
'wmf/WMFVideoMFTManager.cpp',
|
|
||||||
]
|
|
||||||
|
|
||||||
if CONFIG['MOZ_FFMPEG']:
|
if CONFIG['MOZ_FFMPEG']:
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
|
|
|
@ -133,7 +133,7 @@ MFTDecoder::CreateInputSample(const uint8_t* aData,
|
||||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||||
|
|
||||||
RefPtr<IMFMediaBuffer> buffer;
|
RefPtr<IMFMediaBuffer> buffer;
|
||||||
int32_t bufferSize = std::max(uint32_t(mInputStreamInfo.cbSize), aDataSize);
|
int32_t bufferSize = std::max<uint32_t>(uint32_t(mInputStreamInfo.cbSize), aDataSize);
|
||||||
UINT32 alignment = (mInputStreamInfo.cbAlignment > 1) ? mInputStreamInfo.cbAlignment - 1 : 0;
|
UINT32 alignment = (mInputStreamInfo.cbAlignment > 1) ? mInputStreamInfo.cbAlignment - 1 : 0;
|
||||||
hr = wmf::MFCreateAlignedMemoryBuffer(bufferSize, alignment, byRef(buffer));
|
hr = wmf::MFCreateAlignedMemoryBuffer(bufferSize, alignment, byRef(buffer));
|
||||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
EXPORTS += [
|
||||||
|
'MFTDecoder.h',
|
||||||
|
'WMFAudioMFTManager.h',
|
||||||
|
'WMFDecoderModule.h',
|
||||||
|
'WMFMediaDataDecoder.h',
|
||||||
|
'WMFVideoMFTManager.h',
|
||||||
|
]
|
||||||
|
UNIFIED_SOURCES += [
|
||||||
|
'MFTDecoder.cpp',
|
||||||
|
'WMFAudioMFTManager.cpp',
|
||||||
|
'WMFDecoderModule.cpp',
|
||||||
|
'WMFMediaDataDecoder.cpp',
|
||||||
|
'WMFVideoMFTManager.cpp',
|
||||||
|
]
|
||||||
|
|
||||||
|
FINAL_LIBRARY = 'gklayout'
|
||||||
|
|
||||||
|
FAIL_ON_WARNINGS = True
|
|
@ -14,6 +14,8 @@
|
||||||
#include "nsIRunnable.h"
|
#include "nsIRunnable.h"
|
||||||
#include "mozIGeckoMediaPluginService.h"
|
#include "mozIGeckoMediaPluginService.h"
|
||||||
#include "mozilla/unused.h"
|
#include "mozilla/unused.h"
|
||||||
|
#include "nsIObserverService.h"
|
||||||
|
#include "mtransport/runnable_utils.h"
|
||||||
|
|
||||||
#include "mozilla/dom/CrashReporterParent.h"
|
#include "mozilla/dom/CrashReporterParent.h"
|
||||||
using mozilla::dom::CrashReporterParent;
|
using mozilla::dom::CrashReporterParent;
|
||||||
|
@ -321,16 +323,37 @@ GMPParent::GetCrashID(nsString& aResult)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
GMPNotifyObservers(nsAString& aData)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||||
|
if (obs) {
|
||||||
|
nsString temp(aData);
|
||||||
|
obs->NotifyObservers(nullptr, "gmp-plugin-crash", temp.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GMPParent::ActorDestroy(ActorDestroyReason aWhy)
|
GMPParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||||
{
|
{
|
||||||
|
#ifdef MOZ_CRASHREPORTER
|
||||||
if (AbnormalShutdown == aWhy) {
|
if (AbnormalShutdown == aWhy) {
|
||||||
nsString dumpID;
|
nsString dumpID;
|
||||||
#ifdef MOZ_CRASHREPORTER
|
|
||||||
GetCrashID(dumpID);
|
GetCrashID(dumpID);
|
||||||
#endif
|
nsString id;
|
||||||
// now do something with the crash ID, bug 1038961
|
// use the parent address to identify it
|
||||||
|
// We could use any unique-to-the-parent value
|
||||||
|
id.AppendInt(reinterpret_cast<uint64_t>(this));
|
||||||
|
id.Append(NS_LITERAL_STRING(" "));
|
||||||
|
AppendUTF8toUTF16(mDisplayName, id);
|
||||||
|
id.Append(NS_LITERAL_STRING(" "));
|
||||||
|
id.Append(dumpID);
|
||||||
|
|
||||||
|
// NotifyObservers is mainthread-only
|
||||||
|
NS_DispatchToMainThread(WrapRunnableNM(&GMPNotifyObservers, id),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// warn us off trying to close again
|
// warn us off trying to close again
|
||||||
mState = GMPStateClosing;
|
mState = GMPStateClosing;
|
||||||
CloseActive();
|
CloseActive();
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
virtual nsresult Reset() MOZ_OVERRIDE;
|
virtual nsresult Reset() MOZ_OVERRIDE;
|
||||||
virtual nsresult Drain() MOZ_OVERRIDE;
|
virtual nsresult Drain() MOZ_OVERRIDE;
|
||||||
virtual nsresult DecodingComplete() MOZ_OVERRIDE;
|
virtual nsresult DecodingComplete() MOZ_OVERRIDE;
|
||||||
|
virtual const uint64_t ParentID() MOZ_OVERRIDE { return reinterpret_cast<uint64_t>(mPlugin.get()); }
|
||||||
|
|
||||||
// GMPSharedMemManager
|
// GMPSharedMemManager
|
||||||
virtual void CheckThread();
|
virtual void CheckThread();
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
virtual nsresult Reset() = 0;
|
virtual nsresult Reset() = 0;
|
||||||
virtual nsresult Drain() = 0;
|
virtual nsresult Drain() = 0;
|
||||||
virtual nsresult DecodingComplete() = 0;
|
virtual nsresult DecodingComplete() = 0;
|
||||||
|
virtual const uint64_t ParentID() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) MOZ_OVERRIDE;
|
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) MOZ_OVERRIDE;
|
||||||
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) MOZ_OVERRIDE;
|
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) MOZ_OVERRIDE;
|
||||||
virtual void EncodingComplete() MOZ_OVERRIDE;
|
virtual void EncodingComplete() MOZ_OVERRIDE;
|
||||||
|
virtual const uint64_t ParentID() MOZ_OVERRIDE { return reinterpret_cast<uint64_t>(mPlugin.get()); }
|
||||||
|
|
||||||
// GMPSharedMemManager
|
// GMPSharedMemManager
|
||||||
virtual void CheckThread();
|
virtual void CheckThread();
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
|
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
|
||||||
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 0;
|
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 0;
|
||||||
virtual void EncodingComplete() = 0;
|
virtual void EncodingComplete() = 0;
|
||||||
|
virtual const uint64_t ParentID() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GMPVideoEncoderProxy_h_
|
#endif // GMPVideoEncoderProxy_h_
|
||||||
|
|
|
@ -381,7 +381,8 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' # mimetype check, bug 969289
|
||||||
[test_mediarecorder_unsupported_src.html]
|
[test_mediarecorder_unsupported_src.html]
|
||||||
[test_mediarecorder_record_getdata_afterstart.html]
|
[test_mediarecorder_record_getdata_afterstart.html]
|
||||||
[test_mediatrack_consuming_mediaresource.html]
|
[test_mediatrack_consuming_mediaresource.html]
|
||||||
[test_mediatrack_events_and_consuming_ms.html]
|
[test_mediatrack_consuming_mediastream.html]
|
||||||
|
[test_mediatrack_events.html]
|
||||||
[test_mediatrack_replay_from_end.html]
|
[test_mediatrack_replay_from_end.html]
|
||||||
[test_metadata.html]
|
[test_metadata.html]
|
||||||
[test_mixed_principals.html]
|
[test_mixed_principals.html]
|
||||||
|
@ -398,7 +399,6 @@ skip-if = true # bug 567954 and intermittent leaks
|
||||||
# Seamonkey: Bug 598252, B2G: Bug 982100, Android: Bug 758476, bug 981086
|
# Seamonkey: Bug 598252, B2G: Bug 982100, Android: Bug 758476, bug 981086
|
||||||
skip-if = appname == "seamonkey" || toolkit == 'gonk' || toolkit == 'android'
|
skip-if = appname == "seamonkey" || toolkit == 'gonk' || toolkit == 'android'
|
||||||
[test_playback.html]
|
[test_playback.html]
|
||||||
skip-if = buildapp == 'b2g' || toolkit == 'android' # Disabled on Android & B2G due to bug 668973
|
|
||||||
[test_playback_errors.html]
|
[test_playback_errors.html]
|
||||||
[test_playback_rate.html]
|
[test_playback_rate.html]
|
||||||
[test_playback_rate_playpause.html]
|
[test_playback_rate_playpause.html]
|
||||||
|
|
|
@ -23,7 +23,7 @@ function cloneLoaded(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
e.removeEventListener("loadeddata", cloneLoaded, false);
|
e.removeEventListener("loadeddata", cloneLoaded, false);
|
||||||
|
removeNodeAndSource(e);
|
||||||
manager.finished(e.token);
|
manager.finished(e.token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,17 @@ function tryClone(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
clone.addEventListener("loadeddata", cloneLoaded, false);
|
clone.addEventListener("loadeddata", cloneLoaded, false);
|
||||||
|
clone.onloadstart = function(evt) {
|
||||||
|
info("cloned " + evt.target.token + " start loading.");
|
||||||
|
evt.target.onloadstart = null;
|
||||||
|
// Since there is only one H264 decoder instance, we have to delete the
|
||||||
|
// decoder of the original element for the cloned element to load. However,
|
||||||
|
// we can't delete the decoder too early otherwise cloning decoder will
|
||||||
|
// fail to kick in. We wait for 'loadstart' event of the cloned element to
|
||||||
|
// know when the decoder is already cloned and we can delete the decoder of
|
||||||
|
// the original element.
|
||||||
|
removeNodeAndSource(e);
|
||||||
|
}
|
||||||
|
|
||||||
e.removeEventListener("loadeddata", tryClone, false);
|
e.removeEventListener("loadeddata", tryClone, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test track interfaces when consuming a MediaStream from gUM</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
<script type="text/javascript" src="manifest.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
function startTest() {
|
||||||
|
navigator.mozGetUserMedia({audio:true, video:true, fake:true},
|
||||||
|
function(stream) {
|
||||||
|
var element = document.createElement("video");
|
||||||
|
|
||||||
|
var audioOnchange = 0;
|
||||||
|
var audioOnaddtrack = 0;
|
||||||
|
var audioOnremovetrack = 0;
|
||||||
|
var videoOnchange = 0;
|
||||||
|
var videoOnaddtrack = 0;
|
||||||
|
var videoOnremovetrack = 0;
|
||||||
|
var isPlaying = false;
|
||||||
|
|
||||||
|
element.audioTracks.onaddtrack = function(e) {
|
||||||
|
audioOnaddtrack++;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.audioTracks.onremovetrack = function(e) {
|
||||||
|
audioOnremovetrack++;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.audioTracks.onchange = function(e) {
|
||||||
|
audioOnchange++;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.videoTracks.onaddtrack = function(e) {
|
||||||
|
videoOnaddtrack++;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.videoTracks.onremovetrack = function(e) {
|
||||||
|
videoOnremovetrack++;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.videoTracks.onchange = function(e) {
|
||||||
|
videoOnchange++;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkTrackRemoved() {
|
||||||
|
if (isPlaying) {
|
||||||
|
is(audioOnremovetrack, 1, 'Calls of onremovetrack on audioTracks should be 1.');
|
||||||
|
is(element.audioTracks.length, 0, 'The length of audioTracks should be 0.');
|
||||||
|
is(videoOnremovetrack, 1, 'Calls of onremovetrack on videoTracks should be 1.');
|
||||||
|
is(element.videoTracks.length, 0, 'The length of videoTracks should be 0.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onended() {
|
||||||
|
ok(true, 'Event ended is expected to be fired on element.');
|
||||||
|
checkTrackRemoved();
|
||||||
|
element.onended = null;
|
||||||
|
element.onplaying = null;
|
||||||
|
element.onpause = null;
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkTrackAdded() {
|
||||||
|
isPlaying = true;
|
||||||
|
is(audioOnaddtrack, 1, 'Calls of onaddtrack on audioTracks should be 1.');
|
||||||
|
is(element.audioTracks.length, 1, 'The length of audioTracks should be 1.');
|
||||||
|
ok(element.audioTracks[0].enabled, 'Audio track should be enabled as default.');
|
||||||
|
is(videoOnaddtrack, 1, 'Calls of onaddtrack on videoTracks should be 1.');
|
||||||
|
is(element.videoTracks.length, 1, 'The length of videoTracks should be 1.');
|
||||||
|
is(element.videoTracks.selectedIndex, 0,
|
||||||
|
'The first video track is set selected as default.');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTrackEnabled(enabled) {
|
||||||
|
element.audioTracks[0].enabled = enabled;
|
||||||
|
element.videoTracks[0].selected = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkTrackChanged(calls, enabled) {
|
||||||
|
is(audioOnchange, calls, 'Calls of onchange on audioTracks should be '+calls);
|
||||||
|
is(element.audioTracks[0].enabled, enabled,
|
||||||
|
'Enabled value of the audio track should be ' +enabled);
|
||||||
|
is(videoOnchange, calls, 'Calls of onchange on videoTracks should be '+calls);
|
||||||
|
is(element.videoTracks[0].selected, enabled,
|
||||||
|
'Selected value of the video track should be ' +enabled);
|
||||||
|
var index = enabled ? 0 : -1;
|
||||||
|
is(element.videoTracks.selectedIndex, index,
|
||||||
|
'SelectedIndex of video tracks should be ' +index);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onpause() {
|
||||||
|
element.onpause = null;
|
||||||
|
if (element.ended) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (steps == 1) {
|
||||||
|
setTrackEnabled(false);
|
||||||
|
element.onplaying = onplaying;
|
||||||
|
element.play();
|
||||||
|
steps++;
|
||||||
|
} else if (steps == 2) {
|
||||||
|
setTrackEnabled(true);
|
||||||
|
element.onplaying = onplaying;
|
||||||
|
element.play();
|
||||||
|
steps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onplaying() {
|
||||||
|
element.onplaying = null;
|
||||||
|
if (element.ended) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (steps == 1) {
|
||||||
|
element.onpause = onpause;
|
||||||
|
element.pause();
|
||||||
|
checkTrackAdded();
|
||||||
|
} else if (steps == 2) {
|
||||||
|
element.onpause = onpause;
|
||||||
|
element.pause();
|
||||||
|
checkTrackChanged(1, false);
|
||||||
|
} else if (steps == 3) {
|
||||||
|
checkTrackChanged(2, true);
|
||||||
|
stream.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var steps = 0;
|
||||||
|
element.mozSrcObject = stream;
|
||||||
|
element.onplaying = onplaying;
|
||||||
|
element.onended = onended;
|
||||||
|
element.play();
|
||||||
|
steps++;
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
ok(false, 'Unexpected error fired with: ' + err);
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv(
|
||||||
|
{
|
||||||
|
"set": [
|
||||||
|
["media.track.enabled", true]
|
||||||
|
]
|
||||||
|
}, startTest);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,125 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test events of media track interfaces</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
<script type="text/javascript" src="manifest.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
function startTest() {
|
||||||
|
navigator.mozGetUserMedia({audio:true, video:true, fake:true},
|
||||||
|
function(stream) {
|
||||||
|
var element = document.createElement("video");
|
||||||
|
|
||||||
|
isnot(element.audioTracks, undefined,
|
||||||
|
'HTMLMediaElement::AudioTracks() property should be available.');
|
||||||
|
isnot(element.videoTracks, undefined,
|
||||||
|
'HTMLMediaElement::VideoTracks() property should be available.');
|
||||||
|
|
||||||
|
function verifyEvent(e, type) {
|
||||||
|
is(e.type, type, "Event type should be " + type);
|
||||||
|
ok(e.isTrusted, "Event should be trusted.");
|
||||||
|
ok(!e.bubbles, "Event shouldn't bubble.");
|
||||||
|
ok(!e.cancelable, "Event shouldn't be cancelable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
element.audioTracks.onaddtrack = function(e) {
|
||||||
|
ok(e instanceof TrackEvent, "Event fired from onaddtrack should be a TrackEvent");
|
||||||
|
ok(true, 'onaddtrack is expected to be called from audioTracks.');
|
||||||
|
verifyEvent(e, "addtrack");
|
||||||
|
}
|
||||||
|
|
||||||
|
element.audioTracks.onremovetrack = function(e) {
|
||||||
|
ok(e instanceof TrackEvent, "Event fired from onremovetrack should be a TrackEvent");
|
||||||
|
ok(true, 'onremovetrack is expected to be called from audioTracks.');
|
||||||
|
verifyEvent(e, "removetrack");
|
||||||
|
}
|
||||||
|
|
||||||
|
element.audioTracks.onchange = function(e) {
|
||||||
|
ok(e instanceof window.Event, "Event fired from onchange should be a simple event.");
|
||||||
|
ok(true, 'onchange is expected to be called from audioTracks.');
|
||||||
|
verifyEvent(e, "change");
|
||||||
|
}
|
||||||
|
|
||||||
|
element.videoTracks.onaddtrack = function(e) {
|
||||||
|
ok(e instanceof TrackEvent, "Event fired from onaddtrack should be a TrackEvent");
|
||||||
|
ok(true, 'onaddtrack is expected to be called from videoTracks.');
|
||||||
|
verifyEvent(e, "addtrack");
|
||||||
|
}
|
||||||
|
|
||||||
|
element.videoTracks.onremovetrack = function(e) {
|
||||||
|
ok(e instanceof TrackEvent, "Event fired from onremovetrack should be a TrackEvent");
|
||||||
|
ok(true, 'onremovetrack is expected to be called from videoTracks.');
|
||||||
|
verifyEvent(e, "removetrack");
|
||||||
|
}
|
||||||
|
|
||||||
|
element.videoTracks.onchange = function(e) {
|
||||||
|
ok(e instanceof window.Event, "Event fired from onchange should be a simple event.");
|
||||||
|
ok(true, 'onchange is expected to be called from videoTracks.');
|
||||||
|
verifyEvent(e, "change");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onended() {
|
||||||
|
ok(true, 'Event ended is expected to be fired on element.');
|
||||||
|
element.onended = null;
|
||||||
|
element.onplaying = null;
|
||||||
|
element.onpause = null;
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onpause() {
|
||||||
|
element.onpause = null;
|
||||||
|
if (element.ended) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (steps == 1) {
|
||||||
|
element.audioTracks[0].enabled = false;
|
||||||
|
element.videoTracks[0].selected = false;
|
||||||
|
element.onplaying = onplaying;
|
||||||
|
element.play();
|
||||||
|
steps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onplaying() {
|
||||||
|
element.onplaying = null;
|
||||||
|
if (element.ended) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (steps == 1) {
|
||||||
|
element.onpause = onpause;
|
||||||
|
element.pause();
|
||||||
|
} else if (steps == 2) {
|
||||||
|
stream.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var steps = 0;
|
||||||
|
element.mozSrcObject = stream;
|
||||||
|
element.onplaying = onplaying;
|
||||||
|
element.onended = onended;
|
||||||
|
element.play();
|
||||||
|
steps++;
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
ok(false, 'Unexpected error fired with: ' + err);
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv(
|
||||||
|
{
|
||||||
|
"set": [
|
||||||
|
["media.track.enabled", true]
|
||||||
|
]
|
||||||
|
}, startTest);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,189 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Test track interfaces when consuming a MediaStream from gUM</title>
|
|
||||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
||||||
<script type="text/javascript" src="manifest.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
function startTest() {
|
|
||||||
navigator.mozGetUserMedia({audio:true, video:true, fake:true},
|
|
||||||
function(stream) {
|
|
||||||
var audioStreamTracks = stream.getAudioTracks();
|
|
||||||
var videoStreamTracks = stream.getVideoTracks();
|
|
||||||
|
|
||||||
var audioOnchange = 0;
|
|
||||||
var audioOnaddtrack = 0;
|
|
||||||
var audioOnremovetrack = 0;
|
|
||||||
var videoOnchange = 0;
|
|
||||||
var videoOnaddtrack = 0;
|
|
||||||
var videoOnremovetrack = 0;
|
|
||||||
|
|
||||||
var element = document.createElement("video");
|
|
||||||
isnot(element.audioTracks, undefined, "HTMLMediaElement::AudioTracks() property should be available.");
|
|
||||||
isnot(element.videoTracks, undefined, "HTMLMediaElement::VideoTracks() property should be available.");
|
|
||||||
|
|
||||||
function verify_event(e, type) {
|
|
||||||
is(e.type, type, "Event type should be " + type);
|
|
||||||
ok(e.isTrusted, "Event should be trusted.");
|
|
||||||
ok(!e.bubbles, "Event shouldn't bubble.");
|
|
||||||
ok(!e.cancelable, "Event shouldn't be cancelable.");
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAudioEnabled(enabled, index) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
element.audioTracks[index].enabled = enabled;
|
|
||||||
element.audioTracks.onchange = function(e) {
|
|
||||||
ok(e instanceof window.Event, "Event fired from onchange should be a simple event.");
|
|
||||||
ok(true, 'onchange is expected to be called from audioTracks.');
|
|
||||||
verify_event(e, "change");
|
|
||||||
audioOnchange++;
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setVideoSelected(selected, index) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
element.videoTracks[index].selected = selected;
|
|
||||||
element.videoTracks.onchange = function(e) {
|
|
||||||
ok(e instanceof window.Event, "Event fired from onchange should be a simple event.");
|
|
||||||
ok(true, 'onchange is expected to be called from videoTracks.');
|
|
||||||
verify_event(e, "change");
|
|
||||||
|
|
||||||
var noVideoSelected = true;
|
|
||||||
for (var i=0; i < element.videoTracks.length; ++i) {
|
|
||||||
var track = element.videoTracks[i];
|
|
||||||
if (track.selected == true) {
|
|
||||||
noVideoSelected = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selected) {
|
|
||||||
is(element.videoTracks.selectedIndex, index,
|
|
||||||
'SelectedIndex shuld be '+index+' if video track is set selected.');
|
|
||||||
} else {
|
|
||||||
if (noVideoSelected) {
|
|
||||||
is(element.videoTracks.selectedIndex, -1,
|
|
||||||
'SelectedIndex shuld be -1 if no video track is set selected.');
|
|
||||||
} else {
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
videoOnchange++;
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
element.audioTracks.onaddtrack = function(e) {
|
|
||||||
ok(e instanceof TrackEvent, "Event fired from onaddtrack should be a TrackEvent");
|
|
||||||
ok(true, 'onaddtrack is expected to be called from audioTracks.');
|
|
||||||
verify_event(e, "addtrack");
|
|
||||||
audioOnaddtrack++;
|
|
||||||
}
|
|
||||||
|
|
||||||
element.audioTracks.onremovetrack = function(e) {
|
|
||||||
ok(e instanceof TrackEvent, "Event fired from onremovetrack should be a TrackEvent");
|
|
||||||
ok(true, 'onremovetrack is expected to be called from audioTracks.');
|
|
||||||
verify_event(e, "removetrack");
|
|
||||||
audioOnremovetrack++;
|
|
||||||
}
|
|
||||||
|
|
||||||
element.videoTracks.onaddtrack = function(e) {
|
|
||||||
ok(e instanceof TrackEvent, "Event fired from onaddtrack should be a TrackEvent");
|
|
||||||
ok(true, 'onaddtrack is expected to be called from videoTracks.');
|
|
||||||
verify_event(e, "addtrack");
|
|
||||||
videoOnaddtrack++;
|
|
||||||
}
|
|
||||||
|
|
||||||
element.videoTracks.onremovetrack = function(e) {
|
|
||||||
ok(e instanceof TrackEvent, "Event fired from onremovetrack should be a TrackEvent");
|
|
||||||
ok(true, 'onremovetrack is expected to be called from videoTracks.');
|
|
||||||
verify_event(e, "removetrack");
|
|
||||||
videoOnremovetrack++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
element.onended = function() {
|
|
||||||
is(audioOnchange, 2, 'change event on audioTracks should fired twice.');
|
|
||||||
is(videoOnchange, 2, 'change event on videoTracks should fired twice.');
|
|
||||||
|
|
||||||
is(audioOnremovetrack, audioStreamTracks.length,
|
|
||||||
'Calls of onremovetrack from audioTracks should match the numbers of AudioStreamTrack.');
|
|
||||||
is(videoOnremovetrack, videoStreamTracks.length,
|
|
||||||
'Calls of onremovetrack from videoTracks should match the numbers of VideoStreamTrack.');
|
|
||||||
|
|
||||||
SimpleTest.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
var promise = new Promise(function(resolve, reject) {
|
|
||||||
element.mozSrcObject = stream;
|
|
||||||
element.play();
|
|
||||||
|
|
||||||
element.onloadedmetadata = function() {
|
|
||||||
is(audioOnaddtrack, audioStreamTracks.length,
|
|
||||||
'Calls of onaddtrack from audioTracks should match the numbers of AudioStreamTrack.');
|
|
||||||
is(videoOnaddtrack, videoStreamTracks.length,
|
|
||||||
'Calls of onaddtrack from videoTracks should match the numbers of VideoStreamTrack.');
|
|
||||||
|
|
||||||
is(element.audioTracks.length, audioStreamTracks.length,
|
|
||||||
'Length of audioTracks should be the same as the length of AudioStreamTrack.');
|
|
||||||
is(element.videoTracks.length, videoStreamTracks.length,
|
|
||||||
'Length of videoTracks should be the same as the length of VideoStreamTrack.');
|
|
||||||
|
|
||||||
for (var i=0; i < audioStreamTracks.length; ++i) {
|
|
||||||
var track = element.audioTracks.getTrackById(audioStreamTracks[i].id);
|
|
||||||
isnot(track, null, 'Successfully get '+ track.id + ' from audioTracks.');
|
|
||||||
}
|
|
||||||
for (var i=0; i < videoStreamTracks.length; ++i) {
|
|
||||||
var track = element.videoTracks.getTrackById(videoStreamTracks[i].id);
|
|
||||||
isnot(track, null, 'Successfully get '+ track.id + ' from videoTracks.');
|
|
||||||
}
|
|
||||||
|
|
||||||
is(element.videoTracks.selectedIndex, 0,
|
|
||||||
'The first video track is set selected as default.');
|
|
||||||
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.then(function() {
|
|
||||||
var p1 = setAudioEnabled(false, 0);
|
|
||||||
var p2 = setVideoSelected(false, 0);
|
|
||||||
return Promise.all([p1, p2]);
|
|
||||||
}).catch(function(err) {
|
|
||||||
ok(false, 'Something went wrong in onchange callback.');
|
|
||||||
}).then(function() {
|
|
||||||
var p3 = setAudioEnabled(true, 0);
|
|
||||||
var p4 = setVideoSelected(true, 0);
|
|
||||||
return Promise.all([p3, p4]);
|
|
||||||
}).catch(function(err) {
|
|
||||||
ok(false, 'Something went wrong in onchange callback.');
|
|
||||||
}).then(function() {
|
|
||||||
stream.stop();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function(err) {
|
|
||||||
ok(false, 'Unexpected error fired with: ' + err);
|
|
||||||
SimpleTest.finish();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
SpecialPowers.pushPrefEnv(
|
|
||||||
{
|
|
||||||
"set": [
|
|
||||||
["media.track.enabled", true]
|
|
||||||
]
|
|
||||||
}, startTest);
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -10,13 +10,37 @@
|
||||||
<pre id="test">
|
<pre id="test">
|
||||||
<script class="testbody" type="text/javascript">
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
|
//longer timeout for sometimes B2G emulator runs very slowly
|
||||||
|
if (SpecialPowers.Services.appinfo.name == "B2G") {
|
||||||
|
SimpleTest.requestLongerTimeout(3);
|
||||||
|
}
|
||||||
|
|
||||||
var manager = new MediaTestManager;
|
var manager = new MediaTestManager;
|
||||||
|
|
||||||
|
function localCheckMetadata(msg, e, test) {
|
||||||
|
if (test.width) {
|
||||||
|
is(e.videoWidth, test.width, msg + " video width");
|
||||||
|
}
|
||||||
|
if (test.height) {
|
||||||
|
is(e.videoHeight, test.height, msg + " video height");
|
||||||
|
}
|
||||||
|
if (test.duration) {
|
||||||
|
// see bug 1039901 for skipping mp3 duration test on B2G
|
||||||
|
if (SpecialPowers.Services.appinfo.name == "B2G" && /mp3$/.test(test.name)) {
|
||||||
|
todo(false, "Fix mp3 duration bug on B2G");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ok(Math.abs(e.duration - test.duration) < 0.1,
|
||||||
|
msg + " duration (" + e.duration + ") should be around " + test.duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function startTest(test, token) {
|
function startTest(test, token) {
|
||||||
var v = document.createElement('video');
|
var v = document.createElement('video');
|
||||||
v.preload = "metadata";
|
v.preload = "metadata";
|
||||||
v.token = token;
|
v.token = token;
|
||||||
manager.started(token);
|
manager.started(token);
|
||||||
|
var checkMetadata = localCheckMetadata;
|
||||||
|
|
||||||
v.src = test.name;
|
v.src = test.name;
|
||||||
v.name = test.name;
|
v.name = test.name;
|
||||||
|
|
|
@ -34,6 +34,16 @@ which makes Windows Media Foundation unavailable.
|
||||||
#include <wmcodecdsp.h>
|
#include <wmcodecdsp.h>
|
||||||
#include <codecapi.h>
|
#include <codecapi.h>
|
||||||
|
|
||||||
|
// The Windows headers helpfully declare min and max macros, which don't
|
||||||
|
// compile in the prescence of std::min and std::max and unified builds.
|
||||||
|
// So undef them here.
|
||||||
|
#ifdef min
|
||||||
|
#undef min
|
||||||
|
#endif
|
||||||
|
#ifdef max
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
// Some SDK versions don't define the AAC decoder CLSID.
|
// Some SDK versions don't define the AAC decoder CLSID.
|
||||||
#ifndef CLSID_CMSAACDecMFT
|
#ifndef CLSID_CMSAACDecMFT
|
||||||
extern "C" const CLSID CLSID_CMSAACDecMFT;
|
extern "C" const CLSID CLSID_CMSAACDecMFT;
|
||||||
|
|
|
@ -168,10 +168,11 @@ public:
|
||||||
|
|
||||||
JSContext* cx() const {
|
JSContext* cx() const {
|
||||||
MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
|
MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
|
||||||
|
MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
|
||||||
return mCx;
|
return mCx;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CxPusherIsStackTop() { return mCxPusher.ref().IsStackTop(); }
|
bool CxPusherIsStackTop() const { return mCxPusher.ref().IsStackTop(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Protected constructor, allowing subclasses to specify a particular cx to
|
// Protected constructor, allowing subclasses to specify a particular cx to
|
||||||
|
|
|
@ -936,8 +936,12 @@ nsJSContext::InitContext()
|
||||||
nsresult
|
nsresult
|
||||||
nsJSContext::SetProperty(JS::Handle<JSObject*> aTarget, const char* aPropName, nsISupports* aArgs)
|
nsJSContext::SetProperty(JS::Handle<JSObject*> aTarget, const char* aPropName, nsISupports* aArgs)
|
||||||
{
|
{
|
||||||
nsCxPusher pusher;
|
AutoJSAPI jsapi;
|
||||||
pusher.Push(mContext);
|
if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(GetGlobalObject()))) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(jsapi.cx() == mContext,
|
||||||
|
"AutoJSAPI should have found our own JSContext*");
|
||||||
|
|
||||||
JS::AutoValueVector args(mContext);
|
JS::AutoValueVector args(mContext);
|
||||||
|
|
||||||
|
|
|
@ -12,17 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=923010
|
||||||
/** Test for Bug 923010 **/
|
/** Test for Bug 923010 **/
|
||||||
try {
|
try {
|
||||||
var conn = new mozRTCPeerConnection();
|
var conn = new mozRTCPeerConnection();
|
||||||
|
var candidate = new mozRTCIceCandidate({candidate: null });
|
||||||
try {
|
try {
|
||||||
conn.createAnswer(function() {
|
conn.addIceCandidate(candidate, function() {
|
||||||
ok(false, "The call to createAnswer succeeded when it should have thrown");
|
ok(false, "The call to addIceCandidate succeeded when it should have thrown");
|
||||||
}, function() {
|
}, function() {
|
||||||
ok(false, "The call to createAnswer failed when it should have thrown");
|
ok(false, "The call to addIceCandidate failed when it should have thrown");
|
||||||
}, { "mandatory": { "BOGUS": 5 } } )
|
})
|
||||||
ok(false, "That call to createAnswer should have thrown");
|
ok(false, "That call to addIceCandidate should have thrown");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
is(e.lineNumber, 16, "Exception should have been on line 16");
|
is(e.lineNumber, 17, "Exception should have been on line 17");
|
||||||
is(e.message,
|
is(e.message,
|
||||||
"createAnswer passed invalid constraints - unknown mandatory constraint: BOGUS",
|
"Invalid candidate passed to addIceCandidate!",
|
||||||
"Should have the exception we expect");
|
"Should have the exception we expect");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
|
|
||||||
#include "domstubs.idl"
|
#include "domstubs.idl"
|
||||||
|
|
||||||
|
interface nsIDocument;
|
||||||
interface nsIURI;
|
interface nsIURI;
|
||||||
|
|
||||||
[uuid(6117cdf1-cb10-42a3-9901-4f1bab7ffa4d)]
|
[uuid(6e1382f4-3cbc-435f-8ce0-70175f6eb400)]
|
||||||
interface nsIServiceWorkerManager : nsISupports
|
interface nsIServiceWorkerManager : nsISupports
|
||||||
{
|
{
|
||||||
// Returns a Promise
|
// Returns a Promise
|
||||||
|
@ -20,6 +21,21 @@ interface nsIServiceWorkerManager : nsISupports
|
||||||
[noscript] void AddContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
[noscript] void AddContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
||||||
[noscript] void RemoveContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
[noscript] void RemoveContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this to request that document `aDoc` be controlled by a ServiceWorker
|
||||||
|
* if a registration exists for it's scope.
|
||||||
|
*
|
||||||
|
* This MUST only be called once per document!
|
||||||
|
*/
|
||||||
|
[notxpcom,nostdcall] void MaybeStartControlling(in nsIDocument aDoc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documents that have called MaybeStartControlling() should call this when
|
||||||
|
* they are destroyed. This function may be called multiple times, and is
|
||||||
|
* idempotent.
|
||||||
|
*/
|
||||||
|
[notxpcom,nostdcall] void MaybeStopControlling(in nsIDocument aDoc);
|
||||||
|
|
||||||
// Testing
|
// Testing
|
||||||
DOMString getScopeForUrl(in DOMString path);
|
DOMString getScopeForUrl(in DOMString path);
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,6 +42,7 @@ function GlobalPCList() {
|
||||||
Services.obs.addObserver(this, "profile-change-net-teardown", true);
|
Services.obs.addObserver(this, "profile-change-net-teardown", true);
|
||||||
Services.obs.addObserver(this, "network:offline-about-to-go-offline", true);
|
Services.obs.addObserver(this, "network:offline-about-to-go-offline", true);
|
||||||
Services.obs.addObserver(this, "network:offline-status-changed", true);
|
Services.obs.addObserver(this, "network:offline-status-changed", true);
|
||||||
|
Services.obs.addObserver(this, "gmp-plugin-crash", true);
|
||||||
}
|
}
|
||||||
GlobalPCList.prototype = {
|
GlobalPCList.prototype = {
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||||
|
@ -107,6 +108,27 @@ GlobalPCList.prototype = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let hasPluginId = function(list, winID, pluginID, name, crashReport) {
|
||||||
|
if (list.hasOwnProperty(winID)) {
|
||||||
|
list[winID].forEach(function(pcref) {
|
||||||
|
let pc = pcref.get();
|
||||||
|
if (pc) {
|
||||||
|
if (pc._pc.pluginCrash(pluginID)) {
|
||||||
|
// Notify DOM window of the crash
|
||||||
|
let event = new CustomEvent("PluginCrashed",
|
||||||
|
{ bubbles: false, cancelable: false,
|
||||||
|
detail: {
|
||||||
|
pluginName: name,
|
||||||
|
pluginDumpId: crashReport,
|
||||||
|
submittedCrashReport: false }
|
||||||
|
});
|
||||||
|
pc._win.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (topic == "inner-window-destroyed") {
|
if (topic == "inner-window-destroyed") {
|
||||||
let winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
let winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||||
cleanupWinId(this._list, winID);
|
cleanupWinId(this._list, winID);
|
||||||
|
@ -134,6 +156,19 @@ GlobalPCList.prototype = {
|
||||||
} else if (data == "online") {
|
} else if (data == "online") {
|
||||||
this._networkdown = false;
|
this._networkdown = false;
|
||||||
}
|
}
|
||||||
|
} else if (topic == "gmp-plugin-crash") {
|
||||||
|
// a plugin crashed; if it's associated with any of our PCs, fire an
|
||||||
|
// event to the DOM window
|
||||||
|
let sep = data.indexOf(' ');
|
||||||
|
let pluginId = data.slice(0, sep);
|
||||||
|
let rest = data.slice(sep+1);
|
||||||
|
// This presumes no spaces in the name!
|
||||||
|
sep = rest.indexOf(' ');
|
||||||
|
let name = rest.slice(0, sep);
|
||||||
|
let crashId = rest.slice(sep+1);
|
||||||
|
for (let winId in this._list) {
|
||||||
|
hasPluginId(this._list, winId, pluginId, name, crashId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -465,50 +500,6 @@ RTCPeerConnection.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* MediaConstraints look like this:
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* mandatory: {"OfferToReceiveAudio": true, "OfferToReceiveVideo": true },
|
|
||||||
* optional: [{"VoiceActivityDetection": true}, {"FooBar": 10}]
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* WebIDL normalizes the top structure for us, but the mandatory constraints
|
|
||||||
* member comes in as a raw object so we can detect unknown constraints. We
|
|
||||||
* compare its members against ones we support, and fail if not found.
|
|
||||||
*/
|
|
||||||
_mustValidateConstraints: function(constraints, errorMsg) {
|
|
||||||
if (constraints.mandatory) {
|
|
||||||
let supported;
|
|
||||||
try {
|
|
||||||
// Passing the raw constraints.mandatory here validates its structure
|
|
||||||
supported = this._observer.getSupportedConstraints(constraints.mandatory);
|
|
||||||
} catch (e) {
|
|
||||||
throw new this._win.DOMError("", errorMsg + " - " + e.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let constraint of Object.keys(constraints.mandatory)) {
|
|
||||||
if (!(constraint in supported)) {
|
|
||||||
throw new this._win.DOMError("",
|
|
||||||
errorMsg + " - unknown mandatory constraint: " + constraint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (constraints.optional) {
|
|
||||||
let len = constraints.optional.length;
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
let constraints_per_entry = 0;
|
|
||||||
for (let constraint in Object.keys(constraints.optional[i])) {
|
|
||||||
if (constraints_per_entry) {
|
|
||||||
throw new this._win.DOMError("", errorMsg +
|
|
||||||
" - optional constraint must be single key/value pair");
|
|
||||||
}
|
|
||||||
constraints_per_entry += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Ideally, this should be of the form _checkState(state),
|
// Ideally, this should be of the form _checkState(state),
|
||||||
// where the state is taken from an enumeration containing
|
// where the state is taken from an enumeration containing
|
||||||
// the valid peer connection states defined in the WebRTC
|
// the valid peer connection states defined in the WebRTC
|
||||||
|
@ -574,26 +565,22 @@ RTCPeerConnection.prototype = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
createOffer: function(onSuccess, onError, constraints) {
|
createOffer: function(onSuccess, onError, options) {
|
||||||
if (!constraints) {
|
options = options || {};
|
||||||
constraints = {};
|
|
||||||
}
|
|
||||||
this._mustValidateConstraints(constraints, "createOffer passed invalid constraints");
|
|
||||||
|
|
||||||
this._queueOrRun({
|
this._queueOrRun({
|
||||||
func: this._createOffer,
|
func: this._createOffer,
|
||||||
args: [onSuccess, onError, constraints],
|
args: [onSuccess, onError, options],
|
||||||
wait: true
|
wait: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_createOffer: function(onSuccess, onError, constraints) {
|
_createOffer: function(onSuccess, onError, options) {
|
||||||
this._onCreateOfferSuccess = onSuccess;
|
this._onCreateOfferSuccess = onSuccess;
|
||||||
this._onCreateOfferFailure = onError;
|
this._onCreateOfferFailure = onError;
|
||||||
this._impl.createOffer(constraints);
|
this._impl.createOffer(options);
|
||||||
},
|
},
|
||||||
|
|
||||||
_createAnswer: function(onSuccess, onError, constraints, provisional) {
|
_createAnswer: function(onSuccess, onError) {
|
||||||
this._onCreateAnswerSuccess = onSuccess;
|
this._onCreateAnswerSuccess = onSuccess;
|
||||||
this._onCreateAnswerFailure = onError;
|
this._onCreateAnswerFailure = onError;
|
||||||
|
|
||||||
|
@ -610,26 +597,13 @@ RTCPeerConnection.prototype = {
|
||||||
"No outstanding offer");
|
"No outstanding offer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this._impl.createAnswer();
|
||||||
// TODO: Implement provisional answer.
|
|
||||||
|
|
||||||
this._impl.createAnswer(constraints);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
createAnswer: function(onSuccess, onError, constraints, provisional) {
|
createAnswer: function(onSuccess, onError) {
|
||||||
if (!constraints) {
|
|
||||||
constraints = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
this._mustValidateConstraints(constraints, "createAnswer passed invalid constraints");
|
|
||||||
|
|
||||||
if (!provisional) {
|
|
||||||
provisional = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._queueOrRun({
|
this._queueOrRun({
|
||||||
func: this._createAnswer,
|
func: this._createAnswer,
|
||||||
args: [onSuccess, onError, constraints, provisional],
|
args: [onSuccess, onError],
|
||||||
wait: true
|
wait: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -794,7 +768,7 @@ RTCPeerConnection.prototype = {
|
||||||
gotAssertion);
|
gotAssertion);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateIce: function(config, constraints) {
|
updateIce: function(config) {
|
||||||
throw new this._win.DOMError("", "updateIce not yet implemented");
|
throw new this._win.DOMError("", "updateIce not yet implemented");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -815,22 +789,17 @@ RTCPeerConnection.prototype = {
|
||||||
cand.sdpMLineIndex + 1);
|
cand.sdpMLineIndex + 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
addStream: function(stream, constraints) {
|
addStream: function(stream) {
|
||||||
if (!constraints) {
|
|
||||||
constraints = {};
|
|
||||||
}
|
|
||||||
this._mustValidateConstraints(constraints,
|
|
||||||
"addStream passed invalid constraints");
|
|
||||||
if (stream.currentTime === undefined) {
|
if (stream.currentTime === undefined) {
|
||||||
throw new this._win.DOMError("", "Invalid stream passed to addStream!");
|
throw new this._win.DOMError("", "Invalid stream passed to addStream!");
|
||||||
}
|
}
|
||||||
this._queueOrRun({ func: this._addStream,
|
this._queueOrRun({ func: this._addStream,
|
||||||
args: [stream, constraints],
|
args: [stream],
|
||||||
wait: false });
|
wait: false });
|
||||||
},
|
},
|
||||||
|
|
||||||
_addStream: function(stream, constraints) {
|
_addStream: function(stream) {
|
||||||
this._impl.addStream(stream, constraints);
|
this._impl.addStream(stream);
|
||||||
},
|
},
|
||||||
|
|
||||||
removeStream: function(stream) {
|
removeStream: function(stream) {
|
||||||
|
@ -1293,11 +1262,7 @@ PeerConnectionObserver.prototype = {
|
||||||
notifyDataChannel: function(channel) {
|
notifyDataChannel: function(channel) {
|
||||||
this.dispatchEvent(new this._dompc._win.RTCDataChannelEvent("datachannel",
|
this.dispatchEvent(new this._dompc._win.RTCDataChannelEvent("datachannel",
|
||||||
{ channel: channel }));
|
{ channel: channel }));
|
||||||
},
|
}
|
||||||
|
|
||||||
getSupportedConstraints: function(dict) {
|
|
||||||
return dict;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function RTCPeerConnectionStatic() {
|
function RTCPeerConnectionStatic() {
|
||||||
|
|
|
@ -759,10 +759,10 @@ function PCT_setMediaConstraints(constraintsLocal, constraintsRemote) {
|
||||||
*
|
*
|
||||||
* @param {object} constraints the media constraints to use on createOffer
|
* @param {object} constraints the media constraints to use on createOffer
|
||||||
*/
|
*/
|
||||||
PeerConnectionTest.prototype.setOfferConstraints =
|
PeerConnectionTest.prototype.setOfferOptions =
|
||||||
function PCT_setOfferConstraints(constraints) {
|
function PCT_setOfferOptions(options) {
|
||||||
if (this.pcLocal)
|
if (this.pcLocal)
|
||||||
this.pcLocal.offerConstraints = constraints;
|
this.pcLocal.offerOptions = options;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1362,7 +1362,7 @@ function PeerConnectionWrapper(label, configuration, h264) {
|
||||||
this.whenCreated = Date.now();
|
this.whenCreated = Date.now();
|
||||||
|
|
||||||
this.constraints = [ ];
|
this.constraints = [ ];
|
||||||
this.offerConstraints = {};
|
this.offerOptions = {};
|
||||||
this.streams = [ ];
|
this.streams = [ ];
|
||||||
this.mediaCheckers = [ ];
|
this.mediaCheckers = [ ];
|
||||||
|
|
||||||
|
@ -1637,7 +1637,7 @@ PeerConnectionWrapper.prototype = {
|
||||||
offer.sdp = removeVP8(offer.sdp);
|
offer.sdp = removeVP8(offer.sdp);
|
||||||
}
|
}
|
||||||
onSuccess(offer);
|
onSuccess(offer);
|
||||||
}, generateErrorCallback(), this.offerConstraints);
|
}, generateErrorCallback(), this.offerOptions);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
var pc = new mozRTCPeerConnection();
|
var pc = new mozRTCPeerConnection();
|
||||||
|
|
||||||
// necessary to circumvent bug 864109
|
// necessary to circumvent bug 864109
|
||||||
var options = { mandatory: { OfferToReceiveAudio: true} };
|
var options = { offerToReceiveAudio: true };
|
||||||
|
|
||||||
pc.createOffer(function (offer) {
|
pc.createOffer(function (offer) {
|
||||||
ok(!offer.sdp.contains("m=application"),
|
ok(!offer.sdp.contains("m=application"),
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
});
|
});
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
croak("createOffer failed: " + err);
|
croak("createOffer failed: " + err);
|
||||||
}, { mandatory: { OfferToReceiveAudio: true} });
|
}, { offerToReceiveAudio: true });
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
|
@ -32,24 +32,15 @@
|
||||||
ok(!exception, "createOffer(step1, failed, {}) succeeds");
|
ok(!exception, "createOffer(step1, failed, {}) succeeds");
|
||||||
exception = null;
|
exception = null;
|
||||||
try {
|
try {
|
||||||
pconnect.createOffer(step1, failed, { mandatory: { FooBar: true } });
|
pconnect.updateIce();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ok(e.message.indexOf("FooBar") > 0, "createOffer has readable exceptions");
|
ok(e.message.indexOf("updateIce") >= 0, "PeerConnection.js has readable exceptions");
|
||||||
exception = e;
|
exception = e;
|
||||||
}
|
}
|
||||||
ok(exception, "createOffer(step1, failed, { mandatory: { FooBar: true } }) throws");
|
ok(exception, "updateIce not yet implemented and throws");
|
||||||
exception = null;
|
exception = null;
|
||||||
try { pconnects.createOffer(step1, failed, { optional: [] }); } catch (e) { exception = e; }
|
try { pconnects.createOffer(step1, failed, { offerToReceiveVideo: false, offerToReceiveAudio: true, MozDontOfferDataChannel: true }); } catch (e) { exception = e; }
|
||||||
ok(!exception, "createOffer(step1, failed, { optional: [] }) succeeds");
|
ok(!exception, "createOffer(step1, failed, { offerToReceiveVideo: false, offerToReceiveAudio: true, MozDontOfferDataChannel: true }) succeeds");
|
||||||
exception = null;
|
|
||||||
try { pconnect.createOffer(step1, failed, { optional: [1] }); } catch (e) { exception = e; }
|
|
||||||
ok(exception, "createOffer(step1, failed, { optional: [1] }) throws");
|
|
||||||
exception = null;
|
|
||||||
try { pconnect.createOffer(step1, failed, { optional: [{ OfferToReceiveVideo: false, OfferToReceiveAudio: true, }] }); } catch (e) { exception = e; }
|
|
||||||
ok(exception, "createOffer(step1, failed, { optional: [{ OfferToReceiveVideo: false, OfferToReceiveAudio: true, }] }) throws");
|
|
||||||
exception = null;
|
|
||||||
try { pconnects.createOffer(step1, failed, { mandatory: { OfferToReceiveVideo: false, OfferToReceiveAudio: true, MozDontOfferDataChannel: true}, optional: [{ VoiceActivityDetection: true }, { FooBar: "42" }] }); } catch (e) { exception = e; }
|
|
||||||
ok(!exception, "createOffer(step1, failed, { mandatory: { OfferToReceiveVideo: false, OfferToReceiveAudio: true, MozDontOfferDataChannel: true}, optional: [{ VoiceActivityDetection: true }, { FooBar: \"42\" }] }) succeeds");
|
|
||||||
pconnect.close();
|
pconnect.close();
|
||||||
pconnects.close();
|
pconnects.close();
|
||||||
pconnect = null;
|
pconnect = null;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
runNetworkTest(function() {
|
runNetworkTest(function() {
|
||||||
var test = new PeerConnectionTest();
|
var test = new PeerConnectionTest();
|
||||||
test.setOfferConstraints({ mandatory: { OfferToReceiveAudio: true } });
|
test.setOfferOptions({ offerToReceiveAudio: true });
|
||||||
test.run();
|
test.run();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
runNetworkTest(function() {
|
runNetworkTest(function() {
|
||||||
var test = new PeerConnectionTest();
|
var test = new PeerConnectionTest();
|
||||||
test.setOfferConstraints({ mandatory: { OfferToReceiveVideo: true } });
|
test.setOfferOptions({ offerToReceiveVideo: true });
|
||||||
test.run();
|
test.run();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
runNetworkTest(function() {
|
runNetworkTest(function() {
|
||||||
var test = new PeerConnectionTest();
|
var test = new PeerConnectionTest();
|
||||||
test.setOfferConstraints({ mandatory: {
|
test.setOfferOptions({
|
||||||
OfferToReceiveVideo: true,
|
offerToReceiveVideo: true,
|
||||||
OfferToReceiveAudio: true
|
offerToReceiveAudio: true
|
||||||
}});
|
});
|
||||||
test.run();
|
test.run();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "nsWrapperCacheInlines.h"
|
#include "nsWrapperCacheInlines.h"
|
||||||
#include "js/HashTable.h"
|
#include "js/HashTable.h"
|
||||||
#include "mozilla/HashFunctions.h"
|
#include "mozilla/HashFunctions.h"
|
||||||
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
|
|
||||||
|
|
||||||
#define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
|
#define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
|
||||||
|
@ -291,8 +292,8 @@ namespace mozilla {
|
||||||
namespace plugins {
|
namespace plugins {
|
||||||
namespace parent {
|
namespace parent {
|
||||||
|
|
||||||
JSContext *
|
static nsIGlobalObject*
|
||||||
GetJSContext(NPP npp)
|
GetGlobalObject(NPP npp)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(npp, nullptr);
|
NS_ENSURE_TRUE(npp, nullptr);
|
||||||
|
|
||||||
|
@ -306,8 +307,13 @@ GetJSContext(NPP npp)
|
||||||
owner->GetDocument(getter_AddRefs(doc));
|
owner->GetDocument(getter_AddRefs(doc));
|
||||||
NS_ENSURE_TRUE(doc, nullptr);
|
NS_ENSURE_TRUE(doc, nullptr);
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> documentContainer = doc->GetContainer();
|
return doc->GetScopeObject();
|
||||||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_GetInterface(documentContainer));
|
}
|
||||||
|
|
||||||
|
JSContext *
|
||||||
|
GetJSContext(NPP npp)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(GetGlobalObject(npp));
|
||||||
NS_ENSURE_TRUE(sgo, nullptr);
|
NS_ENSURE_TRUE(sgo, nullptr);
|
||||||
|
|
||||||
nsIScriptContext *scx = sgo->GetContext();
|
nsIScriptContext *scx = sgo->GetContext();
|
||||||
|
@ -571,11 +577,11 @@ bool
|
||||||
nsJSObjWrapper::NP_HasMethod(NPObject *npobj, NPIdentifier id)
|
nsJSObjWrapper::NP_HasMethod(NPObject *npobj, NPIdentifier id)
|
||||||
{
|
{
|
||||||
NPP npp = NPPStack::Peek();
|
NPP npp = NPPStack::Peek();
|
||||||
JSContext *cx = GetJSContext(npp);
|
dom::AutoJSAPI jsapi;
|
||||||
|
if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(GetGlobalObject(npp)))) {
|
||||||
if (!cx) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
JSContext *cx = jsapi.cx();
|
||||||
|
|
||||||
if (!npobj) {
|
if (!npobj) {
|
||||||
ThrowJSException(cx,
|
ThrowJSException(cx,
|
||||||
|
@ -586,8 +592,6 @@ nsJSObjWrapper::NP_HasMethod(NPObject *npobj, NPIdentifier id)
|
||||||
|
|
||||||
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
||||||
|
|
||||||
nsCxPusher pusher;
|
|
||||||
pusher.Push(cx);
|
|
||||||
JSAutoCompartment ac(cx, npjsobj->mJSObj);
|
JSAutoCompartment ac(cx, npjsobj->mJSObj);
|
||||||
|
|
||||||
AutoJSExceptionReporter reporter(cx);
|
AutoJSExceptionReporter reporter(cx);
|
||||||
|
@ -696,11 +700,11 @@ bool
|
||||||
nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier npid)
|
nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier npid)
|
||||||
{
|
{
|
||||||
NPP npp = NPPStack::Peek();
|
NPP npp = NPPStack::Peek();
|
||||||
JSContext *cx = GetJSContext(npp);
|
dom::AutoJSAPI jsapi;
|
||||||
|
if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(GetGlobalObject(npp)))) {
|
||||||
if (!cx) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
JSContext *cx = jsapi.cx();
|
||||||
|
|
||||||
if (!npobj) {
|
if (!npobj) {
|
||||||
ThrowJSException(cx,
|
ThrowJSException(cx,
|
||||||
|
@ -712,8 +716,6 @@ nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier npid)
|
||||||
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
||||||
bool found, ok = false;
|
bool found, ok = false;
|
||||||
|
|
||||||
nsCxPusher pusher;
|
|
||||||
pusher.Push(cx);
|
|
||||||
AutoJSExceptionReporter reporter(cx);
|
AutoJSExceptionReporter reporter(cx);
|
||||||
JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
|
JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
|
||||||
JSAutoCompartment ac(cx, jsobj);
|
JSAutoCompartment ac(cx, jsobj);
|
||||||
|
@ -799,11 +801,11 @@ bool
|
||||||
nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier npid)
|
nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier npid)
|
||||||
{
|
{
|
||||||
NPP npp = NPPStack::Peek();
|
NPP npp = NPPStack::Peek();
|
||||||
JSContext *cx = GetJSContext(npp);
|
dom::AutoJSAPI jsapi;
|
||||||
|
if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(GetGlobalObject(npp)))) {
|
||||||
if (!cx) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
JSContext *cx = jsapi.cx();
|
||||||
|
|
||||||
if (!npobj) {
|
if (!npobj) {
|
||||||
ThrowJSException(cx,
|
ThrowJSException(cx,
|
||||||
|
@ -815,8 +817,6 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier npid)
|
||||||
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
nsCxPusher pusher;
|
|
||||||
pusher.Push(cx);
|
|
||||||
AutoJSExceptionReporter reporter(cx);
|
AutoJSExceptionReporter reporter(cx);
|
||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
JS::Rooted<JSObject*> obj(cx, npjsobj->mJSObj);
|
JS::Rooted<JSObject*> obj(cx, npjsobj->mJSObj);
|
||||||
|
@ -850,15 +850,15 @@ nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **idarray,
|
||||||
uint32_t *count)
|
uint32_t *count)
|
||||||
{
|
{
|
||||||
NPP npp = NPPStack::Peek();
|
NPP npp = NPPStack::Peek();
|
||||||
JSContext *cx = GetJSContext(npp);
|
dom::AutoJSAPI jsapi;
|
||||||
|
if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(GetGlobalObject(npp)))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
JSContext *cx = jsapi.cx();
|
||||||
|
|
||||||
*idarray = 0;
|
*idarray = 0;
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
if (!cx) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!npobj) {
|
if (!npobj) {
|
||||||
ThrowJSException(cx,
|
ThrowJSException(cx,
|
||||||
"Null npobj in nsJSObjWrapper::NP_Enumerate!");
|
"Null npobj in nsJSObjWrapper::NP_Enumerate!");
|
||||||
|
@ -868,8 +868,6 @@ nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **idarray,
|
||||||
|
|
||||||
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
||||||
|
|
||||||
nsCxPusher pusher;
|
|
||||||
pusher.Push(cx);
|
|
||||||
AutoJSExceptionReporter reporter(cx);
|
AutoJSExceptionReporter reporter(cx);
|
||||||
JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
|
JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
|
||||||
JSAutoCompartment ac(cx, jsobj);
|
JSAutoCompartment ac(cx, jsobj);
|
||||||
|
|
|
@ -25,9 +25,9 @@ interface PeerConnectionImpl {
|
||||||
nsISupports thread);
|
nsISupports thread);
|
||||||
/* JSEP calls */
|
/* JSEP calls */
|
||||||
[Throws]
|
[Throws]
|
||||||
void createOffer(optional MediaConstraintsInternal constraints);
|
void createOffer(optional RTCOfferOptions options);
|
||||||
[Throws]
|
[Throws]
|
||||||
void createAnswer(optional MediaConstraintsInternal constraints);
|
void createAnswer();
|
||||||
[Throws]
|
[Throws]
|
||||||
void setLocalDescription(long action, DOMString sdp);
|
void setLocalDescription(long action, DOMString sdp);
|
||||||
[Throws]
|
[Throws]
|
||||||
|
@ -40,8 +40,7 @@ interface PeerConnectionImpl {
|
||||||
|
|
||||||
/* Adds the stream created by GetUserMedia */
|
/* Adds the stream created by GetUserMedia */
|
||||||
[Throws]
|
[Throws]
|
||||||
void addStream(MediaStream stream,
|
void addStream(MediaStream stream);
|
||||||
optional MediaConstraintsInternal constraints);
|
|
||||||
[Throws]
|
[Throws]
|
||||||
void removeStream(MediaStream stream);
|
void removeStream(MediaStream stream);
|
||||||
[Throws]
|
[Throws]
|
||||||
|
@ -61,6 +60,9 @@ interface PeerConnectionImpl {
|
||||||
/* Puts the SIPCC engine back to 'kIdle', shuts down threads, deletes state */
|
/* Puts the SIPCC engine back to 'kIdle', shuts down threads, deletes state */
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
/* Notify DOM window if this plugin crash is ours */
|
||||||
|
boolean pluginCrash(unsigned long pluginId);
|
||||||
|
|
||||||
/* Attributes */
|
/* Attributes */
|
||||||
readonly attribute DOMString fingerprint;
|
readonly attribute DOMString fingerprint;
|
||||||
readonly attribute DOMString localDescription;
|
readonly attribute DOMString localDescription;
|
||||||
|
|
|
@ -39,9 +39,4 @@ interface PeerConnectionObserver
|
||||||
void onRemoveStream();
|
void onRemoveStream();
|
||||||
void onAddTrack();
|
void onAddTrack();
|
||||||
void onRemoveTrack();
|
void onRemoveTrack();
|
||||||
|
|
||||||
/* Helper function to access supported constraints defined in webidl. Needs to
|
|
||||||
* be in a separate webidl object we hold, so putting it here was convenient.
|
|
||||||
*/
|
|
||||||
MediaConstraintSet getSupportedConstraints(optional MediaConstraintSet constraints);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,33 +52,13 @@ dictionary RTCDataChannelInit {
|
||||||
unsigned short stream; // now id
|
unsigned short stream; // now id
|
||||||
};
|
};
|
||||||
|
|
||||||
// Misnomer dictionaries housing PeerConnection-specific constraints.
|
dictionary RTCOfferOptions {
|
||||||
//
|
long offerToReceiveVideo;
|
||||||
// Important! Do not ever add members that might need tracing (e.g. object)
|
long offerToReceiveAudio;
|
||||||
// to MediaConstraintSet or any dictionary marked XxxInternal here
|
|
||||||
|
|
||||||
dictionary MediaConstraintSet {
|
|
||||||
boolean OfferToReceiveAudio;
|
|
||||||
boolean OfferToReceiveVideo;
|
|
||||||
boolean MozDontOfferDataChannel;
|
boolean MozDontOfferDataChannel;
|
||||||
boolean MozBundleOnly;
|
boolean MozBundleOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
// MediaConstraint = single-property-subset of MediaConstraintSet
|
|
||||||
// Implemented as full set. Test Object.keys(pair).length == 1
|
|
||||||
|
|
||||||
// typedef MediaConstraintSet MediaConstraint; // TODO: Bug 913053
|
|
||||||
|
|
||||||
dictionary MediaConstraints {
|
|
||||||
object mandatory; // so we can see unknown + unsupported constraints
|
|
||||||
sequence<MediaConstraintSet> _optional; // a.k.a. MediaConstraint
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary MediaConstraintsInternal {
|
|
||||||
MediaConstraintSet mandatory; // holds only supported constraints
|
|
||||||
sequence<MediaConstraintSet> _optional; // a.k.a. MediaConstraint
|
|
||||||
};
|
|
||||||
|
|
||||||
interface RTCDataChannel;
|
interface RTCDataChannel;
|
||||||
|
|
||||||
[Pref="media.peerconnection.enabled",
|
[Pref="media.peerconnection.enabled",
|
||||||
|
@ -95,10 +75,9 @@ interface mozRTCPeerConnection : EventTarget {
|
||||||
void getIdentityAssertion();
|
void getIdentityAssertion();
|
||||||
void createOffer (RTCSessionDescriptionCallback successCallback,
|
void createOffer (RTCSessionDescriptionCallback successCallback,
|
||||||
RTCPeerConnectionErrorCallback failureCallback,
|
RTCPeerConnectionErrorCallback failureCallback,
|
||||||
optional MediaConstraints constraints);
|
optional RTCOfferOptions options);
|
||||||
void createAnswer (RTCSessionDescriptionCallback successCallback,
|
void createAnswer (RTCSessionDescriptionCallback successCallback,
|
||||||
RTCPeerConnectionErrorCallback failureCallback,
|
RTCPeerConnectionErrorCallback failureCallback);
|
||||||
optional MediaConstraints constraints);
|
|
||||||
void setLocalDescription (mozRTCSessionDescription description,
|
void setLocalDescription (mozRTCSessionDescription description,
|
||||||
optional VoidFunction successCallback,
|
optional VoidFunction successCallback,
|
||||||
optional RTCPeerConnectionErrorCallback failureCallback);
|
optional RTCPeerConnectionErrorCallback failureCallback);
|
||||||
|
@ -108,8 +87,7 @@ interface mozRTCPeerConnection : EventTarget {
|
||||||
readonly attribute mozRTCSessionDescription? localDescription;
|
readonly attribute mozRTCSessionDescription? localDescription;
|
||||||
readonly attribute mozRTCSessionDescription? remoteDescription;
|
readonly attribute mozRTCSessionDescription? remoteDescription;
|
||||||
readonly attribute RTCSignalingState signalingState;
|
readonly attribute RTCSignalingState signalingState;
|
||||||
void updateIce (optional RTCConfiguration configuration,
|
void updateIce (optional RTCConfiguration configuration);
|
||||||
optional MediaConstraints constraints);
|
|
||||||
void addIceCandidate (mozRTCIceCandidate candidate,
|
void addIceCandidate (mozRTCIceCandidate candidate,
|
||||||
optional VoidFunction successCallback,
|
optional VoidFunction successCallback,
|
||||||
optional RTCPeerConnectionErrorCallback failureCallback);
|
optional RTCPeerConnectionErrorCallback failureCallback);
|
||||||
|
@ -121,10 +99,11 @@ interface mozRTCPeerConnection : EventTarget {
|
||||||
[ChromeOnly]
|
[ChromeOnly]
|
||||||
readonly attribute DOMString id;
|
readonly attribute DOMString id;
|
||||||
|
|
||||||
|
RTCConfiguration getConfiguration ();
|
||||||
sequence<MediaStream> getLocalStreams ();
|
sequence<MediaStream> getLocalStreams ();
|
||||||
sequence<MediaStream> getRemoteStreams ();
|
sequence<MediaStream> getRemoteStreams ();
|
||||||
MediaStream? getStreamById (DOMString streamId);
|
MediaStream? getStreamById (DOMString streamId);
|
||||||
void addStream (MediaStream stream, optional MediaConstraints constraints);
|
void addStream (MediaStream stream);
|
||||||
void removeStream (MediaStream stream);
|
void removeStream (MediaStream stream);
|
||||||
void close ();
|
void close ();
|
||||||
attribute EventHandler onnegotiationneeded;
|
attribute EventHandler onnegotiationneeded;
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
|
||||||
#include "mozilla/Preferences.h"
|
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
#include "mozilla/dom/DOMError.h"
|
#include "mozilla/dom/DOMError.h"
|
||||||
#include "mozilla/dom/ErrorEvent.h"
|
#include "mozilla/dom/ErrorEvent.h"
|
||||||
|
@ -299,12 +298,15 @@ FinishFetchOnMainThreadRunnable::Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceWorkerRegistration::ServiceWorkerRegistration(const nsACString& aScope)
|
ServiceWorkerRegistration::ServiceWorkerRegistration(const nsACString& aScope)
|
||||||
: mScope(aScope),
|
: mControlledDocumentsCounter(0),
|
||||||
|
mScope(aScope),
|
||||||
mPendingUninstall(false)
|
mPendingUninstall(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
ServiceWorkerRegistration::~ServiceWorkerRegistration()
|
ServiceWorkerRegistration::~ServiceWorkerRegistration()
|
||||||
{ }
|
{
|
||||||
|
MOZ_ASSERT(!IsControllingDocuments());
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
// ServiceWorkerManager //
|
// ServiceWorkerManager //
|
||||||
|
@ -360,6 +362,9 @@ public:
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
Run()
|
Run()
|
||||||
{
|
{
|
||||||
|
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||||
|
nsRefPtr<ServiceWorkerManager::ServiceWorkerDomainInfo> domainInfo = swm->GetDomainInfo(mScriptURI);
|
||||||
|
if (!domainInfo) {
|
||||||
nsCString domain;
|
nsCString domain;
|
||||||
nsresult rv = mScriptURI->GetHost(domain);
|
nsresult rv = mScriptURI->GetHost(domain);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
@ -367,11 +372,6 @@ public:
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
|
||||||
nsRefPtr<ServiceWorkerManager::ServiceWorkerDomainInfo> domainInfo;
|
|
||||||
// XXXnsm: This pattern can be refactored if we end up using it
|
|
||||||
// often enough.
|
|
||||||
if (!swm->mDomainMap.Get(domain, getter_AddRefs(domainInfo))) {
|
|
||||||
domainInfo = new ServiceWorkerManager::ServiceWorkerDomainInfo;
|
domainInfo = new ServiceWorkerManager::ServiceWorkerDomainInfo;
|
||||||
swm->mDomainMap.Put(domain, domainInfo);
|
swm->mDomainMap.Put(domain, domainInfo);
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ public:
|
||||||
domainInfo->GetRegistration(mScope);
|
domainInfo->GetRegistration(mScope);
|
||||||
|
|
||||||
nsCString spec;
|
nsCString spec;
|
||||||
rv = mScriptURI->GetSpec(spec);
|
nsresult rv = mScriptURI->GetSpec(spec);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
mPromise->MaybeReject(rv);
|
mPromise->MaybeReject(rv);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -399,12 +399,12 @@ public:
|
||||||
// There is no update in progress and since SW updating is upto the UA,
|
// There is no update in progress and since SW updating is upto the UA,
|
||||||
// we will not update right now. Simply resolve with whatever worker we
|
// we will not update right now. Simply resolve with whatever worker we
|
||||||
// have.
|
// have.
|
||||||
ServiceWorkerInfo info = registration->Newest();
|
nsRefPtr<ServiceWorkerInfo> info = registration->Newest();
|
||||||
if (info.IsValid()) {
|
if (info) {
|
||||||
nsRefPtr<ServiceWorker> serviceWorker;
|
nsRefPtr<ServiceWorker> serviceWorker;
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
swm->CreateServiceWorkerForWindow(mWindow,
|
swm->CreateServiceWorkerForWindow(mWindow,
|
||||||
info.GetScriptSpec(),
|
info->GetScriptSpec(),
|
||||||
registration->mScope,
|
registration->mScope,
|
||||||
getter_AddRefs(serviceWorker));
|
getter_AddRefs(serviceWorker));
|
||||||
|
|
||||||
|
@ -563,14 +563,14 @@ ServiceWorkerManager::Update(ServiceWorkerRegistration* aRegistration,
|
||||||
aRegistration->mUpdateInstance = nullptr;
|
aRegistration->mUpdateInstance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aRegistration->mInstallingWorker.IsValid()) {
|
if (aRegistration->mInstallingWorker) {
|
||||||
// FIXME(nsm): Terminate the worker. We still haven't figured out worker
|
// FIXME(nsm): Terminate the worker. We still haven't figured out worker
|
||||||
// instance ownership when not associated with a window, so let's wait on
|
// instance ownership when not associated with a window, so let's wait on
|
||||||
// this.
|
// this.
|
||||||
// FIXME(nsm): We should be setting the state on the actual worker
|
// FIXME(nsm): We should be setting the state on the actual worker
|
||||||
// instance.
|
// instance.
|
||||||
// FIXME(nsm): Fire "statechange" on installing worker instance.
|
// FIXME(nsm): Fire "statechange" on installing worker instance.
|
||||||
aRegistration->mInstallingWorker.Invalidate();
|
aRegistration->mInstallingWorker = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
aRegistration->mUpdatePromise = new UpdatePromise();
|
aRegistration->mUpdatePromise = new UpdatePromise();
|
||||||
|
@ -657,7 +657,7 @@ ServiceWorkerManager::FinishFetch(ServiceWorkerRegistration* aRegistration,
|
||||||
|
|
||||||
ResolveRegisterPromises(aRegistration, aRegistration->mScriptSpec);
|
ResolveRegisterPromises(aRegistration, aRegistration->mScriptSpec);
|
||||||
|
|
||||||
ServiceWorkerInfo info(aRegistration->mScriptSpec);
|
nsRefPtr<ServiceWorkerInfo> info = new ServiceWorkerInfo(aRegistration->mScriptSpec);
|
||||||
Install(aRegistration, info);
|
Install(aRegistration, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,14 +680,8 @@ ServiceWorkerManager::HandleError(JSContext* aCx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCString domain;
|
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(uri);
|
||||||
rv = uri->GetHost(domain);
|
if (!domainInfo) {
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo;
|
|
||||||
if (!mDomainMap.Get(domain, getter_AddRefs(domainInfo))) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -760,7 +754,7 @@ public:
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
// FIXME(nsm): Change installing worker state to redundant.
|
// FIXME(nsm): Change installing worker state to redundant.
|
||||||
// FIXME(nsm): Fire statechange.
|
// FIXME(nsm): Fire statechange.
|
||||||
mRegistration->mInstallingWorker.Invalidate();
|
mRegistration->mInstallingWorker = nullptr;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -881,7 +875,7 @@ private:
|
||||||
|
|
||||||
void
|
void
|
||||||
ServiceWorkerManager::Install(ServiceWorkerRegistration* aRegistration,
|
ServiceWorkerManager::Install(ServiceWorkerRegistration* aRegistration,
|
||||||
ServiceWorkerInfo aServiceWorkerInfo)
|
ServiceWorkerInfo* aServiceWorkerInfo)
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
aRegistration->mInstallingWorker = aServiceWorkerInfo;
|
aRegistration->mInstallingWorker = aServiceWorkerInfo;
|
||||||
|
@ -891,12 +885,12 @@ ServiceWorkerManager::Install(ServiceWorkerRegistration* aRegistration,
|
||||||
|
|
||||||
nsRefPtr<ServiceWorker> serviceWorker;
|
nsRefPtr<ServiceWorker> serviceWorker;
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
CreateServiceWorker(aServiceWorkerInfo.GetScriptSpec(),
|
CreateServiceWorker(aServiceWorkerInfo->GetScriptSpec(),
|
||||||
aRegistration->mScope,
|
aRegistration->mScope,
|
||||||
getter_AddRefs(serviceWorker));
|
getter_AddRefs(serviceWorker));
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
aRegistration->mInstallingWorker.Invalidate();
|
aRegistration->mInstallingWorker = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,12 +930,11 @@ ServiceWorkerManager::FinishInstall(ServiceWorkerRegistration* aRegistration)
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
if (aRegistration->mWaitingWorker.IsValid()) {
|
if (aRegistration->mWaitingWorker) {
|
||||||
// FIXME(nsm): Actually update the state of active ServiceWorker instances.
|
// FIXME(nsm): Actually update the state of active ServiceWorker instances.
|
||||||
}
|
}
|
||||||
|
|
||||||
aRegistration->mWaitingWorker = aRegistration->mInstallingWorker;
|
aRegistration->mWaitingWorker = aRegistration->mInstallingWorker.forget();
|
||||||
aRegistration->mInstallingWorker.Invalidate();
|
|
||||||
|
|
||||||
// FIXME(nsm): Actually update state of active ServiceWorker instances to
|
// FIXME(nsm): Actually update state of active ServiceWorker instances to
|
||||||
// installed.
|
// installed.
|
||||||
|
@ -995,8 +988,8 @@ ServiceWorkerManager::CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
|
||||||
already_AddRefed<ServiceWorkerRegistration>
|
already_AddRefed<ServiceWorkerRegistration>
|
||||||
ServiceWorkerManager::GetServiceWorkerRegistration(nsPIDOMWindow* aWindow)
|
ServiceWorkerManager::GetServiceWorkerRegistration(nsPIDOMWindow* aWindow)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIURI> documentURI = aWindow->GetDocumentURI();
|
nsCOMPtr<nsIDocument> document = aWindow->GetExtantDoc();
|
||||||
return GetServiceWorkerRegistration(documentURI);
|
return GetServiceWorkerRegistration(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<ServiceWorkerRegistration>
|
already_AddRefed<ServiceWorkerRegistration>
|
||||||
|
@ -1158,6 +1151,53 @@ ServiceWorkerManager::GetDomainInfo(const nsCString& aURL)
|
||||||
return GetDomainInfo(uri);
|
return GetDomainInfo(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc)
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
if (!Preferences::GetBool("dom.serviceWorkers.enabled")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDoc);
|
||||||
|
if (!domainInfo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<ServiceWorkerRegistration> registration =
|
||||||
|
GetServiceWorkerRegistration(aDoc);
|
||||||
|
if (registration) {
|
||||||
|
MOZ_ASSERT(!domainInfo->mControlledDocuments.Contains(aDoc));
|
||||||
|
registration->StartControllingADocument();
|
||||||
|
// Use the already_AddRefed<> form of Put to avoid the addref-deref since
|
||||||
|
// we don't need the registration pointer in this function anymore.
|
||||||
|
domainInfo->mControlledDocuments.Put(aDoc, registration.forget());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceWorkerManager::MaybeStopControlling(nsIDocument* aDoc)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aDoc);
|
||||||
|
if (!Preferences::GetBool("dom.serviceWorkers.enabled")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDoc);
|
||||||
|
if (!domainInfo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<ServiceWorkerRegistration> registration;
|
||||||
|
domainInfo->mControlledDocuments.Remove(aDoc, getter_AddRefs(registration));
|
||||||
|
// A document which was uncontrolled does not maintain that state itself, so
|
||||||
|
// it will always call MaybeStopControlling() even if there isn't an
|
||||||
|
// associated registration. So this check is required.
|
||||||
|
if (registration) {
|
||||||
|
registration->StopControllingADocument();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
ServiceWorkerManager::GetScopeForUrl(const nsAString& aUrl, nsAString& aScope)
|
ServiceWorkerManager::GetScopeForUrl(const nsAString& aUrl, nsAString& aScope)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/ServiceWorkerContainer.h"
|
#include "mozilla/dom/ServiceWorkerContainer.h"
|
||||||
|
@ -72,35 +73,22 @@ private:
|
||||||
* _GetNewestWorker(serviceWorkerRegistration)", we represent the description
|
* _GetNewestWorker(serviceWorkerRegistration)", we represent the description
|
||||||
* by this class and spawn a ServiceWorker in the right global when required.
|
* by this class and spawn a ServiceWorker in the right global when required.
|
||||||
*/
|
*/
|
||||||
class ServiceWorkerInfo
|
class ServiceWorkerInfo MOZ_FINAL
|
||||||
{
|
{
|
||||||
nsCString mScriptSpec;
|
nsCString mScriptSpec;
|
||||||
|
|
||||||
|
~ServiceWorkerInfo()
|
||||||
|
{ }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(ServiceWorkerInfo)
|
||||||
bool
|
|
||||||
IsValid() const
|
|
||||||
{
|
|
||||||
return !mScriptSpec.IsVoid();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Invalidate()
|
|
||||||
{
|
|
||||||
mScriptSpec.SetIsVoid(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const nsCString&
|
const nsCString&
|
||||||
GetScriptSpec() const
|
GetScriptSpec() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsValid());
|
|
||||||
return mScriptSpec;
|
return mScriptSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceWorkerInfo()
|
|
||||||
{
|
|
||||||
Invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit ServiceWorkerInfo(const nsACString& aScriptSpec)
|
explicit ServiceWorkerInfo(const nsACString& aScriptSpec)
|
||||||
: mScriptSpec(aScriptSpec)
|
: mScriptSpec(aScriptSpec)
|
||||||
{ }
|
{ }
|
||||||
|
@ -110,6 +98,8 @@ public:
|
||||||
// non-ISupports classes.
|
// non-ISupports classes.
|
||||||
class ServiceWorkerRegistration MOZ_FINAL : public nsISupports
|
class ServiceWorkerRegistration MOZ_FINAL : public nsISupports
|
||||||
{
|
{
|
||||||
|
uint32_t mControlledDocumentsCounter;
|
||||||
|
|
||||||
virtual ~ServiceWorkerRegistration();
|
virtual ~ServiceWorkerRegistration();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -120,9 +110,9 @@ public:
|
||||||
// the URLs of the following three workers.
|
// the URLs of the following three workers.
|
||||||
nsCString mScriptSpec;
|
nsCString mScriptSpec;
|
||||||
|
|
||||||
ServiceWorkerInfo mCurrentWorker;
|
nsRefPtr<ServiceWorkerInfo> mCurrentWorker;
|
||||||
ServiceWorkerInfo mWaitingWorker;
|
nsRefPtr<ServiceWorkerInfo> mWaitingWorker;
|
||||||
ServiceWorkerInfo mInstallingWorker;
|
nsRefPtr<ServiceWorkerInfo> mInstallingWorker;
|
||||||
|
|
||||||
nsAutoPtr<UpdatePromise> mUpdatePromise;
|
nsAutoPtr<UpdatePromise> mUpdatePromise;
|
||||||
nsRefPtr<ServiceWorkerUpdateInstance> mUpdateInstance;
|
nsRefPtr<ServiceWorkerUpdateInstance> mUpdateInstance;
|
||||||
|
@ -147,16 +137,37 @@ public:
|
||||||
|
|
||||||
explicit ServiceWorkerRegistration(const nsACString& aScope);
|
explicit ServiceWorkerRegistration(const nsACString& aScope);
|
||||||
|
|
||||||
ServiceWorkerInfo
|
already_AddRefed<ServiceWorkerInfo>
|
||||||
Newest() const
|
Newest()
|
||||||
{
|
{
|
||||||
if (mInstallingWorker.IsValid()) {
|
nsRefPtr<ServiceWorkerInfo> newest;
|
||||||
return mInstallingWorker;
|
if (mInstallingWorker) {
|
||||||
} else if (mWaitingWorker.IsValid()) {
|
newest = mInstallingWorker;
|
||||||
return mWaitingWorker;
|
} else if (mWaitingWorker) {
|
||||||
|
newest = mWaitingWorker;
|
||||||
} else {
|
} else {
|
||||||
return mCurrentWorker;
|
newest = mCurrentWorker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return newest.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StartControllingADocument()
|
||||||
|
{
|
||||||
|
++mControlledDocumentsCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StopControllingADocument()
|
||||||
|
{
|
||||||
|
--mControlledDocumentsCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsControllingDocuments() const
|
||||||
|
{
|
||||||
|
return mControlledDocumentsCounter > 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -186,6 +197,11 @@ public:
|
||||||
|
|
||||||
static ServiceWorkerManager* FactoryCreate()
|
static ServiceWorkerManager* FactoryCreate()
|
||||||
{
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
if (!Preferences::GetBool("dom.serviceWorkers.enabled")) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ServiceWorkerManager* res = new ServiceWorkerManager;
|
ServiceWorkerManager* res = new ServiceWorkerManager;
|
||||||
NS_ADDREF(res);
|
NS_ADDREF(res);
|
||||||
return res;
|
return res;
|
||||||
|
@ -216,6 +232,8 @@ public:
|
||||||
// The containers inform the SWM on creation and destruction.
|
// The containers inform the SWM on creation and destruction.
|
||||||
nsTObserverArray<ServiceWorkerContainer*> mServiceWorkerContainers;
|
nsTObserverArray<ServiceWorkerContainer*> mServiceWorkerContainers;
|
||||||
|
|
||||||
|
nsRefPtrHashtable<nsISupportsHashKey, ServiceWorkerRegistration> mControlledDocuments;
|
||||||
|
|
||||||
ServiceWorkerDomainInfo()
|
ServiceWorkerDomainInfo()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -290,7 +308,7 @@ private:
|
||||||
|
|
||||||
void
|
void
|
||||||
Install(ServiceWorkerRegistration* aRegistration,
|
Install(ServiceWorkerRegistration* aRegistration,
|
||||||
ServiceWorkerInfo aServiceWorkerInfo);
|
ServiceWorkerInfo* aServiceWorkerInfo);
|
||||||
|
|
||||||
NS_IMETHOD
|
NS_IMETHOD
|
||||||
CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
|
CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
|
||||||
|
|
|
@ -46,10 +46,10 @@
|
||||||
#include "nsIScriptContext.h"
|
#include "nsIScriptContext.h"
|
||||||
#include "xpcpublic.h"
|
#include "xpcpublic.h"
|
||||||
#include "jswrapper.h"
|
#include "jswrapper.h"
|
||||||
#include "nsCxPusher.h"
|
|
||||||
|
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "mozilla/dom/NodeListBinding.h"
|
#include "mozilla/dom/NodeListBinding.h"
|
||||||
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
@ -638,21 +638,9 @@ nsBindingManager::GetBindingImplementation(nsIContent* aContent, REFNSIID aIID,
|
||||||
|
|
||||||
// We have never made a wrapper for this implementation.
|
// We have never made a wrapper for this implementation.
|
||||||
// Create an XPC wrapper for the script object and hand it back.
|
// Create an XPC wrapper for the script object and hand it back.
|
||||||
|
AutoJSAPI jsapi;
|
||||||
nsIDocument* doc = aContent->OwnerDoc();
|
jsapi.Init();
|
||||||
|
JSContext* cx = jsapi.cx();
|
||||||
nsCOMPtr<nsIScriptGlobalObject> global =
|
|
||||||
do_QueryInterface(doc->GetWindow());
|
|
||||||
if (!global)
|
|
||||||
return NS_NOINTERFACE;
|
|
||||||
|
|
||||||
nsIScriptContext *context = global->GetContext();
|
|
||||||
if (!context)
|
|
||||||
return NS_NOINTERFACE;
|
|
||||||
|
|
||||||
AutoPushJSContext cx(context->GetNativeContext());
|
|
||||||
if (!cx)
|
|
||||||
return NS_NOINTERFACE;
|
|
||||||
|
|
||||||
nsIXPConnect *xpConnect = nsContentUtils::XPConnect();
|
nsIXPConnect *xpConnect = nsContentUtils::XPConnect();
|
||||||
|
|
||||||
|
@ -666,8 +654,7 @@ nsBindingManager::GetBindingImplementation(nsIContent* aContent, REFNSIID aIID,
|
||||||
// because they're chrome-only and no Xrays are involved.
|
// because they're chrome-only and no Xrays are involved.
|
||||||
//
|
//
|
||||||
// If there's no separate XBL scope, or if the reflector itself lives in
|
// If there's no separate XBL scope, or if the reflector itself lives in
|
||||||
// the XBL scope, we'll end up with the global of the reflector, and this
|
// the XBL scope, we'll end up with the global of the reflector.
|
||||||
// will all be a no-op.
|
|
||||||
JS::Rooted<JSObject*> xblScope(cx, xpc::GetXBLScopeOrGlobal(cx, jsobj));
|
JS::Rooted<JSObject*> xblScope(cx, xpc::GetXBLScopeOrGlobal(cx, jsobj));
|
||||||
JSAutoCompartment ac(cx, xblScope);
|
JSAutoCompartment ac(cx, xblScope);
|
||||||
bool ok = JS_WrapObject(cx, &jsobj);
|
bool ok = JS_WrapObject(cx, &jsobj);
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
#include "nsXBLPrototypeBinding.h"
|
#include "nsXBLPrototypeBinding.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsCxPusher.h"
|
#include "nsCxPusher.h"
|
||||||
|
#include "nsGlobalWindow.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsIAtom.h"
|
#include "nsIAtom.h"
|
||||||
#include "nsIDOMKeyEvent.h"
|
#include "nsIDOMKeyEvent.h"
|
||||||
#include "nsIDOMMouseEvent.h"
|
#include "nsIDOMMouseEvent.h"
|
||||||
#include "nsNameSpaceManager.h"
|
#include "nsNameSpaceManager.h"
|
||||||
#include "nsIScriptContext.h"
|
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIController.h"
|
#include "nsIController.h"
|
||||||
#include "nsIControllers.h"
|
#include "nsIControllers.h"
|
||||||
|
@ -46,6 +46,8 @@
|
||||||
#include "mozilla/JSEventHandler.h"
|
#include "mozilla/JSEventHandler.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/dom/EventHandlerBinding.h"
|
#include "mozilla/dom/EventHandlerBinding.h"
|
||||||
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
|
#include "xpcpublic.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
@ -259,10 +261,6 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
|
||||||
if (!boundGlobal)
|
if (!boundGlobal)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
nsIScriptContext *boundContext = boundGlobal->GetScriptContext();
|
|
||||||
if (!boundContext)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
nsISupports *scriptTarget;
|
nsISupports *scriptTarget;
|
||||||
|
|
||||||
if (winRoot) {
|
if (winRoot) {
|
||||||
|
@ -271,16 +269,17 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
|
||||||
scriptTarget = aTarget;
|
scriptTarget = aTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're about to create a new JSEventHandler, which means that we're
|
// We're about to create a new JSEventHandler, which means that we need to
|
||||||
// responsible for pushing the context of the event target. See the similar
|
// Initiatize an AutoJSAPI with aTarget's bound global to make sure any errors
|
||||||
// comment in nsEventManagerListener.cpp.
|
// are reported to the correct place.
|
||||||
nsCxPusher pusher;
|
AutoJSAPI jsapi;
|
||||||
NS_ENSURE_STATE(pusher.Push(aTarget));
|
if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(boundGlobal))) {
|
||||||
|
return NS_OK;
|
||||||
AutoPushJSContext cx(boundContext->GetNativeContext());
|
}
|
||||||
|
JSContext* cx = jsapi.cx();
|
||||||
JS::Rooted<JSObject*> handler(cx);
|
JS::Rooted<JSObject*> handler(cx);
|
||||||
|
|
||||||
rv = EnsureEventHandler(boundGlobal, boundContext, onEventAtom, &handler);
|
rv = EnsureEventHandler(jsapi, onEventAtom, &handler);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
|
JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
|
||||||
|
@ -338,15 +337,14 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsXBLPrototypeHandler::EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
|
nsXBLPrototypeHandler::EnsureEventHandler(AutoJSAPI& jsapi, nsIAtom* aName,
|
||||||
nsIScriptContext *aBoundContext,
|
|
||||||
nsIAtom *aName,
|
|
||||||
JS::MutableHandle<JSObject*> aHandler)
|
JS::MutableHandle<JSObject*> aHandler)
|
||||||
{
|
{
|
||||||
AutoPushJSContext cx(aBoundContext->GetNativeContext());
|
JSContext* cx = jsapi.cx();
|
||||||
|
|
||||||
// Check to see if we've already compiled this
|
// Check to see if we've already compiled this
|
||||||
nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aGlobal);
|
JS::Rooted<JSObject*> globalObject(cx, JS::CurrentGlobalOrNull(cx));
|
||||||
|
nsCOMPtr<nsPIDOMWindow> pWindow = xpc::WindowOrNull(globalObject);
|
||||||
if (pWindow) {
|
if (pWindow) {
|
||||||
JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this));
|
JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this));
|
||||||
if (cachedHandler) {
|
if (cachedHandler) {
|
||||||
|
@ -363,7 +361,6 @@ nsXBLPrototypeHandler::EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
|
||||||
|
|
||||||
JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
|
JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
|
||||||
|
|
||||||
JS::Rooted<JSObject*> globalObject(cx, aGlobal->GetGlobalJSObject());
|
|
||||||
JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
|
JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
|
||||||
NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "nsXBLEventHandler.h"
|
#include "nsXBLEventHandler.h"
|
||||||
#include "nsIWeakReference.h"
|
#include "nsIWeakReference.h"
|
||||||
#include "nsIScriptGlobalObject.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
#include "js/TypeDecls.h"
|
#include "js/TypeDecls.h"
|
||||||
|
|
||||||
|
@ -28,6 +27,7 @@ class nsXBLPrototypeBinding;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
class AutoJSAPI;
|
||||||
class EventTarget;
|
class EventTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,8 +166,7 @@ protected:
|
||||||
bool aIgnoreShiftKey = false);
|
bool aIgnoreShiftKey = false);
|
||||||
nsresult DispatchXBLCommand(mozilla::dom::EventTarget* aTarget, nsIDOMEvent* aEvent);
|
nsresult DispatchXBLCommand(mozilla::dom::EventTarget* aTarget, nsIDOMEvent* aEvent);
|
||||||
nsresult DispatchXULKeyCommand(nsIDOMEvent* aEvent);
|
nsresult DispatchXULKeyCommand(nsIDOMEvent* aEvent);
|
||||||
nsresult EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
|
nsresult EnsureEventHandler(mozilla::dom::AutoJSAPI& jsapi, nsIAtom* aName,
|
||||||
nsIScriptContext *aBoundContext, nsIAtom *aName,
|
|
||||||
JS::MutableHandle<JSObject*> aHandler);
|
JS::MutableHandle<JSObject*> aHandler);
|
||||||
static int32_t KeyToMask(int32_t key);
|
static int32_t KeyToMask(int32_t key);
|
||||||
static int32_t AccelKeyMask();
|
static int32_t AccelKeyMask();
|
||||||
|
|
|
@ -272,8 +272,8 @@ float Axis::ScaleWillOverscrollAmount(float aScale, float aFocus) {
|
||||||
float originAfterScale = (GetOrigin() + aFocus) - (aFocus / aScale);
|
float originAfterScale = (GetOrigin() + aFocus) - (aFocus / aScale);
|
||||||
|
|
||||||
bool both = ScaleWillOverscrollBothSides(aScale);
|
bool both = ScaleWillOverscrollBothSides(aScale);
|
||||||
bool minus = originAfterScale < GetPageStart();
|
bool minus = GetPageStart() - originAfterScale > COORDINATE_EPSILON;
|
||||||
bool plus = (originAfterScale + (GetCompositionLength() / aScale)) > GetPageEnd();
|
bool plus = (originAfterScale + (GetCompositionLength() / aScale)) - GetPageEnd() > COORDINATE_EPSILON;
|
||||||
|
|
||||||
if ((minus && plus) || both) {
|
if ((minus && plus) || both) {
|
||||||
// If we ever reach here it's a bug in the client code.
|
// If we ever reach here it's a bug in the client code.
|
||||||
|
@ -330,7 +330,7 @@ bool Axis::ScaleWillOverscrollBothSides(float aScale) {
|
||||||
CSSToParentLayerScale scale(metrics.GetZoomToParent().scale * aScale);
|
CSSToParentLayerScale scale(metrics.GetZoomToParent().scale * aScale);
|
||||||
CSSRect cssCompositionBounds = metrics.mCompositionBounds / scale;
|
CSSRect cssCompositionBounds = metrics.mCompositionBounds / scale;
|
||||||
|
|
||||||
return GetRectLength(metrics.GetExpandedScrollableRect()) < GetRectLength(cssCompositionBounds);
|
return GetRectLength(cssCompositionBounds) - GetRectLength(metrics.GetExpandedScrollableRect()) > COORDINATE_EPSILON;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FrameMetrics& Axis::GetFrameMetrics() const {
|
const FrameMetrics& Axis::GetFrameMetrics() const {
|
||||||
|
|
|
@ -141,8 +141,13 @@ static void
|
||||||
TranslateShadowLayer2D(Layer* aLayer,
|
TranslateShadowLayer2D(Layer* aLayer,
|
||||||
const gfxPoint& aTranslation)
|
const gfxPoint& aTranslation)
|
||||||
{
|
{
|
||||||
|
// This layer might also be a scrollable layer and have an async transform.
|
||||||
|
// To make sure we don't clobber that, we start with the shadow transform.
|
||||||
|
// Any adjustments to the shadow transform made in this function in previous
|
||||||
|
// frames have been cleared in ClearAsyncTransforms(), so such adjustments
|
||||||
|
// will not compound over successive frames.
|
||||||
Matrix layerTransform;
|
Matrix layerTransform;
|
||||||
if (!GetBaseTransform2D(aLayer, &layerTransform)) {
|
if (!aLayer->GetLocalTransform().Is2D(&layerTransform)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,6 +899,18 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer)
|
||||||
aLayer->GetLocalTransform(), fixedLayerMargins);
|
aLayer->GetLocalTransform(), fixedLayerMargins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClearAsyncTransforms(Layer* aLayer)
|
||||||
|
{
|
||||||
|
if (!aLayer->AsLayerComposite()->GetShadowTransformSetByAnimation()) {
|
||||||
|
aLayer->AsLayerComposite()->SetShadowTransform(aLayer->GetBaseTransform());
|
||||||
|
}
|
||||||
|
for (Layer* child = aLayer->GetFirstChild();
|
||||||
|
child; child = child->GetNextSibling()) {
|
||||||
|
ClearAsyncTransforms(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame)
|
AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame)
|
||||||
{
|
{
|
||||||
|
@ -909,6 +926,12 @@ AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame)
|
||||||
// transforms.
|
// transforms.
|
||||||
bool wantNextFrame = SampleAnimations(root, aCurrentFrame);
|
bool wantNextFrame = SampleAnimations(root, aCurrentFrame);
|
||||||
|
|
||||||
|
// Clear any async transforms (not due to animations) set in previous frames.
|
||||||
|
// This is necessary because some things called by
|
||||||
|
// ApplyAsyncContentTransformToTree (in particular, TranslateShadowLayer2D),
|
||||||
|
// add to the shadow transform rather than overwriting it.
|
||||||
|
ClearAsyncTransforms(root);
|
||||||
|
|
||||||
// FIXME/bug 775437: unify this interface with the ~native-fennec
|
// FIXME/bug 775437: unify this interface with the ~native-fennec
|
||||||
// derived code
|
// derived code
|
||||||
//
|
//
|
||||||
|
|
|
@ -220,12 +220,6 @@ def main(argv):
|
||||||
|
|
||||||
prefix += ['-f', prolog]
|
prefix += ['-f', prolog]
|
||||||
|
|
||||||
# Avoid racing on the cache by having the js shell create a new cache
|
|
||||||
# subdir for each process. The js shell takes care of deleting these
|
|
||||||
# subdirs when the process exits.
|
|
||||||
if options.max_jobs > 1 and jittests.HAVE_MULTIPROCESSING:
|
|
||||||
prefix += ['--js-cache-per-process']
|
|
||||||
|
|
||||||
# Clean up any remnants from previous crashes etc
|
# Clean up any remnants from previous crashes etc
|
||||||
shutil.rmtree(jittests.JS_CACHE_DIR, ignore_errors=True)
|
shutil.rmtree(jittests.JS_CACHE_DIR, ignore_errors=True)
|
||||||
os.mkdir(jittests.JS_CACHE_DIR)
|
os.mkdir(jittests.JS_CACHE_DIR)
|
||||||
|
|
|
@ -35,7 +35,7 @@ function asmCompileCached()
|
||||||
for (var i = 0; i < arguments.length; i++)
|
for (var i = 0; i < arguments.length; i++)
|
||||||
quotedArgs.push("'" + arguments[i] + "'");
|
quotedArgs.push("'" + arguments[i] + "'");
|
||||||
var code = "var f = new Function(" + quotedArgs.join(',') + ");assertEq(isAsmJSModule(f), true);";
|
var code = "var f = new Function(" + quotedArgs.join(',') + ");assertEq(isAsmJSModule(f), true);";
|
||||||
nestedShell("--js-cache", "--execute=" + code);
|
nestedShell("--js-cache", "--no-js-cache-per-process", "--execute=" + code);
|
||||||
|
|
||||||
var f = Function.apply(null, arguments);
|
var f = Function.apply(null, arguments);
|
||||||
assertEq(isAsmJSModuleLoadedFromCache(f), true);
|
assertEq(isAsmJSModuleLoadedFromCache(f), true);
|
||||||
|
|
|
@ -10,7 +10,7 @@ if (!isAsmJSCompilationAvailable())
|
||||||
// nestedShell() (and the loadedFromCache assertion) to see if the error
|
// nestedShell() (and the loadedFromCache assertion) to see if the error
|
||||||
// reproduces.
|
// reproduces.
|
||||||
var code = "setIonCheckGraphCoherency(false); load('" + libdir + "bullet.js'); runBullet()";
|
var code = "setIonCheckGraphCoherency(false); load('" + libdir + "bullet.js'); runBullet()";
|
||||||
nestedShell("--js-cache", "--execute=" + code);
|
nestedShell("--js-cache", "--no-js-cache-per-process", "--execute=" + code);
|
||||||
setIonCheckGraphCoherency(false);
|
setIonCheckGraphCoherency(false);
|
||||||
load(libdir + 'bullet.js');
|
load(libdir + 'bullet.js');
|
||||||
var results = runBullet();
|
var results = runBullet();
|
||||||
|
|
|
@ -22,6 +22,33 @@ assertEq(f(0x7f),0x7f);
|
||||||
assertEq(f(0xff),-1);
|
assertEq(f(0xff),-1);
|
||||||
assertEq(f(0x100),0);
|
assertEq(f(0x100),0);
|
||||||
|
|
||||||
|
// Test signal handlers deactivation
|
||||||
|
(function() {
|
||||||
|
var jco = getJitCompilerOptions();
|
||||||
|
var signalHandlersBefore = jco["signals.enable"];
|
||||||
|
if (signalHandlersBefore == 1) {
|
||||||
|
setJitCompilerOption("signals.enable", 0);
|
||||||
|
|
||||||
|
if (isCachingEnabled()) {
|
||||||
|
// Cloned modules should fail on linking if the initial module has
|
||||||
|
// been compiled with signals but signals are deactivated.
|
||||||
|
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[0]|0}; return f');
|
||||||
|
assertAsmLinkFail(code, this, null, new ArrayBuffer(4096));
|
||||||
|
}
|
||||||
|
|
||||||
|
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + '/* not a clone */ function f(i) {i=i|0; i32[0] = i; return i8[0]|0}; return f');
|
||||||
|
var f = asmLink(code, this, null, new ArrayBuffer(4096));
|
||||||
|
assertEq(f(0),0);
|
||||||
|
assertEq(f(0x7f),0x7f);
|
||||||
|
assertEq(f(0xff),-1);
|
||||||
|
assertEq(f(0x100),0);
|
||||||
|
setJitCompilerOption("signals.enable", 1);
|
||||||
|
}
|
||||||
|
jco = getJitCompilerOptions();
|
||||||
|
var signalHandlersAfter = jco["signals.enable"];
|
||||||
|
assertEq(signalHandlersBefore, signalHandlersAfter);
|
||||||
|
})();
|
||||||
|
|
||||||
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[0]|0}; return f');
|
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[0]|0}; return f');
|
||||||
var f = asmLink(code, this, null, new ArrayBuffer(4096));
|
var f = asmLink(code, this, null, new ArrayBuffer(4096));
|
||||||
assertEq(f(0),0);
|
assertEq(f(0),0);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
// |jit-test| exitstatus: 6;
|
||||||
|
|
||||||
|
load(libdir + "asm.js");
|
||||||
|
|
||||||
|
var jco = getJitCompilerOptions();
|
||||||
|
if (jco["signals.enable"] === 0 || !isCachingEnabled() || !isAsmJSCompilationAvailable())
|
||||||
|
quit(6);
|
||||||
|
|
||||||
|
// Modules compiled without signal handlers should still work even if signal
|
||||||
|
// handlers have been reactivated.
|
||||||
|
setJitCompilerOption("signals.enable", 0);
|
||||||
|
|
||||||
|
var code = USE_ASM + "function f() {} function g() { while(1) { f() } } return g";
|
||||||
|
|
||||||
|
var m = asmCompile(code);
|
||||||
|
assertEq(isAsmJSModule(m), true);
|
||||||
|
assertEq(isAsmJSModuleLoadedFromCache(m), false);
|
||||||
|
|
||||||
|
setJitCompilerOption("signals.enable", 1);
|
||||||
|
|
||||||
|
var m = asmCompile(code);
|
||||||
|
assertEq(isAsmJSModule(m), true);
|
||||||
|
assertEq(isAsmJSModuleLoadedFromCache(m), true);
|
||||||
|
|
||||||
|
var g = asmLink(m);
|
||||||
|
timeout(1);
|
||||||
|
g();
|
||||||
|
assertEq(true, false);
|
|
@ -0,0 +1,9 @@
|
||||||
|
// |jit-test| exitstatus: 6;
|
||||||
|
|
||||||
|
load(libdir + "asm.js");
|
||||||
|
|
||||||
|
setJitCompilerOption("signals.enable", 0);
|
||||||
|
var g = asmLink(asmCompile(USE_ASM + "function f() {} function g() { while(1) { f() } } return g"));
|
||||||
|
timeout(1);
|
||||||
|
g();
|
||||||
|
assertEq(true, false);
|
|
@ -0,0 +1,9 @@
|
||||||
|
// |jit-test| exitstatus: 6;
|
||||||
|
|
||||||
|
load(libdir + "asm.js");
|
||||||
|
|
||||||
|
setJitCompilerOption("signals.enable", 0);
|
||||||
|
var g = asmLink(asmCompile(USE_ASM + "function g() { while(1) {} } return g"));
|
||||||
|
timeout(1);
|
||||||
|
g();
|
||||||
|
assertEq(true, false);
|
|
@ -0,0 +1,9 @@
|
||||||
|
// |jit-test| exitstatus: 6;
|
||||||
|
|
||||||
|
load(libdir + "asm.js");
|
||||||
|
|
||||||
|
setJitCompilerOption("signals.enable", 0);
|
||||||
|
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if (!i) return; f((i-1)|0); f((i-1)|0); f((i-1)|0); f((i-1)|0); f((i-1)|0); } return f"));
|
||||||
|
timeout(1);
|
||||||
|
f(100);
|
||||||
|
assertEq(true, false);
|
|
@ -0,0 +1,9 @@
|
||||||
|
// |jit-test| exitstatus: 6;
|
||||||
|
|
||||||
|
load(libdir + "asm.js");
|
||||||
|
|
||||||
|
setJitCompilerOption("signals.enable", 0);
|
||||||
|
var g = asmLink(asmCompile(USE_ASM + "function f(d) { d=+d; d=d*.1; d=d/.4; return +d } function g() { while(1) { +f(1.1) } } return g"));
|
||||||
|
timeout(1);
|
||||||
|
g();
|
||||||
|
assertEq(true, false);
|
|
@ -0,0 +1,5 @@
|
||||||
|
// |jit-test| exitstatus: 6;
|
||||||
|
|
||||||
|
setJitCompilerOption('signals.enable', 0);
|
||||||
|
timeout(1);
|
||||||
|
for(;;);
|
|
@ -6065,7 +6065,11 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
// This function and InvokeFromAsmJS* functions all return int32_t rather than
|
||||||
|
// bool to prevent the compiler from optimizing bits higher than what's
|
||||||
|
// actually needed for a bool (as the result is tested in asm.js generated code
|
||||||
|
// which the compiler isn't aware of).
|
||||||
|
static inline int32_t
|
||||||
TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
|
TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
|
||||||
int32_t argc, Value *argv)
|
int32_t argc, Value *argv)
|
||||||
{
|
{
|
||||||
|
@ -6105,64 +6109,53 @@ TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
// See comment above TryEnablingIon.
|
||||||
int32_t
|
int32_t
|
||||||
InvokeFromAsmJS_Ignore(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv)
|
InvokeFromAsmJS(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv,
|
||||||
|
MutableHandleValue rval)
|
||||||
{
|
{
|
||||||
AsmJSModule &module = cx->mainThread().asmJSActivationStackFromOwnerThread()->module();
|
AsmJSModule &module = cx->mainThread().asmJSActivationStackFromOwnerThread()->module();
|
||||||
|
|
||||||
RootedFunction fun(cx, module.exitIndexToGlobalDatum(exitIndex).fun);
|
RootedFunction fun(cx, module.exitIndexToGlobalDatum(exitIndex).fun);
|
||||||
RootedValue fval(cx, ObjectValue(*fun));
|
RootedValue fval(cx, ObjectValue(*fun));
|
||||||
|
if (!Invoke(cx, UndefinedValue(), fval, argc, argv, rval))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return TryEnablingIon(cx, module, fun, exitIndex, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
InvokeFromAsmJS_Ignore(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv)
|
||||||
|
{
|
||||||
RootedValue rval(cx);
|
RootedValue rval(cx);
|
||||||
if (!Invoke(cx, UndefinedValue(), fval, argc, argv, &rval))
|
return InvokeFromAsmJS(cx, exitIndex, argc, argv, &rval);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!TryEnablingIon(cx, module, fun, exitIndex, argc, argv))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
InvokeFromAsmJS_ToInt32(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv)
|
InvokeFromAsmJS_ToInt32(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv)
|
||||||
{
|
{
|
||||||
AsmJSModule &module = cx->mainThread().asmJSActivationStackFromOwnerThread()->module();
|
|
||||||
|
|
||||||
RootedFunction fun(cx, module.exitIndexToGlobalDatum(exitIndex).fun);
|
|
||||||
RootedValue fval(cx, ObjectValue(*fun));
|
|
||||||
RootedValue rval(cx);
|
RootedValue rval(cx);
|
||||||
if (!Invoke(cx, UndefinedValue(), fval, argc, argv, &rval))
|
if (!InvokeFromAsmJS(cx, exitIndex, argc, argv, &rval))
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!TryEnablingIon(cx, module, fun, exitIndex, argc, argv))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int32_t i32;
|
int32_t i32;
|
||||||
if (!ToInt32(cx, rval, &i32))
|
if (!ToInt32(cx, rval, &i32))
|
||||||
return false;
|
return false;
|
||||||
argv[0] = Int32Value(i32);
|
argv[0] = Int32Value(i32);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
InvokeFromAsmJS_ToNumber(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv)
|
InvokeFromAsmJS_ToNumber(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv)
|
||||||
{
|
{
|
||||||
AsmJSModule &module = cx->mainThread().asmJSActivationStackFromOwnerThread()->module();
|
|
||||||
|
|
||||||
RootedFunction fun(cx, module.exitIndexToGlobalDatum(exitIndex).fun);
|
|
||||||
RootedValue fval(cx, ObjectValue(*fun));
|
|
||||||
RootedValue rval(cx);
|
RootedValue rval(cx);
|
||||||
if (!Invoke(cx, UndefinedValue(), fval, argc, argv, &rval))
|
if (!InvokeFromAsmJS(cx, exitIndex, argc, argv, &rval))
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!TryEnablingIon(cx, module, fun, exitIndex, argc, argv))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
double dbl;
|
double dbl;
|
||||||
if (!ToNumber(cx, rval, &dbl))
|
if (!ToNumber(cx, rval, &dbl))
|
||||||
return false;
|
return false;
|
||||||
argv[0] = DoubleValue(dbl);
|
argv[0] = DoubleValue(dbl);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8808,10 +8808,11 @@ CodeGenerator::visitInterruptCheck(LInterruptCheck *lir)
|
||||||
bool
|
bool
|
||||||
CodeGenerator::visitAsmJSInterruptCheck(LAsmJSInterruptCheck *lir)
|
CodeGenerator::visitAsmJSInterruptCheck(LAsmJSInterruptCheck *lir)
|
||||||
{
|
{
|
||||||
Label rejoin;
|
|
||||||
Register scratch = ToRegister(lir->scratch());
|
Register scratch = ToRegister(lir->scratch());
|
||||||
masm.movePtr(AsmJSImmPtr(AsmJSImm_RuntimeInterrupt), scratch);
|
masm.movePtr(AsmJSImmPtr(AsmJSImm_RuntimeInterrupt), scratch);
|
||||||
masm.branchIfFalseBool(scratch, &rejoin);
|
masm.load8ZeroExtend(Address(scratch, 0), scratch);
|
||||||
|
Label rejoin;
|
||||||
|
masm.branch32(Assembler::Equal, scratch, Imm32(0), &rejoin);
|
||||||
{
|
{
|
||||||
uint32_t stackFixup = ComputeByteAlignment(masm.framePushed() + AsmJSFrameSize,
|
uint32_t stackFixup = ComputeByteAlignment(masm.framePushed() + AsmJSFrameSize,
|
||||||
StackAlignment);
|
StackAlignment);
|
||||||
|
|
|
@ -739,6 +739,12 @@ class LAsmJSInterruptCheck : public LInstructionHelper<0, 0, 1>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LInterruptCheck : public LInstructionHelper<0, 0, 0>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LIR_HEADER(InterruptCheck)
|
||||||
|
};
|
||||||
|
|
||||||
// Alternative to LInterruptCheck which does not emit an explicit check of the
|
// Alternative to LInterruptCheck which does not emit an explicit check of the
|
||||||
// interrupt flag but relies on the loop backedge being patched via a signal
|
// interrupt flag but relies on the loop backedge being patched via a signal
|
||||||
// handler.
|
// handler.
|
||||||
|
|
|
@ -397,12 +397,6 @@ class LGuardObjectType : public LInstructionHelper<0, 1, 1>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LInterruptCheck : public LInstructionHelper<0, 0, 0>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LIR_HEADER(InterruptCheck);
|
|
||||||
};
|
|
||||||
|
|
||||||
class LMulI : public LBinaryMath<0>
|
class LMulI : public LBinaryMath<0>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -345,12 +345,6 @@ class LGuardObjectType : public LInstructionHelper<0, 1, 1>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LInterruptCheck : public LInstructionHelper<0, 0, 0>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LIR_HEADER(InterruptCheck);
|
|
||||||
};
|
|
||||||
|
|
||||||
class LMulI : public LBinaryMath<0>
|
class LMulI : public LBinaryMath<0>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -295,12 +295,6 @@ class LGuardObjectType : public LInstructionHelper<0, 1, 0>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LInterruptCheck : public LInstructionHelper<0, 0, 0>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LIR_HEADER(InterruptCheck)
|
|
||||||
};
|
|
||||||
|
|
||||||
class LMulI : public LBinaryMath<0, 1>
|
class LMulI : public LBinaryMath<0, 1>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -187,15 +187,9 @@ class MacroAssemblerX86Shared : public Assembler
|
||||||
void not32(Register reg) {
|
void not32(Register reg) {
|
||||||
notl(reg);
|
notl(reg);
|
||||||
}
|
}
|
||||||
void inc32(const Operand &addr) {
|
|
||||||
incl(addr);
|
|
||||||
}
|
|
||||||
void atomic_inc32(const Operand &addr) {
|
void atomic_inc32(const Operand &addr) {
|
||||||
lock_incl(addr);
|
lock_incl(addr);
|
||||||
}
|
}
|
||||||
void dec32(const Operand &addr) {
|
|
||||||
decl(addr);
|
|
||||||
}
|
|
||||||
void atomic_dec32(const Operand &addr) {
|
void atomic_dec32(const Operand &addr) {
|
||||||
lock_decl(addr);
|
lock_decl(addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6309,6 +6309,15 @@ JS_SetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt, uint32_t v
|
||||||
IonSpew(js::jit::IonSpew_Scripts, "Disable offthread compilation");
|
IonSpew(js::jit::IonSpew_Scripts, "Disable offthread compilation");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case JSJITCOMPILER_SIGNALS_ENABLE:
|
||||||
|
if (value == 1) {
|
||||||
|
rt->setCanUseSignalHandlers(true);
|
||||||
|
IonSpew(js::jit::IonSpew_Scripts, "Enable signals");
|
||||||
|
} else if (value == 0) {
|
||||||
|
rt->setCanUseSignalHandlers(false);
|
||||||
|
IonSpew(js::jit::IonSpew_Scripts, "Disable signals");
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6330,6 +6339,8 @@ JS_GetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt)
|
||||||
return JS::RuntimeOptionsRef(rt).baseline();
|
return JS::RuntimeOptionsRef(rt).baseline();
|
||||||
case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
|
case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
|
||||||
return rt->canUseOffthreadIonCompilation();
|
return rt->canUseOffthreadIonCompilation();
|
||||||
|
case JSJITCOMPILER_SIGNALS_ENABLE:
|
||||||
|
return rt->canUseSignalHandlers();
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4926,7 +4926,8 @@ JS_SetOffthreadIonCompilationEnabled(JSRuntime *rt, bool enabled);
|
||||||
Register(ION_USECOUNT_TRIGGER, "ion.usecount.trigger") \
|
Register(ION_USECOUNT_TRIGGER, "ion.usecount.trigger") \
|
||||||
Register(ION_ENABLE, "ion.enable") \
|
Register(ION_ENABLE, "ion.enable") \
|
||||||
Register(BASELINE_ENABLE, "baseline.enable") \
|
Register(BASELINE_ENABLE, "baseline.enable") \
|
||||||
Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable")
|
Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \
|
||||||
|
Register(SIGNALS_ENABLE, "signals.enable")
|
||||||
|
|
||||||
typedef enum JSJitCompilerOption {
|
typedef enum JSJitCompilerOption {
|
||||||
#define JIT_COMPILER_DECLARE(key, str) \
|
#define JIT_COMPILER_DECLARE(key, str) \
|
||||||
|
|
|
@ -344,27 +344,35 @@ static const AllocKind FinalizePhaseScripts[] = {
|
||||||
FINALIZE_LAZY_SCRIPT
|
FINALIZE_LAZY_SCRIPT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef JS_ION
|
||||||
static const AllocKind FinalizePhaseJitCode[] = {
|
static const AllocKind FinalizePhaseJitCode[] = {
|
||||||
FINALIZE_JITCODE
|
FINALIZE_JITCODE
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static const AllocKind * const FinalizePhases[] = {
|
static const AllocKind * const FinalizePhases[] = {
|
||||||
FinalizePhaseStrings,
|
FinalizePhaseStrings,
|
||||||
FinalizePhaseScripts,
|
FinalizePhaseScripts,
|
||||||
FinalizePhaseJitCode
|
#ifdef JS_ION
|
||||||
|
FinalizePhaseJitCode,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
static const int FinalizePhaseCount = sizeof(FinalizePhases) / sizeof(AllocKind*);
|
static const int FinalizePhaseCount = sizeof(FinalizePhases) / sizeof(AllocKind*);
|
||||||
|
|
||||||
static const int FinalizePhaseLength[] = {
|
static const int FinalizePhaseLength[] = {
|
||||||
sizeof(FinalizePhaseStrings) / sizeof(AllocKind),
|
sizeof(FinalizePhaseStrings) / sizeof(AllocKind),
|
||||||
sizeof(FinalizePhaseScripts) / sizeof(AllocKind),
|
sizeof(FinalizePhaseScripts) / sizeof(AllocKind),
|
||||||
sizeof(FinalizePhaseJitCode) / sizeof(AllocKind)
|
#ifdef JS_ION
|
||||||
|
sizeof(FinalizePhaseJitCode) / sizeof(AllocKind),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const gcstats::Phase FinalizePhaseStatsPhase[] = {
|
static const gcstats::Phase FinalizePhaseStatsPhase[] = {
|
||||||
gcstats::PHASE_SWEEP_STRING,
|
gcstats::PHASE_SWEEP_STRING,
|
||||||
gcstats::PHASE_SWEEP_SCRIPT,
|
gcstats::PHASE_SWEEP_SCRIPT,
|
||||||
gcstats::PHASE_SWEEP_JITCODE
|
#ifdef JS_ION
|
||||||
|
gcstats::PHASE_SWEEP_JITCODE,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2142,12 +2150,14 @@ ArenaLists::queueScriptsForSweep(FreeOp *fop)
|
||||||
queueForForegroundSweep(fop, FINALIZE_LAZY_SCRIPT);
|
queueForForegroundSweep(fop, FINALIZE_LAZY_SCRIPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JS_ION
|
||||||
void
|
void
|
||||||
ArenaLists::queueJitCodeForSweep(FreeOp *fop)
|
ArenaLists::queueJitCodeForSweep(FreeOp *fop)
|
||||||
{
|
{
|
||||||
gcstats::AutoPhase ap(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_JITCODE);
|
gcstats::AutoPhase ap(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_JITCODE);
|
||||||
queueForForegroundSweep(fop, FINALIZE_JITCODE);
|
queueForForegroundSweep(fop, FINALIZE_JITCODE);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
ArenaLists::queueShapesForSweep(FreeOp *fop)
|
ArenaLists::queueShapesForSweep(FreeOp *fop)
|
||||||
|
|
|
@ -919,7 +919,9 @@ class ArenaLists
|
||||||
void queueStringsAndSymbolsForSweep(FreeOp *fop);
|
void queueStringsAndSymbolsForSweep(FreeOp *fop);
|
||||||
void queueShapesForSweep(FreeOp *fop);
|
void queueShapesForSweep(FreeOp *fop);
|
||||||
void queueScriptsForSweep(FreeOp *fop);
|
void queueScriptsForSweep(FreeOp *fop);
|
||||||
|
#ifdef JS_ION
|
||||||
void queueJitCodeForSweep(FreeOp *fop);
|
void queueJitCodeForSweep(FreeOp *fop);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool foregroundFinalize(FreeOp *fop, AllocKind thingKind, SliceBudget &sliceBudget,
|
bool foregroundFinalize(FreeOp *fop, AllocKind thingKind, SliceBudget &sliceBudget,
|
||||||
SortedArenaList &sweepList);
|
SortedArenaList &sweepList);
|
||||||
|
|
265
js/src/jsstr.cpp
265
js/src/jsstr.cpp
|
@ -4268,271 +4268,6 @@ js_InitStringClass(JSContext *cx, HandleObject obj)
|
||||||
return proto;
|
return proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSLinearString *
|
|
||||||
js::NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t length)
|
|
||||||
{
|
|
||||||
if (length == 0)
|
|
||||||
return cx->emptyString();
|
|
||||||
|
|
||||||
JSLinearString *base = baseArg->ensureLinear(cx);
|
|
||||||
if (!base)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (start == 0 && length == base->length())
|
|
||||||
return base;
|
|
||||||
|
|
||||||
if (base->hasTwoByteChars()) {
|
|
||||||
AutoCheckCannotGC nogc;
|
|
||||||
const jschar *chars = base->twoByteChars(nogc) + start;
|
|
||||||
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
|
|
||||||
return staticStr;
|
|
||||||
} else {
|
|
||||||
AutoCheckCannotGC nogc;
|
|
||||||
const Latin1Char *chars = base->latin1Chars(nogc) + start;
|
|
||||||
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
|
|
||||||
return staticStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return JSDependentString::new_(cx, base, start, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename CharT>
|
|
||||||
static void
|
|
||||||
CopyCharsMaybeInflate(jschar *dest, const CharT *src, size_t len);
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void
|
|
||||||
CopyCharsMaybeInflate(jschar *dest, const jschar *src, size_t len)
|
|
||||||
{
|
|
||||||
PodCopy(dest, src, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void
|
|
||||||
CopyCharsMaybeInflate(jschar *dest, const Latin1Char *src, size_t len)
|
|
||||||
{
|
|
||||||
CopyAndInflateChars(dest, src, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
CanStoreCharsAsLatin1(const jschar *s, size_t length)
|
|
||||||
{
|
|
||||||
if (!EnableLatin1Strings)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (const jschar *end = s + length; s < end; ++s) {
|
|
||||||
if (*s > JSString::MAX_LATIN1_CHAR)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
CanStoreCharsAsLatin1(const Latin1Char *s, size_t length)
|
|
||||||
{
|
|
||||||
MOZ_CRASH("Shouldn't be called for Latin1 chars");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
static MOZ_ALWAYS_INLINE JSInlineString *
|
|
||||||
NewFatInlineStringDeflated(ThreadSafeContext *cx, mozilla::Range<const jschar> chars)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(EnableLatin1Strings);
|
|
||||||
|
|
||||||
size_t len = chars.length();
|
|
||||||
Latin1Char *storage;
|
|
||||||
JSInlineString *str = AllocateFatInlineString<allowGC>(cx, len, &storage);
|
|
||||||
if (!str)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
|
||||||
MOZ_ASSERT(chars[i] <= JSString::MAX_LATIN1_CHAR);
|
|
||||||
storage[i] = Latin1Char(chars[i]);
|
|
||||||
}
|
|
||||||
storage[len] = '\0';
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
static JSFlatString *
|
|
||||||
NewStringDeflated(ThreadSafeContext *cx, const jschar *s, size_t n)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(EnableLatin1Strings);
|
|
||||||
|
|
||||||
if (JSFatInlineString::latin1LengthFits(n))
|
|
||||||
return NewFatInlineStringDeflated<allowGC>(cx, mozilla::Range<const jschar>(s, n));
|
|
||||||
|
|
||||||
ScopedJSFreePtr<Latin1Char> news(cx->pod_malloc<Latin1Char>(n + 1));
|
|
||||||
if (!news)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
MOZ_ASSERT(s[i] <= JSString::MAX_LATIN1_CHAR);
|
|
||||||
news.get()[i] = Latin1Char(s[i]);
|
|
||||||
}
|
|
||||||
news[n] = '\0';
|
|
||||||
|
|
||||||
JSFlatString *str = JSFlatString::new_<allowGC>(cx, news.get(), n);
|
|
||||||
if (!str)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
news.forget();
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
static JSFlatString *
|
|
||||||
NewStringDeflated(ThreadSafeContext *cx, const Latin1Char *s, size_t n)
|
|
||||||
{
|
|
||||||
MOZ_CRASH("Shouldn't be called for Latin1 chars");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC, typename CharT>
|
|
||||||
JSFlatString *
|
|
||||||
js::NewStringDontDeflate(ThreadSafeContext *cx, CharT *chars, size_t length)
|
|
||||||
{
|
|
||||||
if (length == 1) {
|
|
||||||
jschar c = chars[0];
|
|
||||||
if (StaticStrings::hasUnit(c)) {
|
|
||||||
// Free |chars| because we're taking possession of it, but it's no
|
|
||||||
// longer needed because we use the static string instead.
|
|
||||||
js_free(chars);
|
|
||||||
return cx->staticStrings().getUnit(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return JSFlatString::new_<allowGC>(cx, chars, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
js::NewStringDontDeflate<CanGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
js::NewStringDontDeflate<NoGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
js::NewStringDontDeflate<CanGC>(ThreadSafeContext *cx, Latin1Char *chars, size_t length);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
js::NewStringDontDeflate<NoGC>(ThreadSafeContext *cx, Latin1Char *chars, size_t length);
|
|
||||||
|
|
||||||
template <AllowGC allowGC, typename CharT>
|
|
||||||
JSFlatString *
|
|
||||||
js::NewString(ThreadSafeContext *cx, CharT *chars, size_t length)
|
|
||||||
{
|
|
||||||
if (IsSame<CharT, jschar>::value && CanStoreCharsAsLatin1(chars, length)) {
|
|
||||||
if (length == 1) {
|
|
||||||
jschar c = chars[0];
|
|
||||||
if (StaticStrings::hasUnit(c)) {
|
|
||||||
js_free(chars);
|
|
||||||
return cx->staticStrings().getUnit(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JSFlatString *s = NewStringDeflated<allowGC>(cx, chars, length);
|
|
||||||
if (!s)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// Free |chars| because we're taking possession of it but not using it.
|
|
||||||
js_free(chars);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewStringDontDeflate<allowGC>(cx, chars, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
js::NewString<CanGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
js::NewString<NoGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
js::NewString<CanGC>(ThreadSafeContext *cx, Latin1Char *chars, size_t length);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
js::NewString<NoGC>(ThreadSafeContext *cx, Latin1Char *chars, size_t length);
|
|
||||||
|
|
||||||
namespace js {
|
|
||||||
|
|
||||||
template <AllowGC allowGC, typename CharT>
|
|
||||||
JSFlatString *
|
|
||||||
NewStringCopyNDontDeflate(ThreadSafeContext *cx, const CharT *s, size_t n)
|
|
||||||
{
|
|
||||||
if (EnableLatin1Strings) {
|
|
||||||
if (JSFatInlineString::lengthFits<CharT>(n))
|
|
||||||
return NewFatInlineString<allowGC>(cx, mozilla::Range<const CharT>(s, n));
|
|
||||||
|
|
||||||
ScopedJSFreePtr<CharT> news(cx->pod_malloc<CharT>(n + 1));
|
|
||||||
if (!news)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
PodCopy(news.get(), s, n);
|
|
||||||
news[n] = 0;
|
|
||||||
|
|
||||||
JSFlatString *str = JSFlatString::new_<allowGC>(cx, news.get(), n);
|
|
||||||
if (!str)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
news.forget();
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JSFatInlineString::twoByteLengthFits(n))
|
|
||||||
return NewFatInlineString<allowGC>(cx, mozilla::Range<const CharT>(s, n));
|
|
||||||
|
|
||||||
ScopedJSFreePtr<jschar> news(cx->pod_malloc<jschar>(n + 1));
|
|
||||||
if (!news)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
CopyCharsMaybeInflate(news.get(), s, n);
|
|
||||||
news[n] = 0;
|
|
||||||
|
|
||||||
JSFlatString *str = JSFlatString::new_<allowGC>(cx, news.get(), n);
|
|
||||||
if (!str)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
news.forget();
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
NewStringCopyNDontDeflate<CanGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
NewStringCopyNDontDeflate<NoGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
NewStringCopyNDontDeflate<CanGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
NewStringCopyNDontDeflate<NoGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
|
|
||||||
|
|
||||||
template <AllowGC allowGC, typename CharT>
|
|
||||||
JSFlatString *
|
|
||||||
NewStringCopyN(ThreadSafeContext *cx, const CharT *s, size_t n)
|
|
||||||
{
|
|
||||||
if (IsSame<CharT, jschar>::value && CanStoreCharsAsLatin1(s, n))
|
|
||||||
return NewStringDeflated<allowGC>(cx, s, n);
|
|
||||||
|
|
||||||
return NewStringCopyNDontDeflate<allowGC>(cx, s, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
NewStringCopyN<CanGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
NewStringCopyN<NoGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
NewStringCopyN<CanGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
|
|
||||||
|
|
||||||
template JSFlatString *
|
|
||||||
NewStringCopyN<NoGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
|
|
||||||
|
|
||||||
} /* namespace js */
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
js_ValueToPrintable(JSContext *cx, const Value &vArg, JSAutoByteString *bytes, bool asSource)
|
js_ValueToPrintable(JSContext *cx, const Value &vArg, JSAutoByteString *bytes, bool asSource)
|
||||||
{
|
{
|
||||||
|
|
|
@ -127,51 +127,6 @@ namespace js {
|
||||||
extern mozilla::UniquePtr<jschar[], JS::FreePolicy>
|
extern mozilla::UniquePtr<jschar[], JS::FreePolicy>
|
||||||
DuplicateString(ThreadSafeContext *cx, const jschar *s);
|
DuplicateString(ThreadSafeContext *cx, const jschar *s);
|
||||||
|
|
||||||
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
|
|
||||||
template <js::AllowGC allowGC, typename CharT>
|
|
||||||
extern JSFlatString *
|
|
||||||
NewString(js::ThreadSafeContext *cx, CharT *chars, size_t length);
|
|
||||||
|
|
||||||
/* Like NewString, but doesn't try to deflate to Latin1. */
|
|
||||||
template <js::AllowGC allowGC, typename CharT>
|
|
||||||
extern JSFlatString *
|
|
||||||
NewStringDontDeflate(js::ThreadSafeContext *cx, CharT *chars, size_t length);
|
|
||||||
|
|
||||||
extern JSLinearString *
|
|
||||||
NewDependentString(JSContext *cx, JSString *base, size_t start, size_t length);
|
|
||||||
|
|
||||||
/* Copy a counted string and GC-allocate a descriptor for it. */
|
|
||||||
template <js::AllowGC allowGC, typename CharT>
|
|
||||||
extern JSFlatString *
|
|
||||||
NewStringCopyN(js::ThreadSafeContext *cx, const CharT *s, size_t n);
|
|
||||||
|
|
||||||
template <js::AllowGC allowGC>
|
|
||||||
inline JSFlatString *
|
|
||||||
NewStringCopyN(ThreadSafeContext *cx, const char *s, size_t n)
|
|
||||||
{
|
|
||||||
return NewStringCopyN<allowGC>(cx, reinterpret_cast<const Latin1Char *>(s), n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Like NewStringCopyN, but doesn't try to deflate to Latin1. */
|
|
||||||
template <js::AllowGC allowGC, typename CharT>
|
|
||||||
extern JSFlatString *
|
|
||||||
NewStringCopyNDontDeflate(js::ThreadSafeContext *cx, const CharT *s, size_t n);
|
|
||||||
|
|
||||||
/* Copy a C string and GC-allocate a descriptor for it. */
|
|
||||||
template <js::AllowGC allowGC>
|
|
||||||
inline JSFlatString *
|
|
||||||
NewStringCopyZ(js::ExclusiveContext *cx, const jschar *s)
|
|
||||||
{
|
|
||||||
return NewStringCopyN<allowGC>(cx, s, js_strlen(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <js::AllowGC allowGC>
|
|
||||||
inline JSFlatString *
|
|
||||||
NewStringCopyZ(js::ThreadSafeContext *cx, const char *s)
|
|
||||||
{
|
|
||||||
return NewStringCopyN<allowGC>(cx, s, strlen(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a non-string value to a string, returning null after reporting an
|
* Convert a non-string value to a string, returning null after reporting an
|
||||||
* error, otherwise returning a new string reference.
|
* error, otherwise returning a new string reference.
|
||||||
|
|
|
@ -6058,7 +6058,7 @@ SetRuntimeOptions(JSRuntime *rt, const OptionParser &op)
|
||||||
|
|
||||||
jsCacheDir = op.getStringOption("js-cache");
|
jsCacheDir = op.getStringOption("js-cache");
|
||||||
if (jsCacheDir) {
|
if (jsCacheDir) {
|
||||||
if (op.getBoolOption("js-cache-per-process"))
|
if (!op.getBoolOption("no-js-cache-per-process"))
|
||||||
jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid());
|
jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid());
|
||||||
jsCacheAsmJSPath = JS_smprintf("%s/asmjs.cache", jsCacheDir);
|
jsCacheAsmJSPath = JS_smprintf("%s/asmjs.cache", jsCacheDir);
|
||||||
}
|
}
|
||||||
|
@ -6100,7 +6100,7 @@ Shell(JSContext *cx, OptionParser *op, char **envp)
|
||||||
if (enableDisassemblyDumps)
|
if (enableDisassemblyDumps)
|
||||||
JS_DumpCompartmentPCCounts(cx);
|
JS_DumpCompartmentPCCounts(cx);
|
||||||
|
|
||||||
if (op->getBoolOption("js-cache-per-process")) {
|
if (!op->getBoolOption("no-js-cache-per-process")) {
|
||||||
if (jsCacheAsmJSPath)
|
if (jsCacheAsmJSPath)
|
||||||
unlink(jsCacheAsmJSPath);
|
unlink(jsCacheAsmJSPath);
|
||||||
if (jsCacheDir)
|
if (jsCacheDir)
|
||||||
|
@ -6178,11 +6178,12 @@ main(int argc, char **argv, char **envp)
|
||||||
|| !op.addStringOption('\0', "js-cache", "[path]",
|
|| !op.addStringOption('\0', "js-cache", "[path]",
|
||||||
"Enable the JS cache by specifying the path of the directory to use "
|
"Enable the JS cache by specifying the path of the directory to use "
|
||||||
"to hold cache files")
|
"to hold cache files")
|
||||||
|| !op.addBoolOption('\0', "js-cache-per-process",
|
|| !op.addBoolOption('\0', "no-js-cache-per-process",
|
||||||
"Generate a separate cache sub-directory for this process inside "
|
"Deactivates cache per process. Otherwise, generate a separate cache"
|
||||||
"the cache directory specified by --js-cache. This cache directory "
|
"sub-directory for this process inside the cache directory"
|
||||||
"will be removed when the js shell exits. This is useful for running "
|
"specified by --js-cache. This cache directory will be removed"
|
||||||
"tests in parallel.")
|
"when the js shell exits. This is useful for running tests in"
|
||||||
|
"parallel.")
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|| !op.addBoolOption('O', "print-alloc", "Print the number of allocations at exit")
|
|| !op.addBoolOption('O', "print-alloc", "Print the number of allocations at exit")
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1088,6 +1088,9 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||||
bool canUseSignalHandlers() const {
|
bool canUseSignalHandlers() const {
|
||||||
return canUseSignalHandlers_;
|
return canUseSignalHandlers_;
|
||||||
}
|
}
|
||||||
|
void setCanUseSignalHandlers(bool enable) {
|
||||||
|
canUseSignalHandlers_ = signalHandlersInstalled_ && enable;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
js::FreeOp defaultFreeOp_;
|
js::FreeOp defaultFreeOp_;
|
||||||
|
|
|
@ -895,3 +895,268 @@ JSAtom::dump()
|
||||||
this->JSString::dump();
|
this->JSString::dump();
|
||||||
}
|
}
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
JSLinearString *
|
||||||
|
js::NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t length)
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
return cx->emptyString();
|
||||||
|
|
||||||
|
JSLinearString *base = baseArg->ensureLinear(cx);
|
||||||
|
if (!base)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (start == 0 && length == base->length())
|
||||||
|
return base;
|
||||||
|
|
||||||
|
if (base->hasTwoByteChars()) {
|
||||||
|
AutoCheckCannotGC nogc;
|
||||||
|
const jschar *chars = base->twoByteChars(nogc) + start;
|
||||||
|
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
|
||||||
|
return staticStr;
|
||||||
|
} else {
|
||||||
|
AutoCheckCannotGC nogc;
|
||||||
|
const Latin1Char *chars = base->latin1Chars(nogc) + start;
|
||||||
|
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
|
||||||
|
return staticStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSDependentString::new_(cx, base, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename CharT>
|
||||||
|
static void
|
||||||
|
CopyCharsMaybeInflate(jschar *dest, const CharT *src, size_t len);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void
|
||||||
|
CopyCharsMaybeInflate(jschar *dest, const jschar *src, size_t len)
|
||||||
|
{
|
||||||
|
PodCopy(dest, src, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void
|
||||||
|
CopyCharsMaybeInflate(jschar *dest, const Latin1Char *src, size_t len)
|
||||||
|
{
|
||||||
|
CopyAndInflateChars(dest, src, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CanStoreCharsAsLatin1(const jschar *s, size_t length)
|
||||||
|
{
|
||||||
|
if (!EnableLatin1Strings)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const jschar *end = s + length; s < end; ++s) {
|
||||||
|
if (*s > JSString::MAX_LATIN1_CHAR)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CanStoreCharsAsLatin1(const Latin1Char *s, size_t length)
|
||||||
|
{
|
||||||
|
MOZ_CRASH("Shouldn't be called for Latin1 chars");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <AllowGC allowGC>
|
||||||
|
static MOZ_ALWAYS_INLINE JSInlineString *
|
||||||
|
NewFatInlineStringDeflated(ThreadSafeContext *cx, mozilla::Range<const jschar> chars)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(EnableLatin1Strings);
|
||||||
|
|
||||||
|
size_t len = chars.length();
|
||||||
|
Latin1Char *storage;
|
||||||
|
JSInlineString *str = AllocateFatInlineString<allowGC>(cx, len, &storage);
|
||||||
|
if (!str)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
MOZ_ASSERT(chars[i] <= JSString::MAX_LATIN1_CHAR);
|
||||||
|
storage[i] = Latin1Char(chars[i]);
|
||||||
|
}
|
||||||
|
storage[len] = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <AllowGC allowGC>
|
||||||
|
static JSFlatString *
|
||||||
|
NewStringDeflated(ThreadSafeContext *cx, const jschar *s, size_t n)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(EnableLatin1Strings);
|
||||||
|
|
||||||
|
if (JSFatInlineString::latin1LengthFits(n))
|
||||||
|
return NewFatInlineStringDeflated<allowGC>(cx, mozilla::Range<const jschar>(s, n));
|
||||||
|
|
||||||
|
ScopedJSFreePtr<Latin1Char> news(cx->pod_malloc<Latin1Char>(n + 1));
|
||||||
|
if (!news)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
MOZ_ASSERT(s[i] <= JSString::MAX_LATIN1_CHAR);
|
||||||
|
news.get()[i] = Latin1Char(s[i]);
|
||||||
|
}
|
||||||
|
news[n] = '\0';
|
||||||
|
|
||||||
|
JSFlatString *str = JSFlatString::new_<allowGC>(cx, news.get(), n);
|
||||||
|
if (!str)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
news.forget();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <AllowGC allowGC>
|
||||||
|
static JSFlatString *
|
||||||
|
NewStringDeflated(ThreadSafeContext *cx, const Latin1Char *s, size_t n)
|
||||||
|
{
|
||||||
|
MOZ_CRASH("Shouldn't be called for Latin1 chars");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <AllowGC allowGC, typename CharT>
|
||||||
|
JSFlatString *
|
||||||
|
js::NewStringDontDeflate(ThreadSafeContext *cx, CharT *chars, size_t length)
|
||||||
|
{
|
||||||
|
if (length == 1) {
|
||||||
|
jschar c = chars[0];
|
||||||
|
if (StaticStrings::hasUnit(c)) {
|
||||||
|
// Free |chars| because we're taking possession of it, but it's no
|
||||||
|
// longer needed because we use the static string instead.
|
||||||
|
js_free(chars);
|
||||||
|
return cx->staticStrings().getUnit(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSFlatString::new_<allowGC>(cx, chars, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
js::NewStringDontDeflate<CanGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
js::NewStringDontDeflate<NoGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
js::NewStringDontDeflate<CanGC>(ThreadSafeContext *cx, Latin1Char *chars, size_t length);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
js::NewStringDontDeflate<NoGC>(ThreadSafeContext *cx, Latin1Char *chars, size_t length);
|
||||||
|
|
||||||
|
template <AllowGC allowGC, typename CharT>
|
||||||
|
JSFlatString *
|
||||||
|
js::NewString(ThreadSafeContext *cx, CharT *chars, size_t length)
|
||||||
|
{
|
||||||
|
if (IsSame<CharT, jschar>::value && CanStoreCharsAsLatin1(chars, length)) {
|
||||||
|
if (length == 1) {
|
||||||
|
jschar c = chars[0];
|
||||||
|
if (StaticStrings::hasUnit(c)) {
|
||||||
|
js_free(chars);
|
||||||
|
return cx->staticStrings().getUnit(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSFlatString *s = NewStringDeflated<allowGC>(cx, chars, length);
|
||||||
|
if (!s)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Free |chars| because we're taking possession of it but not using it.
|
||||||
|
js_free(chars);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewStringDontDeflate<allowGC>(cx, chars, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
js::NewString<CanGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
js::NewString<NoGC>(ThreadSafeContext *cx, jschar *chars, size_t length);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
js::NewString<CanGC>(ThreadSafeContext *cx, Latin1Char *chars, size_t length);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
js::NewString<NoGC>(ThreadSafeContext *cx, Latin1Char *chars, size_t length);
|
||||||
|
|
||||||
|
namespace js {
|
||||||
|
|
||||||
|
template <AllowGC allowGC, typename CharT>
|
||||||
|
JSFlatString *
|
||||||
|
NewStringCopyNDontDeflate(ThreadSafeContext *cx, const CharT *s, size_t n)
|
||||||
|
{
|
||||||
|
if (EnableLatin1Strings) {
|
||||||
|
if (JSFatInlineString::lengthFits<CharT>(n))
|
||||||
|
return NewFatInlineString<allowGC>(cx, mozilla::Range<const CharT>(s, n));
|
||||||
|
|
||||||
|
ScopedJSFreePtr<CharT> news(cx->pod_malloc<CharT>(n + 1));
|
||||||
|
if (!news)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PodCopy(news.get(), s, n);
|
||||||
|
news[n] = 0;
|
||||||
|
|
||||||
|
JSFlatString *str = JSFlatString::new_<allowGC>(cx, news.get(), n);
|
||||||
|
if (!str)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
news.forget();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JSFatInlineString::twoByteLengthFits(n))
|
||||||
|
return NewFatInlineString<allowGC>(cx, mozilla::Range<const CharT>(s, n));
|
||||||
|
|
||||||
|
ScopedJSFreePtr<jschar> news(cx->pod_malloc<jschar>(n + 1));
|
||||||
|
if (!news)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
CopyCharsMaybeInflate(news.get(), s, n);
|
||||||
|
news[n] = 0;
|
||||||
|
|
||||||
|
JSFlatString *str = JSFlatString::new_<allowGC>(cx, news.get(), n);
|
||||||
|
if (!str)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
news.forget();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
NewStringCopyNDontDeflate<CanGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
NewStringCopyNDontDeflate<NoGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
NewStringCopyNDontDeflate<CanGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
NewStringCopyNDontDeflate<NoGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
|
||||||
|
|
||||||
|
template <AllowGC allowGC, typename CharT>
|
||||||
|
JSFlatString *
|
||||||
|
NewStringCopyN(ThreadSafeContext *cx, const CharT *s, size_t n)
|
||||||
|
{
|
||||||
|
if (IsSame<CharT, jschar>::value && CanStoreCharsAsLatin1(s, n))
|
||||||
|
return NewStringDeflated<allowGC>(cx, s, n);
|
||||||
|
|
||||||
|
return NewStringCopyNDontDeflate<allowGC>(cx, s, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
NewStringCopyN<CanGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
NewStringCopyN<NoGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
NewStringCopyN<CanGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
|
||||||
|
|
||||||
|
template JSFlatString *
|
||||||
|
NewStringCopyN<NoGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
|
||||||
|
|
||||||
|
} /* namespace js */
|
||||||
|
|
|
@ -1177,6 +1177,51 @@ template <typename CharT>
|
||||||
void
|
void
|
||||||
CopyChars(CharT *dest, const JSLinearString &str);
|
CopyChars(CharT *dest, const JSLinearString &str);
|
||||||
|
|
||||||
|
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
|
||||||
|
template <js::AllowGC allowGC, typename CharT>
|
||||||
|
extern JSFlatString *
|
||||||
|
NewString(js::ThreadSafeContext *cx, CharT *chars, size_t length);
|
||||||
|
|
||||||
|
/* Like NewString, but doesn't try to deflate to Latin1. */
|
||||||
|
template <js::AllowGC allowGC, typename CharT>
|
||||||
|
extern JSFlatString *
|
||||||
|
NewStringDontDeflate(js::ThreadSafeContext *cx, CharT *chars, size_t length);
|
||||||
|
|
||||||
|
extern JSLinearString *
|
||||||
|
NewDependentString(JSContext *cx, JSString *base, size_t start, size_t length);
|
||||||
|
|
||||||
|
/* Copy a counted string and GC-allocate a descriptor for it. */
|
||||||
|
template <js::AllowGC allowGC, typename CharT>
|
||||||
|
extern JSFlatString *
|
||||||
|
NewStringCopyN(js::ThreadSafeContext *cx, const CharT *s, size_t n);
|
||||||
|
|
||||||
|
template <js::AllowGC allowGC>
|
||||||
|
inline JSFlatString *
|
||||||
|
NewStringCopyN(ThreadSafeContext *cx, const char *s, size_t n)
|
||||||
|
{
|
||||||
|
return NewStringCopyN<allowGC>(cx, reinterpret_cast<const Latin1Char *>(s), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Like NewStringCopyN, but doesn't try to deflate to Latin1. */
|
||||||
|
template <js::AllowGC allowGC, typename CharT>
|
||||||
|
extern JSFlatString *
|
||||||
|
NewStringCopyNDontDeflate(js::ThreadSafeContext *cx, const CharT *s, size_t n);
|
||||||
|
|
||||||
|
/* Copy a C string and GC-allocate a descriptor for it. */
|
||||||
|
template <js::AllowGC allowGC>
|
||||||
|
inline JSFlatString *
|
||||||
|
NewStringCopyZ(js::ExclusiveContext *cx, const jschar *s)
|
||||||
|
{
|
||||||
|
return NewStringCopyN<allowGC>(cx, s, js_strlen(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <js::AllowGC allowGC>
|
||||||
|
inline JSFlatString *
|
||||||
|
NewStringCopyZ(js::ThreadSafeContext *cx, const char *s)
|
||||||
|
{
|
||||||
|
return NewStringCopyN<allowGC>(cx, s, strlen(s));
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
// Addon IDs are interned atoms which are never destroyed. This detail is
|
// Addon IDs are interned atoms which are never destroyed. This detail is
|
||||||
|
|
|
@ -161,7 +161,7 @@ AutoCxPusher::~AutoCxPusher()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AutoCxPusher::IsStackTop()
|
AutoCxPusher::IsStackTop() const
|
||||||
{
|
{
|
||||||
uint32_t currentDepth = XPCJSRuntime::Get()->GetJSContextStack()->Count();
|
uint32_t currentDepth = XPCJSRuntime::Get()->GetJSContextStack()->Count();
|
||||||
MOZ_ASSERT(currentDepth >= mStackDepthAfterPush);
|
MOZ_ASSERT(currentDepth >= mStackDepthAfterPush);
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
|
|
||||||
// Returns true if this AutoCxPusher performed the push that is currently at
|
// Returns true if this AutoCxPusher performed the push that is currently at
|
||||||
// the top of the cx stack.
|
// the top of the cx stack.
|
||||||
bool IsStackTop();
|
bool IsStackTop() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mozilla::Maybe<JSAutoRequest> mAutoRequest;
|
mozilla::Maybe<JSAutoRequest> mAutoRequest;
|
||||||
|
|
|
@ -6,7 +6,6 @@ frameworks/av/include/media/stagefright/foundation/ADebug.h
|
||||||
frameworks/av/include/media/stagefright/foundation/AHandler.h
|
frameworks/av/include/media/stagefright/foundation/AHandler.h
|
||||||
frameworks/av/include/media/stagefright/foundation/AString.h
|
frameworks/av/include/media/stagefright/foundation/AString.h
|
||||||
frameworks/av/include/media/stagefright/foundation/hexdump.h
|
frameworks/av/include/media/stagefright/foundation/hexdump.h
|
||||||
frameworks/av/include/media/stagefright/MediaBufferGroup.h
|
|
||||||
frameworks/av/include/media/stagefright/MediaDefs.h
|
frameworks/av/include/media/stagefright/MediaDefs.h
|
||||||
frameworks/av/include/media/stagefright/MediaErrors.h
|
frameworks/av/include/media/stagefright/MediaErrors.h
|
||||||
frameworks/av/include/media/stagefright/MediaExtractor.h
|
frameworks/av/include/media/stagefright/MediaExtractor.h
|
||||||
|
|
|
@ -54,8 +54,8 @@ public:
|
||||||
|
|
||||||
MediaBuffer(const sp<ABuffer> &buffer);
|
MediaBuffer(const sp<ABuffer> &buffer);
|
||||||
|
|
||||||
// Decrements the reference count and returns the buffer to its
|
// Decrements the reference count and deletes it if the reference
|
||||||
// associated MediaBufferGroup if the reference count drops to 0.
|
// count drops to 0.
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
// Increments the reference count.
|
// Increments the reference count.
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2009 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MEDIA_BUFFER_GROUP_H_
|
|
||||||
|
|
||||||
#define MEDIA_BUFFER_GROUP_H_
|
|
||||||
|
|
||||||
#include <media/stagefright/MediaBuffer.h>
|
|
||||||
#include <utils/Errors.h>
|
|
||||||
#include <utils/threads.h>
|
|
||||||
|
|
||||||
namespace stagefright {
|
|
||||||
|
|
||||||
class MediaBuffer;
|
|
||||||
class MetaData;
|
|
||||||
|
|
||||||
class MediaBufferGroup : public MediaBufferObserver {
|
|
||||||
public:
|
|
||||||
MediaBufferGroup();
|
|
||||||
~MediaBufferGroup();
|
|
||||||
|
|
||||||
void add_buffer(MediaBuffer *buffer);
|
|
||||||
|
|
||||||
// Blocks until a buffer is available and returns it to the caller,
|
|
||||||
// the returned buffer will have a reference count of 1.
|
|
||||||
status_t acquire_buffer(MediaBuffer **buffer);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void signalBufferReturned(MediaBuffer *buffer);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class MediaBuffer;
|
|
||||||
|
|
||||||
Mutex mLock;
|
|
||||||
Condition mCondition;
|
|
||||||
|
|
||||||
MediaBuffer *mFirstBuffer, *mLastBuffer;
|
|
||||||
|
|
||||||
MediaBufferGroup(const MediaBufferGroup &);
|
|
||||||
MediaBufferGroup &operator=(const MediaBufferGroup &);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace stagefright
|
|
||||||
|
|
||||||
#endif // MEDIA_BUFFER_GROUP_H_
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <media/stagefright/foundation/ADebug.h>
|
#include <media/stagefright/foundation/ADebug.h>
|
||||||
#include <media/stagefright/foundation/AMessage.h>
|
#include <media/stagefright/foundation/AMessage.h>
|
||||||
#include <media/stagefright/MediaBuffer.h>
|
#include <media/stagefright/MediaBuffer.h>
|
||||||
#include <media/stagefright/MediaBufferGroup.h>
|
|
||||||
#include <media/stagefright/MediaDefs.h>
|
#include <media/stagefright/MediaDefs.h>
|
||||||
#include <media/stagefright/MediaSource.h>
|
#include <media/stagefright/MediaSource.h>
|
||||||
#include <media/stagefright/MetaData.h>
|
#include <media/stagefright/MetaData.h>
|
||||||
|
@ -98,8 +97,6 @@ private:
|
||||||
|
|
||||||
bool mStarted;
|
bool mStarted;
|
||||||
|
|
||||||
MediaBufferGroup *mGroup;
|
|
||||||
|
|
||||||
MediaBuffer *mBuffer;
|
MediaBuffer *mBuffer;
|
||||||
|
|
||||||
bool mWantsNALFragments;
|
bool mWantsNALFragments;
|
||||||
|
@ -2392,7 +2389,6 @@ MPEG4Source::MPEG4Source(
|
||||||
mIsAVC(false),
|
mIsAVC(false),
|
||||||
mNALLengthSize(0),
|
mNALLengthSize(0),
|
||||||
mStarted(false),
|
mStarted(false),
|
||||||
mGroup(NULL),
|
|
||||||
mBuffer(NULL),
|
mBuffer(NULL),
|
||||||
mWantsNALFragments(false),
|
mWantsNALFragments(false),
|
||||||
mSrcBuffer(NULL) {
|
mSrcBuffer(NULL) {
|
||||||
|
@ -2459,13 +2455,9 @@ status_t MPEG4Source::start(MetaData *params) {
|
||||||
mWantsNALFragments = false;
|
mWantsNALFragments = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mGroup = new MediaBufferGroup;
|
|
||||||
|
|
||||||
int32_t max_size;
|
int32_t max_size;
|
||||||
CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
|
CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
|
||||||
|
|
||||||
mGroup->add_buffer(new MediaBuffer(max_size));
|
|
||||||
|
|
||||||
mSrcBuffer = new uint8_t[max_size];
|
mSrcBuffer = new uint8_t[max_size];
|
||||||
|
|
||||||
mStarted = true;
|
mStarted = true;
|
||||||
|
@ -2486,9 +2478,6 @@ status_t MPEG4Source::stop() {
|
||||||
delete[] mSrcBuffer;
|
delete[] mSrcBuffer;
|
||||||
mSrcBuffer = NULL;
|
mSrcBuffer = NULL;
|
||||||
|
|
||||||
delete mGroup;
|
|
||||||
mGroup = NULL;
|
|
||||||
|
|
||||||
mStarted = false;
|
mStarted = false;
|
||||||
mCurrentSampleIndex = 0;
|
mCurrentSampleIndex = 0;
|
||||||
|
|
||||||
|
@ -3169,12 +3158,10 @@ status_t MPEG4Source::read(
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mGroup->acquire_buffer(&mBuffer);
|
int32_t max_size;
|
||||||
|
CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
|
||||||
if (err != OK) {
|
mBuffer = new MediaBuffer(max_size);
|
||||||
CHECK(mBuffer == NULL);
|
assert(mBuffer);
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mIsAVC || mWantsNALFragments) {
|
if (!mIsAVC || mWantsNALFragments) {
|
||||||
|
@ -3439,13 +3426,10 @@ status_t MPEG4Source::fragmentedRead(
|
||||||
mCurrentTime += smpl->duration;
|
mCurrentTime += smpl->duration;
|
||||||
isSyncSample = (mCurrentSampleIndex == 0); // XXX
|
isSyncSample = (mCurrentSampleIndex == 0); // XXX
|
||||||
|
|
||||||
status_t err = mGroup->acquire_buffer(&mBuffer);
|
int32_t max_size;
|
||||||
|
CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
|
||||||
if (err != OK) {
|
mBuffer = new MediaBuffer(max_size);
|
||||||
CHECK(mBuffer == NULL);
|
assert(mBuffer);
|
||||||
ALOGV("acquire_buffer returned %d", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
|
const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
|
||||||
|
@ -3454,7 +3438,7 @@ status_t MPEG4Source::fragmentedRead(
|
||||||
if (smpl->encryptedsizes.size()) {
|
if (smpl->encryptedsizes.size()) {
|
||||||
// store clear/encrypted lengths in metadata
|
// store clear/encrypted lengths in metadata
|
||||||
bufmeta->setData(kKeyPlainSizes, 0,
|
bufmeta->setData(kKeyPlainSizes, 0,
|
||||||
smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
|
smpl->clearsizes.array(), smpl->clearsizes.size() * 2);
|
||||||
bufmeta->setData(kKeyEncryptedSizes, 0,
|
bufmeta->setData(kKeyEncryptedSizes, 0,
|
||||||
smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
|
smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
|
||||||
bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
|
bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2009 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#undef LOG_TAG
|
|
||||||
#define LOG_TAG "MediaBufferGroup"
|
|
||||||
#include <utils/Log.h>
|
|
||||||
|
|
||||||
#include <media/stagefright/foundation/ADebug.h>
|
|
||||||
#include <media/stagefright/MediaBuffer.h>
|
|
||||||
#include <media/stagefright/MediaBufferGroup.h>
|
|
||||||
|
|
||||||
namespace stagefright {
|
|
||||||
|
|
||||||
MediaBufferGroup::MediaBufferGroup()
|
|
||||||
: mFirstBuffer(NULL),
|
|
||||||
mLastBuffer(NULL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaBufferGroup::~MediaBufferGroup() {
|
|
||||||
MediaBuffer *next;
|
|
||||||
for (MediaBuffer *buffer = mFirstBuffer; buffer != NULL;
|
|
||||||
buffer = next) {
|
|
||||||
next = buffer->nextBuffer();
|
|
||||||
|
|
||||||
CHECK_EQ(buffer->refcount(), 0);
|
|
||||||
|
|
||||||
buffer->setObserver(NULL);
|
|
||||||
buffer->release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MediaBufferGroup::add_buffer(MediaBuffer *buffer) {
|
|
||||||
Mutex::Autolock autoLock(mLock);
|
|
||||||
|
|
||||||
buffer->setObserver(this);
|
|
||||||
|
|
||||||
if (mLastBuffer) {
|
|
||||||
mLastBuffer->setNextBuffer(buffer);
|
|
||||||
} else {
|
|
||||||
mFirstBuffer = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
mLastBuffer = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t MediaBufferGroup::acquire_buffer(MediaBuffer **out) {
|
|
||||||
Mutex::Autolock autoLock(mLock);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
for (MediaBuffer *buffer = mFirstBuffer;
|
|
||||||
buffer != NULL; buffer = buffer->nextBuffer()) {
|
|
||||||
if (buffer->refcount() == 0) {
|
|
||||||
buffer->add_ref();
|
|
||||||
buffer->reset();
|
|
||||||
|
|
||||||
*out = buffer;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// All buffers are in use. Block until one of them is returned to us.
|
|
||||||
mCondition.wait(mLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MediaBufferGroup::signalBufferReturned(MediaBuffer *) {
|
|
||||||
Mutex::Autolock autoLock(mLock);
|
|
||||||
mCondition.signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace stagefright
|
|
||||||
|
|
||||||
#undef LOG_TAG
|
|
|
@ -75,7 +75,6 @@ UNIFIED_SOURCES += [
|
||||||
'frameworks/av/media/libstagefright/foundation/AString.cpp',
|
'frameworks/av/media/libstagefright/foundation/AString.cpp',
|
||||||
'frameworks/av/media/libstagefright/id3/ID3.cpp',
|
'frameworks/av/media/libstagefright/id3/ID3.cpp',
|
||||||
'frameworks/av/media/libstagefright/MediaBuffer.cpp',
|
'frameworks/av/media/libstagefright/MediaBuffer.cpp',
|
||||||
'frameworks/av/media/libstagefright/MediaBufferGroup.cpp',
|
|
||||||
'frameworks/av/media/libstagefright/MediaDefs.cpp',
|
'frameworks/av/media/libstagefright/MediaDefs.cpp',
|
||||||
'frameworks/av/media/libstagefright/MediaSource.cpp',
|
'frameworks/av/media/libstagefright/MediaSource.cpp',
|
||||||
'frameworks/av/media/libstagefright/MPEG4Extractor.cpp',
|
'frameworks/av/media/libstagefright/MPEG4Extractor.cpp',
|
||||||
|
|
|
@ -278,9 +278,9 @@ namespace CSF
|
||||||
*/
|
*/
|
||||||
virtual void originateP2PCall (cc_sdp_direction_t video_pref, const std::string & digits, const std::string & ip) = 0;
|
virtual void originateP2PCall (cc_sdp_direction_t video_pref, const std::string & digits, const std::string & ip) = 0;
|
||||||
|
|
||||||
virtual void createOffer (cc_media_constraints_t* constraints, Timecard *) = 0;
|
virtual void createOffer (cc_media_options_t* options, Timecard *) = 0;
|
||||||
|
|
||||||
virtual void createAnswer(cc_media_constraints_t* constraints, Timecard *) = 0;
|
virtual void createAnswer(Timecard *) = 0;
|
||||||
|
|
||||||
virtual void setLocalDescription(cc_jsep_action_t action, const std::string & sdp, Timecard *) = 0;
|
virtual void setLocalDescription(cc_jsep_action_t action, const std::string & sdp, Timecard *) = 0;
|
||||||
|
|
||||||
|
@ -290,8 +290,7 @@ namespace CSF
|
||||||
|
|
||||||
virtual void addStream(cc_media_stream_id_t stream_id,
|
virtual void addStream(cc_media_stream_id_t stream_id,
|
||||||
cc_media_track_id_t track_id,
|
cc_media_track_id_t track_id,
|
||||||
cc_media_type_t media_type,
|
cc_media_type_t media_type) = 0;
|
||||||
cc_media_constraints_t *constraints) = 0;
|
|
||||||
|
|
||||||
virtual void removeStream(cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) = 0;
|
virtual void removeStream(cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) = 0;
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,7 @@ public:
|
||||||
virtual int SendRTCPPacket(int channel, const void *data, int len) ;
|
virtual int SendRTCPPacket(int channel, const void *data, int len) ;
|
||||||
|
|
||||||
|
|
||||||
|
virtual uint64_t CodecPluginID() { return 0; }
|
||||||
|
|
||||||
WebrtcAudioConduit():
|
WebrtcAudioConduit():
|
||||||
mOtherDirection(nullptr),
|
mOtherDirection(nullptr),
|
||||||
|
|
|
@ -192,21 +192,31 @@ public:
|
||||||
unsigned int* packetsSent,
|
unsigned int* packetsSent,
|
||||||
uint64_t* bytesSent) = 0;
|
uint64_t* bytesSent) = 0;
|
||||||
|
|
||||||
|
virtual uint64_t CodecPluginID() = 0;
|
||||||
|
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaSessionConduit)
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaSessionConduit)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Abstract base classes for external encoder/decoder.
|
// Abstract base classes for external encoder/decoder.
|
||||||
class VideoEncoder
|
class CodecPluginID
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~VideoEncoder() {};
|
virtual ~CodecPluginID() {}
|
||||||
|
|
||||||
|
virtual const uint64_t PluginID() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VideoDecoder
|
class VideoEncoder : public CodecPluginID
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~VideoDecoder() {};
|
virtual ~VideoEncoder() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class VideoDecoder : public CodecPluginID
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~VideoDecoder() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1438,4 +1438,15 @@ WebrtcVideoConduit::MozVideoLatencyAvg()
|
||||||
return mVideoLatencyAvg / sRoundingPadding;
|
return mVideoLatencyAvg / sRoundingPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
WebrtcVideoConduit::CodecPluginID()
|
||||||
|
{
|
||||||
|
if (mExternalSendCodecHandle) {
|
||||||
|
return mExternalSendCodecHandle->PluginID();
|
||||||
|
} else if (mExternalRecvCodecHandle) {
|
||||||
|
return mExternalRecvCodecHandle->PluginID();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
}// end namespace
|
}// end namespace
|
||||||
|
|
|
@ -199,6 +199,8 @@ public:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual uint64_t CodecPluginID();
|
||||||
|
|
||||||
unsigned short SendingWidth() {
|
unsigned short SendingWidth() {
|
||||||
return mSendingWidth;
|
return mSendingWidth;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,6 @@
|
||||||
#include "GMPVideoDecoderProxy.h"
|
#include "GMPVideoDecoderProxy.h"
|
||||||
#include "GMPVideoEncoderProxy.h"
|
#include "GMPVideoEncoderProxy.h"
|
||||||
|
|
||||||
#include "WebrtcGmpVideoCodec.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
class WebrtcGmpVideoEncoder : public WebrtcVideoEncoder,
|
class WebrtcGmpVideoEncoder : public WebrtcVideoEncoder,
|
||||||
|
@ -45,6 +43,11 @@ public:
|
||||||
virtual ~WebrtcGmpVideoEncoder() {}
|
virtual ~WebrtcGmpVideoEncoder() {}
|
||||||
|
|
||||||
// Implement VideoEncoder interface.
|
// Implement VideoEncoder interface.
|
||||||
|
virtual const uint64_t PluginID() MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
return mGMP ? mGMP->ParentID() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual int32_t InitEncode(const webrtc::VideoCodec* aCodecSettings,
|
virtual int32_t InitEncode(const webrtc::VideoCodec* aCodecSettings,
|
||||||
int32_t aNumberOfCores,
|
int32_t aNumberOfCores,
|
||||||
uint32_t aMaxPayloadSize);
|
uint32_t aMaxPayloadSize);
|
||||||
|
@ -97,6 +100,11 @@ public:
|
||||||
virtual ~WebrtcGmpVideoDecoder() {}
|
virtual ~WebrtcGmpVideoDecoder() {}
|
||||||
|
|
||||||
// Implement VideoDecoder interface.
|
// Implement VideoDecoder interface.
|
||||||
|
virtual const uint64_t PluginID() MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
return mGMP ? mGMP->ParentID() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual int32_t InitDecode(const webrtc::VideoCodec* aCodecSettings,
|
virtual int32_t InitDecode(const webrtc::VideoCodec* aCodecSettings,
|
||||||
int32_t aNumberOfCores);
|
int32_t aNumberOfCores);
|
||||||
virtual int32_t Decode(const webrtc::EncodedImage& aInputImage,
|
virtual int32_t Decode(const webrtc::EncodedImage& aInputImage,
|
||||||
|
|
|
@ -35,6 +35,8 @@ public:
|
||||||
virtual ~WebrtcOMXH264VideoEncoder();
|
virtual ~WebrtcOMXH264VideoEncoder();
|
||||||
|
|
||||||
// Implement VideoEncoder interface.
|
// Implement VideoEncoder interface.
|
||||||
|
virtual const uint64_t PluginID() MOZ_OVERRIDE { return 0; }
|
||||||
|
|
||||||
virtual int32_t InitEncode(const webrtc::VideoCodec* aCodecSettings,
|
virtual int32_t InitEncode(const webrtc::VideoCodec* aCodecSettings,
|
||||||
int32_t aNumOfCores,
|
int32_t aNumOfCores,
|
||||||
uint32_t aMaxPayloadSize) MOZ_OVERRIDE;
|
uint32_t aMaxPayloadSize) MOZ_OVERRIDE;
|
||||||
|
@ -77,6 +79,8 @@ public:
|
||||||
virtual ~WebrtcOMXH264VideoDecoder();
|
virtual ~WebrtcOMXH264VideoDecoder();
|
||||||
|
|
||||||
// Implement VideoDecoder interface.
|
// Implement VideoDecoder interface.
|
||||||
|
virtual const uint64_t PluginID() MOZ_OVERRIDE { return 0; }
|
||||||
|
|
||||||
virtual int32_t InitDecode(const webrtc::VideoCodec* aCodecSettings,
|
virtual int32_t InitDecode(const webrtc::VideoCodec* aCodecSettings,
|
||||||
int32_t aNumOfCores) MOZ_OVERRIDE;
|
int32_t aNumOfCores) MOZ_OVERRIDE;
|
||||||
virtual int32_t Decode(const webrtc::EncodedImage& aInputImage,
|
virtual int32_t Decode(const webrtc::EncodedImage& aInputImage,
|
||||||
|
|
|
@ -56,52 +56,48 @@ using namespace dom;
|
||||||
|
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
static void
|
static void
|
||||||
Apply(const Optional<bool> &aSrc, cc_boolean_constraint_t *aDst,
|
Apply(const Optional<bool> &aSrc, cc_boolean_option_t *aDst) {
|
||||||
bool mandatory = false) {
|
if (aSrc.WasPassed()) {
|
||||||
if (aSrc.WasPassed() && (mandatory || !aDst->was_passed)) {
|
aDst->was_passed = true;
|
||||||
|
aDst->value = aSrc.Value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Apply(const Optional<int32_t> &aSrc, cc_int32_option_t *aDst) {
|
||||||
|
if (aSrc.WasPassed()) {
|
||||||
aDst->was_passed = true;
|
aDst->was_passed = true;
|
||||||
aDst->value = aSrc.Value();
|
aDst->value = aSrc.Value();
|
||||||
aDst->mandatory = mandatory;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MediaConstraintsExternal::MediaConstraintsExternal() {
|
SipccOfferOptions::SipccOfferOptions() {
|
||||||
memset(&mConstraints, 0, sizeof(mConstraints));
|
memset(&mOptions, 0, sizeof(mOptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaConstraintsExternal::MediaConstraintsExternal(
|
SipccOfferOptions::SipccOfferOptions(
|
||||||
const MediaConstraintsInternal &aSrc) {
|
const RTCOfferOptions &aSrc) {
|
||||||
cc_media_constraints_t* c = &mConstraints;
|
cc_media_options_t* c = &mOptions;
|
||||||
memset(c, 0, sizeof(*c));
|
memset(c, 0, sizeof(*c));
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
Apply(aSrc.mMandatory.mOfferToReceiveAudio, &c->offer_to_receive_audio, true);
|
Apply(aSrc.mOfferToReceiveAudio, &c->offer_to_receive_audio);
|
||||||
Apply(aSrc.mMandatory.mOfferToReceiveVideo, &c->offer_to_receive_video, true);
|
Apply(aSrc.mOfferToReceiveVideo, &c->offer_to_receive_video);
|
||||||
if (!Preferences::GetBool("media.peerconnection.video.enabled", true)) {
|
if (!Preferences::GetBool("media.peerconnection.video.enabled", true)) {
|
||||||
c->offer_to_receive_video.was_passed = true;
|
c->offer_to_receive_video.was_passed = true;
|
||||||
c->offer_to_receive_video.value = false;
|
c->offer_to_receive_video.value = false;
|
||||||
}
|
}
|
||||||
Apply(aSrc.mMandatory.mMozDontOfferDataChannel, &c->moz_dont_offer_datachannel,
|
Apply(aSrc.mMozDontOfferDataChannel, &c->moz_dont_offer_datachannel);
|
||||||
true);
|
Apply(aSrc.mMozBundleOnly, &c->moz_bundle_only);
|
||||||
Apply(aSrc.mMandatory.mMozBundleOnly, &c->moz_bundle_only, true);
|
|
||||||
if (aSrc.mOptional.WasPassed()) {
|
|
||||||
const Sequence<MediaConstraintSet> &array = aSrc.mOptional.Value();
|
|
||||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
|
||||||
Apply(array[i].mOfferToReceiveAudio, &c->offer_to_receive_audio);
|
|
||||||
Apply(array[i].mOfferToReceiveVideo, &c->offer_to_receive_video);
|
|
||||||
Apply(array[i].mMozDontOfferDataChannel, &c->moz_dont_offer_datachannel);
|
|
||||||
Apply(array[i].mMozBundleOnly, &c->moz_bundle_only);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_media_constraints_t*
|
cc_media_options_t*
|
||||||
MediaConstraintsExternal::build() const {
|
SipccOfferOptions::build() const {
|
||||||
cc_media_constraints_t* cc = (cc_media_constraints_t*)
|
cc_media_options_t* cc = (cc_media_options_t*)
|
||||||
cpr_malloc(sizeof(cc_media_constraints_t));
|
cpr_malloc(sizeof(cc_media_options_t));
|
||||||
if (cc) {
|
if (cc) {
|
||||||
*cc = mConstraints;
|
*cc = mOptions;
|
||||||
}
|
}
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,15 +29,15 @@ namespace dom {
|
||||||
class WebrtcGlobalInformation;
|
class WebrtcGlobalInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unit-test helper, because cc_media_constraints_t is hard to forward-declare
|
// Unit-test helper, because cc_media_options_t is hard to forward-declare
|
||||||
|
|
||||||
class MediaConstraintsExternal {
|
class SipccOfferOptions {
|
||||||
public:
|
public:
|
||||||
MediaConstraintsExternal();
|
SipccOfferOptions();
|
||||||
MediaConstraintsExternal(const dom::MediaConstraintsInternal &aOther);
|
SipccOfferOptions(const dom::RTCOfferOptions &aOther);
|
||||||
cc_media_constraints_t* build() const;
|
cc_media_options_t* build() const;
|
||||||
protected:
|
protected:
|
||||||
cc_media_constraints_t mConstraints;
|
cc_media_options_t mOptions;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1083,7 +1083,7 @@ PeerConnectionImpl::CreateDataChannel(const nsAString& aLabel,
|
||||||
|
|
||||||
if (!mHaveDataStream) {
|
if (!mHaveDataStream) {
|
||||||
// XXX stream_id of 0 might confuse things...
|
// XXX stream_id of 0 might confuse things...
|
||||||
mInternal->mCall->addStream(0, 2, DATA, 0);
|
mInternal->mCall->addStream(0, 2, DATA);
|
||||||
mHaveDataStream = true;
|
mHaveDataStream = true;
|
||||||
}
|
}
|
||||||
nsIDOMDataChannel *retval;
|
nsIDOMDataChannel *retval;
|
||||||
|
@ -1170,14 +1170,14 @@ PeerConnectionImpl::NotifyDataChannel(already_AddRefed<DataChannel> aChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
PeerConnectionImpl::CreateOffer(const MediaConstraintsInternal& aConstraints)
|
PeerConnectionImpl::CreateOffer(const RTCOfferOptions& aOptions)
|
||||||
{
|
{
|
||||||
return CreateOffer(MediaConstraintsExternal (aConstraints));
|
return CreateOffer(SipccOfferOptions(aOptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by unit tests and the IDL CreateOffer.
|
// Used by unit tests and the IDL CreateOffer.
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
PeerConnectionImpl::CreateOffer(const MediaConstraintsExternal& aConstraints)
|
PeerConnectionImpl::CreateOffer(const SipccOfferOptions& aOptions)
|
||||||
{
|
{
|
||||||
PC_AUTO_ENTER_API_CALL(true);
|
PC_AUTO_ENTER_API_CALL(true);
|
||||||
|
|
||||||
|
@ -1185,20 +1185,14 @@ PeerConnectionImpl::CreateOffer(const MediaConstraintsExternal& aConstraints)
|
||||||
mTimeCard = nullptr;
|
mTimeCard = nullptr;
|
||||||
STAMP_TIMECARD(tc, "Create Offer");
|
STAMP_TIMECARD(tc, "Create Offer");
|
||||||
|
|
||||||
cc_media_constraints_t* cc_constraints = aConstraints.build();
|
cc_media_options_t* cc_options = aOptions.build();
|
||||||
NS_ENSURE_TRUE(cc_constraints, NS_ERROR_UNEXPECTED);
|
NS_ENSURE_TRUE(cc_options, NS_ERROR_UNEXPECTED);
|
||||||
mInternal->mCall->createOffer(cc_constraints, tc);
|
mInternal->mCall->createOffer(cc_options, tc);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
PeerConnectionImpl::CreateAnswer(const MediaConstraintsInternal& aConstraints)
|
PeerConnectionImpl::CreateAnswer()
|
||||||
{
|
|
||||||
return CreateAnswer(MediaConstraintsExternal (aConstraints));
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PeerConnectionImpl::CreateAnswer(const MediaConstraintsExternal& aConstraints)
|
|
||||||
{
|
{
|
||||||
PC_AUTO_ENTER_API_CALL(true);
|
PC_AUTO_ENTER_API_CALL(true);
|
||||||
|
|
||||||
|
@ -1206,9 +1200,7 @@ PeerConnectionImpl::CreateAnswer(const MediaConstraintsExternal& aConstraints)
|
||||||
mTimeCard = nullptr;
|
mTimeCard = nullptr;
|
||||||
STAMP_TIMECARD(tc, "Create Answer");
|
STAMP_TIMECARD(tc, "Create Answer");
|
||||||
|
|
||||||
cc_media_constraints_t* cc_constraints = aConstraints.build();
|
mInternal->mCall->createAnswer(tc);
|
||||||
NS_ENSURE_TRUE(cc_constraints, NS_ERROR_UNEXPECTED);
|
|
||||||
mInternal->mCall->createAnswer(cc_constraints, tc);
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1426,15 +1418,7 @@ PeerConnectionImpl::PrincipalChanged(DOMMediaStream* aMediaStream) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
PeerConnectionImpl::AddStream(DOMMediaStream &aMediaStream,
|
PeerConnectionImpl::AddStream(DOMMediaStream &aMediaStream)
|
||||||
const MediaConstraintsInternal& aConstraints)
|
|
||||||
{
|
|
||||||
return AddStream(aMediaStream, MediaConstraintsExternal(aConstraints));
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PeerConnectionImpl::AddStream(DOMMediaStream &aMediaStream,
|
|
||||||
const MediaConstraintsExternal& aConstraints)
|
|
||||||
{
|
{
|
||||||
PC_AUTO_ENTER_API_CALL(true);
|
PC_AUTO_ENTER_API_CALL(true);
|
||||||
|
|
||||||
|
@ -1470,16 +1454,12 @@ PeerConnectionImpl::AddStream(DOMMediaStream &aMediaStream,
|
||||||
|
|
||||||
// TODO(ekr@rtfm.com): these integers should be the track IDs
|
// TODO(ekr@rtfm.com): these integers should be the track IDs
|
||||||
if (hints & DOMMediaStream::HINT_CONTENTS_AUDIO) {
|
if (hints & DOMMediaStream::HINT_CONTENTS_AUDIO) {
|
||||||
cc_media_constraints_t* cc_constraints = aConstraints.build();
|
mInternal->mCall->addStream(stream_id, 0, AUDIO);
|
||||||
NS_ENSURE_TRUE(cc_constraints, NS_ERROR_UNEXPECTED);
|
|
||||||
mInternal->mCall->addStream(stream_id, 0, AUDIO, cc_constraints);
|
|
||||||
mNumAudioStreams++;
|
mNumAudioStreams++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hints & DOMMediaStream::HINT_CONTENTS_VIDEO) {
|
if (hints & DOMMediaStream::HINT_CONTENTS_VIDEO) {
|
||||||
cc_media_constraints_t* cc_constraints = aConstraints.build();
|
mInternal->mCall->addStream(stream_id, 1, VIDEO);
|
||||||
NS_ENSURE_TRUE(cc_constraints, NS_ERROR_UNEXPECTED);
|
|
||||||
mInternal->mCall->addStream(stream_id, 1, VIDEO, cc_constraints);
|
|
||||||
mNumVideoStreams++;
|
mNumVideoStreams++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1656,6 +1636,16 @@ PeerConnectionImpl::Close()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PeerConnectionImpl::PluginCrash(uint64_t aPluginID)
|
||||||
|
{
|
||||||
|
// fire an event to the DOM window if this is "ours"
|
||||||
|
bool result = mMedia ? mMedia->AnyCodecHasPluginID(aPluginID) : false;
|
||||||
|
if (result) {
|
||||||
|
CSFLogError(logTag, "%s: Our plugin %llu crashed", __FUNCTION__, static_cast<unsigned long long>(aPluginID));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
PeerConnectionImpl::CloseInt()
|
PeerConnectionImpl::CloseInt()
|
||||||
|
|
|
@ -73,7 +73,7 @@ class DOMMediaStream;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
struct RTCConfiguration;
|
struct RTCConfiguration;
|
||||||
struct MediaConstraintsInternal;
|
struct RTCOfferOptions;
|
||||||
class MediaStreamTrack;
|
class MediaStreamTrack;
|
||||||
|
|
||||||
#ifdef USE_FAKE_PCOBSERVER
|
#ifdef USE_FAKE_PCOBSERVER
|
||||||
|
@ -84,7 +84,7 @@ class PeerConnectionObserver;
|
||||||
typedef NS_ConvertUTF8toUTF16 PCObserverString;
|
typedef NS_ConvertUTF8toUTF16 PCObserverString;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
class MediaConstraintsExternal;
|
class SipccOfferOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||||
|
@ -108,8 +108,7 @@ namespace sipcc {
|
||||||
|
|
||||||
using mozilla::dom::PeerConnectionObserver;
|
using mozilla::dom::PeerConnectionObserver;
|
||||||
using mozilla::dom::RTCConfiguration;
|
using mozilla::dom::RTCConfiguration;
|
||||||
using mozilla::dom::MediaConstraintsInternal;
|
using mozilla::dom::RTCOfferOptions;
|
||||||
using mozilla::MediaConstraintsExternal;
|
|
||||||
using mozilla::DOMMediaStream;
|
using mozilla::DOMMediaStream;
|
||||||
using mozilla::NrIceCtx;
|
using mozilla::NrIceCtx;
|
||||||
using mozilla::NrIceMediaStream;
|
using mozilla::NrIceMediaStream;
|
||||||
|
@ -214,13 +213,11 @@ public:
|
||||||
|
|
||||||
enum Error {
|
enum Error {
|
||||||
kNoError = 0,
|
kNoError = 0,
|
||||||
kInvalidConstraintsType = 1,
|
|
||||||
kInvalidCandidateType = 2,
|
kInvalidCandidateType = 2,
|
||||||
kInvalidMediastreamTrack = 3,
|
kInvalidMediastreamTrack = 3,
|
||||||
kInvalidState = 4,
|
kInvalidState = 4,
|
||||||
kInvalidSessionDescription = 5,
|
kInvalidSessionDescription = 5,
|
||||||
kIncompatibleSessionDescription = 6,
|
kIncompatibleSessionDescription = 6,
|
||||||
kIncompatibleConstraints = 7,
|
|
||||||
kIncompatibleMediaStreamTrack = 8,
|
kIncompatibleMediaStreamTrack = 8,
|
||||||
kInternalError = 9
|
kInternalError = 9
|
||||||
};
|
};
|
||||||
|
@ -316,19 +313,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_TO_ERRORRESULT(CreateOffer, ErrorResult &rv,
|
NS_IMETHODIMP_TO_ERRORRESULT(CreateOffer, ErrorResult &rv,
|
||||||
const MediaConstraintsInternal& aConstraints)
|
const RTCOfferOptions& aOptions)
|
||||||
{
|
{
|
||||||
rv = CreateOffer(aConstraints);
|
rv = CreateOffer(aOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_TO_ERRORRESULT(CreateAnswer, ErrorResult &rv,
|
NS_IMETHODIMP CreateAnswer();
|
||||||
const MediaConstraintsInternal& aConstraints)
|
void CreateAnswer(ErrorResult &rv)
|
||||||
{
|
{
|
||||||
rv = CreateAnswer(aConstraints);
|
rv = CreateAnswer();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP CreateOffer(const MediaConstraintsExternal& aConstraints);
|
NS_IMETHODIMP CreateOffer(const mozilla::SipccOfferOptions& aConstraints);
|
||||||
NS_IMETHODIMP CreateAnswer(const MediaConstraintsExternal& aConstraints);
|
|
||||||
|
|
||||||
NS_IMETHODIMP SetLocalDescription (int32_t aAction, const char* aSDP);
|
NS_IMETHODIMP SetLocalDescription (int32_t aAction, const char* aSDP);
|
||||||
|
|
||||||
|
@ -368,15 +364,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_TO_ERRORRESULT(AddStream, ErrorResult &rv,
|
NS_IMETHODIMP_TO_ERRORRESULT(AddStream, ErrorResult &rv,
|
||||||
DOMMediaStream& aMediaStream,
|
DOMMediaStream& aMediaStream)
|
||||||
const MediaConstraintsInternal& aConstraints)
|
|
||||||
{
|
{
|
||||||
rv = AddStream(aMediaStream, aConstraints);
|
rv = AddStream(aMediaStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult AddStream(DOMMediaStream &aMediaStream,
|
|
||||||
const MediaConstraintsExternal& aConstraints);
|
|
||||||
|
|
||||||
NS_IMETHODIMP_TO_ERRORRESULT(RemoveStream, ErrorResult &rv,
|
NS_IMETHODIMP_TO_ERRORRESULT(RemoveStream, ErrorResult &rv,
|
||||||
DOMMediaStream& aMediaStream)
|
DOMMediaStream& aMediaStream)
|
||||||
{
|
{
|
||||||
|
@ -490,6 +482,8 @@ public:
|
||||||
rv = Close();
|
rv = Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PluginCrash(uint64_t aPluginID);
|
||||||
|
|
||||||
nsresult InitializeDataChannel(int track_id, uint16_t aLocalport,
|
nsresult InitializeDataChannel(int track_id, uint16_t aLocalport,
|
||||||
uint16_t aRemoteport, uint16_t aNumstreams);
|
uint16_t aRemoteport, uint16_t aNumstreams);
|
||||||
|
|
||||||
|
@ -669,7 +663,7 @@ private:
|
||||||
mozilla::RefPtr<DtlsIdentity> mIdentity;
|
mozilla::RefPtr<DtlsIdentity> mIdentity;
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
// The entity on the other end of the peer-to-peer connection;
|
// The entity on the other end of the peer-to-peer connection;
|
||||||
// void if they are not yet identified, and no constraint has been set
|
// void if they are not yet identified, and no identity setting has been set
|
||||||
nsAutoPtr<PeerIdentity> mPeerIdentity;
|
nsAutoPtr<PeerIdentity> mPeerIdentity;
|
||||||
#endif
|
#endif
|
||||||
// Whether an app should be prevented from accessing media produced by the PC
|
// Whether an app should be prevented from accessing media produced by the PC
|
||||||
|
|
|
@ -636,6 +636,46 @@ void RemoteSourceStreamInfo::UpdatePrincipal_m(nsIPrincipal* aPrincipal)
|
||||||
}
|
}
|
||||||
#endif // MOZILLA_INTERNAL_API
|
#endif // MOZILLA_INTERNAL_API
|
||||||
|
|
||||||
|
bool
|
||||||
|
PeerConnectionMedia::AnyCodecHasPluginID(uint64_t aPluginID)
|
||||||
|
{
|
||||||
|
for (uint32_t i=0; i < mLocalSourceStreams.Length(); ++i) {
|
||||||
|
if (mLocalSourceStreams[i]->AnyCodecHasPluginID(aPluginID)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint32_t i=0; i < mRemoteSourceStreams.Length(); ++i) {
|
||||||
|
if (mRemoteSourceStreams[i]->AnyCodecHasPluginID(aPluginID)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LocalSourceStreamInfo::AnyCodecHasPluginID(uint64_t aPluginID)
|
||||||
|
{
|
||||||
|
// Scan the videoConduits for this plugin ID
|
||||||
|
for (auto it = mPipelines.begin(); it != mPipelines.end(); ++it) {
|
||||||
|
if (it->second->Conduit()->CodecPluginID() == aPluginID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RemoteSourceStreamInfo::AnyCodecHasPluginID(uint64_t aPluginID)
|
||||||
|
{
|
||||||
|
// Scan the videoConduits for this plugin ID
|
||||||
|
for (auto it = mPipelines.begin(); it != mPipelines.end(); ++it) {
|
||||||
|
if (it->second->Conduit()->CodecPluginID() == aPluginID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LocalSourceStreamInfo::StorePipeline(
|
LocalSourceStreamInfo::StorePipeline(
|
||||||
int aTrack, mozilla::RefPtr<mozilla::MediaPipelineTransmit> aPipeline)
|
int aTrack, mozilla::RefPtr<mozilla::MediaPipelineTransmit> aPipeline)
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче