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 :
7 : #include "BrowserStreamParent.h"
8 : #include "PluginInstanceParent.h"
9 : #include "nsNPAPIPlugin.h"
10 :
11 : #include "mozilla/UniquePtr.h"
12 : #include "mozilla/Unused.h"
13 :
14 : // How much data are we willing to send across the wire
15 : // in one chunk?
16 : static const int32_t kSendDataChunk = 0xffff;
17 :
18 : namespace mozilla {
19 : namespace plugins {
20 :
21 0 : BrowserStreamParent::BrowserStreamParent(PluginInstanceParent* npp,
22 0 : NPStream* stream)
23 : : mNPP(npp)
24 : , mStream(stream)
25 0 : , mState(INITIALIZING)
26 : {
27 0 : mStream->pdata = static_cast<AStream*>(this);
28 : nsNPAPIStreamWrapper* wrapper =
29 0 : reinterpret_cast<nsNPAPIStreamWrapper*>(mStream->ndata);
30 0 : if (wrapper) {
31 0 : mStreamListener = wrapper->GetStreamListener();
32 : }
33 0 : }
34 :
35 0 : BrowserStreamParent::~BrowserStreamParent()
36 : {
37 0 : mStream->pdata = nullptr;
38 0 : }
39 :
40 : void
41 0 : BrowserStreamParent::ActorDestroy(ActorDestroyReason aWhy)
42 : {
43 : // Implement me! Bug 1005159
44 0 : }
45 :
46 : mozilla::ipc::IPCResult
47 0 : BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
48 : NPError* result)
49 : {
50 0 : PLUGIN_LOG_DEBUG_FUNCTION;
51 :
52 0 : switch (mState) {
53 : case INITIALIZING:
54 0 : NS_ERROR("Requesting a read before initialization has completed");
55 0 : *result = NPERR_GENERIC_ERROR;
56 0 : return IPC_FAIL_NO_REASON(this);
57 :
58 : case ALIVE:
59 0 : break;
60 :
61 : case DYING:
62 0 : *result = NPERR_GENERIC_ERROR;
63 0 : return IPC_OK();
64 :
65 : default:
66 0 : NS_ERROR("Unexpected state");
67 0 : return IPC_FAIL_NO_REASON(this);
68 : }
69 :
70 0 : if (!mStream)
71 0 : return IPC_FAIL_NO_REASON(this);
72 :
73 0 : if (ranges.Length() > INT32_MAX)
74 0 : return IPC_FAIL_NO_REASON(this);
75 :
76 0 : UniquePtr<NPByteRange[]> rp(new NPByteRange[ranges.Length()]);
77 0 : for (uint32_t i = 0; i < ranges.Length(); ++i) {
78 0 : rp[i].offset = ranges[i].offset;
79 0 : rp[i].length = ranges[i].length;
80 0 : rp[i].next = &rp[i + 1];
81 : }
82 0 : rp[ranges.Length() - 1].next = nullptr;
83 :
84 0 : *result = mNPP->mNPNIface->requestread(mStream, rp.get());
85 0 : return IPC_OK();
86 : }
87 :
88 : mozilla::ipc::IPCResult
89 0 : BrowserStreamParent::RecvNPN_DestroyStream(const NPReason& reason)
90 : {
91 0 : switch (mState) {
92 : case ALIVE:
93 0 : break;
94 :
95 : case DYING:
96 0 : return IPC_OK();
97 :
98 : default:
99 0 : NS_ERROR("Unexpected state");
100 0 : return IPC_FAIL_NO_REASON(this);
101 : }
102 :
103 0 : mNPP->mNPNIface->destroystream(mNPP->mNPP, mStream, reason);
104 0 : return IPC_OK();
105 : }
106 :
107 : void
108 0 : BrowserStreamParent::NPP_DestroyStream(NPReason reason)
109 : {
110 0 : NS_ASSERTION(ALIVE == mState || INITIALIZING == mState,
111 : "NPP_DestroyStream called twice?");
112 0 : bool stillInitializing = INITIALIZING == mState;
113 0 : if (stillInitializing) {
114 0 : mState = DEFERRING_DESTROY;
115 : } else {
116 0 : mState = DYING;
117 0 : Unused << SendNPP_DestroyStream(reason);
118 : }
119 0 : }
120 :
121 : mozilla::ipc::IPCResult
122 0 : BrowserStreamParent::RecvStreamDestroyed()
123 : {
124 0 : if (DYING != mState) {
125 0 : NS_ERROR("Unexpected state");
126 0 : return IPC_FAIL_NO_REASON(this);
127 : }
128 :
129 0 : mStreamPeer = nullptr;
130 :
131 0 : mState = DELETING;
132 0 : IProtocol* mgr = Manager();
133 0 : if (!Send__delete__(this)) {
134 0 : return IPC_FAIL_NO_REASON(mgr);
135 : }
136 0 : return IPC_OK();
137 : }
138 :
139 : int32_t
140 0 : BrowserStreamParent::WriteReady()
141 : {
142 0 : if (mState == INITIALIZING) {
143 0 : return 0;
144 : }
145 0 : return kSendDataChunk;
146 : }
147 :
148 : int32_t
149 0 : BrowserStreamParent::Write(int32_t offset,
150 : int32_t len,
151 : void* buffer)
152 : {
153 0 : PLUGIN_LOG_DEBUG_FUNCTION;
154 :
155 0 : NS_ASSERTION(ALIVE == mState, "Sending data after NPP_DestroyStream?");
156 0 : NS_ASSERTION(len > 0, "Non-positive length to NPP_Write");
157 :
158 0 : if (len > kSendDataChunk)
159 0 : len = kSendDataChunk;
160 :
161 0 : return SendWrite(offset,
162 0 : mStream->end,
163 0 : nsCString(static_cast<char*>(buffer), len)) ?
164 0 : len : -1;
165 : }
166 :
167 : void
168 0 : BrowserStreamParent::StreamAsFile(const char* fname)
169 : {
170 0 : PLUGIN_LOG_DEBUG_FUNCTION;
171 :
172 0 : NS_ASSERTION(ALIVE == mState,
173 : "Calling streamasfile after NPP_DestroyStream?");
174 :
175 : // Make sure our stream survives until the plugin process tells us we've
176 : // been destroyed (until RecvStreamDestroyed() is called). Since we retain
177 : // mStreamPeer at most once, we won't get in trouble if StreamAsFile() is
178 : // called more than once.
179 0 : if (!mStreamPeer) {
180 0 : nsNPAPIPlugin::RetainStream(mStream, getter_AddRefs(mStreamPeer));
181 : }
182 :
183 0 : Unused << SendNPP_StreamAsFile(nsCString(fname));
184 0 : return;
185 : }
186 :
187 : } // namespace plugins
188 : } // namespace mozilla
|