Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// Copyright 2019 Google
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
 
15
// TODO: Remove this class after the uploading of reports via GoogleDataTransport is no longer an
16
// experiment
17
 
18
#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h"
19
 
20
#import "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h"
21
#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h"
22
#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h"
23
 
24
NSString *const FIRCLSCustomFatalIndicatorFile = @"custom_fatal.clsrecord";
25
NSString *const FIRCLSReportBinaryImageFile = @"binary_images.clsrecord";
26
NSString *const FIRCLSReportExceptionFile = @"exception.clsrecord";
27
NSString *const FIRCLSReportCustomExceptionAFile = @"custom_exception_a.clsrecord";
28
NSString *const FIRCLSReportCustomExceptionBFile = @"custom_exception_b.clsrecord";
29
NSString *const FIRCLSReportSignalFile = @"signal.clsrecord";
30
NSString *const FIRCLSMetricKitFatalReportFile = @"metric_kit_fatal.clsrecord";
31
NSString *const FIRCLSMetricKitNonfatalReportFile = @"metric_kit_nonfatal.clsrecord";
32
#if CLS_MACH_EXCEPTION_SUPPORTED
33
NSString *const FIRCLSReportMachExceptionFile = @"mach_exception.clsrecord";
34
#endif
35
NSString *const FIRCLSReportMetadataFile = @"metadata.clsrecord";
36
NSString *const FIRCLSReportErrorAFile = @"errors_a.clsrecord";
37
NSString *const FIRCLSReportErrorBFile = @"errors_b.clsrecord";
38
NSString *const FIRCLSReportLogAFile = @"log_a.clsrecord";
39
NSString *const FIRCLSReportLogBFile = @"log_b.clsrecord";
40
NSString *const FIRCLSReportInternalIncrementalKVFile = @"internal_incremental_kv.clsrecord";
41
NSString *const FIRCLSReportInternalCompactedKVFile = @"internal_compacted_kv.clsrecord";
42
NSString *const FIRCLSReportUserIncrementalKVFile = @"user_incremental_kv.clsrecord";
43
NSString *const FIRCLSReportUserCompactedKVFile = @"user_compacted_kv.clsrecord";
44
 
45
@interface FIRCLSInternalReport () {
46
  NSString *_identifier;
47
  NSString *_path;
48
  NSArray *_metadataSections;
49
}
50
 
51
@end
52
 
53
@implementation FIRCLSInternalReport
54
 
55
+ (instancetype)reportWithPath:(NSString *)path {
56
  return [[self alloc] initWithPath:path];
57
}
58
 
59
#pragma mark - Initialization
60
/**
61
 * Initializes a new report, i.e. one without metadata on the file system yet.
62
 */
63
- (instancetype)initWithPath:(NSString *)path executionIdentifier:(NSString *)identifier {
64
  self = [super init];
65
  if (!self) {
66
    return self;
67
  }
68
 
69
  if (!path || !identifier) {
70
    return nil;
71
  }
72
 
73
  [self setPath:path];
74
 
75
  _identifier = [identifier copy];
76
 
77
  return self;
78
}
79
 
80
/**
81
 * Initializes a pre-existing report, i.e. one with metadata on the file system.
82
 */
83
- (instancetype)initWithPath:(NSString *)path {
84
  NSString *metadataPath = [path stringByAppendingPathComponent:FIRCLSReportMetadataFile];
85
  NSString *identifier = [[[[self.class readFIRCLSFileAtPath:metadataPath] objectAtIndex:0]
86
      objectForKey:@"identity"] objectForKey:@"session_id"];
87
  if (!identifier) {
88
    FIRCLSErrorLog(@"Unable to read identifier at path %@", path);
89
  }
90
  return [self initWithPath:path executionIdentifier:identifier];
91
}
92
 
93
#pragma mark - Path Helpers
94
- (NSString *)directoryName {
95
  return self.path.lastPathComponent;
96
}
97
 
98
- (NSString *)pathForContentFile:(NSString *)name {
99
  return [[self path] stringByAppendingPathComponent:name];
100
}
101
 
102
- (NSString *)metadataPath {
103
  return [[self path] stringByAppendingPathComponent:FIRCLSReportMetadataFile];
104
}
105
 
106
- (NSString *)binaryImagePath {
107
  return [self pathForContentFile:FIRCLSReportBinaryImageFile];
108
}
109
 
110
#pragma mark - Processing Methods
111
- (BOOL)hasAnyEvents {
112
  NSArray *reportFiles = @[
113
    FIRCLSReportExceptionFile, FIRCLSReportSignalFile, FIRCLSReportCustomExceptionAFile,
114
    FIRCLSReportCustomExceptionBFile, FIRCLSMetricKitFatalReportFile,
115
    FIRCLSMetricKitNonfatalReportFile,
116
#if CLS_MACH_EXCEPTION_SUPPORTED
117
    FIRCLSReportMachExceptionFile,
118
#endif
119
    FIRCLSReportErrorAFile, FIRCLSReportErrorBFile
120
  ];
121
  return [self checkExistenceOfAtLeastOneFileInArray:reportFiles];
122
}
123
 
124
// These are purposefully in order of precedence. If duplicate data exists
125
// in any crash file, the exception file's contents take precedence over the
126
// rest, for example
127
//
128
// Do not change the order of this.
129
//
130
+ (NSArray *)crashFileNames {
131
  static NSArray *files;
132
  static dispatch_once_t onceToken;
133
  dispatch_once(&onceToken, ^{
134
    files = @[
135
      FIRCLSReportExceptionFile,
136
#if CLS_MACH_EXCEPTION_SUPPORTED
137
      FIRCLSReportMachExceptionFile,
138
#endif
139
      FIRCLSReportSignalFile, FIRCLSMetricKitFatalReportFile, FIRCLSCustomFatalIndicatorFile
140
    ];
141
  });
142
  return files;
143
}
144
 
145
- (BOOL)isCrash {
146
  NSArray *crashFiles = [FIRCLSInternalReport crashFileNames];
147
  return [self checkExistenceOfAtLeastOneFileInArray:crashFiles];
148
}
149
 
150
- (BOOL)checkExistenceOfAtLeastOneFileInArray:(NSArray *)files {
151
  NSFileManager *manager = [NSFileManager defaultManager];
152
 
153
  for (NSString *fileName in files) {
154
    NSString *path = [self pathForContentFile:fileName];
155
 
156
    if ([manager fileExistsAtPath:path]) {
157
      return YES;
158
    }
159
  }
160
 
161
  return NO;
162
}
163
 
164
- (void)enumerateSymbolicatableFilesInContent:(void (^)(NSString *path))block {
165
  for (NSString *fileName in [FIRCLSInternalReport crashFileNames]) {
166
    NSString *path = [self pathForContentFile:fileName];
167
 
168
    block(path);
169
  }
170
}
171
 
172
#pragma mark - Metadata helpers
173
+ (NSArray *)readFIRCLSFileAtPath:(NSString *)path {
174
  NSArray *sections = FIRCLSFileReadSections([path fileSystemRepresentation], false, nil);
175
 
176
  if ([sections count] == 0) {
177
    return nil;
178
  }
179
 
180
  return sections;
181
}
182
 
183
- (NSArray *)metadataSections {
184
  if (!_metadataSections) {
185
    _metadataSections = [self.class readFIRCLSFileAtPath:self.metadataPath];
186
  }
187
  return _metadataSections;
188
}
189
 
190
- (NSString *)orgID {
191
  return
192
      [[[self.metadataSections objectAtIndex:0] objectForKey:@"identity"] objectForKey:@"org_id"];
193
}
194
 
195
- (NSDictionary *)customKeys {
196
  return nil;
197
}
198
 
199
- (NSString *)bundleVersion {
200
  return [[[self.metadataSections objectAtIndex:2] objectForKey:@"application"]
201
      objectForKey:@"build_version"];
202
}
203
 
204
- (NSString *)bundleShortVersionString {
205
  return [[[self.metadataSections objectAtIndex:2] objectForKey:@"application"]
206
      objectForKey:@"display_version"];
207
}
208
 
209
- (NSDate *)dateCreated {
210
  NSUInteger unixtime = [[[[self.metadataSections objectAtIndex:0] objectForKey:@"identity"]
211
      objectForKey:@"started_at"] unsignedIntegerValue];
212
 
213
  return [NSDate dateWithTimeIntervalSince1970:unixtime];
214
}
215
 
216
- (NSDate *)crashedOnDate {
217
  if (!self.isCrash) {
218
    return nil;
219
  }
220
 
221
#if CLS_MACH_EXCEPTION_SUPPORTED
222
  // try the mach exception first, because it is more common
223
  NSDate *date = [self timeFromCrashContentFile:FIRCLSReportMachExceptionFile
224
                                    sectionName:@"mach_exception"];
225
  if (date) {
226
    return date;
227
  }
228
#endif
229
 
230
  return [self timeFromCrashContentFile:FIRCLSReportSignalFile sectionName:@"signal"];
231
}
232
 
233
- (NSDate *)timeFromCrashContentFile:(NSString *)fileName sectionName:(NSString *)sectionName {
234
  // This works because both signal and mach exception files have the same structure to extract
235
  // the "time" component
236
  NSString *path = [self pathForContentFile:fileName];
237
 
238
  NSNumber *timeValue = [[[[self.class readFIRCLSFileAtPath:path] objectAtIndex:0]
239
      objectForKey:sectionName] objectForKey:@"time"];
240
  if (timeValue == nil) {
241
    return nil;
242
  }
243
 
244
  return [NSDate dateWithTimeIntervalSince1970:[timeValue unsignedIntegerValue]];
245
}
246
 
247
- (NSString *)OSVersion {
248
  return [[[self.metadataSections objectAtIndex:1] objectForKey:@"host"]
249
      objectForKey:@"os_display_version"];
250
}
251
 
252
- (NSString *)OSBuildVersion {
253
  return [[[self.metadataSections objectAtIndex:1] objectForKey:@"host"]
254
      objectForKey:@"os_build_version"];
255
}
256
 
257
@end