1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "SerializedScriptValue.h"
33
34 #include "Blob.h"
35 #include "ByteArray.h"
36 #include "CanvasPixelArray.h"
37 #include "ExceptionCode.h"
38 #include "File.h"
39 #include "FileList.h"
40 #include "ImageData.h"
41 #include "SharedBuffer.h"
42 #include "V8Binding.h"
43 #include "V8Blob.h"
44 #include "V8File.h"
45 #include "V8FileList.h"
46 #include "V8ImageData.h"
47 #include "V8Proxy.h"
48 #include "V8Utilities.h"
49
50 #include <wtf/Assertions.h>
51 #include <wtf/RefCounted.h>
52 #include <wtf/Vector.h>
53
54 // FIXME: consider crashing in debug mode on deserialization errors
55
56 namespace WebCore {
57
58 namespace {
59
60 typedef UChar BufferValueType;
61
62 // Serialization format is a sequence of (tag, optional data)
63 // pairs. Tag always takes exactly one byte.
64 enum SerializationTag {
65 InvalidTag = '!',
66 PaddingTag = '\0',
67 UndefinedTag = '_',
68 NullTag = '0',
69 TrueTag = 'T',
70 FalseTag = 'F',
71 StringTag = 'S',
72 Int32Tag = 'I',
73 Uint32Tag = 'U',
74 DateTag = 'D',
75 NumberTag = 'N',
76 BlobTag = 'b',
77 FileTag = 'f',
78 FileListTag = 'l',
79 ImageDataTag = '#',
80 ArrayTag = '[',
81 ObjectTag = '{',
82 SparseArrayTag = '@',
83 RegExpTag = 'R',
84 };
85
shouldCheckForCycles(int depth)86 static bool shouldCheckForCycles(int depth)
87 {
88 ASSERT(depth >= 0);
89 // Since we are not required to spot the cycle as soon as it
90 // happens we can check for cycles only when the current depth
91 // is a power of two.
92 return !(depth & (depth - 1));
93 }
94
95 static const int maxDepth = 20000;
96
97 // VarInt encoding constants.
98 static const int varIntShift = 7;
99 static const int varIntMask = (1 << varIntShift) - 1;
100
101 // ZigZag encoding helps VarInt encoding stay small for negative
102 // numbers with small absolute values.
103 class ZigZag {
104 public:
encode(uint32_t value)105 static uint32_t encode(uint32_t value)
106 {
107 if (value & (1U << 31))
108 value = ((~value) << 1) + 1;
109 else
110 value <<= 1;
111 return value;
112 }
113
decode(uint32_t value)114 static uint32_t decode(uint32_t value)
115 {
116 if (value & 1)
117 value = ~(value >> 1);
118 else
119 value >>= 1;
120 return value;
121 }
122
123 private:
124 ZigZag();
125 };
126
127 // Writer is responsible for serializing primitive types and storing
128 // information used to reconstruct composite types.
129 class Writer {
130 WTF_MAKE_NONCOPYABLE(Writer);
131 public:
Writer()132 Writer()
133 : m_position(0)
134 {
135 }
136
137 // Write functions for primitive types.
138
writeUndefined()139 void writeUndefined() { append(UndefinedTag); }
140
writeNull()141 void writeNull() { append(NullTag); }
142
writeTrue()143 void writeTrue() { append(TrueTag); }
144
writeFalse()145 void writeFalse() { append(FalseTag); }
146
writeString(const char * data,int length)147 void writeString(const char* data, int length)
148 {
149 ASSERT(length >= 0);
150 append(StringTag);
151 doWriteString(data, length);
152 }
153
writeWebCoreString(const String & string)154 void writeWebCoreString(const String& string)
155 {
156 // Uses UTF8 encoding so we can read it back as either V8 or
157 // WebCore string.
158 append(StringTag);
159 doWriteWebCoreString(string);
160 }
161
writeInt32(int32_t value)162 void writeInt32(int32_t value)
163 {
164 append(Int32Tag);
165 doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
166 }
167
writeUint32(uint32_t value)168 void writeUint32(uint32_t value)
169 {
170 append(Uint32Tag);
171 doWriteUint32(value);
172 }
173
writeDate(double numberValue)174 void writeDate(double numberValue)
175 {
176 append(DateTag);
177 doWriteNumber(numberValue);
178 }
179
writeNumber(double number)180 void writeNumber(double number)
181 {
182 append(NumberTag);
183 doWriteNumber(number);
184 }
185
writeBlob(const String & url,const String & type,unsigned long long size)186 void writeBlob(const String& url, const String& type, unsigned long long size)
187 {
188 append(BlobTag);
189 doWriteWebCoreString(url);
190 doWriteWebCoreString(type);
191 doWriteUint64(size);
192 }
193
writeFile(const String & path,const String & url,const String & type)194 void writeFile(const String& path, const String& url, const String& type)
195 {
196 append(FileTag);
197 doWriteWebCoreString(path);
198 doWriteWebCoreString(url);
199 doWriteWebCoreString(type);
200 }
201
writeFileList(const FileList & fileList)202 void writeFileList(const FileList& fileList)
203 {
204 append(FileListTag);
205 uint32_t length = fileList.length();
206 doWriteUint32(length);
207 for (unsigned i = 0; i < length; ++i) {
208 doWriteWebCoreString(fileList.item(i)->path());
209 doWriteWebCoreString(fileList.item(i)->url().string());
210 doWriteWebCoreString(fileList.item(i)->type());
211 }
212 }
213
writeImageData(uint32_t width,uint32_t height,const uint8_t * pixelData,uint32_t pixelDataLength)214 void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
215 {
216 append(ImageDataTag);
217 doWriteUint32(width);
218 doWriteUint32(height);
219 doWriteUint32(pixelDataLength);
220 append(pixelData, pixelDataLength);
221 }
222
writeRegExp(v8::Local<v8::String> pattern,v8::RegExp::Flags flags)223 void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
224 {
225 append(RegExpTag);
226 v8::String::Utf8Value patternUtf8Value(pattern);
227 doWriteString(*patternUtf8Value, patternUtf8Value.length());
228 doWriteUint32(static_cast<uint32_t>(flags));
229 }
230
writeArray(uint32_t length)231 void writeArray(uint32_t length)
232 {
233 append(ArrayTag);
234 doWriteUint32(length);
235 }
236
writeObject(uint32_t numProperties)237 void writeObject(uint32_t numProperties)
238 {
239 append(ObjectTag);
240 doWriteUint32(numProperties);
241 }
242
writeSparseArray(uint32_t numProperties,uint32_t length)243 void writeSparseArray(uint32_t numProperties, uint32_t length)
244 {
245 append(SparseArrayTag);
246 doWriteUint32(numProperties);
247 doWriteUint32(length);
248 }
249
data()250 Vector<BufferValueType>& data()
251 {
252 fillHole();
253 return m_buffer;
254 }
255
256 private:
doWriteString(const char * data,int length)257 void doWriteString(const char* data, int length)
258 {
259 doWriteUint32(static_cast<uint32_t>(length));
260 append(reinterpret_cast<const uint8_t*>(data), length);
261 }
262
doWriteWebCoreString(const String & string)263 void doWriteWebCoreString(const String& string)
264 {
265 RefPtr<SharedBuffer> buffer = utf8Buffer(string);
266 doWriteString(buffer->data(), buffer->size());
267 }
268
269 template<class T>
doWriteUintHelper(T value)270 void doWriteUintHelper(T value)
271 {
272 while (true) {
273 uint8_t b = (value & varIntMask);
274 value >>= varIntShift;
275 if (!value) {
276 append(b);
277 break;
278 }
279 append(b | (1 << varIntShift));
280 }
281 }
282
doWriteUint32(uint32_t value)283 void doWriteUint32(uint32_t value)
284 {
285 doWriteUintHelper(value);
286 }
287
doWriteUint64(uint64_t value)288 void doWriteUint64(uint64_t value)
289 {
290 doWriteUintHelper(value);
291 }
292
doWriteNumber(double number)293 void doWriteNumber(double number)
294 {
295 append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
296 }
297
append(SerializationTag tag)298 void append(SerializationTag tag)
299 {
300 append(static_cast<uint8_t>(tag));
301 }
302
append(uint8_t b)303 void append(uint8_t b)
304 {
305 ensureSpace(1);
306 *byteAt(m_position++) = b;
307 }
308
append(const uint8_t * data,int length)309 void append(const uint8_t* data, int length)
310 {
311 ensureSpace(length);
312 memcpy(byteAt(m_position), data, length);
313 m_position += length;
314 }
315
ensureSpace(int extra)316 void ensureSpace(int extra)
317 {
318 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
319 m_buffer.grow((m_position + extra + 1) / 2); // "+ 1" to round up.
320 }
321
fillHole()322 void fillHole()
323 {
324 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
325 // If the writer is at odd position in the buffer, then one of
326 // the bytes in the last UChar is not initialized.
327 if (m_position % 2)
328 *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
329 }
330
byteAt(int position)331 uint8_t* byteAt(int position) { return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; }
332
333 Vector<BufferValueType> m_buffer;
334 unsigned m_position;
335 };
336
337 class Serializer {
338 class StateBase;
339 public:
340 enum Status {
341 Success,
342 InputError,
343 JSException,
344 JSFailure
345 };
346
Serializer(Writer & writer,v8::TryCatch & tryCatch)347 Serializer(Writer& writer, v8::TryCatch& tryCatch)
348 : m_writer(writer)
349 , m_tryCatch(tryCatch)
350 , m_depth(0)
351 , m_status(Success)
352 {
353 ASSERT(!tryCatch.HasCaught());
354 }
355
serialize(v8::Handle<v8::Value> value)356 Status serialize(v8::Handle<v8::Value> value)
357 {
358 v8::HandleScope scope;
359 StateBase* state = doSerialize(value, 0);
360 while (state)
361 state = state->advance(*this);
362 return m_status;
363 }
364
365 // Functions used by serialization states.
366
367 StateBase* doSerialize(v8::Handle<v8::Value> value, StateBase* next);
368
checkException(StateBase * state)369 StateBase* checkException(StateBase* state)
370 {
371 return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0;
372 }
373
reportFailure(StateBase * state)374 StateBase* reportFailure(StateBase* state)
375 {
376 return handleError(JSFailure, state);
377 }
378
writeArray(uint32_t length,StateBase * state)379 StateBase* writeArray(uint32_t length, StateBase* state)
380 {
381 m_writer.writeArray(length);
382 return pop(state);
383 }
384
writeObject(uint32_t numProperties,StateBase * state)385 StateBase* writeObject(uint32_t numProperties, StateBase* state)
386 {
387 m_writer.writeObject(numProperties);
388 return pop(state);
389 }
390
writeSparseArray(uint32_t numProperties,uint32_t length,StateBase * state)391 StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
392 {
393 m_writer.writeSparseArray(numProperties, length);
394 return pop(state);
395 }
396
397 private:
398 class StateBase {
399 WTF_MAKE_NONCOPYABLE(StateBase);
400 public:
~StateBase()401 virtual ~StateBase() { }
402
403 // Link to the next state to form a stack.
nextState()404 StateBase* nextState() { return m_next; }
405
406 // Composite object we're processing in this state.
composite()407 v8::Handle<v8::Value> composite() { return m_composite; }
408
409 // Serializes (a part of) the current composite and returns
410 // the next state to process or null when this is the final
411 // state.
412 virtual StateBase* advance(Serializer&) = 0;
413
414 protected:
StateBase(v8::Handle<v8::Value> composite,StateBase * next)415 StateBase(v8::Handle<v8::Value> composite, StateBase* next)
416 : m_composite(composite)
417 , m_next(next)
418 {
419 }
420
421 private:
422 v8::Handle<v8::Value> m_composite;
423 StateBase* m_next;
424 };
425
426 // Dummy state that is used to signal serialization errors.
427 class ErrorState : public StateBase {
428 public:
ErrorState()429 ErrorState()
430 : StateBase(v8::Handle<v8::Value>(), 0)
431 {
432 }
433
advance(Serializer &)434 virtual StateBase* advance(Serializer&)
435 {
436 delete this;
437 return 0;
438 }
439 };
440
441 template <typename T>
442 class State : public StateBase {
443 public:
composite()444 v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
445
446 protected:
State(v8::Handle<T> composite,StateBase * next)447 State(v8::Handle<T> composite, StateBase* next)
448 : StateBase(composite, next)
449 {
450 }
451 };
452
453 #if 0
454 // Currently unused, see comment in newArrayState.
455 class ArrayState : public State<v8::Array> {
456 public:
457 ArrayState(v8::Handle<v8::Array> array, StateBase* next)
458 : State<v8::Array>(array, next)
459 , m_index(-1)
460 {
461 }
462
463 virtual StateBase* advance(Serializer& serializer)
464 {
465 ++m_index;
466 for (; m_index < composite()->Length(); ++m_index) {
467 v8::Handle<v8::Value> value = composite()->Get(m_index);
468 if (StateBase* newState = serializer.checkException(this))
469 return newState;
470 if (StateBase* newState = serializer.doSerialize(value, this))
471 return newState;
472 }
473 return serializer.writeArray(composite()->Length(), this);
474 }
475
476 private:
477 unsigned m_index;
478 };
479 #endif
480
481 class AbstractObjectState : public State<v8::Object> {
482 public:
AbstractObjectState(v8::Handle<v8::Object> object,StateBase * next)483 AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
484 : State<v8::Object>(object, next)
485 , m_index(0)
486 , m_numSerializedProperties(0)
487 , m_nameDone(false)
488 {
489 }
490
advance(Serializer & serializer)491 virtual StateBase* advance(Serializer& serializer)
492 {
493 if (!m_index) {
494 m_propertyNames = composite()->GetPropertyNames();
495 if (StateBase* newState = serializer.checkException(this))
496 return newState;
497 if (m_propertyNames.IsEmpty())
498 return serializer.reportFailure(this);
499 }
500 while (m_index < m_propertyNames->Length()) {
501 if (!m_nameDone) {
502 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
503 if (StateBase* newState = serializer.checkException(this))
504 return newState;
505 if (propertyName.IsEmpty())
506 return serializer.reportFailure(this);
507 bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>());
508 if (StateBase* newState = serializer.checkException(this))
509 return newState;
510 bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value());
511 if (StateBase* newState = serializer.checkException(this))
512 return newState;
513 if (hasStringProperty || hasIndexedProperty)
514 m_propertyName = propertyName;
515 else {
516 ++m_index;
517 continue;
518 }
519 }
520 ASSERT(!m_propertyName.IsEmpty());
521 if (!m_nameDone) {
522 m_nameDone = true;
523 if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
524 return newState;
525 }
526 v8::Local<v8::Value> value = composite()->Get(m_propertyName);
527 if (StateBase* newState = serializer.checkException(this))
528 return newState;
529 m_nameDone = false;
530 m_propertyName.Clear();
531 ++m_index;
532 ++m_numSerializedProperties;
533 if (StateBase* newState = serializer.doSerialize(value, this))
534 return newState;
535 }
536 return objectDone(m_numSerializedProperties, serializer);
537 }
538
539 protected:
540 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
541
542 private:
543 v8::Local<v8::Array> m_propertyNames;
544 v8::Local<v8::Value> m_propertyName;
545 unsigned m_index;
546 unsigned m_numSerializedProperties;
547 bool m_nameDone;
548 };
549
550 class ObjectState : public AbstractObjectState {
551 public:
ObjectState(v8::Handle<v8::Object> object,StateBase * next)552 ObjectState(v8::Handle<v8::Object> object, StateBase* next)
553 : AbstractObjectState(object, next)
554 {
555 }
556
557 protected:
objectDone(unsigned numProperties,Serializer & serializer)558 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
559 {
560 return serializer.writeObject(numProperties, this);
561 }
562 };
563
564 class SparseArrayState : public AbstractObjectState {
565 public:
SparseArrayState(v8::Handle<v8::Array> array,StateBase * next)566 SparseArrayState(v8::Handle<v8::Array> array, StateBase* next)
567 : AbstractObjectState(array, next)
568 {
569 }
570
571 protected:
objectDone(unsigned numProperties,Serializer & serializer)572 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
573 {
574 return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
575 }
576 };
577
push(StateBase * state)578 StateBase* push(StateBase* state)
579 {
580 ASSERT(state);
581 ++m_depth;
582 return checkComposite(state) ? state : handleError(InputError, state);
583 }
584
pop(StateBase * state)585 StateBase* pop(StateBase* state)
586 {
587 ASSERT(state);
588 --m_depth;
589 StateBase* next = state->nextState();
590 delete state;
591 return next;
592 }
593
handleError(Status errorStatus,StateBase * state)594 StateBase* handleError(Status errorStatus, StateBase* state)
595 {
596 ASSERT(errorStatus != Success);
597 m_status = errorStatus;
598 while (state) {
599 StateBase* tmp = state->nextState();
600 delete state;
601 state = tmp;
602 }
603 return new ErrorState;
604 }
605
checkComposite(StateBase * top)606 bool checkComposite(StateBase* top)
607 {
608 ASSERT(top);
609 if (m_depth > maxDepth)
610 return false;
611 if (!shouldCheckForCycles(m_depth))
612 return true;
613 v8::Handle<v8::Value> composite = top->composite();
614 for (StateBase* state = top->nextState(); state; state = state->nextState()) {
615 if (state->composite() == composite)
616 return false;
617 }
618 return true;
619 }
620
writeString(v8::Handle<v8::Value> value)621 void writeString(v8::Handle<v8::Value> value)
622 {
623 v8::String::Utf8Value stringValue(value);
624 m_writer.writeString(*stringValue, stringValue.length());
625 }
626
writeBlob(v8::Handle<v8::Value> value)627 void writeBlob(v8::Handle<v8::Value> value)
628 {
629 Blob* blob = V8Blob::toNative(value.As<v8::Object>());
630 if (!blob)
631 return;
632 m_writer.writeBlob(blob->url().string(), blob->type(), blob->size());
633 }
634
writeFile(v8::Handle<v8::Value> value)635 void writeFile(v8::Handle<v8::Value> value)
636 {
637 File* file = V8File::toNative(value.As<v8::Object>());
638 if (!file)
639 return;
640 m_writer.writeFile(file->path(), file->url().string(), file->type());
641 }
642
writeFileList(v8::Handle<v8::Value> value)643 void writeFileList(v8::Handle<v8::Value> value)
644 {
645 FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
646 if (!fileList)
647 return;
648 m_writer.writeFileList(*fileList);
649 }
650
writeImageData(v8::Handle<v8::Value> value)651 void writeImageData(v8::Handle<v8::Value> value)
652 {
653 ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
654 if (!imageData)
655 return;
656 WTF::ByteArray* pixelArray = imageData->data()->data();
657 m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
658 }
659
writeRegExp(v8::Handle<v8::Value> value)660 void writeRegExp(v8::Handle<v8::Value> value)
661 {
662 v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
663 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
664 }
665
newArrayState(v8::Handle<v8::Array> array,StateBase * next)666 static StateBase* newArrayState(v8::Handle<v8::Array> array, StateBase* next)
667 {
668 // FIXME: use plain Array state when we can quickly check that
669 // an array is not sparse and has only indexed properties.
670 return new SparseArrayState(array, next);
671 }
672
newObjectState(v8::Handle<v8::Object> object,StateBase * next)673 static StateBase* newObjectState(v8::Handle<v8::Object> object, StateBase* next)
674 {
675 // FIXME: check not a wrapper
676 return new ObjectState(object, next);
677 }
678
679 Writer& m_writer;
680 v8::TryCatch& m_tryCatch;
681 int m_depth;
682 Status m_status;
683 };
684
doSerialize(v8::Handle<v8::Value> value,StateBase * next)685 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
686 {
687 if (value.IsEmpty())
688 return reportFailure(next);
689 if (value->IsUndefined())
690 m_writer.writeUndefined();
691 else if (value->IsNull())
692 m_writer.writeNull();
693 else if (value->IsTrue())
694 m_writer.writeTrue();
695 else if (value->IsFalse())
696 m_writer.writeFalse();
697 else if (value->IsInt32())
698 m_writer.writeInt32(value->Int32Value());
699 else if (value->IsUint32())
700 m_writer.writeUint32(value->Uint32Value());
701 else if (value->IsDate())
702 m_writer.writeDate(value->NumberValue());
703 else if (value->IsNumber())
704 m_writer.writeNumber(value.As<v8::Number>()->Value());
705 else if (value->IsString())
706 writeString(value);
707 else if (value->IsArray())
708 return push(newArrayState(value.As<v8::Array>(), next));
709 else if (V8File::HasInstance(value))
710 writeFile(value);
711 else if (V8Blob::HasInstance(value))
712 writeBlob(value);
713 else if (V8FileList::HasInstance(value))
714 writeFileList(value);
715 else if (V8ImageData::HasInstance(value))
716 writeImageData(value);
717 else if (value->IsRegExp())
718 writeRegExp(value);
719 else if (value->IsObject())
720 return push(newObjectState(value.As<v8::Object>(), next));
721 return 0;
722 }
723
724 // Interface used by Reader to create objects of composite types.
725 class CompositeCreator {
726 public:
~CompositeCreator()727 virtual ~CompositeCreator() { }
728
729 virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value) = 0;
730 virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value) = 0;
731 virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) = 0;
732 };
733
734 // Reader is responsible for deserializing primitive types and
735 // restoring information about saved objects of composite types.
736 class Reader {
737 public:
Reader(const uint8_t * buffer,int length)738 Reader(const uint8_t* buffer, int length)
739 : m_buffer(buffer)
740 , m_length(length)
741 , m_position(0)
742 {
743 ASSERT(length >= 0);
744 }
745
isEof() const746 bool isEof() const { return m_position >= m_length; }
747
read(v8::Handle<v8::Value> * value,CompositeCreator & creator)748 bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
749 {
750 SerializationTag tag;
751 if (!readTag(&tag))
752 return false;
753 switch (tag) {
754 case InvalidTag:
755 return false;
756 case PaddingTag:
757 return true;
758 case UndefinedTag:
759 *value = v8::Undefined();
760 break;
761 case NullTag:
762 *value = v8::Null();
763 break;
764 case TrueTag:
765 *value = v8::True();
766 break;
767 case FalseTag:
768 *value = v8::False();
769 break;
770 case StringTag:
771 if (!readString(value))
772 return false;
773 break;
774 case Int32Tag:
775 if (!readInt32(value))
776 return false;
777 break;
778 case Uint32Tag:
779 if (!readUint32(value))
780 return false;
781 break;
782 case DateTag:
783 if (!readDate(value))
784 return false;
785 break;
786 case NumberTag:
787 if (!readNumber(value))
788 return false;
789 break;
790 case BlobTag:
791 if (!readBlob(value))
792 return false;
793 break;
794 case FileTag:
795 if (!readFile(value))
796 return false;
797 break;
798 case FileListTag:
799 if (!readFileList(value))
800 return false;
801 break;
802 case ImageDataTag:
803 if (!readImageData(value))
804 return false;
805 break;
806 case ArrayTag: {
807 uint32_t length;
808 if (!doReadUint32(&length))
809 return false;
810 if (!creator.createArray(length, value))
811 return false;
812 break;
813 }
814 case RegExpTag:
815 if (!readRegExp(value))
816 return false;
817 break;
818 case ObjectTag: {
819 uint32_t numProperties;
820 if (!doReadUint32(&numProperties))
821 return false;
822 if (!creator.createObject(numProperties, value))
823 return false;
824 break;
825 }
826 case SparseArrayTag: {
827 uint32_t numProperties;
828 uint32_t length;
829 if (!doReadUint32(&numProperties))
830 return false;
831 if (!doReadUint32(&length))
832 return false;
833 if (!creator.createSparseArray(numProperties, length, value))
834 return false;
835 break;
836 }
837 default:
838 return false;
839 }
840 return !value->IsEmpty();
841 }
842
843 private:
readTag(SerializationTag * tag)844 bool readTag(SerializationTag* tag)
845 {
846 if (m_position >= m_length)
847 return false;
848 *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
849 return true;
850 }
851
readString(v8::Handle<v8::Value> * value)852 bool readString(v8::Handle<v8::Value>* value)
853 {
854 uint32_t length;
855 if (!doReadUint32(&length))
856 return false;
857 if (m_position + length > m_length)
858 return false;
859 *value = v8::String::New(reinterpret_cast<const char*>(m_buffer + m_position), length);
860 m_position += length;
861 return true;
862 }
863
readWebCoreString(String * string)864 bool readWebCoreString(String* string)
865 {
866 uint32_t length;
867 if (!doReadUint32(&length))
868 return false;
869 if (m_position + length > m_length)
870 return false;
871 *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
872 m_position += length;
873 return true;
874 }
875
readInt32(v8::Handle<v8::Value> * value)876 bool readInt32(v8::Handle<v8::Value>* value)
877 {
878 uint32_t rawValue;
879 if (!doReadUint32(&rawValue))
880 return false;
881 *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue)));
882 return true;
883 }
884
readUint32(v8::Handle<v8::Value> * value)885 bool readUint32(v8::Handle<v8::Value>* value)
886 {
887 uint32_t rawValue;
888 if (!doReadUint32(&rawValue))
889 return false;
890 *value = v8::Integer::NewFromUnsigned(rawValue);
891 return true;
892 }
893
readDate(v8::Handle<v8::Value> * value)894 bool readDate(v8::Handle<v8::Value>* value)
895 {
896 double numberValue;
897 if (!doReadNumber(&numberValue))
898 return false;
899 *value = v8::Date::New(numberValue);
900 return true;
901 }
902
readNumber(v8::Handle<v8::Value> * value)903 bool readNumber(v8::Handle<v8::Value>* value)
904 {
905 double number;
906 if (!doReadNumber(&number))
907 return false;
908 *value = v8::Number::New(number);
909 return true;
910 }
911
readImageData(v8::Handle<v8::Value> * value)912 bool readImageData(v8::Handle<v8::Value>* value)
913 {
914 uint32_t width;
915 uint32_t height;
916 uint32_t pixelDataLength;
917 if (!doReadUint32(&width))
918 return false;
919 if (!doReadUint32(&height))
920 return false;
921 if (!doReadUint32(&pixelDataLength))
922 return false;
923 if (m_position + pixelDataLength > m_length)
924 return false;
925 RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
926 WTF::ByteArray* pixelArray = imageData->data()->data();
927 ASSERT(pixelArray);
928 ASSERT(pixelArray->length() >= pixelDataLength);
929 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
930 m_position += pixelDataLength;
931 *value = toV8(imageData.release());
932 return true;
933 }
934
readRegExp(v8::Handle<v8::Value> * value)935 bool readRegExp(v8::Handle<v8::Value>* value)
936 {
937 v8::Handle<v8::Value> pattern;
938 if (!readString(&pattern))
939 return false;
940 uint32_t flags;
941 if (!doReadUint32(&flags))
942 return false;
943 *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags));
944 return true;
945 }
946
readBlob(v8::Handle<v8::Value> * value)947 bool readBlob(v8::Handle<v8::Value>* value)
948 {
949 String url;
950 String type;
951 uint64_t size;
952 if (!readWebCoreString(&url))
953 return false;
954 if (!readWebCoreString(&type))
955 return false;
956 if (!doReadUint64(&size))
957 return false;
958 PassRefPtr<Blob> blob = Blob::create(KURL(ParsedURLString, url), type, size);
959 *value = toV8(blob);
960 return true;
961 }
962
readFile(v8::Handle<v8::Value> * value)963 bool readFile(v8::Handle<v8::Value>* value)
964 {
965 String path;
966 String url;
967 String type;
968 if (!readWebCoreString(&path))
969 return false;
970 if (!readWebCoreString(&url))
971 return false;
972 if (!readWebCoreString(&type))
973 return false;
974 PassRefPtr<File> file = File::create(path, KURL(ParsedURLString, url), type);
975 *value = toV8(file);
976 return true;
977 }
978
readFileList(v8::Handle<v8::Value> * value)979 bool readFileList(v8::Handle<v8::Value>* value)
980 {
981 uint32_t length;
982 if (!doReadUint32(&length))
983 return false;
984 PassRefPtr<FileList> fileList = FileList::create();
985 for (unsigned i = 0; i < length; ++i) {
986 String path;
987 String urlString;
988 String type;
989 if (!readWebCoreString(&path))
990 return false;
991 if (!readWebCoreString(&urlString))
992 return false;
993 if (!readWebCoreString(&type))
994 return false;
995 fileList->append(File::create(path, KURL(ParsedURLString, urlString), type));
996 }
997 *value = toV8(fileList);
998 return true;
999 }
1000
1001 template<class T>
doReadUintHelper(T * value)1002 bool doReadUintHelper(T* value)
1003 {
1004 *value = 0;
1005 uint8_t currentByte;
1006 int shift = 0;
1007 do {
1008 if (m_position >= m_length)
1009 return false;
1010 currentByte = m_buffer[m_position++];
1011 *value |= ((currentByte & varIntMask) << shift);
1012 shift += varIntShift;
1013 } while (currentByte & (1 << varIntShift));
1014 return true;
1015 }
1016
doReadUint32(uint32_t * value)1017 bool doReadUint32(uint32_t* value)
1018 {
1019 return doReadUintHelper(value);
1020 }
1021
doReadUint64(uint64_t * value)1022 bool doReadUint64(uint64_t* value)
1023 {
1024 return doReadUintHelper(value);
1025 }
1026
doReadNumber(double * number)1027 bool doReadNumber(double* number)
1028 {
1029 if (m_position + sizeof(double) > m_length)
1030 return false;
1031 uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
1032 for (unsigned i = 0; i < sizeof(double); ++i)
1033 numberAsByteArray[i] = m_buffer[m_position++];
1034 return true;
1035 }
1036
1037 const uint8_t* m_buffer;
1038 const unsigned m_length;
1039 unsigned m_position;
1040 };
1041
1042 class Deserializer : public CompositeCreator {
1043 public:
Deserializer(Reader & reader)1044 explicit Deserializer(Reader& reader)
1045 : m_reader(reader)
1046 {
1047 }
1048
deserialize()1049 v8::Handle<v8::Value> deserialize()
1050 {
1051 v8::HandleScope scope;
1052 while (!m_reader.isEof()) {
1053 if (!doDeserialize())
1054 return v8::Null();
1055 }
1056 if (stackDepth() != 1)
1057 return v8::Null();
1058 return scope.Close(element(0));
1059 }
1060
createArray(uint32_t length,v8::Handle<v8::Value> * value)1061 virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value)
1062 {
1063 if (length > stackDepth())
1064 return false;
1065 v8::Local<v8::Array> array = v8::Array::New(length);
1066 if (array.IsEmpty())
1067 return false;
1068 const int depth = stackDepth() - length;
1069 for (unsigned i = 0; i < length; ++i)
1070 array->Set(i, element(depth + i));
1071 pop(length);
1072 *value = array;
1073 return true;
1074 }
1075
createObject(uint32_t numProperties,v8::Handle<v8::Value> * value)1076 virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value)
1077 {
1078 v8::Local<v8::Object> object = v8::Object::New();
1079 if (object.IsEmpty())
1080 return false;
1081 return initializeObject(object, numProperties, value);
1082 }
1083
createSparseArray(uint32_t numProperties,uint32_t length,v8::Handle<v8::Value> * value)1084 virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
1085 {
1086 v8::Local<v8::Array> array = v8::Array::New(length);
1087 if (array.IsEmpty())
1088 return false;
1089 return initializeObject(array, numProperties, value);
1090 }
1091
1092 private:
initializeObject(v8::Handle<v8::Object> object,uint32_t numProperties,v8::Handle<v8::Value> * value)1093 bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
1094 {
1095 unsigned length = 2 * numProperties;
1096 if (length > stackDepth())
1097 return false;
1098 for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
1099 v8::Local<v8::Value> propertyName = element(i);
1100 v8::Local<v8::Value> propertyValue = element(i + 1);
1101 object->Set(propertyName, propertyValue);
1102 }
1103 pop(length);
1104 *value = object;
1105 return true;
1106 }
1107
doDeserialize()1108 bool doDeserialize()
1109 {
1110 v8::Local<v8::Value> value;
1111 if (!m_reader.read(&value, *this))
1112 return false;
1113 if (!value.IsEmpty())
1114 push(value);
1115 return true;
1116 }
1117
push(v8::Local<v8::Value> value)1118 void push(v8::Local<v8::Value> value) { m_stack.append(value); }
1119
pop(unsigned length)1120 void pop(unsigned length)
1121 {
1122 ASSERT(length <= m_stack.size());
1123 m_stack.shrink(m_stack.size() - length);
1124 }
1125
stackDepth() const1126 unsigned stackDepth() const { return m_stack.size(); }
1127
element(unsigned index)1128 v8::Local<v8::Value> element(unsigned index)
1129 {
1130 ASSERT(index < m_stack.size());
1131 return m_stack[index];
1132 }
1133
1134 Reader& m_reader;
1135 Vector<v8::Local<v8::Value> > m_stack;
1136 };
1137
1138 } // namespace
1139
deserializeAndSetProperty(v8::Handle<v8::Object> object,const char * propertyName,v8::PropertyAttribute attribute,SerializedScriptValue * value)1140 void SerializedScriptValue::deserializeAndSetProperty(v8::Handle<v8::Object> object, const char* propertyName,
1141 v8::PropertyAttribute attribute, SerializedScriptValue* value)
1142 {
1143 if (!value)
1144 return;
1145 v8::Handle<v8::Value> deserialized = value->deserialize();
1146 object->ForceSet(v8::String::NewSymbol(propertyName), deserialized, attribute);
1147 }
1148
deserializeAndSetProperty(v8::Handle<v8::Object> object,const char * propertyName,v8::PropertyAttribute attribute,PassRefPtr<SerializedScriptValue> value)1149 void SerializedScriptValue::deserializeAndSetProperty(v8::Handle<v8::Object> object, const char* propertyName,
1150 v8::PropertyAttribute attribute, PassRefPtr<SerializedScriptValue> value)
1151 {
1152 deserializeAndSetProperty(object, propertyName, attribute, value.get());
1153 }
1154
create(v8::Handle<v8::Value> value,bool & didThrow)1155 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, bool& didThrow)
1156 {
1157 return adoptRef(new SerializedScriptValue(value, didThrow));
1158 }
1159
create(v8::Handle<v8::Value> value)1160 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value)
1161 {
1162 bool didThrow;
1163 return adoptRef(new SerializedScriptValue(value, didThrow));
1164 }
1165
createFromWire(String data)1166 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(String data)
1167 {
1168 return adoptRef(new SerializedScriptValue(data));
1169 }
1170
create(String data)1171 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(String data)
1172 {
1173 Writer writer;
1174 writer.writeWebCoreString(data);
1175 String wireData = StringImpl::adopt(writer.data());
1176 return adoptRef(new SerializedScriptValue(wireData));
1177 }
1178
create()1179 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
1180 {
1181 return adoptRef(new SerializedScriptValue());
1182 }
1183
nullValue()1184 SerializedScriptValue* SerializedScriptValue::nullValue()
1185 {
1186 DEFINE_STATIC_LOCAL(RefPtr<SerializedScriptValue>, nullValue, (0));
1187 if (!nullValue) {
1188 Writer writer;
1189 writer.writeNull();
1190 String wireData = StringImpl::adopt(writer.data());
1191 nullValue = adoptRef(new SerializedScriptValue(wireData));
1192 }
1193 return nullValue.get();
1194 }
1195
undefinedValue()1196 SerializedScriptValue* SerializedScriptValue::undefinedValue()
1197 {
1198 DEFINE_STATIC_LOCAL(RefPtr<SerializedScriptValue>, undefinedValue, (0));
1199 if (!undefinedValue) {
1200 Writer writer;
1201 writer.writeUndefined();
1202 String wireData = StringImpl::adopt(writer.data());
1203 undefinedValue = adoptRef(new SerializedScriptValue(wireData));
1204 }
1205 return undefinedValue.get();
1206 }
1207
release()1208 PassRefPtr<SerializedScriptValue> SerializedScriptValue::release()
1209 {
1210 RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data));
1211 m_data = String().crossThreadString();
1212 return result.release();
1213 }
1214
SerializedScriptValue()1215 SerializedScriptValue::SerializedScriptValue()
1216 {
1217 }
1218
SerializedScriptValue(v8::Handle<v8::Value> value,bool & didThrow)1219 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, bool& didThrow)
1220 {
1221 didThrow = false;
1222 Writer writer;
1223 Serializer::Status status;
1224 {
1225 v8::TryCatch tryCatch;
1226 Serializer serializer(writer, tryCatch);
1227 status = serializer.serialize(value);
1228 if (status == Serializer::JSException) {
1229 // If there was a JS exception thrown, re-throw it.
1230 didThrow = true;
1231 tryCatch.ReThrow();
1232 return;
1233 }
1234 }
1235 if (status == Serializer::InputError) {
1236 // If there was an input error, throw a new exception outside
1237 // of the TryCatch scope.
1238 didThrow = true;
1239 throwError(NOT_SUPPORTED_ERR);
1240 return;
1241 }
1242 if (status == Serializer::JSFailure) {
1243 // If there was a JS failure (but no exception), there's not
1244 // much we can do except for unwinding the C++ stack by
1245 // pretending there was a JS exception.
1246 didThrow = true;
1247 return;
1248 }
1249 ASSERT(status == Serializer::Success);
1250 m_data = String(StringImpl::adopt(writer.data())).crossThreadString();
1251 }
1252
SerializedScriptValue(String wireData)1253 SerializedScriptValue::SerializedScriptValue(String wireData)
1254 {
1255 m_data = wireData.crossThreadString();
1256 }
1257
deserialize()1258 v8::Handle<v8::Value> SerializedScriptValue::deserialize()
1259 {
1260 if (!m_data.impl())
1261 return v8::Null();
1262 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
1263 Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters()), 2 * m_data.length());
1264 Deserializer deserializer(reader);
1265 return deserializer.deserialize();
1266 }
1267
1268 } // namespace WebCore
1269