Flutter Engine
The Flutter Engine
filter.cc
Go to the documentation of this file.
1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "bin/filter.h"
6
7#include "bin/dartutils.h"
8#include "bin/io_buffer.h"
9
10#include "include/dart_api.h"
11
12namespace dart {
13namespace bin {
14
17
18static constexpr int kFilterPointerNativeField = 0;
19
20static Dart_Handle GetFilter(Dart_Handle filter_obj, Filter** filter) {
21 ASSERT(filter != nullptr);
24 if (Dart_IsError(err)) {
25 return err;
26 }
27 if (result == nullptr) {
28 return Dart_NewApiError("Filter was destroyed");
29 }
30
31 *filter = result;
32 return Dart_Null();
33}
34
36 uint8_t** dictionary) {
37 ASSERT(dictionary != nullptr);
38 uint8_t* src = nullptr;
39 intptr_t size;
41
42 Dart_Handle err = Dart_ListLength(dictionary_obj, &size);
43 if (Dart_IsError(err)) {
44 return err;
45 }
46
47 uint8_t* result = new uint8_t[size];
48 if (result == nullptr) {
49 return Dart_NewApiError("Could not allocate new dictionary");
50 }
51
52 err = Dart_TypedDataAcquireData(dictionary_obj, &type,
53 reinterpret_cast<void**>(&src), &size);
54 if (!Dart_IsError(err)) {
55 memmove(result, src, size);
56 Dart_TypedDataReleaseData(dictionary_obj);
57 } else {
58 err = Dart_ListGetAsBytes(dictionary_obj, 0, result, size);
59 if (Dart_IsError(err)) {
60 delete[] result;
61 return err;
62 }
63 }
64
65 *dictionary = result;
66 return Dart_Null();
67}
68
71 Dart_Handle window_bits_obj = Dart_GetNativeArgument(args, 1);
72 int64_t window_bits = DartUtils::GetIntegerValue(window_bits_obj);
75 bool raw = DartUtils::GetBooleanValue(raw_obj);
76
77 Dart_Handle err;
78 uint8_t* dictionary = nullptr;
79 intptr_t dictionary_length = 0;
80 if (!Dart_IsNull(dict_obj)) {
81 err = CopyDictionary(dict_obj, &dictionary);
82 if (Dart_IsError(err)) {
84 }
85 ASSERT(dictionary != nullptr);
86 dictionary_length = 0;
87 err = Dart_ListLength(dict_obj, &dictionary_length);
88 if (Dart_IsError(err)) {
89 delete[] dictionary;
91 }
92 }
93
95 static_cast<int32_t>(window_bits), dictionary, dictionary_length, raw);
96 if (filter == nullptr) {
97 delete[] dictionary;
99 Dart_NewApiError("Could not allocate ZLibInflateFilter"));
100 }
101 if (!filter->Init()) {
102 delete filter;
104 DartUtils::NewInternalError("Failed to create ZLibInflateFilter"));
105 }
107 filter_obj, filter, sizeof(*filter) + dictionary_length);
108 if (Dart_IsError(err)) {
109 delete filter;
111 }
112}
113
115 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
117 bool gzip = DartUtils::GetBooleanValue(gzip_obj);
119 int64_t level =
121 Dart_Handle window_bits_obj = Dart_GetNativeArgument(args, 3);
122 int64_t window_bits = DartUtils::GetIntegerValue(window_bits_obj);
123 Dart_Handle mLevel_obj = Dart_GetNativeArgument(args, 4);
124 int64_t mem_level = DartUtils::GetIntegerValue(mLevel_obj);
125 Dart_Handle strategy_obj = Dart_GetNativeArgument(args, 5);
126 int64_t strategy = DartUtils::GetIntegerValue(strategy_obj);
129 bool raw = DartUtils::GetBooleanValue(raw_obj);
130
131 Dart_Handle err;
132 uint8_t* dictionary = nullptr;
133 intptr_t dictionary_length = 0;
134 if (!Dart_IsNull(dict_obj)) {
135 err = CopyDictionary(dict_obj, &dictionary);
136 if (Dart_IsError(err)) {
138 }
139 ASSERT(dictionary != nullptr);
140 dictionary_length = 0;
141 err = Dart_ListLength(dict_obj, &dictionary_length);
142 if (Dart_IsError(err)) {
143 delete[] dictionary;
145 }
146 }
147
149 gzip, static_cast<int32_t>(level), static_cast<int32_t>(window_bits),
150 static_cast<int32_t>(mem_level), static_cast<int32_t>(strategy),
151 dictionary, dictionary_length, raw);
152 if (filter == nullptr) {
153 delete[] dictionary;
155 Dart_NewApiError("Could not allocate ZLibDeflateFilter"));
156 }
157 if (!filter->Init()) {
158 delete filter;
160 DartUtils::NewInternalError("Failed to create ZLibDeflateFilter"));
161 }
163 filter_obj, filter, sizeof(*filter) + dictionary_length);
164 if (Dart_IsError(result)) {
165 delete filter;
167 }
168}
169
171 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
175 intptr_t chunk_length = end - start;
176 intptr_t length;
178 uint8_t* buffer = nullptr;
179
180 Filter* filter = nullptr;
181 Dart_Handle err = GetFilter(filter_obj, &filter);
182 if (Dart_IsError(err)) {
184 }
185
187 data_obj, &type, reinterpret_cast<void**>(&buffer), &length);
188 if (!Dart_IsError(result)) {
193 "Invalid argument passed to Filter_Process"));
194 }
195 uint8_t* zlib_buffer = new uint8_t[chunk_length];
196 if (zlib_buffer == nullptr) {
198 Dart_PropagateError(Dart_NewApiError("Could not allocate zlib buffer"));
199 }
200
201 memmove(zlib_buffer, buffer + start, chunk_length);
203 buffer = zlib_buffer;
204 } else {
205 err = Dart_ListLength(data_obj, &length);
206 if (Dart_IsError(err)) {
208 }
209 buffer = new uint8_t[chunk_length];
210 if (buffer == nullptr) {
211 Dart_PropagateError(Dart_NewApiError("Could not allocate buffer"));
212 }
213 err = Dart_ListGetAsBytes(data_obj, start, buffer, chunk_length);
214 if (Dart_IsError(err)) {
215 delete[] buffer;
217 }
218 }
219 // Process will take ownership of buffer, if successful.
220 if (!filter->Process(buffer, chunk_length)) {
221 delete[] buffer;
223 "Call to Process while still processing data"));
224 }
225}
226
228 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
230 bool flush = DartUtils::GetBooleanValue(flush_obj);
232 bool end = DartUtils::GetBooleanValue(end_obj);
233
234 Filter* filter = nullptr;
235 Dart_Handle err = GetFilter(filter_obj, &filter);
236 if (Dart_IsError(err)) {
238 }
239
240 intptr_t read = filter->Processed(
241 filter->processed_buffer(), filter->processed_buffer_size(), flush, end);
242 if (read < 0) {
244 DartUtils::NewDartFormatException("Filter error, bad data"));
245 } else if (read == 0) {
247 } else {
248 uint8_t* io_buffer;
250 if (Dart_IsNull(result)) {
252 return;
253 }
254 memmove(io_buffer, filter->processed_buffer(), read);
256 }
257}
258
259static void DeleteFilter(void* isolate_data, void* filter_pointer) {
260 Filter* filter = reinterpret_cast<Filter*>(filter_pointer);
261 delete filter;
262}
263
265 Filter* filter_pointer,
266 intptr_t size) {
267 Dart_Handle err =
269 reinterpret_cast<intptr_t>(filter_pointer));
270 if (Dart_IsError(err)) {
271 return err;
272 }
273 Dart_NewFinalizableHandle(filter, reinterpret_cast<void*>(filter_pointer),
275 return err;
276}
277
279 Filter** filter_pointer) {
282 reinterpret_cast<intptr_t*>(filter_pointer));
283}
284
286 delete[] dictionary_;
287 delete[] current_buffer_;
288 if (initialized()) {
289 deflateEnd(&stream_);
290 }
291}
292
294 int window_bits = window_bits_;
295 if ((raw_ || gzip_) && (window_bits == 8)) {
296 // zlib deflater does not work with windows size of 8 bits. Old versions
297 // of zlib would silently upgrade window size to 9 bits, newer versions
298 // return Z_STREAM_ERROR if window size is 8 bits but the stream header
299 // is suppressed. To maintain the old behavior upgrade window size here.
300 // This is safe because you can inflate a stream deflated with zlib
301 // using 9-bits with 8-bits window.
302 // For more details see https://crbug.com/691074.
303 window_bits = 9;
304 }
305 if (raw_) {
306 window_bits = -window_bits;
307 } else if (gzip_) {
308 window_bits += kZLibFlagUseGZipHeader;
309 }
310 stream_.next_in = Z_NULL;
311 stream_.zalloc = Z_NULL;
312 stream_.zfree = Z_NULL;
313 stream_.opaque = Z_NULL;
314 int result = deflateInit2(&stream_, level_, Z_DEFLATED, window_bits,
315 mem_level_, strategy_);
316 if (result != Z_OK) {
317 return false;
318 }
319 if ((dictionary_ != nullptr) && !gzip_ && !raw_) {
320 result = deflateSetDictionary(&stream_, dictionary_, dictionary_length_);
321 delete[] dictionary_;
322 dictionary_ = nullptr;
323 if (result != Z_OK) {
324 return false;
325 }
326 }
327 set_initialized(true);
328 return true;
329}
330
331bool ZLibDeflateFilter::Process(uint8_t* data, intptr_t length) {
332 if (current_buffer_ != nullptr) {
333 return false;
334 }
335 stream_.avail_in = length;
336 stream_.next_in = current_buffer_ = data;
337 return true;
338}
339
341 intptr_t length,
342 bool flush,
343 bool end) {
344 stream_.avail_out = length;
345 stream_.next_out = buffer;
346 bool error = false;
347 switch (deflate(&stream_, end ? Z_FINISH
348 : flush ? Z_SYNC_FLUSH
349 : Z_NO_FLUSH)) {
350 case Z_OK:
351 case Z_STREAM_END:
352 case Z_BUF_ERROR: {
353 intptr_t processed = length - stream_.avail_out;
354 if (processed == 0) {
355 break;
356 }
357 return processed;
358 }
359
360 default:
361 case Z_STREAM_ERROR:
362 error = true;
363 }
364
365 delete[] current_buffer_;
366 current_buffer_ = nullptr;
367 // Either 0 Byte processed or error
368 return error ? -1 : 0;
369}
370
372 delete[] dictionary_;
373 delete[] current_buffer_;
374 if (initialized()) {
375 inflateEnd(&stream_);
376 }
377}
378
380 int window_bits =
381 raw_ ? -window_bits_ : window_bits_ | kZLibFlagAcceptAnyHeader;
382
383 stream_.next_in = Z_NULL;
384 stream_.avail_in = 0;
385 stream_.zalloc = Z_NULL;
386 stream_.zfree = Z_NULL;
387 stream_.opaque = Z_NULL;
388 int result = inflateInit2(&stream_, window_bits);
389 if (result != Z_OK) {
390 return false;
391 }
392 set_initialized(true);
393 return true;
394}
395
396bool ZLibInflateFilter::Process(uint8_t* data, intptr_t length) {
397 if (current_buffer_ != nullptr) {
398 return false;
399 }
400 stream_.avail_in = length;
401 stream_.next_in = current_buffer_ = data;
402 return true;
403}
404
406 intptr_t length,
407 bool flush,
408 bool end) {
409 stream_.avail_out = length;
410 stream_.next_out = buffer;
411 bool error = false;
412 int v;
413 switch (v = inflate(&stream_, end ? Z_FINISH
414 : flush ? Z_SYNC_FLUSH
415 : Z_NO_FLUSH)) {
416 case Z_OK:
417 case Z_STREAM_END:
418 case Z_BUF_ERROR: {
419 intptr_t processed = length - stream_.avail_out;
420
421 if (v == Z_STREAM_END) {
422 // Allow for concatenated compressed blocks. For example:
423 // final data = [
424 // ...gzip.encode([1, 2, 3]),
425 // ...gzip.encode([4, 5, 6]),
426 // ];
427 // final decoded = gzip.decode(data); // [1, 2, 3, 4, 5, 6]
428
429 // The return code for `inflateReset` can be ignored because, if the
430 // result is an error, the same error will be returned in the next
431 // call to `inflate`.
432 inflateReset(&stream_);
433 }
434 if (processed == 0) {
435 break;
436 }
437 return processed;
438 }
439
440 case Z_NEED_DICT:
441 if (dictionary_ == nullptr) {
442 error = true;
443 } else {
444 int result =
445 inflateSetDictionary(&stream_, dictionary_, dictionary_length_);
446 delete[] dictionary_;
447 dictionary_ = nullptr;
448 error = result != Z_OK;
449 }
450 if (error) {
451 break;
452 } else {
453 return Processed(buffer, length, flush, end);
454 }
455
456 default:
457 case Z_MEM_ERROR:
458 case Z_DATA_ERROR:
459 case Z_STREAM_ERROR:
460 error = true;
461 }
462
463 delete[] current_buffer_;
464 current_buffer_ = nullptr;
465 // Either 0 Byte processed or error
466 return error ? -1 : 0;
467}
468
469} // namespace bin
470} // namespace dart
static bool read(SkStream *stream, void *buffer, size_t amount)
GLenum type
#define FUNCTION_NAME(name)
Definition: builtin.h:19
static Dart_Handle NewDartFormatException(const char *message)
Definition: dartutils.cc:750
static int64_t GetIntegerValue(Dart_Handle value_obj)
Definition: dartutils.cc:81
static int64_t GetInt64ValueCheckRange(Dart_Handle value_obj, int64_t lower, int64_t upper)
Definition: dartutils.cc:90
static Dart_Handle NewDartOSError()
Definition: dartutils.cc:702
static bool GetBooleanValue(Dart_Handle bool_obj)
Definition: dartutils.cc:137
static Dart_Handle NewInternalError(const char *message)
Definition: dartutils.cc:781
static intptr_t GetIntptrValue(Dart_Handle value_obj)
Definition: dartutils.cc:100
virtual intptr_t Processed(uint8_t *buffer, intptr_t length, bool finish, bool end)=0
static Dart_Handle SetFilterAndCreateFinalizer(Dart_Handle filter, Filter *filter_pointer, intptr_t filter_size)
Definition: filter.cc:264
virtual bool Process(uint8_t *data, intptr_t length)=0
intptr_t processed_buffer_size() const
Definition: filter.h:42
bool initialized() const
Definition: filter.h:39
uint8_t * processed_buffer()
Definition: filter.h:41
static Dart_Handle GetFilterNativeField(Dart_Handle filter, Filter **filter_pointer)
Definition: filter.cc:278
void set_initialized(bool value)
Definition: filter.h:40
static Dart_Handle Allocate(intptr_t size, uint8_t **buffer)
Definition: io_buffer.cc:12
virtual bool Process(uint8_t *data, intptr_t length)
Definition: filter.cc:331
virtual intptr_t Processed(uint8_t *buffer, intptr_t length, bool finish, bool end)
Definition: filter.cc:340
virtual intptr_t Processed(uint8_t *buffer, intptr_t length, bool finish, bool end)
Definition: filter.cc:405
virtual bool Process(uint8_t *data, intptr_t length)
Definition: filter.cc:396
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
struct _Dart_NativeArguments * Dart_NativeArguments
Definition: dart_api.h:3019
Dart_TypedData_Type
Definition: dart_api.h:2612
@ Dart_TypedData_kUint8
Definition: dart_api.h:2615
@ Dart_TypedData_kInt8
Definition: dart_api.h:2614
#define ASSERT(E)
glong glong end
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
size_t length
void FUNCTION_NAME() Filter_Processed(Dart_NativeArguments args)
Definition: filter.cc:227
void FUNCTION_NAME() Filter_Process(Dart_NativeArguments args)
Definition: filter.cc:170
static void DeleteFilter(void *isolate_data, void *filter_pointer)
Definition: filter.cc:259
const int kZLibFlagAcceptAnyHeader
Definition: filter.cc:16
const int kZLibFlagUseGZipHeader
Definition: filter.cc:15
static Dart_Handle CopyDictionary(Dart_Handle dictionary_obj, uint8_t **dictionary)
Definition: filter.cc:35
static constexpr int kFilterPointerNativeField
Definition: filter.cc:18
void FUNCTION_NAME() Filter_CreateZLibDeflate(Dart_NativeArguments args)
Definition: filter.cc:114
void FUNCTION_NAME() Filter_CreateZLibInflate(Dart_NativeArguments args)
Definition: filter.cc:69
static Dart_Handle GetFilter(Dart_Handle filter_obj, Filter **filter)
Definition: filter.cc:20
Definition: dart_vm.cc:33
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, int index, intptr_t *value)
constexpr int32_t kMinInt32
Definition: globals.h:482
DART_EXPORT void Dart_PropagateError(Dart_Handle handle)
DART_EXPORT Dart_FinalizableHandle Dart_NewFinalizableHandle(Dart_Handle object, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object, Dart_TypedData_Type *type, void **data, intptr_t *len)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj, int index, intptr_t value)
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list, intptr_t offset, uint8_t *native_array, intptr_t length)
DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object)
constexpr int32_t kMaxInt32
Definition: globals.h:483
DART_EXPORT Dart_Handle Dart_NewApiError(const char *error)
DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t *len)
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception)
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_Null()
static int8_t data[kExtLength]
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259