mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Merge inbound to m-c. a=merge
This commit is contained in:
commit
2b848889f8
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1166031 - NSS update hit needs-clobber bustage.
|
||||
Bug 1165460 - GCC changes need clobbering.
|
||||
|
@ -30,6 +30,14 @@ NSS_DISABLE_DBM=1
|
||||
MOZ_NO_EV_CERTS=1
|
||||
MOZ_DISABLE_EXPORT_JS=1
|
||||
|
||||
# Bug 1171082 - Broken on Windows B2G Desktop
|
||||
if test "$OS_TARGET" != "WINNT"; then
|
||||
MOZ_WEBSPEECH=1
|
||||
MOZ_WEBSPEECH_MODELS=1
|
||||
MOZ_WEBSPEECH_POCKETSPHINX=1
|
||||
MOZ_WEBSPEECH_TEST_BACKEND=1
|
||||
fi # !WINNT
|
||||
|
||||
if test "$OS_TARGET" = "Android"; then
|
||||
MOZ_CAPTURE=1
|
||||
MOZ_RAW=1
|
||||
|
@ -135,6 +135,9 @@
|
||||
@RESPATH@/run-mozilla.sh
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MOZ_WEBSPEECH_MODELS
|
||||
@BINPATH@/models/
|
||||
#endif
|
||||
|
||||
; [Components]
|
||||
@RESPATH@/components/components.manifest
|
||||
|
@ -60,6 +60,9 @@ if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
RCINCLUDE = 'splash.rc'
|
||||
DEFINES['MOZ_PHOENIX'] = True
|
||||
|
||||
for cdm in CONFIG['MOZ_EME_MODULES']:
|
||||
DEFINES['MOZ_%s_EME' % cdm.upper()] = True
|
||||
|
||||
# Control the default heap size.
|
||||
# This is the heap returned by GetProcessHeap().
|
||||
# As we use the CRT heap, the default size is too large and wastes VM.
|
||||
|
@ -1842,10 +1842,10 @@ pref("ui.key.menuAccessKeyFocuses", true);
|
||||
// Encrypted media extensions.
|
||||
pref("media.eme.enabled", true);
|
||||
pref("media.eme.apiVisible", true);
|
||||
|
||||
#ifdef XP_WIN
|
||||
pref("media.gmp-eme-adobe.enabled", true);
|
||||
pref("browser.eme.ui.enabled", true);
|
||||
|
||||
#ifdef MOZ_ADOBE_EME
|
||||
pref("media.gmp-eme-adobe.enabled", true);
|
||||
#endif
|
||||
|
||||
// Play with different values of the decay time and get telemetry,
|
||||
|
@ -32,5 +32,10 @@ export MOZ_TELEMETRY_REPORTING=1
|
||||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||
ac_add_options --enable-warnings-as-errors
|
||||
|
||||
# Enable Adobe Primetime CDM on 32-bit Windows in Mozilla builds.
|
||||
# Enabled here on the assumption that downstream vendors will not be using
|
||||
# these build configs.
|
||||
ac_add_options --enable-eme=adobe
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
@ -64,7 +64,7 @@ case "$target" in
|
||||
|
||||
kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"`
|
||||
|
||||
for version in $android_gnu_compiler_version 4.8 4.7 4.6 4.4.3; do
|
||||
for version in $android_gnu_compiler_version 4.9 4.8 4.7 4.6 4.4.3; do
|
||||
case "$target_cpu" in
|
||||
arm)
|
||||
target_name=arm-linux-androideabi-$version
|
||||
|
@ -21,7 +21,7 @@
|
||||
namespace mozilla {
|
||||
|
||||
void
|
||||
OriginAttributes::CreateSuffix(nsACString& aStr)
|
||||
OriginAttributes::CreateSuffix(nsACString& aStr) const
|
||||
{
|
||||
aStr.Truncate();
|
||||
MOZ_RELEASE_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||
@ -259,4 +259,29 @@ BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs)
|
||||
return codebase.forget();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
BasePrincipal::IsCodebasePrincipal(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
bool isNullPrincipal = true;
|
||||
nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPrincipal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isNullPrincipal || nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No expanded principals.
|
||||
nsCOMPtr<nsIExpandedPrincipal> expandedPrincipal =
|
||||
do_QueryInterface(aPrincipal);
|
||||
if (expandedPrincipal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
// Serializes non-default values into the suffix format, i.e.
|
||||
// |!key1=value1&key2=value2|. If there are no non-default attributes, this
|
||||
// returns an empty string.
|
||||
void CreateSuffix(nsACString& aStr);
|
||||
void CreateSuffix(nsACString& aStr) const;
|
||||
|
||||
void Serialize(nsIObjectOutputStream* aStream) const;
|
||||
nsresult Deserialize(nsIObjectInputStream* aStream);
|
||||
@ -83,6 +83,8 @@ public:
|
||||
|
||||
virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
|
||||
|
||||
static bool IsCodebasePrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
|
||||
static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs);
|
||||
|
||||
|
6
config/external/moz.build
vendored
6
config/external/moz.build
vendored
@ -40,6 +40,12 @@ if not CONFIG['MOZ_NATIVE_PNG']:
|
||||
if CONFIG['CPU_ARCH'] == 'arm':
|
||||
external_dirs += ['media/openmax_dl']
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH_POCKETSPHINX']:
|
||||
external_dirs += [
|
||||
'media/sphinxbase',
|
||||
'media/pocketsphinx',
|
||||
]
|
||||
|
||||
external_dirs += [
|
||||
'media/kiss_fft',
|
||||
'media/libcubeb',
|
||||
|
84
configure.in
84
configure.in
@ -3879,6 +3879,9 @@ MOZ_OMX_PLUGIN=
|
||||
MOZ_VPX=
|
||||
MOZ_VPX_ERROR_CONCEALMENT=
|
||||
MOZ_WEBSPEECH=1
|
||||
MOZ_WEBSPEECH_MODELS=
|
||||
MOZ_WEBSPEECH_POCKETSPHINX=
|
||||
MOZ_WEBSPEECH_TEST_BACKEND=1
|
||||
VPX_AS=
|
||||
VPX_ASFLAGS=
|
||||
VPX_AS_CONVERSION=
|
||||
@ -5164,6 +5167,34 @@ else
|
||||
AC_SUBST(MOZ_SAMPLE_TYPE_FLOAT32)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable Speech API test backend
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(webspeechtestbackend,
|
||||
[ --disable-webspeechtestbackend Disable support for HTML Speech API Test Backend],
|
||||
MOZ_WEBSPEECH_TEST_BACKEND=,
|
||||
MOZ_WEBSPEECH_TEST_BACKEND=1)
|
||||
|
||||
if test -n "$MOZ_WEBSPEECH_TEST_BACKEND"; then
|
||||
AC_DEFINE(MOZ_WEBSPEECH_TEST_BACKEND)
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_WEBSPEECH_TEST_BACKEND)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable Speech API pocketsphinx backend
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(webspeechpocketsphinx,
|
||||
[ --disable-webspeechpocketsphinx Disable support for HTML Speech API Pocketsphinx Backend],
|
||||
MOZ_WEBSPEECH_POCKETSPHINX=,
|
||||
MOZ_WEBSPEECH_POCKETSPHINX=1)
|
||||
|
||||
if test -n "$MOZ_WEBSPEECH_POCKETSPHINX"; then
|
||||
AC_DEFINE(MOZ_WEBSPEECH_POCKETSPHINX)
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_WEBSPEECH_POCKETSPHINX)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable Speech API code
|
||||
dnl ========================================================
|
||||
@ -5178,6 +5209,20 @@ fi
|
||||
|
||||
AC_SUBST(MOZ_WEBSPEECH)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable Speech API models
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(webspeechmodels,
|
||||
[ --disable-webspeechmodels Disable support for HTML Speech API Models],
|
||||
MOZ_WEBSPEECH_MODELS=,
|
||||
MOZ_WEBSPEECH_MODELS=1)
|
||||
|
||||
if test -n "$MOZ_WEBSPEECH_MODELS"; then
|
||||
AC_DEFINE(MOZ_WEBSPEECH_MODELS)
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_WEBSPEECH_MODELS)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable Raw Codecs
|
||||
dnl ========================================================
|
||||
@ -5340,17 +5385,31 @@ dnl ========================================================
|
||||
dnl = EME support
|
||||
dnl ========================================================
|
||||
|
||||
MOZ_ARG_DISABLE_BOOL(eme,
|
||||
[ --disable-eme Disable support for Encrypted Media Extensions],
|
||||
MOZ_EME=,
|
||||
MOZ_EME=1)
|
||||
MOZ_ARG_ENABLE_STRING(eme,
|
||||
[ --enable-eme[=adobe] Enable support for Encrypted Media Extensions ],
|
||||
MOZ_EME_ARGS=$enableval)
|
||||
|
||||
if test "$MOZ_EME_ARGS"; then
|
||||
if test "$MOZ_EME_ARGS" = "no"; then
|
||||
dnl EME explicitly disabled with --disable-eme
|
||||
MOZ_EME=
|
||||
elif test "$MOZ_EME_ARGS" = "yes"; then
|
||||
dnl EME explicitly enabled with --enable-eme
|
||||
MOZ_EME=1
|
||||
else
|
||||
dnl EME explicitly enabled with --enable-eme=<args>
|
||||
MOZ_EME=1
|
||||
MOZ_EME_MODULES=`echo $MOZ_EME_ARGS | sed -e 's/,/ /g'`
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST_SET(MOZ_EME_MODULES)
|
||||
if test -n "$MOZ_EME"; then
|
||||
if test -z "$MOZ_FMP4"; then
|
||||
AC_MSG_ERROR([Encrypted Media Extension support requires Fragmented MP4 support])
|
||||
fi
|
||||
AC_DEFINE(MOZ_EME)
|
||||
fi;
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable media plugin support
|
||||
@ -7419,17 +7478,6 @@ dnl =
|
||||
dnl ========================================================
|
||||
MOZ_ARG_HEADER(Profiling and Instrumenting)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable runtime visual profiling logger
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(visual-event-tracer,
|
||||
[ --enable-visual-event-tracer Enable visual event tracer instrumentation],
|
||||
MOZ_VISUAL_EVENT_TRACER=1,
|
||||
MOZ_VISUAL_EVENT_TRACER=)
|
||||
if test -n "$MOZ_VISUAL_EVENT_TRACER"; then
|
||||
AC_DEFINE(MOZ_VISUAL_EVENT_TRACER)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable TaskTracer
|
||||
dnl ========================================================
|
||||
@ -8614,7 +8662,9 @@ else
|
||||
# so if the file is named libsomething.so. The lib/ path is also required
|
||||
# because the unpacked file will be under the lib/ subdirectory and will
|
||||
# need to be executed from that path.
|
||||
MOZ_CHILD_PROCESS_NAME="lib/libplugin-container.so"
|
||||
MOZ_CHILD_PROCESS_NAME="libplugin-container.so"
|
||||
MOZ_CHILD_PROCESS_NAME_PIE="libplugin-container-pie.so"
|
||||
AC_SUBST(MOZ_CHILD_PROCESS_NAME_PIE)
|
||||
fi
|
||||
MOZ_CHILD_PROCESS_BUNDLE="plugin-container.app/Contents/MacOS/"
|
||||
|
||||
|
@ -17,13 +17,13 @@
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/dom/workers/ServiceWorkerManager.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StartupTimeline.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/VisualEventTracer.h"
|
||||
#include "URIUtils.h"
|
||||
|
||||
#include "nsIContent.h"
|
||||
@ -52,7 +52,6 @@
|
||||
#include "nsIAuthPrompt2.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsIServiceWorkerManager.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
@ -217,6 +216,7 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using mozilla::dom::workers::ServiceWorkerManager;
|
||||
|
||||
// True means sUseErrorPages has been added to preferences var cache.
|
||||
static bool gAddedPreferencesVarCache = false;
|
||||
@ -7499,8 +7499,6 @@ nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
MOZ_EVENT_TRACER_DONE(this, "docshell::pageload");
|
||||
|
||||
nsCOMPtr<nsIURI> url;
|
||||
nsresult rv = aChannel->GetURI(getter_AddRefs(url));
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -10481,13 +10479,6 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
nsIURI* aBaseURI,
|
||||
nsContentPolicyType aContentPolicyType)
|
||||
{
|
||||
#ifdef MOZ_VISUAL_EVENT_TRACER
|
||||
nsAutoCString urlSpec;
|
||||
aURI->GetAsciiSpec(urlSpec);
|
||||
MOZ_EVENT_TRACER_NAME_OBJECT(this, urlSpec.BeginReading());
|
||||
MOZ_EVENT_TRACER_EXEC(this, "docshell::pageload");
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURILoader> uriLoader;
|
||||
|
||||
@ -14041,13 +14032,15 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = services::GetServiceWorkerManager();
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIsNavigate) {
|
||||
return swm->IsAvailableForURI(aURI, aShouldIntercept);
|
||||
OriginAttributes attrs(GetAppId(), GetIsInBrowserElement());
|
||||
*aShouldIntercept = swm->IsAvailable(attrs, aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
@ -14055,13 +14048,19 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
return swm->IsControlled(doc, aShouldIntercept);
|
||||
ErrorResult rv;
|
||||
*aShouldIntercept = swm->IsControlled(doc, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = services::GetServiceWorkerManager();
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
aChannel->Cancel();
|
||||
return NS_OK;
|
||||
@ -14081,7 +14080,16 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
|
||||
}
|
||||
|
||||
bool isReload = mLoadType & LOAD_CMD_RELOAD;
|
||||
return swm->DispatchFetchEvent(doc, aChannel, isReload);
|
||||
|
||||
OriginAttributes attrs(GetAppId(), GetIsInBrowserElement());
|
||||
|
||||
ErrorResult error;
|
||||
swm->DispatchFetchEvent(attrs, doc, aChannel, isReload, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1336,127 +1336,127 @@ DOMInterfaces = {
|
||||
'headerFile': 'WebGLBuffer.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionCompressedTextureATC': {
|
||||
'WEBGL_compressed_texture_atc': {
|
||||
'nativeType': 'mozilla::WebGLExtensionCompressedTextureATC',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionCompressedTextureETC1': {
|
||||
'WEBGL_compressed_texture_etc1': {
|
||||
'nativeType': 'mozilla::WebGLExtensionCompressedTextureETC1',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionCompressedTexturePVRTC': {
|
||||
'WEBGL_compressed_texture_pvrtc': {
|
||||
'nativeType': 'mozilla::WebGLExtensionCompressedTexturePVRTC',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionCompressedTextureS3TC': {
|
||||
'WEBGL_compressed_texture_s3tc': {
|
||||
'nativeType': 'mozilla::WebGLExtensionCompressedTextureS3TC',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionDepthTexture': {
|
||||
'WEBGL_depth_texture': {
|
||||
'nativeType': 'mozilla::WebGLExtensionDepthTexture',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionDebugRendererInfo': {
|
||||
'WEBGL_debug_renderer_info': {
|
||||
'nativeType': 'mozilla::WebGLExtensionDebugRendererInfo',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionDebugShaders': {
|
||||
'WEBGL_debug_shaders': {
|
||||
'nativeType': 'mozilla::WebGLExtensionDebugShaders',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionElementIndexUint': {
|
||||
'OES_element_index_uint': {
|
||||
'nativeType': 'mozilla::WebGLExtensionElementIndexUint',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionFragDepth': {
|
||||
'EXT_frag_depth': {
|
||||
'nativeType': 'mozilla::WebGLExtensionFragDepth',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionLoseContext': {
|
||||
'WEBGL_lose_context': {
|
||||
'nativeType': 'mozilla::WebGLExtensionLoseContext',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionSRGB': {
|
||||
'EXT_sRGB': {
|
||||
'nativeType': 'mozilla::WebGLExtensionSRGB',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionStandardDerivatives': {
|
||||
'OES_standard_derivatives': {
|
||||
'nativeType': 'mozilla::WebGLExtensionStandardDerivatives',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionShaderTextureLod': {
|
||||
'EXT_shader_texture_lod': {
|
||||
'nativeType': 'mozilla::WebGLExtensionShaderTextureLod',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionTextureFilterAnisotropic': {
|
||||
'EXT_texture_filter_anisotropic': {
|
||||
'nativeType': 'mozilla::WebGLExtensionTextureFilterAnisotropic',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionTextureFloat': {
|
||||
'OES_texture_float': {
|
||||
'nativeType': 'mozilla::WebGLExtensionTextureFloat',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionTextureFloatLinear': {
|
||||
'OES_texture_float_linear': {
|
||||
'nativeType': 'mozilla::WebGLExtensionTextureFloatLinear',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionTextureHalfFloat': {
|
||||
'OES_texture_half_float': {
|
||||
'nativeType': 'mozilla::WebGLExtensionTextureHalfFloat',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionTextureHalfFloatLinear': {
|
||||
'OES_texture_half_float_linear': {
|
||||
'nativeType': 'mozilla::WebGLExtensionTextureHalfFloatLinear',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionColorBufferFloat': {
|
||||
'WEBGL_color_buffer_float': {
|
||||
'nativeType': 'mozilla::WebGLExtensionColorBufferFloat',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionColorBufferHalfFloat': {
|
||||
'EXT_color_buffer_half_float': {
|
||||
'nativeType': 'mozilla::WebGLExtensionColorBufferHalfFloat',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionDrawBuffers': {
|
||||
'WEBGL_draw_buffers': {
|
||||
'nativeType': 'mozilla::WebGLExtensionDrawBuffers',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionVertexArray': {
|
||||
'OES_vertex_array_object': {
|
||||
'nativeType': 'mozilla::WebGLExtensionVertexArray',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionInstancedArrays': {
|
||||
'ANGLE_instanced_arrays': {
|
||||
'nativeType': 'mozilla::WebGLExtensionInstancedArrays',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionBlendMinMax': {
|
||||
'EXT_blend_minmax': {
|
||||
'nativeType': 'mozilla::WebGLExtensionBlendMinMax',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionDisjointTimerQuery': {
|
||||
'EXT_disjoint_timer_query': {
|
||||
'nativeType': 'mozilla::WebGLExtensionDisjointTimerQuery',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
@ -1519,7 +1519,7 @@ DOMInterfaces = {
|
||||
'headerFile': 'WebGLTexture.h'
|
||||
},
|
||||
|
||||
'WebGLTimerQuery': {
|
||||
'WebGLTimerQueryEXT': {
|
||||
'nativeType': 'mozilla::WebGLTimerQuery',
|
||||
'headerFile': 'WebGLTimerQuery.h'
|
||||
},
|
||||
@ -1534,7 +1534,7 @@ DOMInterfaces = {
|
||||
'headerFile': 'WebGLUniformLocation.h'
|
||||
},
|
||||
|
||||
'WebGLVertexArray': {
|
||||
'WebGLVertexArrayObjectOES': {
|
||||
'nativeType': 'mozilla::WebGLVertexArray',
|
||||
'headerFile': 'WebGLVertexArray.h'
|
||||
},
|
||||
|
@ -11157,12 +11157,13 @@ def memberProperties(m, descriptor):
|
||||
props.isJsonifier = True
|
||||
elif (not m.isIdentifierLess() or m == descriptor.operations['Stringifier']):
|
||||
if not m.isStatic() and descriptor.interface.hasInterfacePrototypeObject():
|
||||
if m.returnsPromise() and descriptor.needsSpecialGenericOps():
|
||||
props.isPromiseReturningMethod = True
|
||||
if descriptor.needsSpecialGenericOps():
|
||||
if m.returnsPromise():
|
||||
props.isPromiseReturningMethod = True
|
||||
else:
|
||||
props.isGenericMethod = True
|
||||
if m.getExtendedAttribute("CrossOriginCallable"):
|
||||
props.isCrossOriginMethod = True
|
||||
elif descriptor.needsSpecialGenericOps():
|
||||
props.isGenericMethod = True
|
||||
elif m.isAttr():
|
||||
if not m.isStatic() and descriptor.interface.hasInterfacePrototypeObject():
|
||||
if m.hasLenientThis():
|
||||
|
@ -1779,7 +1779,7 @@ WebGLContext::GetSurfaceSnapshot(bool* out_premultAlpha)
|
||||
if (!srcPremultAlpha) {
|
||||
if (out_premultAlpha) {
|
||||
*out_premultAlpha = false;
|
||||
} else {
|
||||
} else if(hasAlpha) {
|
||||
gfxUtils::PremultiplyDataSurface(surf, surf);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,6 @@ WebGLExtensionBlendMinMax::IsSupported(const WebGLContext* webgl)
|
||||
return webgl->GL()->IsSupported(gl::GLFeature::blend_minmax);
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionBlendMinMax)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionBlendMinMax, EXT_blend_minmax)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -32,6 +32,6 @@ WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* webgl)
|
||||
gl->IsANGLE();
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferFloat)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferFloat, WEBGL_color_buffer_float)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -30,6 +30,6 @@ WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* webgl)
|
||||
gl->IsANGLE();
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat, EXT_color_buffer_half_float)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -21,6 +21,6 @@ WebGLExtensionCompressedTextureATC::~WebGLExtensionCompressedTextureATC()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureATC)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureATC, WEBGL_compressed_texture_atc)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,6 @@ WebGLExtensionCompressedTextureETC1::~WebGLExtensionCompressedTextureETC1()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureETC1)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureETC1, WEBGL_compressed_texture_etc1)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -22,6 +22,6 @@ WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTexturePVRTC)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTexturePVRTC, WEBGL_compressed_texture_pvrtc)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -22,6 +22,6 @@ WebGLExtensionCompressedTextureS3TC::~WebGLExtensionCompressedTextureS3TC()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureS3TC)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureS3TC, WEBGL_compressed_texture_s3tc)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,6 @@ WebGLExtensionDebugRendererInfo::~WebGLExtensionDebugRendererInfo()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugRendererInfo)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugRendererInfo, WEBGL_debug_renderer_info)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -38,6 +38,6 @@ WebGLExtensionDebugShaders::GetTranslatedShaderSource(WebGLShader* shader,
|
||||
mContext->GetShaderTranslatedSource(shader, retval);
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugShaders)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugShaders, WEBGL_debug_shaders)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,6 @@ WebGLExtensionDepthTexture::~WebGLExtensionDepthTexture()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDepthTexture)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDepthTexture, WEBGL_depth_texture)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -242,6 +242,6 @@ WebGLExtensionDisjointTimerQuery::IsSupported(const WebGLContext* webgl)
|
||||
}
|
||||
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDisjointTimerQuery)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDisjointTimerQuery, EXT_disjoint_timer_query)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -83,6 +83,6 @@ WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* webgl)
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDrawBuffers)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDrawBuffers, WEBGL_draw_buffers)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,6 @@ WebGLExtensionElementIndexUint::~WebGLExtensionElementIndexUint()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionElementIndexUint)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionElementIndexUint, OES_element_index_uint)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -29,6 +29,6 @@ WebGLExtensionFragDepth::IsSupported(const WebGLContext* webgl)
|
||||
}
|
||||
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFragDepth)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFragDepth, EXT_frag_depth)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -73,6 +73,6 @@ WebGLExtensionInstancedArrays::IsSupported(const WebGLContext* webgl)
|
||||
gl->IsSupported(gl::GLFeature::instanced_arrays);
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionInstancedArrays)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionInstancedArrays, ANGLE_instanced_arrays)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -31,6 +31,6 @@ WebGLExtensionLoseContext::RestoreContext()
|
||||
mContext->RestoreContext();
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext, WEBGL_lose_context)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -39,6 +39,6 @@ WebGLExtensionSRGB::IsSupported(const WebGLContext* webgl)
|
||||
}
|
||||
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionSRGB)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionSRGB, EXT_sRGB)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,6 @@ WebGLExtensionShaderTextureLod::~WebGLExtensionShaderTextureLod()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionShaderTextureLod)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionShaderTextureLod, EXT_shader_texture_lod)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,6 @@ WebGLExtensionStandardDerivatives::~WebGLExtensionStandardDerivatives()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionStandardDerivatives)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionStandardDerivatives, OES_standard_derivatives)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,6 @@ WebGLExtensionTextureFilterAnisotropic::~WebGLExtensionTextureFilterAnisotropic(
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFilterAnisotropic)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFilterAnisotropic, EXT_texture_filter_anisotropic)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -18,6 +18,6 @@ WebGLExtensionTextureFloat::~WebGLExtensionTextureFloat()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloat)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloat, OES_texture_float)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -18,6 +18,6 @@ WebGLExtensionTextureFloatLinear::~WebGLExtensionTextureFloatLinear()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloatLinear)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloatLinear, OES_texture_float_linear)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -18,6 +18,6 @@ WebGLExtensionTextureHalfFloat::~WebGLExtensionTextureHalfFloat()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat, OES_texture_half_float)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -18,6 +18,6 @@ WebGLExtensionTextureHalfFloatLinear::~WebGLExtensionTextureHalfFloatLinear()
|
||||
{
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloatLinear)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloatLinear, OES_texture_half_float_linear)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -70,6 +70,6 @@ WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array)
|
||||
mContext->BindVertexArray(array);
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionVertexArray)
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionVertexArray, OES_vertex_array_object)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -45,10 +45,10 @@ protected:
|
||||
#define DECL_WEBGL_EXTENSION_GOOP \
|
||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
#define IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionType) \
|
||||
#define IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionType, WebGLBindingType)\
|
||||
JSObject* \
|
||||
WebGLExtensionType::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) { \
|
||||
return dom::WebGLExtensionType##Binding::Wrap(cx, this, aGivenProto); \
|
||||
return dom::WebGLBindingType##Binding::Wrap(cx, this, aGivenProto); \
|
||||
}
|
||||
|
||||
class WebGLExtensionCompressedTextureATC
|
||||
|
@ -140,6 +140,8 @@ WebGLShader::WebGLShader(WebGLContext* webgl, GLenum type)
|
||||
: WebGLContextBoundObject(webgl)
|
||||
, mGLName(CreateShader(webgl->GL(), type))
|
||||
, mType(type)
|
||||
, mTranslationSuccessful(false)
|
||||
, mCompilationSuccessful(false)
|
||||
{
|
||||
mContext->mShaders.insertBack(this);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace mozilla {
|
||||
JSObject*
|
||||
WebGLTimerQuery::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return dom::WebGLTimerQueryBinding::Wrap(cx, this, aGivenProto);
|
||||
return dom::WebGLTimerQueryEXTBinding::Wrap(cx, this, aGivenProto);
|
||||
}
|
||||
|
||||
WebGLTimerQuery::WebGLTimerQuery(WebGLContext* webgl, GLuint aName)
|
||||
|
@ -17,7 +17,7 @@ namespace mozilla {
|
||||
JSObject*
|
||||
WebGLVertexArray::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return dom::WebGLVertexArrayBinding::Wrap(cx, this, aGivenProto);
|
||||
return dom::WebGLVertexArrayObjectOESBinding::Wrap(cx, this, aGivenProto);
|
||||
}
|
||||
|
||||
WebGLVertexArray::WebGLVertexArray(WebGLContext* webgl)
|
||||
|
@ -14,7 +14,7 @@ load 746813-1.html
|
||||
load 743499-negative-size.html
|
||||
skip-if(Android) load 767337-1.html
|
||||
skip-if(Android||B2G) load 780392-1.html # bug 833371 for B2G
|
||||
skip-if(Android||B2G) skip-if(gtk2Widget&&isDebugBuild) load 789933-1.html # bug 833371 for B2G, bug 1155252 for linux
|
||||
skip-if(Android||B2G) skip-if(gtkWidget&&isDebugBuild) load 789933-1.html # bug 833371 for B2G, bug 1155252 for linux
|
||||
load 794463-1.html
|
||||
load 802926-1.html
|
||||
load 896047-1.html
|
||||
|
@ -23,7 +23,7 @@ pref(webgl.force-layers-readback,true) == webgl-clear-test.html?readback wrappe
|
||||
# failures encountered when running on Try, and then targetting the Try config by
|
||||
# differences in the `sandbox` contents. That is, I'm labeling based on symptoms rather
|
||||
# than cause.
|
||||
# Lin-R-e10s: gtk2Widget && browserIsRemote
|
||||
# Lin-R-e10s: gtkWidget && browserIsRemote
|
||||
# WinXP-R: winWidget && layersGPUAccelerated && !d2d
|
||||
# Win7+-R: winWidget && layersGPUAccelerated && d2d
|
||||
# Win7+-Ru: winWidget && !layersGPUAccelerated
|
||||
@ -47,10 +47,10 @@ pref(webgl.force-layers-readback,true) == webgl-clear-test.html?readback wrappe
|
||||
== webgl-color-test.html?frame=1&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
== webgl-color-test.html?frame=1&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
== webgl-color-test.html?frame=1&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=1&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=1&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=1&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=1&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=1&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=1&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=1&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=1&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
== webgl-color-test.html?frame=1&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
== webgl-color-test.html?frame=1&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
== webgl-color-test.html?frame=1&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
@ -64,10 +64,10 @@ fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersG
|
||||
== webgl-color-test.html?frame=6&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
== webgl-color-test.html?frame=6&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
== webgl-color-test.html?frame=6&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=6&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=6&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=6&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&(!layersGPUAccelerated||!d2d)) == webgl-color-test.html?frame=6&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=6&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=6&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) == webgl-color-test.html?frame=6&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&(!layersGPUAccelerated||!d2d)) == webgl-color-test.html?frame=6&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
== webgl-color-test.html?frame=6&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
== webgl-color-test.html?frame=6&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
== webgl-color-test.html?frame=6&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
@ -81,10 +81,10 @@ fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&(!layer
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
@ -98,10 +98,10 @@ fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersG
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtk2Widget&&browserIsRemote) fails-if(winWidget&&(!layersGPUAccelerated||!d2d)) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&layersGPUAccelerated&&!d2d) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(gtkWidget&&browserIsRemote) fails-if(winWidget&&(!layersGPUAccelerated||!d2d)) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
|
@ -20,7 +20,7 @@ interface nsIServiceWorkerUnregisterCallback : nsISupports
|
||||
void unregisterFailed();
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(8ce0d197-5740-4ddf-aa4a-e5a63e611d03)]
|
||||
[scriptable, builtinclass, uuid(103763c8-53ba-42e4-8b26-e601d5bc4afe)]
|
||||
interface nsIServiceWorkerInfo : nsISupports
|
||||
{
|
||||
readonly attribute nsIPrincipal principal;
|
||||
@ -33,7 +33,7 @@ interface nsIServiceWorkerInfo : nsISupports
|
||||
readonly attribute DOMString waitingCacheName;
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(384c9aec-29e5-4bdb-abc2-fba10da83e17)]
|
||||
[scriptable, builtinclass, uuid(d130fcbd-1afe-4dd9-b70d-08a4b2373af5)]
|
||||
interface nsIServiceWorkerManager : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -66,16 +66,6 @@ interface nsIServiceWorkerManager : nsISupports
|
||||
// Remove ready pending Promise
|
||||
void removeReadyPromise(in nsIDOMWindow aWindow);
|
||||
|
||||
// Returns true if a ServiceWorker is available for the scope of aURI.
|
||||
bool isAvailableForURI(in nsIURI aURI);
|
||||
|
||||
// Returns true if a given document is currently controlled by a ServiceWorker
|
||||
bool isControlled(in nsIDocument aDocument);
|
||||
|
||||
// Cause a fetch event to be dispatched to the worker global associated with the given document.
|
||||
void dispatchFetchEvent(in nsIDocument aDoc, in nsIInterceptedChannel aChannel,
|
||||
in boolean aIsReload);
|
||||
|
||||
/**
|
||||
* Call this to request that document `aDoc` be controlled by a ServiceWorker
|
||||
* if a registration exists for it's scope.
|
||||
@ -108,8 +98,10 @@ interface nsIServiceWorkerManager : nsISupports
|
||||
|
||||
/*
|
||||
* This implements the soft update algorithm.
|
||||
* XXXbaku this can be removed when bug 1155153 lands.
|
||||
*/
|
||||
void softUpdate(in DOMString aScope);
|
||||
[implicit_jscontext] void softUpdate(in jsval aOriginAttributes,
|
||||
in DOMString aScope);
|
||||
|
||||
/*
|
||||
* Clears ServiceWorker registrations from memory and disk for the specified
|
||||
@ -128,14 +120,17 @@ interface nsIServiceWorkerManager : nsISupports
|
||||
void removeAll();
|
||||
|
||||
// Testing
|
||||
DOMString getScopeForUrl(in DOMString path);
|
||||
DOMString getScopeForUrl(in nsIPrincipal aPrincipal, in DOMString aPath);
|
||||
|
||||
// This is meant to be used only by about:serviceworkers. It returns an array
|
||||
// of nsIServiceWorkerInfo.
|
||||
nsIArray getAllRegistrations();
|
||||
|
||||
void sendPushEvent(in ACString scope, in DOMString data);
|
||||
void sendPushSubscriptionChangeEvent(in ACString scope);
|
||||
[implicit_jscontext] void sendPushEvent(in jsval aOriginAttributes,
|
||||
in ACString aScope,
|
||||
in DOMString aData);
|
||||
[implicit_jscontext] void sendPushSubscriptionChangeEvent(in jsval aOriginAttributes,
|
||||
in ACString scope);
|
||||
|
||||
void updateAllRegistrations();
|
||||
};
|
||||
|
@ -768,7 +768,7 @@ void
|
||||
MediaCodecReader::TextureClientRecycleCallback(TextureClient* aClient)
|
||||
{
|
||||
MOZ_ASSERT(aClient, "aClient should not be nullptr in RecycleCallback()");
|
||||
|
||||
MOZ_ASSERT(!aClient->IsDead());
|
||||
size_t index = 0;
|
||||
|
||||
{
|
||||
|
@ -915,6 +915,7 @@ void OmxDecoder::RecycleCallbackImp(TextureClient* aClient)
|
||||
/* static */ void
|
||||
OmxDecoder::RecycleCallback(TextureClient* aClient, void* aClosure)
|
||||
{
|
||||
MOZ_ASSERT(aClient && !aClient->IsDead());
|
||||
OmxDecoder* decoder = static_cast<OmxDecoder*>(aClosure);
|
||||
decoder->RecycleCallbackImp(aClient);
|
||||
}
|
||||
|
@ -569,6 +569,7 @@ GonkVideoDecoderManager::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight
|
||||
void
|
||||
GonkVideoDecoderManager::RecycleCallback(TextureClient* aClient, void* aClosure)
|
||||
{
|
||||
MOZ_ASSERT(aClient && !aClient->IsDead());
|
||||
GonkVideoDecoderManager* videoManager = static_cast<GonkVideoDecoderManager*>(aClosure);
|
||||
GrallocTextureClientOGL* client = static_cast<GrallocTextureClientOGL*>(aClient);
|
||||
aClient->ClearRecycleCallback();
|
||||
|
@ -170,6 +170,11 @@ IntelWebMVideoDecoder::Demux(nsRefPtr<VP8Sample>& aSample, bool* aEOS)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
NS_WARNING("Packet contains more than one video frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t tstamp = holder->Timestamp();
|
||||
|
||||
// The end time of this frame is the start time of the next frame. Fetch
|
||||
@ -187,34 +192,32 @@ IntelWebMVideoDecoder::Demux(nsRefPtr<VP8Sample>& aSample, bool* aEOS)
|
||||
}
|
||||
mReader->SetLastVideoFrameTime(tstamp);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
unsigned char* data;
|
||||
size_t length;
|
||||
r = nestegg_packet_data(packet, i, &data, &length);
|
||||
if (r == -1) {
|
||||
return false;
|
||||
}
|
||||
unsigned char* data;
|
||||
size_t length;
|
||||
r = nestegg_packet_data(packet, 0, &data, &length);
|
||||
if (r == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vpx_codec_stream_info_t si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.sz = sizeof(si);
|
||||
if (mReader->GetVideoCodec() == NESTEGG_CODEC_VP8) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
|
||||
} else if (mReader->GetVideoCodec() == NESTEGG_CODEC_VP9) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
|
||||
}
|
||||
vpx_codec_stream_info_t si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.sz = sizeof(si);
|
||||
if (mReader->GetVideoCodec() == NESTEGG_CODEC_VP8) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
|
||||
} else if (mReader->GetVideoCodec() == NESTEGG_CODEC_VP9) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mPlatform && mMediaDataDecoder);
|
||||
MOZ_ASSERT(mPlatform && mMediaDataDecoder);
|
||||
|
||||
aSample = new VP8Sample(tstamp,
|
||||
next_tstamp - tstamp,
|
||||
0,
|
||||
data,
|
||||
length,
|
||||
si.is_kf);
|
||||
if (!aSample->mData) {
|
||||
return false;
|
||||
}
|
||||
aSample = new VP8Sample(tstamp,
|
||||
next_tstamp - tstamp,
|
||||
0,
|
||||
data,
|
||||
length,
|
||||
si.is_kf);
|
||||
if (!aSample->mData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -98,6 +98,11 @@ SoftwareWebMVideoDecoder::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
NS_WARNING("Packet contains more than one video frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t tstamp = holder->Timestamp();
|
||||
|
||||
// The end time of this frame is the start time of the next frame. Fetch
|
||||
@ -115,106 +120,104 @@ SoftwareWebMVideoDecoder::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
}
|
||||
mReader->SetLastVideoFrameTime(tstamp);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
unsigned char* data;
|
||||
size_t length;
|
||||
r = nestegg_packet_data(packet, i, &data, &length);
|
||||
if (r == -1) {
|
||||
unsigned char* data;
|
||||
size_t length;
|
||||
r = nestegg_packet_data(packet, 0, &data, &length);
|
||||
if (r == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vpx_codec_stream_info_t si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.sz = sizeof(si);
|
||||
if (mReader->GetVideoCodec() == NESTEGG_CODEC_VP8) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
|
||||
} else if (mReader->GetVideoCodec() == NESTEGG_CODEC_VP9) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
|
||||
}
|
||||
if (aKeyframeSkip && (!si.is_kf || tstamp < aTimeThreshold)) {
|
||||
// Skipping to next keyframe...
|
||||
a.mParsed++;
|
||||
a.mDropped++;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aKeyframeSkip && si.is_kf) {
|
||||
aKeyframeSkip = false;
|
||||
}
|
||||
|
||||
if (vpx_codec_decode(&mVPX, data, length, nullptr, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the timestamp of the video frame is less than
|
||||
// the time threshold required then it is not added
|
||||
// to the video queue and won't be displayed.
|
||||
if (tstamp < aTimeThreshold) {
|
||||
a.mParsed++;
|
||||
a.mDropped++;
|
||||
return true;
|
||||
}
|
||||
|
||||
vpx_codec_iter_t iter = nullptr;
|
||||
vpx_image_t *img;
|
||||
|
||||
while ((img = vpx_codec_get_frame(&mVPX, &iter))) {
|
||||
NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420, "WebM image format not I420");
|
||||
|
||||
// Chroma shifts are rounded down as per the decoding examples in the SDK
|
||||
VideoData::YCbCrBuffer b;
|
||||
b.mPlanes[0].mData = img->planes[0];
|
||||
b.mPlanes[0].mStride = img->stride[0];
|
||||
b.mPlanes[0].mHeight = img->d_h;
|
||||
b.mPlanes[0].mWidth = img->d_w;
|
||||
b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0;
|
||||
|
||||
b.mPlanes[1].mData = img->planes[1];
|
||||
b.mPlanes[1].mStride = img->stride[1];
|
||||
b.mPlanes[1].mHeight = (img->d_h + 1) >> img->y_chroma_shift;
|
||||
b.mPlanes[1].mWidth = (img->d_w + 1) >> img->x_chroma_shift;
|
||||
b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0;
|
||||
|
||||
b.mPlanes[2].mData = img->planes[2];
|
||||
b.mPlanes[2].mStride = img->stride[2];
|
||||
b.mPlanes[2].mHeight = (img->d_h + 1) >> img->y_chroma_shift;
|
||||
b.mPlanes[2].mWidth = (img->d_w + 1) >> img->x_chroma_shift;
|
||||
b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
|
||||
|
||||
nsIntRect pictureRect = mReader->GetPicture();
|
||||
IntRect picture = pictureRect;
|
||||
nsIntSize initFrame = mReader->GetInitialFrame();
|
||||
if (img->d_w != static_cast<uint32_t>(initFrame.width) ||
|
||||
img->d_h != static_cast<uint32_t>(initFrame.height)) {
|
||||
// Frame size is different from what the container reports. This is
|
||||
// legal in WebM, and we will preserve the ratio of the crop rectangle
|
||||
// as it was reported relative to the picture size reported by the
|
||||
// container.
|
||||
picture.x = (pictureRect.x * img->d_w) / initFrame.width;
|
||||
picture.y = (pictureRect.y * img->d_h) / initFrame.height;
|
||||
picture.width = (img->d_w * pictureRect.width) / initFrame.width;
|
||||
picture.height = (img->d_h * pictureRect.height) / initFrame.height;
|
||||
}
|
||||
|
||||
VideoInfo videoInfo = mReader->GetMediaInfo().mVideo;
|
||||
nsRefPtr<VideoData> v = VideoData::Create(videoInfo,
|
||||
mReader->GetDecoder()->GetImageContainer(),
|
||||
holder->Offset(),
|
||||
tstamp,
|
||||
next_tstamp - tstamp,
|
||||
b,
|
||||
si.is_kf,
|
||||
-1,
|
||||
picture);
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vpx_codec_stream_info_t si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.sz = sizeof(si);
|
||||
if (mReader->GetVideoCodec() == NESTEGG_CODEC_VP8) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
|
||||
} else if (mReader->GetVideoCodec() == NESTEGG_CODEC_VP9) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
|
||||
}
|
||||
if (aKeyframeSkip && (!si.is_kf || tstamp < aTimeThreshold)) {
|
||||
// Skipping to next keyframe...
|
||||
a.mParsed++; // Assume 1 frame per chunk.
|
||||
a.mDropped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aKeyframeSkip && si.is_kf) {
|
||||
aKeyframeSkip = false;
|
||||
}
|
||||
|
||||
if (vpx_codec_decode(&mVPX, data, length, nullptr, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the timestamp of the video frame is less than
|
||||
// the time threshold required then it is not added
|
||||
// to the video queue and won't be displayed.
|
||||
if (tstamp < aTimeThreshold) {
|
||||
a.mParsed++; // Assume 1 frame per chunk.
|
||||
a.mDropped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
vpx_codec_iter_t iter = nullptr;
|
||||
vpx_image_t *img;
|
||||
|
||||
while ((img = vpx_codec_get_frame(&mVPX, &iter))) {
|
||||
NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420, "WebM image format not I420");
|
||||
|
||||
// Chroma shifts are rounded down as per the decoding examples in the SDK
|
||||
VideoData::YCbCrBuffer b;
|
||||
b.mPlanes[0].mData = img->planes[0];
|
||||
b.mPlanes[0].mStride = img->stride[0];
|
||||
b.mPlanes[0].mHeight = img->d_h;
|
||||
b.mPlanes[0].mWidth = img->d_w;
|
||||
b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0;
|
||||
|
||||
b.mPlanes[1].mData = img->planes[1];
|
||||
b.mPlanes[1].mStride = img->stride[1];
|
||||
b.mPlanes[1].mHeight = (img->d_h + 1) >> img->y_chroma_shift;
|
||||
b.mPlanes[1].mWidth = (img->d_w + 1) >> img->x_chroma_shift;
|
||||
b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0;
|
||||
|
||||
b.mPlanes[2].mData = img->planes[2];
|
||||
b.mPlanes[2].mStride = img->stride[2];
|
||||
b.mPlanes[2].mHeight = (img->d_h + 1) >> img->y_chroma_shift;
|
||||
b.mPlanes[2].mWidth = (img->d_w + 1) >> img->x_chroma_shift;
|
||||
b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
|
||||
|
||||
nsIntRect pictureRect = mReader->GetPicture();
|
||||
IntRect picture = pictureRect;
|
||||
nsIntSize initFrame = mReader->GetInitialFrame();
|
||||
if (img->d_w != static_cast<uint32_t>(initFrame.width) ||
|
||||
img->d_h != static_cast<uint32_t>(initFrame.height)) {
|
||||
// Frame size is different from what the container reports. This is
|
||||
// legal in WebM, and we will preserve the ratio of the crop rectangle
|
||||
// as it was reported relative to the picture size reported by the
|
||||
// container.
|
||||
picture.x = (pictureRect.x * img->d_w) / initFrame.width;
|
||||
picture.y = (pictureRect.y * img->d_h) / initFrame.height;
|
||||
picture.width = (img->d_w * pictureRect.width) / initFrame.width;
|
||||
picture.height = (img->d_h * pictureRect.height) / initFrame.height;
|
||||
}
|
||||
|
||||
VideoInfo videoInfo = mReader->GetMediaInfo().mVideo;
|
||||
nsRefPtr<VideoData> v = VideoData::Create(videoInfo,
|
||||
mReader->GetDecoder()->GetImageContainer(),
|
||||
holder->Offset(),
|
||||
tstamp,
|
||||
next_tstamp - tstamp,
|
||||
b,
|
||||
si.is_kf,
|
||||
-1,
|
||||
picture);
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
a.mParsed++;
|
||||
a.mDecoded++;
|
||||
NS_ASSERTION(a.mDecoded <= a.mParsed,
|
||||
"Expect only 1 frame per chunk per packet in WebM...");
|
||||
mReader->VideoQueue().Push(v);
|
||||
}
|
||||
a.mParsed++;
|
||||
a.mDecoded++;
|
||||
NS_ASSERTION(a.mDecoded <= a.mParsed,
|
||||
"Expect only 1 frame per chunk per packet in WebM...");
|
||||
mReader->VideoQueue().Push(v);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -919,40 +919,25 @@ WebMReader::DemuxPacket()
|
||||
}
|
||||
|
||||
// Figure out if this is a keyframe.
|
||||
//
|
||||
// Doing this at packet-granularity is kind of the wrong level of
|
||||
// abstraction, but timestamps are on the packet, so the only time
|
||||
// we have multiple video frames in a packet is when we have "alternate
|
||||
// reference frames", which are a compression detail and never displayed.
|
||||
// So for our purposes, we can just take the union of the is_kf values for
|
||||
// all the frames in the packet.
|
||||
bool isKeyframe = false;
|
||||
if (track == mAudioTrack) {
|
||||
isKeyframe = true;
|
||||
} else if (track == mVideoTrack) {
|
||||
unsigned int count = 0;
|
||||
r = nestegg_packet_count(packet, &count);
|
||||
unsigned char* data;
|
||||
size_t length;
|
||||
r = nestegg_packet_data(packet, 0, &data, &length);
|
||||
if (r == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
unsigned char* data;
|
||||
size_t length;
|
||||
r = nestegg_packet_data(packet, i, &data, &length);
|
||||
if (r == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
vpx_codec_stream_info_t si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.sz = sizeof(si);
|
||||
if (mVideoCodec == NESTEGG_CODEC_VP8) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
|
||||
} else if (mVideoCodec == NESTEGG_CODEC_VP9) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
|
||||
}
|
||||
isKeyframe = isKeyframe || si.is_kf;
|
||||
vpx_codec_stream_info_t si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.sz = sizeof(si);
|
||||
if (mVideoCodec == NESTEGG_CODEC_VP8) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
|
||||
} else if (mVideoCodec == NESTEGG_CODEC_VP9) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
|
||||
}
|
||||
isKeyframe = si.is_kf;
|
||||
}
|
||||
|
||||
int64_t offset = mDecoder->GetResource()->Tell();
|
||||
|
16
dom/media/webspeech/recognition/Makefile.in
Normal file
16
dom/media/webspeech/recognition/Makefile.in
Normal file
@ -0,0 +1,16 @@
|
||||
ifdef MOZ_WEBSPEECH_MODELS
|
||||
MODELSPS_KEEP_PATH := 1
|
||||
|
||||
MODELSPS_FILES := models/dict/cmu07a.dic \
|
||||
models/en-us-semi/mixture_weights \
|
||||
models/en-us-semi/feat.params \
|
||||
models/en-us-semi/mdef \
|
||||
models/en-us-semi/means \
|
||||
models/en-us-semi/noisedict \
|
||||
models/en-us-semi/sendump \
|
||||
models/en-us-semi/transition_matrices \
|
||||
models/en-us-semi/variances
|
||||
|
||||
MODELSPS_DEST := $(DIST)/bin/models
|
||||
INSTALL_TARGETS += MODELSPS
|
||||
endif
|
133437
dom/media/webspeech/recognition/models/dict/cmu07a.dic
Normal file
133437
dom/media/webspeech/recognition/models/dict/cmu07a.dic
Normal file
File diff suppressed because it is too large
Load Diff
34
dom/media/webspeech/recognition/models/en-us-semi/README
Normal file
34
dom/media/webspeech/recognition/models/en-us-semi/README
Normal file
@ -0,0 +1,34 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2015 Alpha Cephei Inc. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ALPHA CEPHEI INC. ``AS IS'' AND.
|
||||
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,.
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALPHA CEPHEI INC.
|
||||
* NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT.
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,.
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY.
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT.
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE.
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
*/
|
||||
|
||||
This directory contains generic US english acoustic model trained with
|
||||
latest sphinxtrain.
|
@ -0,0 +1,12 @@
|
||||
-lowerf 130
|
||||
-upperf 3700
|
||||
-nfilt 20
|
||||
-transform dct
|
||||
-lifter 22
|
||||
-feat 1s_c_d_dd
|
||||
-svspec 0-12/13-25/26-38
|
||||
-agc none
|
||||
-cmn current
|
||||
-varnorm no
|
||||
-cmninit 40,3,-1
|
||||
-model ptm
|
137105
dom/media/webspeech/recognition/models/en-us-semi/mdef
Normal file
137105
dom/media/webspeech/recognition/models/en-us-semi/mdef
Normal file
File diff suppressed because it is too large
Load Diff
BIN
dom/media/webspeech/recognition/models/en-us-semi/means
Normal file
BIN
dom/media/webspeech/recognition/models/en-us-semi/means
Normal file
Binary file not shown.
Binary file not shown.
@ -0,0 +1,5 @@
|
||||
<s> SIL
|
||||
</s> SIL
|
||||
<sil> SIL
|
||||
[NOISE] +NSN+
|
||||
[SPEECH] +SPN+
|
BIN
dom/media/webspeech/recognition/models/en-us-semi/sendump
Normal file
BIN
dom/media/webspeech/recognition/models/en-us-semi/sendump
Normal file
Binary file not shown.
Binary file not shown.
BIN
dom/media/webspeech/recognition/models/en-us-semi/variances
Normal file
BIN
dom/media/webspeech/recognition/models/en-us-semi/variances
Normal file
Binary file not shown.
@ -19,9 +19,13 @@ EXPORTS.mozilla.dom += [
|
||||
'SpeechRecognitionResult.h',
|
||||
'SpeechRecognitionResultList.h',
|
||||
'SpeechStreamListener.h',
|
||||
'test/FakeSpeechRecognitionService.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH_TEST_BACKEND']:
|
||||
EXPORTS.mozilla.dom += [
|
||||
'test/FakeSpeechRecognitionService.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'endpointer.cc',
|
||||
'energy_endpointer.cc',
|
||||
@ -33,9 +37,13 @@ UNIFIED_SOURCES += [
|
||||
'SpeechRecognitionResult.cpp',
|
||||
'SpeechRecognitionResultList.cpp',
|
||||
'SpeechStreamListener.cpp',
|
||||
'test/FakeSpeechRecognitionService.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH_TEST_BACKEND']:
|
||||
UNIFIED_SOURCES += [
|
||||
'test/FakeSpeechRecognitionService.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
]
|
||||
|
@ -33,10 +33,14 @@ if CONFIG['MOZ_WEBSPEECH']:
|
||||
'SpeechSynthesis.cpp',
|
||||
'SpeechSynthesisUtterance.cpp',
|
||||
'SpeechSynthesisVoice.cpp',
|
||||
'test/FakeSynthModule.cpp',
|
||||
'test/nsFakeSynthServices.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH_TEST_BACKEND']:
|
||||
UNIFIED_SOURCES += [
|
||||
'test/FakeSynthModule.cpp',
|
||||
'test/nsFakeSynthServices.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_SYNTH_PICO']:
|
||||
DIRS = ['pico']
|
||||
|
||||
|
211
dom/push/PushDB.jsm
Normal file
211
dom/push/PushDB.jsm
Normal file
@ -0,0 +1,211 @@
|
||||
/* jshint moz: true, esnext: true */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Don't modify this, instead set dom.push.debug.
|
||||
let gDebuggingEnabled = false;
|
||||
|
||||
function debug(s) {
|
||||
if (gDebuggingEnabled) {
|
||||
dump("-*- PushDB.jsm: " + s + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.importGlobalProperties(["indexedDB"]);
|
||||
|
||||
const prefs = new Preferences("dom.push.");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["PushDB"];
|
||||
|
||||
this.PushDB = function PushDB(dbName, dbVersion, dbStoreName, schemaFunction) {
|
||||
debug("PushDB()");
|
||||
this._dbStoreName = dbStoreName;
|
||||
this._schemaFunction = schemaFunction;
|
||||
|
||||
// set the indexeddb database
|
||||
this.initDBHelper(dbName, dbVersion,
|
||||
[dbStoreName]);
|
||||
gDebuggingEnabled = prefs.get("debug");
|
||||
prefs.observe("debug", this);
|
||||
};
|
||||
|
||||
this.PushDB.prototype = {
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
upgradeSchema: function(aTransaction, aDb, aOldVersion, aNewVersion) {
|
||||
if (this._schemaFunction) {
|
||||
this._schemaFunction(aTransaction, aDb, aOldVersion, aNewVersion, this);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* @param aRecord
|
||||
* The record to be added.
|
||||
*/
|
||||
|
||||
put: function(aRecord) {
|
||||
debug("put()" + JSON.stringify(aRecord));
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readwrite",
|
||||
this._dbStoreName,
|
||||
function txnCb(aTxn, aStore) {
|
||||
aStore.put(aRecord).onsuccess = function setTxnResult(aEvent) {
|
||||
debug("Request successful. Updated record ID: " +
|
||||
aEvent.target.result);
|
||||
};
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
/*
|
||||
* @param aKeyID
|
||||
* The ID of record to be deleted.
|
||||
*/
|
||||
delete: function(aKeyID) {
|
||||
debug("delete()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readwrite",
|
||||
this._dbStoreName,
|
||||
function txnCb(aTxn, aStore) {
|
||||
debug("Going to delete " + aKeyID);
|
||||
aStore.delete(aKeyID);
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
clearAll: function clear() {
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readwrite",
|
||||
this._dbStoreName,
|
||||
function (aTxn, aStore) {
|
||||
debug("Going to clear all!");
|
||||
aStore.clear();
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
getByPushEndpoint: function(aPushEndpoint) {
|
||||
debug("getByPushEndpoint()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readonly",
|
||||
this._dbStoreName,
|
||||
function txnCb(aTxn, aStore) {
|
||||
aTxn.result = undefined;
|
||||
|
||||
let index = aStore.index("pushEndpoint");
|
||||
index.get(aPushEndpoint).onsuccess = function setTxnResult(aEvent) {
|
||||
aTxn.result = aEvent.target.result;
|
||||
debug("Fetch successful " + aEvent.target.result);
|
||||
};
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
getByKeyID: function(aKeyID) {
|
||||
debug("getByKeyID()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readonly",
|
||||
this._dbStoreName,
|
||||
function txnCb(aTxn, aStore) {
|
||||
aTxn.result = undefined;
|
||||
|
||||
aStore.get(aKeyID).onsuccess = function setTxnResult(aEvent) {
|
||||
aTxn.result = aEvent.target.result;
|
||||
debug("Fetch successful " + aEvent.target.result);
|
||||
};
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
getByScope: function(aScope) {
|
||||
debug("getByScope() " + aScope);
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readonly",
|
||||
this._dbStoreName,
|
||||
function txnCb(aTxn, aStore) {
|
||||
aTxn.result = undefined;
|
||||
|
||||
let index = aStore.index("scope");
|
||||
index.get(aScope).onsuccess = function setTxnResult(aEvent) {
|
||||
aTxn.result = aEvent.target.result;
|
||||
debug("Fetch successful " + aEvent.target.result);
|
||||
};
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
getAllKeyIDs: function() {
|
||||
debug("getAllKeyIDs()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readonly",
|
||||
this._dbStoreName,
|
||||
function txnCb(aTxn, aStore) {
|
||||
aStore.mozGetAll().onsuccess = function(event) {
|
||||
aTxn.result = event.target.result;
|
||||
};
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
drop: function() {
|
||||
debug("drop()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readwrite",
|
||||
this._dbStoreName,
|
||||
function txnCb(aTxn, aStore) {
|
||||
aStore.clear();
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
if ((aTopic == "nsPref:changed") && (aData == "dom.push.debug"))
|
||||
gDebuggingEnabled = prefs.get("debug");
|
||||
}
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -10,9 +10,11 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"nsIServiceWorkerManager");
|
||||
|
||||
addMessageListener("push", function (aMessage) {
|
||||
swm.sendPushEvent(aMessage.data.scope, aMessage.data.payload);
|
||||
swm.sendPushEvent(aMessage.data.originAttributes,
|
||||
aMessage.data.scope, aMessage.data.payload);
|
||||
});
|
||||
|
||||
addMessageListener("pushsubscriptionchange", function (aMessage) {
|
||||
swm.sendPushSubscriptionChangeEvent(aMessage.data);
|
||||
swm.sendPushSubscriptionChangeEvent(aMessage.data.originAttributes,
|
||||
aMessage.data.scope);
|
||||
});
|
||||
|
820
dom/push/PushServiceHttp2.jsm
Normal file
820
dom/push/PushServiceHttp2.jsm
Normal file
@ -0,0 +1,820 @@
|
||||
/* jshint moz: true, esnext: true */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
const {PushDB} = Cu.import("resource://gre/modules/PushDB.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["PushServiceHttp2"];
|
||||
|
||||
const prefs = new Preferences("dom.push.");
|
||||
|
||||
// Don't modify this, instead set dom.push.debug.
|
||||
// Set debug first so that all debugging actually works.
|
||||
var gDebuggingEnabled = prefs.get("debug");
|
||||
|
||||
function debug(s) {
|
||||
if (gDebuggingEnabled) {
|
||||
dump("-*- PushServiceHttp2.jsm: " + s + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
const kPUSHHTTP2DB_DB_NAME = "pushHttp2";
|
||||
const kPUSHHTTP2DB_DB_VERSION = 1; // Change this if the IndexedDB format changes
|
||||
const kPUSHHTTP2DB_STORE_NAME = "pushHttp2";
|
||||
|
||||
/**
|
||||
* A proxy between the PushService and connections listening for incoming push
|
||||
* messages. The PushService can silence messages from the connections by
|
||||
* setting PushSubscriptionListener._pushService to null. This is required
|
||||
* because it can happen that there is an outstanding push message that will
|
||||
* be send on OnStopRequest but the PushService may not be interested in these.
|
||||
* It's easier to stop listening than to have checks at specific points.
|
||||
*/
|
||||
var PushSubscriptionListener = function(pushService, uri) {
|
||||
debug("Creating a new pushSubscription listener.");
|
||||
this._pushService = pushService;
|
||||
this.uri = uri;
|
||||
};
|
||||
|
||||
PushSubscriptionListener.prototype = {
|
||||
|
||||
QueryInterface: function (aIID) {
|
||||
if (aIID.equals(Ci.nsIHttpPushListener) ||
|
||||
aIID.equals(Ci.nsIStreamListener)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
getInterface: function(aIID) {
|
||||
return this.QueryInterface(aIID);
|
||||
},
|
||||
|
||||
onStartRequest: function(aRequest, aContext) {
|
||||
debug("PushSubscriptionListener onStartRequest()");
|
||||
// We do not do anything here.
|
||||
},
|
||||
|
||||
onDataAvailable: function(aRequest, aContext, aStream, aOffset, aCount) {
|
||||
debug("PushSubscriptionListener onDataAvailable()");
|
||||
// Nobody should send data, but just to be sure, otherwise necko will
|
||||
// complain.
|
||||
if (aCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let inputStream = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
|
||||
inputStream.init(aStream);
|
||||
var data = inputStream.read(aCount);
|
||||
},
|
||||
|
||||
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||
debug("PushSubscriptionListener onStopRequest()");
|
||||
if (!this._pushService) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._pushService.connOnStop(aRequest,
|
||||
Components.isSuccessCode(aStatusCode),
|
||||
this.uri);
|
||||
},
|
||||
|
||||
onPush: function(associatedChannel, pushChannel) {
|
||||
debug("PushSubscriptionListener onPush()");
|
||||
var pushChannelListener = new PushChannelListener(this);
|
||||
pushChannel.asyncOpen(pushChannelListener, pushChannel);
|
||||
},
|
||||
|
||||
disconnect: function() {
|
||||
this._pushService = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The listener for pushed messages. The message data is collected in
|
||||
* OnDataAvailable and send to the app in OnStopRequest.
|
||||
*/
|
||||
var PushChannelListener = function(pushSubscriptionListener) {
|
||||
debug("Creating a new push channel listener.");
|
||||
this._mainListener = pushSubscriptionListener;
|
||||
};
|
||||
|
||||
PushChannelListener.prototype = {
|
||||
|
||||
_message: null,
|
||||
_ackUri: null,
|
||||
|
||||
onStartRequest: function(aRequest, aContext) {
|
||||
this._ackUri = aRequest.URI.spec;
|
||||
},
|
||||
|
||||
onDataAvailable: function(aRequest, aContext, aStream, aOffset, aCount) {
|
||||
debug("push channel listener onDataAvailable()");
|
||||
|
||||
if (aCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let inputStream = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
|
||||
inputStream.init(aStream);
|
||||
if (!this._message) {
|
||||
this._message = inputStream.read(aCount);
|
||||
} else {
|
||||
this._message.concat(inputStream.read(aCount));
|
||||
}
|
||||
},
|
||||
|
||||
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||
debug("push channel listener onStopRequest() status code:" + aStatusCode);
|
||||
if (Components.isSuccessCode(aStatusCode) &&
|
||||
this._mainListener &&
|
||||
this._mainListener._pushService) {
|
||||
this._mainListener._pushService._pushChannelOnStop(this._mainListener.uri,
|
||||
this._ackUri,
|
||||
this._message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var PushServiceDelete = function(resolve, reject) {
|
||||
this._resolve = resolve;
|
||||
this._reject = reject;
|
||||
};
|
||||
|
||||
PushServiceDelete.prototype = {
|
||||
|
||||
onStartRequest: function(aRequest, aContext) {},
|
||||
|
||||
onDataAvailable: function(aRequest, aContext, aStream, aOffset, aCount) {
|
||||
// Nobody should send data, but just to be sure, otherwise necko will
|
||||
// complain.
|
||||
if (aCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let inputStream = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
|
||||
inputStream.init(aStream);
|
||||
var data = inputStream.read(aCount);
|
||||
},
|
||||
|
||||
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||
|
||||
if (Components.isSuccessCode(aStatusCode)) {
|
||||
this._resolve();
|
||||
} else {
|
||||
this._reject({status: 0, error: "NetworkError"});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var SubscriptionListener = function(aSubInfo, aServerURI, aPushServiceHttp2) {
|
||||
debug("Creating a new subscription listener.");
|
||||
this._subInfo = aSubInfo;
|
||||
this._data = '';
|
||||
this._serverURI = aServerURI;
|
||||
this._service = aPushServiceHttp2;
|
||||
};
|
||||
|
||||
SubscriptionListener.prototype = {
|
||||
|
||||
onStartRequest: function(aRequest, aContext) {},
|
||||
|
||||
onDataAvailable: function(aRequest, aContext, aStream, aOffset, aCount) {
|
||||
debug("subscription listener onDataAvailable()");
|
||||
|
||||
// We do not expect any data, but necko will complain if we do not consume
|
||||
// it.
|
||||
if (aCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let inputStream = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
|
||||
inputStream.init(aStream);
|
||||
this._data.concat(inputStream.read(aCount));
|
||||
},
|
||||
|
||||
onStopRequest: function(aRequest, aContext, aStatus) {
|
||||
debug("subscription listener onStopRequest()");
|
||||
|
||||
// Check if pushService is still active.
|
||||
if (!this._service.hasmainPushService()) {
|
||||
this._subInfo.reject({error: "Service deactivated"});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Components.isSuccessCode(aStatus)) {
|
||||
this._subInfo.reject({error: "Error status" + aStatus});
|
||||
return;
|
||||
}
|
||||
|
||||
var statusCode = aRequest.QueryInterface(Ci.nsIHttpChannel).responseStatus;
|
||||
|
||||
if (Math.floor(statusCode / 100) == 5) {
|
||||
if (this._subInfo.retries < prefs.get("http2.maxRetries")) {
|
||||
this._subInfo.retries++;
|
||||
var retryAfter = retryAfterParser(aRequest);
|
||||
setTimeout(this._service.retrySubscription.bind(this._service,
|
||||
this._subInfo),
|
||||
retryAfter);
|
||||
} else {
|
||||
this._subInfo.reject({error: "Error response code: " + statusCode });
|
||||
}
|
||||
return;
|
||||
} else if (statusCode != 201) {
|
||||
this._subInfo.reject({error: "Error response code: " + statusCode });
|
||||
return;
|
||||
}
|
||||
|
||||
var subscriptionUri;
|
||||
try {
|
||||
subscriptionUri = aRequest.getResponseHeader("location");
|
||||
} catch (err) {
|
||||
this._subInfo.reject({error: "Return code 201, but the answer is bogus"});
|
||||
return;
|
||||
}
|
||||
|
||||
debug("subscriptionUri: " + subscriptionUri);
|
||||
|
||||
var linkList;
|
||||
try {
|
||||
linkList = aRequest.getResponseHeader("link");
|
||||
} catch (err) {
|
||||
this._subInfo.reject({error: "Return code 201, but the answer is bogus"});
|
||||
return;
|
||||
}
|
||||
|
||||
var linkParserResult = linkParser(linkList, this._serverURI);
|
||||
if (linkParserResult.error) {
|
||||
this._subInfo.reject(linkParserResult);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!subscriptionUri) {
|
||||
this._subInfo.reject({error: "Return code 201, but the answer is bogus," +
|
||||
" missing subscriptionUri"});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let uriTry = Services.io.newURI(subscriptionUri, null, null);
|
||||
} catch (e) {
|
||||
debug("Invalid URI " + subscriptionUri);
|
||||
this._subInfo.reject({error: "Return code 201, but URI is bogus. " +
|
||||
subscriptionUri});
|
||||
return;
|
||||
}
|
||||
|
||||
var reply = {
|
||||
subscriptionUri: subscriptionUri,
|
||||
pushEndpoint: linkParserResult.pushEndpoint,
|
||||
pushReceiptEndpoint: linkParserResult.pushReceiptEndpoint,
|
||||
pageURL: this._subInfo.record.pageURL,
|
||||
scope: this._subInfo.record.scope,
|
||||
pushCount: 0,
|
||||
lastPush: 0
|
||||
};
|
||||
this._subInfo.resolve(reply);
|
||||
},
|
||||
};
|
||||
|
||||
function retryAfterParser(aRequest) {
|
||||
var retryAfter = 0;
|
||||
try {
|
||||
var retryField = aRequest.getResponseHeader("retry-after");
|
||||
if (isNaN(retryField)) {
|
||||
retryAfter = Date.parse(retryField) - (new Date().getTime());
|
||||
} else {
|
||||
retryAfter = parseInt(retryField, 10) * 1000;
|
||||
}
|
||||
retryAfter = (retryAfter > 0) ? retryAfter : 0;
|
||||
} catch(e) {}
|
||||
|
||||
return retryAfter;
|
||||
}
|
||||
|
||||
function linkParser(linkHeader, serverURI) {
|
||||
|
||||
var linkList = linkHeader.split(',');
|
||||
if ((linkList.length < 1)) {
|
||||
return {error: "Return code 201, but the answer is bogus"};
|
||||
}
|
||||
|
||||
var pushEndpoint;
|
||||
var pushReceiptEndpoint;
|
||||
|
||||
linkList.forEach(link => {
|
||||
var linkElems = link.split(';');
|
||||
|
||||
if (linkElems.length == 2) {
|
||||
if (linkElems[1].trim() === 'rel="urn:ietf:params:push"') {
|
||||
pushEndpoint = linkElems[0].substring(linkElems[0].indexOf('<') + 1,
|
||||
linkElems[0].indexOf('>'));
|
||||
|
||||
} else if (linkElems[1].trim() === 'rel="urn:ietf:params:push:receipt"') {
|
||||
pushReceiptEndpoint = linkElems[0].substring(linkElems[0].indexOf('<') + 1,
|
||||
linkElems[0].indexOf('>'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
debug("pushEndpoint: " + pushEndpoint);
|
||||
debug("pushReceiptEndpoint: " + pushReceiptEndpoint);
|
||||
// Missing pushReceiptEndpoint is allowed.
|
||||
if (!pushEndpoint) {
|
||||
return {error: "Return code 201, but the answer is bogus, missing" +
|
||||
" pushEndpoint"};
|
||||
}
|
||||
|
||||
var uri;
|
||||
var resUri = [];
|
||||
try {
|
||||
[pushEndpoint, pushReceiptEndpoint].forEach(u => {
|
||||
if (u) {
|
||||
uri = u;
|
||||
resUri[u] = Services.io.newURI(uri, null, serverURI);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
debug("Invalid URI " + uri);
|
||||
return {error: "Return code 201, but URI is bogus. " + uri};
|
||||
}
|
||||
|
||||
return {
|
||||
pushEndpoint: resUri[pushEndpoint].spec,
|
||||
pushReceiptEndpoint: (pushReceiptEndpoint) ? resUri[pushReceiptEndpoint].spec
|
||||
: ""
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The implementation of the WebPush.
|
||||
*/
|
||||
this.PushServiceHttp2 = {
|
||||
_mainPushService: null,
|
||||
_serverURI: null,
|
||||
|
||||
// Keep information about all connections, e.g. the channel, listener...
|
||||
_conns: {},
|
||||
_started: false,
|
||||
|
||||
upgradeSchema: function(aTransaction,
|
||||
aDb,
|
||||
aOldVersion,
|
||||
aNewVersion,
|
||||
aDbInstance) {
|
||||
debug("upgradeSchemaHttp2()");
|
||||
|
||||
let objectStore = aDb.createObjectStore(aDbInstance._dbStoreName,
|
||||
{ keyPath: "subscriptionUri" });
|
||||
|
||||
// index to fetch records based on endpoints. used by unregister
|
||||
objectStore.createIndex("pushEndpoint", "pushEndpoint", { unique: true });
|
||||
|
||||
// index to fetch records per scope, so we can identify endpoints
|
||||
// associated with an app.
|
||||
objectStore.createIndex("scope", "scope", { unique: true });
|
||||
},
|
||||
|
||||
getKeyFromRecord: function(aRecord) {
|
||||
return aRecord.subscriptionUri;
|
||||
},
|
||||
|
||||
newPushDB: function() {
|
||||
return new PushDB(kPUSHHTTP2DB_DB_NAME,
|
||||
kPUSHHTTP2DB_DB_VERSION,
|
||||
kPUSHHTTP2DB_STORE_NAME,
|
||||
this.upgradeSchema);
|
||||
},
|
||||
|
||||
hasmainPushService: function() {
|
||||
return this._mainPushService !== null;
|
||||
},
|
||||
|
||||
checkServerURI: function(serverURL) {
|
||||
if (!serverURL) {
|
||||
debug("No dom.push.serverURL found!");
|
||||
return;
|
||||
}
|
||||
|
||||
let uri;
|
||||
try {
|
||||
uri = Services.io.newURI(serverURL, null, null);
|
||||
} catch(e) {
|
||||
debug("Error creating valid URI from dom.push.serverURL (" +
|
||||
serverURL + ")");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (uri.scheme !== "https") {
|
||||
debug("Unsupported websocket scheme " + uri.scheme);
|
||||
return null;
|
||||
}
|
||||
return uri;
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "nsPref:changed") {
|
||||
if (aData == "dom.push.debug") {
|
||||
gDebuggingEnabled = prefs.get("debug");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
connect: function(subscriptions) {
|
||||
this.startConnections(subscriptions);
|
||||
},
|
||||
|
||||
disconnect: function() {
|
||||
this._shutdownConnections(false);
|
||||
},
|
||||
|
||||
_makeChannel: function(aUri) {
|
||||
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
var chan = ios.newChannel2(aUri,
|
||||
null,
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER)
|
||||
.QueryInterface(Ci.nsIHttpChannel);
|
||||
|
||||
var loadGroup = Cc["@mozilla.org/network/load-group;1"]
|
||||
.createInstance(Ci.nsILoadGroup);
|
||||
chan.loadGroup = loadGroup;
|
||||
return chan;
|
||||
},
|
||||
|
||||
/**
|
||||
* Subscribe new resource.
|
||||
*/
|
||||
_subscribeResource: function(aRecord) {
|
||||
debug("subscribeResource()");
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this._subscribeResourceInternal({record: aRecord,
|
||||
resolve,
|
||||
reject,
|
||||
retries: 0});
|
||||
})
|
||||
.then(result => {
|
||||
this._conns[result.subscriptionUri] = {channel: null,
|
||||
listener: null,
|
||||
countUnableToConnect: 0,
|
||||
lastStartListening: 0,
|
||||
waitingForAlarm: false};
|
||||
this._listenForMsgs(result.subscriptionUri);
|
||||
return result;
|
||||
});
|
||||
},
|
||||
|
||||
_subscribeResourceInternal: function(aSubInfo) {
|
||||
debug("subscribeResource()");
|
||||
|
||||
var listener = new SubscriptionListener(aSubInfo,
|
||||
this._serverURI,
|
||||
this);
|
||||
|
||||
var chan = this._makeChannel(this._serverURI.spec);
|
||||
chan.requestMethod = "POST";
|
||||
try{
|
||||
chan.asyncOpen(listener, null);
|
||||
} catch(e) {
|
||||
aSubInfo.reject({status: 0, error: "NetworkError"});
|
||||
}
|
||||
},
|
||||
|
||||
retrySubscription: function(aSubInfo) {
|
||||
this._subscribeResourceInternal(aSubInfo);
|
||||
},
|
||||
|
||||
_deleteResource: function(aUri) {
|
||||
|
||||
return new Promise((resolve,reject) => {
|
||||
var chan = this._makeChannel(aUri);
|
||||
chan.requestMethod = "DELETE";
|
||||
try {
|
||||
chan.asyncOpen(new PushServiceDelete(resolve, reject), null);
|
||||
} catch(err) {
|
||||
reject({status: 0, error: "NetworkError"});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Unsubscribe the resource with a subscription uri aSubscriptionUri.
|
||||
* We can't do anything about it if it fails, so we don't listen for response.
|
||||
*/
|
||||
_unsubscribeResource: function(aSubscriptionUri) {
|
||||
debug("unsubscribeResource()");
|
||||
|
||||
return this._deleteResource(aSubscriptionUri);
|
||||
},
|
||||
|
||||
/**
|
||||
* Start listening for messages.
|
||||
*/
|
||||
_listenForMsgs: function(aSubscriptionUri) {
|
||||
debug("listenForMsgs() " + aSubscriptionUri);
|
||||
if (!this._conns[aSubscriptionUri]) {
|
||||
debug("We do not have this subscription " + aSubscriptionUri);
|
||||
return;
|
||||
}
|
||||
|
||||
var chan = this._makeChannel(aSubscriptionUri);
|
||||
var conn = {};
|
||||
conn.channel = chan;
|
||||
var listener = new PushSubscriptionListener(this, aSubscriptionUri);
|
||||
conn.listener = listener;
|
||||
|
||||
chan.notificationCallbacks = listener;
|
||||
|
||||
try {
|
||||
chan.asyncOpen(listener, chan);
|
||||
} catch (e) {
|
||||
debug("Error connecting to push server. asyncOpen failed!");
|
||||
conn.listener.disconnect();
|
||||
chan.cancel(Cr.NS_ERROR_ABORT);
|
||||
this._retryAfterBackoff(aSubscriptionUri, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
this._conns[aSubscriptionUri].lastStartListening = Date.now();
|
||||
this._conns[aSubscriptionUri].channel = conn.channel;
|
||||
this._conns[aSubscriptionUri].listener = conn.listener;
|
||||
|
||||
},
|
||||
|
||||
_ackMsgRecv: function(aAckUri) {
|
||||
debug("ackMsgRecv() " + aAckUri);
|
||||
// We can't do anything about it if it fails,
|
||||
// so we don't listen for response.
|
||||
this._deleteResource(aAckUri);
|
||||
},
|
||||
|
||||
init: function(aOptions, aMainPushService, aServerURL) {
|
||||
debug("init()");
|
||||
this._mainPushService = aMainPushService;
|
||||
this._serverURI = aServerURL;
|
||||
gDebuggingEnabled = prefs.get("debug");
|
||||
prefs.observe("debug", this);
|
||||
},
|
||||
|
||||
_retryAfterBackoff: function(aSubscriptionUri, retryAfter) {
|
||||
debug("retryAfterBackoff()");
|
||||
|
||||
var resetRetryCount = prefs.get("http2.reset_retry_count_after_ms");
|
||||
// If it was running for some time, reset retry counter.
|
||||
if ((Date.now() - this._conns[aSubscriptionUri].lastStartListening) >
|
||||
resetRetryCount) {
|
||||
this._conns[aSubscriptionUri].countUnableToConnect = 0;
|
||||
}
|
||||
|
||||
let maxRetries = prefs.get("http2.maxRetries");
|
||||
if (this._conns[aSubscriptionUri].countUnableToConnect >= maxRetries) {
|
||||
this._shutdownSubscription(aSubscriptionUri);
|
||||
this._resubscribe(aSubscriptionUri);
|
||||
return;
|
||||
}
|
||||
|
||||
if (retryAfter !== -1) {
|
||||
// This is a 5xx response.
|
||||
// To respect RetryAfter header, setTimeout is used. setAlarm sets a
|
||||
// cumulative alarm so it will not always respect RetryAfter header.
|
||||
this._conns[aSubscriptionUri].countUnableToConnect++;
|
||||
setTimeout(_ => this._listenForMsgs(aSubscriptionUri), retryAfter);
|
||||
return;
|
||||
}
|
||||
|
||||
// we set just one alarm because most probably all connection will go over
|
||||
// a single TCP connection.
|
||||
retryAfter = prefs.get("http2.retryInterval") *
|
||||
Math.pow(2, this._conns[aSubscriptionUri].countUnableToConnect);
|
||||
|
||||
retryAfter = retryAfter * (0.8 + Math.random() * 0.4); // add +/-20%.
|
||||
|
||||
this._conns[aSubscriptionUri].countUnableToConnect++;
|
||||
|
||||
if (retryAfter === 0) {
|
||||
setTimeout(_ => this._listenForMsgs(aSubscriptionUri), 0);
|
||||
} else {
|
||||
this._conns[aSubscriptionUri].waitingForAlarm = true;
|
||||
this._mainPushService.setAlarm(retryAfter);
|
||||
}
|
||||
debug("Retry in " + retryAfter);
|
||||
},
|
||||
|
||||
// Close connections.
|
||||
_shutdownConnections: function(deleteInfo) {
|
||||
debug("shutdownConnections()");
|
||||
|
||||
for (let subscriptionUri in this._conns) {
|
||||
if (this._conns[subscriptionUri]) {
|
||||
if (this._conns[subscriptionUri].listener) {
|
||||
this._conns[subscriptionUri].listener._pushService = null;
|
||||
}
|
||||
|
||||
if (this._conns[subscriptionUri].channel) {
|
||||
try {
|
||||
this._conns[subscriptionUri].channel.cancel(Cr.NS_ERROR_ABORT);
|
||||
} catch (e) {}
|
||||
}
|
||||
this._conns[subscriptionUri].listener = null;
|
||||
this._conns[subscriptionUri].channel = null;
|
||||
this._conns[subscriptionUri].waitingForAlarm = false;
|
||||
if (deleteInfo) {
|
||||
delete this._conns[subscriptionUri];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Start listening if subscriptions present.
|
||||
startConnections: function(aSubscriptions) {
|
||||
debug("startConnections() " + aSubscriptions.length);
|
||||
|
||||
for (let i = 0; i < aSubscriptions.length; i++) {
|
||||
let record = aSubscriptions[i];
|
||||
if (typeof this._conns[record.subscriptionUri] != "object") {
|
||||
this._conns[record.subscriptionUri] = {channel: null,
|
||||
listener: null,
|
||||
countUnableToConnect: 0,
|
||||
waitingForAlarm: false};
|
||||
}
|
||||
if (!this._conns[record.subscriptionUri].conn) {
|
||||
this._conns[record.subscriptionUri].waitingForAlarm = false;
|
||||
this._listenForMsgs(record.subscriptionUri);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Start listening if subscriptions present.
|
||||
_startConnectionsWaitingForAlarm: function() {
|
||||
debug("startConnectionsWaitingForAlarm()");
|
||||
for (let subscriptionUri in this._conns) {
|
||||
if ((this._conns[subscriptionUri]) &&
|
||||
!this._conns[subscriptionUri].conn &&
|
||||
this._conns[subscriptionUri].waitingForAlarm) {
|
||||
this._conns[subscriptionUri].waitingForAlarm = false;
|
||||
this._listenForMsgs(subscriptionUri);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Close connection and notify apps that subscription are gone.
|
||||
_shutdownSubscription: function(aSubscriptionUri) {
|
||||
debug("shutdownSubscriptions()");
|
||||
|
||||
if (typeof this._conns[aSubscriptionUri] == "object") {
|
||||
if (this._conns[aSubscriptionUri].listener) {
|
||||
this._conns[aSubscriptionUri].listener._pushService = null;
|
||||
}
|
||||
|
||||
if (this._conns[aSubscriptionUri].channel) {
|
||||
try {
|
||||
this._conns[aSubscriptionUri].channel.cancel(Cr.NS_ERROR_ABORT);
|
||||
} catch (e) {}
|
||||
}
|
||||
delete this._conns[aSubscriptionUri];
|
||||
}
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
debug("uninit()");
|
||||
this._shutdownConnections(true);
|
||||
this._mainPushService = null;
|
||||
},
|
||||
|
||||
|
||||
request: function(action, aRecord) {
|
||||
switch (action) {
|
||||
case "register":
|
||||
debug("register");
|
||||
return this._subscribeResource(aRecord);
|
||||
case "unregister":
|
||||
this._shutdownSubscription(aRecord.subscriptionUri);
|
||||
return this._unsubscribeResource(aRecord.subscriptionUri);
|
||||
}
|
||||
},
|
||||
|
||||
/** Push server has deleted subscription.
|
||||
* Re-subscribe - if it succeeds send update db record and send
|
||||
* pushsubscriptionchange,
|
||||
* - on error delete record and send pushsubscriptionchange
|
||||
* TODO: maybe pushsubscriptionerror will be included.
|
||||
*/
|
||||
_resubscribe: function(aSubscriptionUri) {
|
||||
this._mainPushService.getByKeyID(aSubscriptionUri)
|
||||
.then(record => this._subscribeResource(record)
|
||||
.then(recordNew => {
|
||||
if (this._mainPushService) {
|
||||
this._mainPushService.updateRegistrationAndNotifyApp(aSubscriptionUri,
|
||||
recordNew);
|
||||
}
|
||||
}, error => {
|
||||
if (this._mainPushService) {
|
||||
this._mainPushService.dropRegistrationAndNotifyApp(aSubscriptionUri);
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
connOnStop: function(aRequest, aSuccess,
|
||||
aSubscriptionUri) {
|
||||
debug("connOnStop() succeeded: " + aSuccess);
|
||||
|
||||
var conn = this._conns[aSubscriptionUri];
|
||||
if (!conn) {
|
||||
// there is no connection description that means that we closed
|
||||
// connection, so do nothing. But we should have already deleted
|
||||
// the listener.
|
||||
return;
|
||||
}
|
||||
|
||||
conn.channel = null;
|
||||
conn.listener = null;
|
||||
|
||||
if (!aSuccess) {
|
||||
this._retryAfterBackoff(aSubscriptionUri, -1);
|
||||
|
||||
} else if (Math.floor(aRequest.responseStatus / 100) == 5) {
|
||||
var retryAfter = retryAfterParser(aRequest);
|
||||
this._retryAfterBackoff(aSubscriptionUri, retryAfter);
|
||||
|
||||
} else if (Math.floor(aRequest.responseStatus / 100) == 4) {
|
||||
this._shutdownSubscription(aSubscriptionUri);
|
||||
this._resubscribe(aSubscriptionUri);
|
||||
} else if (Math.floor(aRequest.responseStatus / 100) == 2) { // This should be 204
|
||||
setTimeout(_ => this._listenForMsgs(aSubscriptionUri), 0);
|
||||
} else {
|
||||
this._retryAfterBackoff(aSubscriptionUri, -1);
|
||||
}
|
||||
},
|
||||
|
||||
_pushChannelOnStop: function(aUri, aAckUri, aMessage) {
|
||||
debug("pushChannelOnStop() ");
|
||||
|
||||
let sendNotification = function(aAckUri, aPushRecord, self) {
|
||||
aPushRecord.pushCount = aPushRecord.pushCount + 1;
|
||||
aPushRecord.lastPush = new Date().getTime();
|
||||
self._mainPushService.receivedPushMessage(aPushRecord, aMessage);
|
||||
self._ackMsgRecv(aAckUri);
|
||||
};
|
||||
|
||||
let recoverNoSuchEndpoint = function() {
|
||||
debug("Could not get push endpoint " + aUri + " from DB");
|
||||
};
|
||||
|
||||
this._mainPushService.getByKeyID(aUri)
|
||||
.then(pushRecord => sendNotification(aAckUri, pushRecord, this),
|
||||
recoverNoSuchEndpoint);
|
||||
},
|
||||
|
||||
onAlarmFired: function() {
|
||||
// Conditions are arranged in decreasing specificity.
|
||||
// i.e. when _waitingForPong is true, other conditions are also true.
|
||||
this._startConnectionsWaitingForAlarm();
|
||||
},
|
||||
|
||||
prepareRegistration: function(aPushRecord) {
|
||||
return {
|
||||
pushEndpoint: aPushRecord.pushEndpoint,
|
||||
pushReceiptEndpoint: aPushRecord.pushReceiptEndpoint,
|
||||
version: aPushRecord.version,
|
||||
lastPush: aPushRecord.lastPush,
|
||||
pushCount: aPushRecord.pushCount
|
||||
};
|
||||
},
|
||||
|
||||
prepareRegister: function(aPushRecord) {
|
||||
return {
|
||||
pushEndpoint: aPushRecord.pushEndpoint,
|
||||
pushReceiptEndpoint: aPushRecord.pushReceiptEndpoint
|
||||
};
|
||||
}
|
||||
};
|
1425
dom/push/PushServiceWebSocket.jsm
Normal file
1425
dom/push/PushServiceWebSocket.jsm
Normal file
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,10 @@ EXTRA_COMPONENTS += [
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
'PushDB.jsm',
|
||||
'PushService.jsm',
|
||||
'PushServiceHttp2.jsm',
|
||||
'PushServiceWebSocket.jsm',
|
||||
]
|
||||
|
||||
MOCHITEST_MANIFESTS += [
|
||||
|
@ -12,4 +12,10 @@ skip-if = os == "android" || toolkit == "gonk"
|
||||
[test_register.html]
|
||||
skip-if = os == "android" || toolkit == "gonk"
|
||||
[test_multiple_register.html]
|
||||
skip-if = os == "android" || toolkit == "gonk"
|
||||
skip-if = os == "android" || toolkit == "gonk"
|
||||
[test_multiple_register_during_service_activation.html]
|
||||
skip-if = os == "android" || toolkit == "gonk"
|
||||
[test_multiple_register_different_scope.html]
|
||||
skip-if = os == "android" || toolkit == "gonk"
|
||||
[test_try_registering_offline_disabled.html]
|
||||
skip-if = os == "android" || toolkit == "gonk"
|
||||
|
126
dom/push/test/test_multiple_register_different_scope.html
Normal file
126
dom/push/test/test_multiple_register_different_scope.html
Normal file
@ -0,0 +1,126 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 1150812: Test registering for two different scopes.
|
||||
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1150812</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
|
||||
</head>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1150812">Mozilla Bug 1150812</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var scopeA = "./a/";
|
||||
var scopeB = "./b/";
|
||||
|
||||
function debug(str) {
|
||||
// console.log(str + "\n");
|
||||
}
|
||||
|
||||
function registerServiceWorker(scope) {
|
||||
return navigator.serviceWorker.register("worker.js" + "?" + (Math.random()), {scope: scope});
|
||||
}
|
||||
|
||||
function unregister(swr) {
|
||||
return swr.unregister()
|
||||
.then(result => {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, err => {
|
||||
ok(false,"Unregistering the SW failed with " + err + "\n");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function subscribe(swr) {
|
||||
return swr.pushManager.subscribe()
|
||||
.then(sub => {
|
||||
ok(true, "successful registered for push notification");
|
||||
return sub;
|
||||
}, err => {
|
||||
ok(false, "could not register for push notification");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function setupMultipleSubscriptions(swr1, swr2) {
|
||||
return Promise.all([
|
||||
subscribe(swr1),
|
||||
subscribe(swr2)
|
||||
]).then(a => {
|
||||
ok(a[0].endpoint != a[1].endpoint, "setupMultipleSubscriptions - Got different endpoints.");
|
||||
return a;
|
||||
});
|
||||
}
|
||||
|
||||
function getEndpointExpectNull(swr) {
|
||||
return swr.pushManager.getSubscription()
|
||||
.then(pushSubscription => {
|
||||
ok(pushSubscription == null, "getEndpoint should return null when app not subscribed.");
|
||||
}, err => {
|
||||
ok(false, "could not register for push notification");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function getEndpoint(swr, results) {
|
||||
return swr.pushManager.getSubscription()
|
||||
.then(sub => {
|
||||
ok((results[0].endpoint == sub.endpoint) ||
|
||||
(results[1].endpoint == sub.endpoint), "getEndpoint - Got the same endpoint back.");
|
||||
return results;
|
||||
}, err => {
|
||||
ok(false, "could not register for push notification");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function unsubscribe(result) {
|
||||
return result[0].unsubscribe()
|
||||
.then(_ => result[1].unsubscribe());
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
registerServiceWorker(scopeA)
|
||||
.then(swrA =>
|
||||
registerServiceWorker(scopeB)
|
||||
.then(swrB =>
|
||||
getEndpointExpectNull(swrA)
|
||||
.then(_ => getEndpointExpectNull(swrB))
|
||||
.then(_ => setupMultipleSubscriptions(swrA, swrB))
|
||||
.then(results => getEndpoint(swrA, results))
|
||||
.then(results => getEndpoint(swrB, results))
|
||||
.then(results => unsubscribe(results))
|
||||
.then(_ => unregister(swrA))
|
||||
.then(_ => unregister(swrB))
|
||||
)
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
}).then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.push.enabled", true],
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true]
|
||||
]}, runTest);
|
||||
SpecialPowers.addPermission('push', true, document);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,114 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 1150812: If service is in activating or no connection state it can not send
|
||||
request immediately, but the requests are queued. This test test the case of
|
||||
multiple subscription for the same scope during activation.
|
||||
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1150812</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
|
||||
</head>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1150812">Mozilla Bug 1150812</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function debug(str) {
|
||||
// console.log(str + "\n");
|
||||
}
|
||||
|
||||
function registerServiceWorker() {
|
||||
return navigator.serviceWorker.register("worker.js" + "?" + (Math.random()), {scope: "."});
|
||||
}
|
||||
|
||||
function unregister(swr) {
|
||||
return swr.unregister()
|
||||
.then(result => {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, err => {
|
||||
dump("Unregistering the SW failed with " + err + "\n");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function subscribe(swr) {
|
||||
return swr.pushManager.subscribe()
|
||||
.then(sub => {
|
||||
ok(true, "successful registered for push notification");
|
||||
return sub;
|
||||
}, err => {
|
||||
ok(false, "could not register for push notification");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
var defaultServerURL = SpecialPowers.getCharPref("dom.push.serverURL");
|
||||
|
||||
function setupMultipleSubscriptions(swr) {
|
||||
|
||||
// We need to do this to restart service so that a queue will be formed.
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.push.serverURL", defaultServerURL]]},
|
||||
null);
|
||||
return Promise.all([
|
||||
subscribe(swr),
|
||||
subscribe(swr)
|
||||
]).then(a => {
|
||||
ok(a[0].endpoint == a[1].endpoint, "setupMultipleSubscriptions - Got the same endpoint back.");
|
||||
return a[0];
|
||||
}, err => {
|
||||
ok(false, "could not register for push notification");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function getEndpointExpectNull(swr) {
|
||||
return swr.pushManager.getSubscription()
|
||||
.then(pushSubscription => {
|
||||
ok(pushSubscription == null, "getEndpoint should return null when app not subscribed.");
|
||||
}, err => {
|
||||
ok(false, "could not register for push notification");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function unsubscribe(sub) {
|
||||
return sub.unsubscribe();
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
registerServiceWorker()
|
||||
.then(swr =>
|
||||
getEndpointExpectNull(swr)
|
||||
.then(_ => setupMultipleSubscriptions(swr))
|
||||
.then(sub => unsubscribe(sub))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
}).then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.push.enabled", true],
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
["dom.push.serverURL", "wss://something.org"]
|
||||
]}, runTest);
|
||||
SpecialPowers.addPermission('push', true, document);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
300
dom/push/test/test_try_registering_offline_disabled.html
Normal file
300
dom/push/test/test_try_registering_offline_disabled.html
Normal file
@ -0,0 +1,300 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 1150812: Try to register when serviced if offline or connection is disabled.
|
||||
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1150812</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
|
||||
</head>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1150812">Mozilla Bug 1150812</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function debug(str) {
|
||||
// console.log(str + "\n");
|
||||
}
|
||||
|
||||
function registerServiceWorker() {
|
||||
return navigator.serviceWorker.register("worker.js" + "?" + (Math.random()), {scope: "."});
|
||||
}
|
||||
|
||||
function unregister(swr) {
|
||||
return swr.unregister()
|
||||
.then(result => {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, err => {
|
||||
dump("Unregistering the SW failed with " + err + "\n");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function subscribe(swr) {
|
||||
return swr.pushManager.subscribe()
|
||||
.then(sub => {
|
||||
ok(true, "successful registered for push notification");
|
||||
return sub;
|
||||
}, err => {
|
||||
ok(false, "could not register for push notification");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function subscribeFail(swr) {
|
||||
return new Promise((res, rej) => {
|
||||
swr.pushManager.subscribe()
|
||||
.then(sub => {
|
||||
ok(false, "successful registered for push notification");
|
||||
throw "Should fail";
|
||||
}, err => {
|
||||
ok(true, "could not register for push notification");
|
||||
res(swr);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getEndpointExpectNull(swr) {
|
||||
return swr.pushManager.getSubscription()
|
||||
.then(pushSubscription => {
|
||||
ok(pushSubscription == null, "getEndpoint should return null when app not subscribed.");
|
||||
}, err => {
|
||||
ok(false, "could not register for push notification");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function getEndpoint(swr, subOld) {
|
||||
return swr.pushManager.getSubscription()
|
||||
.then(sub => {
|
||||
ok(subOld.endpoint == sub.endpoint, "getEndpoint - Got the same endpoint back.");
|
||||
return sub;
|
||||
}, err => {
|
||||
ok(false, "could not register for push notification");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function offlineObserver(res) {
|
||||
this._res = res;
|
||||
}
|
||||
offlineObserver.prototype = {
|
||||
_res: null,
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
debug("observe: " + subject + " " + topic + " " + data);
|
||||
if (topic === "network:offline-status-changed") {
|
||||
var obsService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIObserverService);
|
||||
obsService.removeObserver(this, topic);
|
||||
this._res(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function changeOfflineState(offline) {
|
||||
return new Promise(function(res, rej) {
|
||||
var obsService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIObserverService);
|
||||
obsService.addObserver(SpecialPowers.wrapCallbackObject(new offlineObserver(res)),
|
||||
"network:offline-status-changed",
|
||||
false);
|
||||
var ioService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIIOService);
|
||||
ioService.offline = offline;
|
||||
});
|
||||
}
|
||||
|
||||
function changePushServerConnectionEnabled(enable) {
|
||||
debug("changePushServerConnectionEnabled");
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.push.connection.enabled", enable]]},
|
||||
null);
|
||||
}
|
||||
|
||||
function unsubscribe(sub) {
|
||||
return sub.unsubscribe()
|
||||
.then(_ => {ok(true, "Unsubscribed!");});
|
||||
}
|
||||
|
||||
// go offline then go online
|
||||
function runTest1() {
|
||||
return registerServiceWorker()
|
||||
.then(swr =>
|
||||
getEndpointExpectNull(swr)
|
||||
.then(_ => changeOfflineState(true))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changeOfflineState(false))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
}
|
||||
|
||||
// disable - enable push connection.
|
||||
function runTest2() {
|
||||
return registerServiceWorker()
|
||||
.then(swr =>
|
||||
getEndpointExpectNull(swr)
|
||||
.then(_ => changePushServerConnectionEnabled(false))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changePushServerConnectionEnabled(true))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
}
|
||||
|
||||
// go offline - disable - enable - go online
|
||||
function runTest3() {
|
||||
return registerServiceWorker()
|
||||
.then(swr =>
|
||||
getEndpointExpectNull(swr)
|
||||
.then(_ => changeOfflineState(true))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changePushServerConnectionEnabled(false))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changePushServerConnectionEnabled(true))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changeOfflineState(false))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
}
|
||||
|
||||
// disable - offline - online - enable.
|
||||
function runTest4() {
|
||||
return registerServiceWorker()
|
||||
.then(swr =>
|
||||
getEndpointExpectNull(swr)
|
||||
.then(_ => changePushServerConnectionEnabled(false))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changeOfflineState(true))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changeOfflineState(false))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changePushServerConnectionEnabled(true))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
}
|
||||
|
||||
// go offline - disable - go online - enable
|
||||
function runTest5() {
|
||||
return registerServiceWorker()
|
||||
.then(swr =>
|
||||
getEndpointExpectNull(swr)
|
||||
.then(_ => changeOfflineState(true))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changePushServerConnectionEnabled(false))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changeOfflineState(false))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changePushServerConnectionEnabled(true))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
}
|
||||
|
||||
// disable - go offline - enable - go online.
|
||||
function runTest6() {
|
||||
return registerServiceWorker()
|
||||
.then(swr =>
|
||||
getEndpointExpectNull(swr)
|
||||
.then(_ => changePushServerConnectionEnabled(false))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changeOfflineState(true))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changePushServerConnectionEnabled(true))
|
||||
.then(_ => subscribeFail(swr))
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => changeOfflineState(false))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
runTest1()
|
||||
.then(_ => runTest2())
|
||||
.then(_ => runTest3())
|
||||
.then(_ => runTest4())
|
||||
.then(_ => runTest5())
|
||||
.then(_ => runTest6())
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.push.enabled", true],
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true]
|
||||
]}, runTest);
|
||||
SpecialPowers.addPermission('push', true, document);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
51
dom/push/test/xpcshell/head-http2.js
Normal file
51
dom/push/test/xpcshell/head-http2.js
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
// Support for making sure we can talk to the invalid cert the server presents
|
||||
var CertOverrideListener = function(host, port, bits) {
|
||||
this.host = host;
|
||||
this.port = port || 443;
|
||||
this.bits = bits;
|
||||
};
|
||||
|
||||
CertOverrideListener.prototype = {
|
||||
host: null,
|
||||
bits: null,
|
||||
|
||||
getInterface: function(aIID) {
|
||||
return this.QueryInterface(aIID);
|
||||
},
|
||||
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Ci.nsIBadCertListener2) ||
|
||||
aIID.equals(Ci.nsIInterfaceRequestor) ||
|
||||
aIID.equals(Ci.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
notifyCertProblem: function(socketInfo, sslStatus, targetHost) {
|
||||
var cert = sslStatus.QueryInterface(Ci.nsISSLStatus).serverCert;
|
||||
var cos = Cc["@mozilla.org/security/certoverride;1"].
|
||||
getService(Ci.nsICertOverrideService);
|
||||
cos.rememberValidityOverride(this.host, this.port, cert, this.bits, false);
|
||||
dump("Certificate Override in place\n");
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
function addCertOverride(host, port, bits) {
|
||||
var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
try {
|
||||
var url;
|
||||
if (port && (port > 0) && (port !== 443)) {
|
||||
url = "https://" + host + ":" + port + "/";
|
||||
} else {
|
||||
url = "https://" + host + "/";
|
||||
}
|
||||
req.open("GET", url, false);
|
||||
req.channel.notificationCallbacks = new CertOverrideListener(host, port, bits);
|
||||
req.send(null);
|
||||
} catch (e) {
|
||||
// This will fail since the server is not trusted yet
|
||||
}
|
||||
}
|
@ -196,7 +196,10 @@ function setPrefs(prefs = {}) {
|
||||
'adaptive.gap': 60000,
|
||||
'adaptive.upperLimit': 29 * 60 * 1000,
|
||||
// Misc. defaults.
|
||||
'adaptive.mobile': ''
|
||||
'adaptive.mobile': '',
|
||||
'http2.maxRetries': 2,
|
||||
'http2.retryInterval': 500,
|
||||
'http2.reset_retry_count_after_ms': 60000
|
||||
}, prefs);
|
||||
for (let pref in defaultPrefs) {
|
||||
servicePrefs.set(pref, defaultPrefs[pref]);
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const channelID = 'db0a7021-ec2d-4bd3-8802-7a6966f10ed8';
|
||||
|
||||
@ -14,7 +14,7 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_unregister_success() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
yield db.put({
|
||||
channelID,
|
||||
@ -25,6 +25,7 @@ add_task(function* test_unregister_success() {
|
||||
|
||||
let unregisterDefer = Promise.defer();
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -41,6 +42,6 @@ add_task(function* test_unregister_success() {
|
||||
});
|
||||
|
||||
yield PushNotificationService.clearAll();
|
||||
let record = yield db.getByChannelID(channelID);
|
||||
let record = yield db.getByKeyID(channelID);
|
||||
ok(!record, 'Unregister did not remove record');
|
||||
});
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
let userAgentID = '5ab1d1df-7a3d-4024-a469-b9e1bb399fad';
|
||||
|
||||
@ -19,7 +19,7 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_notification_ack() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
let records = [{
|
||||
channelID: '21668e05-6da8-42c9-b8ab-9cc3f4d5630c',
|
||||
@ -50,6 +50,7 @@ add_task(function* test_notification_ack() {
|
||||
let acks = 0;
|
||||
let ackDefer = Promise.defer();
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
@ -17,7 +17,7 @@ function run_test() {
|
||||
|
||||
// Should acknowledge duplicate notifications, but not notify apps.
|
||||
add_task(function* test_notification_duplicate() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
let records = [{
|
||||
channelID: '8d2d9400-3597-4c5a-8a38-c546b0043bcc',
|
||||
@ -40,6 +40,7 @@ add_task(function* test_notification_duplicate() {
|
||||
let ackDefer = Promise.defer();
|
||||
let ackDone = after(2, ackDefer.resolve);
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -71,11 +72,11 @@ add_task(function* test_notification_duplicate() {
|
||||
yield waitForPromise(ackDefer.promise, DEFAULT_TIMEOUT,
|
||||
'Timed out waiting for stale acknowledgement');
|
||||
|
||||
let staleRecord = yield db.getByChannelID(
|
||||
let staleRecord = yield db.getByKeyID(
|
||||
'8d2d9400-3597-4c5a-8a38-c546b0043bcc');
|
||||
strictEqual(staleRecord.version, 2, 'Wrong stale record version');
|
||||
|
||||
let updatedRecord = yield db.getByChannelID(
|
||||
let updatedRecord = yield db.getByKeyID(
|
||||
'27d1e393-03ef-4c72-a5e6-9e890dfccad0');
|
||||
strictEqual(updatedRecord.version, 3, 'Wrong updated record version');
|
||||
});
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
@ -17,7 +17,7 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_notification_error() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
let records = [{
|
||||
channelID: 'f04f1e46-9139-4826-b2d1-9411b0821283',
|
||||
@ -53,9 +53,10 @@ add_task(function* test_notification_error() {
|
||||
let ackDefer = Promise.defer();
|
||||
let ackDone = after(records.length, ackDefer.resolve);
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db: makeStub(db, {
|
||||
getByChannelID(prev, channelID) {
|
||||
getByKeyID(prev, channelID) {
|
||||
if (channelID == '3c3930ba-44de-40dc-a7ca-8a133ec1a866') {
|
||||
return Promise.reject('splines not reticulated');
|
||||
}
|
||||
|
94
dom/push/test/xpcshell/test_notification_http2.js
Normal file
94
dom/push/test/xpcshell/test_notification_http2.js
Normal file
@ -0,0 +1,94 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
var prefs;
|
||||
var tlsProfile;
|
||||
|
||||
var serverPort = -1;
|
||||
|
||||
function run_test() {
|
||||
var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
serverPort = env.get("MOZHTTP2-PORT");
|
||||
do_check_neq(serverPort, null);
|
||||
dump("using port " + serverPort + "\n");
|
||||
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
|
||||
|
||||
// Set to allow the cert presented by our H2 server
|
||||
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
|
||||
|
||||
addCertOverride("localhost", serverPort,
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_TIME);
|
||||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page/1',
|
||||
'https://example.com/page/2',
|
||||
'https://example.com/page/3'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* test_pushNotifications() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
var serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
let records = [{
|
||||
subscriptionUri: serverURL + '/pushNotifications/subscription1',
|
||||
pushEndpoint: serverURL + '/pushEndpoint1',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint1',
|
||||
scope: 'https://example.com/page/1'
|
||||
}, {
|
||||
subscriptionUri: serverURL + '/pushNotifications/subscription2',
|
||||
pushEndpoint: serverURL + '/pushEndpoint2',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint2',
|
||||
scope: 'https://example.com/page/2'
|
||||
}, {
|
||||
subscriptionUri: serverURL + '/pushNotifications/subscription3',
|
||||
pushEndpoint: serverURL + '/pushEndpoint3',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint3',
|
||||
scope: 'https://example.com/page/3'
|
||||
}];
|
||||
|
||||
for (let record of records) {
|
||||
yield db.put(record);
|
||||
}
|
||||
|
||||
let notifyPromise = Promise.all([
|
||||
promiseObserverNotification('push-notification'),
|
||||
promiseObserverNotification('push-notification'),
|
||||
promiseObserverNotification('push-notification')
|
||||
]);
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL,
|
||||
db
|
||||
});
|
||||
|
||||
yield waitForPromise(notifyPromise, DEFAULT_TIMEOUT,
|
||||
'Timed out waiting for notifications');
|
||||
});
|
||||
|
||||
add_task(function* test_complete() {
|
||||
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlsProfile);
|
||||
});
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
@ -18,7 +18,7 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_notification_incomplete() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
let records = [{
|
||||
channelID: '123',
|
||||
@ -52,11 +52,12 @@ add_task(function* test_notification_incomplete() {
|
||||
let notificationDefer = Promise.defer();
|
||||
let notificationDone = after(2, notificationDefer.resolve);
|
||||
let prevHandler = PushService._handleNotificationReply;
|
||||
PushService._handleNotificationReply = function _handleNotificationReply() {
|
||||
PushServiceWebSocket._handleNotificationReply = function _handleNotificationReply() {
|
||||
notificationDone();
|
||||
return prevHandler.apply(this, arguments);
|
||||
};
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -101,7 +102,7 @@ add_task(function* test_notification_incomplete() {
|
||||
yield waitForPromise(notificationDefer.promise, DEFAULT_TIMEOUT,
|
||||
'Timed out waiting for incomplete notifications');
|
||||
|
||||
let storeRecords = yield db.getAllChannelIDs();
|
||||
let storeRecords = yield db.getAllKeyIDs();
|
||||
storeRecords.sort(({pushEndpoint: a}, {pushEndpoint: b}) =>
|
||||
compareAscending(a, b));
|
||||
recordsAreEqual(records, storeRecords);
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
@ -15,7 +15,7 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_notification_version_string() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
yield db.put({
|
||||
channelID: '6ff97d56-d0c0-43bc-8f5b-61b855e1d93b',
|
||||
@ -28,6 +28,7 @@ add_task(function* test_notification_version_string() {
|
||||
|
||||
let ackDefer = Promise.defer();
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -65,7 +66,7 @@ add_task(function* test_notification_version_string() {
|
||||
yield waitForPromise(ackDefer.promise, DEFAULT_TIMEOUT,
|
||||
'Timed out waiting for string acknowledgement');
|
||||
|
||||
let storeRecord = yield db.getByChannelID(
|
||||
let storeRecord = yield db.getByKeyID(
|
||||
'6ff97d56-d0c0-43bc-8f5b-61b855e1d93b');
|
||||
strictEqual(storeRecord.version, 4, 'Wrong record version');
|
||||
});
|
||||
|
114
dom/push/test/xpcshell/test_register_5xxCode_http2.js
Normal file
114
dom/push/test/xpcshell/test_register_5xxCode_http2.js
Normal file
@ -0,0 +1,114 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
var httpServer = null;
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "serverPort", function() {
|
||||
return httpServer.identity.primaryPort;
|
||||
});
|
||||
|
||||
var retries = 0
|
||||
|
||||
function subscribe5xxCodeHandler(metadata, response) {
|
||||
if (retries == 0) {
|
||||
ok(true, "Subscribe 5xx code");
|
||||
do_test_finished();
|
||||
response.setHeader("Retry-After", '1');
|
||||
response.setStatusLine(metadata.httpVersion, 500, "Retry");
|
||||
} else {
|
||||
ok(true, "Subscribed");
|
||||
do_test_finished();
|
||||
response.setHeader("Location",
|
||||
'http://localhost:' + serverPort + '/subscription')
|
||||
response.setHeader("Link",
|
||||
'</pushEndpoint>; rel="urn:ietf:params:push", ' +
|
||||
'</receiptPushEndpoint>; rel="urn:ietf:params:push:receipt"');
|
||||
response.setStatusLine(metadata.httpVersion, 201, "OK");
|
||||
}
|
||||
retries++;
|
||||
}
|
||||
|
||||
function listenSuccessHandler(metadata, response) {
|
||||
do_check_true(true, "New listener point");
|
||||
ok(retries == 2, "Should try 2 times.");
|
||||
do_test_finished();
|
||||
response.setHeader("Retry-After", '10');
|
||||
response.setStatusLine(metadata.httpVersion, 500, "Retry");
|
||||
}
|
||||
|
||||
|
||||
httpServer = new HttpServer();
|
||||
httpServer.registerPathHandler("/subscribe5xxCode", subscribe5xxCodeHandler);
|
||||
httpServer.registerPathHandler("/subscription", listenSuccessHandler);
|
||||
httpServer.start(-1);
|
||||
|
||||
function run_test() {
|
||||
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
'http2.retryInterval': 1000,
|
||||
'http2.maxRetries': 2
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/retry5xxCode'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* test1() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
|
||||
var serverURL = "http://localhost:" + httpServer.identity.primaryPort;
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/subscribe5xxCode",
|
||||
service: PushServiceHttp2,
|
||||
db
|
||||
});
|
||||
|
||||
let newRecord = yield PushNotificationService.register(
|
||||
'https://example.com/retry5xxCode'
|
||||
);
|
||||
|
||||
var subscriptionUri = serverURL + '/subscription';
|
||||
var pushEndpoint = serverURL + '/pushEndpoint';
|
||||
var pushReceiptEndpoint = serverURL + '/receiptPushEndpoint';
|
||||
equal(newRecord.subscriptionUri, subscriptionUri,
|
||||
'Wrong subscription ID in registration record');
|
||||
equal(newRecord.pushEndpoint, pushEndpoint,
|
||||
'Wrong push endpoint in registration record');
|
||||
|
||||
equal(newRecord.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in registration record');
|
||||
equal(newRecord.scope, 'https://example.com/retry5xxCode',
|
||||
'Wrong scope in registration record');
|
||||
|
||||
let record = yield db.getByKeyID(subscriptionUri);
|
||||
equal(record.subscriptionUri, subscriptionUri,
|
||||
'Wrong subscription ID in database record');
|
||||
equal(record.pushEndpoint, pushEndpoint,
|
||||
'Wrong push endpoint in database record');
|
||||
equal(record.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in database record');
|
||||
equal(record.scope, 'https://example.com/retry5xxCode',
|
||||
'Wrong scope in database record');
|
||||
|
||||
httpServer.stop(do_test_finished);
|
||||
});
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '1760b1f5-c3ba-40e3-9344-adef7c18ab12';
|
||||
|
||||
@ -17,10 +17,11 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_register_case() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -55,7 +56,7 @@ add_task(function* test_register_case() {
|
||||
equal(newRecord.scope, 'https://example.net/case',
|
||||
'Wrong scope in registration record');
|
||||
|
||||
let record = yield db.getByChannelID(newRecord.channelID);
|
||||
let record = yield db.getByKeyID(newRecord.channelID);
|
||||
equal(record.pushEndpoint, 'https://example.com/update/case',
|
||||
'Wrong push endpoint in database record');
|
||||
equal(record.scope, 'https://example.net/case',
|
||||
|
207
dom/push/test/xpcshell/test_register_error_http2.js
Normal file
207
dom/push/test/xpcshell/test_register_error_http2.js
Normal file
@ -0,0 +1,207 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
var prefs;
|
||||
var tlsProfile;
|
||||
var serverURL;
|
||||
|
||||
var serverPort = -1;
|
||||
|
||||
function run_test() {
|
||||
var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
serverPort = env.get("MOZHTTP2-PORT");
|
||||
do_check_neq(serverPort, null);
|
||||
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
|
||||
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.net/page/invalid-response'
|
||||
);
|
||||
|
||||
serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
// Connection will fail because of the certificates.
|
||||
add_task(function* test_pushSubscriptionNoConnection() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionNoConnection/subscribe",
|
||||
db
|
||||
});
|
||||
|
||||
yield rejects(
|
||||
PushNotificationService.register(
|
||||
'https://example.net/page/invalid-response'),
|
||||
function(error) {
|
||||
return error && error.includes("Error");
|
||||
},
|
||||
'Wrong error for not being able to establish connecion.'
|
||||
);
|
||||
|
||||
let record = yield db.getAllKeyIDs();
|
||||
ok(record.length === 0, "Should not store records when connection couldn't be established.");
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(function* test_TLS() {
|
||||
// Set to allow the cert presented by our H2 server
|
||||
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
|
||||
|
||||
addCertOverride("localhost", serverPort,
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_TIME);
|
||||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
});
|
||||
|
||||
add_task(function* test_pushSubscriptionMissingLocation() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionMissingLocation/subscribe",
|
||||
db
|
||||
});
|
||||
|
||||
yield rejects(
|
||||
PushNotificationService.register(
|
||||
'https://example.net/page/invalid-response'),
|
||||
function(error) {
|
||||
return error && error.includes("Return code 201, but the answer is bogus");
|
||||
},
|
||||
'Wrong error for the missing location header.'
|
||||
);
|
||||
|
||||
let record = yield db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when the location header is missing.');
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(function* test_pushSubscriptionMissingLink() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionMissingLink/subscribe",
|
||||
db
|
||||
});
|
||||
|
||||
yield rejects(
|
||||
PushNotificationService.register(
|
||||
'https://example.net/page/invalid-response'),
|
||||
function(error) {
|
||||
return error && error.includes("Return code 201, but the answer is bogus");
|
||||
},
|
||||
'Wrong error for the missing link header.'
|
||||
);
|
||||
|
||||
let record = yield db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when a link header is missing.');
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(function* test_pushSubscriptionMissingLink1() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionMissingLink1/subscribe",
|
||||
db
|
||||
});
|
||||
|
||||
yield rejects(
|
||||
PushNotificationService.register(
|
||||
'https://example.net/page/invalid-response'),
|
||||
function(error) {
|
||||
return error && error.includes("Return code 201, but the answer is bogus");
|
||||
},
|
||||
'Wrong error for the missing push endpoint.'
|
||||
);
|
||||
|
||||
let record = yield db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when the push endpoint is missing.');
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(function* test_pushSubscriptionLocationBogus() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionLocationBogus/subscribe",
|
||||
db
|
||||
});
|
||||
|
||||
yield rejects(
|
||||
PushNotificationService.register(
|
||||
'https://example.net/page/invalid-response'),
|
||||
function(error) {
|
||||
return error && error.includes("Return code 201, but URI is bogus.");
|
||||
},
|
||||
'Wrong error for the bogus location'
|
||||
);
|
||||
|
||||
let record = yield db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when location header is bogus.');
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(function* test_pushSubscriptionNot2xxCode() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionNot201Code/subscribe",
|
||||
db
|
||||
});
|
||||
|
||||
yield rejects(
|
||||
PushNotificationService.register(
|
||||
'https://example.net/page/invalid-response'),
|
||||
function(error) {
|
||||
return error && error.includes("Error");
|
||||
},
|
||||
'Wrong error for not 201 responce code.'
|
||||
);
|
||||
|
||||
let record = yield db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when respons code is not 201.');
|
||||
});
|
||||
|
||||
add_task(function* test_complete() {
|
||||
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlsProfile);
|
||||
});
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '9ce1e6d3-7bdb-4fe9-90a5-def1d64716f1';
|
||||
const channelID = 'c26892c5-6e08-4c16-9f0c-0044697b4d85';
|
||||
@ -23,7 +23,7 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_register_flush() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
let record = {
|
||||
channelID: '9bcc7efb-86c7-4457-93ea-e24e6eb59b74',
|
||||
@ -38,6 +38,7 @@ add_task(function* test_register_flush() {
|
||||
let ackDefer = Promise.defer();
|
||||
let ackDone = after(2, ackDefer.resolve);
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -88,14 +89,14 @@ add_task(function* test_register_flush() {
|
||||
yield waitForPromise(ackDefer.promise, DEFAULT_TIMEOUT,
|
||||
'Timed out waiting for acknowledgements');
|
||||
|
||||
let prevRecord = yield db.getByChannelID(
|
||||
let prevRecord = yield db.getByKeyID(
|
||||
'9bcc7efb-86c7-4457-93ea-e24e6eb59b74');
|
||||
equal(prevRecord.pushEndpoint, 'https://example.org/update/1',
|
||||
'Wrong existing push endpoint');
|
||||
strictEqual(prevRecord.version, 3,
|
||||
'Should record version updates sent before register responses');
|
||||
|
||||
let registeredRecord = yield db.getByChannelID(newRecord.channelID);
|
||||
let registeredRecord = yield db.getByKeyID(newRecord.channelID);
|
||||
equal(registeredRecord.pushEndpoint, 'https://example.org/update/2',
|
||||
'Wrong new push endpoint');
|
||||
ok(!registeredRecord.version, 'Should not record premature updates');
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '52b2b04c-b6cc-42c6-abdf-bef9cbdbea00';
|
||||
const channelID = 'cafed00d';
|
||||
@ -18,11 +18,12 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_register_invalid_channel() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
|
||||
PushService._generateID = () => channelID;
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -54,6 +55,6 @@ add_task(function* test_register_invalid_channel() {
|
||||
'Wrong error for invalid channel ID'
|
||||
);
|
||||
|
||||
let record = yield db.getByChannelID(channelID);
|
||||
let record = yield db.getByKeyID(channelID);
|
||||
ok(!record, 'Should not store records for error responses');
|
||||
});
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'c9a12e81-ea5e-40f9-8bf4-acee34621671';
|
||||
const channelID = 'c0660af8-b532-4931-81f0-9fd27a12d6ab';
|
||||
@ -18,11 +18,12 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_register_invalid_endpoint() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
|
||||
PushService._generateID = () => channelID;
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -51,11 +52,11 @@ add_task(function* test_register_invalid_endpoint() {
|
||||
PushNotificationService.register(
|
||||
'https://example.net/page/invalid-endpoint'),
|
||||
function(error) {
|
||||
return error && error.contains('Invalid pushEndpoint');
|
||||
return error && error.includes('Invalid pushEndpoint');
|
||||
},
|
||||
'Wrong error for invalid endpoint'
|
||||
);
|
||||
|
||||
let record = yield db.getByChannelID(channelID);
|
||||
let record = yield db.getByKeyID(channelID);
|
||||
ok(!record, 'Should not store records with invalid endpoints');
|
||||
});
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '8271186b-8073-43a3-adf6-225bd44a8b0a';
|
||||
const channelID = '2d08571e-feab-48a0-9f05-8254c3c7e61f';
|
||||
@ -25,8 +25,9 @@ add_task(function* test_register_invalid_json() {
|
||||
let helloDone = after(2, helloDefer.resolve);
|
||||
let registers = 0;
|
||||
|
||||
PushService._generateID = () => channelID;
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
let userAgentID = '9a2f9efe-2ebb-4bcb-a5d9-9e2b73d30afe';
|
||||
let channelID = '264c2ba0-f6db-4e84-acdb-bd225b62d9e3';
|
||||
@ -26,8 +26,9 @@ add_task(function* test_register_no_id() {
|
||||
let helloDefer = Promise.defer();
|
||||
let helloDone = after(2, helloDefer.resolve);
|
||||
|
||||
PushService._generateID = () => channelID;
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
@ -18,7 +18,7 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_register_request_queue() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
|
||||
let helloDefer = Promise.defer();
|
||||
@ -31,6 +31,7 @@ add_task(function* test_register_request_queue() {
|
||||
helloDefer.resolve();
|
||||
});
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'b2546987-4f63-49b1-99f7-739cd3c40e44';
|
||||
const channelID = '35a820f7-d7dd-43b3-af21-d65352212ae3';
|
||||
@ -22,14 +22,15 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_register_rollback() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
|
||||
let handshakes = 0;
|
||||
let registers = 0;
|
||||
let unregisterDefer = Promise.defer();
|
||||
PushService._generateID = () => channelID;
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db: makeStub(db, {
|
||||
put(prev, record) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'bd744428-f125-436a-b6d0-dd0c9845837f';
|
||||
const channelID = '0ef2ad4a-6c49-41ad-af6e-95d2425276bf';
|
||||
@ -22,11 +22,12 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_register_success() {
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
|
||||
PushService._generateID = () => channelID;
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -65,7 +66,7 @@ add_task(function* test_register_success() {
|
||||
equal(newRecord.scope, 'https://example.org/1',
|
||||
'Wrong scope in registration record');
|
||||
|
||||
let record = yield db.getByChannelID(channelID);
|
||||
let record = yield db.getByKeyID(channelID);
|
||||
equal(record.channelID, channelID,
|
||||
'Wrong channel ID in database record');
|
||||
equal(record.pushEndpoint, 'https://example.com/update/1',
|
||||
|
131
dom/push/test/xpcshell/test_register_success_http2.js
Normal file
131
dom/push/test/xpcshell/test_register_success_http2.js
Normal file
@ -0,0 +1,131 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
var prefs;
|
||||
var tlsProfile;
|
||||
var serverURL;
|
||||
var serverPort = -1;
|
||||
|
||||
function run_test() {
|
||||
var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
serverPort = env.get("MOZHTTP2-PORT");
|
||||
do_check_neq(serverPort, null);
|
||||
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
|
||||
|
||||
// Set to allow the cert presented by our H2 server
|
||||
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
|
||||
|
||||
addCertOverride("localhost", serverPort,
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_TIME);
|
||||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
|
||||
serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.org/1',
|
||||
'https://example.org/no_receiptEndpoint'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* test_pushSubscriptionSuccess() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionSuccess/subscribe",
|
||||
db
|
||||
});
|
||||
|
||||
let newRecord = yield PushNotificationService.register(
|
||||
'https://example.org/1'
|
||||
);
|
||||
|
||||
var subscriptionUri = serverURL + '/pushSubscriptionSuccesss';
|
||||
var pushEndpoint = serverURL + '/pushEndpointSuccess';
|
||||
var pushReceiptEndpoint = serverURL + '/receiptPushEndpointSuccess';
|
||||
equal(newRecord.subscriptionUri, subscriptionUri,
|
||||
'Wrong subscription ID in registration record');
|
||||
equal(newRecord.pushEndpoint, pushEndpoint,
|
||||
'Wrong push endpoint in registration record');
|
||||
|
||||
equal(newRecord.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in registration record');
|
||||
equal(newRecord.scope, 'https://example.org/1',
|
||||
'Wrong scope in registration record');
|
||||
|
||||
let record = yield db.getByKeyID(subscriptionUri);
|
||||
equal(record.subscriptionUri, subscriptionUri,
|
||||
'Wrong subscription ID in database record');
|
||||
equal(record.pushEndpoint, pushEndpoint,
|
||||
'Wrong push endpoint in database record');
|
||||
equal(record.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in database record');
|
||||
equal(record.scope, 'https://example.org/1',
|
||||
'Wrong scope in database record');
|
||||
|
||||
db.drop().then(PushService.uninit());
|
||||
});
|
||||
|
||||
add_task(function* test_pushSubscriptionMissingLink2() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
do_register_cleanup(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionMissingLink2/subscribe",
|
||||
db
|
||||
});
|
||||
|
||||
let newRecord = yield PushNotificationService.register(
|
||||
'https://example.org/no_receiptEndpoint'
|
||||
);
|
||||
|
||||
var subscriptionUri = serverURL + '/subscriptionMissingLink2';
|
||||
var pushEndpoint = serverURL + '/pushEndpointMissingLink2';
|
||||
var pushReceiptEndpoint = '';
|
||||
equal(newRecord.subscriptionUri, subscriptionUri,
|
||||
'Wrong subscription ID in registration record');
|
||||
equal(newRecord.pushEndpoint, pushEndpoint,
|
||||
'Wrong push endpoint in registration record');
|
||||
|
||||
equal(newRecord.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in registration record');
|
||||
equal(newRecord.scope, 'https://example.org/no_receiptEndpoint',
|
||||
'Wrong scope in registration record');
|
||||
|
||||
let record = yield db.getByKeyID(subscriptionUri);
|
||||
equal(record.subscriptionUri, subscriptionUri,
|
||||
'Wrong subscription ID in database record');
|
||||
equal(record.pushEndpoint, pushEndpoint,
|
||||
'Wrong push endpoint in database record');
|
||||
equal(record.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in database record');
|
||||
equal(record.scope, 'https://example.org/no_receiptEndpoint',
|
||||
'Wrong scope in database record');
|
||||
});
|
||||
|
||||
add_task(function* test_complete() {
|
||||
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlsProfile);
|
||||
});
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'a4be0df9-b16d-4b5f-8f58-0f93b6f1e23d';
|
||||
const channelID = 'e1944e0b-48df-45e7-bdc0-d1fbaa7986d3';
|
||||
@ -25,11 +25,12 @@ add_task(function* test_register_timeout() {
|
||||
let timeoutDefer = Promise.defer();
|
||||
let registers = 0;
|
||||
|
||||
let db = new PushDB();
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||
|
||||
PushService._generateID = () => channelID;
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
@ -89,7 +90,7 @@ add_task(function* test_register_timeout() {
|
||||
'Wrong error for request timeout'
|
||||
);
|
||||
|
||||
let record = yield db.getByChannelID(channelID);
|
||||
let record = yield db.getByKeyID(channelID);
|
||||
ok(!record, 'Should not store records for timed-out responses');
|
||||
|
||||
yield waitForPromise(
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '84afc774-6995-40d1-9c90-8c34ddcd0cb4';
|
||||
const clientChannelID = '4b42a681c99e4dfbbb166a7e01a09b8b';
|
||||
@ -28,8 +28,9 @@ add_task(function* test_register_wrong_id() {
|
||||
let helloDefer = Promise.defer();
|
||||
let helloDone = after(2, helloDefer.resolve);
|
||||
|
||||
PushService._generateID = () => clientChannelID;
|
||||
PushServiceWebSocket._generateID = () => clientChannelID;
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
|
@ -26,6 +26,7 @@ add_task(function* test_register_wrong_type() {
|
||||
|
||||
PushService._generateID = () => '1234';
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
networkInfo: new MockDesktopNetworkInfo(),
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user