Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-06-03 15:55:09 -04:00
commit 2b848889f8
452 changed files with 352458 additions and 4140 deletions

View File

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

View File

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

View File

@ -135,6 +135,9 @@
@RESPATH@/run-mozilla.sh
#endif
#endif
#ifdef MOZ_WEBSPEECH_MODELS
@BINPATH@/models/
#endif
; [Components]
@RESPATH@/components/components.manifest

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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',

View File

@ -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/"

View File

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

View File

@ -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'
},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,6 +21,6 @@ WebGLExtensionCompressedTextureATC::~WebGLExtensionCompressedTextureATC()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureATC)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureATC, WEBGL_compressed_texture_atc)
} // namespace mozilla

View File

@ -19,6 +19,6 @@ WebGLExtensionCompressedTextureETC1::~WebGLExtensionCompressedTextureETC1()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureETC1)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureETC1, WEBGL_compressed_texture_etc1)
} // namespace mozilla

View File

@ -22,6 +22,6 @@ WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTexturePVRTC)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTexturePVRTC, WEBGL_compressed_texture_pvrtc)
} // namespace mozilla

View File

@ -22,6 +22,6 @@ WebGLExtensionCompressedTextureS3TC::~WebGLExtensionCompressedTextureS3TC()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureS3TC)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureS3TC, WEBGL_compressed_texture_s3tc)
} // namespace mozilla

View File

@ -19,6 +19,6 @@ WebGLExtensionDebugRendererInfo::~WebGLExtensionDebugRendererInfo()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugRendererInfo)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugRendererInfo, WEBGL_debug_renderer_info)
} // namespace mozilla

View File

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

View File

@ -19,6 +19,6 @@ WebGLExtensionDepthTexture::~WebGLExtensionDepthTexture()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDepthTexture)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDepthTexture, WEBGL_depth_texture)
} // namespace mozilla

View File

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

View File

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

View File

@ -19,6 +19,6 @@ WebGLExtensionElementIndexUint::~WebGLExtensionElementIndexUint()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionElementIndexUint)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionElementIndexUint, OES_element_index_uint)
} // namespace mozilla

View File

@ -29,6 +29,6 @@ WebGLExtensionFragDepth::IsSupported(const WebGLContext* webgl)
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFragDepth)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFragDepth, EXT_frag_depth)
} // namespace mozilla

View File

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

View File

@ -31,6 +31,6 @@ WebGLExtensionLoseContext::RestoreContext()
mContext->RestoreContext();
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext, WEBGL_lose_context)
} // namespace mozilla

View File

@ -39,6 +39,6 @@ WebGLExtensionSRGB::IsSupported(const WebGLContext* webgl)
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionSRGB)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionSRGB, EXT_sRGB)
} // namespace mozilla

View File

@ -19,6 +19,6 @@ WebGLExtensionShaderTextureLod::~WebGLExtensionShaderTextureLod()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionShaderTextureLod)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionShaderTextureLod, EXT_shader_texture_lod)
} // namespace mozilla

View File

@ -19,6 +19,6 @@ WebGLExtensionStandardDerivatives::~WebGLExtensionStandardDerivatives()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionStandardDerivatives)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionStandardDerivatives, OES_standard_derivatives)
} // namespace mozilla

View File

@ -19,6 +19,6 @@ WebGLExtensionTextureFilterAnisotropic::~WebGLExtensionTextureFilterAnisotropic(
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFilterAnisotropic)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFilterAnisotropic, EXT_texture_filter_anisotropic)
} // namespace mozilla

View File

@ -18,6 +18,6 @@ WebGLExtensionTextureFloat::~WebGLExtensionTextureFloat()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloat)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloat, OES_texture_float)
} // namespace mozilla

View File

@ -18,6 +18,6 @@ WebGLExtensionTextureFloatLinear::~WebGLExtensionTextureFloatLinear()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloatLinear)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloatLinear, OES_texture_float_linear)
} // namespace mozilla

View File

@ -18,6 +18,6 @@ WebGLExtensionTextureHalfFloat::~WebGLExtensionTextureHalfFloat()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat, OES_texture_half_float)
} // namespace mozilla

View File

@ -18,6 +18,6 @@ WebGLExtensionTextureHalfFloatLinear::~WebGLExtensionTextureHalfFloatLinear()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloatLinear)
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloatLinear, OES_texture_half_float_linear)
} // namespace mozilla

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

File diff suppressed because it is too large Load Diff

View 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.

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
<s> SIL
</s> SIL
<sil> SIL
[NOISE] +NSN+
[SPEECH] +SPN+

View File

@ -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',
]

View File

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

View File

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

View 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
};
}
};

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,10 @@ EXTRA_COMPONENTS += [
]
EXTRA_PP_JS_MODULES += [
'PushDB.jsm',
'PushService.jsm',
'PushServiceHttp2.jsm',
'PushServiceWebSocket.jsm',
]
MOCHITEST_MANIFESTS += [

View File

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

View 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>

View File

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

View 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>

View 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
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View 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);
});

View File

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

View File

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

View 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);
});

View File

@ -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',

View 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);
});

View File

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

View File

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

View File

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

View File

@ -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, {

View File

@ -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, {

View File

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

View File

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

View File

@ -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',

View 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);
});

View File

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

View File

@ -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, {

View File

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