Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / src / tracing / importer / gzip_importer.js
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.
4
5 'use strict';
6
7 /**
8  * @fileoverview GzipImporter inflates gzip compressed data and passes it along
9  * to an actual importer.
10  */
11 tvcm.require('tracing.importer.importer');
12 tvcm.require('tracing.trace_model');
13 tvcm.requireRawScript('jszip.js');
14 tvcm.requireRawScript('jszip-inflate.js');
15
16 tvcm.exportTo('tracing.importer', function() {
17
18   var Importer = tracing.importer.Importer;
19
20   var GZIP_HEADER_ID1 = 0x1f;
21   var GZIP_HEADER_ID2 = 0x8b;
22   var GZIP_DEFLATE_COMPRESSION = 8;
23
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);
30     } else
31       throw new Error('Unknown gzip data format');
32     this.model_ = model;
33     this.gzipData_ = eventData;
34   }
35
36   /**
37    * @param {eventData} Possibly gzip compressed data as a string or an
38    *                    ArrayBuffer.
39    * @return {boolean} Whether obj looks like gzip compressed data.
40    */
41   GzipImporter.canImport = function(eventData) {
42     var header;
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);
47       header =
48           [header.charCodeAt(0), header.charCodeAt(1), header.charCodeAt(2)];
49     } else
50       return false;
51     return header[0] == GZIP_HEADER_ID1 &&
52         header[1] == GZIP_HEADER_ID2 &&
53         header[2] == GZIP_DEFLATE_COMPRESSION;
54   };
55
56   /**
57    * Inflates (decompresses) the data stored in the given gzip bitstream.
58    * @return {string} Inflated data.
59    */
60   GzipImporter.inflateGzipData_ = function(data) {
61     var position = 0;
62
63     function getByte() {
64       if (position >= data.length)
65         throw new Error('Unexpected end of gzip data');
66       return data[position++];
67     }
68
69     function getWord() {
70       var low = getByte();
71       var high = getByte();
72       return (high << 8) + low;
73     }
74
75     function skipBytes(amount) {
76       position += amount;
77     }
78
79     function skipZeroTerminatedString() {
80       while (getByte() != 0) {}
81     }
82
83     var id1 = getByte();
84     var id2 = getByte();
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);
95
96     // Skip modification time, extra flags and OS.
97     skipBytes(4 + 1 + 1);
98
99     // Skip remaining fields before compressed data.
100     if (have_extra_fields) {
101       var bytes_to_skip = getWord();
102       skipBytes(bytes_to_skip);
103     }
104     if (have_file_name)
105       skipZeroTerminatedString();
106     if (have_comment)
107       skipZeroTerminatedString();
108     if (have_header_crc)
109       getWord();
110
111     // Inflate the data using jszip.
112     var inflated_data =
113         JSZip.compressions['DEFLATE'].uncompress(data.subarray(position));
114     return JSZip.utils.transformTo('string', inflated_data);
115   },
116
117   GzipImporter.prototype = {
118     __proto__: Importer.prototype,
119
120     /**
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.
123      */
124     extractSubtraces: function() {
125       var eventData = GzipImporter.inflateGzipData_(this.gzipData_);
126       return eventData ? [eventData] : [];
127     }
128   };
129
130   tracing.TraceModel.registerImporter(GzipImporter);
131
132   return {
133     GzipImporter: GzipImporter
134   };
135 });