コード例 #1
0
/**
 * Initialize us. If we are in a box get our alignment so we know what direction we are
 */
NS_IMETHODIMP
nsSplitterFrame::Init(nsIContent*      aContent,
                      nsIFrame*        aParent,
                      nsIFrame*        aPrevInFlow)
{
  NS_ENSURE_FALSE(mInner, NS_ERROR_ALREADY_INITIALIZED);
  mInner = new nsSplitterFrameInner(this);
  if (!mInner)
    return NS_ERROR_OUT_OF_MEMORY;

  mInner->AddRef();
  mInner->mChildInfosAfter = nullptr;
  mInner->mChildInfosBefore = nullptr;
  mInner->mState = nsSplitterFrameInner::Open;
  mInner->mDragging = false;

  // determine orientation of parent, and if vertical, set orient to vertical
  // on splitter content, then re-resolve style
  // XXXbz this is pretty messed up, since this can change whether we should
  // have a frame at all.  This really needs a better solution.
  if (aParent && aParent->IsBoxFrame()) {
    if (!aParent->IsHorizontal()) {
      if (!nsContentUtils::HasNonEmptyAttr(aContent, kNameSpaceID_None,
                                           nsGkAtoms::orient)) {
        aContent->SetAttr(kNameSpaceID_None, nsGkAtoms::orient,
                          NS_LITERAL_STRING("vertical"), false);
        nsStyleContext* parentStyleContext = GetStyleContext()->GetParent();
        nsRefPtr<nsStyleContext> newContext = PresContext()->StyleSet()->
          ResolveStyleFor(aContent->AsElement(), parentStyleContext);
        SetStyleContextWithoutNotification(newContext);
      }
    }
  }

  nsresult  rv = nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
  NS_ENSURE_SUCCESS(rv, rv);

  mInner->mState = nsSplitterFrameInner::Open;
  mInner->AddListener(PresContext());
  mInner->mParentBox = nullptr;
  return rv;
}
コード例 #2
0
NS_IMETHODIMP
nsSpeechTask::SendAudio(JS::Handle<JS::Value> aData, JS::Handle<JS::Value> aLandmarks,
                        JSContext* aCx)
{
  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);

  NS_ENSURE_TRUE(mStream, NS_ERROR_NOT_AVAILABLE);
  NS_ENSURE_FALSE(mStream->IsDestroyed(), NS_ERROR_NOT_AVAILABLE);
  NS_ENSURE_TRUE(mChannels, NS_ERROR_FAILURE);
  NS_ENSURE_TRUE(aData.isObject(), NS_ERROR_INVALID_ARG);

  if (mIndirectAudio) {
    NS_WARNING("Can't call SendAudio from an indirect audio speech service.");
    return NS_ERROR_FAILURE;
  }

  JS::Rooted<JSObject*> darray(aCx, &aData.toObject());
  JSAutoCompartment ac(aCx, darray);

  JS::Rooted<JSObject*> tsrc(aCx, nullptr);

  // Allow either Int16Array or plain JS Array
  if (JS_IsInt16Array(darray)) {
    tsrc = darray;
  } else if (JS_IsArrayObject(aCx, darray)) {
    tsrc = JS_NewInt16ArrayFromArray(aCx, darray);
  }

  if (!tsrc) {
    return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
  }

  uint32_t dataLen = JS_GetTypedArrayLength(tsrc);
  nsRefPtr<mozilla::SharedBuffer> samples;
  {
    JS::AutoCheckCannotGC nogc;
    samples = makeSamples(JS_GetInt16ArrayData(tsrc, nogc), dataLen);
  }
  SendAudioImpl(samples, dataLen);

  return NS_OK;
}
コード例 #3
0
nsresult
CacheStorageService::WalkStorageEntries(CacheStorage const* aStorage,
                                        bool aVisitEntries,
                                        nsICacheStorageVisitor* aVisitor)
{
  LOG(("CacheStorageService::WalkStorageEntries [cb=%p, visitentries=%d]", aVisitor, aVisitEntries));
  NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED);

  NS_ENSURE_ARG(aStorage);

  if (aStorage->WriteToDisk()) {
    nsRefPtr<WalkDiskCacheRunnable> event =
      new WalkDiskCacheRunnable(aStorage->LoadInfo(), aVisitEntries, aVisitor);
    return event->Walk();
  }

  nsRefPtr<WalkMemoryCacheRunnable> event =
    new WalkMemoryCacheRunnable(aStorage->LoadInfo(), aVisitEntries, aVisitor);
  return event->Walk();
}
コード例 #4
0
nsresult sbRequestThreadQueue::Start()
{
  TRACE_FUNCTION("");
  // Ensure we've allocated our lock and monitor
  NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
  NS_ENSURE_TRUE(mStopWaitMonitor, NS_ERROR_OUT_OF_MEMORY);

  nsresult rv;

  // No need to lock since Start should not be called while the request thread
  // is running or from multiple threads.
  // Start should not be called more than once before Stop is called.
  NS_ENSURE_FALSE(mThreadStarted, NS_ERROR_FAILURE);

  // Clear the stop request processing flag. No need to lock since this is
  // the only live thread with access to the object.
  mStopProcessing = false;

  // Create the request added event object.
  rv = sbRTQAddedEvent::New(this, getter_AddRefs(mReqAddedEvent));
  NS_ENSURE_SUCCESS(rv, rv);


  rv = sbRunnableMethod(*this,
                        &sbRequestThreadQueue::ThreadShutdownAction,
                        NS_ERROR_FAILURE,
                        0,
                        getter_AddRefs(mShutdownAction));
  NS_ENSURE_SUCCESS(rv, rv);

  mThreadStarted = true;

  // Create the request processing thread.
  rv = NS_NewThread(getter_AddRefs(mThread), nsnull);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = PushRequest(sbRequestItem::New(REQUEST_THREAD_START));
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
コード例 #5
0
NS_IMETHODIMP
Service::SetQuotaForFilenamePattern(const nsACString &aPattern,
                                    PRInt64 aSizeLimit,
                                    mozIStorageQuotaCallback *aCallback,
                                    nsISupports *aUserData)
{
  NS_ENSURE_FALSE(aPattern.IsEmpty(), NS_ERROR_INVALID_ARG);

  nsAutoPtr<QuotaCallbackData> data;
  if (aSizeLimit && aCallback) {
    data = new QuotaCallbackData(aCallback, aUserData);
  }

  int rc = ::sqlite3_quota_set(PromiseFlatCString(aPattern).get(),
                               aSizeLimit, QuotaCallbackData::Callback,
                               data, QuotaCallbackData::Destroy);
  NS_ENSURE_TRUE(rc == SQLITE_OK, convertResultCode(rc));

  data.forget();
  return NS_OK;
}
コード例 #6
0
NS_IMETHODIMP sbTagLibChannelFileIOManager::GetChannel(
    const nsACString            &aChannelID,
    sbISeekableChannel          **_retval)
{
    sbTagLibChannelFileIOManager::Channel   *pChannel;
    nsresult                                rv;

    /* Validate parameters. */
    NS_ENSURE_FALSE(aChannelID.IsEmpty(), NS_ERROR_INVALID_ARG);
    NS_ENSURE_ARG_POINTER(_retval);

    /* Get the metadata channel. */
    rv = GetChannel(aChannelID, &pChannel);
    if (NS_FAILED(rv))
        return (rv);

    /* Return results. */
    NS_ADDREF(*_retval = pChannel->pSeekableChannel);

    return (NS_OK);
}
コード例 #7
0
NS_IMETHODIMP
BindingParams::BindByIndex(uint32_t aIndex,
                           nsIVariant *aValue)
{
  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
  ENSURE_INDEX_VALUE(aIndex, mParamCount);

  // Store the variant for later use.
  RefPtr<Variant_base> variant = convertVariantToStorageVariant(aValue);
  if (!variant)
    return NS_ERROR_UNEXPECTED;
  if (mParameters.Length() <= aIndex) {
    (void)mParameters.SetLength(aIndex);
    (void)mParameters.AppendElement(variant);
  }
  else {
    NS_ENSURE_TRUE(mParameters.ReplaceElementAt(aIndex, variant),
                   NS_ERROR_OUT_OF_MEMORY);
  }
  return NS_OK;
}
コード例 #8
0
NS_IMETHODIMP
AsyncBindingParams::BindByIndex(uint32_t aIndex,
                                nsIVariant *aValue)
{
  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
  // In the asynchronous case we do not know how many parameters there are to
  // bind to, so we cannot check the validity of aIndex.

  RefPtr<Variant_base> variant = convertVariantToStorageVariant(aValue);
  if (!variant)
    return NS_ERROR_UNEXPECTED;
  if (mParameters.Length() <= aIndex) {
    mParameters.SetLength(aIndex);
    mParameters.AppendElement(variant);
  }
  else {
    NS_ENSURE_TRUE(mParameters.ReplaceElementAt(aIndex, variant),
                   NS_ERROR_OUT_OF_MEMORY);
  }
  return NS_OK;
}
コード例 #9
0
ファイル: TabContext.cpp プロジェクト: JCROM-FxOS/b2jc_gecko
bool
TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp,
                                         ScrollingBehavior aRequestedBehavior)
{
  NS_ENSURE_FALSE(mInitialized, false);

  uint32_t containingAppId = NO_APP_ID;
  if (aBrowserFrameOwnerApp) {
    nsresult rv = aBrowserFrameOwnerApp->GetLocalId(&containingAppId);
    NS_ENSURE_SUCCESS(rv, false);
    NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
  }

  mInitialized = true;
  mIsBrowser = true;
  mOwnAppId = NO_APP_ID;
  mContainingAppId = containingAppId;
  mScrollingBehavior = aRequestedBehavior;
  mContainingApp = aBrowserFrameOwnerApp;
  return true;
}
コード例 #10
0
NS_IMETHODIMP sbTagLibChannelFileIOManager::GetChannelRestart(
    const nsACString            &aChannelID,
    PRBool                      *_retval)
{
    sbTagLibChannelFileIOManager::Channel   *pChannel;
    PRBool                                  restart;
    nsresult                                rv;

    /* Validate parameters. */
    NS_ENSURE_FALSE(aChannelID.IsEmpty(), NS_ERROR_INVALID_ARG);
    NS_ENSURE_ARG_POINTER(_retval);

    /* Get the channel restart flag. */
    rv = GetChannel(aChannelID, &pChannel);
    NS_ENSURE_SUCCESS(rv, rv);
    restart = pChannel->restart;

    /* Return results. */
    *_retval = restart;

    return (NS_OK);
}
コード例 #11
0
ファイル: inFlasher.cpp プロジェクト: lofter2011/Icefox
NS_IMETHODIMP
inFlasher::SetColor(const nsAString& aColor)
{
    NS_ENSURE_FALSE(aColor.IsEmpty(), NS_ERROR_ILLEGAL_VALUE);

    nsAutoString colorStr;
    colorStr.Assign(aColor);

    if (colorStr.CharAt(0) != '#') {
        if (NS_ColorNameToRGB(colorStr, &mColor)) {
            return NS_OK;
        }
    }
    else {
        colorStr.Cut(0, 1);
        if (NS_HexToRGB(colorStr, &mColor)) {
            return NS_OK;
        }
    }

    return NS_ERROR_ILLEGAL_VALUE;
}
コード例 #12
0
nsresult
Connection::setClosedState()
{
  // Ensure that we are on the correct thread to close the database.
  PRBool onOpenedThread;
  nsresult rv = threadOpenedOn->IsOnCurrentThread(&onOpenedThread);
  NS_ENSURE_SUCCESS(rv, rv);
  if (!onOpenedThread) {
    NS_ERROR("Must close the database on the thread that you opened it with!");
    return NS_ERROR_UNEXPECTED;
  }

  // Flag that we are shutting down the async thread, so that
  // getAsyncExecutionTarget knows not to expose/create the async thread.
  {
    MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
    NS_ENSURE_FALSE(mAsyncExecutionThreadShuttingDown, NS_ERROR_UNEXPECTED);
    mAsyncExecutionThreadShuttingDown = true;
  }

  return NS_OK;
}
コード例 #13
0
NS_IMETHODIMP sbTagLibChannelFileIOManager::AddChannel(
    const nsACString            &aChannelID,
    sbISeekableChannel          *aChannel)
{
    nsAutoPtr<sbTagLibChannelFileIOManager::Channel> pChannel;
    PRBool                                           success;

    /* Validate parameters. */
    NS_ENSURE_FALSE(aChannelID.IsEmpty(), NS_ERROR_INVALID_ARG);
    NS_ENSURE_ARG_POINTER(aChannel);

    /* Create a new channel object. */
    pChannel = new sbTagLibChannelFileIOManager::Channel(aChannel);
    NS_ENSURE_TRUE(pChannel, NS_ERROR_OUT_OF_MEMORY);

    /* Add the channel to the channel map. */
    success = mChannelMap.Put(aChannelID, pChannel);
    NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
    pChannel.forget();

    return (NS_OK);
}
コード例 #14
0
NS_IMETHODIMP
calDateTime::AddDuration(calIDuration *aDuration)
{
    NS_ENSURE_FALSE(mImmutable, NS_ERROR_OBJECT_IS_IMMUTABLE);
    NS_ENSURE_ARG_POINTER(aDuration);
    ensureTimezone();

    nsresult rv;
    nsCOMPtr<calIDurationLibical> icaldur = do_QueryInterface(aDuration, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    icaldurationtype idt;
    icaldur->ToIcalDuration(&idt);

    icaltimetype itt;
    ToIcalTime(&itt);

    icaltimetype const newitt = icaltime_add(itt, idt);
    FromIcalTime(&newitt, mTimezone);

    return NS_OK;
}
コード例 #15
0
NS_IMETHODIMP
AsyncExecuteStatements::Cancel()
{
#ifdef DEBUG
  bool onCallingThread = false;
  (void)mCallingThread->IsOnCurrentThread(&onCallingThread);
  NS_ASSERTION(onCallingThread, "Not canceling from the calling thread!");
#endif

  // If we have already canceled, we have an error, but always indicate that
  // we are trying to cancel.
  NS_ENSURE_FALSE(mCancelRequested, NS_ERROR_UNEXPECTED);

  {
    MutexAutoLock lockedScope(mMutex);

    // We need to indicate that we want to try and cancel now.
    mCancelRequested = true;
  }

  return NS_OK;
}
コード例 #16
0
ファイル: calDateTime.cpp プロジェクト: dualsky/FossaMail
NS_IMETHODIMP
calDateTime::ResetTo(int16_t year,
                     int16_t month,
                     int16_t day,
                     int16_t hour,
                     int16_t minute,
                     int16_t second,
                     calITimezone * tz)
{
    NS_ENSURE_FALSE(mImmutable, NS_ERROR_OBJECT_IS_IMMUTABLE);
    NS_ENSURE_ARG_POINTER(tz);
    mYear = year;
    mMonth = month;
    mDay = day;
    mHour = hour;
    mMinute = minute;
    mSecond = second;
    mIsDate = false;
    mTimezone = tz;
    Normalize();
    return NS_OK;
}
コード例 #17
0
NS_IMETHODIMP
nsGZFileWriter::Write(const nsACString& aStr)
{
  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
  NS_ENSURE_FALSE(mFinished, NS_ERROR_FAILURE);

  // gzwrite uses a return value of 0 to indicate failure.  Otherwise, it
  // returns the number of uncompressed bytes written.  To ensure we can
  // distinguish between success and failure, don't call gzwrite when we have 0
  // bytes to write.
  if (aStr.IsEmpty()) {
    return NS_OK;
  }

  // gzwrite never does a short write -- that is, the return value should
  // always be either 0 or aStr.Length(), and we shouldn't have to call it
  // multiple times in order to get it to read the whole buffer.
  int rv = gzwrite(mGZFile, aStr.BeginReading(), aStr.Length());
  NS_ENSURE_TRUE(rv == static_cast<int>(aStr.Length()), NS_ERROR_FAILURE);

  return NS_OK;
}
コード例 #18
0
NS_IMETHODIMP 
sbDeviceFirmwareUpdater::RegisterHandler(sbIDeviceFirmwareHandler *aFirmwareHandler)
{
  LOG(("[sbDeviceFirmwareUpdater] - RegisterHandler"));

  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
  NS_ENSURE_ARG_POINTER(aFirmwareHandler);

  nsString contractId;
  nsresult rv = aFirmwareHandler->GetContractId(contractId);
  NS_ENSURE_SUCCESS(rv, rv);

  NS_ConvertUTF16toUTF8 contractId8(contractId);
  
  nsAutoMonitor mon(mMonitor);
  if(!mFirmwareHandlers.Contains(contractId8)) {
    nsCString *element = mFirmwareHandlers.AppendElement(contractId8);
    NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
  }

  return NS_OK;
}
コード例 #19
0
NS_IMETHODIMP sbTagLibChannelFileIOManager::GetChannelSize(
    const nsACString            &aChannelID,
    PRUint64                    *_retval)
{
    sbTagLibChannelFileIOManager::Channel   *pChannel;
    PRUint64                                size = 0;
    nsresult                                rv;

    /* Validate parameters. */
    NS_ENSURE_FALSE(aChannelID.IsEmpty(), NS_ERROR_INVALID_ARG);
    NS_ENSURE_ARG_POINTER(_retval);

    /* Get the channel size. */
    rv = GetChannel(aChannelID, &pChannel);
    NS_ENSURE_SUCCESS(rv, rv);
    rv = pChannel->pSeekableChannel->GetSize(&size);
    NS_ENSURE_SUCCESS(rv, rv);

    /* Return results. */
    *_retval = size;

    return (NS_OK);
}
コード例 #20
0
ファイル: calDateTime.cpp プロジェクト: SecareLupus/Drood
NS_IMETHODIMP
calDateTime::Reset()
{
    NS_ENSURE_FALSE(mImmutable, NS_ERROR_OBJECT_IS_IMMUTABLE);
    mYear = 1970;
    mMonth = 0;
    mDay = 1;
    mHour = 0;
    mMinute = 0;
    mSecond = 0;
    mWeekday = 4;
    mYearday = 1;
    mIsDate = PR_FALSE;
#if 1
    nsCOMPtr<calITimezoneService> tzSvc =
      do_GetService(CAL_TIMEZONESERVICE_CONTRACTID);
    tzSvc->GetUTC(getter_AddRefs(mTimezone));
#else
    cal::getTimezoneService()->GetUTC(getter_AddRefs(mTimezone));
#endif
    mNativeTime = 0;
    mIsValid = PR_TRUE;
    return NS_OK;
}
コード例 #21
0
bool
TabContext::SetTabContext(const TabContext& aContext)
{
  NS_ENSURE_FALSE(mInitialized, false);

  // Verify that we can actually get apps for the given ids.  This step gives us
  // confidence that HasX() returns true iff GetX() returns true.
  if (aContext.mOwnAppId != nsIScriptSecurityManager::NO_APP_ID) {
    nsCOMPtr<mozIApplication> app = GetAppForId(aContext.mOwnAppId);
    NS_ENSURE_TRUE(app, false);
  }

  if (aContext.mContainingAppId != nsIScriptSecurityManager::NO_APP_ID) {
    nsCOMPtr<mozIApplication> app = GetAppForId(aContext.mContainingAppId);
    NS_ENSURE_TRUE(app, false);
  }

  mInitialized = true;
  mIsBrowser = aContext.mIsBrowser;
  mOwnAppId = aContext.mOwnAppId;
  mContainingAppId = aContext.mContainingAppId;
  mScrollingBehavior = aContext.mScrollingBehavior;
  return true;
}
コード例 #22
0
NS_IMETHODIMP
sbDeviceFirmwareUpdater::Cancel(sbIDevice *aDevice) 
{
  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
  NS_ENSURE_ARG_POINTER(aDevice);

  nsAutoMonitor mon(mMonitor);
  
  nsCOMPtr<sbIDeviceFirmwareHandler> handler = GetRunningHandler(aDevice);

  if(handler) {
    nsresult rv = handler->Cancel();
    NS_ENSURE_SUCCESS(rv, rv);

    rv = handler->Unbind();
    NS_ENSURE_SUCCESS(rv, rv);

    mRunningHandlers.Remove(aDevice);
    mHandlerStatus.Remove(handler);
  }

  return NS_OK;
}
コード例 #23
0
nsresult
nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal)
{
  // Copied from nsAppFileLocationProvider (more or less)
  nsresult rv;
  nsCOMPtr<nsIFile> localDir;

#if defined(XP_MACOSX)
  FSRef fsRef;
  OSType folderType;
  if (aLocal) {
    folderType = kCachedDataFolderType;
  } else {
#ifdef MOZ_THUNDERBIRD
    folderType = kDomainLibraryFolderType;
#else
    folderType = kApplicationSupportFolderType;
#endif
  }
  OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
  NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);

  rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
  NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);

  rv = dirFileMac->InitWithFSRef(&fsRef);
  NS_ENSURE_SUCCESS(rv, rv);

  localDir = do_QueryInterface(dirFileMac, &rv);
#elif defined(XP_IOS)
  nsAutoCString userDir;
  if (GetUIKitDirectory(aLocal, userDir)) {
    rv = NS_NewNativeLocalFile(userDir, true, getter_AddRefs(localDir));
  } else {
    rv = NS_ERROR_FAILURE;
  }
  NS_ENSURE_SUCCESS(rv, rv);
#elif defined(XP_WIN)
  nsString path;
  if (aLocal) {
    rv = GetShellFolderPath(CSIDL_LOCAL_APPDATA, path);
    if (NS_FAILED(rv))
      rv = GetRegWindowsAppDataFolder(aLocal, path);
  }
  if (!aLocal || NS_FAILED(rv)) {
    rv = GetShellFolderPath(CSIDL_APPDATA, path);
    if (NS_FAILED(rv)) {
      if (!aLocal)
        rv = GetRegWindowsAppDataFolder(aLocal, path);
    }
  }
  NS_ENSURE_SUCCESS(rv, rv);

  rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
#elif defined(MOZ_WIDGET_GONK)
  rv = NS_NewNativeLocalFile(NS_LITERAL_CSTRING("/data/b2g"), true,
                             getter_AddRefs(localDir));
#elif defined(XP_UNIX)
  const char* homeDir = getenv("HOME");
  if (!homeDir || !*homeDir)
    return NS_ERROR_FAILURE;

#ifdef ANDROID /* We want (ProfD == ProfLD) on Android. */
  aLocal = false;
#endif

  if (aLocal) {
    // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache.
    const char* cacheHome = getenv("XDG_CACHE_HOME");
    if (cacheHome && *cacheHome) {
      rv = NS_NewNativeLocalFile(nsDependentCString(cacheHome), true,
                                 getter_AddRefs(localDir));
    } else {
      rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
                                 getter_AddRefs(localDir));
      if (NS_SUCCEEDED(rv))
        rv = localDir->AppendNative(NS_LITERAL_CSTRING(".cache"));
    }
  } else {
    rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
                               getter_AddRefs(localDir));
  }
#else
#error "Don't know how to get product dir on your platform"
#endif

  NS_IF_ADDREF(*aFile = localDir);
  return rv;
}
コード例 #24
0
nsresult
CacheStorageService::DoomStorageEntry(CacheStorage const* aStorage,
                                      nsIURI *aURI,
                                      const nsACString & aIdExtension,
                                      nsICacheEntryDoomCallback* aCallback)
{
  LOG(("CacheStorageService::DoomStorageEntry"));

  NS_ENSURE_ARG(aStorage);
  NS_ENSURE_ARG(aURI);

  nsAutoCString contextKey;
  CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey);

  nsAutoCString entryKey;
  nsresult rv = CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURI, entryKey);
  NS_ENSURE_SUCCESS(rv, rv);

  nsRefPtr<CacheEntry> entry;
  {
    mozilla::MutexAutoLock lock(mLock);

    NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED);

    CacheEntryTable* entries;
    if (sGlobalEntryTables->Get(contextKey, &entries)) {
      if (entries->Get(entryKey, getter_AddRefs(entry))) {
        if (aStorage->WriteToDisk() || !entry->IsUsingDiskLocked()) {
          // When evicting from disk storage, purge
          // When evicting from memory storage and the entry is memory-only, purge
          LOG(("  purging entry %p for %s [storage use disk=%d, entry use disk=%d]",
            entry.get(), entryKey.get(), aStorage->WriteToDisk(), entry->IsUsingDiskLocked()));
          entries->Remove(entryKey);
        }
        else {
          // Otherwise, leave it
          LOG(("  leaving entry %p for %s [storage use disk=%d, entry use disk=%d]",
            entry.get(), entryKey.get(), aStorage->WriteToDisk(), entry->IsUsingDiskLocked()));
          entry = nullptr;
        }
      }
    }
  }

  if (entry) {
    LOG(("  dooming entry %p for %s", entry.get(), entryKey.get()));
    return entry->AsyncDoom(aCallback);
  }

  LOG(("  no entry loaded for %s", entryKey.get()));

  if (aStorage->WriteToDisk()) {
    nsAutoCString contextKey;
    CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey);

    rv = CacheEntry::HashingKey(contextKey, aIdExtension, aURI, entryKey);
    NS_ENSURE_SUCCESS(rv, rv);

    LOG(("  dooming file only for %s", entryKey.get()));

    nsRefPtr<CacheEntryDoomByKeyCallback> callback(
      new CacheEntryDoomByKeyCallback(aCallback));
    rv = CacheFileIOManager::DoomFileByKey(entryKey, callback);
    NS_ENSURE_SUCCESS(rv, rv);

    return NS_OK;
  }

  if (aCallback)
    aCallback->OnCacheEntryDoomed(NS_ERROR_NOT_AVAILABLE);

  return NS_OK;
}
コード例 #25
0
nsresult
CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
                                     nsIURI* aURI,
                                     const nsACString & aIdExtension,
                                     bool aWriteToDisk,
                                     bool aCreateIfNotExist,
                                     bool aReplace,
                                     CacheEntryHandle** aResult)
{
  NS_ENSURE_ARG(aURI);

  nsresult rv;

  nsAutoCString entryKey;
  rv = CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURI, entryKey);
  NS_ENSURE_SUCCESS(rv, rv);

  LOG(("CacheStorageService::AddStorageEntry [entryKey=%s, contextKey=%s]",
    entryKey.get(), aContextKey.BeginReading()));

  nsRefPtr<CacheEntry> entry;
  nsRefPtr<CacheEntryHandle> handle;

  {
    mozilla::MutexAutoLock lock(mLock);

    NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED);

    // Ensure storage table
    CacheEntryTable* entries;
    if (!sGlobalEntryTables->Get(aContextKey, &entries)) {
      entries = new CacheEntryTable(CacheEntryTable::ALL_ENTRIES);
      sGlobalEntryTables->Put(aContextKey, entries);
      LOG(("  new storage entries table for context %s", aContextKey.BeginReading()));
    }

    bool entryExists = entries->Get(entryKey, getter_AddRefs(entry));

    // check whether the file is already doomed
    if (entryExists && entry->IsFileDoomed() && !aReplace) {
      aReplace = true;
    }

    // If truncate is demanded, delete and doom the current entry
    if (entryExists && aReplace) {
      entries->Remove(entryKey);

      LOG(("  dooming entry %p for %s because of OPEN_TRUNCATE", entry.get(), entryKey.get()));
      // On purpose called under the lock to prevent races of doom and open on I/O thread
      // No need to remove from both memory-only and all-entries tables.  The new entry
      // will overwrite the shadow entry in its ctor.
      entry->DoomAlreadyRemoved();

      entry = nullptr;
      entryExists = false;
    }

    if (entryExists && entry->SetUsingDisk(aWriteToDisk)) {
      RecordMemoryOnlyEntry(entry, !aWriteToDisk, true /* overwrite */);
    }

    // Ensure entry for the particular URL, if not read/only
    if (!entryExists && (aCreateIfNotExist || aReplace)) {
      // Entry is not in the hashtable or has just been truncated...
      entry = new CacheEntry(aContextKey, aURI, aIdExtension, aWriteToDisk);
      entries->Put(entryKey, entry);
      LOG(("  new entry %p for %s", entry.get(), entryKey.get()));
    }

    if (entry) {
      // Here, if this entry was not for a long time referenced by any consumer,
      // gets again first 'handles count' reference.
      handle = entry->NewHandle();
    }
  }

  handle.forget(aResult);
  return NS_OK;
}
コード例 #26
0
nsresult
DASHRepDecoder::GetByteRangeForSeek(int64_t const aOffset,
                                    MediaByteRange& aByteRange)
{
  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");

  // Only check data ranges if they're available and if this decoder is active,
  // i.e. inactive rep decoders should only load metadata.
  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());

  for (uint32_t i = 0; i < mByteRanges.Length(); i++) {
    NS_ENSURE_FALSE(mByteRanges[i].IsNull(), NS_ERROR_NOT_INITIALIZED);
    // Check if |aOffset| lies within the current data range.
    if (mByteRanges[i].mStart <= aOffset && aOffset <= mByteRanges[i].mEnd) {
      if (mMainDecoder->IsDecoderAllowedToDownloadSubsegment(this, i)) {
        mCurrentByteRange = aByteRange = mByteRanges[i];
        mSubsegmentIdx = i;
        // XXX Hack: should be setting subsegment outside this function, but
        // need to review seeking for multiple switches anyhow.
        mMainDecoder->SetSubsegmentIndex(this, i);
        LOG("Getting DATA range [%d] for seek offset [%lld]: "
            "bytes [%lld] to [%lld]",
            i, aOffset, aByteRange.mStart, aByteRange.mEnd);
        return NS_OK;
      }
      break;
    }
  }
  // Don't allow metadata downloads once they're loaded and byte ranges have
  // been populated.
  bool canDownloadMetadata = mByteRanges.IsEmpty();
  if (canDownloadMetadata) {
    // Check metadata ranges; init range.
    if (mInitByteRange.mStart <= aOffset && aOffset <= mInitByteRange.mEnd) {
      mCurrentByteRange = aByteRange = mInitByteRange;
      mSubsegmentIdx = 0;
        LOG("Getting INIT range for seek offset [%lld]: bytes [%lld] to "
            "[%lld]", aOffset, aByteRange.mStart, aByteRange.mEnd);
      return NS_OK;
    }
    // ... index range.
    if (mIndexByteRange.mStart <= aOffset && aOffset <= mIndexByteRange.mEnd) {
      mCurrentByteRange = aByteRange = mIndexByteRange;
      mSubsegmentIdx = 0;
      LOG("Getting INDEXES range for seek offset [%lld]: bytes [%lld] to "
          "[%lld]", aOffset, aByteRange.mStart, aByteRange.mEnd);
      return NS_OK;
    }
  } else {
    LOG1("Metadata should be read; inhibiting further metadata downloads.");
  }

  // If no byte range is found by this stage, clear the parameter and return.
  aByteRange.Clear();
  if (mByteRanges.IsEmpty() || !canDownloadMetadata) {
    // Assume mByteRanges will be populated after metadata is read.
    LOG("Data ranges not populated [%s]; metadata download restricted [%s]: "
        "offset[%lld].",
        (mByteRanges.IsEmpty() ? "yes" : "no"),
        (canDownloadMetadata ? "no" : "yes"), aOffset);
    return NS_ERROR_NOT_AVAILABLE;
  } else {
    // Cannot seek to an unknown offset.
    // XXX Revisit this for dynamic MPD profiles if MPD is regularly updated.
    LOG("Error! Offset [%lld] is in an unknown range!", aOffset);
    return NS_ERROR_ILLEGAL_VALUE;
  }
}
コード例 #27
0
/**
 * See sbIMediaList
 */
NS_IMETHODIMP
sbLocalDatabaseMediaListBase::EnumerateItemsByProperty(const nsAString& aID,
                                                       const nsAString& aValue,
                                                       sbIMediaListEnumerationListener* aEnumerationListener,
                                                       PRUint16 aEnumerationType)
{
  NS_ENSURE_ARG_POINTER(aEnumerationListener);

  nsresult rv = NS_ERROR_UNEXPECTED;

  // A property id must be specified.
  NS_ENSURE_TRUE(!aID.IsEmpty(), NS_ERROR_INVALID_ARG);

  // Get the sortable format of the value
  nsCOMPtr<sbIPropertyManager> propMan =
    do_GetService(SB_PROPERTYMANAGER_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<sbIPropertyInfo> info;
  rv = propMan->GetPropertyInfo(aID, getter_AddRefs(info));
  NS_ENSURE_SUCCESS(rv, rv);

  nsAutoString sortableValue;
  rv = info->MakeSortable(aValue, sortableValue);
  NS_ENSURE_SUCCESS(rv, rv);

  // Make a single-item string array to hold our property value.
  sbStringArray valueArray(1);
  nsString* value = valueArray.AppendElement(sortableValue);
  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);

  // Make a string enumerator for it.
  nsCOMPtr<nsIStringEnumerator> valueEnum =
    new sbTArrayStringEnumerator(&valueArray);
  NS_ENSURE_TRUE(valueEnum, NS_ERROR_OUT_OF_MEMORY);

  switch (aEnumerationType) {

    case sbIMediaList::ENUMERATIONTYPE_LOCKING: {
      mozilla::MonitorAutoLock mon(mFullArrayMonitor);

      // Don't reenter!
      NS_ENSURE_FALSE(mLockedEnumerationActive, NS_ERROR_FAILURE);
      mLockedEnumerationActive = PR_TRUE;

      PRUint16 stepResult;
      rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);

      if (NS_SUCCEEDED(rv)) {
        if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
          rv = EnumerateItemsByPropertyInternal(aID, valueEnum,
                                                aEnumerationListener);
        }
        else {
          // The user cancelled the enumeration.
          rv = NS_ERROR_ABORT;
        }
      }

      mLockedEnumerationActive = PR_FALSE;

    } break; // ENUMERATIONTYPE_LOCKING

    case sbIMediaList::ENUMERATIONTYPE_SNAPSHOT: {
      PRUint16 stepResult;
      rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);

      if (NS_SUCCEEDED(rv)) {
        if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
          rv = EnumerateItemsByPropertyInternal(aID, valueEnum,
                                                aEnumerationListener);
        }
        else {
          // The user cancelled the enumeration.
          rv = NS_ERROR_ABORT;
        }
      }
    } break; // ENUMERATIONTYPE_SNAPSHOT

    default: {
      NS_NOTREACHED("Invalid enumeration type");
      rv = NS_ERROR_INVALID_ARG;
    } break;
  }

  aEnumerationListener->OnEnumerationEnd(this, rv);
  return NS_OK;
}
コード例 #28
0
/**
 * See sbIMediaList
 */
NS_IMETHODIMP
sbLocalDatabaseMediaListBase::EnumerateItemsByProperties(sbIPropertyArray* aProperties,
                                                         sbIMediaListEnumerationListener* aEnumerationListener,
                                                         PRUint16 aEnumerationType)
{
  NS_ENSURE_ARG_POINTER(aProperties);
  NS_ENSURE_ARG_POINTER(aEnumerationListener);

  PRUint32 propertyCount;
  nsresult rv = aProperties->GetLength(&propertyCount);
  NS_ENSURE_SUCCESS(rv, rv);

  // It doesn't make sense to call this method without specifying any properties
  // so it is probably a caller error if we have none.
  NS_ENSURE_STATE(propertyCount);

  // The guidArray needs AddFilter called only once per property with an
  // enumerator that contains all the values. We were given an array of
  // id/value pairs, so this is a little tricky. We make a hash table that
  // uses the property id for a key and an array of values as its data. Then
  // we load the arrays in a loop and finally call AddFilter as an enumeration
  // function.

  sbStringArrayHash propertyHash;

  // Init with the propertyCount as the number of buckets to create. This will
  // probably be too many, but it's likely less than the default of 16.
  propertyHash.Init(propertyCount);

  nsCOMPtr<sbIPropertyManager> propMan =
    do_GetService(SB_PROPERTYMANAGER_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // Load the hash table with properties from the array.
  for (PRUint32 index = 0; index < propertyCount; index++) {

    // Get the property.
    nsCOMPtr<sbIProperty> property;
    rv = aProperties->GetPropertyAt(index, getter_AddRefs(property));
    SB_CONTINUE_IF_FAILED(rv);

    // Get the id of the property. This will be the key for the hash table.
    nsString propertyID;
    rv = property->GetId(propertyID);
    SB_CONTINUE_IF_FAILED(rv);

    // Get the string array associated with the key. If it doesn't yet exist
    // then we need to create it.
    sbStringArray* stringArray;
    PRBool arrayExists = propertyHash.Get(propertyID, &stringArray);
    if (!arrayExists) {
      stringArray = new sbStringArray;
      SB_CONTINUE_IF_FALSE(stringArray);

      // Try to add the array to the hash table.
      PRBool success = propertyHash.Put(propertyID, stringArray);
      if (!success) {
        NS_WARNING("Failed to add string array to property hash!");

        // Make sure to delete the new array, otherwise it will leak.
        delete stringArray;
        continue;
      }
    }
    NS_ASSERTION(stringArray, "Must have a valid pointer here!");

    // Now we need a slot for the property value.
    nsString* valueString = stringArray->AppendElement();
    SB_CONTINUE_IF_FALSE(valueString);

    // Make the value sortable and assign it
    nsCOMPtr<sbIPropertyInfo> info;
    rv = propMan->GetPropertyInfo(propertyID, getter_AddRefs(info));
    SB_CONTINUE_IF_FAILED(rv);

    nsAutoString value;
    rv = property->GetValue(value);
    SB_CONTINUE_IF_FAILED(rv);

    nsAutoString sortableValue;
    rv = info->MakeSortable(value, *valueString);
    SB_CONTINUE_IF_FAILED(rv);
  }

  switch (aEnumerationType) {

    case sbIMediaList::ENUMERATIONTYPE_LOCKING: {
      mozilla::MonitorAutoLock mon(mFullArrayMonitor);

      // Don't reenter!
      NS_ENSURE_FALSE(mLockedEnumerationActive, NS_ERROR_FAILURE);
      mLockedEnumerationActive = PR_TRUE;

      PRUint16 stepResult;
      rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);

      if (NS_SUCCEEDED(rv)) {
        if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
          rv = EnumerateItemsByPropertiesInternal(&propertyHash,
                                                  aEnumerationListener);
        }
        else {
          // The user cancelled the enumeration.
          rv = NS_ERROR_ABORT;
        }
      }

      mLockedEnumerationActive = PR_FALSE;

    } break; // ENUMERATIONTYPE_LOCKING

    case sbIMediaList::ENUMERATIONTYPE_SNAPSHOT: {
      PRUint16 stepResult;
      rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);

      if (NS_SUCCEEDED(rv)) {
        if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
          rv = EnumerateItemsByPropertiesInternal(&propertyHash,
                                                  aEnumerationListener);
        }
        else {
          // The user cancelled the enumeration.
          rv = NS_ERROR_ABORT;
        }
      }
    } break; // ENUMERATIONTYPE_SNAPSHOT

    default: {
      NS_NOTREACHED("Invalid enumeration type");
      rv = NS_ERROR_INVALID_ARG;
    } break;
  }

  aEnumerationListener->OnEnumerationEnd(this, rv);
  return NS_OK;
}
コード例 #29
0
nsresult
nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal)
{
  // Copied from nsAppFileLocationProvider (more or less)
  nsresult rv;
  nsCOMPtr<nsIFile> localDir;

#if defined(XP_MACOSX)
  FSRef fsRef;
  OSType folderType;
  if (aLocal) {
    folderType = kCachedDataFolderType;
  } else {
#ifdef MOZ_THUNDERBIRD
    folderType = kDomainLibraryFolderType;
#else
    folderType = kApplicationSupportFolderType;
#endif
  }
  OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
  NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);

  rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
  NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);

  rv = dirFileMac->InitWithFSRef(&fsRef);
  NS_ENSURE_SUCCESS(rv, rv);

  localDir = do_QueryInterface(dirFileMac, &rv);
#elif defined(XP_WIN)
  nsString path;
  if (aLocal) {
    rv = GetShellFolderPath(CSIDL_LOCAL_APPDATA, path);
    if (NS_FAILED(rv))
      rv = GetRegWindowsAppDataFolder(aLocal, path);
  }
  if (!aLocal || NS_FAILED(rv)) {
    rv = GetShellFolderPath(CSIDL_APPDATA, path);
    if (NS_FAILED(rv)) {
      if (!aLocal)
        rv = GetRegWindowsAppDataFolder(aLocal, path);
    }
  }
  NS_ENSURE_SUCCESS(rv, rv);

  rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
#elif defined(XP_OS2)
#if 0 /* For OS/2 we want to always use MOZILLA_HOME */
  // we want an environment variable of the form
  // FIREFOX_HOME, etc
  if (!gAppData)
    return NS_ERROR_FAILURE;
  nsDependentCString envVar(nsDependentCString(gAppData->name));
  envVar.Append("_HOME");
  char *pHome = getenv(envVar.get());
#endif
  char *pHome = getenv("MOZILLA_HOME");
  if (pHome && *pHome) {
    rv = NS_NewNativeLocalFile(nsDependentCString(pHome), true,
                               getter_AddRefs(localDir));
  } else {
    PPIB ppib;
    PTIB ptib;
    char appDir[CCHMAXPATH];

    DosGetInfoBlocks(&ptib, &ppib);
    DosQueryModuleName(ppib->pib_hmte, CCHMAXPATH, appDir);
    *strrchr(appDir, '\\') = '\0';
    rv = NS_NewNativeLocalFile(nsDependentCString(appDir), true, getter_AddRefs(localDir));
  }
#elif defined(MOZ_WIDGET_GONK)
  rv = NS_NewNativeLocalFile(NS_LITERAL_CSTRING("/data/b2g"), true,
                             getter_AddRefs(localDir));
#elif defined(XP_UNIX)
  const char* homeDir = getenv("HOME");
  if (!homeDir || !*homeDir)
    return NS_ERROR_FAILURE;

#ifdef ANDROID /* We want (ProfD == ProfLD) on Android. */
  aLocal = false;
#endif

  if (aLocal) {
    // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache.
    const char* cacheHome = getenv("XDG_CACHE_HOME");
    if (cacheHome && *cacheHome) {
      rv = NS_NewNativeLocalFile(nsDependentCString(cacheHome), true,
                                 getter_AddRefs(localDir));
    } else {
      rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
                                 getter_AddRefs(localDir));
      if (NS_SUCCEEDED(rv))
        rv = localDir->AppendNative(NS_LITERAL_CSTRING(".cache"));
    }
  } else {
    rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
                               getter_AddRefs(localDir));
  }
#else
#error "Don't know how to get product dir on your platform"
#endif

  NS_IF_ADDREF(*aFile = localDir);
  return rv;
}
コード例 #30
0
ファイル: HttpServer.cpp プロジェクト: bgrins/gecko-dev
nsresult
HttpServer::Connection::ConsumeLine(const char* aBuffer,
                                    size_t aLength)
{
  MOZ_ASSERT(mState == eRequestLine ||
             mState == eHeaders);

  if (MOZ_LOG_TEST(gHttpServerLog, mozilla::LogLevel::Verbose)) {
    nsCString line(aBuffer, aLength);
    LOG_V("HttpServer::Connection::ConsumeLine(%p) - \"%s\"", this, line.get());
  }

  if (mState == eRequestLine) {
    LOG_V("HttpServer::Connection::ConsumeLine(%p) - Parsing request line", this);
    NS_ENSURE_FALSE(mCloseAfterRequest, NS_ERROR_UNEXPECTED);

    if (aLength == 0) {
      // Ignore empty lines before the request line
      return NS_OK;
    }
    MOZ_ASSERT(!mPendingReq);

    // Process request line
    nsCWhitespaceTokenizer tokens(Substring(aBuffer, aLength));

    NS_ENSURE_TRUE(tokens.hasMoreTokens(), NS_ERROR_UNEXPECTED);
    nsDependentCSubstring method = tokens.nextToken();
    NS_ENSURE_TRUE(NS_IsValidHTTPToken(method), NS_ERROR_UNEXPECTED);
    NS_ENSURE_TRUE(tokens.hasMoreTokens(), NS_ERROR_UNEXPECTED);
    nsDependentCSubstring url = tokens.nextToken();
    // Seems like it's also allowed to pass full urls with scheme+host+port.
    // May need to support that.
    NS_ENSURE_TRUE(url.First() == '/', NS_ERROR_UNEXPECTED);
    mPendingReq = new InternalRequest(url, /* aURLFragment */ EmptyCString());
    mPendingReq->SetMethod(method);
    NS_ENSURE_TRUE(tokens.hasMoreTokens(), NS_ERROR_UNEXPECTED);
    nsDependentCSubstring version = tokens.nextToken();
    NS_ENSURE_TRUE(StringBeginsWith(version, NS_LITERAL_CSTRING("HTTP/1.")),
                   NS_ERROR_UNEXPECTED);
    nsresult rv;
    // This integer parsing is likely not strict enough.
    nsCString reqVersion;
    reqVersion = Substring(version, MOZ_ARRAY_LENGTH("HTTP/1.") - 1);
    mPendingReqVersion = reqVersion.ToInteger(&rv);
    NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);

    NS_ENSURE_FALSE(tokens.hasMoreTokens(), NS_ERROR_UNEXPECTED);

    LOG_V("HttpServer::Connection::ConsumeLine(%p) - Parsed request line", this);

    mState = eHeaders;

    return NS_OK;
  }

  if (aLength == 0) {
    LOG_V("HttpServer::Connection::ConsumeLine(%p) - Found end of headers", this);

    MaybeAddPendingHeader();

    ErrorResult res;
    mPendingReq->Headers()->SetGuard(HeadersGuardEnum::Immutable, res);

    // Check for WebSocket
    if (IsWebSocketRequest(mPendingReq, mPendingReqVersion)) {
      LOG_V("HttpServer::Connection::ConsumeLine(%p) - Fire OnWebSocket", this);

      mState = ePause;
      mPendingWebSocketRequest = mPendingReq.forget();
      mPendingReqVersion = 0;

      RefPtr<HttpServerListener> listener = mServer->mListener;
      RefPtr<InternalRequest> request = mPendingWebSocketRequest;
      nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction(
        "dom::HttpServer::Connection::ConsumeLine",
        [listener, request]() { listener->OnWebSocket(request); });
      NS_DispatchToCurrentThread(event);

      return NS_OK;
    }

    nsAutoCString header;
    mPendingReq->Headers()->GetFirst(NS_LITERAL_CSTRING("connection"),
                                     header,
                                     res);
    MOZ_ASSERT(!res.Failed());
    // 1.0 defaults to closing connections.
    // 1.1 and higher defaults to keep-alive.
    if (ContainsToken(header, NS_LITERAL_CSTRING("close")) ||
        (mPendingReqVersion == 0 &&
         !ContainsToken(header, NS_LITERAL_CSTRING("keep-alive")))) {
      mCloseAfterRequest = true;
    }

    mPendingReq->Headers()->GetFirst(NS_LITERAL_CSTRING("content-length"),
                                     header,
                                     res);
    MOZ_ASSERT(!res.Failed());

    LOG_V("HttpServer::Connection::ConsumeLine(%p) - content-length is \"%s\"",
          this, header.get());

    if (!header.IsEmpty()) {
      nsresult rv;
      mRemainingBodySize = header.ToInteger(&rv);
      NS_ENSURE_SUCCESS(rv, rv);
    } else {
      mRemainingBodySize = 0;
    }

    if (mRemainingBodySize) {
      LOG_V("HttpServer::Connection::ConsumeLine(%p) - Starting consume body", this);
      mState = eBody;

      // We use an unlimited buffer size here to ensure
      // that we get to the next request even if the webpage hangs on
      // to the request indefinitely without consuming the body.
      nsCOMPtr<nsIInputStream> input;
      nsCOMPtr<nsIOutputStream> output;
      nsresult rv = NS_NewPipe(getter_AddRefs(input),
                               getter_AddRefs(output),
                               0,          // Segment size
                               UINT32_MAX, // Unlimited buffer size
                               false,      // not nonBlockingInput
                               true);      // nonBlockingOutput
      NS_ENSURE_SUCCESS(rv, rv);

      mCurrentRequestBody = do_QueryInterface(output);
      mPendingReq->SetBody(input);
    } else {
      LOG_V("HttpServer::Connection::ConsumeLine(%p) - No body", this);
      mState = eRequestLine;
    }

    mPendingRequests.AppendElement(PendingRequest(mPendingReq, nullptr));

    LOG_V("HttpServer::Connection::ConsumeLine(%p) - Fire OnRequest", this);

    RefPtr<HttpServerListener> listener = mServer->mListener;
    RefPtr<InternalRequest> request = mPendingReq.forget();
    nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction(
      "dom::HttpServer::Connection::ConsumeLine",
      [listener, request]() { listener->OnRequest(request); });
    NS_DispatchToCurrentThread(event);

    mPendingReqVersion = 0;

    return NS_OK;
  }

  // Parse header line
  if (aBuffer[0] == ' ' || aBuffer[0] == '\t') {
    LOG_V("HttpServer::Connection::ConsumeLine(%p) - Add to header %s",
          this,
          mPendingHeaderName.get());

    NS_ENSURE_FALSE(mPendingHeaderName.IsEmpty(),
                    NS_ERROR_UNEXPECTED);

    // We might need to do whitespace trimming/compression here.
    mPendingHeaderValue.Append(aBuffer, aLength);
    return NS_OK;
  }

  MaybeAddPendingHeader();

  const char* colon = static_cast<const char*>(memchr(aBuffer, ':', aLength));
  NS_ENSURE_TRUE(colon, NS_ERROR_UNEXPECTED);

  ToLowerCase(Substring(aBuffer, colon - aBuffer), mPendingHeaderName);
  mPendingHeaderValue.Assign(colon + 1, aLength - (colon - aBuffer) - 1);

  NS_ENSURE_TRUE(NS_IsValidHTTPToken(mPendingHeaderName),
                 NS_ERROR_UNEXPECTED);

  LOG_V("HttpServer::Connection::ConsumeLine(%p) - Parsed header %s",
        this,
        mPendingHeaderName.get());

  return NS_OK;
}