Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/broadcastchannel/BroadcastChannelService.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "BroadcastChannelService.h"
8
#include "BroadcastChannelParent.h"
9
#include "mozilla/dom/File.h"
10
#include "mozilla/dom/IPCBlobUtils.h"
11
#include "mozilla/ipc/BackgroundParent.h"
12
13
#ifdef XP_WIN
14
#undef PostMessage
15
#endif
16
17
namespace mozilla {
18
19
using namespace ipc;
20
21
namespace dom {
22
23
namespace {
24
25
BroadcastChannelService* sInstance = nullptr;
26
27
} // namespace
28
29
BroadcastChannelService::BroadcastChannelService()
30
0
{
31
0
  AssertIsOnBackgroundThread();
32
0
33
0
  // sInstance is a raw BroadcastChannelService*.
34
0
  MOZ_ASSERT(!sInstance);
35
0
  sInstance = this;
36
0
}
37
38
BroadcastChannelService::~BroadcastChannelService()
39
0
{
40
0
  AssertIsOnBackgroundThread();
41
0
  MOZ_ASSERT(sInstance == this);
42
0
  MOZ_ASSERT(mAgents.Count() == 0);
43
0
44
0
  sInstance = nullptr;
45
0
}
46
47
// static
48
already_AddRefed<BroadcastChannelService>
49
BroadcastChannelService::GetOrCreate()
50
0
{
51
0
  AssertIsOnBackgroundThread();
52
0
53
0
  RefPtr<BroadcastChannelService> instance = sInstance;
54
0
  if (!instance) {
55
0
    instance = new BroadcastChannelService();
56
0
  }
57
0
  return instance.forget();
58
0
}
59
60
void
61
BroadcastChannelService::RegisterActor(BroadcastChannelParent* aParent,
62
                                       const nsAString& aOriginChannelKey)
63
0
{
64
0
  AssertIsOnBackgroundThread();
65
0
  MOZ_ASSERT(aParent);
66
0
67
0
  nsTArray<BroadcastChannelParent*>* parents =
68
0
    mAgents.LookupForAdd(aOriginChannelKey).OrInsert(
69
0
      [] () { return new nsTArray<BroadcastChannelParent*>(); });
70
0
71
0
  MOZ_ASSERT(!parents->Contains(aParent));
72
0
  parents->AppendElement(aParent);
73
0
}
74
75
void
76
BroadcastChannelService::UnregisterActor(BroadcastChannelParent* aParent,
77
                                         const nsAString& aOriginChannelKey)
78
0
{
79
0
  AssertIsOnBackgroundThread();
80
0
  MOZ_ASSERT(aParent);
81
0
82
0
  if (auto entry = mAgents.Lookup(aOriginChannelKey)) {
83
0
    entry.Data()->RemoveElement(aParent);
84
0
    // remove the entry if the array is now empty
85
0
    if (entry.Data()->IsEmpty()) {
86
0
      entry.Remove();
87
0
    }
88
0
  } else {
89
0
    MOZ_CRASH("Invalid state");
90
0
  }
91
0
}
92
93
void
94
BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
95
                                     const ClonedMessageData& aData,
96
                                     const nsAString& aOriginChannelKey)
97
0
{
98
0
  AssertIsOnBackgroundThread();
99
0
  MOZ_ASSERT(aParent);
100
0
101
0
  nsTArray<BroadcastChannelParent*>* parents;
102
0
  if (!mAgents.Get(aOriginChannelKey, &parents)) {
103
0
    MOZ_CRASH("Invalid state");
104
0
  }
105
0
106
0
  // We need to keep the array alive for the life-time of this operation.
107
0
  nsTArray<RefPtr<BlobImpl>> blobImpls;
108
0
  if (!aData.blobs().IsEmpty()) {
109
0
    blobImpls.SetCapacity(aData.blobs().Length());
110
0
111
0
    for (uint32_t i = 0, len = aData.blobs().Length(); i < len; ++i) {
112
0
      RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(aData.blobs()[i]);
113
0
114
0
      MOZ_ASSERT(impl);
115
0
      blobImpls.AppendElement(impl);
116
0
    }
117
0
  }
118
0
119
0
  // For each parent actor, we notify the message.
120
0
  for (uint32_t i = 0; i < parents->Length(); ++i) {
121
0
    BroadcastChannelParent* parent = parents->ElementAt(i);
122
0
    MOZ_ASSERT(parent);
123
0
124
0
    if (parent == aParent) {
125
0
      continue;
126
0
    }
127
0
128
0
    // We need to have a copy of the data for this parent.
129
0
    ClonedMessageData newData(aData);
130
0
    MOZ_ASSERT(blobImpls.Length() == newData.blobs().Length());
131
0
132
0
    if (!blobImpls.IsEmpty()) {
133
0
      // Serialize Blob objects for this message.
134
0
      for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) {
135
0
        nsresult rv = IPCBlobUtils::Serialize(blobImpls[i], parent->Manager(),
136
0
                                              newData.blobs()[i]);
137
0
        if (NS_WARN_IF(NS_FAILED(rv))) {
138
0
          return;
139
0
        }
140
0
      }
141
0
    }
142
0
143
0
    Unused << parent->SendNotify(newData);
144
0
  }
145
0
}
146
147
} // namespace dom
148
} // namespace mozilla