OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "config.h" |
| 6 #include "modules/fetch/FetchFormDataConsumerHandle.h" |
| 7 |
| 8 #include "core/dom/DOMTypedArray.h" |
| 9 #include "core/html/DOMFormData.h" |
| 10 #include "core/html/FormDataList.h" |
| 11 #include "core/loader/ThreadableLoader.h" |
| 12 #include "core/loader/ThreadableLoaderClient.h" |
| 13 #include "core/testing/DummyPageHolder.h" |
| 14 #include "modules/fetch/DataConsumerHandleTestUtil.h" |
| 15 #include "platform/network/ResourceResponse.h" |
| 16 #include "platform/testing/UnitTestHelpers.h" |
| 17 #include "platform/weborigin/KURL.h" |
| 18 #include "wtf/PassRefPtr.h" |
| 19 #include "wtf/RefPtr.h" |
| 20 #include "wtf/Vector.h" |
| 21 #include "wtf/text/TextEncoding.h" |
| 22 #include "wtf/text/WTFString.h" |
| 23 |
| 24 #include <gtest/gtest.h> |
| 25 #include <string.h> |
| 26 |
| 27 namespace blink { |
| 28 namespace { |
| 29 |
| 30 using Result = WebDataConsumerHandle::Result; |
| 31 const Result kOk = WebDataConsumerHandle::Ok; |
| 32 const Result kDone = WebDataConsumerHandle::Done; |
| 33 const Result kShouldWait = WebDataConsumerHandle::ShouldWait; |
| 34 const WebDataConsumerHandle::Flags kNone = WebDataConsumerHandle::FlagNone; |
| 35 using HandleReader = DataConsumerHandleTestUtil::HandleReader; |
| 36 using HandleTwoPhaseReader = DataConsumerHandleTestUtil::HandleTwoPhaseReader; |
| 37 using HandleReadResult = DataConsumerHandleTestUtil::HandleReadResult; |
| 38 template <typename T> |
| 39 using HandleReaderRunner = DataConsumerHandleTestUtil::HandleReaderRunner<T>; |
| 40 using ReplayingHandle = DataConsumerHandleTestUtil::ReplayingHandle; |
| 41 using Command = DataConsumerHandleTestUtil::Command; |
| 42 |
| 43 String toString(const Vector<char>& data) |
| 44 { |
| 45 return String(data.data(), data.size()); |
| 46 } |
| 47 |
| 48 class NoopLoader final : public ThreadableLoader { |
| 49 public: |
| 50 static PassRefPtr<ThreadableLoader> create() { return adoptRef(new NoopLoade
r); } |
| 51 void overrideTimeout(unsigned long) override {} |
| 52 void cancel() override {} |
| 53 }; |
| 54 |
| 55 class LoaderFactory : public FetchBlobDataConsumerHandle::LoaderFactory { |
| 56 public: |
| 57 explicit LoaderFactory(PassOwnPtr<WebDataConsumerHandle> handle) : m_handle(
handle) {} |
| 58 PassRefPtr<ThreadableLoader> create(ExecutionContext&, ThreadableLoaderClien
t* client, const ResourceRequest&, const ThreadableLoaderOptions&, const Resourc
eLoaderOptions&) override |
| 59 { |
| 60 RefPtr<ThreadableLoader> loader = NoopLoader::create(); |
| 61 client->didReceiveResponse(0, ResourceResponse(), m_handle.release()); |
| 62 return loader.release(); |
| 63 } |
| 64 |
| 65 private: |
| 66 OwnPtr<WebDataConsumerHandle> m_handle; |
| 67 }; |
| 68 |
| 69 class FetchFormDataConsumerHandleTest : public ::testing::Test { |
| 70 public: |
| 71 FetchFormDataConsumerHandleTest() : m_page(DummyPageHolder::create(IntSize(1
, 1))) {} |
| 72 |
| 73 protected: |
| 74 Document* document() { return &m_page->document(); } |
| 75 |
| 76 OwnPtr<DummyPageHolder> m_page; |
| 77 }; |
| 78 |
| 79 PassRefPtr<FormData> complexFormData() |
| 80 { |
| 81 RefPtr<FormData> data = FormData::create(); |
| 82 |
| 83 data->appendData("foo", 3); |
| 84 data->appendFileRange("/foo/bar/baz", 3, 4, 5); |
| 85 data->appendFileSystemURLRange(KURL(KURL(), "file:///foo/bar/baz"), 6, 7, 8)
; |
| 86 OwnPtr<BlobData> blobData = BlobData::create(); |
| 87 blobData->appendText("hello", false); |
| 88 auto size = blobData->length(); |
| 89 RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(blobData.rele
ase(), size); |
| 90 data->appendBlob(blobDataHandle->uuid(), blobDataHandle); |
| 91 Vector<char> boundary; |
| 92 boundary.append("\0", 1); |
| 93 data->setBoundary(boundary); |
| 94 return data.release(); |
| 95 } |
| 96 |
| 97 void verifyComplexFormData(FormData* data) |
| 98 { |
| 99 const auto& elements = data->elements(); |
| 100 if (4 != elements.size()) { |
| 101 FAIL() << "data->elements().size() should be 4, but is " << data->elemen
ts().size() << "."; |
| 102 } |
| 103 EXPECT_EQ(FormDataElement::data, elements[0].m_type); |
| 104 EXPECT_EQ("foo", String(elements[0].m_data.data(), elements[0].m_data.size()
)); |
| 105 |
| 106 EXPECT_EQ(FormDataElement::encodedFile, elements[1].m_type); |
| 107 EXPECT_EQ("/foo/bar/baz", elements[1].m_filename); |
| 108 EXPECT_EQ(3, elements[1].m_fileStart); |
| 109 EXPECT_EQ(4, elements[1].m_fileLength); |
| 110 EXPECT_EQ(5, elements[1].m_expectedFileModificationTime); |
| 111 |
| 112 EXPECT_EQ(FormDataElement::encodedFileSystemURL, elements[2].m_type); |
| 113 EXPECT_EQ(KURL(KURL(), "file:///foo/bar/baz"), elements[2].m_fileSystemURL); |
| 114 EXPECT_EQ(6, elements[2].m_fileStart); |
| 115 EXPECT_EQ(7, elements[2].m_fileLength); |
| 116 EXPECT_EQ(8, elements[2].m_expectedFileModificationTime); |
| 117 |
| 118 EXPECT_EQ(FormDataElement::encodedBlob, elements[3].m_type); |
| 119 if (!elements[3].m_optionalBlobDataHandle) { |
| 120 FAIL() << "optional BlobDataHandle must be set."; |
| 121 } |
| 122 EXPECT_EQ(elements[3].m_blobUUID, elements[3].m_optionalBlobDataHandle->uuid
()); |
| 123 EXPECT_EQ(5u, elements[3].m_optionalBlobDataHandle->size()); |
| 124 } |
| 125 |
| 126 TEST_F(FetchFormDataConsumerHandleTest, ReadFromString) |
| 127 { |
| 128 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(String("hello, world")); |
| 129 HandleReaderRunner<HandleReader> runner(handle.release()); |
| 130 OwnPtr<HandleReadResult> r = runner.wait(); |
| 131 EXPECT_EQ(kDone, r->result()); |
| 132 EXPECT_EQ("hello, world", toString(r->data())); |
| 133 } |
| 134 |
| 135 TEST_F(FetchFormDataConsumerHandleTest, TwoPhaseReadFromString) |
| 136 { |
| 137 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(String("hello, world")); |
| 138 HandleReaderRunner<HandleTwoPhaseReader> runner(handle.release()); |
| 139 OwnPtr<HandleReadResult> r = runner.wait(); |
| 140 EXPECT_EQ(kDone, r->result()); |
| 141 EXPECT_EQ("hello, world", toString(r->data())); |
| 142 } |
| 143 |
| 144 TEST_F(FetchFormDataConsumerHandleTest, ReadFromStringNonLatin) |
| 145 { |
| 146 UChar cs[] = {0x3042, 0}; |
| 147 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(String(cs)); |
| 148 HandleReaderRunner<HandleReader> runner(handle.release()); |
| 149 OwnPtr<HandleReadResult> r = runner.wait(); |
| 150 EXPECT_EQ(kDone, r->result()); |
| 151 EXPECT_EQ("\xe3\x81\x82", toString(r->data())); |
| 152 } |
| 153 |
| 154 TEST_F(FetchFormDataConsumerHandleTest, ReadFromArrayBuffer) |
| 155 { |
| 156 const unsigned char data[] = { 0x21, 0xfe, 0x00, 0x00, 0xff, 0xa3, 0x42, 0x3
0, 0x42, 0x99, 0x88 }; |
| 157 RefPtr<DOMArrayBuffer> buffer = DOMArrayBuffer::create(data, WTF_ARRAY_LENGT
H(data)); |
| 158 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(buffer); |
| 159 HandleReaderRunner<HandleReader> runner(handle.release()); |
| 160 OwnPtr<HandleReadResult> r = runner.wait(); |
| 161 EXPECT_EQ(kDone, r->result()); |
| 162 Vector<char> expected; |
| 163 expected.append(data, WTF_ARRAY_LENGTH(data)); |
| 164 EXPECT_EQ(expected, r->data()); |
| 165 } |
| 166 |
| 167 TEST_F(FetchFormDataConsumerHandleTest, ReadFromArrayBufferView) |
| 168 { |
| 169 const unsigned char data[] = { 0x21, 0xfe, 0x00, 0x00, 0xff, 0xa3, 0x42, 0x3
0, 0x42, 0x99, 0x88 }; |
| 170 const size_t offset = 1, size = 4; |
| 171 RefPtr<DOMArrayBuffer> buffer = DOMArrayBuffer::create(data, WTF_ARRAY_LENGT
H(data)); |
| 172 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(DOMUint8Array::create(buffer, offset, size)); |
| 173 HandleReaderRunner<HandleReader> runner(handle.release()); |
| 174 OwnPtr<HandleReadResult> r = runner.wait(); |
| 175 EXPECT_EQ(kDone, r->result()); |
| 176 Vector<char> expected; |
| 177 expected.append(data + offset, size); |
| 178 EXPECT_EQ(expected, r->data()); |
| 179 } |
| 180 |
| 181 TEST_F(FetchFormDataConsumerHandleTest, ReadFromSimplFormData) |
| 182 { |
| 183 RefPtr<FormData> data = FormData::create(); |
| 184 data->appendData("foo", 3); |
| 185 data->appendData("hoge", 4); |
| 186 |
| 187 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(document(), data); |
| 188 HandleReaderRunner<HandleReader> runner(handle.release()); |
| 189 testing::runPendingTasks(); |
| 190 OwnPtr<HandleReadResult> r = runner.wait(); |
| 191 EXPECT_EQ(kDone, r->result()); |
| 192 EXPECT_EQ("foohoge", toString(r->data())); |
| 193 } |
| 194 |
| 195 TEST_F(FetchFormDataConsumerHandleTest, ReadFromComplexFormData) |
| 196 { |
| 197 RefPtr<FormData> data = complexFormData(); |
| 198 OwnPtr<ReplayingHandle> src = ReplayingHandle::create(); |
| 199 src->add(Command(Command::Data, "bar")); |
| 200 src->add(Command(Command::Done)); |
| 201 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
ForTest(document(), data, new LoaderFactory(src.release())); |
| 202 char c; |
| 203 size_t readSize; |
| 204 EXPECT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(&c, 1, kNone, &re
adSize)); |
| 205 |
| 206 HandleReaderRunner<HandleReader> runner(handle.release()); |
| 207 testing::runPendingTasks(); |
| 208 OwnPtr<HandleReadResult> r = runner.wait(); |
| 209 EXPECT_EQ(kDone, r->result()); |
| 210 EXPECT_EQ("bar", toString(r->data())); |
| 211 } |
| 212 |
| 213 TEST_F(FetchFormDataConsumerHandleTest, TwoPhaseReadFromComplexFormData) |
| 214 { |
| 215 RefPtr<FormData> data = complexFormData(); |
| 216 OwnPtr<ReplayingHandle> src = ReplayingHandle::create(); |
| 217 src->add(Command(Command::Data, "bar")); |
| 218 src->add(Command(Command::Done)); |
| 219 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
ForTest(document(), data, new LoaderFactory(src.release())); |
| 220 char c; |
| 221 size_t readSize; |
| 222 EXPECT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(&c, 1, kNone, &re
adSize)); |
| 223 |
| 224 HandleReaderRunner<HandleTwoPhaseReader> runner(handle.release()); |
| 225 testing::runPendingTasks(); |
| 226 OwnPtr<HandleReadResult> r = runner.wait(); |
| 227 EXPECT_EQ(kDone, r->result()); |
| 228 EXPECT_EQ("bar", toString(r->data())); |
| 229 } |
| 230 |
| 231 TEST_F(FetchFormDataConsumerHandleTest, DrainAsBlobDataHandle) |
| 232 { |
| 233 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(String("hello, world")); |
| 234 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 235 EXPECT_FALSE(reader->drainAsBlobDataHandle(FetchDataConsumerHandle::Reader::
AllowBlobWithInvalidSize)); |
| 236 } |
| 237 |
| 238 TEST_F(FetchFormDataConsumerHandleTest, DrainAsFormDataFromString) |
| 239 { |
| 240 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(String("hello, world")); |
| 241 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 242 RefPtr<FormData> formData = reader->drainAsFormData(); |
| 243 ASSERT_TRUE(formData); |
| 244 EXPECT_TRUE(formData->isSafeToSendToAnotherThread()); |
| 245 EXPECT_EQ("hello, world", formData->flattenToString()); |
| 246 |
| 247 const void* buffer = nullptr; |
| 248 size_t size; |
| 249 EXPECT_EQ(kDone, reader->read(nullptr, 0, kNone, &size)); |
| 250 EXPECT_EQ(kDone, reader->beginRead(&buffer, kNone, &size)); |
| 251 } |
| 252 |
| 253 TEST_F(FetchFormDataConsumerHandleTest, DrainAsFormDataFromArrayBuffer) |
| 254 { |
| 255 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(DOMArrayBuffer::create("foo", 3)); |
| 256 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 257 RefPtr<FormData> formData = reader->drainAsFormData(); |
| 258 ASSERT_TRUE(formData); |
| 259 EXPECT_TRUE(formData->isSafeToSendToAnotherThread()); |
| 260 EXPECT_EQ("foo", formData->flattenToString()); |
| 261 } |
| 262 |
| 263 TEST_F(FetchFormDataConsumerHandleTest, DrainAsFormDataFromSimpleFormData) |
| 264 { |
| 265 DOMFormData* data = DOMFormData::create(UTF8Encoding()); |
| 266 data->append("name1", "value1"); |
| 267 data->append("name2", "value2"); |
| 268 RefPtr<FormData> inputFormData = data->createMultiPartFormData(); |
| 269 |
| 270 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(document(), inputFormData); |
| 271 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 272 RefPtr<FormData> outputFormData = reader->drainAsFormData(); |
| 273 ASSERT_TRUE(outputFormData); |
| 274 EXPECT_TRUE(outputFormData->isSafeToSendToAnotherThread()); |
| 275 EXPECT_NE(outputFormData.get(), inputFormData.get()); |
| 276 EXPECT_EQ(inputFormData->flattenToString(), outputFormData->flattenToString(
)); |
| 277 } |
| 278 |
| 279 TEST_F(FetchFormDataConsumerHandleTest, DrainAsFormDataFromComplexFormData) |
| 280 { |
| 281 RefPtr<FormData> inputFormData = complexFormData(); |
| 282 |
| 283 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(document(), inputFormData); |
| 284 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 285 RefPtr<FormData> outputFormData = reader->drainAsFormData(); |
| 286 ASSERT_TRUE(outputFormData); |
| 287 EXPECT_TRUE(outputFormData->isSafeToSendToAnotherThread()); |
| 288 EXPECT_NE(outputFormData.get(), inputFormData.get()); |
| 289 verifyComplexFormData(outputFormData.get()); |
| 290 } |
| 291 |
| 292 TEST_F(FetchFormDataConsumerHandleTest, ZeroByteReadDoesNotAffectDraining) |
| 293 { |
| 294 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(String("hello, world")); |
| 295 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 296 size_t readSize; |
| 297 EXPECT_EQ(kOk, reader->read(nullptr, 0, kNone, &readSize)); |
| 298 RefPtr<FormData> formData = reader->drainAsFormData(); |
| 299 ASSERT_TRUE(formData); |
| 300 EXPECT_TRUE(formData->isSafeToSendToAnotherThread()); |
| 301 EXPECT_EQ("hello, world", formData->flattenToString()); |
| 302 } |
| 303 |
| 304 TEST_F(FetchFormDataConsumerHandleTest, OneByteReadAffectsDraining) |
| 305 { |
| 306 char c; |
| 307 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(String("hello, world")); |
| 308 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 309 size_t readSize; |
| 310 EXPECT_EQ(kOk, reader->read(&c, 1, kNone, &readSize)); |
| 311 EXPECT_EQ(1u, readSize); |
| 312 EXPECT_EQ('h', c); |
| 313 EXPECT_FALSE(reader->drainAsFormData()); |
| 314 } |
| 315 |
| 316 TEST_F(FetchFormDataConsumerHandleTest, BeginReadAffectsDraining) |
| 317 { |
| 318 const void* buffer = nullptr; |
| 319 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
(String("hello, world")); |
| 320 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 321 size_t available; |
| 322 EXPECT_EQ(kOk, reader->beginRead(&buffer, kNone, &available)); |
| 323 ASSERT_TRUE(buffer); |
| 324 EXPECT_EQ("hello, world", String(static_cast<const char*>(buffer), available
)); |
| 325 EXPECT_FALSE(reader->drainAsFormData()); |
| 326 reader->endRead(0); |
| 327 EXPECT_FALSE(reader->drainAsFormData()); |
| 328 } |
| 329 |
| 330 TEST_F(FetchFormDataConsumerHandleTest, ZeroByteReadDoesNotAffectDrainingForComp
lexFormData) |
| 331 { |
| 332 OwnPtr<ReplayingHandle> src = ReplayingHandle::create(); |
| 333 src->add(Command(Command::Data, "bar")); |
| 334 src->add(Command(Command::Done)); |
| 335 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
ForTest(document(), complexFormData(), new LoaderFactory(src.release())); |
| 336 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 337 size_t readSize; |
| 338 EXPECT_EQ(kShouldWait, reader->read(nullptr, 0, kNone, &readSize)); |
| 339 testing::runPendingTasks(); |
| 340 EXPECT_EQ(kOk, reader->read(nullptr, 0, kNone, &readSize)); |
| 341 RefPtr<FormData> formData = reader->drainAsFormData(); |
| 342 ASSERT_TRUE(formData); |
| 343 EXPECT_TRUE(formData->isSafeToSendToAnotherThread()); |
| 344 verifyComplexFormData(formData.get()); |
| 345 } |
| 346 |
| 347 TEST_F(FetchFormDataConsumerHandleTest, OneByteReadAffectsDrainingForComplexForm
Data) |
| 348 { |
| 349 OwnPtr<ReplayingHandle> src = ReplayingHandle::create(); |
| 350 src->add(Command(Command::Data, "bar")); |
| 351 src->add(Command(Command::Done)); |
| 352 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
ForTest(document(), complexFormData(), new LoaderFactory(src.release())); |
| 353 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 354 char c; |
| 355 size_t readSize; |
| 356 EXPECT_EQ(kShouldWait, reader->read(&c, 1, kNone, &readSize)); |
| 357 testing::runPendingTasks(); |
| 358 EXPECT_EQ(kOk, reader->read(&c, 1, kNone, &readSize)); |
| 359 EXPECT_EQ(1u, readSize); |
| 360 EXPECT_EQ('b', c); |
| 361 EXPECT_FALSE(reader->drainAsFormData()); |
| 362 } |
| 363 |
| 364 TEST_F(FetchFormDataConsumerHandleTest, BeginReadAffectsDrainingForComplexFormDa
ta) |
| 365 { |
| 366 OwnPtr<ReplayingHandle> src = ReplayingHandle::create(); |
| 367 src->add(Command(Command::Data, "bar")); |
| 368 src->add(Command(Command::Done)); |
| 369 const void* buffer = nullptr; |
| 370 OwnPtr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create
ForTest(document(), complexFormData(), new LoaderFactory(src.release())); |
| 371 OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(nullpt
r); |
| 372 size_t available; |
| 373 EXPECT_EQ(kShouldWait, reader->beginRead(&buffer, kNone, &available)); |
| 374 testing::runPendingTasks(); |
| 375 EXPECT_EQ(kOk, reader->beginRead(&buffer, kNone, &available)); |
| 376 EXPECT_FALSE(reader->drainAsFormData()); |
| 377 reader->endRead(0); |
| 378 EXPECT_FALSE(reader->drainAsFormData()); |
| 379 } |
| 380 |
| 381 } // namespace |
| 382 } // namespace blink |
OLD | NEW |