bool
ServiceWorkerManagerParent::RecvRegister(
                                     const ServiceWorkerRegistrationData& aData)
{
  AssertIsInMainProcess();
  AssertIsOnBackgroundThread();

  // Basic validation.
  if (aData.scope().IsEmpty() ||
      aData.scriptSpec().IsEmpty() ||
      aData.principal().type() == PrincipalInfo::TNullPrincipalInfo ||
      aData.principal().type() == PrincipalInfo::TSystemPrincipalInfo) {
    return false;
  }

  RefPtr<RegisterServiceWorkerCallback> callback =
    new RegisterServiceWorkerCallback(aData, mID);

  RefPtr<ContentParent> parent =
    BackgroundParent::GetContentParent(Manager());

  // If the ContentParent is null we are dealing with a same-process actor.
  if (!parent) {
    callback->Run();
    return true;
  }

  RefPtr<CheckPrincipalWithCallbackRunnable> runnable =
    new CheckPrincipalWithCallbackRunnable(parent.forget(), aData.principal(),
                                           callback);
  nsresult rv = NS_DispatchToMainThread(runnable);
  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));

  return true;
}
nsresult
ServiceWorkerRegistrar::ReadData()
{
  // We cannot assert about the correct thread because normally this method
  // runs on a IO thread, but in gTests we call it from the main-thread.

  MOZ_ASSERT(mProfileDir);

  nsCOMPtr<nsIFile> file;
  nsresult rv = mProfileDir->Clone(getter_AddRefs(file));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  rv = file->Append(NS_LITERAL_STRING(SERVICEWORKERREGISTRAR_FILE));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

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

  if (!exists) {
    return NS_OK;
  }

  nsCOMPtr<nsIInputStream> stream;
  rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  nsCOMPtr<nsILineInputStream> lineInputStream = do_QueryInterface(stream);
  MOZ_ASSERT(lineInputStream);

  nsAutoCString line;
  bool hasMoreLines;
  rv = lineInputStream->ReadLine(line, &hasMoreLines);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  // The file is corrupted ?
  // FIXME: in case we implement a version 2, we should inform the user using
  // the console about this issue.
  if (!line.EqualsLiteral(SERVICEWORKERREGISTRAR_VERSION)) {
    return NS_ERROR_FAILURE;
  }

  while (hasMoreLines) {
    ServiceWorkerRegistrationData* entry = mData.AppendElement();

#define GET_LINE(x)                                   \
    rv = lineInputStream->ReadLine(x, &hasMoreLines); \
    if (NS_WARN_IF(NS_FAILED(rv))) {                  \
      return rv;                                      \
    }                                                 \
    if (NS_WARN_IF(!hasMoreLines)) {                  \
      return NS_ERROR_FAILURE;                        \
    }

    GET_LINE(line);

    if (line.EqualsLiteral(SERVICEWORKERREGISTRAR_SYSTEM_PRINCIPAL)) {
      entry->principal() = mozilla::ipc::SystemPrincipalInfo();
    } else {
      if (!line.EqualsLiteral(SERVICEWORKERREGISTRAR_CONTENT_PRINCIPAL)) {
        return NS_ERROR_FAILURE;
      }

      GET_LINE(line);

      uint32_t appId = line.ToInteger(&rv);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
      }

      GET_LINE(line);

      if (!line.EqualsLiteral(SERVICEWORKERREGISTRAR_TRUE) &&
          !line.EqualsLiteral(SERVICEWORKERREGISTRAR_FALSE)) {
        return NS_ERROR_FAILURE;
      }

      bool isInBrowserElement = line.EqualsLiteral(SERVICEWORKERREGISTRAR_TRUE);

      GET_LINE(line);
      entry->principal() =
        mozilla::ipc::ContentPrincipalInfo(appId, isInBrowserElement,
                                           line);
    }

    GET_LINE(entry->scope());
    GET_LINE(entry->scriptSpec());
    GET_LINE(entry->currentWorkerURL());

#undef GET_LINE

    rv = lineInputStream->ReadLine(line, &hasMoreLines);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }

    if (!line.EqualsLiteral(SERVICEWORKERREGISTRAR_TERMINATOR)) {
      return NS_ERROR_FAILURE;
    }
  }

  return NS_OK;
}