1 : /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
2 :
3 : #include "BrowserStreamParent.h"
4 : #include "PluginInstanceParent.h"
5 : #include "nsNPAPIPlugin.h"
6 :
7 : #include "mozilla/unused.h"
8 :
9 : // How much data are we willing to send across the wire
10 : // in one chunk?
11 : static const int32_t kSendDataChunk = 0x4000;
12 :
13 : namespace mozilla {
14 : namespace plugins {
15 :
16 0 : BrowserStreamParent::BrowserStreamParent(PluginInstanceParent* npp,
17 : NPStream* stream)
18 : : mNPP(npp)
19 : , mStream(stream)
20 0 : , mState(ALIVE)
21 : {
22 0 : mStream->pdata = static_cast<AStream*>(this);
23 0 : }
24 :
25 0 : BrowserStreamParent::~BrowserStreamParent()
26 : {
27 0 : }
28 :
29 : bool
30 0 : BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
31 : NPError* result)
32 : {
33 0 : PLUGIN_LOG_DEBUG_FUNCTION;
34 :
35 0 : switch (mState) {
36 : case ALIVE:
37 : break;
38 :
39 : case DYING:
40 0 : *result = NPERR_GENERIC_ERROR;
41 0 : return true;
42 :
43 : default:
44 0 : NS_ERROR("Unexpected state");
45 0 : return false;
46 : }
47 :
48 0 : if (!mStream)
49 0 : return false;
50 :
51 0 : if (ranges.size() > PR_INT32_MAX)
52 0 : return false;
53 :
54 0 : nsAutoArrayPtr<NPByteRange> rp(new NPByteRange[ranges.size()]);
55 0 : for (PRUint32 i = 0; i < ranges.size(); ++i) {
56 0 : rp[i].offset = ranges[i].offset;
57 0 : rp[i].length = ranges[i].length;
58 0 : rp[i].next = &rp[i + 1];
59 : }
60 0 : rp[ranges.size() - 1].next = NULL;
61 :
62 0 : *result = mNPP->mNPNIface->requestread(mStream, rp);
63 0 : return true;
64 : }
65 :
66 : bool
67 0 : BrowserStreamParent::RecvNPN_DestroyStream(const NPReason& reason)
68 : {
69 0 : switch (mState) {
70 : case ALIVE:
71 : break;
72 :
73 : case DYING:
74 0 : return true;
75 :
76 : default:
77 0 : NS_ERROR("Unexpected state");
78 0 : return false;
79 : };
80 :
81 0 : mNPP->mNPNIface->destroystream(mNPP->mNPP, mStream, reason);
82 0 : return true;
83 : }
84 :
85 : void
86 0 : BrowserStreamParent::NPP_DestroyStream(NPReason reason)
87 : {
88 0 : NS_ASSERTION(ALIVE == mState, "NPP_DestroyStream called twice?");
89 0 : mState = DYING;
90 0 : unused << SendNPP_DestroyStream(reason);
91 0 : }
92 :
93 : bool
94 0 : BrowserStreamParent::RecvStreamDestroyed()
95 : {
96 0 : if (DYING != mState) {
97 0 : NS_ERROR("Unexpected state");
98 0 : return false;
99 : }
100 :
101 0 : mStreamPeer = NULL;
102 :
103 0 : mState = DELETING;
104 0 : return Send__delete__(this);
105 : }
106 :
107 : int32_t
108 0 : BrowserStreamParent::WriteReady()
109 : {
110 0 : return kSendDataChunk;
111 : }
112 :
113 : int32_t
114 0 : BrowserStreamParent::Write(int32_t offset,
115 : int32_t len,
116 : void* buffer)
117 : {
118 0 : PLUGIN_LOG_DEBUG_FUNCTION;
119 :
120 0 : NS_ASSERTION(ALIVE == mState, "Sending data after NPP_DestroyStream?");
121 0 : NS_ASSERTION(len > 0, "Non-positive length to NPP_Write");
122 :
123 0 : if (len > kSendDataChunk)
124 0 : len = kSendDataChunk;
125 :
126 : return SendWrite(offset,
127 0 : nsCString(static_cast<char*>(buffer), len),
128 0 : mStream->end) ?
129 0 : len : -1;
130 : }
131 :
132 : void
133 0 : BrowserStreamParent::StreamAsFile(const char* fname)
134 : {
135 0 : PLUGIN_LOG_DEBUG_FUNCTION;
136 :
137 0 : NS_ASSERTION(ALIVE == mState,
138 : "Calling streamasfile after NPP_DestroyStream?");
139 :
140 : // Make sure our stream survives until the plugin process tells us we've
141 : // been destroyed (until RecvStreamDestroyed() is called). Since we retain
142 : // mStreamPeer at most once, we won't get in trouble if StreamAsFile() is
143 : // called more than once.
144 0 : if (!mStreamPeer) {
145 0 : nsNPAPIPlugin::RetainStream(mStream, getter_AddRefs(mStreamPeer));
146 : }
147 :
148 0 : unused << SendNPP_StreamAsFile(nsCString(fname));
149 : return;
150 : }
151 :
152 : } // namespace plugins
153 : } // namespace mozilla
|