bool
MessagePortService::DisentanglePort(
                  MessagePortParent* aParent,
                  FallibleTArray<RefPtr<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->mWaitingForNewParent = true;
    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;
}
// OTS drops the OT Layout tables when decoding a WOFF file, so retrieve them
// separately and cache them (unchecked) in the font entry; harfbuzz will
// sanitize them when it needs to use them.
static void
PreloadTableFromWOFF(const PRUint8* aFontData, PRUint32 aLength,
                     PRUint32 aTableTag, gfxFontEntry* aFontEntry)
{
    PRUint32 status = eWOFF_ok;
    PRUint32 len = woffGetTableSize(aFontData, aLength, aTableTag, &status);
    if (WOFF_SUCCESS(status) && len > 0) {
        FallibleTArray<PRUint8> buffer;
        if (!buffer.AppendElements(len)) {
            NS_WARNING("failed to cache font table - out of memory?");
            return;
        }
        woffGetTableToBuffer(aFontData, aLength, aTableTag,
                             buffer.Elements(), buffer.Length(),
                             &len, &status);
        if (WOFF_FAILURE(status)) {
            NS_WARNING("failed to cache font table - WOFF decoding error?");
            return;
        }
        aFontEntry->PreloadFontTable(aTableTag, buffer);
    }
}
// Find the GDEF, GSUB, GPOS tables in aFontData (if present)
// and cache copies in the given font entry.
// The sfnt table directory has already been accepted by the OTS
// sanitizer before this is called, so we can assume entries are valid.
//
// This is a temporary workaround until OTS has full support for the
// G*** tables, so that they can safely be left in the main font.
// When http://code.google.com/p/chromium/issues/detail?id=27131 gets fixed,
// we should remove this hack.
static void
CacheLayoutTablesFromSFNT(const PRUint8* aFontData, PRUint32 aLength,
                          gfxFontEntry* aFontEntry)
{
    const SFNTHeader *sfntHeader = reinterpret_cast<const SFNTHeader*>(aFontData);
    PRUint16 numTables = sfntHeader->numTables;
    
    // table directory entries begin immediately following SFNT header
    const TableDirEntry *dirEntry = 
        reinterpret_cast<const TableDirEntry*>(aFontData + sizeof(SFNTHeader));

    while (numTables-- > 0) {
        switch (dirEntry->tag) {
        case TRUETYPE_TAG('G','D','E','F'):
        case TRUETYPE_TAG('G','P','O','S'):
        case TRUETYPE_TAG('G','S','U','B'): {
                FallibleTArray<PRUint8> buffer;
                if (!buffer.AppendElements(aFontData + dirEntry->offset,
                                           dirEntry->length)) {
                    NS_WARNING("failed to cache font table - out of memory?");
                    break;
                }
                aFontEntry->PreloadFontTable(dirEntry->tag, buffer);
            }
            break;

        default:
            if (dirEntry->tag > TRUETYPE_TAG('G','S','U','B')) {
                // directory entries are required to be sorted,
                // so we can terminate as soon as we find a tag > 'GSUB'
                numTables = 0;
            }
            break;
        }
        ++dirEntry;
    }
}