Skip to content

Commit ea54ba9

Browse files
authored
Implement URL.createObjectURL and URL.revokeObjectURL methods (#187)
1 parent 257fece commit ea54ba9

File tree

18 files changed

+893
-185
lines changed

18 files changed

+893
-185
lines changed

builtins/web/crypto/crypto-algorithm.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,7 @@ JSObject *CryptoAlgorithmRSASSA_PKCS1_v1_5_Import::importKey(JSContext *cx, Cryp
18411841
case CryptoKeyFormat::Spki:
18421842
case CryptoKeyFormat::Pkcs8: {
18431843
// TODO: Add implementations for these
1844+
[[fallthrough]];
18441845
}
18451846
default: {
18461847
DOMException::raise(cx, "Supplied format is not supported", "DataError");

builtins/web/crypto/crypto.cpp

Lines changed: 7 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
// TODO: remove these once the warnings are fixed
2-
#pragma clang diagnostic push
3-
#pragma clang diagnostic ignored "-Winvalid-offsetof"
4-
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"
5-
#include "js/experimental/TypedData.h" // used in "js/Conversions.h"
6-
#pragma clang diagnostic pop
7-
81
#include "../dom-exception.h"
92
#include "crypto.h"
103
#include "host_api.h"
114
#include "subtle-crypto.h"
5+
#include "uuid.h"
126

137
bool is_int_typed_array(JSObject *obj) {
148
return JS_IsInt8Array(obj) || JS_IsUint8Array(obj) || JS_IsInt16Array(obj) ||
@@ -66,114 +60,18 @@ bool Crypto::get_random_values(JSContext *cx, unsigned argc, JS::Value *vp) {
6660
return true;
6761
}
6862

69-
/*
70-
FROM RFC 4122
71-
The formal definition of the UUID string representation is
72-
provided by the following ABNF [7]:
73-
74-
UUID = time-low "-" time-mid "-"
75-
time-high-and-version "-"
76-
clock-seq-and-reserved
77-
clock-seq-low "-" node
78-
time-low = 4hexOctet
79-
time-mid = 2hexOctet
80-
time-high-and-version = 2hexOctet
81-
clock-seq-and-reserved = hexOctet
82-
clock-seq-low = hexOctet
83-
node = 6hexOctet
84-
hexOctet = hexDigit hexDigit
85-
hexDigit =
86-
"0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /
87-
"a" / "b" / "c" / "d" / "e" / "f" /
88-
"A" / "B" / "C" / "D" / "E" / "F"
89-
*/
90-
struct UUID {
91-
uint32_t time_low;
92-
uint16_t time_mid;
93-
uint16_t time_high_and_version;
94-
uint8_t clock_seq_and_reserved;
95-
uint8_t clock_seq_low;
96-
uint8_t node[6];
97-
};
98-
99-
/*
100-
FROM RFC 4122
101-
4.1.3. Version
102-
103-
The version number is in the most significant 4 bits of the time
104-
stamp (bits 4 through 7 of the time_hi_and_version field).
105-
106-
The following table lists the currently-defined versions for this
107-
UUID variant.
108-
109-
Msb0 Msb1 Msb2 Msb3 Version Description
110-
111-
0 0 0 1 1 The time-based version
112-
specified in this document.
113-
114-
0 0 1 0 2 DCE Security version, with
115-
embedded POSIX UIDs.
116-
117-
0 0 1 1 3 The name-based version
118-
specified in this document
119-
that uses MD5 hashing.
120-
121-
0 1 0 0 4 The randomly or pseudo-
122-
randomly generated version
123-
specified in this document.
124-
125-
0 1 0 1 5 The name-based version
126-
specified in this document
127-
that uses SHA-1 hashing.
128-
*/
129-
/*
130-
FROM RFC 4122
131-
The version 4 UUID is meant for generating UUIDs from truly-random or
132-
pseudo-random numbers.
133-
134-
The algorithm is as follows:
135-
136-
Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one,
137-
respectively.
138-
139-
Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the
140-
4-bit version number from Section 4.1.3.
141-
142-
Set all the other bits to randomly (or pseudo-randomly) chosen values.
143-
*/
14463
bool Crypto::random_uuid(JSContext *cx, unsigned argc, JS::Value *vp) {
14564
METHOD_HEADER(0)
146-
UUID id;
14765

148-
{
149-
auto res = host_api::Random::get_bytes(sizeof(id));
150-
if (auto *err = res.to_err()) {
151-
HANDLE_ERROR(cx, *err);
152-
return false;
153-
}
154-
155-
auto bytes = std::move(res.unwrap());
156-
std::copy_n(bytes.begin(), sizeof(id), reinterpret_cast<uint8_t *>(&id));
66+
auto maybe_uuid = random_uuid_v4(cx);
67+
if (!maybe_uuid.has_value()) {
68+
return false;
15769
}
15870

159-
// Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and
160-
// one, respectively.
161-
id.clock_seq_and_reserved &= 0x3f;
162-
id.clock_seq_and_reserved |= 0x80;
163-
// Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the
164-
// 4-bit version number from Section 4.1.3.
165-
id.time_high_and_version &= 0x0fff;
166-
id.time_high_and_version |= 0x4000;
167-
168-
const char *fmt = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
169-
char buf[80];
170-
std::snprintf(buf, sizeof(buf) - 1, fmt, id.time_low, (uint32_t)id.time_mid,
171-
(uint32_t)id.time_high_and_version, (uint32_t)id.clock_seq_and_reserved,
172-
(uint32_t)id.clock_seq_low, (uint32_t)id.node[0], (uint32_t)id.node[1],
173-
(uint32_t)id.node[2], (uint32_t)id.node[3], (uint32_t)id.node[4],
174-
(uint32_t)id.node[5]);
175-
JS::RootedString str(cx, JS_NewStringCopyN(cx, buf, 36));
71+
auto uuid = maybe_uuid.value();
72+
MOZ_ASSERT(uuid.size() == 36);
17673

74+
JS::RootedString str(cx, JS_NewStringCopyN(cx, uuid.data(), uuid.size()));
17775
if (!str) {
17876
return false;
17977
}

builtins/web/crypto/uuid.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#include "uuid.h"
2+
#include "host_api.h"
3+
4+
#include <fmt/core.h>
5+
6+
namespace builtins {
7+
namespace web {
8+
namespace crypto {
9+
10+
// FROM RFC 4122
11+
// The formal definition of the UUID string representation is
12+
// provided by the following ABNF [7]:
13+
//
14+
// UUID = time-low "-" time-mid "-"
15+
// time-high-and-version "-"
16+
// clock-seq-and-reserved
17+
// clock-seq-low "-" node
18+
// time-low = 4hexOctet
19+
// time-mid = 2hexOctet
20+
// time-high-and-version = 2hexOctet
21+
// clock-seq-and-reserved = hexOctet
22+
// clock-seq-low = hexOctet
23+
// node = 6hexOctet
24+
// hexOctet = hexDigit hexDigit
25+
// hexDigit =
26+
// "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /
27+
// "a" / "b" / "c" / "d" / "e" / "f" /
28+
// "A" / "B" / "C" / "D" / "E" / "F"
29+
struct UUID {
30+
uint32_t time_low;
31+
uint16_t time_mid;
32+
uint16_t time_high_and_version;
33+
uint8_t clock_seq_and_reserved;
34+
uint8_t clock_seq_low;
35+
uint8_t node[6];
36+
};
37+
38+
// FROM RFC 4122
39+
// 4.1.3. Version
40+
//
41+
// The version number is in the most significant 4 bits of the time
42+
// stamp (bits 4 through 7 of the time_hi_and_version field).
43+
//
44+
// The following table lists the currently-defined versions for this
45+
// UUID variant.
46+
//
47+
// Msb0 Msb1 Msb2 Msb3 Version Description
48+
//
49+
// 0 0 0 1 1 The time-based version
50+
// specified in this document.
51+
//
52+
// 0 0 1 0 2 DCE Security version, with
53+
// embedded POSIX UIDs.
54+
//
55+
// 0 0 1 1 3 The name-based version
56+
// specified in this document
57+
// that uses MD5 hashing.
58+
//
59+
// 0 1 0 0 4 The randomly or pseudo-
60+
// randomly generated version
61+
// specified in this document.
62+
//
63+
// 0 1 0 1 5 The name-based version
64+
// specified in this document
65+
// that uses SHA-1 hashing.
66+
std::optional<std::string> random_uuid_v4(JSContext *cx) {
67+
UUID id;
68+
69+
{
70+
auto res = host_api::Random::get_bytes(sizeof(id));
71+
if (auto *err = res.to_err()) {
72+
HANDLE_ERROR(cx, *err);
73+
return std::nullopt;
74+
}
75+
76+
auto bytes = std::move(res.unwrap());
77+
std::copy_n(bytes.begin(), sizeof(id), reinterpret_cast<uint8_t *>(&id));
78+
}
79+
80+
// Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and
81+
// one, respectively.
82+
id.clock_seq_and_reserved &= 0x3f;
83+
id.clock_seq_and_reserved |= 0x80;
84+
// Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the
85+
// 4-bit version number from Section 4.1.3.
86+
id.time_high_and_version &= 0x0fff;
87+
id.time_high_and_version |= 0x4000;
88+
89+
return fmt::format("{:08x}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
90+
id.time_low,
91+
id.time_mid,
92+
id.time_high_and_version,
93+
id.clock_seq_and_reserved, id.clock_seq_low,
94+
id.node[0], id.node[1], id.node[2],
95+
id.node[3], id.node[4], id.node[5]);
96+
}
97+
98+
} // namespace uuid
99+
} // namespace web
100+
} // namespace builtins

builtins/web/crypto/uuid.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef BUILTINS_WEB_CRYPTO_UUID_H
2+
#define BUILTINS_WEB_CRYPTO_UUID_H
3+
4+
#include "builtin.h"
5+
6+
namespace builtins {
7+
namespace web {
8+
namespace crypto {
9+
10+
// FROM RFC 4122
11+
// The version 4 UUID is meant for generating UUIDs from truly-random or
12+
// pseudo-random numbers.
13+
//
14+
// The algorithm is as follows:
15+
//
16+
// Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one,
17+
// respectively.
18+
//
19+
// Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the
20+
// 4-bit version number from Section 4.1.3.
21+
//
22+
// Set all the other bits to randomly (or pseudo-randomly) chosen values.
23+
std::optional<std::string> random_uuid_v4(JSContext *cx);
24+
25+
} // namespace crypto
26+
} // namespace web
27+
} // namespace builtins
28+
29+
#endif // BUILTINS_WEB_CRYPTO_UUID_H

0 commit comments

Comments
 (0)