dom/network/TCPServerSocket.cpp
author J. Ryan Stinnett <jryans@gmail.com>
Wed, 17 Feb 2016 22:35:45 -0600
changeset 324714 76944f0d24abc3e3d968f324f18a8a3835e535dc
parent 308333 85e218929a7a10851b83487c3b622b26f490c544
child 328529 9b9dde0705bdcd960e78bbab5083ae7a1543e33b
permissions -rw-r--r--
Bug 1238160 - Set frame type on TabContext. r=billm,mayhemer This change renames TabContext::IsBrowserElement to IsIsolatedMozBrowserElement. Other methods that pass these values around also have name changes. Adds TabContext::IsMozBrowserElement which is set by the frame loader for all browser frames. This is in contrast to its previous implementation, which has since been renamed IsIsolatedMozBrowserElement, since it checks isolated state in OriginAttributes. TabContext methods related to browser elements (and their callers) are updated to use IsIsolatedMozBrowserElement when check isolation / origins and IsMozBrowserElement when checking frame types. MozReview-Commit-ID: DDMZTkSn5yd

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/dom/TCPServerSocketBinding.h"
#include "mozilla/dom/TCPServerSocketEvent.h"
#include "mozilla/dom/TCPSocketBinding.h"
#include "TCPServerSocketParent.h"
#include "TCPServerSocketChild.h"
#include "mozilla/dom/Event.h"
#include "mozilla/ErrorResult.h"
#include "TCPServerSocket.h"
#include "TCPSocket.h"

using namespace mozilla::dom;

NS_IMPL_CYCLE_COLLECTION_CLASS(TCPServerSocket)

NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(TCPServerSocket,
                                               DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRACE_END

NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TCPServerSocket,
                                                  DOMEventTargetHelper)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerSocket)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerBridgeChild)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerBridgeParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TCPServerSocket,
                                                DOMEventTargetHelper)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerSocket)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerBridgeChild)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerBridgeParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

NS_IMPL_ADDREF_INHERITED(TCPServerSocket, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(TCPServerSocket, DOMEventTargetHelper)

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TCPServerSocket)
  NS_INTERFACE_MAP_ENTRY(nsIServerSocketListener)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)

TCPServerSocket::TCPServerSocket(nsIGlobalObject* aGlobal, uint16_t aPort,
                                 bool aUseArrayBuffers, uint16_t aBacklog)
  : DOMEventTargetHelper(aGlobal)
  , mPort(aPort)
  , mBacklog(aBacklog)
  , mUseArrayBuffers(aUseArrayBuffers)
{
}

TCPServerSocket::~TCPServerSocket()
{
}

nsresult
TCPServerSocket::Init()
{
  if (mServerSocket || mServerBridgeChild) {
    NS_WARNING("Child TCPServerSocket is already listening.");
    return NS_ERROR_FAILURE;
  }

  if (XRE_GetProcessType() == GeckoProcessType_Content) {
    mServerBridgeChild = new TCPServerSocketChild(this, mPort, mBacklog, mUseArrayBuffers);
    return NS_OK;
  }

  nsresult rv;
  mServerSocket = do_CreateInstance("@mozilla.org/network/server-socket;1", &rv);
  NS_ENSURE_SUCCESS(rv, rv);
  rv = mServerSocket->Init(mPort, false, mBacklog);
  NS_ENSURE_SUCCESS(rv, rv);
  rv = mServerSocket->GetPort(&mPort);
  NS_ENSURE_SUCCESS(rv, rv);
  rv = mServerSocket->AsyncListen(this);
  NS_ENSURE_SUCCESS(rv, rv);
  return NS_OK;
}

already_AddRefed<TCPServerSocket>
TCPServerSocket::Constructor(const GlobalObject& aGlobal,
                             uint16_t aPort,
                             const ServerSocketOptions& aOptions,
                             uint16_t aBacklog,
                             mozilla::ErrorResult& aRv)
{
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
  if (!global) {
    aRv = NS_ERROR_FAILURE;
    return nullptr;
  }
  bool useArrayBuffers = aOptions.mBinaryType == TCPSocketBinaryType::Arraybuffer;
  RefPtr<TCPServerSocket> socket = new TCPServerSocket(global, aPort, useArrayBuffers, aBacklog);
  nsresult rv = socket->Init();
  if (NS_WARN_IF(NS_FAILED(rv))) {
    aRv = NS_ERROR_FAILURE;
    return nullptr;
  }
  return socket.forget();
}

uint16_t
TCPServerSocket::LocalPort()
{
  return mPort;
}

void
TCPServerSocket::Close()
{
  if (mServerBridgeChild) {
    mServerBridgeChild->Close();
  }
  if (mServerSocket) {
    mServerSocket->Close();
  }
}

void
TCPServerSocket::FireEvent(const nsAString& aType, TCPSocket* aSocket)
{
  AutoJSAPI api;
  api.Init(GetOwnerGlobal());

  TCPServerSocketEventInit init;
  init.mBubbles = false;
  init.mCancelable = false;
  init.mSocket = aSocket;

  RefPtr<TCPServerSocketEvent> event =
      TCPServerSocketEvent::Constructor(this, aType, init);
  event->SetTrusted(true);
  bool dummy;
  DispatchEvent(event, &dummy);

  if (mServerBridgeParent) {
    mServerBridgeParent->OnConnect(event);
  }
}

NS_IMETHODIMP
TCPServerSocket::OnSocketAccepted(nsIServerSocket* aServer, nsISocketTransport* aTransport)
{
  nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
  RefPtr<TCPSocket> socket = TCPSocket::CreateAcceptedSocket(global, aTransport, mUseArrayBuffers);
  if (mServerBridgeParent) {
    socket->SetAppIdAndBrowser(mServerBridgeParent->GetAppId(),
                               mServerBridgeParent->GetInIsolatedMozBrowser());
  }
  FireEvent(NS_LITERAL_STRING("connect"), socket);
  return NS_OK;
}

NS_IMETHODIMP
TCPServerSocket::OnStopListening(nsIServerSocket* aServer, nsresult aStatus)
{
  if (aStatus != NS_BINDING_ABORTED) {
    RefPtr<Event> event = new Event(GetOwner());
    event->InitEvent(NS_LITERAL_STRING("error"), false, false);
    event->SetTrusted(true);
    bool dummy;
    DispatchEvent(event, &dummy);

    NS_WARNING("Server socket was closed by unexpected reason.");
    return NS_ERROR_FAILURE;
  }
  mServerSocket = nullptr;
  return NS_OK;
}

nsresult
TCPServerSocket::AcceptChildSocket(TCPSocketChild* aSocketChild)
{
  nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
  NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
  RefPtr<TCPSocket> socket = TCPSocket::CreateAcceptedSocket(global, aSocketChild, mUseArrayBuffers);
  NS_ENSURE_TRUE(socket, NS_ERROR_FAILURE);
  FireEvent(NS_LITERAL_STRING("connect"), socket);
  return NS_OK;
}

void
TCPServerSocket::SetServerBridgeParent(TCPServerSocketParent* aBridgeParent)
{
  mServerBridgeParent = aBridgeParent;
}

JSObject*
TCPServerSocket::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
  return TCPServerSocketBinding::Wrap(aCx, this, aGivenProto);
}