Line data Source code
1 : /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef mozilla_plugins_BrowserStreamChild_h
7 : #define mozilla_plugins_BrowserStreamChild_h 1
8 :
9 : #include "mozilla/plugins/PBrowserStreamChild.h"
10 : #include "mozilla/plugins/AStream.h"
11 : #include "base/task.h"
12 : #include "base/timer.h"
13 :
14 : namespace mozilla {
15 : namespace plugins {
16 :
17 : class PluginInstanceChild;
18 : class StreamNotifyChild;
19 :
20 : class BrowserStreamChild : public PBrowserStreamChild, public AStream
21 : {
22 : public:
23 : BrowserStreamChild(PluginInstanceChild* instance,
24 : const nsCString& url,
25 : const uint32_t& length,
26 : const uint32_t& lastmodified,
27 : StreamNotifyChild* notifyData,
28 : const nsCString& headers);
29 : virtual ~BrowserStreamChild();
30 :
31 0 : virtual bool IsBrowserStream() override { return true; }
32 :
33 : NPError StreamConstructed(
34 : const nsCString& mimeType,
35 : const bool& seekable,
36 : uint16_t* stype);
37 :
38 : virtual mozilla::ipc::IPCResult RecvWrite(const int32_t& offset,
39 : const uint32_t& newsize,
40 : const Buffer& data) override;
41 : virtual mozilla::ipc::IPCResult RecvNPP_StreamAsFile(const nsCString& fname) override;
42 : virtual mozilla::ipc::IPCResult RecvNPP_DestroyStream(const NPReason& reason) override;
43 : virtual mozilla::ipc::IPCResult Recv__delete__() override;
44 :
45 : void EnsureCorrectInstance(PluginInstanceChild* i)
46 : {
47 : if (i != mInstance)
48 : MOZ_CRASH("Incorrect stream instance");
49 : }
50 0 : void EnsureCorrectStream(NPStream* s)
51 : {
52 0 : if (s != &mStream)
53 0 : MOZ_CRASH("Incorrect stream data");
54 0 : }
55 :
56 : NPError NPN_RequestRead(NPByteRange* aRangeList);
57 : void NPN_DestroyStream(NPReason reason);
58 :
59 0 : void NotifyPending() {
60 0 : NS_ASSERTION(!mNotifyPending, "Pending twice?");
61 0 : mNotifyPending = true;
62 0 : EnsureDeliveryPending();
63 0 : }
64 :
65 : /**
66 : * During instance destruction, artificially cancel all outstanding streams.
67 : *
68 : * @return false if we are already in the DELETING state.
69 : */
70 0 : bool InstanceDying() {
71 0 : if (DELETING == mState)
72 0 : return false;
73 :
74 0 : mInstanceDying = true;
75 0 : return true;
76 : }
77 :
78 0 : void FinishDelivery() {
79 0 : NS_ASSERTION(mInstanceDying, "Should only be called after InstanceDying");
80 0 : NS_ASSERTION(DELETING != mState, "InstanceDying didn't work?");
81 0 : mStreamStatus = NPRES_USER_BREAK;
82 0 : Deliver();
83 0 : NS_ASSERTION(!mStreamNotify, "Didn't deliver NPN_URLNotify?");
84 0 : }
85 :
86 : private:
87 : friend class StreamNotifyChild;
88 : using PBrowserStreamChild::SendNPN_DestroyStream;
89 :
90 : /**
91 : * Post an event to ensure delivery of pending data/destroy/urlnotify events
92 : * outside of the current RPC stack.
93 : */
94 : void EnsureDeliveryPending();
95 :
96 : /**
97 : * Deliver data, destruction, notify scheduling
98 : * or cancelling the suspended timer as needed.
99 : */
100 : void Deliver();
101 :
102 : /**
103 : * Deliver one chunk of pending data.
104 : * @return true if the plugin indicated a pause was necessary
105 : */
106 : bool DeliverPendingData();
107 :
108 : void SetSuspendedTimer();
109 : void ClearSuspendedTimer();
110 :
111 : PluginInstanceChild* mInstance;
112 : NPStream mStream;
113 :
114 : static const NPReason kStreamOpen = -1;
115 :
116 : /**
117 : * The plugin's notion of whether a stream has been "closed" (no more
118 : * data delivery) differs from the plugin host due to asynchronous delivery
119 : * of data and NPN_DestroyStream. While the plugin-visible stream is open,
120 : * mStreamStatus should be kStreamOpen (-1). mStreamStatus will be a
121 : * failure code if either the parent or child indicates stream failure.
122 : */
123 : NPReason mStreamStatus;
124 :
125 : /**
126 : * Delivery of NPP_DestroyStream and NPP_URLNotify must be postponed until
127 : * all data has been delivered.
128 : */
129 : enum {
130 : NOT_DESTROYED, // NPP_DestroyStream not yet received
131 : DESTROY_PENDING, // NPP_DestroyStream received, not yet delivered
132 : DESTROYED // NPP_DestroyStream delivered, NPP_URLNotify may still be pending
133 : } mDestroyPending;
134 : bool mNotifyPending;
135 : bool mStreamAsFilePending;
136 : nsCString mStreamAsFileName;
137 :
138 : // When NPP_Destroy is called for our instance (manager), this flag is set
139 : // cancels the stream and avoids sending StreamDestroyed.
140 : bool mInstanceDying;
141 :
142 : enum {
143 : CONSTRUCTING,
144 : ALIVE,
145 : DYING,
146 : DELETING
147 : } mState;
148 : nsCString mURL;
149 : nsCString mHeaders;
150 : StreamNotifyChild* mStreamNotify;
151 :
152 0 : struct PendingData
153 : {
154 : int32_t offset;
155 : Buffer data;
156 : int32_t curpos;
157 : };
158 : nsTArray<PendingData> mPendingData;
159 :
160 : /**
161 : * Asynchronous RecvWrite messages are never delivered to the plugin
162 : * immediately, because that may be in the midst of an unexpected RPC
163 : * stack frame. It instead posts a runnable using this tracker to cancel
164 : * in case we are destroyed.
165 : */
166 : ScopedRunnableMethodFactory<BrowserStreamChild> mDeliveryTracker;
167 : base::RepeatingTimer<BrowserStreamChild> mSuspendedTimer;
168 : };
169 :
170 : } // namespace plugins
171 : } // namespace mozilla
172 :
173 : #endif /* mozilla_plugins_BrowserStreamChild_h */
|