1// Copyright (c) 2010 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#include "base/strings/string_util.h"
6#include "content/renderer/npapi/webplugin_impl.h"
7#include "testing/gtest/include/gtest/gtest.h"
8#include "third_party/WebKit/public/platform/WebCString.h"
9#include "third_party/WebKit/public/platform/WebString.h"
10#include "third_party/WebKit/public/platform/WebURLRequest.h"
11
12using blink::WebHTTPBody;
13using blink::WebString;
14using blink::WebURLRequest;
15
16namespace content {
17
18namespace {
19
20std::string GetHeader(const WebURLRequest& request, const char* name) {
21  std::string result;
22  base::TrimWhitespace(
23      request.httpHeaderField(WebString::fromUTF8(name)).utf8(),
24      base::TRIM_ALL,
25      &result);
26  return result;
27}
28
29std::string GetBodyText(const WebURLRequest& request) {
30  const WebHTTPBody& body = request.httpBody();
31  if (body.isNull())
32    return std::string();
33
34  std::string result;
35  size_t i = 0;
36  WebHTTPBody::Element element;
37  while (body.elementAt(i++, element)) {
38    if (element.type == WebHTTPBody::Element::TypeData) {
39      result.append(element.data.data(), element.data.size());
40    } else {
41      NOTREACHED() << "unexpected element type encountered!";
42    }
43  }
44  return result;
45}
46
47}  // namespace
48
49// The Host functions for NPN_PostURL and NPN_PostURLNotify
50// need to parse out some HTTP headers.  Make sure it works
51// with the following tests
52
53TEST(WebPluginImplTest, PostParserSimple) {
54  // Test a simple case with headers & data
55  const char *ex1 = "foo: bar\nContent-length: 10\n\nabcdefghij";
56  WebURLRequest request;
57  request.initialize();
58  bool rv = WebPluginImpl::SetPostData(&request, ex1,
59                                       static_cast<uint32>(strlen(ex1)));
60  EXPECT_TRUE(rv);
61  EXPECT_EQ("bar", GetHeader(request, "foo"));
62  EXPECT_EQ(0U, GetHeader(request, "bar").length());
63  EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
64  EXPECT_EQ("abcdefghij", GetBodyText(request));
65}
66
67TEST(WebPluginImplTest, PostParserLongHeader) {
68  // Test a simple case with long headers
69  const char *ex1 = "foo: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n\nabcdefghij";
70  WebURLRequest request;
71  request.initialize();
72  bool rv = WebPluginImpl::SetPostData(&request, ex1,
73                                       static_cast<uint32>(strlen(ex1)));
74  EXPECT_TRUE(rv);
75  EXPECT_EQ(100U, GetHeader(request, "foo").length());
76}
77
78TEST(WebPluginImplTest, PostParserManyHeaders) {
79  // Test a simple case with long headers
80  const char *ex1 = "h1:h1\nh2:h2\nh3:h3\nh4:h4\nh5:h5\nh6:h6\nh7:h7\nh8:h8\nh9:h9\nh10:h10\n\nbody";
81  WebURLRequest request;
82  request.initialize();
83  bool rv = WebPluginImpl::SetPostData(&request, ex1,
84                                       static_cast<uint32>(strlen(ex1)));
85  EXPECT_TRUE(rv);
86  EXPECT_EQ("h1", GetHeader(request, "h1"));
87  EXPECT_EQ("h2", GetHeader(request, "h2"));
88  EXPECT_EQ("h3", GetHeader(request, "h3"));
89  EXPECT_EQ("h4", GetHeader(request, "h4"));
90  EXPECT_EQ("h5", GetHeader(request, "h5"));
91  EXPECT_EQ("h6", GetHeader(request, "h6"));
92  EXPECT_EQ("h7", GetHeader(request, "h7"));
93  EXPECT_EQ("h8", GetHeader(request, "h8"));
94  EXPECT_EQ("h9", GetHeader(request, "h9"));
95  EXPECT_EQ("h10", GetHeader(request, "h10"));
96  EXPECT_EQ("body", GetBodyText(request));
97}
98
99TEST(WebPluginImplTest, PostParserDuplicateHeaders) {
100  // Test a simple case with long headers
101  // What value gets returned doesn't really matter.  It shouldn't error
102  // out.
103  const char *ex1 = "h1:h1\nh1:h2\n\nbody";
104  WebURLRequest request;
105  request.initialize();
106  bool rv = WebPluginImpl::SetPostData(&request, ex1,
107                                       static_cast<uint32>(strlen(ex1)));
108  EXPECT_TRUE(rv);
109}
110
111TEST(WebPluginImplTest, PostParserNoHeaders) {
112  // Test a simple case with no headers but with data
113  const char *ex1 = "\nabcdefghij";
114  WebURLRequest request;
115  request.initialize();
116  bool rv = WebPluginImpl::SetPostData(&request, ex1,
117                                       static_cast<uint32>(strlen(ex1)));
118  EXPECT_TRUE(rv);
119  EXPECT_EQ(0U, GetHeader(request, "foo").length());
120  EXPECT_EQ(0U, GetHeader(request, "bar").length());
121  EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
122  EXPECT_EQ("abcdefghij", GetBodyText(request));
123}
124
125TEST(WebPluginImplTest, PostParserNoBody) {
126  // Test a simple case with headers and no body
127  const char *ex1 = "Foo:bar\n\n";
128  WebURLRequest request;
129  request.initialize();
130  bool rv = WebPluginImpl::SetPostData(&request, ex1,
131                                       static_cast<uint32>(strlen(ex1)));
132  EXPECT_TRUE(rv);
133  EXPECT_EQ("bar", GetHeader(request, "foo"));
134  EXPECT_EQ(0U, GetHeader(request, "bar").length());
135  EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
136  EXPECT_EQ(0U, GetBodyText(request).length());
137}
138
139TEST(WebPluginImplTest, PostParserBodyWithNewLines) {
140  // Test a simple case with headers and no body
141  const char *ex1 = "Foo:bar\n\n\n\nabcdefg\n\nabcdefg";
142  WebURLRequest request;
143  request.initialize();
144  bool rv = WebPluginImpl::SetPostData(&request, ex1,
145                                       static_cast<uint32>(strlen(ex1)));
146  EXPECT_TRUE(rv);
147  EXPECT_EQ(GetBodyText(request), "\n\nabcdefg\n\nabcdefg");
148}
149
150TEST(WebPluginImplTest, PostParserErrorNoBody) {
151  // Test with headers and no body
152  const char *ex1 = "Foo:bar\n";
153  WebURLRequest request;
154  request.initialize();
155  bool rv = WebPluginImpl::SetPostData(&request, ex1,
156                                       static_cast<uint32>(strlen(ex1)));
157  EXPECT_TRUE(rv);
158}
159
160TEST(WebPluginImplTest, PostParserErrorEmpty) {
161  // Test with an empty string
162  const char *ex1 = "";
163  WebURLRequest request;
164  request.initialize();
165  bool rv = WebPluginImpl::SetPostData(&request, ex1,
166                                       static_cast<uint32>(strlen(ex1)));
167  EXPECT_TRUE(rv);
168}
169
170TEST(WebPluginImplTest, PostParserEmptyName) {
171  // Test an error case with an empty header name field
172  const char *ex1 = "foo:bar\n:blat\n\nbody";
173  WebURLRequest request;
174  request.initialize();
175  bool rv = WebPluginImpl::SetPostData(&request, ex1,
176                                       static_cast<uint32>(strlen(ex1)));
177  EXPECT_TRUE(rv);
178  EXPECT_EQ("bar", GetHeader(request, "foo"));
179  EXPECT_EQ("body", GetBodyText(request));
180}
181
182TEST(WebPluginImplTest, PostParserEmptyValue) {
183  // Test an error case with an empty value field
184  const char *ex1 = "foo:bar\nbar:\n\nbody";
185  WebURLRequest request;
186  request.initialize();
187  bool rv = WebPluginImpl::SetPostData(&request, ex1,
188                                       static_cast<uint32>(strlen(ex1)));
189  EXPECT_TRUE(rv);
190  EXPECT_EQ("bar", GetHeader(request, "foo"));
191  EXPECT_EQ(0U, GetHeader(request, "bar").length());
192  EXPECT_EQ("body", GetBodyText(request));
193}
194
195TEST(WebPluginImplTest, PostParserCRLF) {
196  // Test an error case with an empty value field
197  const char *ex1 = "foo: bar\r\nbar:\r\n\r\nbody\r\n\r\nbody2";
198  WebURLRequest request;
199  request.initialize();
200  bool rv = WebPluginImpl::SetPostData(&request, ex1,
201                                       static_cast<uint32>(strlen(ex1)));
202  EXPECT_TRUE(rv);
203  EXPECT_EQ("bar", GetHeader(request, "foo"));
204  EXPECT_EQ(0U, GetHeader(request, "bar").length());
205  EXPECT_EQ("body\r\n\r\nbody2", GetBodyText(request));
206}
207
208TEST(WebPluginImplTest, PostParserBodyWithBinaryData) {
209  // Test a simple case with headers and binary data.
210  char ex1[33] = "foo: bar\nContent-length: 10\n\n";
211  unsigned int binary_data = 0xFFFFFFF0;
212  memcpy(ex1 + strlen("foo: bar\nContent-length: 10\n\n"), &binary_data,
213        sizeof(binary_data));
214
215  WebURLRequest request;
216  request.initialize();
217  bool rv = WebPluginImpl::SetPostData(&request, ex1,
218                                      sizeof(ex1)/sizeof(ex1[0]));
219  EXPECT_TRUE(rv);
220  EXPECT_EQ("bar", GetHeader(request, "foo"));
221  EXPECT_EQ(0U, GetHeader(request, "bar").length());
222  EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
223
224  std::string body = GetBodyText(request);
225
226  EXPECT_EQ(0xF0, (unsigned char)body[0]);
227  EXPECT_EQ(0xFF, (unsigned char)body[1]);
228  EXPECT_EQ(0xFF, (unsigned char)body[2]);
229  EXPECT_EQ(0xFF, (unsigned char)body[3]);
230}
231
232}  // namespace content
233