mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
8428cd56e3
@ -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);
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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
1
aclocal.m4
vendored
@ -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()
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
26
browser/config/tooltool-manifests/linux64/msan.manifest
Normal file
26
browser/config/tooltool-manifests/linux64/msan.manifest
Normal 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
|
||||
}
|
||||
]
|
@ -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">
|
||||
|
@ -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,
|
||||
|
85
build/autoconf/sanitize.m4
Normal file
85
build/autoconf/sanitize.m4
Normal 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)
|
||||
|
||||
])
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
2
config/external/icu/common/moz.build
vendored
2
config/external/icu/common/moz.build
vendored
@ -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')
|
||||
|
89
config/external/icu/common/sources.mozbuild
vendored
89
config/external/icu/common/sources.mozbuild
vendored
@ -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',
|
||||
]
|
||||
|
2
config/external/icu/i18n/moz.build
vendored
2
config/external/icu/i18n/moz.build
vendored
@ -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')
|
||||
|
84
config/external/icu/i18n/sources.mozbuild
vendored
84
config/external/icu/i18n/sources.mozbuild
vendored
@ -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',
|
||||
]
|
||||
|
2
config/external/icu/stubdata/moz.build
vendored
2
config/external/icu/stubdata/moz.build
vendored
@ -10,6 +10,4 @@
|
||||
|
||||
Library('icustubdata')
|
||||
|
||||
LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
|
||||
|
||||
SOURCES += ['/intl/icu/source/stubdata/stubdata.c']
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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),
|
||||
}
|
||||
)
|
||||
);
|
||||
},
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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.");
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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]
|
||||
|
64
docshell/test/browser/browser_tab_touch_events.js
Normal file
64
docshell/test/browser/browser_tab_touch_events.js
Normal 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);
|
||||
});
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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")
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"),
|
||||
|
@ -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]
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -467,8 +467,6 @@ protected:
|
||||
*/
|
||||
EventMessage GetLegacyEventMessage(EventMessage aEventMessage) const;
|
||||
|
||||
nsIDocShell* GetDocShellForTarget();
|
||||
|
||||
void ProcessApzAwareEventListenerAdd();
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 request’s 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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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']
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "DirectShowDecoder.h"
|
||||
#include "DirectShowReader.h"
|
||||
#include "DirectShowUtils.h"
|
||||
#include "MediaDecoderStateMachine.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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]",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ EXPORTS.mozilla += [
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'CDMCaps.cpp',
|
||||
'CDMProxy.cpp',
|
||||
'DetailedPromise.cpp',
|
||||
'EMEUtils.cpp',
|
||||
'MediaEncryptedEvent.cpp',
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
~GMPCDMCallbackProxy() {}
|
||||
|
||||
private:
|
||||
friend class CDMProxy;
|
||||
friend class GMPCDMProxy;
|
||||
explicit GMPCDMCallbackProxy(CDMProxy* aProxy);
|
||||
|
||||
// Warning: Weak ref.
|
||||
|
@ -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
258
dom/media/gmp/GMPCDMProxy.h
Normal 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_
|
@ -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
Loading…
Reference in New Issue
Block a user