Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/messagechannel/MessagePort.h
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
#ifndef mozilla_dom_MessagePort_h
8
#define mozilla_dom_MessagePort_h
9
10
#include "mozilla/Attributes.h"
11
#include "mozilla/DOMEventTargetHelper.h"
12
#include "nsAutoPtr.h"
13
#include "nsTArray.h"
14
15
#ifdef XP_WIN
16
#undef PostMessage
17
#endif
18
19
class nsIGlobalObject;
20
21
namespace mozilla {
22
namespace dom {
23
24
class ClonedMessageData;
25
class MessagePortChild;
26
class MessagePortIdentifier;
27
class PostMessageRunnable;
28
class SharedMessagePortMessage;
29
class StrongWorkerRef;
30
31
class MessagePort final : public DOMEventTargetHelper
32
{
33
  friend class PostMessageRunnable;
34
35
public:
36
  NS_DECL_ISUPPORTS_INHERITED
37
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MessagePort,
38
                                           DOMEventTargetHelper)
39
40
  static already_AddRefed<MessagePort>
41
  Create(nsIGlobalObject* aGlobal, const nsID& aUUID,
42
         const nsID& aDestinationUUID, ErrorResult& aRv);
43
44
  static already_AddRefed<MessagePort>
45
  Create(nsIGlobalObject* aGlobal,
46
         const MessagePortIdentifier& aIdentifier,
47
         ErrorResult& aRv);
48
49
  // For IPC.
50
  static void
51
  ForceClose(const MessagePortIdentifier& aIdentifier);
52
53
  virtual JSObject*
54
  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
55
56
  void
57
  PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
58
              const Sequence<JSObject*>& aTransferable,
59
              ErrorResult& aRv);
60
61
  void Start();
62
63
  void Close();
64
65
  EventHandlerNonNull* GetOnmessage();
66
67
  void SetOnmessage(EventHandlerNonNull* aCallback);
68
69
  IMPL_EVENT_HANDLER(messageerror)
70
71
  // Non WebIDL methods
72
73
  void UnshippedEntangle(MessagePort* aEntangledPort);
74
75
  bool CanBeCloned() const
76
  {
77
    return !mHasBeenTransferredOrClosed;
78
  }
79
80
  void CloneAndDisentangle(MessagePortIdentifier& aIdentifier);
81
82
  void CloseForced();
83
84
  // These methods are useful for MessagePortChild
85
86
  void Entangled(nsTArray<ClonedMessageData>& aMessages);
87
  void MessagesReceived(nsTArray<ClonedMessageData>& aMessages);
88
  void StopSendingDataConfirmed();
89
  void Closed();
90
91
private:
92
  enum State {
93
    // When a port is created by a MessageChannel it is entangled with the
94
    // other. They both run on the same thread, same event loop and the
95
    // messages are added to the queues without using PBackground actors.
96
    // When one of the port is shipped, the state is changed to
97
    // StateEntangling.
98
    eStateUnshippedEntangled,
99
100
    // If the port is closed or cloned when we are in this state, we go in one
101
    // of the following 2 steps. EntanglingForClose or ForDisentangle.
102
    eStateEntangling,
103
104
    // We are not fully entangled yet but are already disentangled.
105
    eStateEntanglingForDisentangle,
106
107
    // We are not fully entangled yet but are already closed.
108
    eStateEntanglingForClose,
109
110
    // When entangled() is received we send all the messages in the
111
    // mMessagesForTheOtherPort to the actor and we change the state to
112
    // StateEntangled. At this point the port is entangled with the other. We
113
    // send and receive messages.
114
    // If the port queue is not enabled, the received messages are stored in
115
    // the mMessages.
116
    eStateEntangled,
117
118
    // When the port is cloned or disentangled we want to stop receiving
119
    // messages. We call 'SendStopSendingData' to the actor and we wait for an
120
    // answer. All the messages received between now and the
121
    // 'StopSendingDataComfirmed are queued in the mMessages but not
122
    // dispatched.
123
    eStateDisentangling,
124
125
    // When 'StopSendingDataConfirmed' is received, we can disentangle the port
126
    // calling SendDisentangle in the actor because we are 100% sure that we
127
    // don't receive any other message, so nothing will be lost.
128
    // Disentangling the port we send all the messages from the mMessages
129
    // though the actor.
130
    eStateDisentangled,
131
132
    // We are here if Close() has been called. We are disentangled but we can
133
    // still send pending messages.
134
    eStateDisentangledForClose
135
  };
136
137
  explicit MessagePort(nsIGlobalObject* aGlobal, State aState);
138
  ~MessagePort();
139
140
  void DisconnectFromOwner() override;
141
142
  void Initialize(const nsID& aUUID, const nsID& aDestinationUUID,
143
                  uint32_t aSequenceID, bool aNeutered, ErrorResult& aRv);
144
145
  bool ConnectToPBackground();
146
147
  // Dispatch events from the Message Queue using a nsRunnable.
148
  void Dispatch();
149
150
  void DispatchError();
151
152
  void StartDisentangling();
153
  void Disentangle();
154
155
  void RemoveDocFromBFCache();
156
157
  void CloseInternal(bool aSoftly);
158
159
  // This method is meant to keep alive the MessagePort when this object is
160
  // creating the actor and until the actor is entangled.
161
  // We release the object when the port is closed or disentangled.
162
  void UpdateMustKeepAlive();
163
164
  bool IsCertainlyAliveForCC() const override
165
0
  {
166
0
    return mIsKeptAlive;
167
0
  }
168
169
  RefPtr<StrongWorkerRef> mWorkerRef;
170
171
  RefPtr<PostMessageRunnable> mPostMessageRunnable;
172
173
  RefPtr<MessagePortChild> mActor;
174
175
  RefPtr<MessagePort> mUnshippedEntangledPort;
176
177
  nsTArray<RefPtr<SharedMessagePortMessage>> mMessages;
178
  nsTArray<RefPtr<SharedMessagePortMessage>> mMessagesForTheOtherPort;
179
180
  nsAutoPtr<MessagePortIdentifier> mIdentifier;
181
182
  State mState;
183
184
  bool mMessageQueueEnabled;
185
186
  bool mIsKeptAlive;
187
188
  // mHasBeenTransferredOrClosed is used to know if this port has been manually
189
  // closed or transferred via postMessage. Note that if the entangled port is
190
  // closed, this port is closed as well (see mState) but, just because close()
191
  // has not been called directly, by spec, this port can still be transferred.
192
  bool mHasBeenTransferredOrClosed;
193
};
194
195
} // namespace dom
196
} // namespace mozilla
197
198
#endif // mozilla_dom_MessagePort_h