Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/encoding/TextDecoder.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/dom/TextDecoder.h"
8
#include "mozilla/dom/UnionTypes.h"
9
#include "mozilla/Encoding.h"
10
#include "mozilla/UniquePtrExtensions.h"
11
#include "nsContentUtils.h"
12
#include <stdint.h>
13
14
namespace mozilla {
15
namespace dom {
16
17
void
18
TextDecoder::Init(const nsAString& aLabel,
19
                  const TextDecoderOptions& aOptions,
20
                  ErrorResult& aRv)
21
0
{
22
0
  // Let encoding be the result of getting an encoding from label.
23
0
  // If encoding is failure or replacement, throw a RangeError
24
0
  // (https://encoding.spec.whatwg.org/#dom-textdecoder).
25
0
  const Encoding* encoding = Encoding::ForLabelNoReplacement(aLabel);
26
0
  if (!encoding) {
27
0
    nsAutoString label(aLabel);
28
0
    label.Trim(" \t\n\f\r");
29
0
    aRv.ThrowRangeError<MSG_ENCODING_NOT_SUPPORTED>(label);
30
0
    return;
31
0
  }
32
0
  InitWithEncoding(WrapNotNull(encoding), aOptions);
33
0
}
34
35
void
36
TextDecoder::InitWithEncoding(NotNull<const Encoding*> aEncoding,
37
                              const TextDecoderOptions& aOptions)
38
0
{
39
0
  aEncoding->Name(mEncoding);
40
0
  // Store the flags passed via our options dictionary.
41
0
  mFatal = aOptions.mFatal;
42
0
  mIgnoreBOM = aOptions.mIgnoreBOM;
43
0
44
0
  // Create a decoder object for mEncoding.
45
0
  if (mIgnoreBOM) {
46
0
    mDecoder = aEncoding->NewDecoderWithoutBOMHandling();
47
0
  } else {
48
0
    mDecoder = aEncoding->NewDecoderWithBOMRemoval();
49
0
  }
50
0
}
51
52
void
53
TextDecoder::Decode(Span<const uint8_t> aInput,
54
                    const bool aStream,
55
                    nsAString& aOutDecodedString,
56
                    ErrorResult& aRv)
57
0
{
58
0
  aOutDecodedString.Truncate();
59
0
60
0
  CheckedInt<size_t> needed = mDecoder->MaxUTF16BufferLength(aInput.Length());
61
0
  if (!needed.isValid() ||
62
0
      needed.value() > MaxValue<nsAString::size_type>::value) {
63
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
64
0
    return;
65
0
  }
66
0
67
0
  if (!aOutDecodedString.SetLength(needed.value(), fallible)) {
68
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
69
0
    return;
70
0
  }
71
0
72
0
  uint32_t result;
73
0
  size_t read;
74
0
  size_t written;
75
0
  bool hadErrors;
76
0
  if (mFatal) {
77
0
    Tie(result, read, written) = mDecoder->DecodeToUTF16WithoutReplacement(
78
0
      aInput, aOutDecodedString, !aStream);
79
0
    if (result != kInputEmpty) {
80
0
      aRv.ThrowTypeError<MSG_DOM_DECODING_FAILED>();
81
0
      return;
82
0
    }
83
0
  } else {
84
0
    Tie(result, read, written, hadErrors) =
85
0
      mDecoder->DecodeToUTF16(aInput, aOutDecodedString, !aStream);
86
0
  }
87
0
  MOZ_ASSERT(result == kInputEmpty);
88
0
  MOZ_ASSERT(read == aInput.Length());
89
0
  MOZ_ASSERT(written <= aOutDecodedString.Length());
90
0
  Unused << hadErrors;
91
0
92
0
  if (!aOutDecodedString.SetLength(written, fallible)) {
93
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
94
0
    return;
95
0
  }
96
0
97
0
  // If the internal streaming flag of the decoder object is not set,
98
0
  // then reset the encoding algorithm state to the default values
99
0
  if (!aStream) {
100
0
    mDecoder->Encoding()->NewDecoderWithBOMRemovalInto(*mDecoder);
101
0
  }
102
0
}
103
104
void
105
TextDecoder::Decode(const Optional<ArrayBufferViewOrArrayBuffer>& aBuffer,
106
                    const TextDecodeOptions& aOptions,
107
                    nsAString& aOutDecodedString,
108
                    ErrorResult& aRv)
109
0
{
110
0
  if (!aBuffer.WasPassed()) {
111
0
    Decode(nullptr, aOptions.mStream, aOutDecodedString, aRv);
112
0
    return;
113
0
  }
114
0
  const ArrayBufferViewOrArrayBuffer& buf = aBuffer.Value();
115
0
  uint8_t* data;
116
0
  uint32_t length;
117
0
  if (buf.IsArrayBufferView()) {
118
0
    buf.GetAsArrayBufferView().ComputeLengthAndData();
119
0
    data = buf.GetAsArrayBufferView().Data();
120
0
    length = buf.GetAsArrayBufferView().Length();
121
0
  } else {
122
0
    MOZ_ASSERT(buf.IsArrayBuffer());
123
0
    buf.GetAsArrayBuffer().ComputeLengthAndData();
124
0
    data = buf.GetAsArrayBuffer().Data();
125
0
    length = buf.GetAsArrayBuffer().Length();
126
0
  }
127
0
  Decode(MakeSpan(data, length), aOptions.mStream, aOutDecodedString, aRv);
128
0
}
129
130
void
131
TextDecoder::GetEncoding(nsAString& aEncoding)
132
0
{
133
0
  CopyASCIItoUTF16(mEncoding, aEncoding);
134
0
  nsContentUtils::ASCIIToLower(aEncoding);
135
0
}
136
137
} // namespace dom
138
} // namespace mozilla