mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
14f7ec3aac
- Bug 1173947 - Make getRandomValues message be urgent (r=mrbkap) (aca1a06a9) - Bug 1182824 - Part 1: Use move assignment rather than copy assignment with ContextState::dash. r=mattwoodrow (73af33d32) - Bug 1182824 - Part 2: Make ContextState::dash a nsTArray. r=mattwoodrow (c66c3105d) - Bug 1134166 - Restart toolbox if selected app re-opens. r=ochameau (e370c8f02) - Bug 1134166 - Close toolbox if selected app dies. r=ochameau (5acb76254) - Bug 1134166 - Check for project when updating toolbox state. r=me (c60bb8766) - Bug 1090949 - Add way to make WebIDE runtimes configurable. r=ochameau (eef01e3e6) - Bug 1090949 - Refactor WebIDE preferences panel style. r=ochameau (fe1a9c757) - Bug 1135191 - Add runtime panel with toggle. r=jryans (e2e290a67) - missing bit of Bug 1116188 - Add async ProfileGatherer (308cfdd4f) - Bug 1185737 - Propagate pause and resume commands to child processes. r=BenWa (2dd302569) - Bug 1161831 - Stop using threaddsafe ISupports for nsResProtocolHandler. r=billm (0bec61aac) - Bug 1155968 - Correct indent not multiple of 4. r=khuey (5fb8e3b20) - Bug 1183291 - Factor idl-parser into a Python package. r=khuey (63a2f0c68) - Bug 1155968 - Add blank lines where needed in xpcom/idl-parser. r=khuey (ce91a905b) - Bug 1161831 - Generate an extra macro to declare a non-virtual variant of an interface. r=billm (058876228) - Bug 1161831 - Factor the sharable bits out of nsIResProtocolHandler. r=billm (b02278fb9) - Bug 1152997 - Cleanup app update build to exclude android. r=glandium, r=mossop (6cd935294) - Bug 1170075 - Remove Print Progress UI and view source XUL files from Android. r=snorp (64796ae4a) - Bug 1180921 - Create a dumping ground for simple services in toolkit/components/utils. r=Gijs (2757d43c8) - Bug 1180921 - Support custom callbacks for allowing access per-addon load access to cross-origin URIs. r=bz,r=billm (8cc7e2c96) - Bug 1161831 - Implement moz-extension protocol. r=bz,r=billm,sr=mcmanus (5ee451357) - Bug 1161831 - Associate extension URIs with the appropriate addon ID. r=billm,sr=bz (f36655ac9) - Bug 1161831 - Forbid mapping to anything but file:// and jar:// URIs. r=billm,sr=bz (144add9de) - Bug 1180921 - Generalize test_origin to make it easier to add new origin attributes. r=gabor (b3fbc3545) - Bug 1180921 - Add the addonId OriginAttribute. r=bholley (0723d0dec) - Bug 1174093 - Don't recurse into caps/tests/mochitest during the build; r=mshal (76366d21a) - Bug 1161831 - Tests. r=billm (ed116a703) - Bug 1155547, Part 1: Fix unified build breakage in adding new sources under dom/ipc/. r=khuey (0d6875348) - Bug 1166985 - Use two image decoding threads on dual core devices. r=tn (7f07ee8b8) - Bug 1160422 - Prioritize size decodes over full decodes. r=tn (48d42c011) - Bug 1151672 - Part 1: Remove the calls to nsThreadManager::SetThreadWorking() and nsThreadManager::SetThreadIdle() due to backout of bug 970307. r=seth (0428dd4a4) - Bug 1151672 - Part 2: Block PHal::Msg_NotifyNetworkChange__ID to the Nuwa process after it is ready. r=khuey (42debf2c0) - Bug 1176034 - MessagePort should force a close() if the structured clone algorithm fails, r=bent (3afe74856) - Bug 1176034 - Implement JSAutoStructuredCloneBuffer::clear(with callbacks and closure), r=sfink (f28f6852b) - Bug 1155547, Part 2: Create PNuwa protocol (managed by PBackground) for forking content processes. r=khuey (047bc5e61) - missing bit of Bug 1170075 - Remove Print Progress UI and view source XUL (a08888308)
379 lines
9.7 KiB
C++
379 lines
9.7 KiB
C++
/* -*- 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 "MessagePortService.h"
|
|
#include "MessagePortParent.h"
|
|
#include "SharedMessagePortMessage.h"
|
|
#include "mozilla/ipc/BackgroundParent.h"
|
|
#include "mozilla/StaticPtr.h"
|
|
#include "mozilla/unused.h"
|
|
#include "nsDataHashtable.h"
|
|
#include "nsTArray.h"
|
|
|
|
using mozilla::ipc::AssertIsOnBackgroundThread;
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
namespace {
|
|
|
|
StaticRefPtr<MessagePortService> gInstance;
|
|
|
|
void
|
|
AssertIsInMainProcess()
|
|
{
|
|
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
class MessagePortService::MessagePortServiceData final
|
|
{
|
|
public:
|
|
explicit MessagePortServiceData(const nsID& aDestinationUUID)
|
|
: mDestinationUUID(aDestinationUUID)
|
|
, mSequenceID(1)
|
|
, mParent(nullptr)
|
|
{
|
|
MOZ_COUNT_CTOR(MessagePortServiceData);
|
|
}
|
|
|
|
MessagePortServiceData(const MessagePortServiceData& aOther) = delete;
|
|
MessagePortServiceData& operator=(const MessagePortServiceData&) = delete;
|
|
|
|
~MessagePortServiceData()
|
|
{
|
|
MOZ_COUNT_DTOR(MessagePortServiceData);
|
|
}
|
|
|
|
nsID mDestinationUUID;
|
|
|
|
uint32_t mSequenceID;
|
|
MessagePortParent* mParent;
|
|
|
|
struct NextParent
|
|
{
|
|
uint32_t mSequenceID;
|
|
// MessagePortParent keeps the service alive, and we don't want a cycle.
|
|
MessagePortParent* mParent;
|
|
};
|
|
|
|
FallibleTArray<NextParent> mNextParents;
|
|
FallibleTArray<nsRefPtr<SharedMessagePortMessage>> mMessages;
|
|
};
|
|
|
|
/* static */ MessagePortService*
|
|
MessagePortService::Get()
|
|
{
|
|
AssertIsInMainProcess();
|
|
AssertIsOnBackgroundThread();
|
|
|
|
return gInstance;
|
|
}
|
|
|
|
/* static */ MessagePortService*
|
|
MessagePortService::GetOrCreate()
|
|
{
|
|
AssertIsInMainProcess();
|
|
AssertIsOnBackgroundThread();
|
|
|
|
if (!gInstance) {
|
|
gInstance = new MessagePortService();
|
|
}
|
|
|
|
return gInstance;
|
|
}
|
|
|
|
bool
|
|
MessagePortService::RequestEntangling(MessagePortParent* aParent,
|
|
const nsID& aDestinationUUID,
|
|
const uint32_t& aSequenceID)
|
|
{
|
|
MOZ_ASSERT(aParent);
|
|
MessagePortServiceData* data;
|
|
|
|
// If we don't have a MessagePortServiceData, we must create 2 of them for
|
|
// both ports.
|
|
if (!mPorts.Get(aParent->ID(), &data)) {
|
|
// Create the MessagePortServiceData for the destination.
|
|
if (mPorts.Get(aDestinationUUID, nullptr)) {
|
|
MOZ_ASSERT(false, "The creation of the 2 ports should be in sync.");
|
|
return false;
|
|
}
|
|
|
|
data = new MessagePortServiceData(aParent->ID());
|
|
mPorts.Put(aDestinationUUID, data);
|
|
|
|
data = new MessagePortServiceData(aDestinationUUID);
|
|
mPorts.Put(aParent->ID(), data);
|
|
}
|
|
|
|
// This is a security check.
|
|
if (!data->mDestinationUUID.Equals(aDestinationUUID)) {
|
|
MOZ_ASSERT(false, "DestinationUUIDs do not match!");
|
|
return false;
|
|
}
|
|
|
|
if (aSequenceID < data->mSequenceID) {
|
|
MOZ_ASSERT(false, "Invalid sequence ID!");
|
|
return false;
|
|
}
|
|
|
|
if (aSequenceID == data->mSequenceID) {
|
|
if (data->mParent) {
|
|
MOZ_ASSERT(false, "Two ports cannot have the same sequenceID.");
|
|
return false;
|
|
}
|
|
|
|
// We activate this port, sending all the messages.
|
|
data->mParent = aParent;
|
|
FallibleTArray<MessagePortMessage> array;
|
|
if (!SharedMessagePortMessage::FromSharedToMessagesParent(aParent,
|
|
data->mMessages,
|
|
array)) {
|
|
return false;
|
|
}
|
|
|
|
data->mMessages.Clear();
|
|
return aParent->Entangled(array);
|
|
}
|
|
|
|
// This new parent will be the next one when a Disentangle request is
|
|
// received from the current parent.
|
|
MessagePortServiceData::NextParent* nextParent =
|
|
data->mNextParents.AppendElement(mozilla::fallible);
|
|
if (!nextParent) {
|
|
return false;
|
|
}
|
|
|
|
nextParent->mSequenceID = aSequenceID;
|
|
nextParent->mParent = aParent;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
MessagePortService::DisentanglePort(
|
|
MessagePortParent* aParent,
|
|
FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aMessages)
|
|
{
|
|
MessagePortServiceData* data;
|
|
if (!mPorts.Get(aParent->ID(), &data)) {
|
|
MOZ_ASSERT(false, "Unknown MessagePortParent should not happen.");
|
|
return false;
|
|
}
|
|
|
|
if (data->mParent != aParent) {
|
|
MOZ_ASSERT(false, "DisentanglePort() should be called just from the correct parent.");
|
|
return false;
|
|
}
|
|
|
|
// Let's put the messages in the correct order. |aMessages| contains the
|
|
// unsent messages so they have to go first.
|
|
if (!aMessages.AppendElements(data->mMessages, mozilla::fallible)) {
|
|
return false;
|
|
}
|
|
|
|
data->mMessages.Clear();
|
|
|
|
++data->mSequenceID;
|
|
|
|
// If we don't have a parent, we have to store the pending messages and wait.
|
|
uint32_t index = 0;
|
|
MessagePortParent* nextParent = nullptr;
|
|
for (; index < data->mNextParents.Length(); ++index) {
|
|
if (data->mNextParents[index].mSequenceID == data->mSequenceID) {
|
|
nextParent = data->mNextParents[index].mParent;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// We didn't find the parent.
|
|
if (!nextParent) {
|
|
data->mMessages.SwapElements(aMessages);
|
|
data->mParent = nullptr;
|
|
return true;
|
|
}
|
|
|
|
data->mParent = nextParent;
|
|
data->mNextParents.RemoveElementAt(index);
|
|
|
|
FallibleTArray<MessagePortMessage> array;
|
|
if (!SharedMessagePortMessage::FromSharedToMessagesParent(data->mParent,
|
|
aMessages,
|
|
array)) {
|
|
return false;
|
|
}
|
|
|
|
unused << data->mParent->Entangled(array);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
MessagePortService::ClosePort(MessagePortParent* aParent)
|
|
{
|
|
MessagePortServiceData* data;
|
|
if (!mPorts.Get(aParent->ID(), &data)) {
|
|
MOZ_ASSERT(false, "Unknown MessagePortParent should not happend.");
|
|
return false;
|
|
}
|
|
|
|
if (data->mParent != aParent) {
|
|
MOZ_ASSERT(false, "ClosePort() should be called just from the correct parent.");
|
|
return false;
|
|
}
|
|
|
|
if (!data->mNextParents.IsEmpty()) {
|
|
MOZ_ASSERT(false, "ClosePort() should be called when there are not next parents.");
|
|
return false;
|
|
}
|
|
|
|
// We don't want to send a message to this parent.
|
|
data->mParent = nullptr;
|
|
|
|
CloseAll(aParent->ID());
|
|
return true;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
PLDHashOperator
|
|
MessagePortService::CloseAllDebugCheck(const nsID& aID,
|
|
MessagePortServiceData* aData,
|
|
void* aPtr)
|
|
{
|
|
nsID* id = static_cast<nsID*>(aPtr);
|
|
MOZ_ASSERT(!id->Equals(aID));
|
|
return PL_DHASH_NEXT;
|
|
}
|
|
#endif
|
|
|
|
void
|
|
MessagePortService::CloseAll(const nsID& aUUID)
|
|
{
|
|
MessagePortServiceData* data;
|
|
if (!mPorts.Get(aUUID, &data)) {
|
|
MaybeShutdown();
|
|
return;
|
|
}
|
|
|
|
if (data->mParent) {
|
|
data->mParent->Close();
|
|
}
|
|
|
|
for (const MessagePortServiceData::NextParent& parent : data->mNextParents) {
|
|
parent.mParent->CloseAndDelete();
|
|
}
|
|
|
|
nsID destinationUUID = data->mDestinationUUID;
|
|
mPorts.Remove(aUUID);
|
|
|
|
CloseAll(destinationUUID);
|
|
|
|
// CloseAll calls itself recursively and it can happen that it deletes
|
|
// itself. Before continuing we must check if we are still alive.
|
|
if (!gInstance) {
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
mPorts.EnumerateRead(CloseAllDebugCheck, const_cast<nsID*>(&aUUID));
|
|
#endif
|
|
|
|
MaybeShutdown();
|
|
}
|
|
|
|
// This service can be dismissed when there are not active ports.
|
|
void
|
|
MessagePortService::MaybeShutdown()
|
|
{
|
|
if (mPorts.Count() == 0) {
|
|
gInstance = nullptr;
|
|
}
|
|
}
|
|
|
|
bool
|
|
MessagePortService::PostMessages(
|
|
MessagePortParent* aParent,
|
|
FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aMessages)
|
|
{
|
|
MessagePortServiceData* data;
|
|
if (!mPorts.Get(aParent->ID(), &data)) {
|
|
MOZ_ASSERT(false, "Unknown MessagePortParent should not happend.");
|
|
return false;
|
|
}
|
|
|
|
if (data->mParent != aParent) {
|
|
MOZ_ASSERT(false, "PostMessages() should be called just from the correct parent.");
|
|
return false;
|
|
}
|
|
|
|
MOZ_ALWAYS_TRUE(mPorts.Get(data->mDestinationUUID, &data));
|
|
|
|
if (!data->mMessages.AppendElements(aMessages, mozilla::fallible)) {
|
|
return false;
|
|
}
|
|
|
|
// If the parent can send data to the child, let's proceed.
|
|
if (data->mParent && data->mParent->CanSendData()) {
|
|
FallibleTArray<MessagePortMessage> messages;
|
|
if (!SharedMessagePortMessage::FromSharedToMessagesParent(data->mParent,
|
|
data->mMessages,
|
|
messages)) {
|
|
return false;
|
|
}
|
|
|
|
data->mMessages.Clear();
|
|
unused << data->mParent->SendReceiveData(messages);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void
|
|
MessagePortService::ParentDestroy(MessagePortParent* aParent)
|
|
{
|
|
// This port has already been destroyed.
|
|
MessagePortServiceData* data;
|
|
if (!mPorts.Get(aParent->ID(), &data)) {
|
|
return;
|
|
}
|
|
|
|
if (data->mParent != aParent) {
|
|
// We don't want to send a message to this parent.
|
|
for (uint32_t i = 0; i < data->mNextParents.Length(); ++i) {
|
|
if (aParent == data->mNextParents[i].mParent) {
|
|
data->mNextParents.RemoveElementAt(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseAll(aParent->ID());
|
|
}
|
|
|
|
bool
|
|
MessagePortService::ForceClose(const nsID& aUUID,
|
|
const nsID& aDestinationUUID,
|
|
const uint32_t& aSequenceID)
|
|
{
|
|
MessagePortServiceData* data;
|
|
if (!mPorts.Get(aUUID, &data)) {
|
|
NS_WARNING("Unknown MessagePort in ForceClose()");
|
|
return true;
|
|
}
|
|
|
|
if (!data->mDestinationUUID.Equals(aDestinationUUID) ||
|
|
data->mSequenceID != aSequenceID) {
|
|
NS_WARNING("DestinationUUID and/or sequenceID do not match.");
|
|
return false;
|
|
}
|
|
|
|
CloseAll(aUUID);
|
|
return true;
|
|
}
|
|
|
|
} // dom namespace
|
|
} // mozilla namespace
|