| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright (c) 2012 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 var SourceEntry = (function() { | 
|  | 6   'use strict'; | 
|  | 7 | 
|  | 8   /** | 
|  | 9    * A SourceEntry gathers all log entries with the same source. | 
|  | 10    * | 
|  | 11    * @constructor | 
|  | 12    */ | 
|  | 13   function SourceEntry(logEntry, maxPreviousSourceId) { | 
|  | 14     this.maxPreviousSourceId_ = maxPreviousSourceId; | 
|  | 15     this.entries_ = []; | 
|  | 16     this.description_ = ''; | 
|  | 17 | 
|  | 18     // Set to true on most net errors. | 
|  | 19     this.isError_ = false; | 
|  | 20 | 
|  | 21     // If the first entry is a BEGIN_PHASE, set to false. | 
|  | 22     // Set to true when an END_PHASE matching the first entry is encountered. | 
|  | 23     this.isInactive_ = true; | 
|  | 24 | 
|  | 25     if (logEntry.phase == EventPhase.PHASE_BEGIN) | 
|  | 26       this.isInactive_ = false; | 
|  | 27 | 
|  | 28     this.update(logEntry); | 
|  | 29   } | 
|  | 30 | 
|  | 31   SourceEntry.prototype = { | 
|  | 32     update: function(logEntry) { | 
|  | 33       // Only the last event should have the same type first event, | 
|  | 34       if (!this.isInactive_ && | 
|  | 35           logEntry.phase == EventPhase.PHASE_END && | 
|  | 36           logEntry.type == this.entries_[0].type) { | 
|  | 37         this.isInactive_ = true; | 
|  | 38       } | 
|  | 39 | 
|  | 40       // If we have a net error code, update |this.isError_| if appropriate. | 
|  | 41       if (logEntry.params) { | 
|  | 42         var netErrorCode = logEntry.params.net_error; | 
|  | 43         // Skip both cases where netErrorCode is undefined, and cases where it | 
|  | 44         // is 0, indicating no actual error occurred. | 
|  | 45         if (netErrorCode) { | 
|  | 46           // Ignore error code caused by not finding an entry in the cache. | 
|  | 47           if (logEntry.type != EventType.HTTP_CACHE_OPEN_ENTRY || | 
|  | 48               netErrorCode != NetError.ERR_FAILED) { | 
|  | 49             this.isError_ = true; | 
|  | 50           } | 
|  | 51         } | 
|  | 52       } | 
|  | 53 | 
|  | 54       var prevStartEntry = this.getStartEntry_(); | 
|  | 55       this.entries_.push(logEntry); | 
|  | 56       var curStartEntry = this.getStartEntry_(); | 
|  | 57 | 
|  | 58       // If we just got the first entry for this source. | 
|  | 59       if (prevStartEntry != curStartEntry) | 
|  | 60         this.updateDescription_(); | 
|  | 61     }, | 
|  | 62 | 
|  | 63     updateDescription_: function() { | 
|  | 64       var e = this.getStartEntry_(); | 
|  | 65       this.description_ = ''; | 
|  | 66       if (!e) | 
|  | 67         return; | 
|  | 68 | 
|  | 69       if (e.source.type == EventSourceType.NONE) { | 
|  | 70         // NONE is what we use for global events that aren't actually grouped | 
|  | 71         // by a "source ID", so we will just stringize the event's type. | 
|  | 72         this.description_ = EventTypeNames[e.type]; | 
|  | 73         return; | 
|  | 74       } | 
|  | 75 | 
|  | 76       if (e.params == undefined) { | 
|  | 77         return; | 
|  | 78       } | 
|  | 79 | 
|  | 80       switch (e.source.type) { | 
|  | 81         case EventSourceType.URL_REQUEST: | 
|  | 82         // TODO(ricea): Remove SOCKET_STREAM after M41 is released. | 
|  | 83         case EventSourceType.SOCKET_STREAM: | 
|  | 84         case EventSourceType.HTTP_STREAM_JOB: | 
|  | 85           this.description_ = e.params.url; | 
|  | 86           break; | 
|  | 87         case EventSourceType.CONNECT_JOB: | 
|  | 88           this.description_ = e.params.group_name; | 
|  | 89           break; | 
|  | 90         case EventSourceType.HOST_RESOLVER_IMPL_JOB: | 
|  | 91         case EventSourceType.HOST_RESOLVER_IMPL_PROC_TASK: | 
|  | 92           this.description_ = e.params.host; | 
|  | 93           break; | 
|  | 94         case EventSourceType.DISK_CACHE_ENTRY: | 
|  | 95         case EventSourceType.MEMORY_CACHE_ENTRY: | 
|  | 96           this.description_ = e.params.key; | 
|  | 97           break; | 
|  | 98         case EventSourceType.QUIC_SESSION: | 
|  | 99           if (e.params.host != undefined) | 
|  | 100             this.description_ = e.params.host; | 
|  | 101           break; | 
|  | 102         case EventSourceType.HTTP2_SESSION: | 
|  | 103           if (e.params.host) | 
|  | 104             this.description_ = e.params.host + ' (' + e.params.proxy + ')'; | 
|  | 105           break; | 
|  | 106         case EventSourceType.HTTP_PIPELINED_CONNECTION: | 
|  | 107           if (e.params.host_and_port) | 
|  | 108             this.description_ = e.params.host_and_port; | 
|  | 109           break; | 
|  | 110         case EventSourceType.SOCKET: | 
|  | 111         case EventSourceType.PROXY_CLIENT_SOCKET: | 
|  | 112           // Use description of parent source, if any. | 
|  | 113           if (e.params.source_dependency != undefined) { | 
|  | 114             var parentId = e.params.source_dependency.id; | 
|  | 115             this.description_ = | 
|  | 116                 SourceTracker.getInstance().getDescription(parentId); | 
|  | 117           } | 
|  | 118           break; | 
|  | 119         case EventSourceType.UDP_SOCKET: | 
|  | 120           if (e.params.address != undefined) { | 
|  | 121             this.description_ = e.params.address; | 
|  | 122             // If the parent of |this| is a HOST_RESOLVER_IMPL_JOB, use | 
|  | 123             // '<DNS Server IP> [<host we're resolving>]'. | 
|  | 124             if (this.entries_[0].type == EventType.SOCKET_ALIVE && | 
|  | 125                 this.entries_[0].params && | 
|  | 126                 this.entries_[0].params.source_dependency != undefined) { | 
|  | 127               var parentId = this.entries_[0].params.source_dependency.id; | 
|  | 128               var parent = SourceTracker.getInstance().getSourceEntry(parentId); | 
|  | 129               if (parent && | 
|  | 130                   parent.getSourceType() == | 
|  | 131                       EventSourceType.HOST_RESOLVER_IMPL_JOB && | 
|  | 132                   parent.getDescription().length > 0) { | 
|  | 133                 this.description_ += ' [' + parent.getDescription() + ']'; | 
|  | 134               } | 
|  | 135             } | 
|  | 136           } | 
|  | 137           break; | 
|  | 138         case EventSourceType.ASYNC_HOST_RESOLVER_REQUEST: | 
|  | 139         case EventSourceType.DNS_TRANSACTION: | 
|  | 140           this.description_ = e.params.hostname; | 
|  | 141           break; | 
|  | 142         case EventSourceType.DOWNLOAD: | 
|  | 143           switch (e.type) { | 
|  | 144             case EventType.DOWNLOAD_FILE_RENAMED: | 
|  | 145               this.description_ = e.params.new_filename; | 
|  | 146               break; | 
|  | 147             case EventType.DOWNLOAD_FILE_OPENED: | 
|  | 148               this.description_ = e.params.file_name; | 
|  | 149               break; | 
|  | 150             case EventType.DOWNLOAD_ITEM_ACTIVE: | 
|  | 151               this.description_ = e.params.file_name; | 
|  | 152               break; | 
|  | 153           } | 
|  | 154           break; | 
|  | 155         case EventSourceType.FILESTREAM: | 
|  | 156           this.description_ = e.params.file_name; | 
|  | 157           break; | 
|  | 158         case EventSourceType.IPV6_PROBE_JOB: | 
|  | 159           if (e.type == EventType.IPV6_PROBE_RUNNING && | 
|  | 160               e.phase == EventPhase.PHASE_END) { | 
|  | 161             this.description_ = e.params.ipv6_supported ? 'IPv6 Supported' : | 
|  | 162                                                           'IPv6 Not Supported'; | 
|  | 163           } | 
|  | 164           break; | 
|  | 165       } | 
|  | 166 | 
|  | 167       if (this.description_ == undefined) | 
|  | 168         this.description_ = ''; | 
|  | 169     }, | 
|  | 170 | 
|  | 171     /** | 
|  | 172      * Returns a description for this source log stream, which will be displayed | 
|  | 173      * in the list view. Most often this is a URL that identifies the request, | 
|  | 174      * or a hostname for a connect job, etc... | 
|  | 175      */ | 
|  | 176     getDescription: function() { | 
|  | 177       return this.description_; | 
|  | 178     }, | 
|  | 179 | 
|  | 180     /** | 
|  | 181      * Returns the starting entry for this source. Conceptually this is the | 
|  | 182      * first entry that was logged to this source. However, we skip over the | 
|  | 183      * TYPE_REQUEST_ALIVE entries which wrap TYPE_URL_REQUEST_START_JOB | 
|  | 184      * entries. | 
|  | 185      */ | 
|  | 186     getStartEntry_: function() { | 
|  | 187       if (this.entries_.length < 1) | 
|  | 188         return undefined; | 
|  | 189       if (this.entries_[0].source.type == EventSourceType.FILESTREAM) { | 
|  | 190         var e = this.findLogEntryByType_(EventType.FILE_STREAM_OPEN); | 
|  | 191         if (e != undefined) | 
|  | 192           return e; | 
|  | 193       } | 
|  | 194       if (this.entries_[0].source.type == EventSourceType.DOWNLOAD) { | 
|  | 195         // If any rename occurred, use the last name | 
|  | 196         e = this.findLastLogEntryStartByType_( | 
|  | 197             EventType.DOWNLOAD_FILE_RENAMED); | 
|  | 198         if (e != undefined) | 
|  | 199           return e; | 
|  | 200         // Otherwise, if the file was opened, use that name | 
|  | 201         e = this.findLogEntryByType_(EventType.DOWNLOAD_FILE_OPENED); | 
|  | 202         if (e != undefined) | 
|  | 203           return e; | 
|  | 204         // History items are never opened, so use the activation info | 
|  | 205         e = this.findLogEntryByType_(EventType.DOWNLOAD_ITEM_ACTIVE); | 
|  | 206         if (e != undefined) | 
|  | 207           return e; | 
|  | 208       } | 
|  | 209       if (this.entries_.length >= 2) { | 
|  | 210         // Needed for compatability with log dumps prior to M26. | 
|  | 211         // TODO(mmenke):  Remove this. | 
|  | 212         if (this.entries_[0].type == EventType.SOCKET_POOL_CONNECT_JOB && | 
|  | 213             this.entries_[0].params == undefined) { | 
|  | 214           return this.entries_[1]; | 
|  | 215         } | 
|  | 216         if (this.entries_[1].type == EventType.UDP_CONNECT) | 
|  | 217           return this.entries_[1]; | 
|  | 218         if (this.entries_[0].type == EventType.REQUEST_ALIVE && | 
|  | 219             this.entries_[0].params == undefined) { | 
|  | 220           var startIndex = 1; | 
|  | 221           // Skip over delegate events for URL_REQUESTs. | 
|  | 222           for (; startIndex + 1 < this.entries_.length; ++startIndex) { | 
|  | 223             var type = this.entries_[startIndex].type; | 
|  | 224             if (type != EventType.URL_REQUEST_DELEGATE && | 
|  | 225                 type != EventType.DELEGATE_INFO) { | 
|  | 226               break; | 
|  | 227             } | 
|  | 228           } | 
|  | 229           return this.entries_[startIndex]; | 
|  | 230         } | 
|  | 231         if (this.entries_[1].type == EventType.IPV6_PROBE_RUNNING) | 
|  | 232           return this.entries_[1]; | 
|  | 233       } | 
|  | 234       return this.entries_[0]; | 
|  | 235     }, | 
|  | 236 | 
|  | 237     /** | 
|  | 238      * Returns the first entry with the specified type, or undefined if not | 
|  | 239      * found. | 
|  | 240      */ | 
|  | 241     findLogEntryByType_: function(type) { | 
|  | 242       for (var i = 0; i < this.entries_.length; ++i) { | 
|  | 243         if (this.entries_[i].type == type) { | 
|  | 244           return this.entries_[i]; | 
|  | 245         } | 
|  | 246       } | 
|  | 247       return undefined; | 
|  | 248     }, | 
|  | 249 | 
|  | 250     /** | 
|  | 251      * Returns the beginning of the last entry with the specified type, or | 
|  | 252      * undefined if not found. | 
|  | 253      */ | 
|  | 254     findLastLogEntryStartByType_: function(type) { | 
|  | 255       for (var i = this.entries_.length - 1; i >= 0; --i) { | 
|  | 256         if (this.entries_[i].type == type) { | 
|  | 257           if (this.entries_[i].phase != EventPhase.PHASE_END) | 
|  | 258             return this.entries_[i]; | 
|  | 259         } | 
|  | 260       } | 
|  | 261       return undefined; | 
|  | 262     }, | 
|  | 263 | 
|  | 264     getLogEntries: function() { | 
|  | 265       return this.entries_; | 
|  | 266     }, | 
|  | 267 | 
|  | 268     getSourceTypeString: function() { | 
|  | 269       return EventSourceTypeNames[this.entries_[0].source.type]; | 
|  | 270     }, | 
|  | 271 | 
|  | 272     getSourceType: function() { | 
|  | 273       return this.entries_[0].source.type; | 
|  | 274     }, | 
|  | 275 | 
|  | 276     getSourceId: function() { | 
|  | 277       return this.entries_[0].source.id; | 
|  | 278     }, | 
|  | 279 | 
|  | 280     /** | 
|  | 281      * Returns the largest source ID seen before this object was received. | 
|  | 282      * Used only for sorting SourceEntries without a source by source ID. | 
|  | 283      */ | 
|  | 284     getMaxPreviousEntrySourceId: function() { | 
|  | 285       return this.maxPreviousSourceId_; | 
|  | 286     }, | 
|  | 287 | 
|  | 288     isInactive: function() { | 
|  | 289       return this.isInactive_; | 
|  | 290     }, | 
|  | 291 | 
|  | 292     isError: function() { | 
|  | 293       return this.isError_; | 
|  | 294     }, | 
|  | 295 | 
|  | 296     /** | 
|  | 297      * Returns time ticks of first event. | 
|  | 298      */ | 
|  | 299     getStartTicks: function() { | 
|  | 300       return this.entries_[0].time; | 
|  | 301     }, | 
|  | 302 | 
|  | 303     /** | 
|  | 304      * Returns time of last event if inactive.  Returns current time otherwise. | 
|  | 305      * Returned time is a "time ticks" value. | 
|  | 306      */ | 
|  | 307     getEndTicks: function() { | 
|  | 308       if (!this.isInactive_) | 
|  | 309         return timeutil.getCurrentTimeTicks(); | 
|  | 310       return this.entries_[this.entries_.length - 1].time; | 
|  | 311     }, | 
|  | 312 | 
|  | 313     /** | 
|  | 314      * Returns the time between the first and last events with a matching | 
|  | 315      * source ID.  If source is still active, uses the current time for the | 
|  | 316      * last event. | 
|  | 317      */ | 
|  | 318     getDuration: function() { | 
|  | 319       var startTime = this.getStartTicks(); | 
|  | 320       var endTime = this.getEndTicks(); | 
|  | 321       return endTime - startTime; | 
|  | 322     }, | 
|  | 323 | 
|  | 324     /** | 
|  | 325      * Prints descriptive text about |entries_| to a new node added to the end | 
|  | 326      * of |parent|. | 
|  | 327      */ | 
|  | 328     printAsText: function(parent) { | 
|  | 329       var tablePrinter = this.createTablePrinter(); | 
|  | 330 | 
|  | 331       // Format the table for fixed-width text. | 
|  | 332       tablePrinter.toText(0, parent); | 
|  | 333     }, | 
|  | 334 | 
|  | 335     /** | 
|  | 336      * Creates a table printer for the SourceEntry. | 
|  | 337      */ | 
|  | 338     createTablePrinter: function() { | 
|  | 339       return createLogEntryTablePrinter( | 
|  | 340           this.entries_, | 
|  | 341           SourceTracker.getInstance().getPrivacyStripping(), | 
|  | 342           SourceTracker.getInstance().getUseRelativeTimes() ? | 
|  | 343               timeutil.getBaseTime() : 0, | 
|  | 344           Constants.clientInfo.numericDate); | 
|  | 345     }, | 
|  | 346   }; | 
|  | 347 | 
|  | 348   return SourceEntry; | 
|  | 349 })(); | 
|  | 350 | 
| OLD | NEW | 
|---|