This commit is contained in:
Wes Kocher 2014-07-21 12:54:52 -07:00
Родитель 82d02bf40a 9d17e171bb
Коммит 8cc1c6b2ac
134 изменённых файлов: 2088 добавлений и 2203 удалений

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

@ -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);

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

@ -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)

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