merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-07-20 11:20:15 +02:00
commit 8428cd56e3
780 changed files with 29114 additions and 35268 deletions

View File

@ -154,8 +154,13 @@ nsCoreUtils::DispatchTouchEvent(EventMessage aMessage, int32_t aX, int32_t aY,
nsIContent* aContent, nsIFrame* aFrame,
nsIPresShell* aPresShell, nsIWidget* aRootWidget)
{
if (!dom::TouchEvent::PrefEnabled())
nsIDocShell* docShell = nullptr;
if (aPresShell->GetDocument()) {
docShell = aPresShell->GetDocument()->GetDocShell();
}
if (!dom::TouchEvent::PrefEnabled(docShell)) {
return;
}
WidgetTouchEvent event(true, aMessage, aRootWidget);

View File

@ -115,8 +115,9 @@ OuterDocAccessible::Shutdown()
bool
OuterDocAccessible::InsertChildAt(uint32_t aIdx, Accessible* aAccessible)
{
NS_ASSERTION(aAccessible->IsDoc(),
"OuterDocAccessible should only have document child!");
MOZ_RELEASE_ASSERT(aAccessible->IsDoc(),
"OuterDocAccessible can have a document child only!");
// We keep showing the old document for a bit after creating the new one,
// and while building the new DOM and frame tree. That's done on purpose
// to avoid weird flashes of default background color.
@ -164,6 +165,14 @@ OuterDocAccessible::RemoveChild(Accessible* aAccessible)
return wasRemoved;
}
bool
OuterDocAccessible::IsAcceptableChild(nsIContent* aEl) const
{
// outer document accessible doesn't not participate in ordinal tree
// mutations.
return false;
}
ProxyAccessible*
OuterDocAccessible::RemoteChildDoc() const
{

View File

@ -38,6 +38,7 @@ public:
virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) override;
virtual bool RemoveChild(Accessible* aAccessible) override;
virtual bool IsAcceptableChild(nsIContent* aEl) const override;
protected:
virtual ~OuterDocAccessible() override;

View File

@ -46,7 +46,8 @@ public:
mParent(aParent), mDoc(aDoc), mWrapper(0), mID(aID), mRole(aRole),
mOuterDoc(false), mIsDoc(false),
mHasValue(aInterfaces & Interfaces::VALUE),
mIsHyperLink(aInterfaces & Interfaces::HYPERLINK)
mIsHyperLink(aInterfaces & Interfaces::HYPERLINK),
mIsHyperText(aInterfaces & Interfaces::HYPERTEXT)
{
MOZ_COUNT_CTOR(ProxyAccessible);
}
@ -422,7 +423,7 @@ protected:
explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc) :
mParent(nullptr), mDoc(aThisAsDoc), mWrapper(0), mID(0),
mRole(roles::DOCUMENT), mOuterDoc(false), mIsDoc(true), mHasValue(false),
mIsHyperLink(false)
mIsHyperLink(false), mIsHyperText(false)
{ MOZ_COUNT_CTOR(ProxyAccessible); }
protected:
@ -436,7 +437,7 @@ private:
protected:
// XXX DocAccessibleParent gets to change this to change the role of
// documents.
role mRole : 28;
role mRole : 27;
private:
bool mOuterDoc : 1;
@ -444,6 +445,7 @@ public:
const bool mIsDoc: 1;
const bool mHasValue: 1;
const bool mIsHyperLink: 1;
const bool mIsHyperText: 1;
};
}

View File

@ -21,7 +21,6 @@ skip-if = e10s
[browser_caching_relations.js]
[browser_caching_states.js]
[browser_caching_value.js]
skip-if = e10s # Bug 1276721: QueryInterface is not working with proxies.
# Events tests
[browser_events_caretmove.js]

View File

@ -222,6 +222,14 @@ xpcAccessibleDocument::GetXPCAccessible(ProxyAccessible* aProxy)
interfaces |= eHyperLink;
}
if (aProxy->mIsHyperText) {
interfaces |= eText;
acc = new xpcAccessibleHyperText(aProxy, interfaces);
mCache.Put(aProxy, acc);
return acc;
}
acc = new xpcAccessibleGeneric(aProxy, interfaces);
mCache.Put(aProxy, acc);

1
aclocal.m4 vendored
View File

@ -32,6 +32,7 @@ builtin(include, build/autoconf/clang-plugin.m4)dnl
builtin(include, build/autoconf/alloc.m4)dnl
builtin(include, build/autoconf/ios.m4)dnl
builtin(include, build/autoconf/jemalloc.m4)dnl
builtin(include, build/autoconf/sanitize.m4)dnl
MOZ_PROG_CHECKMSYS()

View File

@ -244,9 +244,16 @@ const WeakValueGetterSetter = {
},
set: function(v) {
if (v && typeof v === "object") {
this._weakValue = Cu.getWeakReference(v)
this._simpleValue = undefined;
return;
try {
// Try to set a weak reference. This can throw for some values.
// For example, if the value is a native object that does not
// implement nsISupportsWeakReference.
this._weakValue = Cu.getWeakReference(v)
this._simpleValue = undefined;
return;
} catch (e) {
// Do nothing. Fall through to setting _simpleValue below.
}
}
this._simpleValue = v;
this._weakValue = undefined;

View File

@ -297,7 +297,7 @@ select[disabled] > button {
padding: 1px 7px 1px 7px;
}
*:-moz-any-link:active,
*:any-link:active,
*[role=button]:active,
button:active,
option:active,

View File

@ -1371,8 +1371,10 @@ pref("privacy.trackingprotection.introURL", "https://www.mozilla.org/%LOCALE%/fi
// Enable Contextual Identity Containers
#ifdef NIGHTLY_BUILD
pref("privacy.userContext.enabled", true);
pref("privacy.userContext.ui.enabled", true);
#else
pref("privacy.userContext.enabled", false);
pref("privacy.userContext.ui.enabled", false);
#endif
#ifndef RELEASE_BUILD

View File

@ -53,6 +53,17 @@ var gPrivacyPane = {
.getService(Components.interfaces.mozIPlacesAutoComplete);
},
/**
* Show the Containers UI depending on the privacy.userContext.ui.enabled pref.
*/
_initBrowserContainers: function () {
if (!Services.prefs.getBoolPref("privacy.userContext.ui.enabled")) {
return;
}
document.getElementById("browserContainersbox").hidden = false;
},
/**
* Sets up the UI for the number of days of history to keep, and updates the
* label of the "Clear Now..." button.
@ -73,6 +84,7 @@ var gPrivacyPane = {
this._initTrackingProtection();
this._initTrackingProtectionPBM();
this._initAutocomplete();
this._initBrowserContainers();
setEventListener("privacy.sanitize.sanitizeOnShutdown", "change",
gPrivacyPane._updateSanitizeSettingsButton);

View File

@ -74,6 +74,11 @@
name="browser.privatebrowsing.autostart"
type="bool"/>
<!-- Containers -->
<preference id="privacy.userContext.enabled"
name="privacy.userContext.enabled"
type="bool"/>
</preferences>
<hbox id="header-privacy"
@ -283,3 +288,14 @@
&suggestionSettings.label;
</label>
</groupbox>
<!-- Containers -->
<groupbox id="browserContainersGroup" data-category="panePrivacy" hidden="true">
<vbox id="browserContainersbox" hidden="true">
<caption><label>&browserContainersHeader.label;</label></caption>
<checkbox id="browserContainersCheckbox"
label="&browserContainersEnabled.label;"
accesskey="&browserContainersEnabled.accesskey;"
preference="privacy.userContext.enabled"/>
</vbox>
</groupbox>

View File

@ -0,0 +1,26 @@
[
{
"version": "gcc 4.8.5 + PR64905",
"size": 80160264,
"digest": "c1a9dc9da289b8528874d16300b9d13a997cec99195bb0bc46ff665216d8535d6d6cb5af6b4b1f2749af6815dab12e703fdb3849014e5c23a70eff351a0baf4e",
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": true
},
{
"version": "clang 3.8.0, libgcc 4.8.5",
"size": 139183100,
"digest": "a056a151d4f25f415b6d905136c3fa8d51d12a5a815c3df37d5663c67d59571736641a4c990884a69f78ea6b5e37a6a7bfff0417dfe38936d842d6fa0776ae54",
"algorithm": "sha512",
"filename": "clang.tar.xz",
"unpack": true
},
{
"size": 12072532,
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"setup": "setup.sh",
"unpack": true
}
]

View File

@ -104,3 +104,7 @@
<!ENTITY clearOnCloseSettings.label "Settings…">
<!ENTITY clearOnCloseSettings.accesskey "t">
<!ENTITY browserContainersHeader.label "Container Tabs">
<!ENTITY browserContainersEnabled.label "Enable Container Tabs">
<!ENTITY browserContainersEnabled.accesskey "a">

View File

@ -16,11 +16,10 @@ MOZ_ARG_WITH_BOOL(system-icu,
if test -n "$MOZ_SYSTEM_ICU"; then
PKG_CHECK_MODULES(MOZ_ICU, icu-i18n >= 50.1)
else
MOZ_ICU_INCLUDES="/intl/icu/source/common /intl/icu/source/i18n"
CFLAGS="$CFLAGS $MOZ_ICU_CFLAGS"
CXXFLAGS="$CXXFLAGS $MOZ_ICU_CFLAGS"
fi
AC_SUBST_LIST(MOZ_ICU_INCLUDES)
AC_SUBST(MOZ_SYSTEM_ICU)
MOZ_ARG_WITH_STRING(intl-api,

View File

@ -0,0 +1,85 @@
dnl This Source Code Form is subject to the terms of the Mozilla Public
dnl License, v. 2.0. If a copy of the MPL was not distributed with this
dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
AC_DEFUN([MOZ_CONFIG_SANITIZE], [
dnl ========================================================
dnl = Use Address Sanitizer
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(address-sanitizer,
[ --enable-address-sanitizer Enable Address Sanitizer (default=no)],
MOZ_ASAN=1,
MOZ_ASAN= )
if test -n "$MOZ_ASAN"; then
MOZ_LLVM_HACKS=1
if test -n "$CLANG_CL"; then
# Look for clang_rt.asan_dynamic-i386.dll
MOZ_CLANG_RT_ASAN_LIB=clang_rt.asan_dynamic-i386.dll
# We use MOZ_PATH_PROG in order to get a Windows style path.
MOZ_PATH_PROG(MOZ_CLANG_RT_ASAN_LIB_PATH, $MOZ_CLANG_RT_ASAN_LIB)
if test -z "$MOZ_CLANG_RT_ASAN_LIB_PATH"; then
AC_MSG_ERROR([Couldn't find $MOZ_CLANG_RT_ASAN_LIB. It should be available in the same location as clang-cl.])
fi
AC_SUBST(MOZ_CLANG_RT_ASAN_LIB_PATH)
fi
CFLAGS="-fsanitize=address -Dxmalloc=myxmalloc -fPIC $CFLAGS"
CXXFLAGS="-fsanitize=address -Dxmalloc=myxmalloc -fPIC $CXXFLAGS"
LDFLAGS="-fsanitize=address $LDFLAGS"
AC_DEFINE(MOZ_ASAN)
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
fi
AC_SUBST(MOZ_ASAN)
dnl ========================================================
dnl = Use Memory Sanitizer
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(memory-sanitizer,
[ --enable-memory-sanitizer Enable Memory Sanitizer (default=no)],
MOZ_MSAN=1,
MOZ_MSAN= )
if test -n "$MOZ_MSAN"; then
MOZ_LLVM_HACKS=1
CFLAGS="-fsanitize=memory -fsanitize-memory-track-origins $CFLAGS"
CXXFLAGS="-fsanitize=memory -fsanitize-memory-track-origins $CXXFLAGS"
LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins $LDFLAGS"
AC_DEFINE(MOZ_MSAN)
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
fi
AC_SUBST(MOZ_MSAN)
dnl ========================================================
dnl = Use Thread Sanitizer
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(thread-sanitizer,
[ --enable-thread-sanitizer Enable Thread Sanitizer (default=no)],
MOZ_TSAN=1,
MOZ_TSAN= )
if test -n "$MOZ_TSAN"; then
MOZ_LLVM_HACKS=1
CFLAGS="-fsanitize=thread $CFLAGS"
CXXFLAGS="-fsanitize=thread $CXXFLAGS"
LDFLAGS="-fsanitize=thread $LDFLAGS"
AC_DEFINE(MOZ_TSAN)
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
fi
AC_SUBST(MOZ_TSAN)
# The LLVM symbolizer is used by all sanitizers
AC_SUBST(LLVM_SYMBOLIZER)
dnl ========================================================
dnl = Enable hacks required for LLVM instrumentations
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(llvm-hacks,
[ --enable-llvm-hacks Enable workarounds required for several LLVM instrumentations (default=no)],
MOZ_LLVM_HACKS=1,
MOZ_LLVM_HACKS= )
if test -n "$MOZ_LLVM_HACKS"; then
MOZ_NO_WLZDEFS=1
MOZ_CFLAGS_NSS=1
fi
AC_SUBST(MOZ_NO_WLZDEFS)
AC_SUBST(MOZ_CFLAGS_NSS)
])

View File

@ -7,12 +7,6 @@ export CC="$topsrcdir/clang/bin/clang -fgnu89-inline"
export CXX="$topsrcdir/clang/bin/clang++"
export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
# Mandatory flags for ASan
export ASANFLAGS="-fsanitize=address -Dxmalloc=myxmalloc -fPIC"
export CFLAGS="$ASANFLAGS"
export CXXFLAGS="$ASANFLAGS"
export LDFLAGS="-fsanitize=address"
# Use a newer binutils, from the tooltool gcc package, if it's there
if [ -e "$topsrcdir/gcc/bin/ld" ]; then
export CC="$CC -B $topsrcdir/gcc/bin"

View File

@ -7,11 +7,6 @@ export CC="$topsrcdir/clang/bin/clang"
export CXX="$topsrcdir/clang/bin/clang++"
export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
# Mandatory flag for TSan
export CFLAGS="-fsanitize=thread"
export CXXFLAGS="-fsanitize=thread"
export LDFLAGS="-fsanitize=thread"
# Use a newer binutils, from the tooltool gcc package, if it's there
if [ -e "$topsrcdir/gcc/bin/ld" ]; then
export CC="$CC -B $topsrcdir/gcc/bin"
@ -21,7 +16,7 @@ fi
# Enable TSan specific code and build workarounds
ac_add_options --enable-thread-sanitizer
# The ThreadSanitizer is not compatible with sanboxing
# The ThreadSanitizer is not compatible with sandboxing
# (see bug 1182565)
ac_add_options --disable-sandbox

View File

@ -17,7 +17,7 @@ DEFINES['U_COMMON_IMPLEMENTATION'] = True
#FIXME: should probably stop including mozilla-config.h
DEFINES['LOCALE_SNAME'] = 0x5c
LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
LOCAL_INCLUDES += ['/intl/icu/source/i18n']
include('../defs.mozbuild')
include('sources.mozbuild')

View File

@ -179,3 +179,92 @@ SOURCES += [
'/intl/icu/source/common/uvectr64.cpp',
'/intl/icu/source/common/wintz.c',
]
EXPORTS.unicode += [
'/intl/icu/source/common/unicode/appendable.h',
'/intl/icu/source/common/unicode/brkiter.h',
'/intl/icu/source/common/unicode/bytestream.h',
'/intl/icu/source/common/unicode/bytestrie.h',
'/intl/icu/source/common/unicode/bytestriebuilder.h',
'/intl/icu/source/common/unicode/caniter.h',
'/intl/icu/source/common/unicode/chariter.h',
'/intl/icu/source/common/unicode/dbbi.h',
'/intl/icu/source/common/unicode/docmain.h',
'/intl/icu/source/common/unicode/dtintrv.h',
'/intl/icu/source/common/unicode/enumset.h',
'/intl/icu/source/common/unicode/errorcode.h',
'/intl/icu/source/common/unicode/filteredbrk.h',
'/intl/icu/source/common/unicode/icudataver.h',
'/intl/icu/source/common/unicode/icuplug.h',
'/intl/icu/source/common/unicode/idna.h',
'/intl/icu/source/common/unicode/listformatter.h',
'/intl/icu/source/common/unicode/localpointer.h',
'/intl/icu/source/common/unicode/locid.h',
'/intl/icu/source/common/unicode/messagepattern.h',
'/intl/icu/source/common/unicode/normalizer2.h',
'/intl/icu/source/common/unicode/normlzr.h',
'/intl/icu/source/common/unicode/parseerr.h',
'/intl/icu/source/common/unicode/parsepos.h',
'/intl/icu/source/common/unicode/platform.h',
'/intl/icu/source/common/unicode/ptypes.h',
'/intl/icu/source/common/unicode/putil.h',
'/intl/icu/source/common/unicode/rbbi.h',
'/intl/icu/source/common/unicode/rep.h',
'/intl/icu/source/common/unicode/resbund.h',
'/intl/icu/source/common/unicode/schriter.h',
'/intl/icu/source/common/unicode/std_string.h',
'/intl/icu/source/common/unicode/strenum.h',
'/intl/icu/source/common/unicode/stringpiece.h',
'/intl/icu/source/common/unicode/stringtriebuilder.h',
'/intl/icu/source/common/unicode/symtable.h',
'/intl/icu/source/common/unicode/ubidi.h',
'/intl/icu/source/common/unicode/ubrk.h',
'/intl/icu/source/common/unicode/ucasemap.h',
'/intl/icu/source/common/unicode/ucat.h',
'/intl/icu/source/common/unicode/uchar.h',
'/intl/icu/source/common/unicode/ucharstrie.h',
'/intl/icu/source/common/unicode/ucharstriebuilder.h',
'/intl/icu/source/common/unicode/uchriter.h',
'/intl/icu/source/common/unicode/uclean.h',
'/intl/icu/source/common/unicode/ucnv.h',
'/intl/icu/source/common/unicode/ucnv_cb.h',
'/intl/icu/source/common/unicode/ucnv_err.h',
'/intl/icu/source/common/unicode/ucnvsel.h',
'/intl/icu/source/common/unicode/uconfig.h',
'/intl/icu/source/common/unicode/udata.h',
'/intl/icu/source/common/unicode/uenum.h',
'/intl/icu/source/common/unicode/uidna.h',
'/intl/icu/source/common/unicode/uiter.h',
'/intl/icu/source/common/unicode/ulistformatter.h',
'/intl/icu/source/common/unicode/uloc.h',
'/intl/icu/source/common/unicode/umachine.h',
'/intl/icu/source/common/unicode/umisc.h',
'/intl/icu/source/common/unicode/unifilt.h',
'/intl/icu/source/common/unicode/unifunct.h',
'/intl/icu/source/common/unicode/unimatch.h',
'/intl/icu/source/common/unicode/uniset.h',
'/intl/icu/source/common/unicode/unistr.h',
'/intl/icu/source/common/unicode/unorm.h',
'/intl/icu/source/common/unicode/unorm2.h',
'/intl/icu/source/common/unicode/uobject.h',
'/intl/icu/source/common/unicode/urename.h',
'/intl/icu/source/common/unicode/urep.h',
'/intl/icu/source/common/unicode/ures.h',
'/intl/icu/source/common/unicode/uscript.h',
'/intl/icu/source/common/unicode/uset.h',
'/intl/icu/source/common/unicode/usetiter.h',
'/intl/icu/source/common/unicode/ushape.h',
'/intl/icu/source/common/unicode/usprep.h',
'/intl/icu/source/common/unicode/ustring.h',
'/intl/icu/source/common/unicode/ustringtrie.h',
'/intl/icu/source/common/unicode/utext.h',
'/intl/icu/source/common/unicode/utf.h',
'/intl/icu/source/common/unicode/utf16.h',
'/intl/icu/source/common/unicode/utf32.h',
'/intl/icu/source/common/unicode/utf8.h',
'/intl/icu/source/common/unicode/utf_old.h',
'/intl/icu/source/common/unicode/utrace.h',
'/intl/icu/source/common/unicode/utypes.h',
'/intl/icu/source/common/unicode/uvernum.h',
'/intl/icu/source/common/unicode/uversion.h',
]

View File

@ -9,7 +9,7 @@ FINAL_LIBRARY = 'icu'
DEFINES['U_I18N_IMPLEMENTATION'] = True
LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
LOCAL_INCLUDES += ['/intl/icu/source/common']
include('../defs.mozbuild')
include('sources.mozbuild')

View File

@ -199,3 +199,87 @@ SOURCES += [
'/intl/icu/source/i18n/zrule.cpp',
'/intl/icu/source/i18n/ztrans.cpp',
]
EXPORTS.unicode += [
'/intl/icu/source/i18n/unicode/alphaindex.h',
'/intl/icu/source/i18n/unicode/basictz.h',
'/intl/icu/source/i18n/unicode/calendar.h',
'/intl/icu/source/i18n/unicode/choicfmt.h',
'/intl/icu/source/i18n/unicode/coleitr.h',
'/intl/icu/source/i18n/unicode/coll.h',
'/intl/icu/source/i18n/unicode/compactdecimalformat.h',
'/intl/icu/source/i18n/unicode/curramt.h',
'/intl/icu/source/i18n/unicode/currpinf.h',
'/intl/icu/source/i18n/unicode/currunit.h',
'/intl/icu/source/i18n/unicode/datefmt.h',
'/intl/icu/source/i18n/unicode/dcfmtsym.h',
'/intl/icu/source/i18n/unicode/decimfmt.h',
'/intl/icu/source/i18n/unicode/dtfmtsym.h',
'/intl/icu/source/i18n/unicode/dtitvfmt.h',
'/intl/icu/source/i18n/unicode/dtitvinf.h',
'/intl/icu/source/i18n/unicode/dtptngen.h',
'/intl/icu/source/i18n/unicode/dtrule.h',
'/intl/icu/source/i18n/unicode/fieldpos.h',
'/intl/icu/source/i18n/unicode/fmtable.h',
'/intl/icu/source/i18n/unicode/format.h',
'/intl/icu/source/i18n/unicode/fpositer.h',
'/intl/icu/source/i18n/unicode/gender.h',
'/intl/icu/source/i18n/unicode/gregocal.h',
'/intl/icu/source/i18n/unicode/locdspnm.h',
'/intl/icu/source/i18n/unicode/measfmt.h',
'/intl/icu/source/i18n/unicode/measunit.h',
'/intl/icu/source/i18n/unicode/measure.h',
'/intl/icu/source/i18n/unicode/msgfmt.h',
'/intl/icu/source/i18n/unicode/numfmt.h',
'/intl/icu/source/i18n/unicode/numsys.h',
'/intl/icu/source/i18n/unicode/plurfmt.h',
'/intl/icu/source/i18n/unicode/plurrule.h',
'/intl/icu/source/i18n/unicode/rbnf.h',
'/intl/icu/source/i18n/unicode/rbtz.h',
'/intl/icu/source/i18n/unicode/regex.h',
'/intl/icu/source/i18n/unicode/region.h',
'/intl/icu/source/i18n/unicode/reldatefmt.h',
'/intl/icu/source/i18n/unicode/scientificnumberformatter.h',
'/intl/icu/source/i18n/unicode/search.h',
'/intl/icu/source/i18n/unicode/selfmt.h',
'/intl/icu/source/i18n/unicode/simpletz.h',
'/intl/icu/source/i18n/unicode/smpdtfmt.h',
'/intl/icu/source/i18n/unicode/sortkey.h',
'/intl/icu/source/i18n/unicode/stsearch.h',
'/intl/icu/source/i18n/unicode/tblcoll.h',
'/intl/icu/source/i18n/unicode/timezone.h',
'/intl/icu/source/i18n/unicode/tmunit.h',
'/intl/icu/source/i18n/unicode/tmutamt.h',
'/intl/icu/source/i18n/unicode/tmutfmt.h',
'/intl/icu/source/i18n/unicode/translit.h',
'/intl/icu/source/i18n/unicode/tzfmt.h',
'/intl/icu/source/i18n/unicode/tznames.h',
'/intl/icu/source/i18n/unicode/tzrule.h',
'/intl/icu/source/i18n/unicode/tztrans.h',
'/intl/icu/source/i18n/unicode/ucal.h',
'/intl/icu/source/i18n/unicode/ucol.h',
'/intl/icu/source/i18n/unicode/ucoleitr.h',
'/intl/icu/source/i18n/unicode/ucsdet.h',
'/intl/icu/source/i18n/unicode/ucurr.h',
'/intl/icu/source/i18n/unicode/udat.h',
'/intl/icu/source/i18n/unicode/udateintervalformat.h',
'/intl/icu/source/i18n/unicode/udatpg.h',
'/intl/icu/source/i18n/unicode/udisplaycontext.h',
'/intl/icu/source/i18n/unicode/ufieldpositer.h',
'/intl/icu/source/i18n/unicode/uformattable.h',
'/intl/icu/source/i18n/unicode/ugender.h',
'/intl/icu/source/i18n/unicode/uldnames.h',
'/intl/icu/source/i18n/unicode/ulocdata.h',
'/intl/icu/source/i18n/unicode/umsg.h',
'/intl/icu/source/i18n/unicode/unirepl.h',
'/intl/icu/source/i18n/unicode/unum.h',
'/intl/icu/source/i18n/unicode/unumsys.h',
'/intl/icu/source/i18n/unicode/upluralrules.h',
'/intl/icu/source/i18n/unicode/uregex.h',
'/intl/icu/source/i18n/unicode/uregion.h',
'/intl/icu/source/i18n/unicode/usearch.h',
'/intl/icu/source/i18n/unicode/uspoof.h',
'/intl/icu/source/i18n/unicode/utmscale.h',
'/intl/icu/source/i18n/unicode/utrans.h',
'/intl/icu/source/i18n/unicode/vtzone.h',
]

View File

@ -10,6 +10,4 @@
Library('icustubdata')
LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
SOURCES += ['/intl/icu/source/stubdata/stubdata.c']

View File

@ -11,6 +11,7 @@
# all related options.
from __future__ import print_function
from optparse import OptionParser
import mozfile
import os
import os.path
import sys
@ -126,10 +127,10 @@ def _nsinstall_internal(argv):
os.chmod(targetpath, options.m)
else:
if os.path.exists(targetpath):
# On Windows, read-only files can't be deleted
if sys.platform == "win32":
os.chmod(targetpath, stat.S_IWUSR)
os.remove(targetpath)
mozfile.remove(targetpath)
else:
os.remove(targetpath)
if options.t:
shutil.copy2(srcpath, targetpath)
else:

View File

@ -557,6 +557,10 @@ IOKit/IOMessage.h
IOKit/pwr_mgt/IOPMLib.h
iomanip
iostream.h
#if MOZ_JACK==1
jack/jack.h
jack/statistics.h
#endif
JavaControl.h
JavaEmbedding/JavaControl.h
JavaVM/jni.h

View File

@ -116,8 +116,8 @@ function* userAgentStylesVisible(inspector, view) {
// These tests rely on the "a" selector being the last test in
// TEST_DATA.
ok(uaRules.some(rule => {
return rule.matchedSelectors.indexOf(":-moz-any-link") !== -1;
}), "There is a rule for :-moz-any-link");
return rule.matchedSelectors.indexOf(":any-link") !== -1;
}), "There is a rule for :any-link");
ok(uaRules.some(rule => {
return rule.matchedSelectors.indexOf("*|*:link") !== -1;
}), "There is a rule for *|*:link");

View File

@ -2,6 +2,8 @@
* 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/. */
/* eslint-env browser */
"use strict";
const { DOM: dom, createClass, PropTypes, addons } =
@ -25,6 +27,10 @@ module.exports = createClass({
return {};
},
componentDidMount() {
window.addEventListener("keydown", this.onKeyDown, true);
},
componentWillReceiveProps(nextProps) {
let {
devices,
@ -39,6 +45,10 @@ module.exports = createClass({
}
},
componentWillUnmount() {
window.removeEventListener("keydown", this.onKeyDown, true);
},
onDeviceCheckboxClick({ target }) {
this.setState({
[target.value]: !this.state[target.value]
@ -78,18 +88,25 @@ module.exports = createClass({
onUpdateDeviceModalOpen(false);
},
onKeyDown(event) {
if (!this.props.devices.isModalOpen) {
return;
}
// Escape keycode
if (event.keyCode === 27) {
let {
onUpdateDeviceModalOpen
} = this.props;
onUpdateDeviceModalOpen(false);
}
},
render() {
let {
devices,
onUpdateDeviceModalOpen,
} = this.props;
let modalClass = "device-modal container";
if (!devices.isModalOpen) {
modalClass += " hidden";
}
const sortedDevices = {};
for (let type of devices.types) {
sortedDevices[type] = Object.assign([], devices[type])
@ -98,54 +115,66 @@ module.exports = createClass({
return dom.div(
{
className: modalClass,
id: "device-modal-wrapper",
className: this.props.devices.isModalOpen ? "opened" : "closed",
},
dom.button({
id: "device-close-button",
className: "toolbar-button devtools-button",
onClick: () => onUpdateDeviceModalOpen(false),
}),
dom.div(
{
className: "device-modal-content",
className: "device-modal container",
},
devices.types.map(type => {
return dom.div(
{
className: "device-type",
key: type,
},
dom.header(
dom.button({
id: "device-close-button",
className: "toolbar-button devtools-button",
onClick: () => onUpdateDeviceModalOpen(false),
}),
dom.div(
{
className: "device-modal-content",
},
devices.types.map(type => {
return dom.div(
{
className: "device-header",
className: "device-type",
key: type,
},
type
),
sortedDevices[type].map(device => {
return dom.label(
dom.header(
{
className: "device-label",
key: device.name,
className: "device-header",
},
dom.input({
className: "device-input-checkbox",
type: "checkbox",
value: device.name,
checked: this.state[device.name],
onChange: this.onDeviceCheckboxClick,
}),
device.name
);
})
);
})
type
),
sortedDevices[type].map(device => {
return dom.label(
{
className: "device-label",
key: device.name,
},
dom.input({
className: "device-input-checkbox",
type: "checkbox",
value: device.name,
checked: this.state[device.name],
onChange: this.onDeviceCheckboxClick,
}),
device.name
);
})
);
})
),
dom.button(
{
id: "device-submit-button",
onClick: this.onDeviceModalSubmit,
},
getStr("responsive.done")
)
),
dom.button(
dom.div(
{
id: "device-submit-button",
onClick: this.onDeviceModalSubmit,
},
getStr("responsive.done")
className: "modal-overlay",
onClick: () => onUpdateDeviceModalOpen(false),
}
)
);
},

View File

@ -39,6 +39,7 @@
#root,
html, body {
height: 100%;
margin: 0;
}
@ -47,12 +48,10 @@ html, body {
display: flex;
align-items: center;
flex-direction: column;
height: 100vh;
/* Snap to the top of the app when there isn't enough vertical space anymore
to center the viewports (so we don't lose the global toolbar) */
position: sticky;
top: 0;
padding-top: 15px;
padding-bottom: 1%;
position: relative;
height: 100%;
}
/**
@ -86,7 +85,7 @@ html, body {
color: var(--theme-body-color-alt);
border-radius: 2px;
box-shadow: var(--rdm-box-shadow);
margin: 10% 0 30px 0;
margin: 0 0 15px 0;
padding: 4px 5px;
display: inline-flex;
-moz-user-select: none;
@ -336,9 +335,33 @@ html, body {
* Device Modal
*/
@keyframes fade-in-and-up {
0% {
opacity: 0;
transform: translateY(5px);
}
100% {
opacity: 1;
transform: translateY(0px);
}
}
@keyframes fade-down-and-out {
0% {
opacity: 1;
transform: translateY(0px);
}
100% {
opacity: 0;
transform: translateY(5px);
visibility: hidden;
}
}
.device-modal {
border-radius: 2px;
box-shadow: var(--rdm-box-shadow);
display: none;
position: absolute;
margin: auto;
top: 0;
@ -347,10 +370,31 @@ html, body {
right: 0;
width: 642px;
height: 612px;
z-index: 1;
}
.device-modal.hidden {
display: none;
/* Handles the opening/closing of the modal */
#device-modal-wrapper.opened .device-modal {
animation: fade-in-and-up 0.3s ease;
animation-fill-mode: forwards;
display: block;
}
#device-modal-wrapper.closed .device-modal {
animation: fade-down-and-out 0.3s ease;
animation-fill-mode: forwards;
display: block;
}
#device-modal-wrapper.opened .modal-overlay {
background-color: var(--theme-splitter-color);
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 0;
opacity: 0.5;
}
.device-modal-content {

View File

@ -10,7 +10,7 @@ const Types = require("devtools/client/responsive.html/types");
addRDMTask(TEST_URL, function* ({ ui }) {
let { store, document } = ui.toolWindow;
let modal = document.querySelector(".device-modal");
let modal = document.querySelector("#device-modal-wrapper");
let closeButton = document.querySelector("#device-close-button");
// Wait until the viewport has been added and the device list has been loaded
@ -28,8 +28,8 @@ addRDMTask(TEST_URL, function* ({ ui }) {
uncheckedCb.click();
closeButton.click();
ok(modal.classList.contains("hidden"),
"The device modal is hidden on exit.");
ok(modal.classList.contains("closed") && !modal.classList.contains("opened"),
"The device modal is closed on exit.");
info("Check that the device list remains unchanged after exitting.");
let preferredDevicesAfter = _loadPreferredDevices();

View File

@ -23,7 +23,7 @@ const Types = require("devtools/client/responsive.html/types");
addRDMTask(TEST_URL, function* ({ ui }) {
let { store, document } = ui.toolWindow;
let modal = document.querySelector(".device-modal");
let modal = document.querySelector("#device-modal-wrapper");
let select = document.querySelector(".viewport-device-selector");
let submitButton = document.querySelector("#device-submit-button");
@ -61,8 +61,8 @@ addRDMTask(TEST_URL, function* ({ ui }) {
uncheckedCb.click();
submitButton.click();
ok(modal.classList.contains("hidden"),
"The device modal is hidden on submit.");
ok(modal.classList.contains("closed") && !modal.classList.contains("opened"),
"The device modal is closed on submit.");
info("Checking that the new device is added to the user preference list.");
let preferredDevices = _loadPreferredDevices();

View File

@ -135,14 +135,14 @@ var setViewportSize = Task.async(function* (ui, manager, width, height) {
function openDeviceModal(ui) {
let { document } = ui.toolWindow;
let select = document.querySelector(".viewport-device-selector");
let modal = document.querySelector(".device-modal");
let modal = document.querySelector("#device-modal-wrapper");
let editDeviceOption = [...select.options].filter(o => {
return o.value === OPEN_DEVICE_MODAL_VALUE;
})[0];
info("Checking initial device modal state");
ok(modal.classList.contains("hidden"),
"The device modal is hidden by default.");
ok(modal.classList.contains("closed") && !modal.classList.contains("opened"),
"The device modal is closed by default.");
info("Opening device modal through device selector.");
EventUtils.synthesizeMouseAtCenter(select, {type: "mousedown"},
@ -150,7 +150,7 @@ function openDeviceModal(ui) {
EventUtils.synthesizeMouseAtCenter(editDeviceOption, {type: "mouseup"},
ui.toolWindow);
ok(!modal.classList.contains("hidden"),
ok(modal.classList.contains("opened") && !modal.classList.contains("closed"),
"The device modal is displayed.");
}

View File

@ -815,6 +815,7 @@ nsDocShell::nsDocShell()
, mPrivateBrowsingId(0)
, mParentCharsetSource(0)
, mJSRunToCompletionDepth(0)
, mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE)
{
AssertOriginAttributesMatchPrivateBrowsing();
mHistoryID = ++gDocshellIDCounter;
@ -3180,6 +3181,36 @@ nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetTouchEventsOverride(uint32_t* aTouchEventsOverride)
{
NS_ENSURE_ARG_POINTER(aTouchEventsOverride);
*aTouchEventsOverride = mTouchEventsOverride;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetTouchEventsOverride(uint32_t aTouchEventsOverride)
{
if (!(aTouchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE ||
aTouchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED ||
aTouchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_DISABLED)) {
return NS_ERROR_INVALID_ARG;
}
mTouchEventsOverride = aTouchEventsOverride;
uint32_t childCount = mChildList.Length();
for (uint32_t i = 0; i < childCount; ++i) {
nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(ChildAt(i));
if (childShell) {
childShell->SetTouchEventsOverride(aTouchEventsOverride);
}
}
return NS_OK;
}
/* virtual */ int32_t
nsDocShell::ItemType()
{
@ -3352,6 +3383,10 @@ nsDocShell::SetDocLoaderParent(nsDocLoader* aParent)
if (NS_SUCCEEDED(parentAsDocShell->GetDefaultLoadFlags(&flags))) {
SetDefaultLoadFlags(flags);
}
uint32_t touchEventsOverride;
if (NS_SUCCEEDED(parentAsDocShell->GetTouchEventsOverride(&touchEventsOverride))) {
SetTouchEventsOverride(touchEventsOverride);
}
}
nsCOMPtr<nsILoadContext> parentAsLoadContext(do_QueryInterface(parent));

View File

@ -1038,6 +1038,10 @@ private:
// has been called without a matching NotifyRunToCompletionStop.
uint32_t mJSRunToCompletionDepth;
// Whether or not touch events are overridden. Possible values are defined
// as constants in the nsIDocShell.idl file.
uint32_t mTouchEventsOverride;
// Separate function to do the actual name (i.e. not _top, _self etc.)
// searching for FindItemWithName.
nsresult DoFindItemWithName(const char16_t* aName,

View File

@ -1114,4 +1114,22 @@ interface nsIDocShell : nsIDocShellTreeItem
[noscript,notxpcom,nostdcall] TabChildRef GetTabChild();
[noscript,nostdcall,notxpcom] nsICommandManager GetCommandManager();
/**
* This allows chrome to override the default choice of whether touch events
* are available on a specific docshell. Possible values are listed below.
*/
attribute unsigned long touchEventsOverride;
/**
* Override platform/pref default behaviour and force-disable touch events.
*/
const unsigned long TOUCHEVENTS_OVERRIDE_DISABLED = 0;
/**
* Override platform/pref default behaviour and force-enable touch events.
*/
const unsigned long TOUCHEVENTS_OVERRIDE_ENABLED = 1;
/**
* Don't override the platform/pref default behaviour for touch events.
*/
const unsigned long TOUCHEVENTS_OVERRIDE_NONE = 2;
};

View File

@ -84,10 +84,11 @@ support-files =
[browser_multiple_pushState.js]
[browser_onbeforeunload_navigation.js]
[browser_search_notification.js]
[browser_ua_emulation.js]
[browser_tab_touch_events.js]
[browser_timelineMarkers-01.js]
[browser_timelineMarkers-02.js]
skip-if = true # Bug 1220415
[browser_timelineMarkers-03.js]
[browser_timelineMarkers-04.js]
[browser_timelineMarkers-05.js]
[browser_ua_emulation.js]

View File

@ -0,0 +1,64 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
add_task(function*() {
yield openUrl("data:text/html;charset=utf-8,<iframe id='test-iframe'></iframe>");
let docshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_NONE,
"touchEventsOverride flag should be initially set to NONE");
docshell.touchEventsOverride = Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED;
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
"touchEventsOverride flag should be changed to DISABLED");
let frameWin = content.document.querySelector("#test-iframe").contentWindow;
docshell = frameWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
"touchEventsOverride flag should be passed on to frames.");
let newFrame = content.document.createElement("iframe");
content.document.body.appendChild(newFrame);
let newFrameWin = newFrame.contentWindow;
docshell = newFrameWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
"Newly created frames should use the new touchEventsOverride flag");
newFrameWin.location.reload();
yield waitForEvent(newFrameWin, "load");
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
"New touchEventsOverride flag should persist across reloads");
gBrowser.removeCurrentTab();
});
function waitForEvent(target, event) {
return new Promise(function(resolve) {
target.addEventListener(event, resolve);
});
}
function openUrl(url) {
return new Promise(function(resolve, reject) {
window.focus();
let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
let linkedBrowser = tab.linkedBrowser;
linkedBrowser.addEventListener("load", function onload() {
linkedBrowser.removeEventListener("load", onload, true);
resolve(tab);
}, true);
});
}

View File

@ -8346,6 +8346,25 @@ nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal,
return aChannel->SetReferrerWithPolicy(referrerURI, referrerPolicy);
}
// static
net::ReferrerPolicy
nsContentUtils::GetReferrerPolicyFromHeader(const nsAString& aHeader)
{
// Multiple headers could be concatenated into one comma-separated
// list of policies. Need to tokenize the multiple headers.
nsCharSeparatedTokenizer tokenizer(aHeader, ',');
nsAutoString token;
net::ReferrerPolicy referrerPolicy = mozilla::net::RP_Unset;
while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
net::ReferrerPolicy policy = net::ReferrerPolicyFromString(token);
if (policy != net::RP_Unset) {
referrerPolicy = policy;
}
}
return referrerPolicy;
}
// static
bool
nsContentUtils::PushEnabled(JSContext* aCx, JSObject* aObj)
@ -9212,3 +9231,43 @@ nsContentUtils::GetPresentationURL(nsIDocShell* aDocShell, nsAString& aPresentat
topFrameElement->GetAttribute(NS_LITERAL_STRING("mozpresentation"), aPresentationUrl);
}
/* static */ nsIDocShell*
nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget)
{
nsCOMPtr<nsINode> node(do_QueryInterface(aTarget));
nsIDocument* doc = nullptr;
nsIDocShell* docShell = nullptr;
if (node) {
doc = node->OwnerDoc();
if (!doc->GetDocShell()) {
bool ignore;
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(doc->GetScriptHandlingObject(ignore));
if (window) {
doc = window->GetExtantDoc();
}
}
} else {
nsCOMPtr<nsPIDOMWindowInner> window(do_QueryInterface(aTarget));
if (window) {
doc = window->GetExtantDoc();
}
}
if (!doc) {
nsCOMPtr<DOMEventTargetHelper> helper(do_QueryInterface(aTarget));
if (helper) {
if (nsPIDOMWindowInner* window = helper->GetOwner()) {
doc = window->GetExtantDoc();
}
}
}
if (doc) {
docShell = doc->GetDocShell();
}
return docShell;
}

View File

@ -2578,6 +2578,15 @@ public:
nsIHttpChannel* aChannel,
mozilla::net::ReferrerPolicy aReferrerPolicy);
/*
* Parse a referrer policy from a Referrer-Policy header
* https://www.w3.org/TR/referrer-policy/#parse-referrer-policy-from-header
*
* @param aHeader the response's Referrer-Policy header to parse
* @return referrer policy from the response header.
*/
static mozilla::net::ReferrerPolicy GetReferrerPolicyFromHeader(const nsAString& aHeader);
static bool PushEnabled(JSContext* aCx, JSObject* aObj);
static bool IsNonSubresourceRequest(nsIChannel* aChannel);
@ -2642,6 +2651,11 @@ public:
*/
static void GetPresentationURL(nsIDocShell* aDocShell, nsAString& aPresentationUrl);
/*
* Try to find the docshell corresponding to the given event target.
*/
static nsIDocShell* GetDocShellForEventTarget(mozilla::dom::EventTarget* aTarget);
private:
static bool InitializeEventTable();

View File

@ -3785,6 +3785,15 @@ nsDocument::SetHeaderData(nsIAtom* aHeaderField, const nsAString& aData)
mReferrerPolicySet = true;
}
}
if (aHeaderField == nsGkAtoms::headerReferrerPolicy && !aData.IsEmpty()) {
ReferrerPolicy policy = nsContentUtils::GetReferrerPolicyFromHeader(aData);
if (policy != mozilla::net::RP_Unset) {
mReferrerPolicy = policy;
mReferrerPolicySet = true;
}
}
}
void
nsDocument::TryChannelCharset(nsIChannel *aChannel,
@ -8726,6 +8735,7 @@ nsDocument::RetrieveRelevantHeaders(nsIChannel *aChannel)
"refresh",
"x-dns-prefetch-control",
"x-frame-options",
"referrer-policy",
// add more http headers if you need
// XXXbz don't add content-location support without reading bug
// 238654 and its dependencies/dups first.

View File

@ -1735,7 +1735,8 @@ nsMessageManagerScriptExecutor::LoadScriptInternal(const nsAString& aURL,
JSContext* cx = aes.cx();
if (script) {
if (aRunInGlobalScope) {
JS::CloneAndExecuteScript(cx, script);
JS::RootedValue rval(cx);
JS::CloneAndExecuteScript(cx, script, &rval);
} else {
JS::Rooted<JSObject*> scope(cx);
bool ok = js::ExecuteInGlobalAndReturnScope(cx, global, script, &scope);

View File

@ -599,6 +599,7 @@ GK_ATOM(message, "message")
GK_ATOM(meta, "meta")
GK_ATOM(referrer, "referrer")
GK_ATOM(referrerpolicy, "referrerpolicy")
GK_ATOM(headerReferrerPolicy, "referrer-policy")
GK_ATOM(meter, "meter")
GK_ATOM(method, "method")
GK_ATOM(middle, "middle")

View File

@ -51,9 +51,10 @@ public:
/**
* Content type identifying the scripting language. Can be empty, in
* which case javascript will be assumed.
* Return false if type attribute is not found.
*/
virtual void GetScriptType(nsAString& type) = 0;
virtual bool GetScriptType(nsAString& type) = 0;
/**
* Location of script source text. Can return null, in which case
* this is assumed to be an inline script element.
@ -63,7 +64,7 @@ public:
NS_PRECONDITION(mFrozen, "Not ready for this call yet!");
return mUri;
}
/**
* Script source text for inline script elements.
*/
@ -93,7 +94,7 @@ public:
bool GetScriptAsync()
{
NS_PRECONDITION(mFrozen, "Not ready for this call yet!");
return mAsync;
return mAsync;
}
/**
@ -198,7 +199,7 @@ public:
parser->EndEvaluatingParserInsertedScript();
}
}
/**
* Retrieves a pointer to the creator parser if this has one or null if not
*/
@ -264,17 +265,17 @@ protected:
* The start line number of the script.
*/
uint32_t mLineNumber;
/**
* The "already started" flag per HTML5.
*/
bool mAlreadyStarted;
/**
* The script didn't have an end tag.
*/
bool mMalformed;
/**
* False if parser-inserted but the parser hasn't triggered running yet.
*/
@ -290,17 +291,17 @@ protected:
* Whether src, defer and async are frozen.
*/
bool mFrozen;
/**
* The effective deferredness.
*/
bool mDefer;
/**
* The effective asyncness.
*/
bool mAsync;
/**
* The effective externalness. A script can be external with mUri being null
* if the src attribute contained an invalid URL string.
@ -316,7 +317,7 @@ protected:
* The effective src (or null if no src).
*/
nsCOMPtr<nsIURI> mUri;
/**
* The creator parser of a non-defer, non-async parser-inserted script.
*/

View File

@ -195,7 +195,7 @@ nsJSUtils::EvaluateString(JSContext* aCx,
if (ok && aOffThreadToken) {
JS::Rooted<JSScript*>
script(aCx, JS::FinishOffThreadScript(aCx, JS_GetRuntime(aCx), *aOffThreadToken));
script(aCx, JS::FinishOffThreadScript(aCx, *aOffThreadToken));
*aOffThreadToken = nullptr; // Mark the token as having been finished.
if (script) {
ok = JS_ExecuteScript(aCx, scopeChain, script);

View File

@ -708,8 +708,7 @@ nsScriptLoader::CreateModuleScript(nsModuleLoadRequest* aRequest)
JS::Rooted<JSObject*> module(cx);
if (aRequest->mWasCompiledOMT) {
module = JS::FinishOffThreadModule(cx, xpc::GetJSRuntime(),
aRequest->mOffThreadToken);
module = JS::FinishOffThreadModule(cx, aRequest->mOffThreadToken);
aRequest->mOffThreadToken = nullptr;
rv = module ? NS_OK : NS_ERROR_FAILURE;
} else {
@ -1277,7 +1276,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// Check the type attribute to determine language and version.
// If type exists, it trumps the deprecated 'language='
nsAutoString type;
aElement->GetScriptType(type);
bool hasType = aElement->GetScriptType(type);
nsScriptKind scriptKind = nsScriptKind::Classic;
if (!type.IsEmpty()) {
// Support type="module" only for chrome documents.
@ -1286,7 +1286,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
} else {
NS_ENSURE_TRUE(ParseTypeAttribute(type, &version), false);
}
} else {
} else if (!hasType) {
// no 'type=' element
// "language" is a deprecated attribute of HTML, so we check it only for
// HTML script elements.
@ -1829,7 +1829,8 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
// (disappearing window, some other error, ...). Finish the
// request to avoid leaks in the JS engine.
MOZ_ASSERT(!aRequest->IsModuleRequest());
JS::FinishOffThreadScript(nullptr, xpc::GetJSRuntime(), aRequest->mOffThreadToken);
JSContext* cx = JS_GetContext(xpc::GetJSRuntime());
JS::CancelOffThreadScript(cx, aRequest->mOffThreadToken);
aRequest->mOffThreadToken = nullptr;
}

View File

@ -44,7 +44,7 @@ nsresult TestGetURL(const nsCString& aURL)
rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
TEST_ENSURE_SUCCESS(rv, "Couldn't get system principal!");
rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr, nullptr);
rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr);
TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!");
rv = xhr->Open(getString, aURL, false, empty, empty);

View File

@ -54,7 +54,7 @@ nsresult TestNativeXMLHttpRequest()
rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
TEST_ENSURE_SUCCESS(rv, "Couldn't get system principal!");
rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr, nullptr);
rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr);
TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!");
rv = xhr->Open(getString, testURL, false, empty, empty);

View File

@ -16,9 +16,7 @@ namespace dom {
template<class T>
T* GetAtomCache(JSContext* aCx)
{
JSRuntime* rt = JS_GetRuntime(aCx);
auto atomCache = static_cast<PerThreadAtomCache*>(JS_GetRuntimePrivate(rt));
auto atomCache = static_cast<PerThreadAtomCache*>(JS_GetContextPrivate(aCx));
return static_cast<T*>(atomCache);
}

View File

@ -3910,13 +3910,6 @@ CanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
{
nsresult rv;
// spec isn't clear on what should happen if aMaxWidth <= 0, so
// treat it as an invalid argument
// technically, 0 should be an invalid value as well, but 0 is the default
// arg, and there is no way to tell if the default was used
if (aMaxWidth.WasPassed() && aMaxWidth.Value() < 0)
return NS_ERROR_INVALID_ARG;
if (!mCanvasElement && !mDocShell) {
NS_WARNING("Canvas element must be non-null or a docshell must be provided");
return NS_ERROR_FAILURE;
@ -3932,6 +3925,12 @@ CanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
nsAutoString textToDraw(aRawText);
TextReplaceWhitespaceCharacters(textToDraw);
// According to spec, the API should return an empty array if maxWidth was provided
// but is less than or equal to zero or equal to NaN.
if (aMaxWidth.WasPassed() && (aMaxWidth.Value() <= 0 || IsNaN(aMaxWidth.Value()))) {
textToDraw.Truncate();
}
// for now, default to ltr if not in doc
bool isRTL = false;

View File

@ -20,12 +20,12 @@ namespace mozilla {
namespace webgl {
static bool
UnpackFormatHasAlpha(GLenum unpackFormat)
UnpackFormatHasColorAndAlpha(GLenum unpackFormat)
{
switch (unpackFormat) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE_ALPHA:
case LOCAL_GL_RGBA:
case LOCAL_GL_SRGB_ALPHA:
return true;
default:
@ -216,7 +216,7 @@ TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
const auto dstFormat = FormatForPackingInfo(pi);
bool premultMatches = (mIsSrcPremult == isDstPremult);
if (!UnpackFormatHasAlpha(dstDUI->unpackFormat)) {
if (!UnpackFormatHasColorAndAlpha(dstDUI->unpackFormat)) {
premultMatches = true;
}

View File

@ -25,11 +25,8 @@ WebGLExtensionVertexArray::~WebGLExtensionVertexArray()
already_AddRefed<WebGLVertexArray>
WebGLExtensionVertexArray::CreateVertexArrayOES()
{
if (mIsLost) {
mContext->ErrorInvalidOperation("%s: Extension is lost.",
"createVertexArrayOES");
if (mIsLost)
return nullptr;
}
return mContext->CreateVertexArray();
}
@ -37,11 +34,8 @@ WebGLExtensionVertexArray::CreateVertexArrayOES()
void
WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
{
if (mIsLost) {
mContext->ErrorInvalidOperation("%s: Extension is lost.",
"deleteVertexArrayOES");
if (mIsLost)
return;
}
mContext->DeleteVertexArray(array);
}
@ -49,11 +43,8 @@ WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
bool
WebGLExtensionVertexArray::IsVertexArrayOES(WebGLVertexArray* array)
{
if (mIsLost) {
mContext->ErrorInvalidOperation("%s: Extension is lost.",
"isVertexArrayOES");
if (mIsLost)
return false;
}
return mContext->IsVertexArray(array);
}
@ -61,11 +52,8 @@ WebGLExtensionVertexArray::IsVertexArrayOES(WebGLVertexArray* array)
void
WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array)
{
if (mIsLost) {
mContext->ErrorInvalidOperation("%s: Extension is lost.",
"bindVertexArrayOES");
if (mIsLost)
return;
}
mContext->BindVertexArray(array);
}

View File

@ -396,6 +396,10 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
}
}
// Frag outputs
prog->EnumerateFragOutputs(info->fragDataMap);
return info.forget();
}
@ -632,9 +636,9 @@ WebGLProgram::GetFragDataLocation(const nsAString& userName_wide) const
}
const NS_LossyConvertUTF16toASCII userName(userName_wide);
nsCString mappedName;
if (!FindActiveOutputMappedNameByUserName(userName, &mappedName)) {
if (!LinkInfo()->FindFragData(userName, &mappedName)) {
mappedName = userName;
}
@ -1189,17 +1193,6 @@ WebGLProgram::LinkAndUpdate()
MOZ_RELEASE_ASSERT(mMostRecentLinkInfo, "GFX: most recent link info not set.");
}
bool
WebGLProgram::FindActiveOutputMappedNameByUserName(const nsACString& userName,
nsCString* const out_mappedName) const
{
if (mFragShader->FindActiveOutputMappedNameByUserName(userName, out_mappedName)) {
return true;
}
return false;
}
bool
WebGLProgram::FindAttribUserNameByMappedName(const nsACString& mappedName,
nsDependentCString* const out_userName) const
@ -1309,6 +1302,14 @@ WebGLProgram::FindUniformBlockByMappedName(const nsACString& mappedName,
return false;
}
void
WebGLProgram::EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const
{
MOZ_ASSERT(mFragShader);
mFragShader->EnumerateFragOutputs(out_FragOutputs);
}
////////////////////////////////////////////////////////////////////////////////
bool

View File

@ -90,6 +90,9 @@ struct LinkedProgramInfo final
//////
// The maps for the frag data names to the translated names.
std::map<nsCString, const nsCString> fragDataMap;
explicit LinkedProgramInfo(WebGLProgram* prog);
~LinkedProgramInfo();
@ -97,6 +100,19 @@ struct LinkedProgramInfo final
bool FindUniform(const nsCString& baseUserName, UniformInfo** const out) const;
bool FindUniformBlock(const nsCString& baseUserName,
const UniformBlockInfo** const out) const;
bool
FindFragData(const nsCString& baseUserName,
nsCString* const out_baseMappedName) const
{
const auto itr = fragDataMap.find(baseUserName);
if (itr == fragDataMap.end()) {
return false;
}
*out_baseMappedName = itr->second;
return true;
}
};
} // namespace webgl
@ -144,8 +160,6 @@ public:
////////////////
bool FindActiveOutputMappedNameByUserName(const nsACString& userName,
nsCString* const out_mappedName) const;
bool FindAttribUserNameByMappedName(const nsACString& mappedName,
nsDependentCString* const out_userName) const;
bool FindVaryingByMappedName(const nsACString& mappedName,
@ -162,6 +176,8 @@ public:
GLenum bufferMode);
already_AddRefed<WebGLActiveInfo> GetTransformFeedbackVarying(GLuint index);
void EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const;
bool IsLinked() const { return mMostRecentLinkInfo; }
const webgl::LinkedProgramInfo* LinkInfo() const {

View File

@ -329,22 +329,6 @@ WebGLShader::BindAttribLocation(GLuint prog, const nsCString& userName,
mContext->gl->fBindAttribLocation(prog, index, mappedNameStr->c_str());
}
bool
WebGLShader::FindActiveOutputMappedNameByUserName(const nsACString& userName,
nsCString* const out_mappedName) const
{
if (!mValidator)
return false;
const std::string userNameStr(userName.BeginReading());
const std::string* mappedNameStr;
if (!mValidator->FindActiveOutputMappedNameByUserName(userNameStr, &mappedNameStr))
return false;
*out_mappedName = mappedNameStr->c_str();
return true;
}
bool
WebGLShader::FindAttribUserNameByMappedName(const nsACString& mappedName,
nsDependentCString* const out_userName) const
@ -412,6 +396,17 @@ WebGLShader::FindUniformBlockByMappedName(const nsACString& mappedName,
return true;
}
void
WebGLShader::EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const
{
out_FragOutputs.clear();
if (!mValidator) {
return;
}
mValidator->EnumerateFragOutputs(out_FragOutputs);
}
void
WebGLShader::ApplyTransformFeedbackVaryings(GLuint prog,
const std::vector<nsCString>& varyings,

View File

@ -52,8 +52,6 @@ public:
size_t CalcNumSamplerUniforms() const;
size_t NumAttributes() const;
void BindAttribLocation(GLuint prog, const nsCString& userName, GLuint index) const;
bool FindActiveOutputMappedNameByUserName(const nsACString& userName,
nsCString* const out_mappedName) const;
bool FindAttribUserNameByMappedName(const nsACString& mappedName,
nsDependentCString* const out_userName) const;
bool FindVaryingByMappedName(const nsACString& mappedName,
@ -66,6 +64,8 @@ public:
nsCString* const out_userName,
bool* const out_isArray) const;
void EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const;
bool IsCompiled() const {
return mTranslationSuccessful && mCompilationSuccessful;
}

View File

@ -11,7 +11,6 @@
#include "mozilla/Preferences.h"
#include "MurmurHash3.h"
#include "nsPrintfCString.h"
#include "nsTArray.h"
#include <string>
#include <vector>
#include "WebGLContext.h"
@ -289,64 +288,66 @@ ShaderValidator::CanLinkTo(const ShaderValidator* prev, nsCString* const out_log
}
}
}
const auto& vertVaryings = ShGetVaryings(prev->mHandle);
const auto& fragVaryings = ShGetVaryings(mHandle);
if (!vertVaryings || !fragVaryings) {
nsPrintfCString error("Could not create varying list.");
*out_log = error;
return false;
}
{
const std::vector<sh::Varying>* vertPtr = ShGetVaryings(prev->mHandle);
const std::vector<sh::Varying>* fragPtr = ShGetVaryings(mHandle);
if (!vertPtr || !fragPtr) {
nsPrintfCString error("Could not create varying list.");
*out_log = error;
return false;
}
std::vector<ShVariableInfo> staticUseVaryingList;
nsTArray<ShVariableInfo> staticUseVaryingList;
for (auto itrFrag = fragPtr->begin(); itrFrag != fragPtr->end(); ++itrFrag) {
const ShVariableInfo varInfo = { itrFrag->type,
(int)itrFrag->elementCount() };
for (const auto& fragVarying : *fragVaryings) {
const ShVariableInfo varInfo = { fragVarying.type,
(int)fragVarying.elementCount() };
static const char prefix[] = "gl_";
if (StartsWith(itrFrag->name, prefix)) {
if (itrFrag->staticUse)
staticUseVaryingList.AppendElement(varInfo);
if (StartsWith(fragVarying.name, prefix)) {
if (fragVarying.staticUse) {
staticUseVaryingList.push_back(varInfo);
}
continue;
}
bool definedInVertShader = false;
bool staticVertUse = false;
for (auto itrVert = vertPtr->begin(); itrVert != vertPtr->end(); ++itrVert) {
if (itrVert->name != itrFrag->name)
for (const auto& vertVarying : *vertVaryings) {
if (vertVarying.name != fragVarying.name)
continue;
if (!itrVert->isSameVaryingAtLinkTime(*itrFrag)) {
if (!vertVarying.isSameVaryingAtLinkTime(fragVarying)) {
nsPrintfCString error("Varying `%s`is not linkable between"
" attached shaders.",
itrFrag->name.c_str());
fragVarying.name.c_str());
*out_log = error;
return false;
}
definedInVertShader = true;
staticVertUse = itrVert->staticUse;
staticVertUse = vertVarying.staticUse;
break;
}
if (!definedInVertShader && itrFrag->staticUse) {
if (!definedInVertShader && fragVarying.staticUse) {
nsPrintfCString error("Varying `%s` has static-use in the frag"
" shader, but is undeclared in the vert"
" shader.", itrFrag->name.c_str());
" shader.", fragVarying.name.c_str());
*out_log = error;
return false;
}
if (staticVertUse && itrFrag->staticUse)
staticUseVaryingList.AppendElement(varInfo);
if (staticVertUse && fragVarying.staticUse) {
staticUseVaryingList.push_back(varInfo);
}
}
if (!ShCheckVariablesWithinPackingLimits(mMaxVaryingVectors,
staticUseVaryingList.Elements(),
staticUseVaryingList.Length()))
staticUseVaryingList.data(),
staticUseVaryingList.size()))
{
*out_log = "Statically used varyings do not fit within packing limits. (see"
" GLSL ES Specification 1.0.17, p111)";
@ -354,6 +355,50 @@ ShaderValidator::CanLinkTo(const ShaderValidator* prev, nsCString* const out_log
}
}
{
bool isInvariant_Position = false;
bool isInvariant_PointSize = false;
bool isInvariant_FragCoord = false;
bool isInvariant_PointCoord = false;
for (const auto& varying : *vertVaryings) {
if (varying.name == "gl_Position") {
isInvariant_Position = varying.isInvariant;
} else if (varying.name == "gl_PointSize") {
isInvariant_PointSize = varying.isInvariant;
}
}
for (const auto& varying : *fragVaryings) {
if (varying.name == "gl_FragCoord") {
isInvariant_FragCoord = varying.isInvariant;
} else if (varying.name == "gl_PointCoord") {
isInvariant_PointCoord = varying.isInvariant;
}
}
////
const auto fnCanBuiltInsLink = [](bool vertIsInvariant, bool fragIsInvariant) {
if (vertIsInvariant)
return true;
return !fragIsInvariant;
};
if (!fnCanBuiltInsLink(isInvariant_Position, isInvariant_FragCoord)) {
*out_log = "gl_Position must be invariant if gl_FragCoord is. (see GLSL ES"
" Specification 1.0.17, p39)";
return false;
}
if (!fnCanBuiltInsLink(isInvariant_PointSize, isInvariant_PointCoord)) {
*out_log = "gl_PointSize must be invariant if gl_PointCoord is. (see GLSL ES"
" Specification 1.0.17, p39)";
return false;
}
}
return true;
}
@ -399,21 +444,6 @@ ShaderValidator::FindAttribUserNameByMappedName(const std::string& mappedName,
return false;
}
bool
ShaderValidator::FindActiveOutputMappedNameByUserName(const std::string& userName,
const std::string** const out_mappedName) const
{
const std::vector<sh::OutputVariable>& varibles = *ShGetOutputVariables(mHandle);
for (auto itr = varibles.begin(); itr != varibles.end(); ++itr) {
if (itr->name == userName) {
*out_mappedName = &(itr->mappedName);
return true;
}
}
return false;
}
bool
ShaderValidator::FindAttribMappedNameByUserName(const std::string& userName,
const std::string** const out_mappedName) const
@ -538,5 +568,18 @@ ShaderValidator::FindUniformBlockByMappedName(const std::string& mappedName,
return false;
}
void
ShaderValidator::EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const
{
const auto* fragOutputs = ShGetOutputVariables(mHandle);
if (fragOutputs) {
for (const auto& fragOutput : *fragOutputs) {
out_FragOutputs.insert({nsCString(fragOutput.name.c_str()),
nsCString(fragOutput.mappedName.c_str())});
}
}
}
} // namespace webgl
} // namespace mozilla

View File

@ -48,9 +48,6 @@ public:
bool FindAttribUserNameByMappedName(const std::string& mappedName,
const std::string** const out_userName) const;
bool FindActiveOutputMappedNameByUserName(const std::string& userName,
const std::string** const out_mappedName) const;
bool FindAttribMappedNameByUserName(const std::string& userName,
const std::string** const out_mappedName) const;
@ -66,6 +63,7 @@ public:
bool FindUniformBlockByMappedName(const std::string& mappedName,
std::string* const out_userName) const;
void EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const;
};
} // namespace webgl

View File

@ -123,7 +123,7 @@ function testColorConversions() {
testColorConversion("RGBA32", "GRAY8"),
testColorConversion("RGBA32", "YUV444P"),
testColorConversion("RGBA32", "YUV422P"),
testColorConversion("RGBA32", "YUV420P", 2),
testColorConversion("RGBA32", "YUV420P"),
testColorConversion("RGBA32", "YUV420SP_NV12"),
testColorConversion("RGBA32", "YUV420SP_NV21"),
testColorConversion("RGBA32", "HSV", 0.01),
@ -136,10 +136,10 @@ function testColorConversions() {
testColorConversion("BGRA32", "BGR24"),
testColorConversion("BGRA32", "GRAY8"),
testColorConversion("BGRA32", "YUV444P", 3),
testColorConversion("BGRA32", "YUV422P", 2),
testColorConversion("BGRA32", "YUV420P", 2),
testColorConversion("BGRA32", "YUV420SP_NV12", 2),
testColorConversion("BGRA32", "YUV420SP_NV21", 2),
testColorConversion("BGRA32", "YUV422P"),
testColorConversion("BGRA32", "YUV420P"),
testColorConversion("BGRA32", "YUV420SP_NV12"),
testColorConversion("BGRA32", "YUV420SP_NV21"),
testColorConversion("BGRA32", "HSV", 0.01),
testColorConversion("BGRA32", "Lab", 0.5),
@ -178,7 +178,7 @@ function testColorConversions() {
testColorConversion("YUV444P", "BGR24"),
testColorConversion("YUV444P", "GRAY8"),
testColorConversion("YUV444P", "YUV444P"),
testColorConversion("YUV444P", "YUV422P", 4),
testColorConversion("YUV444P", "YUV422P", 3),
testColorConversion("YUV444P", "YUV420P", 3),
testColorConversion("YUV444P", "YUV420SP_NV12", 3),
testColorConversion("YUV444P", "YUV420SP_NV21", 3),
@ -187,7 +187,7 @@ function testColorConversions() {
// From YUV422P
testColorConversion("YUV422P", "RGBA32"),
testColorConversion("YUV422P", "BGRA32", 2),
testColorConversion("YUV422P", "BGRA32"),
testColorConversion("YUV422P", "RGB24"),
testColorConversion("YUV422P", "BGR24"),
testColorConversion("YUV422P", "GRAY8"),
@ -200,13 +200,13 @@ function testColorConversions() {
testColorConversion("YUV422P", "Lab", 0.01),
// From YUV420P
testColorConversion("YUV420P", "RGBA32", 2),
testColorConversion("YUV420P", "BGRA32", 2),
testColorConversion("YUV420P", "RGBA32"),
testColorConversion("YUV420P", "BGRA32"),
testColorConversion("YUV420P", "RGB24"),
testColorConversion("YUV420P", "BGR24"),
testColorConversion("YUV420P", "GRAY8"),
testColorConversion("YUV420P", "YUV444P", 3),
testColorConversion("YUV420P", "YUV422P", 1),
testColorConversion("YUV420P", "YUV422P"),
testColorConversion("YUV420P", "YUV420P"),
testColorConversion("YUV420P", "YUV420SP_NV12"),
testColorConversion("YUV420P", "YUV420SP_NV21"),
@ -215,12 +215,12 @@ function testColorConversions() {
// From NV12
testColorConversion("YUV420SP_NV12", "RGBA32"),
testColorConversion("YUV420SP_NV12", "BGRA32", 2),
testColorConversion("YUV420SP_NV12", "BGRA32"),
testColorConversion("YUV420SP_NV12", "RGB24"),
testColorConversion("YUV420SP_NV12", "BGR24"),
testColorConversion("YUV420SP_NV12", "GRAY8"),
testColorConversion("YUV420SP_NV12", "YUV444P", 3),
testColorConversion("YUV420SP_NV12", "YUV422P", 1),
testColorConversion("YUV420SP_NV12", "YUV422P"),
testColorConversion("YUV420SP_NV12", "YUV420P"),
testColorConversion("YUV420SP_NV12", "YUV420SP_NV12"),
testColorConversion("YUV420SP_NV12", "YUV420SP_NV21"),
@ -229,12 +229,12 @@ function testColorConversions() {
// From NV21
testColorConversion("YUV420SP_NV21", "RGBA32"),
testColorConversion("YUV420SP_NV21", "BGRA32", 2),
testColorConversion("YUV420SP_NV21", "BGRA32"),
testColorConversion("YUV420SP_NV21", "RGB24"),
testColorConversion("YUV420SP_NV21", "BGR24"),
testColorConversion("YUV420SP_NV21", "GRAY8"),
testColorConversion("YUV420SP_NV21", "YUV444P", 3),
testColorConversion("YUV420SP_NV21", "YUV422P", 1),
testColorConversion("YUV420SP_NV21", "YUV422P"),
testColorConversion("YUV420SP_NV21", "YUV420P"),
testColorConversion("YUV420SP_NV21", "YUV420SP_NV12"),
testColorConversion("YUV420SP_NV21", "YUV420SP_NV21"),

View File

@ -5214,7 +5214,7 @@ skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.
[generated/test_2_conformance__glsl__misc__shaders-with-constant-expression-loop-conditions.html]
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1') || (os == 'win' && os_version == '6.2'))
[generated/test_2_conformance__glsl__misc__shaders-with-invariance.html]
fail-if = (os == 'mac') || (os == 'win')
fail-if = (os == 'mac')
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1') || (os == 'win' && os_version == '6.2'))
[generated/test_2_conformance__glsl__misc__shaders-with-mis-matching-uniforms.html]
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1') || (os == 'win' && os_version == '6.2'))
@ -5991,7 +5991,6 @@ skip-if = (os == 'android')
[generated/test_conformance__context__context-hidden-alpha.html]
[generated/test_conformance__context__context-lost-restored.html]
[generated/test_conformance__context__context-lost.html]
fail-if = 1
[generated/test_conformance__context__context-release-upon-reload.html]
skip-if = (os == 'android')
[generated/test_conformance__context__context-release-with-workers.html]
@ -6349,7 +6348,7 @@ fail-if = (os == 'android')
[generated/test_conformance__glsl__misc__shader-without-precision.frag.html]
[generated/test_conformance__glsl__misc__shaders-with-constant-expression-loop-conditions.html]
[generated/test_conformance__glsl__misc__shaders-with-invariance.html]
fail-if = 1
fail-if = (os == 'mac')
[generated/test_conformance__glsl__misc__shaders-with-mis-matching-uniforms.html]
[generated/test_conformance__glsl__misc__shaders-with-mis-matching-varyings.html]
[generated/test_conformance__glsl__misc__shaders-with-missing-varyings.html]

View File

@ -32,10 +32,6 @@ skip-if = os == 'b2g' || ((os == 'linux') && (buildapp == 'mulet'))
[generated/test_..__always-fail.html]
fail-if = 1
[generated/test_conformance__context__context-lost.html]
fail-if = 1
[generated/test_conformance__glsl__misc__shaders-with-invariance.html]
fail-if = 1
####################
# Tests requesting non-local network connections.
@ -175,8 +171,6 @@ fail-if = (os == 'mac') || (os == 'win')
fail-if = (os == 'mac') || (os == 'win') || (os == 'android') || (os == 'linux')
[generated/test_conformance__buffers__buffer-data-and-buffer-sub-data.html]
fail-if = (os == 'mac') || (os == 'win') || (os == 'android') || (os == 'linux')
[generated/test_2_conformance__glsl__misc__shaders-with-invariance.html]
fail-if = (os == 'mac') || (os == 'win')
[generated/test_2_conformance__textures__misc__tex-sub-image-2d-bad-args.html]
fail-if = (os == 'mac') || (os == 'win')
[generated/test_2_conformance2__misc__expando-loss-2.html]
@ -570,6 +564,10 @@ fail-if = (os == 'mac')
fail-if = (os == 'mac')
[generated/test_2_conformance__rendering__point-size.html]
fail-if = (os == 'mac')
[generated/test_conformance__glsl__misc__shaders-with-invariance.html]
fail-if = (os == 'mac')
[generated/test_2_conformance__glsl__misc__shaders-with-invariance.html]
fail-if = (os == 'mac')
[generated/test_2_conformance2__extensions__ext-color-buffer-float.html]
skip-if = (os == 'mac' && debug)

View File

@ -82,10 +82,62 @@ function getFramebufferAttachmentParameter_bug1267100()
ok(true, 'WebGL test getFramebufferAttachmentParameter');
}
// Test to call getFragDataLocation() when the fragment shader is detatched.
function getFragDataLocation_bug1259702() {
var canvas = document.createElement('canvas');
var gl = canvas.getContext('webgl2');
if (!gl) {
todo(false, 'WebGL2 is not supported');
return;
}
var program = gl.createProgram();
var vertexShaderSrc =
"void main(void) { \
gl_Position = vec4(1.0, 1.0, 1.0, 1.0); \
}";
var fragmentShaderSrc =
"void main(void) { \
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); \
}";
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader, vertexShaderSrc);
gl.compileShader(vertexShader);
gl.attachShader(program, vertexShader);
gl.shaderSource(fragmentShader, fragmentShaderSrc);
gl.compileShader(fragmentShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
var lastError = gl.getProgramInfoLog(program);
ok(false, 'WebGL getFragDataLocation() test, error in linking:' +
lastError);
return;
}
gl.useProgram(program);
gl.detachShader(program, fragmentShader);
// Test the getFragDataLocation() call after detatch the shader.
// This call should not hit crash.
gl.getFragDataLocation(program, "foobar");
ok(true, 'WebGL getFragDataLocation() call after detatch fragment shader');
}
function run() {
webGL2ClearBufferXXX_bug1252414();
framebufferTexture2D_bug1257593();
getFramebufferAttachmentParameter_bug1267100();
getFragDataLocation_bug1259702();
SimpleTest.finish();
}

View File

@ -931,7 +931,7 @@ EventDispatcher::CreateEvent(EventTarget* aOwner,
return PopStateEvent::Constructor(aOwner, EmptyString(), init);
}
if (aEventType.LowerCaseEqualsLiteral("touchevent") &&
TouchEvent::PrefEnabled())
TouchEvent::PrefEnabled(nsContentUtils::GetDocShellForEventTarget(aOwner)))
return NS_NewDOMTouchEvent(aOwner, aPresContext, nullptr);
if (aEventType.LowerCaseEqualsLiteral("hashchangeevent")) {
HashChangeEventInit init;

View File

@ -1154,45 +1154,6 @@ EventListenerManager::GetLegacyEventMessage(EventMessage aEventMessage) const
}
}
nsIDocShell*
EventListenerManager::GetDocShellForTarget()
{
nsCOMPtr<nsINode> node(do_QueryInterface(mTarget));
nsIDocument* doc = nullptr;
nsIDocShell* docShell = nullptr;
if (node) {
doc = node->OwnerDoc();
if (!doc->GetDocShell()) {
bool ignore;
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(doc->GetScriptHandlingObject(ignore));
if (window) {
doc = window->GetExtantDoc();
}
}
} else {
if (nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow()) {
doc = window->GetExtantDoc();
}
}
if (!doc) {
nsCOMPtr<DOMEventTargetHelper> helper(do_QueryInterface(mTarget));
if (helper) {
if (nsPIDOMWindowInner* window = helper->GetOwner()) {
doc = window->GetExtantDoc();
}
}
}
if (doc) {
docShell = doc->GetDocShell();
}
return docShell;
}
/**
* Causes a check for event listeners and processing by them if they exist.
* @param an event listener
@ -1269,7 +1230,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
if (mIsMainThreadELM &&
listener->mListenerType != Listener::eNativeListener) {
docShell = GetDocShellForTarget();
docShell = nsContentUtils::GetDocShellForEventTarget(mTarget);
if (docShell) {
if (timelines && timelines->HasConsumer(docShell)) {
needsEndEventMarker = true;
@ -1733,11 +1694,10 @@ EventListenerManager::IsApzAwareEvent(nsIAtom* aEvent)
// less expecting touch listeners on the page to immediately start preventing
// scrolling without so much as a repaint. Tests that we write can work
// around this constraint easily enough.
if (TouchEvent::PrefEnabled()) {
if (aEvent == nsGkAtoms::ontouchstart ||
aEvent == nsGkAtoms::ontouchmove) {
return true;
}
if (aEvent == nsGkAtoms::ontouchstart ||
aEvent == nsGkAtoms::ontouchmove) {
return TouchEvent::PrefEnabled(
nsContentUtils::GetDocShellForEventTarget(mTarget));
}
return false;
}

View File

@ -467,8 +467,6 @@ protected:
*/
EventMessage GetLegacyEventMessage(EventMessage aEventMessage) const;
nsIDocShell* GetDocShellForTarget();
void ProcessApzAwareEventListenerAdd();
/**

View File

@ -4,12 +4,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/Navigator.h"
#include "mozilla/dom/TouchEvent.h"
#include "mozilla/dom/Touch.h"
#include "mozilla/dom/TouchListBinding.h"
#include "mozilla/Preferences.h"
#include "mozilla/TouchEvents.h"
#include "nsContentUtils.h"
#include "nsIDocShell.h"
#include "mozilla/WidgetUtils.h"
namespace mozilla {
@ -164,39 +166,65 @@ TouchEvent::ChangedTouches()
// static
bool
TouchEvent::PrefEnabled(JSContext* aCx, JSObject* aGlobal)
{
nsIDocShell* docShell = nullptr;
if (aGlobal) {
nsGlobalWindow* win = xpc::WindowOrNull(aGlobal);
if (win) {
docShell = win->GetDocShell();
}
}
return PrefEnabled(docShell);
}
// static
bool
TouchEvent::PrefEnabled(nsIDocShell* aDocShell)
{
static bool sPrefCached = false;
static int32_t sPrefCacheValue = 0;
uint32_t touchEventsOverride = nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE;
if (aDocShell) {
aDocShell->GetTouchEventsOverride(&touchEventsOverride);
}
if (!sPrefCached) {
sPrefCached = true;
Preferences::AddIntVarCache(&sPrefCacheValue, "dom.w3c_touch_events.enabled");
}
bool prefValue = false;
if (sPrefCacheValue == 2) {
#if defined(MOZ_B2G) || defined(MOZ_WIDGET_ANDROID)
// Touch support is always enabled on B2G and android.
prefValue = true;
#elif defined(XP_WIN) || MOZ_WIDGET_GTK == 3
static bool sDidCheckTouchDeviceSupport = false;
static bool sIsTouchDeviceSupportPresent = false;
// On Windows and GTK3 we auto-detect based on device support.
if (!sDidCheckTouchDeviceSupport) {
sDidCheckTouchDeviceSupport = true;
sIsTouchDeviceSupportPresent = WidgetUtils::IsTouchDeviceSupportPresent();
}
prefValue = sIsTouchDeviceSupportPresent;
#else
prefValue = false;
#endif
bool enabled = false;
if (touchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED) {
enabled = true;
} else if (touchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_DISABLED) {
enabled = false;
} else {
prefValue = !!sPrefCacheValue;
if (sPrefCacheValue == 2) {
#if defined(MOZ_B2G) || defined(MOZ_WIDGET_ANDROID)
// Touch support is always enabled on B2G and android.
enabled = true;
#elif defined(XP_WIN) || MOZ_WIDGET_GTK == 3
static bool sDidCheckTouchDeviceSupport = false;
static bool sIsTouchDeviceSupportPresent = false;
// On Windows and GTK3 we auto-detect based on device support.
if (!sDidCheckTouchDeviceSupport) {
sDidCheckTouchDeviceSupport = true;
sIsTouchDeviceSupportPresent = WidgetUtils::IsTouchDeviceSupportPresent();
}
enabled = sIsTouchDeviceSupportPresent;
#else
enabled = false;
#endif
} else {
enabled = !!sPrefCacheValue;
}
}
if (prefValue) {
if (enabled) {
nsContentUtils::InitializeTouchEventTable();
}
return prefValue;
return enabled;
}
// static

View File

@ -52,8 +52,7 @@ public:
return mParent;
}
static bool PrefEnabled(JSContext* aCx = nullptr,
JSObject* aGlobal = nullptr);
static bool PrefEnabled(JSContext* aCx, JSObject* aGlobal);
uint32_t Length() const
{
@ -119,8 +118,8 @@ public:
TouchList* aTargetTouches,
TouchList* aChangedTouches);
static bool PrefEnabled(JSContext* aCx = nullptr,
JSObject* aGlobal = nullptr);
static bool PrefEnabled(JSContext* aCx, JSObject* aGlobal);
static bool PrefEnabled(nsIDocShell* aDocShell);
static already_AddRefed<Event> Constructor(const GlobalObject& aGlobal,
const nsAString& aType,

View File

@ -675,6 +675,13 @@ FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
SetRequestHeaders(httpChannel);
}
nsCOMPtr<nsIHttpChannel> oldHttpChannel = do_QueryInterface(aOldChannel);
nsAutoCString tRPHeaderCValue;
if (oldHttpChannel) {
oldHttpChannel->GetResponseHeader(NS_LITERAL_CSTRING("referrer-policy"),
tRPHeaderCValue);
}
// "HTTP-redirect fetch": step 14 "Append locationURL to request's URL list."
nsCOMPtr<nsIURI> uri;
MOZ_ALWAYS_SUCCEEDS(aNewChannel->GetURI(getter_AddRefs(uri)));
@ -693,6 +700,39 @@ FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
mRequest->AddURL(spec);
NS_ConvertUTF8toUTF16 tRPHeaderValue(tRPHeaderCValue);
// updates requests associated referrer policy according to the
// Referrer-Policy header (if any).
if (!tRPHeaderValue.IsEmpty()) {
net::ReferrerPolicy net_referrerPolicy =
nsContentUtils::GetReferrerPolicyFromHeader(tRPHeaderValue);
if (net_referrerPolicy != net::RP_Unset) {
ReferrerPolicy referrerPolicy = mRequest->ReferrerPolicy_();
switch (net_referrerPolicy) {
case net::RP_No_Referrer:
referrerPolicy = ReferrerPolicy::No_referrer;
break;
case net::RP_No_Referrer_When_Downgrade:
referrerPolicy = ReferrerPolicy::No_referrer_when_downgrade;
break;
case net::RP_Origin:
referrerPolicy = ReferrerPolicy::Origin;
break;
case net::RP_Origin_When_Crossorigin:
referrerPolicy = ReferrerPolicy::Origin_when_cross_origin;
break;
case net::RP_Unsafe_URL:
referrerPolicy = ReferrerPolicy::Unsafe_url;
break;
default:
MOZ_ASSERT_UNREACHABLE("Invalid ReferrerPolicy value");
break;
}
mRequest->SetReferrerPolicy(referrerPolicy);
}
}
aCallback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

View File

@ -29,8 +29,6 @@ InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusTe
already_AddRefed<InternalResponse>
InternalResponse::FromIPC(const IPCInternalResponse& aIPCResponse)
{
MOZ_ASSERT(!aIPCResponse.urlList().IsEmpty());
if (aIPCResponse.type() == ResponseType::Error) {
return InternalResponse::NetworkError();
}
@ -109,7 +107,6 @@ InternalResponse::ToIPC(IPCInternalResponse* aIPCResponse,
UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream)
{
MOZ_ASSERT(aIPCResponse);
MOZ_ASSERT(!mURLList.IsEmpty());
aIPCResponse->type() = mType;
aIPCResponse->urlList() = mURLList;
aIPCResponse->status() = GetUnfilteredStatus();

View File

@ -7034,8 +7034,7 @@ HTMLInputElement::HasPatternMismatch() const
bool
HTMLInputElement::IsRangeOverflow() const
{
// TODO: this is temporary until bug 888324 is fixed.
if (!DoesMinMaxApply() || mType == NS_FORM_INPUT_MONTH) {
if (!DoesMinMaxApply()) {
return false;
}
@ -7055,8 +7054,7 @@ HTMLInputElement::IsRangeOverflow() const
bool
HTMLInputElement::IsRangeUnderflow() const
{
// TODO: this is temporary until bug 888324 is fixed.
if (!DoesMinMaxApply() || mType == NS_FORM_INPUT_MONTH) {
if (!DoesMinMaxApply()) {
return false;
}
@ -7443,8 +7441,8 @@ HTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
DebugOnly<bool> ok = maximum.toString(buf, ArrayLength(buf));
maxStr.AssignASCII(buf);
MOZ_ASSERT(ok, "buf not big enough");
} else if (mType == NS_FORM_INPUT_DATE || mType == NS_FORM_INPUT_TIME) {
msgTemplate = mType == NS_FORM_INPUT_DATE ? kDateOverTemplate : kTimeOverTemplate;
} else if (IsDateTimeInputType(mType)) {
msgTemplate = mType == NS_FORM_INPUT_TIME ? kTimeOverTemplate : kDateOverTemplate;
GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
} else {
msgTemplate = kNumberOverTemplate;
@ -7479,8 +7477,8 @@ HTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
DebugOnly<bool> ok = minimum.toString(buf, ArrayLength(buf));
minStr.AssignASCII(buf);
MOZ_ASSERT(ok, "buf not big enough");
} else if (mType == NS_FORM_INPUT_DATE || mType == NS_FORM_INPUT_TIME) {
msgTemplate = mType == NS_FORM_INPUT_DATE ? kDateUnderTemplate : kTimeUnderTemplate;
} else if (IsDateTimeInputType(mType)) {
msgTemplate = mType == NS_FORM_INPUT_TIME ? kTimeUnderTemplate : kDateUnderTemplate;
GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
} else {
msgTemplate = kNumberUnderTemplate;
@ -8035,8 +8033,7 @@ HTMLInputElement::UpdateHasRange()
mHasRange = false;
// TODO: this is temporary until bug 888324 is fixed.
if (!DoesMinMaxApply() || mType == NS_FORM_INPUT_MONTH) {
if (!DoesMinMaxApply()) {
return;
}

View File

@ -244,10 +244,10 @@ HTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML,
// variation of this code in nsSVGScriptElement - check if changes
// need to be transfered when modifying
void
bool
HTMLScriptElement::GetScriptType(nsAString& type)
{
GetType(type);
return GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
}
void

View File

@ -38,7 +38,7 @@ public:
NS_DECL_NSIDOMHTMLSCRIPTELEMENT
// nsIScriptElement
virtual void GetScriptType(nsAString& type) override;
virtual bool GetScriptType(nsAString& type) override;
virtual void GetScriptText(nsAString& text) override;
virtual void GetScriptCharset(nsAString& charset) override;
virtual void FreezeUriAsyncDefer() override;

View File

@ -224,6 +224,8 @@ TextTrackManager::DidSeek()
void
TextTrackManager::UpdateCueDisplay()
{
mUpdateCueDisplayDispatched = false;
if (!mMediaElement || !mTextTracks) {
return;
}
@ -241,7 +243,7 @@ TextTrackManager::UpdateCueDisplay()
}
nsTArray<RefPtr<TextTrackCue> > activeCues;
mTextTracks->UpdateAndGetShowingCues(activeCues);
mTextTracks->GetShowingCues(activeCues);
if (activeCues.Length() > 0) {
RefPtr<nsVariantCC> jsCues = new nsVariantCC();
@ -250,7 +252,6 @@ TextTrackManager::UpdateCueDisplay()
&NS_GET_IID(nsIDOMEventTarget),
activeCues.Length(),
static_cast<void*>(activeCues.Elements()));
nsPIDOMWindowInner* window = mMediaElement->OwnerDoc()->GetInnerWindow();
if (window) {
sParserWrapper->ProcessCues(window, jsCues, overlay, controls);
@ -277,6 +278,10 @@ TextTrackManager::NotifyCueRemoved(TextTrackCue& aCue)
mNewCues->RemoveCue(aCue);
}
DispatchTimeMarchesOn();
if (aCue.GetActive()) {
// We remove an active cue, need to update the display.
DispatchUpdateCueDisplay();
}
}
void
@ -523,6 +528,16 @@ private:
nsTArray<RefPtr<TextTrack>> mTextTracks;
};
void
TextTrackManager::DispatchUpdateCueDisplay()
{
if (!mUpdateCueDisplayDispatched && !mShutdown &&
(mMediaElement->GetHasUserInteraction() || mMediaElement->IsCurrentlyPlaying())) {
NS_DispatchToMainThread(NewRunnableMethod(this, &TextTrackManager::UpdateCueDisplay));
mUpdateCueDisplayDispatched = true;
}
}
void
TextTrackManager::DispatchTimeMarchesOn()
{

View File

@ -92,6 +92,7 @@ public:
void DispatchTimeMarchesOn();
void TimeMarchesOn();
void DispatchUpdateCueDisplay();
void NotifyShutdown()
{
@ -128,6 +129,7 @@ private:
double mLastTimeMarchesOnCalled;
bool mTimeMarchesOnDispatched;
bool mUpdateCueDisplayDispatched;
static StaticRefPtr<nsIWebVTTParserWrapper> sParserWrapper;

View File

@ -1921,9 +1921,9 @@ nsGenericHTMLElement::SetUndoScopeInternal(bool aUndoScope)
// static
bool
nsGenericHTMLElement::TouchEventsEnabled(JSContext* /* unused */, JSObject* /* unused */)
nsGenericHTMLElement::TouchEventsEnabled(JSContext* aCx, JSObject* aGlobal)
{
return TouchEvent::PrefEnabled();
return TouchEvent::PrefEnabled(aCx, aGlobal);
}
//----------------------------------------------------------------------

View File

@ -29,8 +29,7 @@ var data = [
{ type: 'password', apply: false },
{ type: 'datetime', apply: true, todo: true },
{ type: 'date', apply: true },
// TODO: temporary set to false until bug 888324 is fixed.
{ type: 'month', apply: false },
{ type: 'month', apply: true },
{ type: 'week', apply: true, todo: true },
{ type: 'time', apply: true },
{ type: 'datetime-local', apply: true, todo: true },
@ -71,7 +70,8 @@ function checkValidity(aElement, aValidity, aApply, aRangeApply)
is(aElement.validity.rangeOverflow, !aValidity,
"element overflow status should be " + !aValidity);
var overflowMsg =
(aElement.type == "date" || aElement.type == "time") ?
(aElement.type == "date" || aElement.type == "time" ||
aElement.type == "month") ?
("Please select a value that is no later than " + aElement.max + ".") :
("Please select a value that is no more than " + aElement.max + ".");
is(aElement.validationMessage,
@ -147,7 +147,7 @@ for (var test of data) {
input.max = '10';
break;
case 'month':
// TODO: this is temporary until bug 888324 is fixed.
input.max = '2016-12';
break;
default:
ok(false, 'please, add a case for this new type (' + input.type + ')');
@ -342,6 +342,44 @@ for (var test of data) {
input.max = 'foo';
checkValidity(input, true, apply, false);
break;
case 'month':
input.value = '2016-06';
checkValidity(input, true, apply, apply);
input.value = '2016-12';
checkValidity(input, true, apply, apply);
input.value = 'foo';
checkValidity(input, true, apply, apply);
input.value = '2017-01';
checkValidity(input, false, apply, apply);
input.max = '2017-07';
checkValidity(input, true, apply, apply);
input.value = '2017-12';
checkValidity(input, false, apply, apply);
input.value = '1000-01';
checkValidity(input, true, apply, apply);
input.value = '20160-01';
checkValidity(input, false, apply, apply);
input.max = '0050-01';
checkValidity(input, false, apply, apply);
input.value = '0049-12';
checkValidity(input, true, apply, apply);
input.max = '';
checkValidity(input, true, apply, false);
input.max = 'foo';
checkValidity(input, true, apply, false);
break;
}

View File

@ -29,8 +29,7 @@ var data = [
{ type: 'password', apply: false },
{ type: 'datetime', apply: true, todo: true },
{ type: 'date', apply: true },
// TODO: temporary set to false until bug 888324 is fixed.
{ type: 'month', apply: false },
{ type: 'month', apply: true },
{ type: 'week', apply: true, todo: true },
{ type: 'time', apply: true },
{ type: 'datetime-local', apply: true, todo: true },
@ -71,7 +70,8 @@ function checkValidity(aElement, aValidity, aApply, aRangeApply)
is(aElement.validity.rangeUnderflow, !aValidity,
"element underflow status should be " + !aValidity);
var underflowMsg =
(aElement.type == "date" || aElement.type == "time") ?
(aElement.type == "date" || aElement.type == "time" ||
aElement.type == "month") ?
("Please select a value that is no earlier than " + aElement.min + ".") :
("Please select a value that is no less than " + aElement.min + ".");
is(aElement.validationMessage,
@ -143,7 +143,7 @@ for (var test of data) {
// suffer from overflow.
break;
case 'month':
// TODO: this is temporary until bug 888324 is fixed.
input.min = '2016-06';
break;
default:
ok(false, 'please, add a case for this new type (' + input.type + ')');
@ -340,7 +340,41 @@ for (var test of data) {
checkValidity(input, true, apply, false);
break;
case 'month':
// TODO: this is temporary until bug 888324 is fixed.
input.value = '2016-07';
checkValidity(input, true, apply, apply);
input.value = '2016-06';
checkValidity(input, true, apply, apply);
input.value = 'foo';
checkValidity(input, true, apply, apply);
input.value = '2016-05';
checkValidity(input, false, apply, apply);
input.min = '2016-01';
checkValidity(input, true, apply, apply);
input.value = '2015-12';
checkValidity(input, false, apply, apply);
input.value = '1000-01';
checkValidity(input, false, apply, apply);
input.value = '10000-01';
checkValidity(input, true, apply, apply);
input.min = '0010-01';
checkValidity(input, true, apply, apply);
input.value = '0001-01';
checkValidity(input, false, apply, apply);
input.min = '';
checkValidity(input, true, apply, false);
input.min = 'foo';
checkValidity(input, true, apply, false);
break;
default:
ok(false, 'write tests for ' + input.type);

View File

@ -8995,6 +8995,12 @@ public:
virtual void
ShutdownWorkThreads() override;
virtual void
DidInitialize(QuotaManager* aQuotaManager) override;
virtual void
WillShutdown() override;
private:
~QuotaClient();
@ -9915,7 +9921,7 @@ RecvFlushPendingFileDeletions()
RefPtr<FlushPendingFileDeletionsRunnable> runnable =
new FlushPendingFileDeletionsRunnable();
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable.forget()));
return true;
}
@ -12014,11 +12020,11 @@ ConnectionPool::ShutdownThread(ThreadInfo& aThreadInfo)
runnable->SerialNumber()));
// This should clean up the thread with the profiler.
MOZ_ALWAYS_SUCCEEDS(thread->Dispatch(runnable, NS_DISPATCH_NORMAL));
MOZ_ALWAYS_SUCCEEDS(thread->Dispatch(runnable.forget(),
NS_DISPATCH_NORMAL));
nsCOMPtr<nsIRunnable> shutdownRunnable =
NewRunnableMethod(thread, &nsIThread::Shutdown);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(shutdownRunnable));
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(
NewRunnableMethod(thread, &nsIThread::Shutdown)));
mTotalThreadCount--;
}
@ -12133,7 +12139,7 @@ ConnectionPool::ScheduleTransaction(TransactionInfo* aTransactionInfo,
MOZ_ASSERT(dbInfo->mThreadInfo.mThread);
MOZ_ALWAYS_SUCCEEDS(
dbInfo->mThreadInfo.mThread->Dispatch(runnable,
dbInfo->mThreadInfo.mThread->Dispatch(runnable.forget(),
NS_DISPATCH_NORMAL));
}
}
@ -12191,7 +12197,8 @@ ConnectionPool::ScheduleTransaction(TransactionInfo* aTransactionInfo,
queuedRunnables[index].swap(runnable);
MOZ_ALWAYS_SUCCEEDS(
dbInfo->mThreadInfo.mThread->Dispatch(runnable, NS_DISPATCH_NORMAL));
dbInfo->mThreadInfo.mThread->Dispatch(runnable.forget(),
NS_DISPATCH_NORMAL));
}
queuedRunnables.Clear();
@ -12525,7 +12532,7 @@ ConnectionPool::PerformIdleDatabaseMaintenance(DatabaseInfo* aDatabaseInfo)
mDatabasesPerformingIdleMaintenance.AppendElement(aDatabaseInfo);
MOZ_ALWAYS_SUCCEEDS(
aDatabaseInfo->mThreadInfo.mThread->Dispatch(runnable,
aDatabaseInfo->mThreadInfo.mThread->Dispatch(runnable.forget(),
NS_DISPATCH_NORMAL));
}
@ -12546,7 +12553,7 @@ ConnectionPool::CloseDatabase(DatabaseInfo* aDatabaseInfo)
nsCOMPtr<nsIRunnable> runnable = new CloseConnectionRunnable(aDatabaseInfo);
MOZ_ALWAYS_SUCCEEDS(
aDatabaseInfo->mThreadInfo.mThread->Dispatch(runnable,
aDatabaseInfo->mThreadInfo.mThread->Dispatch(runnable.forget(),
NS_DISPATCH_NORMAL));
}
@ -17413,6 +17420,26 @@ QuotaClient::ShutdownWorkThreads()
}
}
void
QuotaClient::DidInitialize(QuotaManager* aQuotaManager)
{
MOZ_ASSERT(NS_IsMainThread());
if (IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get()) {
mgr->NoteLiveQuotaManager(aQuotaManager);
}
}
void
QuotaClient::WillShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
if (IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get()) {
mgr->NoteShuttingDownQuotaManager();
}
}
nsresult
QuotaClient::GetDirectory(PersistenceType aPersistenceType,
const nsACString& aOrigin, nsIFile** aDirectory)
@ -18583,8 +18610,7 @@ DatabaseMaintenance::RunOnOwningThread()
AssertIsOnBackgroundThread();
if (mCompleteCallback) {
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(mCompleteCallback));
mCompleteCallback = nullptr;
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(mCompleteCallback.forget()));
}
mMaintenance->UnregisterDatabaseMaintenance(this);
@ -19930,14 +19956,12 @@ FactoryOp::Open()
{
// These services have to be started on the main thread currently.
IndexedDatabaseManager* mgr = IndexedDatabaseManager::GetOrCreate();
if (NS_WARN_IF(!mgr)) {
IndexedDatabaseManager* mgr;
if (NS_WARN_IF(!(mgr = IndexedDatabaseManager::GetOrCreate()))) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
mgr->NoteBackgroundThread(mOwningThread);
nsCOMPtr<mozIStorageService> ss;
if (NS_WARN_IF(!(ss = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID)))) {
IDB_REPORT_INTERNAL_ERR();
@ -20143,8 +20167,7 @@ FactoryOp::FinishSendResults()
if (mBlockedDatabaseOpen) {
if (mDelayedOp) {
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(mDelayedOp));
mDelayedOp = nullptr;
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(mDelayedOp.forget()));
}
MOZ_ASSERT(gFactoryOps);
@ -22202,7 +22225,8 @@ DeleteDatabaseOp::DispatchToWorkThread()
MOZ_ASSERT(quotaManager);
nsresult rv =
quotaManager->IOThread()->Dispatch(versionChangeOp, NS_DISPATCH_NORMAL);
quotaManager->IOThread()->Dispatch(versionChangeOp.forget(),
NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;

View File

@ -348,6 +348,10 @@ IndexedDatabaseManager::Init()
mDeleteTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
NS_ENSURE_STATE(mDeleteTimer);
if (QuotaManager* quotaManager = QuotaManager::Get()) {
NoteLiveQuotaManager(quotaManager);
}
}
Preferences::RegisterCallbackAndCall(AtomicBoolPrefChangedCallback,
@ -747,13 +751,24 @@ IndexedDatabaseManager::ClearBackgroundActor()
}
void
IndexedDatabaseManager::NoteBackgroundThread(nsIEventTarget* aBackgroundThread)
IndexedDatabaseManager::NoteLiveQuotaManager(QuotaManager* aQuotaManager)
{
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aBackgroundThread);
MOZ_ASSERT(aQuotaManager);
mBackgroundThread = aBackgroundThread;
mBackgroundThread = aQuotaManager->OwningThread();
}
void
IndexedDatabaseManager::NoteShuttingDownQuotaManager()
{
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_ALWAYS_SUCCEEDS(mDeleteTimer->Cancel());
mBackgroundThread = nullptr;
}
already_AddRefed<FileManager>
@ -852,6 +867,10 @@ IndexedDatabaseManager::AsyncDeleteFile(FileManager* aFileManager,
MOZ_ASSERT(aFileId > 0);
MOZ_ASSERT(mDeleteTimer);
if (!mBackgroundThread) {
return NS_OK;
}
nsresult rv = mDeleteTimer->Cancel();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@ -1043,6 +1062,7 @@ IndexedDatabaseManager::Notify(nsITimer* aTimer)
{
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mBackgroundThread);
for (auto iter = mPendingDeleteInfos.ConstIter(); !iter.Done(); iter.Next()) {
auto key = iter.Key();

View File

@ -28,6 +28,12 @@ namespace dom {
class IDBFactory;
namespace quota {
class QuotaManager;
} // namespace quota
namespace indexedDB {
class BackgroundUtilsChild;
@ -41,6 +47,7 @@ class IndexedDatabaseManager final
, public nsITimerCallback
{
typedef mozilla::dom::quota::PersistenceType PersistenceType;
typedef mozilla::dom::quota::QuotaManager QuotaManager;
typedef mozilla::dom::indexedDB::FileManager FileManager;
typedef mozilla::dom::indexedDB::FileManagerInfo FileManagerInfo;
@ -128,7 +135,10 @@ public:
ClearBackgroundActor();
void
NoteBackgroundThread(nsIEventTarget* aBackgroundThread);
NoteLiveQuotaManager(QuotaManager* aQuotaManager);
void
NoteShuttingDownQuotaManager();
already_AddRefed<FileManager>
GetFileManager(PersistenceType aPersistenceType,

View File

@ -100,10 +100,6 @@ if CONFIG['GNU_CC']:
SOURCES['Key.cpp'].flags += ['-Wno-error=type-limits']
CXXFLAGS += ['-Wno-error=shadow']
if CONFIG['_MSC_VER']:
# This is intended as a temporary hack to support building with VS2015.
CXXFLAGS += ['-wd4577']
LOCAL_INCLUDES += [
'/db/sqlite3/src',
'/dom/base',
@ -113,7 +109,3 @@ LOCAL_INCLUDES += [
'/xpcom/build',
'/xpcom/threads',
]
if CONFIG['ENABLE_INTL_API']:
CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']

View File

@ -148,19 +148,6 @@ static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
static TabChildMap* sTabChildren;
static bool
UsingCompositorLRU()
{
static bool sHavePrefs = false;
static uint32_t sCompositorLRUSize = 0;
if (!sHavePrefs) {
sHavePrefs = true;
Preferences::AddUintVarCache(&sCompositorLRUSize,
"layers.compositor-lru-size", 0);
}
return sCompositorLRUSize != 0;
}
TabChildBase::TabChildBase()
: mTabChildGlobal(nullptr)
{
@ -2872,11 +2859,6 @@ TabChild::NotifyPainted()
void
TabChild::MakeVisible()
{
CompositorBridgeChild* compositor = CompositorBridgeChild::Get();
if (UsingCompositorLRU()) {
compositor->SendNotifyVisible(mLayersId);
}
if (mPuppetWidget) {
mPuppetWidget->Show(true);
}
@ -2886,14 +2868,10 @@ void
TabChild::MakeHidden()
{
CompositorBridgeChild* compositor = CompositorBridgeChild::Get();
if (UsingCompositorLRU()) {
compositor->SendNotifyHidden(mLayersId);
} else {
// Clear cached resources directly. This avoids one extra IPC
// round-trip from CompositorBridgeChild to CompositorBridgeParent when
// CompositorLRU is not used.
compositor->RecvClearCachedResources(mLayersId);
}
// Clear cached resources directly. This avoids one extra IPC
// round-trip from CompositorBridgeChild to CompositorBridgeParent.
compositor->RecvClearCachedResources(mLayersId);
if (mPuppetWidget) {
mPuppetWidget->Show(false);

View File

@ -93,7 +93,6 @@ TextTrack::SetMode(TextTrackMode aValue)
if (mMode != aValue) {
mMode = aValue;
if (aValue == TextTrackMode::Disabled) {
SetCuesInactive();
// Remove all the cues in MediaElement.
if (mTextTrackList) {
HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
@ -103,6 +102,7 @@ TextTrack::SetMode(TextTrackMode aValue)
}
}
}
SetCuesInactive();
} else {
// Add all the cues into MediaElement.
if (mTextTrackList) {

View File

@ -40,19 +40,11 @@ TextTrackList::~TextTrackList()
}
void
TextTrackList::UpdateAndGetShowingCues(nsTArray<RefPtr<TextTrackCue> >& aCues)
TextTrackList::GetShowingCues(nsTArray<RefPtr<TextTrackCue> >& aCues)
{
nsTArray< RefPtr<TextTrackCue> > cues;
for (uint32_t i = 0; i < Length(); i++) {
TextTrackMode mode = mTextTracks[i]->Mode();
// If the mode is hidden then we just need to update the active cue list,
// we don't need to show it on the video.
if (mode == TextTrackMode::Hidden) {
mTextTracks[i]->UpdateActiveCueList();
} else if (mode == TextTrackMode::Showing) {
// If the mode is showing then we need to update the cue list and show it
// on the video. GetActiveCueArray() calls UpdateActiveCueList() so we
// don't need to call it explicitly.
if (mTextTracks[i]->Mode() == TextTrackMode::Showing) {
mTextTracks[i]->GetActiveCueArray(cues);
aCues.AppendElements(cues);
}

View File

@ -37,7 +37,7 @@ public:
}
// Get all the current active cues.
void UpdateAndGetShowingCues(nsTArray<RefPtr<TextTrackCue> >& aCues);
void GetShowingCues(nsTArray<RefPtr<TextTrackCue> >& aCues);
TextTrack* IndexedGetter(uint32_t aIndex, bool& aFound);
TextTrack* operator[](uint32_t aIndex);

View File

@ -23,8 +23,8 @@ using namespace mozilla::media;
namespace mozilla {
extern LogModule* GetDirectShowLog();
#define LOG(...) MOZ_LOG(GetDirectShowLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
static LazyLogModule gDirectShowLog("DirectShowDecoder");
#define LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
AudioSinkFilter::AudioSinkFilter(const wchar_t* aObjectName, HRESULT* aOutResult)
: BaseFilter(aObjectName, CLSID_MozAudioSinkFilter),

View File

@ -15,8 +15,8 @@ using namespace mozilla::media;
namespace mozilla {
extern LogModule* GetDirectShowLog();
#define LOG(...) MOZ_LOG(GetDirectShowLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
static LazyLogModule gDirectShowLog("DirectShowDecoder");
#define LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
AudioSinkInputPin::AudioSinkInputPin(wchar_t* aObjectName,
AudioSinkFilter* aFilter,

View File

@ -6,6 +6,7 @@
#include "DirectShowDecoder.h"
#include "DirectShowReader.h"
#include "DirectShowUtils.h"
#include "MediaDecoderStateMachine.h"
#include "mozilla/Preferences.h"
#include "mozilla/WindowsVersion.h"

View File

@ -17,13 +17,14 @@ using namespace mozilla::media;
namespace mozilla {
LogModule*
GetDirectShowLog() {
static LazyLogModule log("DirectShowDecoder");
return log;
}
// Windows XP's MP3 decoder filter. This is available on XP only, on Vista
// and later we can use the DMO Wrapper filter and MP3 decoder DMO.
const GUID DirectShowReader::CLSID_MPEG_LAYER_3_DECODER_FILTER =
{ 0x38BE3000, 0xDBF4, 0x11D0, {0x86, 0x0E, 0x00, 0xA0, 0x24, 0xCF, 0xEF, 0x6D} };
#define LOG(...) MOZ_LOG(GetDirectShowLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
static LazyLogModule gDirectShowLog("DirectShowDecoder");
#define LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
DirectShowReader::DirectShowReader(AbstractMediaDecoder* aDecoder)
: MediaDecoderReader(aDecoder),
@ -78,11 +79,6 @@ ParseMP3Headers(MP3FrameParser *aParser, MediaResource *aResource)
return aParser->IsMP3() ? NS_OK : NS_ERROR_FAILURE;
}
// Windows XP's MP3 decoder filter. This is available on XP only, on Vista
// and later we can use the DMO Wrapper filter and MP3 decoder DMO.
static const GUID CLSID_MPEG_LAYER_3_DECODER_FILTER =
{ 0x38BE3000, 0xDBF4, 0x11D0, {0x86, 0x0E, 0x00, 0xA0, 0x24, 0xCF, 0xEF, 0x6D} };
nsresult
DirectShowReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)

View File

@ -60,6 +60,8 @@ public:
RefPtr<SeekPromise>
Seek(SeekTarget aTarget, int64_t aEndTime) override;
static const GUID CLSID_MPEG_LAYER_3_DECODER_FILTER;
private:
// Notifies the filter graph that playback is complete. aStatus is
// the code to send to the filter graph. Always returns false, so

View File

@ -287,7 +287,7 @@ CanDecodeMP3UsingDirectShow()
}
// Can we create either the WinXP MP3 decoder filter or the MP3 DMO decoder?
if (FAILED(CoCreateInstance(CLSID_MPEG_LAYER_3_DECODER_FILTER,
if (FAILED(CoCreateInstance(DirectShowReader::CLSID_MPEG_LAYER_3_DECODER_FILTER,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IBaseFilter,

View File

@ -14,8 +14,8 @@ using namespace mozilla::media;
namespace mozilla {
extern LogModule* GetDirectShowLog();
#define LOG(...) MOZ_LOG(GetDirectShowLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
static LazyLogModule gDirectShowLog("DirectShowDecoder");
#define LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
SampleSink::SampleSink()
: mMonitor("SampleSink"),
@ -65,7 +65,7 @@ SampleSink::Receive(IMediaSample* aSample)
mon.Wait();
}
if (MOZ_LOG_TEST(GetDirectShowLog(), LogLevel::Debug)) {
if (MOZ_LOG_TEST(gDirectShowLog, LogLevel::Debug)) {
REFERENCE_TIME start = 0, end = 0;
HRESULT hr = aSample->GetMediaTime(&start, &end);
LOG("SampleSink::Receive() [%4.2lf-%4.2lf]",
@ -102,7 +102,7 @@ SampleSink::Extract(RefPtr<IMediaSample>& aOutSample)
}
aOutSample = mSample;
if (MOZ_LOG_TEST(GetDirectShowLog(), LogLevel::Debug)) {
if (MOZ_LOG_TEST(gDirectShowLog, LogLevel::Debug)) {
int64_t start = 0, end = 0;
mSample->GetMediaTime(&start, &end);
LOG("SampleSink::Extract() [%4.2lf-%4.2lf]",

View File

@ -20,8 +20,8 @@ namespace mozilla {
//#define DEBUG_SOURCE_TRACE 1
#if defined (DEBUG_SOURCE_TRACE)
extern LogModule* GetDirectShowLog();
#define DIRECTSHOW_LOG(...) MOZ_LOG(GetDirectShowLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
static LazyLogModule gDirectShowLog("DirectShowDecoder");
#define DIRECTSHOW_LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
#else
#define DIRECTSHOW_LOG(...)
#endif

View File

@ -13,16 +13,16 @@ EXPORTS += [
]
UNIFIED_SOURCES += [
'AudioSinkInputPin.cpp',
'DirectShowDecoder.cpp',
'DirectShowReader.cpp',
'DirectShowUtils.cpp',
'SampleSink.cpp',
'SourceFilter.cpp',
]
SOURCES += [
'AudioSinkFilter.cpp',
'AudioSinkInputPin.cpp',
'DirectShowReader.cpp',
'SampleSink.cpp',
]
# If WebRTC isn't being built, we need to compile the DirectShow base classes so that

View File

@ -8,91 +8,93 @@
#define CDMProxy_h_
#include "mozilla/CDMCaps.h"
#include "mozilla/Monitor.h"
#include "mozilla/MozPromise.h"
#include "mozilla/dom/MediaKeyMessageEvent.h"
#include "mozilla/dom/MediaKeys.h"
#include "nsIThread.h"
#include "nsString.h"
#include "nsAutoPtr.h"
#include "GMPDecryptorProxy.h"
namespace mozilla {
class MediaRawData;
class GMPCDMCallbackProxy;
namespace dom {
class MediaKeySession;
} // namespace dom
enum DecryptStatus {
Ok = 0,
GenericErr = 1,
NoKeyErr = 2,
AbortedErr = 3,
};
struct DecryptResult {
DecryptResult(GMPErr aStatus, MediaRawData* aSample)
DecryptResult(DecryptStatus aStatus, MediaRawData* aSample)
: mStatus(aStatus)
, mSample(aSample)
{}
GMPErr mStatus;
DecryptStatus mStatus;
RefPtr<MediaRawData> mSample;
};
// Proxies calls GMP/CDM, and proxies calls back.
// Proxies calls CDM, and proxies calls back.
// Note: Promises are passed in via a PromiseId, so that the ID can be
// passed via IPC to the CDM, which can then signal when to reject or
// resolve the promise using its PromiseId.
class CDMProxy {
protected:
typedef dom::PromiseId PromiseId;
typedef dom::SessionType SessionType;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMProxy)
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
typedef MozPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise;
// Main thread only.
CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem);
CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem)
: mKeys(aKeys), mKeySystem(aKeySystem)
{}
// Main thread only.
// Loads the CDM corresponding to mKeySystem.
// Calls MediaKeys::OnCDMCreated() when the CDM is created.
void Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing,
GMPCrashHelper* aHelper);
virtual void Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aName,
bool aInPrivateBrowsing) = 0;
// Main thread only.
// Uses the CDM to create a key session.
// Calls MediaKeys::OnSessionActivated() when session is created.
// Assumes ownership of (Move()s) aInitData's contents.
void CreateSession(uint32_t aCreateSessionToken,
dom::SessionType aSessionType,
PromiseId aPromiseId,
const nsAString& aInitDataType,
nsTArray<uint8_t>& aInitData);
virtual void CreateSession(uint32_t aCreateSessionToken,
dom::SessionType aSessionType,
PromiseId aPromiseId,
const nsAString& aInitDataType,
nsTArray<uint8_t>& aInitData) = 0;
// Main thread only.
// Uses the CDM to load a presistent session stored on disk.
// Calls MediaKeys::OnSessionActivated() when session is loaded.
void LoadSession(PromiseId aPromiseId,
const nsAString& aSessionId);
virtual void LoadSession(PromiseId aPromiseId,
const nsAString& aSessionId) = 0;
// Main thread only.
// Sends a new certificate to the CDM.
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
// processed the request.
// Assumes ownership of (Move()s) aCert's contents.
void SetServerCertificate(PromiseId aPromiseId,
nsTArray<uint8_t>& aCert);
virtual void SetServerCertificate(PromiseId aPromiseId,
nsTArray<uint8_t>& aCert) = 0;
// Main thread only.
// Sends an update to the CDM.
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
// processed the request.
// Assumes ownership of (Move()s) aResponse's contents.
void UpdateSession(const nsAString& aSessionId,
PromiseId aPromiseId,
nsTArray<uint8_t>& aResponse);
virtual void UpdateSession(const nsAString& aSessionId,
PromiseId aPromiseId,
nsTArray<uint8_t>& aResponse) = 0;
// Main thread only.
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
@ -100,200 +102,90 @@ public:
// If processing this operation results in the session actually closing,
// we also call MediaKeySession::OnClosed(), which in turn calls
// MediaKeys::OnSessionClosed().
void CloseSession(const nsAString& aSessionId,
PromiseId aPromiseId);
virtual void CloseSession(const nsAString& aSessionId,
PromiseId aPromiseId) = 0;
// Main thread only.
// Removes all data for a persisent session.
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
// processed the request.
void RemoveSession(const nsAString& aSessionId,
PromiseId aPromiseId);
virtual void RemoveSession(const nsAString& aSessionId,
PromiseId aPromiseId) = 0;
// Main thread only.
void Shutdown();
virtual void Shutdown() = 0;
// Main thread only.
void Terminated();
virtual void Terminated() = 0;
// Threadsafe.
const nsCString& GetNodeId() const;
virtual const nsCString& GetNodeId() const = 0;
// Main thread only.
void OnSetSessionId(uint32_t aCreateSessionToken,
const nsAString& aSessionId);
virtual void OnSetSessionId(uint32_t aCreateSessionToken,
const nsAString& aSessionId) = 0;
// Main thread only.
void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess);
virtual void OnResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess) = 0;
// Main thread only.
void OnSessionMessage(const nsAString& aSessionId,
GMPSessionMessageType aMessageType,
nsTArray<uint8_t>& aMessage);
virtual void OnSessionMessage(const nsAString& aSessionId,
dom::MediaKeyMessageType aMessageType,
nsTArray<uint8_t>& aMessage) = 0;
// Main thread only.
void OnExpirationChange(const nsAString& aSessionId,
GMPTimestamp aExpiryTime);
virtual void OnExpirationChange(const nsAString& aSessionId,
int64_t aExpiryTime) = 0;
// Main thread only.
void OnSessionClosed(const nsAString& aSessionId);
virtual void OnSessionClosed(const nsAString& aSessionId) = 0;
// Main thread only.
void OnSessionError(const nsAString& aSessionId,
nsresult aException,
uint32_t aSystemCode,
const nsAString& aMsg);
virtual void OnSessionError(const nsAString& aSessionId,
nsresult aException,
uint32_t aSystemCode,
const nsAString& aMsg) = 0;
// Main thread only.
void OnRejectPromise(uint32_t aPromiseId,
nsresult aDOMException,
const nsCString& aMsg);
virtual void OnRejectPromise(uint32_t aPromiseId,
nsresult aDOMException,
const nsCString& aMsg) = 0;
RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample);
virtual RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) = 0;
// Owner thread only.
virtual void OnDecrypted(uint32_t aId,
DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData) = 0;
// Reject promise with DOMException corresponding to aExceptionCode.
// Can be called from any thread.
void RejectPromise(PromiseId aId, nsresult aExceptionCode,
const nsCString& aReason);
virtual void RejectPromise(PromiseId aId,
nsresult aExceptionCode,
const nsCString& aReason) = 0;
// Resolves promise with "undefined".
// Can be called from any thread.
void ResolvePromise(PromiseId aId);
virtual void ResolvePromise(PromiseId aId) = 0;
// Threadsafe.
const nsString& KeySystem() const;
virtual const nsString& KeySystem() const = 0;
// GMP thread only.
void gmp_Decrypted(uint32_t aId,
GMPErr aResult,
const nsTArray<uint8_t>& aDecryptedData);
CDMCaps& Capabilites();
virtual CDMCaps& Capabilites() = 0;
// Main thread only.
void OnKeyStatusesChange(const nsAString& aSessionId);
virtual void OnKeyStatusesChange(const nsAString& aSessionId) = 0;
void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
nsTArray<nsCString>& aSessionIds);
virtual void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
nsTArray<nsCString>& aSessionIds) = 0;
#ifdef DEBUG
bool IsOnGMPThread();
virtual bool IsOnOwnerThread() = 0;
#endif
private:
friend class gmp_InitDoneCallback;
friend class gmp_InitGetGMPDecryptorCallback;
struct InitData {
uint32_t mPromiseId;
nsString mOrigin;
nsString mTopLevelOrigin;
nsString mGMPName;
RefPtr<GMPCrashHelper> mCrashHelper;
bool mInPrivateBrowsing;
};
// GMP thread only.
void gmp_Init(nsAutoPtr<InitData>&& aData);
void gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData);
void gmp_InitGetGMPDecryptor(nsresult aResult,
const nsACString& aNodeId,
nsAutoPtr<InitData>&& aData);
// GMP thread only.
void gmp_Shutdown();
// Main thread only.
void OnCDMCreated(uint32_t aPromiseId);
struct CreateSessionData {
dom::SessionType mSessionType;
uint32_t mCreateSessionToken;
PromiseId mPromiseId;
nsCString mInitDataType;
nsTArray<uint8_t> mInitData;
};
// GMP thread only.
void gmp_CreateSession(nsAutoPtr<CreateSessionData> aData);
struct SessionOpData {
PromiseId mPromiseId;
nsCString mSessionId;
};
// GMP thread only.
void gmp_LoadSession(nsAutoPtr<SessionOpData> aData);
struct SetServerCertificateData {
PromiseId mPromiseId;
nsTArray<uint8_t> mCert;
};
// GMP thread only.
void gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData);
struct UpdateSessionData {
PromiseId mPromiseId;
nsCString mSessionId;
nsTArray<uint8_t> mResponse;
};
// GMP thread only.
void gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData);
// GMP thread only.
void gmp_CloseSession(nsAutoPtr<SessionOpData> aData);
// GMP thread only.
void gmp_RemoveSession(nsAutoPtr<SessionOpData> aData);
class DecryptJob {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecryptJob)
explicit DecryptJob(MediaRawData* aSample)
: mId(0)
, mSample(aSample)
{
}
void PostResult(GMPErr aResult, const nsTArray<uint8_t>& aDecryptedData);
void PostResult(GMPErr aResult);
RefPtr<DecryptPromise> Ensure() {
return mPromise.Ensure(__func__);
}
uint32_t mId;
RefPtr<MediaRawData> mSample;
private:
~DecryptJob() {}
MozPromiseHolder<DecryptPromise> mPromise;
};
// GMP thread only.
void gmp_Decrypt(RefPtr<DecryptJob> aJob);
class RejectPromiseTask : public Runnable {
public:
RejectPromiseTask(CDMProxy* aProxy,
PromiseId aId,
nsresult aCode,
const nsCString& aReason)
: mProxy(aProxy)
, mId(aId)
, mCode(aCode)
, mReason(aReason)
{
}
NS_METHOD Run() {
mProxy->RejectPromise(mId, mCode, mReason);
return NS_OK;
}
private:
RefPtr<CDMProxy> mProxy;
PromiseId mId;
nsresult mCode;
nsCString mReason;
};
~CDMProxy();
protected:
virtual ~CDMProxy() {}
// Helper to enforce that a raw pointer is only accessed on the main thread.
template<class Type>
@ -330,30 +222,13 @@ private:
const nsString mKeySystem;
// Gecko Media Plugin thread. All interactions with the out-of-process
// EME plugin must come from this thread.
RefPtr<nsIThread> mGMPThread;
// Onwer specified thread. e.g. Gecko Media Plugin thread.
// All interactions with the out-of-process EME plugin must come from this thread.
RefPtr<nsIThread> mOwnerThread;
nsCString mNodeId;
GMPDecryptorProxy* mCDM;
CDMCaps mCapabilites;
nsAutoPtr<GMPCDMCallbackProxy> mCallback;
// Decryption jobs sent to CDM, awaiting result.
// GMP thread only.
nsTArray<RefPtr<DecryptJob>> mDecryptionJobs;
// Number of buffers we've decrypted. Used to uniquely identify
// decryption jobs sent to CDM. Note we can't just use the length of
// mDecryptionJobs as that shrinks as jobs are completed and removed
// from it.
// GMP thread only.
uint32_t mDecryptionJobCount;
// True if CDMProxy::gmp_Shutdown was called.
// GMP thread only.
bool mShutdownCalled;
};

View File

@ -13,7 +13,7 @@
#include "mozilla/dom/MediaKeySession.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/CDMProxy.h"
#include "GMPCDMProxy.h"
#include "mozilla/EMEUtils.h"
#include "nsContentUtils.h"
#include "nsIScriptObjectPrincipal.h"
@ -313,7 +313,7 @@ MediaKeys::Init(ErrorResult& aRv)
return nullptr;
}
mProxy = new CDMProxy(this, mKeySystem);
mProxy = new GMPCDMProxy(this, mKeySystem, new MediaKeysGMPCrashHelper(this));
// Determine principal (at creation time) of the MediaKeys object.
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(GetParentObject());
@ -387,8 +387,7 @@ MediaKeys::Init(ErrorResult& aRv)
origin,
topLevelOrigin,
KeySystemToGMPName(mKeySystem),
inPrivateBrowsing,
new MediaKeysGMPCrashHelper(this));
inPrivateBrowsing);
return promise.forget();
}

View File

@ -24,7 +24,6 @@ EXPORTS.mozilla += [
UNIFIED_SOURCES += [
'CDMCaps.cpp',
'CDMProxy.cpp',
'DetailedPromise.cpp',
'EMEUtils.cpp',
'MediaEncryptedEvent.cpp',

View File

@ -48,7 +48,7 @@ void
GMPCDMCallbackProxy::SetSessionId(uint32_t aToken,
const nsCString& aSessionId)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
nsCOMPtr<nsIRunnable> task(new SetSessionIdTask(mProxy,
aToken,
@ -81,7 +81,7 @@ void
GMPCDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
nsCOMPtr<nsIRunnable> task(new LoadSessionTask(mProxy,
aPromiseId,
@ -92,7 +92,7 @@ GMPCDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId,
void
GMPCDMCallbackProxy::ResolvePromise(uint32_t aPromiseId)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
// Note: CDMProxy proxies this from non-main threads to main thread.
mProxy->ResolvePromise(aPromiseId);
@ -128,7 +128,7 @@ GMPCDMCallbackProxy::RejectPromise(uint32_t aPromiseId,
nsresult aException,
const nsCString& aMessage)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
nsCOMPtr<nsIRunnable> task;
task = new RejectPromiseTask(mProxy,
@ -138,6 +138,17 @@ GMPCDMCallbackProxy::RejectPromise(uint32_t aPromiseId,
NS_DispatchToMainThread(task);
}
static dom::MediaKeyMessageType
ToMediaKeyMessageType(GMPSessionMessageType aMessageType) {
switch (aMessageType) {
case kGMPLicenseRequest: return dom::MediaKeyMessageType::License_request;
case kGMPLicenseRenewal: return dom::MediaKeyMessageType::License_renewal;
case kGMPLicenseRelease: return dom::MediaKeyMessageType::License_release;
case kGMPIndividualizationRequest: return dom::MediaKeyMessageType::Individualization_request;
default: return dom::MediaKeyMessageType::License_request;
};
};
class SessionMessageTask : public Runnable {
public:
SessionMessageTask(CDMProxy* aProxy,
@ -152,7 +163,7 @@ public:
}
NS_IMETHOD Run() {
mProxy->OnSessionMessage(mSid, mMsgType, mMsg);
mProxy->OnSessionMessage(mSid, ToMediaKeyMessageType(mMsgType), mMsg);
return NS_OK;
}
@ -168,7 +179,7 @@ GMPCDMCallbackProxy::SessionMessage(const nsCString& aSessionId,
GMPSessionMessageType aMessageType,
const nsTArray<uint8_t>& aMessage)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
nsCOMPtr<nsIRunnable> task;
task = new SessionMessageTask(mProxy,
@ -202,7 +213,7 @@ void
GMPCDMCallbackProxy::ExpirationChange(const nsCString& aSessionId,
GMPTimestamp aExpiryTime)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
nsCOMPtr<nsIRunnable> task;
task = new ExpirationChangeTask(mProxy,
@ -214,7 +225,7 @@ GMPCDMCallbackProxy::ExpirationChange(const nsCString& aSessionId,
void
GMPCDMCallbackProxy::SessionClosed(const nsCString& aSessionId)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
bool keyStatusesChange = false;
{
@ -269,7 +280,7 @@ GMPCDMCallbackProxy::SessionError(const nsCString& aSessionId,
uint32_t aSystemCode,
const nsCString& aMessage)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
nsCOMPtr<nsIRunnable> task;
task = new SessionErrorTask(mProxy,
@ -285,7 +296,7 @@ GMPCDMCallbackProxy::KeyStatusChanged(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId,
GMPMediaKeyStatus aStatus)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
bool keyStatusesChange = false;
{
@ -303,20 +314,31 @@ GMPCDMCallbackProxy::KeyStatusChanged(const nsCString& aSessionId,
}
}
DecryptStatus
ToDecryptStatus(GMPErr aError)
{
switch (aError) {
case GMPNoErr: return Ok;
case GMPNoKeyErr: return NoKeyErr;
case GMPAbortedErr: return AbortedErr;
default: return GenericErr;
}
}
void
GMPCDMCallbackProxy::Decrypted(uint32_t aId,
GMPErr aResult,
const nsTArray<uint8_t>& aDecryptedData)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
mProxy->gmp_Decrypted(aId, aResult, aDecryptedData);
mProxy->OnDecrypted(aId, ToDecryptStatus(aResult), aDecryptedData);
}
void
GMPCDMCallbackProxy::Terminated()
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
MOZ_ASSERT(mProxy->IsOnOwnerThread());
nsCOMPtr<nsIRunnable> task = NewRunnableMethod(mProxy, &CDMProxy::Terminated);
NS_DispatchToMainThread(task);
}

View File

@ -56,7 +56,7 @@ public:
~GMPCDMCallbackProxy() {}
private:
friend class CDMProxy;
friend class GMPCDMProxy;
explicit GMPCDMCallbackProxy(CDMProxy* aProxy);
// Warning: Weak ref.

View File

@ -4,70 +4,73 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/CDMProxy.h"
#include "nsString.h"
#include "GMPCDMProxy.h"
#include "mozilla/EMEUtils.h"
#include "mozilla/PodOperations.h"
#include "mozilla/dom/MediaKeys.h"
#include "mozilla/dom/MediaKeySession.h"
#include "mozIGeckoMediaPluginService.h"
#include "nsContentCID.h"
#include "nsServiceManagerUtils.h"
#include "MainThreadUtils.h"
#include "mozilla/EMEUtils.h"
#include "nsIConsoleService.h"
#include "prenv.h"
#include "mozilla/PodOperations.h"
#include "GMPCDMCallbackProxy.h"
#include "MediaData.h"
#include "nsPrintfCString.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "prenv.h"
#include "GMPCDMCallbackProxy.h"
#include "GMPService.h"
#include "MainThreadUtils.h"
#include "MediaData.h"
namespace mozilla {
CDMProxy::CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem)
: mKeys(aKeys)
, mKeySystem(aKeySystem)
GMPCDMProxy::GMPCDMProxy(dom::MediaKeys* aKeys,
const nsAString& aKeySystem,
GMPCrashHelper* aCrashHelper)
: CDMProxy(aKeys, aKeySystem)
, mCrashHelper(aCrashHelper)
, mCDM(nullptr)
, mDecryptionJobCount(0)
, mShutdownCalled(false)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(CDMProxy);
MOZ_COUNT_CTOR(GMPCDMProxy);
}
CDMProxy::~CDMProxy()
GMPCDMProxy::~GMPCDMProxy()
{
MOZ_COUNT_DTOR(CDMProxy);
MOZ_COUNT_DTOR(GMPCDMProxy);
}
void
CDMProxy::Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing,
GMPCrashHelper* aCrashHelper)
GMPCDMProxy::Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
EME_LOG("CDMProxy::Init (%s, %s) %s",
EME_LOG("GMPCDMProxy::Init (%s, %s) %s",
NS_ConvertUTF16toUTF8(aOrigin).get(),
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
(aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));
nsCString pluginVersion;
if (!mGMPThread) {
if (!mOwnerThread) {
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (!mps) {
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Couldn't get MediaPluginService in CDMProxy::Init"));
NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::Init"));
return;
}
mps->GetThread(getter_AddRefs(mGMPThread));
if (!mGMPThread) {
mps->GetThread(getter_AddRefs(mOwnerThread));
if (!mOwnerThread) {
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Couldn't get GMP thread CDMProxy::Init"));
NS_LITERAL_CSTRING("Couldn't get GMP thread GMPCDMProxy::Init"));
return;
}
}
@ -84,32 +87,32 @@ CDMProxy::Init(PromiseId aPromiseId,
data->mTopLevelOrigin = aTopLevelOrigin;
data->mGMPName = aGMPName;
data->mInPrivateBrowsing = aInPrivateBrowsing;
data->mCrashHelper = aCrashHelper;
data->mCrashHelper = mCrashHelper;
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<nsAutoPtr<InitData>>(this,
&CDMProxy::gmp_Init,
&GMPCDMProxy::gmp_Init,
Move(data)));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
#ifdef DEBUG
bool
CDMProxy::IsOnGMPThread()
GMPCDMProxy::IsOnOwnerThread()
{
return NS_GetCurrentThread() == mGMPThread;
return NS_GetCurrentThread() == mOwnerThread;
}
#endif
void
CDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData)
GMPCDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData)
{
EME_LOG("CDMProxy::gmp_InitDone");
EME_LOG("GMPCDMProxy::gmp_InitDone");
if (mShutdownCalled) {
if (aCDM) {
aCDM->Close();
}
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("CDMProxy was shut down before init could complete"));
NS_LITERAL_CSTRING("GMPCDMProxy was shut down before init could complete"));
return;
}
if (!aCDM) {
@ -123,7 +126,7 @@ CDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData)
mCDM->Init(mCallback);
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<uint32_t>(this,
&CDMProxy::OnCDMCreated,
&GMPCDMProxy::OnCDMCreated,
aData->mPromiseId));
NS_DispatchToMainThread(task);
}
@ -131,53 +134,53 @@ CDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData)
class gmp_InitDoneCallback : public GetGMPDecryptorCallback
{
public:
gmp_InitDoneCallback(CDMProxy* aCDMProxy,
nsAutoPtr<CDMProxy::InitData>&& aData)
: mCDMProxy(aCDMProxy),
gmp_InitDoneCallback(GMPCDMProxy* aGMPCDMProxy,
nsAutoPtr<GMPCDMProxy::InitData>&& aData)
: mGMPCDMProxy(aGMPCDMProxy),
mData(Move(aData))
{
}
void Done(GMPDecryptorProxy* aCDM)
{
mCDMProxy->gmp_InitDone(aCDM, Move(mData));
mGMPCDMProxy->gmp_InitDone(aCDM, Move(mData));
}
private:
RefPtr<CDMProxy> mCDMProxy;
nsAutoPtr<CDMProxy::InitData> mData;
RefPtr<GMPCDMProxy> mGMPCDMProxy;
nsAutoPtr<GMPCDMProxy::InitData> mData;
};
class gmp_InitGetGMPDecryptorCallback : public GetNodeIdCallback
{
public:
gmp_InitGetGMPDecryptorCallback(CDMProxy* aCDMProxy,
nsAutoPtr<CDMProxy::InitData>&& aData)
: mCDMProxy(aCDMProxy),
gmp_InitGetGMPDecryptorCallback(GMPCDMProxy* aGMPCDMProxy,
nsAutoPtr<GMPCDMProxy::InitData>&& aData)
: mGMPCDMProxy(aGMPCDMProxy),
mData(aData)
{
}
void Done(nsresult aResult, const nsACString& aNodeId)
{
mCDMProxy->gmp_InitGetGMPDecryptor(aResult, aNodeId, Move(mData));
mGMPCDMProxy->gmp_InitGetGMPDecryptor(aResult, aNodeId, Move(mData));
}
private:
RefPtr<CDMProxy> mCDMProxy;
nsAutoPtr<CDMProxy::InitData> mData;
RefPtr<GMPCDMProxy> mGMPCDMProxy;
nsAutoPtr<GMPCDMProxy::InitData> mData;
};
void
CDMProxy::gmp_Init(nsAutoPtr<InitData>&& aData)
GMPCDMProxy::gmp_Init(nsAutoPtr<InitData>&& aData)
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (!mps) {
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Couldn't get MediaPluginService in CDMProxy::gmp_Init"));
NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_Init"));
return;
}
@ -198,9 +201,9 @@ CDMProxy::gmp_Init(nsAutoPtr<InitData>&& aData)
}
void
CDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
const nsACString& aNodeId,
nsAutoPtr<InitData>&& aData)
GMPCDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
const nsACString& aNodeId,
nsAutoPtr<InitData>&& aData)
{
uint32_t promiseID = aData->mPromiseId;
if (NS_FAILED(aResult)) {
@ -216,11 +219,11 @@ CDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (!mps) {
RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Couldn't get MediaPluginService in CDMProxy::gmp_InitGetGMPDecryptor"));
NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_InitGetGMPDecryptor"));
return;
}
EME_LOG("CDMProxy::gmp_Init (%s, %s) %s NodeId=%s",
EME_LOG("GMPCDMProxy::gmp_Init (%s, %s) %s NodeId=%s",
NS_ConvertUTF16toUTF8(aData->mOrigin).get(),
NS_ConvertUTF16toUTF8(aData->mTopLevelOrigin).get(),
(aData->mInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"),
@ -242,7 +245,7 @@ CDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
}
void
CDMProxy::OnCDMCreated(uint32_t aPromiseId)
GMPCDMProxy::OnCDMCreated(uint32_t aPromiseId)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
@ -259,14 +262,14 @@ CDMProxy::OnCDMCreated(uint32_t aPromiseId)
}
void
CDMProxy::CreateSession(uint32_t aCreateSessionToken,
dom::SessionType aSessionType,
PromiseId aPromiseId,
const nsAString& aInitDataType,
nsTArray<uint8_t>& aInitData)
GMPCDMProxy::CreateSession(uint32_t aCreateSessionToken,
dom::SessionType aSessionType,
PromiseId aPromiseId,
const nsAString& aInitDataType,
nsTArray<uint8_t>& aInitData)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGMPThread);
MOZ_ASSERT(mOwnerThread);
nsAutoPtr<CreateSessionData> data(new CreateSessionData());
data->mSessionType = aSessionType;
@ -276,8 +279,8 @@ CDMProxy::CreateSession(uint32_t aCreateSessionToken,
data->mInitData = Move(aInitData);
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<nsAutoPtr<CreateSessionData>>(this, &CDMProxy::gmp_CreateSession, data));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
NewRunnableMethod<nsAutoPtr<CreateSessionData>>(this, &GMPCDMProxy::gmp_CreateSession, data));
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
GMPSessionType
@ -290,9 +293,9 @@ ToGMPSessionType(dom::SessionType aSessionType) {
};
void
CDMProxy::gmp_CreateSession(nsAutoPtr<CreateSessionData> aData)
GMPCDMProxy::gmp_CreateSession(nsAutoPtr<CreateSessionData> aData)
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
if (!mCDM) {
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Null CDM in gmp_CreateSession"));
@ -306,24 +309,24 @@ CDMProxy::gmp_CreateSession(nsAutoPtr<CreateSessionData> aData)
}
void
CDMProxy::LoadSession(PromiseId aPromiseId,
const nsAString& aSessionId)
GMPCDMProxy::LoadSession(PromiseId aPromiseId,
const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGMPThread);
MOZ_ASSERT(mOwnerThread);
nsAutoPtr<SessionOpData> data(new SessionOpData());
data->mPromiseId = aPromiseId;
data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &CDMProxy::gmp_LoadSession, data));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &GMPCDMProxy::gmp_LoadSession, data));
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
void
CDMProxy::gmp_LoadSession(nsAutoPtr<SessionOpData> aData)
GMPCDMProxy::gmp_LoadSession(nsAutoPtr<SessionOpData> aData)
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
if (!mCDM) {
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
@ -334,24 +337,24 @@ CDMProxy::gmp_LoadSession(nsAutoPtr<SessionOpData> aData)
}
void
CDMProxy::SetServerCertificate(PromiseId aPromiseId,
nsTArray<uint8_t>& aCert)
GMPCDMProxy::SetServerCertificate(PromiseId aPromiseId,
nsTArray<uint8_t>& aCert)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGMPThread);
MOZ_ASSERT(mOwnerThread);
nsAutoPtr<SetServerCertificateData> data(new SetServerCertificateData());
data->mPromiseId = aPromiseId;
data->mCert = Move(aCert);
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<nsAutoPtr<SetServerCertificateData>>(this, &CDMProxy::gmp_SetServerCertificate, data));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
NewRunnableMethod<nsAutoPtr<SetServerCertificateData>>(this, &GMPCDMProxy::gmp_SetServerCertificate, data));
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
void
CDMProxy::gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData)
GMPCDMProxy::gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData)
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
if (!mCDM) {
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Null CDM in gmp_SetServerCertificate"));
@ -361,12 +364,12 @@ CDMProxy::gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData)
}
void
CDMProxy::UpdateSession(const nsAString& aSessionId,
PromiseId aPromiseId,
nsTArray<uint8_t>& aResponse)
GMPCDMProxy::UpdateSession(const nsAString& aSessionId,
PromiseId aPromiseId,
nsTArray<uint8_t>& aResponse)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGMPThread);
MOZ_ASSERT(mOwnerThread);
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
nsAutoPtr<UpdateSessionData> data(new UpdateSessionData());
@ -374,14 +377,14 @@ CDMProxy::UpdateSession(const nsAString& aSessionId,
data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
data->mResponse = Move(aResponse);
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<nsAutoPtr<UpdateSessionData>>(this, &CDMProxy::gmp_UpdateSession, data));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
NewRunnableMethod<nsAutoPtr<UpdateSessionData>>(this, &GMPCDMProxy::gmp_UpdateSession, data));
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
void
CDMProxy::gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData)
GMPCDMProxy::gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData)
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
if (!mCDM) {
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Null CDM in gmp_UpdateSession"));
@ -393,8 +396,8 @@ CDMProxy::gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData)
}
void
CDMProxy::CloseSession(const nsAString& aSessionId,
PromiseId aPromiseId)
GMPCDMProxy::CloseSession(const nsAString& aSessionId,
PromiseId aPromiseId)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
@ -403,14 +406,14 @@ CDMProxy::CloseSession(const nsAString& aSessionId,
data->mPromiseId = aPromiseId;
data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &CDMProxy::gmp_CloseSession, data));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &GMPCDMProxy::gmp_CloseSession, data));
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
void
CDMProxy::gmp_CloseSession(nsAutoPtr<SessionOpData> aData)
GMPCDMProxy::gmp_CloseSession(nsAutoPtr<SessionOpData> aData)
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
if (!mCDM) {
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Null CDM in gmp_CloseSession"));
@ -420,8 +423,8 @@ CDMProxy::gmp_CloseSession(nsAutoPtr<SessionOpData> aData)
}
void
CDMProxy::RemoveSession(const nsAString& aSessionId,
PromiseId aPromiseId)
GMPCDMProxy::RemoveSession(const nsAString& aSessionId,
PromiseId aPromiseId)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
@ -430,14 +433,14 @@ CDMProxy::RemoveSession(const nsAString& aSessionId,
data->mPromiseId = aPromiseId;
data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &CDMProxy::gmp_RemoveSession, data));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &GMPCDMProxy::gmp_RemoveSession, data));
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
void
CDMProxy::gmp_RemoveSession(nsAutoPtr<SessionOpData> aData)
GMPCDMProxy::gmp_RemoveSession(nsAutoPtr<SessionOpData> aData)
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
if (!mCDM) {
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Null CDM in gmp_RemoveSession"));
@ -447,28 +450,28 @@ CDMProxy::gmp_RemoveSession(nsAutoPtr<SessionOpData> aData)
}
void
CDMProxy::Shutdown()
GMPCDMProxy::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread());
mKeys.Clear();
// Note: This may end up being the last owning reference to the CDMProxy.
nsCOMPtr<nsIRunnable> task(NewRunnableMethod(this, &CDMProxy::gmp_Shutdown));
if (mGMPThread) {
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
// Note: This may end up being the last owning reference to the GMPCDMProxy.
nsCOMPtr<nsIRunnable> task(NewRunnableMethod(this, &GMPCDMProxy::gmp_Shutdown));
if (mOwnerThread) {
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
}
void
CDMProxy::gmp_Shutdown()
GMPCDMProxy::gmp_Shutdown()
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
mShutdownCalled = true;
// Abort any pending decrypt jobs, to awaken any clients waiting on a job.
for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
DecryptJob* job = mDecryptionJobs[i];
job->PostResult(GMPAbortedErr);
job->PostResult(AbortedErr);
}
mDecryptionJobs.Clear();
@ -479,8 +482,8 @@ CDMProxy::gmp_Shutdown()
}
void
CDMProxy::RejectPromise(PromiseId aId, nsresult aCode,
const nsCString& aReason)
GMPCDMProxy::RejectPromise(PromiseId aId, nsresult aCode,
const nsCString& aReason)
{
if (NS_IsMainThread()) {
if (!mKeys.IsNull()) {
@ -494,32 +497,32 @@ CDMProxy::RejectPromise(PromiseId aId, nsresult aCode,
}
void
CDMProxy::ResolvePromise(PromiseId aId)
GMPCDMProxy::ResolvePromise(PromiseId aId)
{
if (NS_IsMainThread()) {
if (!mKeys.IsNull()) {
mKeys->ResolvePromise(aId);
} else {
NS_WARNING("CDMProxy unable to resolve promise!");
NS_WARNING("GMPCDMProxy unable to resolve promise!");
}
} else {
nsCOMPtr<nsIRunnable> task;
task = NewRunnableMethod<PromiseId>(this,
&CDMProxy::ResolvePromise,
&GMPCDMProxy::ResolvePromise,
aId);
NS_DispatchToMainThread(task);
}
}
const nsCString&
CDMProxy::GetNodeId() const
GMPCDMProxy::GetNodeId() const
{
return mNodeId;
}
void
CDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
const nsAString& aSessionId)
GMPCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
@ -533,7 +536,7 @@ CDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
}
void
CDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
GMPCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
@ -542,21 +545,10 @@ CDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
mKeys->OnSessionLoaded(aPromiseId, aSuccess);
}
static dom::MediaKeyMessageType
ToMediaKeyMessageType(GMPSessionMessageType aMessageType) {
switch (aMessageType) {
case kGMPLicenseRequest: return dom::MediaKeyMessageType::License_request;
case kGMPLicenseRenewal: return dom::MediaKeyMessageType::License_renewal;
case kGMPLicenseRelease: return dom::MediaKeyMessageType::License_release;
case kGMPIndividualizationRequest: return dom::MediaKeyMessageType::Individualization_request;
default: return dom::MediaKeyMessageType::License_request;
};
};
void
CDMProxy::OnSessionMessage(const nsAString& aSessionId,
GMPSessionMessageType aMessageType,
nsTArray<uint8_t>& aMessage)
GMPCDMProxy::OnSessionMessage(const nsAString& aSessionId,
dom::MediaKeyMessageType aMessageType,
nsTArray<uint8_t>& aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
@ -564,12 +556,12 @@ CDMProxy::OnSessionMessage(const nsAString& aSessionId,
}
RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
if (session) {
session->DispatchKeyMessage(ToMediaKeyMessageType(aMessageType), aMessage);
session->DispatchKeyMessage(aMessageType, aMessage);
}
}
void
CDMProxy::OnKeyStatusesChange(const nsAString& aSessionId)
GMPCDMProxy::OnKeyStatusesChange(const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
@ -582,8 +574,8 @@ CDMProxy::OnKeyStatusesChange(const nsAString& aSessionId)
}
void
CDMProxy::OnExpirationChange(const nsAString& aSessionId,
GMPTimestamp aExpiryTime)
GMPCDMProxy::OnExpirationChange(const nsAString& aSessionId,
GMPTimestamp aExpiryTime)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
@ -596,7 +588,7 @@ CDMProxy::OnExpirationChange(const nsAString& aSessionId,
}
void
CDMProxy::OnSessionClosed(const nsAString& aSessionId)
GMPCDMProxy::OnSessionClosed(const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
@ -608,6 +600,15 @@ CDMProxy::OnSessionClosed(const nsAString& aSessionId)
}
}
void
GMPCDMProxy::OnDecrypted(uint32_t aId,
DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData)
{
MOZ_ASSERT(IsOnOwnerThread());
gmp_Decrypted(aId, aResult, aDecryptedData);
}
static void
LogToConsole(const nsAString& aMsg)
{
@ -622,7 +623,7 @@ LogToConsole(const nsAString& aMsg)
}
void
CDMProxy::OnSessionError(const nsAString& aSessionId,
GMPCDMProxy::OnSessionError(const nsAString& aSessionId,
nsresult aException,
uint32_t aSystemCode,
const nsAString& aMsg)
@ -639,7 +640,7 @@ CDMProxy::OnSessionError(const nsAString& aSessionId,
}
void
CDMProxy::OnRejectPromise(uint32_t aPromiseId,
GMPCDMProxy::OnRejectPromise(uint32_t aPromiseId,
nsresult aDOMException,
const nsCString& aMsg)
{
@ -648,35 +649,35 @@ CDMProxy::OnRejectPromise(uint32_t aPromiseId,
}
const nsString&
CDMProxy::KeySystem() const
GMPCDMProxy::KeySystem() const
{
return mKeySystem;
}
CDMCaps&
CDMProxy::Capabilites() {
GMPCDMProxy::Capabilites() {
return mCapabilites;
}
RefPtr<CDMProxy::DecryptPromise>
CDMProxy::Decrypt(MediaRawData* aSample)
RefPtr<GMPCDMProxy::DecryptPromise>
GMPCDMProxy::Decrypt(MediaRawData* aSample)
{
RefPtr<DecryptJob> job(new DecryptJob(aSample));
RefPtr<DecryptPromise> promise(job->Ensure());
nsCOMPtr<nsIRunnable> task(
NewRunnableMethod<RefPtr<DecryptJob>>(this, &CDMProxy::gmp_Decrypt, job));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
NewRunnableMethod<RefPtr<DecryptJob>>(this, &GMPCDMProxy::gmp_Decrypt, job));
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
return promise;
}
void
CDMProxy::gmp_Decrypt(RefPtr<DecryptJob> aJob)
GMPCDMProxy::gmp_Decrypt(RefPtr<DecryptJob> aJob)
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
if (!mCDM) {
aJob->PostResult(GMPAbortedErr);
aJob->PostResult(AbortedErr);
return;
}
@ -688,11 +689,11 @@ CDMProxy::gmp_Decrypt(RefPtr<DecryptJob> aJob)
}
void
CDMProxy::gmp_Decrypted(uint32_t aId,
GMPErr aResult,
const nsTArray<uint8_t>& aDecryptedData)
GMPCDMProxy::gmp_Decrypted(uint32_t aId,
DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData)
{
MOZ_ASSERT(IsOnGMPThread());
MOZ_ASSERT(IsOnOwnerThread());
#ifdef DEBUG
bool jobIdFound = false;
#endif
@ -714,29 +715,30 @@ CDMProxy::gmp_Decrypted(uint32_t aId,
}
void
CDMProxy::DecryptJob::PostResult(GMPErr aResult)
GMPCDMProxy::DecryptJob::PostResult(DecryptStatus aResult)
{
nsTArray<uint8_t> empty;
PostResult(aResult, empty);
}
void
CDMProxy::DecryptJob::PostResult(GMPErr aResult, const nsTArray<uint8_t>& aDecryptedData)
GMPCDMProxy::DecryptJob::PostResult(DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData)
{
if (aDecryptedData.Length() != mSample->Size()) {
NS_WARNING("CDM returned incorrect number of decrypted bytes");
}
if (GMP_SUCCEEDED(aResult)) {
if (aResult == Ok) {
nsAutoPtr<MediaRawDataWriter> writer(mSample->CreateWriter());
PodCopy(writer->Data(),
aDecryptedData.Elements(),
std::min<size_t>(aDecryptedData.Length(), mSample->Size()));
} else if (aResult == GMPNoKeyErr) {
NS_WARNING("CDM returned GMPNoKeyErr");
} else if (aResult == NoKeyErr) {
NS_WARNING("CDM returned NoKeyErr");
// We still have the encrypted sample, so we can re-enqueue it to be
// decrypted again once the key is usable again.
} else {
nsAutoCString str("CDM returned decode failure GMPErr=");
nsAutoCString str("CDM returned decode failure DecryptStatus=");
str.AppendInt(aResult);
NS_WARNING(str.get());
}
@ -744,15 +746,15 @@ CDMProxy::DecryptJob::PostResult(GMPErr aResult, const nsTArray<uint8_t>& aDecry
}
void
CDMProxy::GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
nsTArray<nsCString>& aSessionIds)
GMPCDMProxy::GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
nsTArray<nsCString>& aSessionIds)
{
CDMCaps::AutoLock caps(Capabilites());
caps.GetSessionIdsForKeyId(aKeyId, aSessionIds);
}
void
CDMProxy::Terminated()
GMPCDMProxy::Terminated()
{
MOZ_ASSERT(NS_IsMainThread());
NS_WARNING("CDM terminated");

258
dom/media/gmp/GMPCDMProxy.h Normal file
View File

@ -0,0 +1,258 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GMPCDMProxy_h_
#define GMPCDMProxy_h_
#include "mozilla/CDMProxy.h"
#include "GMPCDMCallbackProxy.h"
#include "GMPDecryptorProxy.h"
namespace mozilla {
class MediaRawData;
// Implementation of CDMProxy which is based on GMP architecture.
class GMPCDMProxy : public CDMProxy {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPCDMProxy, override)
typedef MozPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise;
GMPCDMProxy(dom::MediaKeys* aKeys,
const nsAString& aKeySystem,
GMPCrashHelper* aCrashHelper);
void Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
bool aInPrivateBrowsing) override;
void CreateSession(uint32_t aCreateSessionToken,
dom::SessionType aSessionType,
PromiseId aPromiseId,
const nsAString& aInitDataType,
nsTArray<uint8_t>& aInitData) override;
void LoadSession(PromiseId aPromiseId,
const nsAString& aSessionId) override;
void SetServerCertificate(PromiseId aPromiseId,
nsTArray<uint8_t>& aCert) override;
void UpdateSession(const nsAString& aSessionId,
PromiseId aPromiseId,
nsTArray<uint8_t>& aResponse) override;
void CloseSession(const nsAString& aSessionId,
PromiseId aPromiseId) override;
void RemoveSession(const nsAString& aSessionId,
PromiseId aPromiseId) override;
void Shutdown() override;
void Terminated() override;
const nsCString& GetNodeId() const override;
void OnSetSessionId(uint32_t aCreateSessionToken,
const nsAString& aSessionId) override;
void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess) override;
void OnSessionMessage(const nsAString& aSessionId,
dom::MediaKeyMessageType aMessageType,
nsTArray<uint8_t>& aMessage) override;
void OnExpirationChange(const nsAString& aSessionId,
GMPTimestamp aExpiryTime) override;
void OnSessionClosed(const nsAString& aSessionId) override;
void OnSessionError(const nsAString& aSessionId,
nsresult aException,
uint32_t aSystemCode,
const nsAString& aMsg) override;
void OnRejectPromise(uint32_t aPromiseId,
nsresult aDOMException,
const nsCString& aMsg) override;
RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) override;
void OnDecrypted(uint32_t aId,
DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData) override;
void RejectPromise(PromiseId aId, nsresult aExceptionCode,
const nsCString& aReason) override;
void ResolvePromise(PromiseId aId) override;
const nsString& KeySystem() const override;
CDMCaps& Capabilites() override;
void OnKeyStatusesChange(const nsAString& aSessionId) override;
void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
nsTArray<nsCString>& aSessionIds) override;
#ifdef DEBUG
bool IsOnOwnerThread() override;
#endif
private:
friend class gmp_InitDoneCallback;
friend class gmp_InitGetGMPDecryptorCallback;
struct InitData {
uint32_t mPromiseId;
nsString mOrigin;
nsString mTopLevelOrigin;
nsString mGMPName;
RefPtr<GMPCrashHelper> mCrashHelper;
bool mInPrivateBrowsing;
};
// GMP thread only.
void gmp_Init(nsAutoPtr<InitData>&& aData);
void gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData);
void gmp_InitGetGMPDecryptor(nsresult aResult,
const nsACString& aNodeId,
nsAutoPtr<InitData>&& aData);
// GMP thread only.
void gmp_Shutdown();
// Main thread only.
void OnCDMCreated(uint32_t aPromiseId);
struct CreateSessionData {
dom::SessionType mSessionType;
uint32_t mCreateSessionToken;
PromiseId mPromiseId;
nsCString mInitDataType;
nsTArray<uint8_t> mInitData;
};
// GMP thread only.
void gmp_CreateSession(nsAutoPtr<CreateSessionData> aData);
struct SessionOpData {
PromiseId mPromiseId;
nsCString mSessionId;
};
// GMP thread only.
void gmp_LoadSession(nsAutoPtr<SessionOpData> aData);
struct SetServerCertificateData {
PromiseId mPromiseId;
nsTArray<uint8_t> mCert;
};
// GMP thread only.
void gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData);
struct UpdateSessionData {
PromiseId mPromiseId;
nsCString mSessionId;
nsTArray<uint8_t> mResponse;
};
// GMP thread only.
void gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData);
// GMP thread only.
void gmp_CloseSession(nsAutoPtr<SessionOpData> aData);
// GMP thread only.
void gmp_RemoveSession(nsAutoPtr<SessionOpData> aData);
class DecryptJob {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecryptJob)
explicit DecryptJob(MediaRawData* aSample)
: mId(0)
, mSample(aSample)
{
}
void PostResult(DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData);
void PostResult(DecryptStatus aResult);
RefPtr<DecryptPromise> Ensure() {
return mPromise.Ensure(__func__);
}
uint32_t mId;
RefPtr<MediaRawData> mSample;
private:
~DecryptJob() {}
MozPromiseHolder<DecryptPromise> mPromise;
};
// GMP thread only.
void gmp_Decrypt(RefPtr<DecryptJob> aJob);
// GMP thread only.
void gmp_Decrypted(uint32_t aId,
DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData);
class RejectPromiseTask : public Runnable {
public:
RejectPromiseTask(GMPCDMProxy* aProxy,
PromiseId aId,
nsresult aCode,
const nsCString& aReason)
: mProxy(aProxy)
, mId(aId)
, mCode(aCode)
, mReason(aReason)
{
}
NS_METHOD Run() {
mProxy->RejectPromise(mId, mCode, mReason);
return NS_OK;
}
private:
RefPtr<GMPCDMProxy> mProxy;
PromiseId mId;
nsresult mCode;
nsCString mReason;
};
~GMPCDMProxy();
GMPCrashHelper* mCrashHelper;
GMPDecryptorProxy* mCDM;
CDMCaps mCapabilites;
nsAutoPtr<GMPCDMCallbackProxy> mCallback;
// Decryption jobs sent to CDM, awaiting result.
// GMP thread only.
nsTArray<RefPtr<DecryptJob>> mDecryptionJobs;
// Number of buffers we've decrypted. Used to uniquely identify
// decryption jobs sent to CDM. Note we can't just use the length of
// mDecryptionJobs as that shrinks as jobs are completed and removed
// from it.
// GMP thread only.
uint32_t mDecryptionJobCount;
// True if GMPCDMProxy::gmp_Shutdown was called.
// GMP thread only.
bool mShutdownCalled;
};
} // namespace mozilla
#endif // GMPCDMProxy_h_

View File

@ -36,6 +36,7 @@ EXPORTS += [
'GMPAudioHost.h',
'GMPCallbackBase.h',
'GMPCDMCallbackProxy.h',
'GMPCDMProxy.h',
'GMPChild.h',
'GMPContentChild.h',
'GMPContentParent.h',
@ -87,6 +88,7 @@ UNIFIED_SOURCES += [
'GMPAudioDecoderParent.cpp',
'GMPAudioHost.cpp',
'GMPCDMCallbackProxy.cpp',
'GMPCDMProxy.cpp',
'GMPChild.cpp',
'GMPContentChild.cpp',
'GMPContentParent.cpp',

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