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 "BlobImpl.h"
8 #include "File.h"
9 #include "mozilla/CheckedInt.h"
10 #include "mozilla/ErrorResult.h"
11 #include "nsIInputStream.h"
12 
13 namespace mozilla::dom {
14 
15 // Makes sure that aStart and aEnd is less then or equal to aSize and greater
16 // than 0
ParseSize(int64_t aSize,int64_t & aStart,int64_t & aEnd)17 static void ParseSize(int64_t aSize, int64_t& aStart, int64_t& aEnd) {
18   CheckedInt64 newStartOffset = aStart;
19   if (aStart < -aSize) {
20     newStartOffset = 0;
21   } else if (aStart < 0) {
22     newStartOffset += aSize;
23   } else if (aStart > aSize) {
24     newStartOffset = aSize;
25   }
26 
27   CheckedInt64 newEndOffset = aEnd;
28   if (aEnd < -aSize) {
29     newEndOffset = 0;
30   } else if (aEnd < 0) {
31     newEndOffset += aSize;
32   } else if (aEnd > aSize) {
33     newEndOffset = aSize;
34   }
35 
36   if (!newStartOffset.isValid() || !newEndOffset.isValid() ||
37       newStartOffset.value() >= newEndOffset.value()) {
38     aStart = aEnd = 0;
39   } else {
40     aStart = newStartOffset.value();
41     aEnd = newEndOffset.value();
42   }
43 }
44 
Slice(const Optional<int64_t> & aStart,const Optional<int64_t> & aEnd,const nsAString & aContentType,ErrorResult & aRv)45 already_AddRefed<BlobImpl> BlobImpl::Slice(const Optional<int64_t>& aStart,
46                                            const Optional<int64_t>& aEnd,
47                                            const nsAString& aContentType,
48                                            ErrorResult& aRv) {
49   // Truncate aStart and aEnd so that we stay within this file.
50   uint64_t thisLength = GetSize(aRv);
51   if (NS_WARN_IF(aRv.Failed())) {
52     return nullptr;
53   }
54 
55   int64_t start = aStart.WasPassed() ? aStart.Value() : 0;
56   int64_t end = aEnd.WasPassed() ? aEnd.Value() : (int64_t)thisLength;
57 
58   ParseSize((int64_t)thisLength, start, end);
59 
60   nsAutoString type(aContentType);
61   Blob::MakeValidBlobType(type);
62   return CreateSlice((uint64_t)start, (uint64_t)(end - start), type, aRv);
63 }
64 
GetSendInfo(nsIInputStream ** aBody,uint64_t * aContentLength,nsACString & aContentType,nsACString & aCharset)65 nsresult BlobImpl::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
66                                nsACString& aContentType, nsACString& aCharset) {
67   MOZ_ASSERT(aContentLength);
68 
69   ErrorResult rv;
70 
71   nsCOMPtr<nsIInputStream> stream;
72   CreateInputStream(getter_AddRefs(stream), rv);
73   if (NS_WARN_IF(rv.Failed())) {
74     return rv.StealNSResult();
75   }
76 
77   *aContentLength = GetSize(rv);
78   if (NS_WARN_IF(rv.Failed())) {
79     return rv.StealNSResult();
80   }
81 
82   nsAutoString contentType;
83   GetType(contentType);
84 
85   if (contentType.IsEmpty()) {
86     aContentType.SetIsVoid(true);
87   } else {
88     CopyUTF16toUTF8(contentType, aContentType);
89   }
90 
91   aCharset.Truncate();
92 
93   stream.forget(aBody);
94   return NS_OK;
95 }
96 
97 NS_IMPL_ISUPPORTS(BlobImpl, BlobImpl)
98 
99 }  // namespace mozilla::dom
100