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

Side by Side Diff: webkit/plugins/ppapi/ppb_url_request_info_impl.cc

Issue 7706021: Convert FileRefImpl and URLRequestInfo to shared_impl. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Tests fixed Created 9 years, 4 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 #include "webkit/plugins/ppapi/ppb_url_request_info_impl.h" 5 #include "webkit/plugins/ppapi/ppb_url_request_info_impl.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "googleurl/src/gurl.h" 9 #include "googleurl/src/gurl.h"
10 #include "googleurl/src/url_util.h" 10 #include "googleurl/src/url_util.h"
11 #include "net/http/http_util.h" 11 #include "net/http/http_util.h"
12 #include "ppapi/c/pp_var.h"
13 #include "ppapi/shared_impl/var.h" 12 #include "ppapi/shared_impl/var.h"
14 #include "ppapi/thunk/enter.h" 13 #include "ppapi/thunk/enter.h"
15 #include "ppapi/thunk/ppb_file_ref_api.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h" 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPBody.h" 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPBody.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
22 #include "webkit/glue/webkit_glue.h" 20 #include "webkit/glue/webkit_glue.h"
23 #include "webkit/plugins/ppapi/common.h" 21 #include "webkit/plugins/ppapi/common.h"
24 #include "webkit/plugins/ppapi/plugin_module.h" 22 #include "webkit/plugins/ppapi/plugin_module.h"
25 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
26 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h" 23 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
27 #include "webkit/plugins/ppapi/ppb_file_system_impl.h" 24 #include "webkit/plugins/ppapi/ppb_file_system_impl.h"
28 #include "webkit/plugins/ppapi/resource_helper.h" 25 #include "webkit/plugins/ppapi/resource_helper.h"
29 #include "webkit/plugins/ppapi/string.h"
30 26
31 using ppapi::StringVar; 27 using ppapi::PPB_URLRequestInfo_Data;
28 using ppapi::Resource;
32 using ppapi::thunk::EnterResourceNoLock; 29 using ppapi::thunk::EnterResourceNoLock;
33 using ppapi::thunk::PPB_FileRef_API; 30 using ppapi::thunk::PPB_FileRef_API;
34 using ppapi::thunk::PPB_URLRequestInfo_API;
35 using WebKit::WebData; 31 using WebKit::WebData;
36 using WebKit::WebHTTPBody; 32 using WebKit::WebHTTPBody;
37 using WebKit::WebString; 33 using WebKit::WebString;
38 using WebKit::WebFrame; 34 using WebKit::WebFrame;
39 using WebKit::WebURL; 35 using WebKit::WebURL;
40 using WebKit::WebURLRequest; 36 using WebKit::WebURLRequest;
41 37
42 namespace webkit { 38 namespace webkit {
43 namespace ppapi { 39 namespace ppapi {
44 40
(...skipping 13 matching lines...) Expand all
58 return false; 54 return false;
59 if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' || 55 if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
60 c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' || 56 c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
61 c == '/' || c == '[' || c == ']' || c == '?' || c == '=' || 57 c == '/' || c == '[' || c == ']' || c == '?' || c == '=' ||
62 c == '{' || c == '}') 58 c == '{' || c == '}')
63 return false; 59 return false;
64 } 60 }
65 return true; 61 return true;
66 } 62 }
67 63
68 // These methods are not allowed by the XMLHttpRequest standard.
69 // http://www.w3.org/TR/XMLHttpRequest/#the-open-method
70 const char* const kForbiddenHttpMethods[] = {
71 "connect",
72 "trace",
73 "track",
74 };
75
76 // These are the "known" methods in the Webkit XHR implementation. Also see
77 // the XMLHttpRequest standard.
78 // http://www.w3.org/TR/XMLHttpRequest/#the-open-method
79 const char* const kKnownHttpMethods[] = {
80 "get",
81 "post",
82 "put",
83 "head",
84 "copy",
85 "delete",
86 "index",
87 "lock",
88 "m-post",
89 "mkcol",
90 "move",
91 "options",
92 "propfind",
93 "proppatch",
94 "unlock",
95 };
96
97 std::string ValidateMethod(const std::string& method) {
98 for (size_t i = 0; i < arraysize(kForbiddenHttpMethods); ++i) {
99 if (LowerCaseEqualsASCII(method, kForbiddenHttpMethods[i]))
100 return std::string();
101 }
102 for (size_t i = 0; i < arraysize(kKnownHttpMethods); ++i) {
103 if (LowerCaseEqualsASCII(method, kKnownHttpMethods[i])) {
104 // Convert the method name to upper case to match Webkit and Firefox's
105 // XHR implementation.
106 return StringToUpperASCII(std::string(kKnownHttpMethods[i]));
107 }
108 }
109 // Pass through unknown methods that are not forbidden.
110 return method;
111 }
112
113 // A header string containing any of the following fields will cause 64 // A header string containing any of the following fields will cause
114 // an error. The list comes from the XMLHttpRequest standard. 65 // an error. The list comes from the XMLHttpRequest standard.
115 // http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method 66 // http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method
116 const char* const kForbiddenHeaderFields[] = { 67 const char* const kForbiddenHeaderFields[] = {
117 "accept-charset", 68 "accept-charset",
118 "accept-encoding", 69 "accept-encoding",
119 "connection", 70 "connection",
120 "content-length", 71 "content-length",
121 "cookie", 72 "cookie",
122 "cookie2", 73 "cookie2",
(...skipping 29 matching lines...) Expand all
152 net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n"); 103 net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
153 while (it.GetNext()) { 104 while (it.GetNext()) {
154 if (!IsValidHeaderField(it.name())) 105 if (!IsValidHeaderField(it.name()))
155 return false; 106 return false;
156 } 107 }
157 return true; 108 return true;
158 } 109 }
159 110
160 } // namespace 111 } // namespace
161 112
162 struct PPB_URLRequestInfo_Impl::BodyItem {
163 explicit BodyItem(const std::string& data)
164 : data(data),
165 start_offset(0),
166 number_of_bytes(-1),
167 expected_last_modified_time(0.0) {
168 }
169 113
170 BodyItem(PPB_FileRef_Impl* file_ref, 114 PPB_URLRequestInfo_Impl::PPB_URLRequestInfo_Impl(
171 int64_t start_offset, 115 PP_Instance instance,
172 int64_t number_of_bytes, 116 const PPB_URLRequestInfo_Data& data)
173 PP_Time expected_last_modified_time) 117 : URLRequestInfoImpl(instance, data) {
174 : file_ref(file_ref),
175 start_offset(start_offset),
176 number_of_bytes(number_of_bytes),
177 expected_last_modified_time(expected_last_modified_time) {
178 }
179
180 std::string data;
181 scoped_refptr<PPB_FileRef_Impl> file_ref;
182 int64_t start_offset;
183 int64_t number_of_bytes;
184 PP_Time expected_last_modified_time;
185 };
186
187 PPB_URLRequestInfo_Impl::PPB_URLRequestInfo_Impl(PP_Instance instance)
188 : Resource(instance),
189 stream_to_file_(false),
190 follow_redirects_(true),
191 record_download_progress_(false),
192 record_upload_progress_(false),
193 has_custom_referrer_url_(false),
194 allow_cross_origin_requests_(false),
195 allow_credentials_(false),
196 has_custom_content_transfer_encoding_(false),
197 prefetch_buffer_upper_threshold_(kDefaultPrefetchBufferUpperThreshold),
198 prefetch_buffer_lower_threshold_(kDefaultPrefetchBufferLowerThreshold) {
199 } 118 }
200 119
201 PPB_URLRequestInfo_Impl::~PPB_URLRequestInfo_Impl() { 120 PPB_URLRequestInfo_Impl::~PPB_URLRequestInfo_Impl() {
202 } 121 }
203 122
204 PPB_URLRequestInfo_API* PPB_URLRequestInfo_Impl::AsPPB_URLRequestInfo_API() { 123 bool PPB_URLRequestInfo_Impl::ToWebURLRequest(WebFrame* frame,
205 return this; 124 WebURLRequest* dest) {
206 } 125 // In the out-of-process case, we've received the PPB_URLRequestInfo_Data
126 // from the untrusted plugin and done no validation on it. We need to be
127 // sure it's not being malicious by checking everything for consistency.
128 if (!ValidateData())
129 return false;
207 130
208 PP_Bool PPB_URLRequestInfo_Impl::SetProperty(PP_URLRequestProperty property, 131 dest->initialize();
209 PP_Var var) { 132 dest->setURL(frame->document().completeURL(WebString::fromUTF8(
210 PP_Bool result = PP_FALSE; 133 data().url)));
bbudge 2011/08/25 19:50:37 Single line?
211 switch (var.type) { 134 dest->setDownloadToFile(data().stream_to_file);
212 case PP_VARTYPE_UNDEFINED: 135 dest->setReportUploadProgress(data().record_upload_progress);
213 result = PP_FromBool(SetUndefinedProperty(property));
214 break;
215 case PP_VARTYPE_BOOL:
216 result = PP_FromBool(
217 SetBooleanProperty(property, PP_ToBool(var.value.as_bool)));
218 break;
219 case PP_VARTYPE_INT32:
220 result = PP_FromBool(
221 SetIntegerProperty(property, var.value.as_int));
222 break;
223 case PP_VARTYPE_STRING: {
224 StringVar* string = StringVar::FromPPVar(var);
225 if (string)
226 result = PP_FromBool(SetStringProperty(property, string->value()));
227 break;
228 }
229 default:
230 break;
231 }
232 return result;
233 }
234 136
235 PP_Bool PPB_URLRequestInfo_Impl::AppendDataToBody(const void* data, 137 if (!data().method.empty())
236 uint32_t len) { 138 dest->setHTTPMethod(WebString::fromUTF8(data().method));
237 if (len > 0)
238 body_.push_back(BodyItem(std::string(static_cast<const char*>(data), len)));
239 return PP_TRUE;
240 }
241 139
242 PP_Bool PPB_URLRequestInfo_Impl::AppendFileToBody( 140 dest->setFirstPartyForCookies(
243 PP_Resource file_ref,
244 int64_t start_offset,
245 int64_t number_of_bytes,
246 PP_Time expected_last_modified_time) {
247 // Ignore a call to append nothing.
248 if (number_of_bytes == 0)
249 return PP_TRUE;
250
251 // Check for bad values. (-1 means read until end of file.)
252 if (start_offset < 0 || number_of_bytes < -1)
253 return PP_FALSE;
254
255 EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, true);
256 if (enter.failed())
257 return PP_FALSE;
258
259 body_.push_back(BodyItem(static_cast<PPB_FileRef_Impl*>(enter.object()),
260 start_offset,
261 number_of_bytes,
262 expected_last_modified_time));
263 return PP_TRUE;
264 }
265
266 WebURLRequest PPB_URLRequestInfo_Impl::ToWebURLRequest(WebFrame* frame) const {
267 WebURLRequest web_request;
268 web_request.initialize();
269 web_request.setURL(frame->document().completeURL(WebString::fromUTF8(url_)));
270 web_request.setDownloadToFile(stream_to_file_);
271 web_request.setReportUploadProgress(record_upload_progress());
272
273 if (!method_.empty())
274 web_request.setHTTPMethod(WebString::fromUTF8(method_));
275
276 web_request.setFirstPartyForCookies(
277 frame->document().firstPartyForCookies()); 141 frame->document().firstPartyForCookies());
bbudge 2011/08/25 19:50:37 Single line?
278 142
279 if (!headers_.empty()) { 143 const std::string& headers = data().headers;
280 net::HttpUtil::HeadersIterator it(headers_.begin(), headers_.end(), "\n"); 144 if (!headers.empty()) {
145 net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
281 while (it.GetNext()) { 146 while (it.GetNext()) {
282 web_request.addHTTPHeaderField( 147 dest->addHTTPHeaderField(
283 WebString::fromUTF8(it.name()), 148 WebString::fromUTF8(it.name()),
284 WebString::fromUTF8(it.values())); 149 WebString::fromUTF8(it.values()));
285 } 150 }
286 } 151 }
287 152
288 if (!body_.empty()) { 153 // Append the upload data.
154 if (!data().body.empty()) {
289 WebHTTPBody http_body; 155 WebHTTPBody http_body;
290 http_body.initialize(); 156 http_body.initialize();
291 for (size_t i = 0; i < body_.size(); ++i) { 157 for (size_t i = 0; i < data().body.size(); ++i) {
292 if (body_[i].file_ref) { 158 const PPB_URLRequestInfo_Data::BodyItem& item = data().body[i];
293 FilePath platform_path; 159 if (item.is_file) {
294 switch (body_[i].file_ref->file_system()->type()) { 160 if (!AppendFileRefToBody(item.file_ref,
295 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: 161 item.start_offset,
296 case PP_FILESYSTEMTYPE_LOCALPERSISTENT: { 162 item.number_of_bytes,
297 // TODO(kinuko): remove this sync IPC when we add more generic 163 item.expected_last_modified_time,
298 // AppendURLRange solution that works for both Blob/FileSystem URL. 164 &http_body))
299 PluginDelegate* plugin_delegate = 165 return false;
300 ResourceHelper::GetPluginDelegate(this);
301 if (plugin_delegate) {
302 plugin_delegate->SyncGetFileSystemPlatformPath(
303 body_[i].file_ref->GetFileSystemURL(), &platform_path);
304 }
305 break;
306 }
307 case PP_FILESYSTEMTYPE_EXTERNAL:
308 platform_path = body_[i].file_ref->GetSystemPath();
309 break;
310 default:
311 NOTREACHED();
312 }
313 http_body.appendFileRange(
314 webkit_glue::FilePathToWebString(platform_path),
315 body_[i].start_offset,
316 body_[i].number_of_bytes,
317 body_[i].expected_last_modified_time);
318 } else { 166 } else {
319 DCHECK(!body_[i].data.empty()); 167 DCHECK(!item.data.empty());
320 http_body.appendData(WebData(body_[i].data)); 168 http_body.appendData(WebData(item.data));
321 } 169 }
322 } 170 }
323 web_request.setHTTPBody(http_body); 171 dest->setHTTPBody(http_body);
324 } 172 }
325 173
326 if (has_custom_referrer_url_) { 174 if (data().has_custom_referrer_url) {
327 if (!custom_referrer_url_.empty()) 175 if (!data().custom_referrer_url.empty())
328 frame->setReferrerForRequest(web_request, GURL(custom_referrer_url_)); 176 frame->setReferrerForRequest(*dest, GURL(data().custom_referrer_url));
329 } else if (!allow_cross_origin_requests_) { 177 } else if (!data().allow_cross_origin_requests) {
330 // Use default, except for cross-origin requests, since 'referer' is not 178 // Use default, except for cross-origin requests, since 'referer' is not
331 // whitelisted and will cause the request to fail. 179 // whitelisted and will cause the request to fail.
332 frame->setReferrerForRequest(web_request, WebURL()); 180 frame->setReferrerForRequest(*dest, WebURL());
333 } 181 }
334 182
335 if (has_custom_content_transfer_encoding_) { 183 if (data().has_custom_content_transfer_encoding) {
336 if (!custom_content_transfer_encoding_.empty()) { 184 if (!data().custom_content_transfer_encoding.empty()) {
337 web_request.addHTTPHeaderField( 185 dest->addHTTPHeaderField(
338 WebString::fromUTF8("Content-Transfer-Encoding"), 186 WebString::fromUTF8("Content-Transfer-Encoding"),
339 WebString::fromUTF8(custom_content_transfer_encoding_)); 187 WebString::fromUTF8(data().custom_content_transfer_encoding));
340 } 188 }
341 } 189 }
342 190
343 return web_request; 191 return true;
344 } 192 }
345 193
346 bool PPB_URLRequestInfo_Impl::RequiresUniversalAccess() const { 194 bool PPB_URLRequestInfo_Impl::RequiresUniversalAccess() const {
347 return 195 return
348 has_custom_referrer_url_ || 196 data().has_custom_referrer_url ||
349 has_custom_content_transfer_encoding_ || 197 data().has_custom_content_transfer_encoding ||
350 url_util::FindAndCompareScheme(url_, "javascript", NULL); 198 url_util::FindAndCompareScheme(data().url, "javascript", NULL);
351 } 199 }
352 200
353 bool PPB_URLRequestInfo_Impl::SetUndefinedProperty( 201 bool PPB_URLRequestInfo_Impl::ValidateData() {
354 PP_URLRequestProperty property) { 202 // Method should either be empty or a valid one.
355 switch (property) { 203 if (!data().method.empty()) {
356 case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL: 204 std::string canonicalized = ValidateMethod(data().method);
357 has_custom_referrer_url_ = false; 205 if (canonicalized.empty())
358 custom_referrer_url_ = std::string();
359 return true;
360 case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
361 has_custom_content_transfer_encoding_ = false;
362 custom_content_transfer_encoding_ = std::string();
363 return true;
364 default:
365 return false; 206 return false;
207 data().method = canonicalized;
366 } 208 }
209
210 if (!AreValidHeaders(data().headers))
211 return false;
212
213 // Get the Resource objects for any file refs with only host resource (this
214 // is the state of the request as it comes off IPC).
215 for (size_t i = 0; i < data().body.size(); ++i) {
216 PPB_URLRequestInfo_Data::BodyItem& item = data().body[i];
217 if (item.is_file && !item.file_ref) {
218 EnterResourceNoLock<PPB_FileRef_API> enter(
219 item.file_ref_host_resource.host_resource(), false);
220 if (!enter.succeeded())
221 return false;
222 item.file_ref = enter.resource();
223 }
224 }
225 return true;
367 } 226 }
368 227
369 bool PPB_URLRequestInfo_Impl::SetBooleanProperty(PP_URLRequestProperty property, 228 bool PPB_URLRequestInfo_Impl::AppendFileRefToBody(
370 bool value) { 229 Resource* file_ref_resource,
371 switch (property) { 230 int64_t start_offset,
372 case PP_URLREQUESTPROPERTY_STREAMTOFILE: 231 int64_t number_of_bytes,
373 stream_to_file_ = value; 232 PP_Time expected_last_modified_time,
374 return true; 233 WebHTTPBody *http_body) {
375 case PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS: 234 // Get the underlying file ref impl.
376 follow_redirects_ = value; 235 if (!file_ref_resource)
377 return true; 236 return false;
378 case PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS: 237 PPB_FileRef_API* file_ref_api = file_ref_resource->AsPPB_FileRef_API();
379 record_download_progress_ = value; 238 if (!file_ref_api)
380 return true; 239 return false;
381 case PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS: 240 const PPB_FileRef_Impl* file_ref =
382 record_upload_progress_ = value; 241 static_cast<PPB_FileRef_Impl*>(file_ref_api);
383 return true; 242
384 case PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS: 243 PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(this);
385 allow_cross_origin_requests_ = value; 244 if (!plugin_delegate)
386 return true; 245 return false;
387 case PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS: 246
388 allow_credentials_ = value; 247 FilePath platform_path;
389 return true; 248 switch (file_ref->file_system()->type()) {
249 case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
250 case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
251 // TODO(kinuko): remove this sync IPC when we add more generic
252 // AppendURLRange solution that works for both Blob/FileSystem URL.
253 plugin_delegate->SyncGetFileSystemPlatformPath(
254 file_ref->GetFileSystemURL(), &platform_path);
255 break;
256 case PP_FILESYSTEMTYPE_EXTERNAL:
257 platform_path = file_ref->GetSystemPath();
258 break;
390 default: 259 default:
391 return false; 260 NOTREACHED();
392 } 261 }
262 http_body->appendFileRange(
263 webkit_glue::FilePathToWebString(platform_path),
264 start_offset,
265 number_of_bytes,
266 expected_last_modified_time);
267 return true;
393 } 268 }
394 269
395 bool PPB_URLRequestInfo_Impl::SetIntegerProperty(PP_URLRequestProperty property,
396 int32_t value) {
397 switch (property) {
398 case PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD:
399 prefetch_buffer_upper_threshold_ = value;
400 return true;
401 case PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD:
402 prefetch_buffer_lower_threshold_ = value;
403 return true;
404 default:
405 return false;
406 }
407 }
408
409 bool PPB_URLRequestInfo_Impl::SetStringProperty(PP_URLRequestProperty property,
410 const std::string& value) {
411 // TODO(darin): Validate input. Perhaps at a different layer?
412 switch (property) {
413 case PP_URLREQUESTPROPERTY_URL:
414 url_ = value; // NOTE: This may be a relative URL.
415 return true;
416 case PP_URLREQUESTPROPERTY_METHOD:
417 if (!IsValidToken(value))
418 return false;
419 method_ = ValidateMethod(value);
420 return !method_.empty();
421 case PP_URLREQUESTPROPERTY_HEADERS:
422 if (!AreValidHeaders(value))
423 return false;
424 headers_ = value;
425 return true;
426 case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
427 has_custom_referrer_url_ = true;
428 custom_referrer_url_ = value;
429 return true;
430 case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
431 has_custom_content_transfer_encoding_ = true;
432 custom_content_transfer_encoding_ = value;
433 return true;
434 default:
435 return false;
436 }
437 }
438 270
439 } // namespace ppapi 271 } // namespace ppapi
440 } // namespace webkit 272 } // namespace webkit
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698