Пример #1
0
bool
RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
  aWorkerPrivate->AssertIsOnParentThread();

  WorkerPrivate* parent = aWorkerPrivate->GetParent();
  if (!parent) {
    AssertIsOnMainThread();

    if (mShuttingDown) {
      JS_ReportError(aCx, "Cannot create worker during shutdown!");
      return false;
    }
  }

  WorkerDomainInfo* domainInfo;
  bool queued = false;
  {
    const nsCString& domain = aWorkerPrivate->Domain();

    MutexAutoLock lock(mMutex);

    if (!mDomainMap.Get(domain, &domainInfo)) {
      NS_ASSERTION(!parent, "Shouldn't have a parent here!");

      domainInfo = new WorkerDomainInfo();
      domainInfo->mDomain = domain;

      if (!mDomainMap.Put(domain, domainInfo)) {
        delete domainInfo;
        domainInfo = nsnull;
      }
    }

    if (domainInfo) {
      queued = gMaxWorkersPerDomain &&
               domainInfo->ActiveWorkerCount() >= gMaxWorkersPerDomain &&
               !domain.IsEmpty();

      if (queued) {
        domainInfo->mQueuedWorkers.AppendElement(aWorkerPrivate);
      }
      else if (parent) {
        domainInfo->mChildWorkerCount++;
      }
      else {
        domainInfo->mActiveWorkers.AppendElement(aWorkerPrivate);
      }
    }
  }

  if (!domainInfo) {
    JS_ReportOutOfMemory(aCx);
    return false;
  }

  // From here on out we must call UnregisterWorker if something fails!
  if (parent) {
    if (!parent->AddChildWorker(aCx, aWorkerPrivate)) {
      UnregisterWorker(aCx, aWorkerPrivate);
      return false;
    }
  }
  else {
    if (!mNavigatorStringsLoaded) {
      if (NS_FAILED(NS_GetNavigatorAppName(mNavigatorStrings.mAppName)) ||
          NS_FAILED(NS_GetNavigatorAppVersion(mNavigatorStrings.mAppVersion)) ||
          NS_FAILED(NS_GetNavigatorPlatform(mNavigatorStrings.mPlatform)) ||
          NS_FAILED(NS_GetNavigatorUserAgent(mNavigatorStrings.mUserAgent))) {
        JS_ReportError(aCx, "Failed to load navigator strings!");
        UnregisterWorker(aCx, aWorkerPrivate);
        return false;
      }

      mNavigatorStringsLoaded = true;
    }

    nsPIDOMWindow* window = aWorkerPrivate->GetWindow();

    nsTArray<WorkerPrivate*>* windowArray;
    if (!mWindowMap.Get(window, &windowArray)) {
      NS_ASSERTION(!parent, "Shouldn't have a parent here!");

      windowArray = new nsTArray<WorkerPrivate*>(1);

      if (!mWindowMap.Put(window, windowArray)) {
        delete windowArray;
        UnregisterWorker(aCx, aWorkerPrivate);
        JS_ReportOutOfMemory(aCx);
        return false;
      }
    }

    NS_ASSERTION(!windowArray->Contains(aWorkerPrivate),
                 "Already know about this worker!");
    windowArray->AppendElement(aWorkerPrivate);
  }

  if (!queued && !ScheduleWorker(aCx, aWorkerPrivate)) {
    return false;
  }

  return true;
}