Exemplo n.º 1
0
/**
 * GetEncodedData() runs as a state machine, starting with mState set to
 * GET_METADDATA, the procedure should be as follow:
 *
 * While non-stop
 *   If mState is GET_METADDATA
 *     Get the meta data from audio/video encoder
 *     If a meta data is generated
 *       Get meta data from audio/video encoder
 *       Set mState to ENCODE_TRACK
 *       Return the final container data
 *
 *   If mState is ENCODE_TRACK
 *     Get encoded track data from audio/video encoder
 *     If a packet of track data is generated
 *       Insert encoded track data into the container stream of writer
 *       If the final container data is copied to aOutput
 *         Return the copy of final container data
 *       If this is the last packet of input stream
 *         Set mState to ENCODE_DONE
 *
 *   If mState is ENCODE_DONE or ENCODE_ERROR
 *     Stop the loop
 */
void
MediaEncoder::GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
                             nsAString& aMIMEType)
{
  MOZ_ASSERT(!NS_IsMainThread());

  aMIMEType = mMIMEType;
  PROFILER_LABEL("MediaEncoder", "GetEncodedData",
    js::ProfileEntry::Category::OTHER);

  bool reloop = true;
  while (reloop) {
    switch (mState) {
    case ENCODE_METADDATA: {
      LOG(LogLevel::Debug, ("ENCODE_METADDATA TimeStamp = %f", GetEncodeTimeStamp()));
      nsresult rv = CopyMetadataToMuxer(mAudioEncoder.get());
      if (NS_FAILED(rv)) {
        LOG(LogLevel::Error, ("Error! Fail to Set Audio Metadata"));
        break;
      }
      rv = CopyMetadataToMuxer(mVideoEncoder.get());
      if (NS_FAILED(rv)) {
        LOG(LogLevel::Error, ("Error! Fail to Set Video Metadata"));
        break;
      }

      rv = mWriter->GetContainerData(aOutputBufs,
                                     ContainerWriter::GET_HEADER);
      if (aOutputBufs != nullptr) {
        mSizeOfBuffer = aOutputBufs->ShallowSizeOfExcludingThis(MallocSizeOf);
      }
      if (NS_FAILED(rv)) {
       LOG(LogLevel::Error,("Error! writer fail to generate header!"));
       mState = ENCODE_ERROR;
       break;
      }
      LOG(LogLevel::Debug, ("Finish ENCODE_METADDATA TimeStamp = %f", GetEncodeTimeStamp()));
      mState = ENCODE_TRACK;
      break;
    }

    case ENCODE_TRACK: {
      LOG(LogLevel::Debug, ("ENCODE_TRACK TimeStamp = %f", GetEncodeTimeStamp()));
      EncodedFrameContainer encodedData;
      nsresult rv = NS_OK;
      rv = WriteEncodedDataToMuxer(mAudioEncoder.get());
      if (NS_FAILED(rv)) {
        LOG(LogLevel::Error, ("Error! Fail to write audio encoder data to muxer"));
        break;
      }
      LOG(LogLevel::Debug, ("Audio encoded TimeStamp = %f", GetEncodeTimeStamp()));
      rv = WriteEncodedDataToMuxer(mVideoEncoder.get());
      if (NS_FAILED(rv)) {
        LOG(LogLevel::Error, ("Fail to write video encoder data to muxer"));
        break;
      }
      LOG(LogLevel::Debug, ("Video encoded TimeStamp = %f", GetEncodeTimeStamp()));
      // In audio only or video only case, let unavailable track's flag to be true.
      bool isAudioCompleted = (mAudioEncoder && mAudioEncoder->IsEncodingComplete()) || !mAudioEncoder;
      bool isVideoCompleted = (mVideoEncoder && mVideoEncoder->IsEncodingComplete()) || !mVideoEncoder;
      rv = mWriter->GetContainerData(aOutputBufs,
                                     isAudioCompleted && isVideoCompleted ?
                                     ContainerWriter::FLUSH_NEEDED : 0);
      if (aOutputBufs != nullptr) {
        mSizeOfBuffer = aOutputBufs->ShallowSizeOfExcludingThis(MallocSizeOf);
      }
      if (NS_SUCCEEDED(rv)) {
        // Successfully get the copy of final container data from writer.
        reloop = false;
      }
      mState = (mWriter->IsWritingComplete()) ? ENCODE_DONE : ENCODE_TRACK;
      LOG(LogLevel::Debug, ("END ENCODE_TRACK TimeStamp = %f "
          "mState = %d aComplete %d vComplete %d",
          GetEncodeTimeStamp(), mState, isAudioCompleted, isVideoCompleted));
      break;
    }

    case ENCODE_DONE:
    case ENCODE_ERROR:
      LOG(LogLevel::Debug, ("MediaEncoder has been shutdown."));
      mSizeOfBuffer = 0;
      mShutdown = true;
      reloop = false;
      break;
    default:
      MOZ_CRASH("Invalid encode state");
    }
  }
}
Exemplo n.º 2
0
bool
GLLibraryEGL::EnsureInitialized()
{
    if (mInitialized) {
        return true;
    }

    mozilla::ScopedGfxFeatureReporter reporter("EGL");

#ifdef MOZ_B2G
    if (!sCurrentContext.init())
      MOZ_CRASH("Tls init failed");
#endif

#ifdef XP_WIN
    if (!mEGLLibrary) {
        // On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul and
        // we should look for them there. We have to load the libs in this
        // order, because libEGL.dll depends on libGLESv2.dll which depends on the DXSDK
        // libraries. This matters especially for WebRT apps which are in a different directory.
        // See bug 760323 and bug 749459

        // Also note that we intentionally leak the libs we load.

        do {
            // Windows 8.1 has d3dcompiler_47.dll in the system directory.
            // Try it first. Note that _46 will never be in the system
            // directory and we ship with at least _43. So there is no point
            // trying _46 and _43 in the system directory.

            if (LoadLibrarySystem32(L"d3dcompiler_47.dll"))
                break;

#ifdef MOZ_D3DCOMPILER_VISTA_DLL
            if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL))))
                break;
#endif

#ifdef MOZ_D3DCOMPILER_XP_DLL
            if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_XP_DLL))))
                break;
#endif

            MOZ_ASSERT(false, "d3dcompiler DLL loading failed.");
        } while (false);

        LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll"));

        mEGLLibrary = LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll"));

        if (!mEGLLibrary)
            return false;
    }

#else // !Windows

    // On non-Windows (Android) we use system copies of libEGL. We look for
    // the APITrace lib, libEGL.so, and libEGL.so.1 in that order.

#if defined(ANDROID)
    if (!mEGLLibrary)
        mEGLLibrary = LoadApitraceLibrary();
#endif

    if (!mEGLLibrary) {
        printf_stderr("Attempting load of libEGL.so\n");
        mEGLLibrary = PR_LoadLibrary("libEGL.so");
    }
#if defined(XP_UNIX)
    if (!mEGLLibrary) {
        mEGLLibrary = PR_LoadLibrary("libEGL.so.1");
    }
#endif

    if (!mEGLLibrary) {
        NS_WARNING("Couldn't load EGL LIB.");
        return false;
    }

#endif // !Windows

#define SYMBOL(name) \
{ (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, nullptr } }

    GLLibraryLoader::SymLoadStruct earlySymbols[] = {
        SYMBOL(GetDisplay),
        SYMBOL(Terminate),
        SYMBOL(GetCurrentSurface),
        SYMBOL(GetCurrentContext),
        SYMBOL(MakeCurrent),
        SYMBOL(DestroyContext),
        SYMBOL(CreateContext),
        SYMBOL(DestroySurface),
        SYMBOL(CreateWindowSurface),
        SYMBOL(CreatePbufferSurface),
        SYMBOL(CreatePixmapSurface),
        SYMBOL(BindAPI),
        SYMBOL(Initialize),
        SYMBOL(ChooseConfig),
        SYMBOL(GetError),
        SYMBOL(GetConfigs),
        SYMBOL(GetConfigAttrib),
        SYMBOL(WaitNative),
        SYMBOL(GetProcAddress),
        SYMBOL(SwapBuffers),
        SYMBOL(CopyBuffers),
        SYMBOL(QueryString),
        SYMBOL(QueryContext),
        SYMBOL(BindTexImage),
        SYMBOL(ReleaseTexImage),
        SYMBOL(QuerySurface),
        { nullptr, { nullptr } }
    };

    if (!GLLibraryLoader::LoadSymbols(mEGLLibrary, &earlySymbols[0])) {
        NS_WARNING("Couldn't find required entry points in EGL library (early init)");
        return false;
    }

    GLLibraryLoader::SymLoadStruct optionalSymbols[] = {
        // On Android 4.3 and up, certain features like ANDROID_native_fence_sync
        // can only be queried by using a special eglQueryString.
        { (PRFuncPtr*) &mSymbols.fQueryStringImplementationANDROID,
          { "_Z35eglQueryStringImplementationANDROIDPvi", nullptr } },
        { nullptr, { nullptr } }
    };

    // Do not warn about the failure to load this - see bug 1092191
    GLLibraryLoader::LoadSymbols(mEGLLibrary, &optionalSymbols[0], nullptr, nullptr,
                                 false);

#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
    MOZ_RELEASE_ASSERT(mSymbols.fQueryStringImplementationANDROID,
                       "Couldn't find eglQueryStringImplementationANDROID");
#endif

    mEGLDisplay = GetAndInitDisplay(*this, EGL_DEFAULT_DISPLAY);

    const char* vendor = (char*)fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
    if (vendor && (strstr(vendor, "TransGaming") != 0 ||
                   strstr(vendor, "Google Inc.") != 0))
    {
        mIsANGLE = true;
    }

    if (mIsANGLE) {
        EGLDisplay newDisplay = EGL_NO_DISPLAY;

        // D3D11 ANGLE only works with OMTC; there's a bug in the non-OMTC layer
        // manager, and it's pointless to try to fix it.  We also don't try
        // D3D11 ANGLE if the layer manager is prefering D3D9 (hrm, do we care?)
        if (gfxPrefs::LayersOffMainThreadCompositionEnabled() &&
            !gfxPrefs::LayersPreferD3D9())
        {
            if (gfxPrefs::WebGLANGLEForceD3D11()) {
                newDisplay = GetAndInitDisplay(*this,
                                               LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
            } else if (gfxPrefs::WebGLANGLETryD3D11() && gfxPlatform::CanUseDirect3D11ANGLE()) {
                newDisplay = GetAndInitDisplay(*this,
                                               LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE);
            }
        }

        if (newDisplay != EGL_NO_DISPLAY) {
            DebugOnly<EGLBoolean> success = fTerminate(mEGLDisplay);
            MOZ_ASSERT(success == LOCAL_EGL_TRUE);

            mEGLDisplay = newDisplay;

            vendor = (char*)fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
        }
    }

    InitExtensions();

    GLLibraryLoader::PlatformLookupFunction lookupFunction =
            (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;

    if (IsExtensionSupported(KHR_lock_surface)) {
        GLLibraryLoader::SymLoadStruct lockSymbols[] = {
            { (PRFuncPtr*) &mSymbols.fLockSurface,   { "eglLockSurfaceKHR",   nullptr } },
            { (PRFuncPtr*) &mSymbols.fUnlockSurface, { "eglUnlockSurfaceKHR", nullptr } },
            { nullptr, { nullptr } }
        };

        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
                                                    &lockSymbols[0],
                                                    lookupFunction);
        if (!success) {
            NS_ERROR("EGL supports KHR_lock_surface without exposing its functions!");

            MarkExtensionUnsupported(KHR_lock_surface);

            mSymbols.fLockSurface = nullptr;
            mSymbols.fUnlockSurface = nullptr;
        }
    }

    if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle)) {
        GLLibraryLoader::SymLoadStruct d3dSymbols[] = {
            { (PRFuncPtr*) &mSymbols.fQuerySurfacePointerANGLE, { "eglQuerySurfacePointerANGLE", nullptr } },
            { nullptr, { nullptr } }
        };

        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
                                                    &d3dSymbols[0],
                                                    lookupFunction);
        if (!success) {
            NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!");

            MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle);

            mSymbols.fQuerySurfacePointerANGLE = nullptr;
        }
    }

    //XXX: use correct extension name
    if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle)) {
        GLLibraryLoader::SymLoadStruct d3dSymbols[] = {
            { (PRFuncPtr*)&mSymbols.fSurfaceReleaseSyncANGLE, { "eglSurfaceReleaseSyncANGLE", nullptr } },
            { nullptr, { nullptr } }
        };

        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
                                                    &d3dSymbols[0],
                                                    lookupFunction);
        if (!success) {
            NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!");

            MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle);

            mSymbols.fSurfaceReleaseSyncANGLE = nullptr;
        }
    }

    if (IsExtensionSupported(KHR_fence_sync)) {
        GLLibraryLoader::SymLoadStruct syncSymbols[] = {
            { (PRFuncPtr*) &mSymbols.fCreateSync,     { "eglCreateSyncKHR",     nullptr } },
            { (PRFuncPtr*) &mSymbols.fDestroySync,    { "eglDestroySyncKHR",    nullptr } },
            { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "eglClientWaitSyncKHR", nullptr } },
            { (PRFuncPtr*) &mSymbols.fGetSyncAttrib,  { "eglGetSyncAttribKHR",  nullptr } },
            { nullptr, { nullptr } }
        };

        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
                                                    &syncSymbols[0],
                                                    lookupFunction);
        if (!success) {
            NS_ERROR("EGL supports KHR_fence_sync without exposing its functions!");

            MarkExtensionUnsupported(KHR_fence_sync);

            mSymbols.fCreateSync = nullptr;
            mSymbols.fDestroySync = nullptr;
            mSymbols.fClientWaitSync = nullptr;
            mSymbols.fGetSyncAttrib = nullptr;
        }
    }

    if (IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base)) {
        GLLibraryLoader::SymLoadStruct imageSymbols[] = {
            { (PRFuncPtr*) &mSymbols.fCreateImage,  { "eglCreateImageKHR",  nullptr } },
            { (PRFuncPtr*) &mSymbols.fDestroyImage, { "eglDestroyImageKHR", nullptr } },
            { nullptr, { nullptr } }
        };

        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
                                                    &imageSymbols[0],
                                                    lookupFunction);
        if (!success) {
            NS_ERROR("EGL supports KHR_image(_base) without exposing its functions!");

            MarkExtensionUnsupported(KHR_image);
            MarkExtensionUnsupported(KHR_image_base);
            MarkExtensionUnsupported(KHR_image_pixmap);

            mSymbols.fCreateImage = nullptr;
            mSymbols.fDestroyImage = nullptr;
        }
    } else {
        MarkExtensionUnsupported(KHR_image_pixmap);
    }

    if (IsExtensionSupported(ANDROID_native_fence_sync)) {
        GLLibraryLoader::SymLoadStruct nativeFenceSymbols[] = {
            { (PRFuncPtr*) &mSymbols.fDupNativeFenceFDANDROID, { "eglDupNativeFenceFDANDROID", nullptr } },
            { nullptr, { nullptr } }
        };

        bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
                                                    &nativeFenceSymbols[0],
                                                    lookupFunction);
        if (!success) {
            NS_ERROR("EGL supports ANDROID_native_fence_sync without exposing its functions!");

            MarkExtensionUnsupported(ANDROID_native_fence_sync);

            mSymbols.fDupNativeFenceFDANDROID = nullptr;
        }
    }

    mInitialized = true;
    reporter.SetSuccessful();
    return true;
}
Exemplo n.º 3
0
 // We should never write to the fanotify fd.
 virtual void OnFileCanWriteWithoutBlocking(int aFd)
 {
     MOZ_CRASH("Must not write to fanotify fd");
 }
Exemplo n.º 4
0
void
CanvasLayerD3D10::UpdateSurface()
{
  if (!IsDirty())
    return;
  Painted();
  if (mDrawTarget) {
    mDrawTarget->Flush();
  } else if (mIsD2DTexture) {
    return;
  }
  if (!mTexture) {
    return;
  }

  if (mGLContext) {
    SharedSurface_GL* surf = mGLContext->RequestFrame();
    if (!surf) {
      return;
    }
    switch (surf->Type()) {
      case SharedSurfaceType::EGLSurfaceANGLE: {
        SharedSurface_ANGLEShareHandle* shareSurf = SharedSurface_ANGLEShareHandle::Cast(surf);
        mSRView = shareSurf->GetSRV();
        return;
      }
      case SharedSurfaceType::Basic: {
        SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf);
        // WebGL reads entire surface.
        D3D10_MAPPED_TEXTURE2D map;

        HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);

        if (FAILED(hr)) {
          NS_WARNING("Failed to map CanvasLayer texture.");
          return;
        }

        DataSourceSurface* frameData = shareSurf->GetData();
        // Scope for DrawTarget, so it's destroyed before Unmap.
        {
          IntSize boundsSize(mBounds.width, mBounds.height);
          RefPtr<DrawTarget> mapDt = Factory::CreateDrawTargetForData(BackendType::CAIRO,
                                                                      (uint8_t*)map.pData,
                                                                      boundsSize,
                                                                      map.RowPitch,
                                                                      SurfaceFormat::B8G8R8A8);

          Rect drawRect(0, 0, frameData->GetSize().width, frameData->GetSize().height);
          mapDt->DrawSurface(frameData, drawRect, drawRect,
                             DrawSurfaceOptions(),  DrawOptions(1.0F, CompositionOp::OP_SOURCE));
          mapDt->Flush();
        }

        mTexture->Unmap(0);
        mSRView = mUploadSRView;
        break;
      }

      default:
        MOZ_CRASH("Unhandled SharedSurfaceType.");
    }
  } else if (mSurface) {
    D3D10_MAPPED_TEXTURE2D map;
    HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);

    if (FAILED(hr)) {
      NS_WARNING("Failed to lock CanvasLayer texture.");
      return;
    }

    RefPtr<DrawTarget> destTarget =
      Factory::CreateDrawTargetForD3D10Texture(mTexture,
                                               SurfaceFormat::R8G8B8A8);
    Rect r(Point(0, 0), ToRect(mBounds).Size());
    destTarget->DrawSurface(mSurface, r, r, DrawSurfaceOptions(),
                            DrawOptions(1.0F, CompositionOp::OP_SOURCE));

    mTexture->Unmap(0);
    mSRView = mUploadSRView;
  }
}
Exemplo n.º 5
0
bool
StreamTextureSourceOGL::RetrieveTextureFromStream()
{
    gl()->MakeCurrent();

    SharedSurface* sharedSurf = mStream->SwapConsumer();
    if (!sharedSurf) {
        // We don't have a valid surf to show yet.
        return false;
    }

    gl()->MakeCurrent();

    mSize = IntSize(sharedSurf->Size().width, sharedSurf->Size().height);

    DataSourceSurface* toUpload = nullptr;
    switch (sharedSurf->Type()) {
    case SharedSurfaceType::GLTextureShare: {
        SharedSurface_GLTexture* glTexSurf = SharedSurface_GLTexture::Cast(sharedSurf);
        mTextureHandle = glTexSurf->ConsTexture(gl());
        mTextureTarget = glTexSurf->ConsTextureTarget();
        MOZ_ASSERT(mTextureHandle);
        mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
                  : SurfaceFormat::R8G8B8X8;
        break;
    }
    case SharedSurfaceType::EGLImageShare: {
        SharedSurface_EGLImage* eglImageSurf =
            SharedSurface_EGLImage::Cast(sharedSurf);

        eglImageSurf->AcquireConsumerTexture(gl(), &mTextureHandle, &mTextureTarget);
        MOZ_ASSERT(mTextureHandle);
        mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
                  : SurfaceFormat::R8G8B8X8;
        break;
    }
#ifdef XP_MACOSX
    case SharedSurfaceType::IOSurface: {
        SharedSurface_IOSurface* glTexSurf = SharedSurface_IOSurface::Cast(sharedSurf);
        mTextureHandle = glTexSurf->ConsTexture(gl());
        mTextureTarget = glTexSurf->ConsTextureTarget();
        MOZ_ASSERT(mTextureHandle);
        mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8
                  : SurfaceFormat::R8G8B8X8;
        break;
    }
#endif
    case SharedSurfaceType::Basic: {
        toUpload = SharedSurface_Basic::Cast(sharedSurf)->GetData();
        MOZ_ASSERT(toUpload);
        break;
    }
    default:
        MOZ_CRASH("Invalid SharedSurface type.");
    }

    if (toUpload) {
        // mBounds seems to end up as (0,0,0,0) a lot, so don't use it?
        nsIntSize size(ThebesIntSize(toUpload->GetSize()));
        nsIntRect rect(nsIntPoint(0,0), size);
        nsIntRegion bounds(rect);
        mFormat = UploadSurfaceToTexture(gl(),
                                         toUpload,
                                         bounds,
                                         mUploadTexture,
                                         true);
        mTextureHandle = mUploadTexture;
        mTextureTarget = LOCAL_GL_TEXTURE_2D;
    }

    MOZ_ASSERT(mTextureHandle);
    gl()->fBindTexture(mTextureTarget, mTextureHandle);
    gl()->fTexParameteri(mTextureTarget,
                         LOCAL_GL_TEXTURE_WRAP_S,
                         LOCAL_GL_CLAMP_TO_EDGE);
    gl()->fTexParameteri(mTextureTarget,
                         LOCAL_GL_TEXTURE_WRAP_T,
                         LOCAL_GL_CLAMP_TO_EDGE);

    ClearCachedFilter();

    return true;
}
Exemplo n.º 6
0
uint32_t MozBaseAssembler::PlaceConstantPoolBarrier(int offset) {
  MOZ_CRASH("PlaceConstantPoolBarrier");
}
Exemplo n.º 7
0
TimeStamp
OfflineClockDriver::GetCurrentTimeStamp()
{
  MOZ_CRASH("This driver does not support getting the current timestamp.");
  return TimeStamp();
}
Exemplo n.º 8
0
void
OriginAttributes::CreateSuffix(nsACString& aStr) const
{
  UniquePtr<URLParams> params(new URLParams());
  nsAutoString value;

  //
  // Important: While serializing any string-valued attributes, perform a
  // release-mode assertion to make sure that they don't contain characters that
  // will break the quota manager when it uses the serialization for file
  // naming (see addonId below).
  //

  if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
    value.AppendInt(mAppId);
    params->Set(NS_LITERAL_STRING("appId"), value);
  }

  if (mInIsolatedMozBrowser) {
    params->Set(NS_LITERAL_STRING("inBrowser"), NS_LITERAL_STRING("1"));
  }

  if (!mAddonId.IsEmpty()) {
    if (mAddonId.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) != kNotFound) {
#ifdef MOZ_CRASHREPORTER
      CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Crash_AddonId"),
                                         NS_ConvertUTF16toUTF8(mAddonId));
#endif
      MOZ_CRASH();
    }
    params->Set(NS_LITERAL_STRING("addonId"), mAddonId);
  }

  if (mUserContextId != nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) {
    value.Truncate();
    value.AppendInt(mUserContextId);
    params->Set(NS_LITERAL_STRING("userContextId"), value);
  }

  if (!mSignedPkg.IsEmpty()) {
    MOZ_RELEASE_ASSERT(mSignedPkg.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
    params->Set(NS_LITERAL_STRING("signedPkg"), mSignedPkg);
  }

  if (mPrivateBrowsingId) {
    value.Truncate();
    value.AppendInt(mPrivateBrowsingId);
    params->Set(NS_LITERAL_STRING("privateBrowsingId"), value);
  }

  if (!mFirstPartyDomain.IsEmpty()) {
    MOZ_RELEASE_ASSERT(mFirstPartyDomain.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
    params->Set(NS_LITERAL_STRING("firstPartyDomain"), mFirstPartyDomain);
  }

  aStr.Truncate();

  params->Serialize(value);
  if (!value.IsEmpty()) {
    aStr.AppendLiteral("^");
    aStr.Append(NS_ConvertUTF16toUTF8(value));
  }

// In debug builds, check the whole string for illegal characters too (just in case).
#ifdef DEBUG
  nsAutoCString str;
  str.Assign(aStr);
  MOZ_ASSERT(str.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
#endif
}
Exemplo n.º 9
0
nsresult
GetDirectoryListingTaskParent::IOWork()
{
  MOZ_ASSERT(XRE_IsParentProcess(),
             "Only call from parent process!");
  MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");

  if (mFileSystem->IsShutdown()) {
    return NS_ERROR_FAILURE;
  }

  bool exists;
  nsresult rv = mTargetPath->Exists(&exists);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (!exists) {
    if (!mFileSystem->ShouldCreateDirectory()) {
      return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
    }

    rv = mTargetPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }
  }

  // Get isDirectory.
  bool isDir;
  rv = mTargetPath->IsDirectory(&isDir);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (!isDir) {
    return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
  }

  nsCOMPtr<nsISimpleEnumerator> entries;
  rv = mTargetPath->GetDirectoryEntries(getter_AddRefs(entries));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  bool filterOutSensitive = false;
  {
    HTMLSplitOnSpacesTokenizer tokenizer(mFilters, ';');
    nsAutoString token;
    while (tokenizer.hasMoreTokens()) {
      token = tokenizer.nextToken();
      if (token.EqualsLiteral("filter-out-sensitive")) {
        filterOutSensitive = true;
      } else {
        MOZ_CRASH("Unrecognized filter");
      }
    }
  }

  for (;;) {
    bool hasMore = false;
    if (NS_WARN_IF(NS_FAILED(entries->HasMoreElements(&hasMore))) || !hasMore) {
      break;
    }
    nsCOMPtr<nsISupports> supp;
    if (NS_WARN_IF(NS_FAILED(entries->GetNext(getter_AddRefs(supp))))) {
      break;
    }

    nsCOMPtr<nsIFile> currFile = do_QueryInterface(supp);
    MOZ_ASSERT(currFile);

    bool isLink, isSpecial, isFile;
    if (NS_WARN_IF(NS_FAILED(currFile->IsSymlink(&isLink)) ||
                   NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
        isLink || isSpecial) {
      continue;
    }
    if (NS_WARN_IF(NS_FAILED(currFile->IsFile(&isFile)) ||
                   NS_FAILED(currFile->IsDirectory(&isDir))) ||
        !(isFile || isDir)) {
      continue;
    }

    if (filterOutSensitive) {
      bool isHidden;
      if (NS_WARN_IF(NS_FAILED(currFile->IsHidden(&isHidden))) || isHidden) {
        continue;
      }
      nsAutoString leafName;
      if (NS_WARN_IF(NS_FAILED(currFile->GetLeafName(leafName)))) {
        continue;
      }
      if (leafName[0] == char16_t('.')) {
        continue;
      }
    }

    nsAutoString path;
    if (NS_WARN_IF(NS_FAILED(currFile->GetPath(path)))) {
      continue;
    }

    Directory::FileOrDirectoryPath element;
    element.mPath = path;
    element.mType = isDir ? Directory::FileOrDirectoryPath::eDirectoryPath
                          : Directory::FileOrDirectoryPath::eFilePath;

    if (!mTargetData.AppendElement(element, fallible)) {
      return NS_ERROR_OUT_OF_MEMORY;
    }
  }
  return NS_OK;
}
bool
BluetoothServiceChildProcess::UpdateSdpRecords(const nsAString& aDeviceAddress,
                                               BluetoothProfileManagerBase* aManager)
{
  MOZ_CRASH("This should never be called!");
}
nsresult
BluetoothServiceChildProcess::SendInputMessage(const nsAString& aDeviceAddresses,
                                               const nsAString& aMessage)
{
  MOZ_CRASH("This should never be called!");
}
Exemplo n.º 12
0
bool
ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
{
    // Guard that R0 is an integer and R1 is an integer.
    Label failure;
    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);

    Label revertRegister, maybeNegZero;
    switch(op_) {
    case JSOP_ADD:
        masm.unboxInt32(R0, ExtractTemp0);
        // Just jump to failure on overflow. R0 and R1 are preserved, so we can just jump to
        // the next stub.
        masm.addl(R1.valueReg(), ExtractTemp0);
        masm.j(Assembler::Overflow, &failure);

        // Box the result
        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
        break;
    case JSOP_SUB:
        masm.unboxInt32(R0, ExtractTemp0);
        masm.subl(R1.valueReg(), ExtractTemp0);
        masm.j(Assembler::Overflow, &failure);
        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
        break;
    case JSOP_MUL:
        masm.unboxInt32(R0, ExtractTemp0);
        masm.imull(R1.valueReg(), ExtractTemp0);
        masm.j(Assembler::Overflow, &failure);

        masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &maybeNegZero);

        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
        break;
    case JSOP_DIV:
    {
        MOZ_ASSERT(R2.scratchReg() == rax);
        MOZ_ASSERT(R0.valueReg() != rdx);
        MOZ_ASSERT(R1.valueReg() != rdx);
        masm.unboxInt32(R0, eax);
        masm.unboxInt32(R1, ExtractTemp0);

        // Prevent division by 0.
        masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);

        // Prevent negative 0 and -2147483648 / -1.
        masm.branch32(Assembler::Equal, eax, Imm32(INT32_MIN), &failure);

        Label notZero;
        masm.branch32(Assembler::NotEqual, eax, Imm32(0), &notZero);
        masm.branchTest32(Assembler::Signed, ExtractTemp0, ExtractTemp0, &failure);
        masm.bind(&notZero);

        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
        masm.cdq();
        masm.idiv(ExtractTemp0);

        // A remainder implies a double result.
        masm.branchTest32(Assembler::NonZero, edx, edx, &failure);

        masm.boxValue(JSVAL_TYPE_INT32, eax, R0.valueReg());
        break;
    }
    case JSOP_MOD:
    {
        MOZ_ASSERT(R2.scratchReg() == rax);
        MOZ_ASSERT(R0.valueReg() != rdx);
        MOZ_ASSERT(R1.valueReg() != rdx);
        masm.unboxInt32(R0, eax);
        masm.unboxInt32(R1, ExtractTemp0);

        // x % 0 always results in NaN.
        masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);

        // Prevent negative 0 and -2147483648 % -1.
        masm.branchTest32(Assembler::Zero, eax, Imm32(0x7fffffff), &failure);

        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
        masm.cdq();
        masm.idiv(ExtractTemp0);

        // Fail when we would need a negative remainder.
        Label done;
        masm.branchTest32(Assembler::NonZero, edx, edx, &done);
        masm.orl(ExtractTemp0, eax);
        masm.branchTest32(Assembler::Signed, eax, eax, &failure);

        masm.bind(&done);
        masm.boxValue(JSVAL_TYPE_INT32, edx, R0.valueReg());
        break;
    }
    case JSOP_BITOR:
        // We can overide R0, because the instruction is unfailable.
        // Because the tag bits are the same, we don't need to retag.
        masm.orq(R1.valueReg(), R0.valueReg());
        break;
    case JSOP_BITXOR:
        masm.xorl(R1.valueReg(), R0.valueReg());
        masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
        break;
    case JSOP_BITAND:
        masm.andq(R1.valueReg(), R0.valueReg());
        break;
    case JSOP_LSH:
        masm.unboxInt32(R0, ExtractTemp0);
        masm.unboxInt32(R1, ecx); // Unboxing R1 to ecx, clobbers R0.
        masm.shll_cl(ExtractTemp0);
        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
        break;
    case JSOP_RSH:
        masm.unboxInt32(R0, ExtractTemp0);
        masm.unboxInt32(R1, ecx);
        masm.sarl_cl(ExtractTemp0);
        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
        break;
    case JSOP_URSH:
        if (!allowDouble_)
            masm.movq(R0.valueReg(), ScratchReg);

        masm.unboxInt32(R0, ExtractTemp0);
        masm.unboxInt32(R1, ecx); // This clobbers R0

        masm.shrl_cl(ExtractTemp0);
        masm.test32(ExtractTemp0, ExtractTemp0);
        if (allowDouble_) {
            Label toUint;
            masm.j(Assembler::Signed, &toUint);

            // Box and return.
            masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
            EmitReturnFromIC(masm);

            masm.bind(&toUint);
            masm.convertUInt32ToDouble(ExtractTemp0, ScratchDoubleReg);
            masm.boxDouble(ScratchDoubleReg, R0);
        } else {
            masm.j(Assembler::Signed, &revertRegister);
            masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
        }
        break;
    default:
        MOZ_CRASH("Unhandled op in BinaryArith_Int32");
    }

    // Return from stub.
    EmitReturnFromIC(masm);

    if (op_ == JSOP_MUL) {
        masm.bind(&maybeNegZero);

        // Result is -0 if exactly one of lhs or rhs is negative.
        masm.movl(R0.valueReg(), ScratchReg);
        masm.orl(R1.valueReg(), ScratchReg);
        masm.j(Assembler::Signed, &failure);

        // Result is +0.
        masm.moveValue(Int32Value(0), R0);
        EmitReturnFromIC(masm);
    }

    // Revert the content of R0 in the fallible >>> case.
    if (op_ == JSOP_URSH && !allowDouble_) {
        masm.bind(&revertRegister);
        // Restore tag and payload.
        masm.movq(ScratchReg, R0.valueReg());
        // Fall through to failure.
    }
    // Failure case - jump to next stub
    masm.bind(&failure);
    EmitStubGuardFailure(masm);

    return true;
}
Exemplo n.º 13
0
void
HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
                                  uint32_t aStart, uint32_t aEnd,
                                  const SelectionMode& aSelectMode,
                                  ErrorResult& aRv, int32_t aSelectionStart,
                                  int32_t aSelectionEnd)
{
  if (aStart > aEnd) {
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  nsAutoString value;
  GetValueInternal(value, false);
  uint32_t inputValueLength = value.Length();

  if (aStart > inputValueLength) {
    aStart = inputValueLength;
  }

  if (aEnd > inputValueLength) {
    aEnd = inputValueLength;
  }

  if (aSelectionStart == -1 && aSelectionEnd == -1) {
    aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
    if (aRv.Failed()) {
      if (mState.IsSelectionCached()) {
        aSelectionStart = mState.GetSelectionProperties().GetStart();
        aSelectionEnd = mState.GetSelectionProperties().GetEnd();
        aRv = NS_OK;
      }
    }
  }

  if (aStart <= aEnd) {
    value.Replace(aStart, aEnd - aStart, aReplacement);
    nsresult rv =
      SetValueInternal(value, nsTextEditorState::eSetValue_ByContent);
    if (NS_FAILED(rv)) {
      aRv.Throw(rv);
      return;
    }
  }

  uint32_t newEnd = aStart + aReplacement.Length();
  int32_t delta =  aReplacement.Length() - (aEnd - aStart);

  switch (aSelectMode) {
    case mozilla::dom::SelectionMode::Select:
    {
      aSelectionStart = aStart;
      aSelectionEnd = newEnd;
    }
    break;
    case mozilla::dom::SelectionMode::Start:
    {
      aSelectionStart = aSelectionEnd = aStart;
    }
    break;
    case mozilla::dom::SelectionMode::End:
    {
      aSelectionStart = aSelectionEnd = newEnd;
    }
    break;
    case mozilla::dom::SelectionMode::Preserve:
    {
      if ((uint32_t)aSelectionStart > aEnd) {
        aSelectionStart += delta;
      } else if ((uint32_t)aSelectionStart > aStart) {
        aSelectionStart = aStart;
      }

      if ((uint32_t)aSelectionEnd > aEnd) {
        aSelectionEnd += delta;
      } else if ((uint32_t)aSelectionEnd > aStart) {
        aSelectionEnd = newEnd;
      }
    }
    break;
    default:
      MOZ_CRASH("Unknown mode!");
  }

  Optional<nsAString> direction;
  SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv);
}
Exemplo n.º 14
0
WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl, TexTarget target,
                                                 FakeBlackType type)
    : mGL(gl)
    , mGLName(CreateGLTexture(gl))
{
    GLenum texFormat;
    switch (type) {
    case FakeBlackType::RGBA0000:
        texFormat = LOCAL_GL_RGBA;
        break;

    case FakeBlackType::RGBA0001:
        texFormat = LOCAL_GL_RGB;
        break;

    default:
        MOZ_CRASH("bad type");
    }

    gl::ScopedBindTexture scopedBind(mGL, mGLName, target.get());

    mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
    mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);

    // We allocate our zeros on the heap, and we overallocate (16 bytes instead of 4) to
    // minimize the risk of running into a driver bug in texImage2D, as it is a bit
    // unusual maybe to create 1x1 textures, and the stack may not have the alignment that
    // TexImage2D expects.

    const webgl::DriverUnpackInfo dui = {texFormat, texFormat, LOCAL_GL_UNSIGNED_BYTE};
    UniqueBuffer zeros = moz_xcalloc(1, 16); // Infallible allocation.

    MOZ_ASSERT(gl->IsCurrent());
    if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
        for (int i = 0; i < 6; ++i) {
            const TexImageTarget curTarget = LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
            const GLenum error = DoTexImage(mGL, curTarget.get(), 0, &dui, 1, 1, 1,
                                            zeros.get());
            if (error) {
                const nsPrintfCString text("DoTexImage failed with `error`: 0x%04x, "
                                           "for `curTarget`: 0x%04x, "
                                           "`dui`: {0x%04x, 0x%04x, 0x%04x}.",
                                           error, curTarget.get(), dui.internalFormat,
                                           dui.unpackFormat, dui.unpackType);
                gfxCriticalError() << text.BeginReading();
                MOZ_CRASH("Unexpected error during cube map FakeBlack creation.");
            }
        }
    } else {
        const GLenum error = DoTexImage(mGL, target.get(), 0, &dui, 1, 1, 1,
                                        zeros.get());
        if (error) {
            const nsPrintfCString text("DoTexImage failed with `error`: 0x%04x, "
                                       "for `target`: 0x%04x, "
                                       "`dui`: {0x%04x, 0x%04x, 0x%04x}.",
                                       error, target.get(), dui.internalFormat,
                                       dui.unpackFormat, dui.unpackType);
            gfxCriticalError() << text.BeginReading();
            MOZ_CRASH("Unexpected error during FakeBlack creation.");
        }
    }
}
/*
 * The meat of our exception handler. This thread waits for an exception
 * message, annotates the exception if needed, then forwards it to the
 * previously installed handler (which will likely terminate the process).
 */
static void
MachExceptionHandler()
{
    kern_return_t ret;
    MachExceptionParameters& current = sMachExceptionState.current;
    MachExceptionParameters& previous = sMachExceptionState.previous;

    // We use the simplest kind of 64-bit exception message here.
    ExceptionRequest64 request = {};
    request.header.msgh_local_port = current.port;
    request.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(request));
    ret = mach_msg(&request.header, MACH_RCV_MSG, 0, request.header.msgh_size,
                   current.port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);

    // Restore the previous handler. We're going to forward to it
    // anyway, and if we crash while doing so we don't want to hang.
    task_set_exception_ports(mach_task_self(), previous.mask, previous.port,
                             previous.behavior, previous.flavor);

    // If we failed even receiving the message, just give up.
    if (ret != MACH_MSG_SUCCESS)
        MOZ_CRASH("MachExceptionHandler: mach_msg failed to receive a message!");

    // Terminate the thread if we're shutting down.
    if (request.header.msgh_id == sIDQuit)
        return;

    // The only other valid message ID is the one associated with the
    // EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES behavior we chose.
    if (request.header.msgh_id != sIDRequest64)
        MOZ_CRASH("MachExceptionHandler: Unexpected Message ID!");

    // Make sure we can understand the exception we received.
    if (request.exception != EXC_BAD_ACCESS || request.code_count != 2)
        MOZ_CRASH("MachExceptionHandler: Unexpected exception type!");

    // Get the address that the offending code tried to access.
    uintptr_t address = uintptr_t(request.code[1]);

    // If the faulting address is inside one of our protected regions, we
    // want to annotate the crash to make it stand out from the crowd.
    if (sProtectedRegions.isProtected(address)) {
        ReportCrashIfDebug("Hit MOZ_CRASH(Tried to access a protected region!)\n");
        MOZ_CRASH_ANNOTATE("MOZ_CRASH(Tried to access a protected region!)");
    }

    // Forward to the previous handler which may be a debugger, the unix
    // signal handler, the crash reporter or something else entirely.
    if (previous.port != MACH_PORT_NULL) {
        mach_msg_type_number_t stateCount;
        thread_state_data_t state;
        if ((uint32_t(previous.behavior) & ~MACH_EXCEPTION_CODES) != EXCEPTION_DEFAULT) {
            // If the previous handler requested thread state, get it here.
            stateCount = THREAD_STATE_MAX;
            ret = thread_get_state(request.thread.name, previous.flavor, state, &stateCount);
            if (ret != KERN_SUCCESS)
                MOZ_CRASH("MachExceptionHandler: Could not get the thread state to forward!");
        }

        // Depending on the behavior of the previous handler, the forwarded
        // exception message will have a different set of fields.
        // Of particular note is that exception handlers that lack
        // MACH_EXCEPTION_CODES will get 32-bit fields even on 64-bit
        // systems. It appears that OSX simply truncates these fields.
        ExceptionRequestUnion forward;
        switch (uint32_t(previous.behavior)) {
          case EXCEPTION_DEFAULT:
             CopyExceptionRequest32(request, forward.r32);
             break;
          case EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES:
             CopyExceptionRequest64(request, forward.r64);
             break;
          case EXCEPTION_STATE:
             CopyExceptionRequestState32(request, forward.rs32,
                                         previous.flavor, stateCount, state);
             break;
          case EXCEPTION_STATE | MACH_EXCEPTION_CODES:
             CopyExceptionRequestState64(request, forward.rs64,
                                         previous.flavor, stateCount, state);
             break;
          case EXCEPTION_STATE_IDENTITY:
             CopyExceptionRequestStateIdentity32(request, forward.rsi32,
                                                 previous.flavor, stateCount, state);
             break;
          case EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES:
             CopyExceptionRequestStateIdentity64(request, forward.rsi64,
                                                 previous.flavor, stateCount, state);
             break;
          default:
             MOZ_CRASH("MachExceptionHandler: Unknown previous handler behavior!");
        }

        // Forward the generated message to the old port. The local and remote
        // port fields *and their rights* are swapped on arrival, so we need to
        // swap them back first.
        forward.header.msgh_bits = (request.header.msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
            MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(request.header.msgh_bits),
                           MACH_MSGH_BITS_REMOTE(request.header.msgh_bits));
        forward.header.msgh_local_port = forward.header.msgh_remote_port;
        forward.header.msgh_remote_port = previous.port;
        ret = mach_msg(&forward.header, MACH_SEND_MSG, forward.header.msgh_size, 0,
                       MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
        if (ret != MACH_MSG_SUCCESS)
            MOZ_CRASH("MachExceptionHandler: Failed to forward to the previous handler!");
    } else {
        // There was no previous task-level exception handler, so defer to the
        // host level one instead. We set the return code to KERN_FAILURE to
        // indicate that we did not handle the exception.
        // The reply message ID is always the request ID + 100.
        ExceptionReply reply = {};
        reply.header.msgh_bits =
            MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.header.msgh_bits), 0);
        reply.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(reply));
        reply.header.msgh_remote_port = request.header.msgh_remote_port;
        reply.header.msgh_local_port = MACH_PORT_NULL;
        reply.header.msgh_id = request.header.msgh_id + 100;
        reply.NDR = request.NDR;
        reply.RetCode = KERN_FAILURE;
        ret = mach_msg(&reply.header, MACH_SEND_MSG, reply.header.msgh_size, 0,
                       MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
        if (ret != MACH_MSG_SUCCESS)
            MOZ_CRASH("MachExceptionHandler: Failed to forward to the host level!");
    }
}
Exemplo n.º 16
0
 NS_IMETHOD OnDataWritten(CacheFileHandle *aHandle, const char *aBuf,
                          nsresult aResult)
 {
   MOZ_CRASH("DoomFileHelper::OnDataWritten should not be called!");
   return NS_ERROR_UNEXPECTED;
 }
Exemplo n.º 17
0
bool
ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
{
    // Guard that R0 is an integer and R1 is an integer.
    Label failure;
    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);

    // Add R0 and R1. Don't need to explicitly unbox, just use R2's payloadReg.
    Register scratchReg = R2.payloadReg();

    // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs.set());

    Label goodMul, divTest1, divTest2;
    switch(op_) {
      case JSOP_ADD:
        // We know R0.typeReg() already contains the integer tag. No boxing
        // required.
        masm.ma_addTestOverflow(scratchReg, R0.payloadReg(), R1.payloadReg(), &failure);
        masm.move32(scratchReg, R0.payloadReg());
        break;
      case JSOP_SUB:
        masm.ma_subTestOverflow(scratchReg, R0.payloadReg(), R1.payloadReg(), &failure);
        masm.move32(scratchReg, R0.payloadReg());
        break;
      case JSOP_MUL: {
        masm.ma_mul_branch_overflow(scratchReg, R0.payloadReg(), R1.payloadReg(), &failure);

        masm.ma_b(scratchReg, Imm32(0), &goodMul, Assembler::NotEqual, ShortJump);

        // Result is -0 if operands have different signs.
        masm.as_xor(t8, R0.payloadReg(), R1.payloadReg());
        masm.ma_b(t8, Imm32(0), &failure, Assembler::LessThan, ShortJump);

        masm.bind(&goodMul);
        masm.move32(scratchReg, R0.payloadReg());
        break;
      }
      case JSOP_DIV:
      case JSOP_MOD: {
        // Check for INT_MIN / -1, it results in a double.
        masm.ma_b(R0.payloadReg(), Imm32(INT_MIN), &divTest1, Assembler::NotEqual, ShortJump);
        masm.ma_b(R1.payloadReg(), Imm32(-1), &failure, Assembler::Equal, ShortJump);
        masm.bind(&divTest1);

        // Check for division by zero
        masm.ma_b(R1.payloadReg(), Imm32(0), &failure, Assembler::Equal, ShortJump);

        // Check for 0 / X with X < 0 (results in -0).
        masm.ma_b(R0.payloadReg(), Imm32(0), &divTest2, Assembler::NotEqual, ShortJump);
        masm.ma_b(R1.payloadReg(), Imm32(0), &failure, Assembler::LessThan, ShortJump);
        masm.bind(&divTest2);

        masm.as_div(R0.payloadReg(), R1.payloadReg());

        if (op_ == JSOP_DIV) {
            // Result is a double if the remainder != 0.
            masm.as_mfhi(scratchReg);
            masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::NotEqual, ShortJump);
            masm.as_mflo(scratchReg);
            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
        } else {
            Label done;
            // If X % Y == 0 and X < 0, the result is -0.
            masm.as_mfhi(scratchReg);
            masm.ma_b(scratchReg, Imm32(0), &done, Assembler::NotEqual, ShortJump);
            masm.ma_b(R0.payloadReg(), Imm32(0), &failure, Assembler::LessThan, ShortJump);
            masm.bind(&done);
            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
        }
        break;
      }
      case JSOP_BITOR:
        masm.ma_or(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
        break;
      case JSOP_BITXOR:
        masm.ma_xor(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
        break;
      case JSOP_BITAND:
        masm.ma_and(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
        break;
      case JSOP_LSH:
        // MIPS will only use 5 lowest bits in R1 as shift offset.
        masm.ma_sll(R0.payloadReg(), R0.payloadReg(), R1.payloadReg());
        break;
      case JSOP_RSH:
        masm.ma_sra(R0.payloadReg(), R0.payloadReg(), R1.payloadReg());
        break;
      case JSOP_URSH:
        masm.ma_srl(scratchReg, R0.payloadReg(), R1.payloadReg());
        if (allowDouble_) {
            Label toUint;
            masm.ma_b(scratchReg, Imm32(0), &toUint, Assembler::LessThan, ShortJump);

            // Move result and box for return.
            masm.move32(scratchReg, R0.payloadReg());
            EmitReturnFromIC(masm);

            masm.bind(&toUint);
            masm.convertUInt32ToDouble(scratchReg, FloatReg1);
            masm.boxDouble(FloatReg1, R0);
        } else {
            masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::LessThan, ShortJump);
            // Move result for return.
            masm.move32(scratchReg, R0.payloadReg());
        }
        break;
      default:
        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
    }

    EmitReturnFromIC(masm);

    // Failure case - jump to next stub
    masm.bind(&failure);
    EmitStubGuardFailure(masm);

    return true;
}
Exemplo n.º 18
0
 NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult)
 {
   MOZ_CRASH("DoomFileHelper::OnEOFSet should not be called!");
   return NS_ERROR_UNEXPECTED;
 }
Exemplo n.º 19
0
void
FileBlobImpl::SetLastModified(int64_t aLastModified)
{
  MOZ_CRASH("SetLastModified of a real file is not allowed!");
}
Exemplo n.º 20
0
 NS_IMETHOD OnMetadataRead(nsresult aResult)
 {
   MOZ_CRASH("MetadataListenerHelper::OnMetadataRead should not be called!");
   return NS_ERROR_UNEXPECTED;
 }
Exemplo n.º 21
0
MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
  : mInvalidReason(nullptr)
{
  bool isBrowser = false;
  uint32_t ownAppId = NO_APP_ID;
  uint32_t containingAppId = NO_APP_ID;

  const IPCTabAppBrowserContext& appBrowser = aParams.appBrowserContext();
  switch(appBrowser.type()) {
    case IPCTabAppBrowserContext::TPopupIPCTabContext: {
      const PopupIPCTabContext &ipcContext = appBrowser.get_PopupIPCTabContext();

      TabContext *context;
      if (ipcContext.openerParent()) {
        context = static_cast<TabParent*>(ipcContext.openerParent());
        if (context->IsBrowserElement() && !ipcContext.isBrowserElement()) {
          // If the TabParent corresponds to a browser element, then it can only
          // open other browser elements, for security reasons.  We should have
          // checked this before calling the TabContext constructor, so this is
          // a fatal error.
          mInvalidReason = "Child is-browser process tried to "
                           "open a non-browser tab.";
          return;
        }
      } else if (ipcContext.openerChild()) {
        context = static_cast<TabChild*>(ipcContext.openerChild());
      } else {
        // This should be unreachable because PopupIPCTabContext::opener is not a
        // nullable field.
        mInvalidReason = "PopupIPCTabContext::opener was null (?!).";
        return;
      }

      // Browser elements can't nest other browser elements.  So if
      // our opener is browser element, we must be a new DOM window
      // opened by it.  In that case we inherit our containing app ID
      // (if any).
      //
      // Otherwise, we're a new app window and we inherit from our
      // opener app.
      if (ipcContext.isBrowserElement()) {
        isBrowser = true;
        ownAppId = NO_APP_ID;
        containingAppId = context->OwnOrContainingAppId();
      } else {
        isBrowser = false;
        ownAppId = context->mOwnAppId;
        containingAppId = context->mContainingAppId;
      }
      break;
    }
    case IPCTabAppBrowserContext::TAppFrameIPCTabContext: {
      const AppFrameIPCTabContext &ipcContext =
        appBrowser.get_AppFrameIPCTabContext();

      isBrowser = false;
      ownAppId = ipcContext.ownAppId();
      containingAppId = ipcContext.appFrameOwnerAppId();
      break;
    }
    case IPCTabAppBrowserContext::TBrowserFrameIPCTabContext: {
      const BrowserFrameIPCTabContext &ipcContext =
        appBrowser.get_BrowserFrameIPCTabContext();

      isBrowser = true;
      ownAppId = NO_APP_ID;
      containingAppId = ipcContext.browserFrameOwnerAppId();
      break;
    }
    case IPCTabAppBrowserContext::TVanillaFrameIPCTabContext: {
      isBrowser = false;
      ownAppId = NO_APP_ID;
      containingAppId = NO_APP_ID;
      break;
    }
    default: {
      MOZ_CRASH();
    }
  }

  nsCOMPtr<mozIApplication> ownApp = GetAppForId(ownAppId);
  if ((ownApp == nullptr) != (ownAppId == NO_APP_ID)) {
    mInvalidReason = "Got an ownAppId that didn't correspond to an app.";
    return;
  }

  nsCOMPtr<mozIApplication> containingApp = GetAppForId(containingAppId);
  if ((containingApp == nullptr) != (containingAppId == NO_APP_ID)) {
    mInvalidReason = "Got a containingAppId that didn't correspond to an app.";
    return;
  }

  bool rv;
  if (isBrowser) {
    rv = mTabContext.SetTabContextForBrowserFrame(containingApp,
                                                  aParams.scrollingBehavior());
  } else {
    rv = mTabContext.SetTabContextForAppFrame(ownApp,
                                              containingApp,
                                              aParams.scrollingBehavior());
  }

  if (!rv) {
    mInvalidReason = "Couldn't initialize TabContext.";
  }
}
Exemplo n.º 22
0
nsresult
CacheFile::OnChunkUpdated(CacheFileChunk *aChunk)
{
  MOZ_CRASH("CacheFile::OnChunkUpdated should not be called!");
  return NS_ERROR_UNEXPECTED;
}
Exemplo n.º 23
0
bool
GMPChild::RecvCrashPluginNow()
{
  MOZ_CRASH();
  return true;
}
Exemplo n.º 24
0
nsresult
CacheFile::OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult)
{
  MOZ_CRASH("CacheFile::OnDataRead should not be called!");
  return NS_ERROR_UNEXPECTED;
}
Exemplo n.º 25
0
already_AddRefed<nsIPrincipal>
PrincipalInfoToPrincipal(const PrincipalInfo& aPrincipalInfo,
                         nsresult* aOptionalResult)
{
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(aPrincipalInfo.type() != PrincipalInfo::T__None);

  nsresult stackResult;
  nsresult& rv = aOptionalResult ? *aOptionalResult : stackResult;

  nsCOMPtr<nsIScriptSecurityManager> secMan =
    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return nullptr;
  }

  nsCOMPtr<nsIPrincipal> principal;

  switch (aPrincipalInfo.type()) {
    case PrincipalInfo::TSystemPrincipalInfo: {
      rv = secMan->GetSystemPrincipal(getter_AddRefs(principal));
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return nullptr;
      }

      return principal.forget();
    }

    case PrincipalInfo::TNullPrincipalInfo: {
      principal = do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID, &rv);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return nullptr;
      }

      return principal.forget();
    }

    case PrincipalInfo::TContentPrincipalInfo: {
      const ContentPrincipalInfo& info =
        aPrincipalInfo.get_ContentPrincipalInfo();

      nsCOMPtr<nsIURI> uri;
      rv = NS_NewURI(getter_AddRefs(uri), info.spec());
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return nullptr;
      }

      if (info.appId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
        rv = secMan->GetSimpleCodebasePrincipal(uri, getter_AddRefs(principal));
      } else {
        rv = secMan->GetAppCodebasePrincipal(uri,
                                             info.appId(),
                                             info.isInBrowserElement(),
                                             getter_AddRefs(principal));
      }
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return nullptr;
      }

      return principal.forget();
    }

    case PrincipalInfo::TExpandedPrincipalInfo: {
      const ExpandedPrincipalInfo& info = aPrincipalInfo.get_ExpandedPrincipalInfo();

      nsTArray< nsCOMPtr<nsIPrincipal> > whitelist;
      nsCOMPtr<nsIPrincipal> wlPrincipal;

      for (uint32_t i = 0; i < info.whitelist().Length(); i++) {
        wlPrincipal = PrincipalInfoToPrincipal(info.whitelist()[i], &rv);
        if (NS_WARN_IF(NS_FAILED(rv))) {
          return nullptr;
        }
        // append that principal to the whitelist
        whitelist.AppendElement(wlPrincipal);
      }

      nsRefPtr<nsExpandedPrincipal> expandedPrincipal = new nsExpandedPrincipal(whitelist);
      if (!expandedPrincipal) {
        NS_WARNING("could not instantiate expanded principal");
        return nullptr;
      }

      principal = expandedPrincipal;
      return principal.forget();
    }

    default:
      MOZ_CRASH("Unknown PrincipalInfo type!");
  }

  MOZ_CRASH("Should never get here!");
}
Exemplo n.º 26
0
nsresult
CacheFile::OnEOFSet(CacheFileHandle *aHandle, nsresult aResult)
{
  MOZ_CRASH("CacheFile::OnEOFSet should not be called!");
  return NS_ERROR_UNEXPECTED;
}
Exemplo n.º 27
0
static already_AddRefed<const webgl::LinkedProgramInfo>
QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
{
    RefPtr<webgl::LinkedProgramInfo> info(new webgl::LinkedProgramInfo(prog));

    GLuint maxAttribLenWithNull = 0;
    gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
                      (GLint*)&maxAttribLenWithNull);
    if (maxAttribLenWithNull < 1)
        maxAttribLenWithNull = 1;

    GLuint maxUniformLenWithNull = 0;
    gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH,
                      (GLint*)&maxUniformLenWithNull);
    if (maxUniformLenWithNull < 1)
        maxUniformLenWithNull = 1;

    GLuint maxUniformBlockLenWithNull = 0;
    if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) {
        gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH,
                          (GLint*)&maxUniformBlockLenWithNull);
        if (maxUniformBlockLenWithNull < 1)
            maxUniformBlockLenWithNull = 1;
    }

#ifdef DUMP_SHADERVAR_MAPPINGS
    printf_stderr("maxAttribLenWithNull: %d\n", maxAttribLenWithNull);
    printf_stderr("maxUniformLenWithNull: %d\n", maxUniformLenWithNull);
    printf_stderr("maxUniformBlockLenWithNull: %d\n", maxUniformBlockLenWithNull);
#endif

    // Attribs

    GLuint numActiveAttribs = 0;
    gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES,
                      (GLint*)&numActiveAttribs);

    for (GLuint i = 0; i < numActiveAttribs; i++) {
        nsAutoCString mappedName;
        mappedName.SetLength(maxAttribLenWithNull - 1);

        GLsizei lengthWithoutNull = 0;
        GLint elemCount = 0; // `size`
        GLenum elemType = 0; // `type`
        gl->fGetActiveAttrib(prog->mGLName, i, mappedName.Length()+1, &lengthWithoutNull,
                             &elemCount, &elemType, mappedName.BeginWriting());

        mappedName.SetLength(lengthWithoutNull);

        // Collect ActiveInfos:

        // Attribs can't be arrays, so we can skip some of the mess we have in the Uniform
        // path.
        nsDependentCString userName;
        if (!prog->FindAttribUserNameByMappedName(mappedName, &userName))
            userName.Rebind(mappedName, 0);

#ifdef DUMP_SHADERVAR_MAPPINGS
        printf_stderr("[attrib %i] %s/%s\n", i, mappedName.BeginReading(),
                      userName.BeginReading());
        printf_stderr("    lengthWithoutNull: %d\n", lengthWithoutNull);
#endif

        const bool isArray = false;
        AddActiveInfo(prog->Context(), elemCount, elemType, isArray, userName, mappedName,
                      &info->activeAttribs, &info->attribMap);

        // Collect active locations:
        GLint loc = gl->fGetAttribLocation(prog->mGLName, mappedName.BeginReading());
        if (loc == -1)
            MOZ_CRASH("Active attrib has no location.");

        info->activeAttribLocs.insert(loc);
    }

    // Uniforms

    const bool needsCheckForArrays = gl->WorkAroundDriverBugs();

    GLuint numActiveUniforms = 0;
    gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORMS,
                      (GLint*)&numActiveUniforms);

    for (GLuint i = 0; i < numActiveUniforms; i++) {
        nsAutoCString mappedName;
        mappedName.SetLength(maxUniformLenWithNull - 1);

        GLsizei lengthWithoutNull = 0;
        GLint elemCount = 0; // `size`
        GLenum elemType = 0; // `type`
        gl->fGetActiveUniform(prog->mGLName, i, mappedName.Length()+1, &lengthWithoutNull,
                              &elemCount, &elemType, mappedName.BeginWriting());

        mappedName.SetLength(lengthWithoutNull);

        nsAutoCString baseMappedName;
        bool isArray;
        size_t arrayIndex;
        if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
            MOZ_CRASH("Failed to parse `mappedName` received from driver.");

        // Note that for good drivers, `isArray` should already be correct.
        // However, if FindUniform succeeds, it will be validator-guaranteed correct.

        nsAutoCString baseUserName;
        if (!prog->FindUniformByMappedName(baseMappedName, &baseUserName, &isArray)) {
            baseUserName = baseMappedName;

            if (needsCheckForArrays && !isArray) {
                // By GLES 3, GetUniformLocation("foo[0]") should return -1 if `foo` is
                // not an array. Our current linux Try slaves return the location of `foo`
                // anyways, though.
                std::string mappedNameStr = baseMappedName.BeginReading();
                mappedNameStr += "[0]";

                GLint loc = gl->fGetUniformLocation(prog->mGLName, mappedNameStr.c_str());
                if (loc != -1)
                    isArray = true;
            }
        }

#ifdef DUMP_SHADERVAR_MAPPINGS
        printf_stderr("[uniform %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(),
                      (int)isArray, baseMappedName.BeginReading(),
                      baseUserName.BeginReading());
        printf_stderr("    lengthWithoutNull: %d\n", lengthWithoutNull);
        printf_stderr("    isArray: %d\n", (int)isArray);
#endif

        AddActiveInfo(prog->Context(), elemCount, elemType, isArray, baseUserName,
                      baseMappedName, &info->activeUniforms, &info->uniformMap);
    }

    // Uniform Blocks

    if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) {
        GLuint numActiveUniformBlocks = 0;
        gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_BLOCKS,
                          (GLint*)&numActiveUniformBlocks);

        for (GLuint i = 0; i < numActiveUniformBlocks; i++) {
            nsAutoCString mappedName;
            mappedName.SetLength(maxUniformBlockLenWithNull - 1);

            GLint lengthWithoutNull;
            gl->fGetActiveUniformBlockiv(prog->mGLName, i, LOCAL_GL_UNIFORM_BLOCK_NAME_LENGTH, &lengthWithoutNull);
            gl->fGetActiveUniformBlockName(prog->mGLName, i, maxUniformBlockLenWithNull, &lengthWithoutNull, mappedName.BeginWriting());
            mappedName.SetLength(lengthWithoutNull);

            nsAutoCString baseMappedName;
            bool isArray;
            size_t arrayIndex;
            if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
                MOZ_CRASH("Failed to parse `mappedName` received from driver.");

            nsAutoCString baseUserName;
            if (!prog->FindUniformBlockByMappedName(baseMappedName, &baseUserName,
                                                    &isArray))
            {
                baseUserName = baseMappedName;

                if (needsCheckForArrays && !isArray) {
                    std::string mappedNameStr = baseMappedName.BeginReading();
                    mappedNameStr += "[0]";

                    GLuint loc = gl->fGetUniformBlockIndex(prog->mGLName,
                                                           mappedNameStr.c_str());
                    if (loc != LOCAL_GL_INVALID_INDEX)
                        isArray = true;
                }
            }

#ifdef DUMP_SHADERVAR_MAPPINGS
            printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(),
                          (int)isArray, baseMappedName.BeginReading(),
                          baseUserName.BeginReading());
            printf_stderr("    lengthWithoutNull: %d\n", lengthWithoutNull);
            printf_stderr("    isArray: %d\n", (int)isArray);
#endif

            AddActiveBlockInfo(baseUserName, baseMappedName, &info->uniformBlocks);
        }
    }

    return info.forget();
}
Exemplo n.º 28
0
void
SpeechRecognition::Transition(SpeechEvent* aEvent)
{
    switch (mCurrentState) {
    case STATE_IDLE:
        switch (aEvent->mType) {
        case EVENT_START:
            // TODO: may want to time out if we wait too long
            // for user to approve
            WaitForAudioData(aEvent);
            break;
        case EVENT_STOP:
        case EVENT_ABORT:
        case EVENT_AUDIO_DATA:
        case EVENT_RECOGNITIONSERVICE_INTERMEDIATE_RESULT:
        case EVENT_RECOGNITIONSERVICE_FINAL_RESULT:
            DoNothing(aEvent);
            break;
        case EVENT_AUDIO_ERROR:
        case EVENT_RECOGNITIONSERVICE_ERROR:
            AbortError(aEvent);
            break;
        case EVENT_COUNT:
            MOZ_CRASH("Invalid event EVENT_COUNT");
        }
        break;
    case STATE_STARTING:
        switch (aEvent->mType) {
        case EVENT_AUDIO_DATA:
            StartedAudioCapture(aEvent);
            break;
        case EVENT_AUDIO_ERROR:
        case EVENT_RECOGNITIONSERVICE_ERROR:
            AbortError(aEvent);
            break;
        case EVENT_ABORT:
            AbortSilently(aEvent);
            break;
        case EVENT_STOP:
            Reset();
            break;
        case EVENT_RECOGNITIONSERVICE_INTERMEDIATE_RESULT:
        case EVENT_RECOGNITIONSERVICE_FINAL_RESULT:
            DoNothing(aEvent);
            break;
        case EVENT_START:
            SR_LOG("STATE_STARTING: Unhandled event %s", GetName(aEvent));
            MOZ_CRASH();
        case EVENT_COUNT:
            MOZ_CRASH("Invalid event EVENT_COUNT");
        }
        break;
    case STATE_ESTIMATING:
        switch (aEvent->mType) {
        case EVENT_AUDIO_DATA:
            WaitForEstimation(aEvent);
            break;
        case EVENT_STOP:
            StopRecordingAndRecognize(aEvent);
            break;
        case EVENT_ABORT:
            AbortSilently(aEvent);
            break;
        case EVENT_RECOGNITIONSERVICE_INTERMEDIATE_RESULT:
        case EVENT_RECOGNITIONSERVICE_FINAL_RESULT:
        case EVENT_RECOGNITIONSERVICE_ERROR:
            DoNothing(aEvent);
            break;
        case EVENT_AUDIO_ERROR:
            AbortError(aEvent);
            break;
        case EVENT_START:
            SR_LOG("STATE_ESTIMATING: Unhandled event %d", aEvent->mType);
            MOZ_CRASH();
        case EVENT_COUNT:
            MOZ_CRASH("Invalid event EVENT_COUNT");
        }
        break;
    case STATE_WAITING_FOR_SPEECH:
        switch (aEvent->mType) {
        case EVENT_AUDIO_DATA:
            DetectSpeech(aEvent);
            break;
        case EVENT_STOP:
            StopRecordingAndRecognize(aEvent);
            break;
        case EVENT_ABORT:
            AbortSilently(aEvent);
            break;
        case EVENT_AUDIO_ERROR:
            AbortError(aEvent);
            break;
        case EVENT_RECOGNITIONSERVICE_INTERMEDIATE_RESULT:
        case EVENT_RECOGNITIONSERVICE_FINAL_RESULT:
        case EVENT_RECOGNITIONSERVICE_ERROR:
            DoNothing(aEvent);
            break;
        case EVENT_START:
            SR_LOG("STATE_STARTING: Unhandled event %s", GetName(aEvent));
            MOZ_CRASH();
        case EVENT_COUNT:
            MOZ_CRASH("Invalid event EVENT_COUNT");
        }
        break;
    case STATE_RECOGNIZING:
        switch (aEvent->mType) {
        case EVENT_AUDIO_DATA:
            WaitForSpeechEnd(aEvent);
            break;
        case EVENT_STOP:
            StopRecordingAndRecognize(aEvent);
            break;
        case EVENT_AUDIO_ERROR:
        case EVENT_RECOGNITIONSERVICE_ERROR:
            AbortError(aEvent);
            break;
        case EVENT_ABORT:
            AbortSilently(aEvent);
            break;
        case EVENT_RECOGNITIONSERVICE_FINAL_RESULT:
        case EVENT_RECOGNITIONSERVICE_INTERMEDIATE_RESULT:
            DoNothing(aEvent);
            break;
        case EVENT_START:
            SR_LOG("STATE_RECOGNIZING: Unhandled aEvent %s", GetName(aEvent));
            MOZ_CRASH();
        case EVENT_COUNT:
            MOZ_CRASH("Invalid event EVENT_COUNT");
        }
        break;
    case STATE_WAITING_FOR_RESULT:
        switch (aEvent->mType) {
        case EVENT_STOP:
            DoNothing(aEvent);
            break;
        case EVENT_AUDIO_ERROR:
        case EVENT_RECOGNITIONSERVICE_ERROR:
            AbortError(aEvent);
            break;
        case EVENT_RECOGNITIONSERVICE_FINAL_RESULT:
            NotifyFinalResult(aEvent);
            break;
        case EVENT_AUDIO_DATA:
            DoNothing(aEvent);
            break;
        case EVENT_ABORT:
            AbortSilently(aEvent);
            break;
        case EVENT_START:
        case EVENT_RECOGNITIONSERVICE_INTERMEDIATE_RESULT:
            SR_LOG("STATE_WAITING_FOR_RESULT: Unhandled aEvent %s", GetName(aEvent));
            MOZ_CRASH();
        case EVENT_COUNT:
            MOZ_CRASH("Invalid event EVENT_COUNT");
        }
        break;
    case STATE_COUNT:
        MOZ_CRASH("Invalid state STATE_COUNT");
    }

    return;
}
Exemplo n.º 29
0
void
ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
    gl->MakeCurrent();
    MOZ_ASSERT(dest->GetSize() != gfxIntSize(0, 0));

    /* gfxImageFormat::ARGB32:
     * RGBA+UByte: be[RGBA], le[ABGR]
     * RGBA+UInt: le[RGBA]
     * BGRA+UInt: le[BGRA]
     * BGRA+UIntRev: le[ARGB]
     *
     * gfxImageFormat::RGB16_565:
     * RGB+UShort: le[rrrrrggg,gggbbbbb]
     */
    bool hasAlpha = dest->Format() == gfxImageFormat::ARGB32;

    int destPixelSize;
    GLenum destFormat;
    GLenum destType;

    switch (dest->Format()) {
        case gfxImageFormat::RGB24: // XRGB
        case gfxImageFormat::ARGB32:
            destPixelSize = 4;
            // Needs host (little) endian ARGB.
            destFormat = LOCAL_GL_BGRA;
            destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
            break;

        case gfxImageFormat::RGB16_565:
            destPixelSize = 2;
            destFormat = LOCAL_GL_RGB;
            destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV;
            break;

        default:
            MOZ_CRASH("Bad format.");
    }
    MOZ_ASSERT(dest->Stride() == dest->Width() * destPixelSize);

    GLenum readFormat = destFormat;
    GLenum readType = destType;
    bool needsTempSurf = !GetActualReadFormats(gl,
                                               destFormat, destType,
                                               readFormat, readType);

    nsAutoPtr<gfxImageSurface> tempSurf;
    gfxImageSurface* readSurf = nullptr;
    int readPixelSize = 0;
    if (needsTempSurf) {
        if (gl->DebugMode()) {
            NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
        }
        SurfaceFormat readFormatGFX;

        switch (readFormat) {
            case LOCAL_GL_RGBA:
            case LOCAL_GL_BGRA: {
                readFormatGFX = hasAlpha ? SurfaceFormat::B8G8R8A8
                                         : SurfaceFormat::B8G8R8X8;
                break;
            }
            case LOCAL_GL_RGB: {
                MOZ_ASSERT(readPixelSize == 2);
                MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV);
                readFormatGFX = SurfaceFormat::R5G6B5;
                break;
            }
            default: {
                MOZ_CRASH("Bad read format.");
            }
        }

        switch (readType) {
            case LOCAL_GL_UNSIGNED_BYTE: {
                MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
                readPixelSize = 4;
                break;
            }
            case LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV: {
                MOZ_ASSERT(readFormat == LOCAL_GL_BGRA);
                readPixelSize = 4;
                break;
            }
            case LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV: {
                MOZ_ASSERT(readFormat == LOCAL_GL_RGB);
                readPixelSize = 2;
                break;
            }
            default: {
                MOZ_CRASH("Bad read type.");
            }
        }

        tempSurf = new gfxImageSurface(dest->GetSize(),
                                       SurfaceFormatToImageFormat(readFormatGFX),
                                       false);
        readSurf = tempSurf;
    } else {
        readPixelSize = destPixelSize;
        readSurf = dest;
    }
    MOZ_ASSERT(readPixelSize);

    GLint currentPackAlignment = 0;
    gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &currentPackAlignment);

    if (currentPackAlignment != readPixelSize)
        gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readPixelSize);

    GLsizei width = dest->Width();
    GLsizei height = dest->Height();

    readSurf->Flush();
    gl->fReadPixels(0, 0,
                    width, height,
                    readFormat, readType,
                    readSurf->Data());
    readSurf->MarkDirty();

    if (currentPackAlignment != readPixelSize)
        gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);

    if (readSurf != dest) {
        MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
        MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
        // So we just copied in RGBA in big endian, or le: 0xAABBGGRR.
        // We want 0xAARRGGBB, so swap R and B:
        dest->Flush();
        RefPtr<DataSourceSurface> readDSurf =
            Factory::CreateWrappingDataSourceSurface(readSurf->Data(),
                                                     readSurf->Stride(),
                                                     ToIntSize(readSurf->GetSize()),
                                                     ImageFormatToSurfaceFormat(readSurf->Format()));
        SwapRAndBComponents(readDSurf);
        dest->MarkDirty();

        gfxContext ctx(dest);
        ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
        ctx.SetSource(readSurf);
        ctx.Paint();
    }

    // Check if GL is giving back 1.0 alpha for
    // RGBA reads to RGBA images from no-alpha buffers.
#ifdef XP_MACOSX
    if (gl->WorkAroundDriverBugs() &&
        gl->Vendor() == gl::GLVendor::NVIDIA &&
        dest->Format() == gfxImageFormat::ARGB32 &&
        width && height)
    {
        GLint alphaBits = 0;
        gl->fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
        if (!alphaBits) {
            const uint32_t alphaMask = gfxPackedPixelNoPreMultiply(0xff,0,0,0);

            dest->Flush();
            uint32_t* itr = (uint32_t*)dest->Data();
            uint32_t testPixel = *itr;
            if ((testPixel & alphaMask) != alphaMask) {
                // We need to set the alpha channel to 1.0 manually.
                uint32_t* itrEnd = itr + width*height;  // Stride is guaranteed to be width*4.

                for (; itr != itrEnd; itr++) {
                    *itr |= alphaMask;
                }
            }
            dest->MarkDirty();
        }
    }
#endif
}
Exemplo n.º 30
0
JS::Value
WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
{
    if (IsContextLost())
        return JS::NullValue();

    MakeContextCurrent();

    if (MinCapabilityMode()) {
        switch(pname) {
            ////////////////////////////
            // Single-value params

            // int
            case LOCAL_GL_MAX_VERTEX_ATTRIBS:
                return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_ATTRIBS);

            case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
                return JS::Int32Value(MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS);

            case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
                return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS);

            case LOCAL_GL_MAX_VARYING_VECTORS:
                return JS::Int32Value(MINVALUE_GL_MAX_VARYING_VECTORS);

            case LOCAL_GL_MAX_TEXTURE_SIZE:
                return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_SIZE);

            case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
                return JS::Int32Value(MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE);

            case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
                return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS);

            case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
                return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);

            case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
                return JS::Int32Value(MINVALUE_GL_MAX_RENDERBUFFER_SIZE);

            default:
                // Return the real value; we're not overriding this one
                break;
        }
    }

    if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
        if (pname == LOCAL_GL_MAX_COLOR_ATTACHMENTS) {
            return JS::Int32Value(mImplMaxColorAttachments);

        } else if (pname == LOCAL_GL_MAX_DRAW_BUFFERS) {
            return JS::Int32Value(mImplMaxDrawBuffers);

        } else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
                   pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mImplMaxDrawBuffers))
        {
            GLint iv = 0;
            gl->fGetIntegerv(pname, &iv);

            if (mBoundDrawFramebuffer)
                return JS::Int32Value(iv);

            const GLint index = (pname - LOCAL_GL_DRAW_BUFFER0);
            if (iv == LOCAL_GL_COLOR_ATTACHMENT0 + index)
                return JS::Int32Value(LOCAL_GL_BACK);

            return JS::Int32Value(LOCAL_GL_NONE);
        }
    }

    if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
        if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) {
            WebGLVertexArray* vao =
                (mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr;
            return WebGLObjectAsJSValue(cx, vao, rv);
        }
    }

    if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
        if (pname == LOCAL_GL_TIMESTAMP_EXT) {
            GLuint64 iv = 0;
            gl->fGetInteger64v(pname, (GLint64*) &iv);
            // TODO: JS doesn't support 64-bit integers. Be lossy and
            // cast to double (53 bits)
            return JS::NumberValue(static_cast<double>(iv));
        } else if (pname == LOCAL_GL_GPU_DISJOINT_EXT) {
            // When disjoint isn't supported, leave as false.
            realGLboolean disjoint = LOCAL_GL_FALSE;
            if (gl->IsExtensionSupported(gl::GLContext::EXT_disjoint_timer_query)) {
                gl->fGetBooleanv(pname, &disjoint);
            }
            return JS::BooleanValue(bool(disjoint));
        }
    }

    // Privileged string params exposed by WEBGL_debug_renderer_info.
    // The privilege check is done in WebGLContext::IsExtensionSupported.
    // So here we just have to check that the extension is enabled.
    if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
        switch (pname) {
        case UNMASKED_VENDOR_WEBGL:
        case UNMASKED_RENDERER_WEBGL:
            {
                const char* overridePref = nullptr;
                GLenum driverEnum = LOCAL_GL_NONE;

                switch (pname) {
                case UNMASKED_RENDERER_WEBGL:
                    overridePref = "webgl.renderer-string-override";
                    driverEnum = LOCAL_GL_RENDERER;
                    break;
                case UNMASKED_VENDOR_WEBGL:
                    overridePref = "webgl.vendor-string-override";
                    driverEnum = LOCAL_GL_VENDOR;
                    break;
                default:
                    MOZ_CRASH("bad `pname`");
                }

                bool hasRetVal = false;

                nsAutoString ret;
                if (overridePref) {
                    nsresult res = Preferences::GetString(overridePref, &ret);
                    if (NS_SUCCEEDED(res) && ret.Length() > 0)
                        hasRetVal = true;
                }

                if (!hasRetVal) {
                    const char* chars = reinterpret_cast<const char*>(gl->fGetString(driverEnum));
                    ret = NS_ConvertASCIItoUTF16(chars);
                    hasRetVal = true;
                }

                return StringValue(cx, ret, rv);
            }
        }
    }

    if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
        if (pname == LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT) {
            GLint i = 0;
            gl->fGetIntegerv(pname, &i);
            return JS::Int32Value(i);
        }
    }

    if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
        if (pname == LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) {
            GLfloat f = 0.f;
            gl->fGetFloatv(pname, &f);
            return JS::NumberValue(f);
        }
    }

    switch (pname) {
        //
        // String params
        //
        case LOCAL_GL_VENDOR:
        case LOCAL_GL_RENDERER:
            return StringValue(cx, "Mozilla", rv);
        case LOCAL_GL_VERSION:
            return StringValue(cx, "WebGL 1.0", rv);
        case LOCAL_GL_SHADING_LANGUAGE_VERSION:
            return StringValue(cx, "WebGL GLSL ES 1.0", rv);

        ////////////////////////////////
        // Single-value params

        // unsigned int
        case LOCAL_GL_CULL_FACE_MODE:
        case LOCAL_GL_FRONT_FACE:
        case LOCAL_GL_ACTIVE_TEXTURE:
        case LOCAL_GL_STENCIL_FUNC:
        case LOCAL_GL_STENCIL_FAIL:
        case LOCAL_GL_STENCIL_PASS_DEPTH_FAIL:
        case LOCAL_GL_STENCIL_PASS_DEPTH_PASS:
        case LOCAL_GL_STENCIL_BACK_FUNC:
        case LOCAL_GL_STENCIL_BACK_FAIL:
        case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_FAIL:
        case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_PASS:
        case LOCAL_GL_DEPTH_FUNC:
        case LOCAL_GL_BLEND_SRC_RGB:
        case LOCAL_GL_BLEND_SRC_ALPHA:
        case LOCAL_GL_BLEND_DST_RGB:
        case LOCAL_GL_BLEND_DST_ALPHA:
        case LOCAL_GL_BLEND_EQUATION_RGB:
        case LOCAL_GL_BLEND_EQUATION_ALPHA:
        case LOCAL_GL_GENERATE_MIPMAP_HINT: {
            GLint i = 0;
            gl->fGetIntegerv(pname, &i);
            return JS::NumberValue(uint32_t(i));
        }
        case LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE: {
            if (mBoundReadFramebuffer) {
                nsCString fbStatusInfoIgnored;
                const auto status = mBoundReadFramebuffer->CheckFramebufferStatus(&fbStatusInfoIgnored);
                if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
                    ErrorInvalidOperation("getParameter: Read framebuffer must be"
                                          " complete before querying"
                                          " IMPLEMENTATION_COLOR_READ_TYPE.");
                    return JS::NullValue();
                }
            }

            GLint i = 0;
            if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) {
                gl->fGetIntegerv(pname, &i);
            } else {
                i = LOCAL_GL_UNSIGNED_BYTE;
            }

            return JS::NumberValue(uint32_t(i));
        }
        case LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT: {
            if (mBoundReadFramebuffer) {
                nsCString fbStatusInfoIgnored;
                const auto status = mBoundReadFramebuffer->CheckFramebufferStatus(&fbStatusInfoIgnored);
                if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
                    ErrorInvalidOperation("getParameter: Read framebuffer must be"
                                          " complete before querying"
                                          " IMPLEMENTATION_COLOR_READ_FORMAT.");
                    return JS::NullValue();
                }
            }

            GLint i = 0;
            if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) {
                gl->fGetIntegerv(pname, &i);
            } else {
                i = LOCAL_GL_RGBA;
            }

            // OpenGL ES 3.0.4 p112 Table 3.2 shows that read format SRGB_ALPHA is
            // not supported. And if internal format of fbo is SRGB8_ALPHA8, then
            // IMPLEMENTATION_COLOR_READ_FORMAT is SRGB_ALPHA which is not supported
            // by ReadPixels. So, just return RGBA here.
            if (i == LOCAL_GL_SRGB_ALPHA)
                i = LOCAL_GL_RGBA;

            return JS::NumberValue(uint32_t(i));
        }
        // int
        case LOCAL_GL_STENCIL_REF:
        case LOCAL_GL_STENCIL_BACK_REF: {
            GLint stencilBits = 0;
            if (!GetStencilBits(&stencilBits))
                return JS::NullValue();

            // Assuming stencils have 8 bits
            const GLint stencilMask = (1 << stencilBits) - 1;

            GLint refValue = 0;
            gl->fGetIntegerv(pname, &refValue);

            return JS::Int32Value(refValue & stencilMask);
        }
        case LOCAL_GL_STENCIL_BITS: {
            GLint stencilBits = 0;
            GetStencilBits(&stencilBits);
            return JS::Int32Value(stencilBits);
        }
        case LOCAL_GL_STENCIL_CLEAR_VALUE:
        case LOCAL_GL_UNPACK_ALIGNMENT:
        case LOCAL_GL_PACK_ALIGNMENT:
        case LOCAL_GL_SUBPIXEL_BITS:
        case LOCAL_GL_SAMPLE_BUFFERS:
        case LOCAL_GL_SAMPLES:
        case LOCAL_GL_MAX_VERTEX_ATTRIBS:
        case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
        case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
        case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
        case LOCAL_GL_RED_BITS:
        case LOCAL_GL_GREEN_BITS:
        case LOCAL_GL_BLUE_BITS: {
            GLint i = 0;
            gl->fGetIntegerv(pname, &i);
            return JS::Int32Value(i);
        }
        case LOCAL_GL_DEPTH_BITS: {
            GLint i = 0;
            if (!mNeedsFakeNoDepth) {
                gl->fGetIntegerv(pname, &i);
            }
            return JS::Int32Value(i);
        }
        case LOCAL_GL_ALPHA_BITS: {
            GLint i = 0;
            if (!mNeedsFakeNoAlpha) {
                gl->fGetIntegerv(pname, &i);
            }
            return JS::Int32Value(i);
        }
        case LOCAL_GL_MAX_TEXTURE_SIZE:
            return JS::Int32Value(mImplMaxTextureSize);

        case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
            return JS::Int32Value(mImplMaxCubeMapTextureSize);

        case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
            return JS::Int32Value(mImplMaxRenderbufferSize);

        case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
            return JS::Int32Value(mGLMaxVertexUniformVectors);

        case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
            return JS::Int32Value(mGLMaxFragmentUniformVectors);

        case LOCAL_GL_MAX_VARYING_VECTORS:
            return JS::Int32Value(mGLMaxVaryingVectors);

        case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS: {
            uint32_t length = mCompressedTextureFormats.Length();
            JSObject* obj = dom::Uint32Array::Create(cx, this, length,
                                                     mCompressedTextureFormats.Elements());
            if (!obj) {
                rv = NS_ERROR_OUT_OF_MEMORY;
            }
            return JS::ObjectOrNullValue(obj);
        }

        // unsigned int. here we may have to return very large values like 2^32-1 that can't be represented as
        // javascript integer values. We just return them as doubles and javascript doesn't care.
        case LOCAL_GL_STENCIL_BACK_VALUE_MASK:
            return JS::DoubleValue(mStencilValueMaskBack); // pass as FP value to allow large values such as 2^32-1.

        case LOCAL_GL_STENCIL_BACK_WRITEMASK:
            return JS::DoubleValue(mStencilWriteMaskBack);

        case LOCAL_GL_STENCIL_VALUE_MASK:
            return JS::DoubleValue(mStencilValueMaskFront);

        case LOCAL_GL_STENCIL_WRITEMASK:
            return JS::DoubleValue(mStencilWriteMaskFront);

        // float
        case LOCAL_GL_DEPTH_CLEAR_VALUE:
        case LOCAL_GL_LINE_WIDTH:
        case LOCAL_GL_POLYGON_OFFSET_FACTOR:
        case LOCAL_GL_POLYGON_OFFSET_UNITS:
        case LOCAL_GL_SAMPLE_COVERAGE_VALUE: {
            GLfloat f = 0.f;
            gl->fGetFloatv(pname, &f);
            return JS::DoubleValue(f);
        }

        // bool
        case LOCAL_GL_BLEND:
        case LOCAL_GL_DEPTH_TEST:
        case LOCAL_GL_STENCIL_TEST:
        case LOCAL_GL_CULL_FACE:
        case LOCAL_GL_DITHER:
        case LOCAL_GL_POLYGON_OFFSET_FILL:
        case LOCAL_GL_SCISSOR_TEST:
        case LOCAL_GL_SAMPLE_COVERAGE_INVERT:
        case LOCAL_GL_DEPTH_WRITEMASK: {
            realGLboolean b = 0;
            gl->fGetBooleanv(pname, &b);
            return JS::BooleanValue(bool(b));
        }

        // bool, WebGL-specific
        case UNPACK_FLIP_Y_WEBGL:
            return JS::BooleanValue(mPixelStore_FlipY);
        case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
            return JS::BooleanValue(mPixelStore_PremultiplyAlpha);

        // uint, WebGL-specific
        case UNPACK_COLORSPACE_CONVERSION_WEBGL:
            return JS::NumberValue(uint32_t(mPixelStore_ColorspaceConversion));

        ////////////////////////////////
        // Complex values

        // 2 floats
        case LOCAL_GL_DEPTH_RANGE:
        case LOCAL_GL_ALIASED_POINT_SIZE_RANGE:
        case LOCAL_GL_ALIASED_LINE_WIDTH_RANGE: {
            GLfloat fv[2] = { 0 };
            gl->fGetFloatv(pname, fv);
            JSObject* obj = dom::Float32Array::Create(cx, this, 2, fv);
            if (!obj) {
                rv = NS_ERROR_OUT_OF_MEMORY;
            }
            return JS::ObjectOrNullValue(obj);
        }

        // 4 floats
        case LOCAL_GL_COLOR_CLEAR_VALUE:
        case LOCAL_GL_BLEND_COLOR: {
            GLfloat fv[4] = { 0 };
            gl->fGetFloatv(pname, fv);
            JSObject* obj = dom::Float32Array::Create(cx, this, 4, fv);
            if (!obj) {
                rv = NS_ERROR_OUT_OF_MEMORY;
            }
            return JS::ObjectOrNullValue(obj);
        }

        // 2 ints
        case LOCAL_GL_MAX_VIEWPORT_DIMS: {
            GLint iv[2] = { 0 };
            gl->fGetIntegerv(pname, iv);
            JSObject* obj = dom::Int32Array::Create(cx, this, 2, iv);
            if (!obj) {
                rv = NS_ERROR_OUT_OF_MEMORY;
            }
            return JS::ObjectOrNullValue(obj);
        }

        // 4 ints
        case LOCAL_GL_SCISSOR_BOX:
        case LOCAL_GL_VIEWPORT: {
            GLint iv[4] = { 0 };
            gl->fGetIntegerv(pname, iv);
            JSObject* obj = dom::Int32Array::Create(cx, this, 4, iv);
            if (!obj) {
                rv = NS_ERROR_OUT_OF_MEMORY;
            }
            return JS::ObjectOrNullValue(obj);
        }

        // 4 bools
        case LOCAL_GL_COLOR_WRITEMASK: {
            realGLboolean gl_bv[4] = { 0 };
            gl->fGetBooleanv(pname, gl_bv);
            bool vals[4] = { bool(gl_bv[0]), bool(gl_bv[1]),
                             bool(gl_bv[2]), bool(gl_bv[3]) };
            JS::Rooted<JS::Value> arr(cx);
            if (!dom::ToJSValue(cx, vals, &arr)) {
                rv = NS_ERROR_OUT_OF_MEMORY;
            }
            return arr;
        }

        case LOCAL_GL_ARRAY_BUFFER_BINDING: {
            return WebGLObjectAsJSValue(cx, mBoundArrayBuffer.get(), rv);
        }

        case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING: {
            return WebGLObjectAsJSValue(cx, mBoundVertexArray->mElementArrayBuffer.get(), rv);
        }

        case LOCAL_GL_RENDERBUFFER_BINDING: {
            return WebGLObjectAsJSValue(cx, mBoundRenderbuffer.get(), rv);
        }

        // DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
        case LOCAL_GL_FRAMEBUFFER_BINDING: {
            return WebGLObjectAsJSValue(cx, mBoundDrawFramebuffer.get(), rv);
        }

        case LOCAL_GL_CURRENT_PROGRAM: {
            return WebGLObjectAsJSValue(cx, mCurrentProgram.get(), rv);
        }

        case LOCAL_GL_TEXTURE_BINDING_2D: {
            return WebGLObjectAsJSValue(cx, mBound2DTextures[mActiveTexture].get(), rv);
        }

        case LOCAL_GL_TEXTURE_BINDING_CUBE_MAP: {
            return WebGLObjectAsJSValue(cx, mBoundCubeMapTextures[mActiveTexture].get(), rv);
        }

        default:
            break;
    }

    ErrorInvalidEnumInfo("getParameter: parameter", pname);
    return JS::NullValue();
}