Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: webkit/glue/plugins/plugin_stream.cc

Issue 6012002: Move the NPAPI files from webkit/glue/plugins to webkit/plugins/npapi and put... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/glue/plugins/plugin_stream.h ('k') | webkit/glue/plugins/plugin_stream_posix.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // TODO : Support NP_ASFILEONLY mode
6 // TODO : Support NP_SEEK mode
7 // TODO : Support SEEKABLE=true in NewStream
8
9 #include "webkit/glue/plugins/plugin_stream.h"
10
11 #include "base/message_loop.h"
12 #include "base/string_util.h"
13 #include "base/utf_string_conversions.h"
14 #include "net/base/mime_util.h"
15 #include "webkit/glue/plugins/plugin_instance.h"
16 #include "googleurl/src/gurl.h"
17
18 namespace NPAPI {
19
20 PluginStream::~PluginStream() {
21 // always close our temporary files.
22 CloseTempFile();
23 free(const_cast<char*>(stream_.url));
24 }
25
26 bool PluginStream::Open(const std::string &mime_type,
27 const std::string &headers,
28 uint32 length,
29 uint32 last_modified,
30 bool request_is_seekable) {
31 headers_ = headers;
32 NPP id = instance_->npp();
33 stream_.end = length;
34 stream_.lastmodified = last_modified;
35 stream_.pdata = 0;
36 stream_.ndata = id->ndata;
37 stream_.notifyData = notify_data_;
38 if (!headers_.empty())
39 stream_.headers = headers_.c_str();
40
41 bool seekable_stream = false;
42 if (request_is_seekable) {
43 std::string headers_lc = StringToLowerASCII(headers);
44 if (headers_lc.find("accept-ranges: bytes") != std::string::npos) {
45 seekable_stream = true;
46 }
47 }
48
49 const char *char_mime_type = "application/x-unknown-content-type";
50 std::string temp_mime_type;
51 if (!mime_type.empty()) {
52 char_mime_type = mime_type.c_str();
53 } else {
54 GURL gurl(stream_.url);
55
56 #if defined(OS_WIN)
57 FilePath path(UTF8ToWide(gurl.path()));
58 #elif defined(OS_POSIX)
59 FilePath path(gurl.path());
60 #endif
61 if (net::GetMimeTypeFromFile(path, &temp_mime_type))
62 char_mime_type = temp_mime_type.c_str();
63 }
64
65 // Silverlight expects a valid mime type
66 DCHECK(strlen(char_mime_type) != 0);
67 NPError err = instance_->NPP_NewStream((NPMIMEType)char_mime_type,
68 &stream_, seekable_stream,
69 &requested_plugin_mode_);
70 if (err != NPERR_NO_ERROR) {
71 Notify(err);
72 return false;
73 }
74
75 opened_ = true;
76
77 if (requested_plugin_mode_ == NP_SEEK) {
78 seekable_stream_ = true;
79 }
80 // If the plugin has requested certain modes, then we need a copy
81 // of this file on disk. Open it and save it as we go.
82 if (requested_plugin_mode_ == NP_ASFILEONLY ||
83 requested_plugin_mode_ == NP_ASFILE) {
84 if (OpenTempFile() == false)
85 return false;
86 }
87
88 mime_type_ = char_mime_type;
89 return true;
90 }
91
92 int PluginStream::Write(const char *buffer, const int length,
93 int data_offset) {
94 // There may be two streams to write to - the plugin and the file.
95 // It is unclear what to do if we cannot write to both. The rules of
96 // this function are that the plugin must consume at least as many
97 // bytes as returned by the WriteReady call. So, we will attempt to
98 // write that many to both streams. If we can't write that many bytes
99 // to each stream, we'll return failure.
100
101 DCHECK(opened_);
102 if (WriteToFile(buffer, length) &&
103 WriteToPlugin(buffer, length, data_offset))
104 return length;
105
106 return -1;
107 }
108
109 bool PluginStream::WriteToFile(const char *buf, size_t length) {
110 // For ASFILEONLY, ASFILE, and SEEK modes, we need to write
111 // to the disk
112 if (TempFileIsValid() &&
113 (requested_plugin_mode_ == NP_ASFILE ||
114 requested_plugin_mode_ == NP_ASFILEONLY) ) {
115 size_t totalBytesWritten = 0, bytes;
116 do {
117 bytes = WriteBytes(buf, length);
118 totalBytesWritten += bytes;
119 } while (bytes > 0U && totalBytesWritten < length);
120
121 if (totalBytesWritten != length)
122 return false;
123 }
124
125 return true;
126 }
127
128 bool PluginStream::WriteToPlugin(const char *buf, const int length,
129 const int data_offset) {
130 // For NORMAL and ASFILE modes, we send the data to the plugin now
131 if (requested_plugin_mode_ != NP_NORMAL &&
132 requested_plugin_mode_ != NP_ASFILE &&
133 requested_plugin_mode_ != NP_SEEK)
134 return true;
135
136 int written = TryWriteToPlugin(buf, length, data_offset);
137 if (written == -1)
138 return false;
139
140 if (written < length) {
141 // Buffer the remaining data.
142 size_t remaining = length - written;
143 size_t previous_size = delivery_data_.size();
144 delivery_data_.resize(previous_size + remaining);
145 data_offset_ = data_offset;
146 memcpy(&delivery_data_[previous_size], buf + written, remaining);
147 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
148 this, &PluginStream::OnDelayDelivery));
149 }
150
151 return true;
152 }
153
154 void PluginStream::OnDelayDelivery() {
155 // It is possible that the plugin stream may have closed before the task
156 // was hit.
157 if (!opened_) {
158 return;
159 }
160
161 int size = static_cast<int>(delivery_data_.size());
162 int written = TryWriteToPlugin(&delivery_data_.front(), size,
163 data_offset_);
164 if (written > 0) {
165 // Remove the data that we already wrote.
166 delivery_data_.erase(delivery_data_.begin(),
167 delivery_data_.begin() + written);
168 }
169 }
170
171 int PluginStream::TryWriteToPlugin(const char *buf, const int length,
172 const int data_offset) {
173 int byte_offset = 0;
174
175 if (data_offset > 0)
176 data_offset_ = data_offset;
177
178 while (byte_offset < length) {
179 int bytes_remaining = length - byte_offset;
180 int bytes_to_write = instance_->NPP_WriteReady(&stream_);
181 if (bytes_to_write > bytes_remaining)
182 bytes_to_write = bytes_remaining;
183
184 if (bytes_to_write == 0)
185 return byte_offset;
186
187 int bytes_consumed = instance_->NPP_Write(
188 &stream_, data_offset_, bytes_to_write,
189 const_cast<char*>(buf + byte_offset));
190 if (bytes_consumed < 0) {
191 // The plugin failed, which means that we need to close the stream.
192 Close(NPRES_NETWORK_ERR);
193 return -1;
194 }
195 if (bytes_consumed == 0) {
196 // The plugin couldn't take all of the data now.
197 return byte_offset;
198 }
199
200 // The plugin might report more that we gave it.
201 bytes_consumed = std::min(bytes_consumed, bytes_to_write);
202
203 data_offset_ += bytes_consumed;
204 byte_offset += bytes_consumed;
205 }
206
207 if (close_on_write_data_)
208 Close(NPRES_DONE);
209
210 return length;
211 }
212
213 bool PluginStream::Close(NPReason reason) {
214 if (opened_ == true) {
215 opened_ = false;
216
217 if (delivery_data_.size()) {
218 if (reason == NPRES_DONE) {
219 // There is more data to be streamed, don't destroy the stream now.
220 close_on_write_data_ = true;
221 return true;
222 } else {
223 // Stop any pending data from being streamed
224 delivery_data_.resize(0);
225 }
226 }
227
228 // If we have a temp file, be sure to close it.
229 // Also, allow the plugin to access it now.
230 if (TempFileIsValid()) {
231 CloseTempFile();
232 if (reason == NPRES_DONE)
233 WriteAsFile();
234 }
235
236 if (stream_.ndata != NULL) {
237 // Stream hasn't been closed yet.
238 NPError err = instance_->NPP_DestroyStream(&stream_, reason);
239 DCHECK(err == NPERR_NO_ERROR);
240 }
241 }
242
243 Notify(reason);
244 return true;
245 }
246
247 webkit_glue::WebPluginResourceClient* PluginStream::AsResourceClient() {
248 return NULL;
249 }
250
251 void PluginStream::Notify(NPReason reason) {
252 if (notify_needed_) {
253 instance_->NPP_URLNotify(stream_.url, reason, notify_data_);
254 notify_needed_ = false;
255 }
256 }
257
258 } // namespace NPAPI
OLDNEW
« no previous file with comments | « webkit/glue/plugins/plugin_stream.h ('k') | webkit/glue/plugins/plugin_stream_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698