1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 * @fileoverview GzipImporter inflates gzip compressed data and passes it along
9 * to an actual importer.
11 tvcm.require('tracing.importer.importer');
12 tvcm.require('tracing.trace_model');
13 tvcm.requireRawScript('jszip.js');
14 tvcm.requireRawScript('jszip-inflate.js');
16 tvcm.exportTo('tracing.importer', function() {
18 var Importer = tracing.importer.Importer;
20 var GZIP_HEADER_ID1 = 0x1f;
21 var GZIP_HEADER_ID2 = 0x8b;
22 var GZIP_DEFLATE_COMPRESSION = 8;
24 function GzipImporter(model, eventData) {
25 // Normalize the data into an Uint8Array.
26 if (typeof(eventData) === 'string' || eventData instanceof String) {
27 eventData = JSZip.utils.transformTo('uint8array', eventData);
28 } else if (eventData instanceof ArrayBuffer) {
29 eventData = new Uint8Array(eventData);
31 throw new Error('Unknown gzip data format');
33 this.gzipData_ = eventData;
37 * @param {eventData} Possibly gzip compressed data as a string or an
39 * @return {boolean} Whether obj looks like gzip compressed data.
41 GzipImporter.canImport = function(eventData) {
43 if (eventData instanceof ArrayBuffer)
44 header = new Uint8Array(eventData.slice(0, 3));
45 else if (typeof(eventData) === 'string' || eventData instanceof String) {
46 header = eventData.substring(0, 7);
48 [header.charCodeAt(0), header.charCodeAt(1), header.charCodeAt(2)];
51 return header[0] == GZIP_HEADER_ID1 &&
52 header[1] == GZIP_HEADER_ID2 &&
53 header[2] == GZIP_DEFLATE_COMPRESSION;
57 * Inflates (decompresses) the data stored in the given gzip bitstream.
58 * @return {string} Inflated data.
60 GzipImporter.inflateGzipData_ = function(data) {
64 if (position >= data.length)
65 throw new Error('Unexpected end of gzip data');
66 return data[position++];
72 return (high << 8) + low;
75 function skipBytes(amount) {
79 function skipZeroTerminatedString() {
80 while (getByte() != 0) {}
85 if (id1 !== GZIP_HEADER_ID1 || id2 !== GZIP_HEADER_ID2)
86 throw new Error('Not gzip data');
87 var compression_method = getByte();
88 if (compression_method !== GZIP_DEFLATE_COMPRESSION)
89 throw new Error('Unsupported compression method: ' + compression_method);
90 var flags = getByte();
91 var have_header_crc = flags & (1 << 1);
92 var have_extra_fields = flags & (1 << 2);
93 var have_file_name = flags & (1 << 3);
94 var have_comment = flags & (1 << 4);
96 // Skip modification time, extra flags and OS.
99 // Skip remaining fields before compressed data.
100 if (have_extra_fields) {
101 var bytes_to_skip = getWord();
102 skipBytes(bytes_to_skip);
105 skipZeroTerminatedString();
107 skipZeroTerminatedString();
111 // Inflate the data using jszip.
113 JSZip.compressions['DEFLATE'].uncompress(data.subarray(position));
114 return JSZip.utils.transformTo('string', inflated_data);
117 GzipImporter.prototype = {
118 __proto__: Importer.prototype,
121 * Called by the Model to extract subtraces from the event data. The
122 * subtraces are passed on to other importers that can recognize them.
124 extractSubtraces: function() {
125 var eventData = GzipImporter.inflateGzipData_(this.gzipData_);
126 return eventData ? [eventData] : [];
130 tracing.TraceModel.registerImporter(GzipImporter);
133 GzipImporter: GzipImporter