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

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

Issue 2896: This CB fixes the following issues:-... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 3 months 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_url.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // TODO : Support NP_ASFILEONLY mode 5 // TODO : Support NP_ASFILEONLY mode
6 // TODO : Support NP_SEEK mode 6 // TODO : Support NP_SEEK mode
7 // TODO : Support SEEKABLE=true in NewStream 7 // TODO : Support SEEKABLE=true in NewStream
8 8
9 #include "webkit/glue/plugins/plugin_stream.h" 9 #include "webkit/glue/plugins/plugin_stream.h"
10 10
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "base/message_loop.h" 12 #include "base/message_loop.h"
13 #include "webkit/glue/plugins/plugin_instance.h" 13 #include "webkit/glue/plugins/plugin_instance.h"
14 #include "webkit/glue/webkit_glue.h" 14 #include "webkit/glue/webkit_glue.h"
15 #include "googleurl/src/gurl.h" 15 #include "googleurl/src/gurl.h"
16 16
17 namespace NPAPI { 17 namespace NPAPI {
18 18
19 PluginStream::PluginStream( 19 PluginStream::PluginStream(
20 PluginInstance *instance, 20 PluginInstance *instance,
21 const char *url, 21 const char *url,
22 bool need_notify, 22 bool need_notify,
23 void *notify_data) 23 void *notify_data)
24 : instance_(instance), 24 : instance_(instance),
25 bytes_sent_(0),
26 notify_needed_(need_notify), 25 notify_needed_(need_notify),
27 notify_data_(notify_data), 26 notify_data_(notify_data),
28 close_on_write_data_(false), 27 close_on_write_data_(false),
29 opened_(false), 28 opened_(false),
30 requested_plugin_mode_(NP_NORMAL), 29 requested_plugin_mode_(NP_NORMAL),
31 temp_file_handle_(INVALID_HANDLE_VALUE) { 30 temp_file_handle_(INVALID_HANDLE_VALUE),
31 seekable_stream_(false),
32 data_offset_(0) {
32 memset(&stream_, 0, sizeof(stream_)); 33 memset(&stream_, 0, sizeof(stream_));
33 stream_.url = _strdup(url); 34 stream_.url = _strdup(url);
34 temp_file_name_[0] = '\0'; 35 temp_file_name_[0] = '\0';
35 } 36 }
36 37
37 PluginStream::~PluginStream() { 38 PluginStream::~PluginStream() {
38 // always cleanup our temporary files. 39 // always cleanup our temporary files.
39 CleanupTempFile(); 40 CleanupTempFile();
40
41 free(const_cast<char*>(stream_.url)); 41 free(const_cast<char*>(stream_.url));
42 } 42 }
43 43
44 void PluginStream::UpdateUrl(const char* url) { 44 void PluginStream::UpdateUrl(const char* url) {
45 DCHECK(!opened_); 45 DCHECK(!opened_);
46 free(const_cast<char*>(stream_.url)); 46 free(const_cast<char*>(stream_.url));
47 stream_.url = _strdup(url); 47 stream_.url = _strdup(url);
48 } 48 }
49 49
50 bool PluginStream::Open(const std::string &mime_type, 50 bool PluginStream::Open(const std::string &mime_type,
51 const std::string &headers, 51 const std::string &headers,
52 uint32 length, 52 uint32 length,
53 uint32 last_modified) { 53 uint32 last_modified) {
54 headers_ = headers; 54 headers_ = headers;
55 NPP id = instance_->npp(); 55 NPP id = instance_->npp();
56 stream_.end = length; 56 stream_.end = length;
57 stream_.lastmodified = last_modified; 57 stream_.lastmodified = last_modified;
58 stream_.pdata = 0; 58 stream_.pdata = 0;
59 stream_.ndata = id->ndata; 59 stream_.ndata = id->ndata;
60 stream_.notifyData = notify_data_; 60 stream_.notifyData = notify_data_;
61 if (!headers_.empty()) 61
62 bool seekable_stream = false;
63 if (!headers_.empty()) {
62 stream_.headers = headers_.c_str(); 64 stream_.headers = headers_.c_str();
65 if (headers_.find("Accept-Ranges: bytes") != std::string::npos) {
66 seekable_stream = true;
67 }
68 }
63 69
64 const char *char_mime_type = "application/x-unknown-content-type"; 70 const char *char_mime_type = "application/x-unknown-content-type";
65 std::string temp_mime_type; 71 std::string temp_mime_type;
66 if (!mime_type.empty()) { 72 if (!mime_type.empty()) {
67 char_mime_type = mime_type.c_str(); 73 char_mime_type = mime_type.c_str();
68 } else { 74 } else {
69 GURL gurl(stream_.url); 75 GURL gurl(stream_.url);
70 std::wstring path(UTF8ToWide(gurl.path())); 76 std::wstring path(UTF8ToWide(gurl.path()));
71 if (webkit_glue::GetMimeTypeFromFile(path, &temp_mime_type)) 77 if (webkit_glue::GetMimeTypeFromFile(path, &temp_mime_type))
72 char_mime_type = temp_mime_type.c_str(); 78 char_mime_type = temp_mime_type.c_str();
73 } 79 }
74 80
75 // Silverlight expects a valid mime type 81 // Silverlight expects a valid mime type
76 DCHECK(strlen(char_mime_type) != 0); 82 DCHECK(strlen(char_mime_type) != 0);
77 NPError err = instance_->NPP_NewStream((NPMIMEType)char_mime_type, 83 NPError err = instance_->NPP_NewStream((NPMIMEType)char_mime_type,
78 &stream_, false, 84 &stream_, seekable_stream,
79 &requested_plugin_mode_); 85 &requested_plugin_mode_);
80 if (err != NPERR_NO_ERROR) 86 if (err != NPERR_NO_ERROR)
81 return false; 87 return false;
82 88
83 opened_ = true; 89 opened_ = true;
84 90
91 if (requested_plugin_mode_ == NP_SEEK) {
92 seekable_stream_ = true;
93 }
94
85 // If the plugin has requested certain modes, then we need a copy 95 // If the plugin has requested certain modes, then we need a copy
86 // of this file on disk. Open it and save it as we go. 96 // of this file on disk. Open it and save it as we go.
87 if (requested_plugin_mode_ == NP_ASFILEONLY || 97 if (requested_plugin_mode_ == NP_ASFILEONLY ||
88 requested_plugin_mode_ == NP_ASFILE || 98 requested_plugin_mode_ == NP_ASFILE) {
89 requested_plugin_mode_ == NP_SEEK) {
90 if (OpenTempFile() == false) 99 if (OpenTempFile() == false)
91 return false; 100 return false;
92 } 101 }
93 102
103 mime_type_ = char_mime_type;
94 return true; 104 return true;
95 } 105 }
96 106
97 int PluginStream::Write(const char *buffer, const int length) { 107 int PluginStream::Write(const char *buffer, const int length,
108 int data_offset) {
98 // There may be two streams to write to - the plugin and the file. 109 // There may be two streams to write to - the plugin and the file.
99 // It is unclear what to do if we cannot write to both. The rules of 110 // It is unclear what to do if we cannot write to both. The rules of
100 // this function are that the plugin must consume at least as many 111 // this function are that the plugin must consume at least as many
101 // bytes as returned by the WriteReady call. So, we will attempt to 112 // bytes as returned by the WriteReady call. So, we will attempt to
102 // write that many to both streams. If we can't write that many bytes 113 // write that many to both streams. If we can't write that many bytes
103 // to each stream, we'll return failure. 114 // to each stream, we'll return failure.
104 115
105 DCHECK(opened_); 116 DCHECK(opened_);
106 if (WriteToFile(buffer, length) && WriteToPlugin(buffer, length)) 117 if (WriteToFile(buffer, length) &&
118 WriteToPlugin(buffer, length, data_offset))
107 return length; 119 return length;
108 120
109 return -1; 121 return -1;
110 } 122 }
111 123
112 bool PluginStream::WriteToFile(const char *buf, const int length) { 124 bool PluginStream::WriteToFile(const char *buf, const int length) {
113 // For ASFILEONLY, ASFILE, and SEEK modes, we need to write 125 // For ASFILEONLY, ASFILE, and SEEK modes, we need to write
114 // to the disk 126 // to the disk
115 if (temp_file_handle_ != INVALID_HANDLE_VALUE && 127 if (temp_file_handle_ != INVALID_HANDLE_VALUE &&
116 (requested_plugin_mode_ == NP_SEEK || 128 (requested_plugin_mode_ == NP_ASFILE ||
117 requested_plugin_mode_ == NP_ASFILE ||
118 requested_plugin_mode_ == NP_ASFILEONLY) ) { 129 requested_plugin_mode_ == NP_ASFILEONLY) ) {
119 int totalBytesWritten = 0; 130 int totalBytesWritten = 0;
120 DWORD bytes; 131 DWORD bytes;
121 do { 132 do {
122 if (WriteFile(temp_file_handle_, buf, length, &bytes, 0) == FALSE) 133 if (WriteFile(temp_file_handle_, buf, length, &bytes, 0) == FALSE)
123 break; 134 break;
124 totalBytesWritten += bytes; 135 totalBytesWritten += bytes;
125 } while (bytes > 0 && totalBytesWritten < length); 136 } while (bytes > 0 && totalBytesWritten < length);
126 137
127 if (totalBytesWritten != length) 138 if (totalBytesWritten != length)
128 return false; 139 return false;
129 } 140 }
130 141
131 return true; 142 return true;
132 } 143 }
133 144
134 bool PluginStream::WriteToPlugin(const char *buf, const int length) { 145 bool PluginStream::WriteToPlugin(const char *buf, const int length,
146 const int data_offset) {
135 // For NORMAL and ASFILE modes, we send the data to the plugin now 147 // For NORMAL and ASFILE modes, we send the data to the plugin now
136 if (requested_plugin_mode_ != NP_NORMAL && 148 if (requested_plugin_mode_ != NP_NORMAL &&
137 requested_plugin_mode_ != NP_ASFILE) 149 requested_plugin_mode_ != NP_ASFILE &&
150 requested_plugin_mode_ != NP_SEEK)
138 return true; 151 return true;
139 152
140 int written = TryWriteToPlugin(buf, length); 153 int written = TryWriteToPlugin(buf, length, data_offset);
141 if (written == -1) 154 if (written == -1)
142 return false; 155 return false;
143 156
144 if (written < length) { 157 if (written < length) {
145 // Buffer the remaining data. 158 // Buffer the remaining data.
146 size_t remaining = length - written; 159 size_t remaining = length - written;
147 size_t previous_size = delivery_data_.size(); 160 size_t previous_size = delivery_data_.size();
148 delivery_data_.resize(previous_size + remaining); 161 delivery_data_.resize(previous_size + remaining);
162 data_offset_ = data_offset;
149 memcpy(&delivery_data_[previous_size], buf + written, remaining); 163 memcpy(&delivery_data_[previous_size], buf + written, remaining);
150 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 164 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
151 this, &PluginStream::OnDelayDelivery)); 165 this, &PluginStream::OnDelayDelivery));
152 } 166 }
153 167
154 return true; 168 return true;
155 } 169 }
156 170
157 void PluginStream::OnDelayDelivery() { 171 void PluginStream::OnDelayDelivery() {
158 // It is possible that the plugin stream may have closed before the task 172 // It is possible that the plugin stream may have closed before the task
159 // was hit. 173 // was hit.
160 if (!opened_) { 174 if (!opened_) {
161 return; 175 return;
162 } 176 }
163 177
164 int size = static_cast<int>(delivery_data_.size()); 178 int size = static_cast<int>(delivery_data_.size());
165 int written = TryWriteToPlugin(&delivery_data_.front(), size); 179 int written = TryWriteToPlugin(&delivery_data_.front(), size,
180 data_offset_);
166 if (written > 0) { 181 if (written > 0) {
167 // Remove the data that we already wrote. 182 // Remove the data that we already wrote.
168 delivery_data_.erase(delivery_data_.begin(), 183 delivery_data_.erase(delivery_data_.begin(),
169 delivery_data_.begin() + written); 184 delivery_data_.begin() + written);
170 } 185 }
171 } 186 }
172 187
173 int PluginStream::TryWriteToPlugin(const char *buf, const int length) { 188 int PluginStream::TryWriteToPlugin(const char *buf, const int length,
189 const int data_offset) {
174 bool result = true; 190 bool result = true;
175 int byte_offset = 0; 191 int byte_offset = 0;
176 192
193 if (data_offset > 0)
194 data_offset_ = data_offset;
195
177 while (byte_offset < length) { 196 while (byte_offset < length) {
178 int bytes_remaining = length - byte_offset; 197 int bytes_remaining = length - byte_offset;
179 int bytes_to_write = instance_->NPP_WriteReady(&stream_); 198 int bytes_to_write = instance_->NPP_WriteReady(&stream_);
180 if (bytes_to_write > bytes_remaining) 199 if (bytes_to_write > bytes_remaining)
181 bytes_to_write = bytes_remaining; 200 bytes_to_write = bytes_remaining;
182 201
183 if (bytes_to_write == 0) 202 if (bytes_to_write == 0)
184 return byte_offset; 203 return byte_offset;
185 204
186 int bytes_consumed = instance_->NPP_Write( 205 int bytes_consumed = instance_->NPP_Write(
187 &stream_, bytes_sent_, bytes_to_write, 206 &stream_, data_offset_, bytes_to_write,
188 const_cast<char*>(buf + byte_offset)); 207 const_cast<char*>(buf + byte_offset));
189 if (bytes_consumed < 0) { 208 if (bytes_consumed < 0) {
190 // The plugin failed, which means that we need to close the stream. 209 // The plugin failed, which means that we need to close the stream.
191 Close(NPRES_NETWORK_ERR); 210 Close(NPRES_NETWORK_ERR);
192 return -1; 211 return -1;
193 } 212 }
194 if (bytes_consumed == 0) { 213 if (bytes_consumed == 0) {
195 // The plugin couldn't take all of the data now. 214 // The plugin couldn't take all of the data now.
196 return byte_offset; 215 return byte_offset;
197 } 216 }
198 217
199 // The plugin might report more that we gave it. 218 // The plugin might report more that we gave it.
200 bytes_consumed = std::min(bytes_consumed, bytes_to_write); 219 bytes_consumed = std::min(bytes_consumed, bytes_to_write);
201 220
202 bytes_sent_ += bytes_consumed; 221 data_offset_ += bytes_consumed;
203 byte_offset += bytes_consumed; 222 byte_offset += bytes_consumed;
204 } 223 }
205 224
206 if (close_on_write_data_) 225 if (close_on_write_data_)
207 Close(NPRES_DONE); 226 Close(NPRES_DONE);
208 227
209 return length; 228 return length;
210 } 229 }
211 230
212 void PluginStream::WriteAsFile() { 231 void PluginStream::WriteAsFile() {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 317
299 void PluginStream::Notify(NPReason reason) { 318 void PluginStream::Notify(NPReason reason) {
300 if (notify_needed_) { 319 if (notify_needed_) {
301 instance_->NPP_URLNotify(stream_.url, reason, notify_data_); 320 instance_->NPP_URLNotify(stream_.url, reason, notify_data_);
302 notify_needed_ = false; 321 notify_needed_ = false;
303 } 322 }
304 } 323 }
305 324
306 } // namespace NPAPI 325 } // namespace NPAPI
307 326
OLDNEW
« no previous file with comments | « webkit/glue/plugins/plugin_stream.h ('k') | webkit/glue/plugins/plugin_stream_url.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698