17
17
#import " Crashlytics/Crashlytics/Controllers/FIRCLSManagerData.h"
18
18
#import " Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h"
19
19
#import " Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h"
20
- #import " Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h"
21
20
#import " Crashlytics/Crashlytics/Models/FIRCLSFileManager.h"
22
21
#import " Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h"
22
+ #import " Crashlytics/Crashlytics/Private/FIRCrashlyticsReport_Private.h"
23
+ #import " Crashlytics/Crashlytics/Public/FirebaseCrashlytics/FIRCrashlyticsReport.h"
23
24
24
25
@interface FIRCLSExistingReportManager ()
25
26
26
27
@property (nonatomic , strong ) FIRCLSFileManager *fileManager;
27
28
@property (nonatomic , strong ) NSOperationQueue *operationQueue;
28
29
@property (nonatomic , strong ) FIRCLSReportUploader *reportUploader;
29
30
31
+ // This list of active reports excludes the brand new active report that will be created this run of
32
+ // the app.
33
+ @property (nonatomic , strong ) NSArray *existingUnemptyActiveReportPaths;
34
+ @property (nonatomic , strong ) NSArray *processingReportPaths;
35
+ @property (nonatomic , strong ) NSArray *preparedReportPaths;
36
+
30
37
@end
31
38
32
39
@implementation FIRCLSExistingReportManager
@@ -45,51 +52,106 @@ - (instancetype)initWithManagerData:(FIRCLSManagerData *)managerData
45
52
return self;
46
53
}
47
54
48
- /* *
49
- * Returns the number of unsent reports on the device, including the ones passed in.
50
- */
51
- - (int )unsentReportsCountWithPreexisting : (NSArray <NSString *> *)paths {
52
- int count = [self countSubmittableAndDeleteUnsubmittableReportPaths: paths];
55
+ NSInteger compareOlder (FIRCLSInternalReport *reportA,
56
+ FIRCLSInternalReport *reportB,
57
+ void *context) {
58
+ return [reportA.dateCreated compare: reportB.dateCreated];
59
+ }
60
+
61
+ - (void )collectExistingReports {
62
+ self.existingUnemptyActiveReportPaths =
63
+ [self getUnemptyExistingActiveReportsAndDeleteEmpty: self .fileManager.activePathContents];
64
+ self.processingReportPaths = self.fileManager .processingPathContents ;
65
+ self.preparedReportPaths = self.fileManager .preparedPathContents ;
66
+ }
67
+
68
+ - (FIRCrashlyticsReport *)newestUnsentReport {
69
+ if (self.unsentReportsCount <= 0 ) {
70
+ return nil ;
71
+ }
72
+
73
+ NSMutableArray <NSString *> *allReportPaths =
74
+ [NSMutableArray arrayWithArray: self .existingUnemptyActiveReportPaths];
53
75
54
- count += self.fileManager .processingPathContents .count ;
55
- count += self.fileManager .preparedPathContents .count ;
56
- return count;
76
+ NSMutableArray <FIRCLSInternalReport *> *validReports = [NSMutableArray array ];
77
+ for (NSString *path in allReportPaths) {
78
+ FIRCLSInternalReport *_Nullable report = [FIRCLSInternalReport reportWithPath: path];
79
+ if (!report) {
80
+ continue ;
81
+ }
82
+ [validReports addObject: report];
83
+ }
84
+
85
+ [validReports sortUsingFunction: compareOlder context: nil ];
86
+
87
+ FIRCLSInternalReport *_Nullable internalReport = [validReports lastObject ];
88
+ return [[FIRCrashlyticsReport alloc ] initWithInternalReport: internalReport];
89
+ }
90
+
91
+ - (NSUInteger )unsentReportsCount {
92
+ // There are nuances about why we only count active reports.
93
+ // See the header comment for more information.
94
+ return self.existingUnemptyActiveReportPaths .count ;
57
95
}
58
96
59
- - (int ) countSubmittableAndDeleteUnsubmittableReportPaths : (NSArray *)reportPaths {
60
- int count = 0 ;
97
+ - (NSArray *) getUnemptyExistingActiveReportsAndDeleteEmpty : (NSArray *)reportPaths {
98
+ NSMutableArray *unemptyReports = [ NSMutableArray array ] ;
61
99
for (NSString *path in reportPaths) {
62
100
FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath: path];
63
- if ([report needsToBeSubmitted ]) {
64
- count++ ;
101
+ if ([report hasAnyEvents ]) {
102
+ [unemptyReports addObject: path] ;
65
103
} else {
66
104
[self .operationQueue addOperationWithBlock: ^{
67
- [self ->_fileManager removeItemAtPath: path];
105
+ [self .fileManager removeItemAtPath: path];
68
106
}];
69
107
}
70
108
}
71
- return count ;
109
+ return unemptyReports ;
72
110
}
73
111
74
- - (void )processExistingReportPaths : (NSArray *)reportPaths
75
- dataCollectionToken : (FIRCLSDataCollectionToken *)dataCollectionToken
112
+ - (void )sendUnsentReportsWithToken : (FIRCLSDataCollectionToken *)dataCollectionToken
76
113
asUrgent : (BOOL )urgent {
77
- for (NSString *path in reportPaths ) {
114
+ for (NSString *path in self. existingUnemptyActiveReportPaths ) {
78
115
[self processExistingActiveReportPath: path
79
116
dataCollectionToken: dataCollectionToken
80
117
asUrgent: urgent];
81
118
}
119
+
120
+ // deal with stuff in processing more carefully - do not process again
121
+ [self .operationQueue addOperationWithBlock: ^{
122
+ for (NSString *path in self.processingReportPaths ) {
123
+ FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath: path];
124
+ [self .reportUploader prepareAndSubmitReport: report
125
+ dataCollectionToken: dataCollectionToken
126
+ asUrgent: NO
127
+ withProcessing: NO ];
128
+ }
129
+ }];
130
+
131
+ // Because this could happen quite a bit after the inital set of files was
132
+ // captured, some could be completed (deleted). So, just double-check to make sure
133
+ // the file still exists.
134
+ [self .operationQueue addOperationWithBlock: ^{
135
+ for (NSString *path in self.preparedReportPaths ) {
136
+ if (![[self .fileManager underlyingFileManager ] fileExistsAtPath: path]) {
137
+ continue ;
138
+ }
139
+ [self .reportUploader uploadPackagedReportAtPath: path
140
+ dataCollectionToken: dataCollectionToken
141
+ asUrgent: NO ];
142
+ }
143
+ }];
82
144
}
83
145
84
146
- (void )processExistingActiveReportPath : (NSString *)path
85
147
dataCollectionToken : (FIRCLSDataCollectionToken *)dataCollectionToken
86
148
asUrgent : (BOOL )urgent {
87
149
FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath: path];
88
150
89
- // TODO: needsToBeSubmitted should really be called on the background queue.
90
- if (![report needsToBeSubmitted ]) {
151
+ // TODO: hasAnyEvents should really be called on the background queue.
152
+ if (![report hasAnyEvents ]) {
91
153
[self .operationQueue addOperationWithBlock: ^{
92
- [self ->_fileManager removeItemAtPath: path];
154
+ [self .fileManager removeItemAtPath: path];
93
155
}];
94
156
95
157
return ;
@@ -104,11 +166,6 @@ - (void)processExistingActiveReportPath:(NSString *)path
104
166
return ;
105
167
}
106
168
107
- [self submitReport: report dataCollectionToken: dataCollectionToken];
108
- }
109
-
110
- - (void )submitReport : (FIRCLSInternalReport *)report
111
- dataCollectionToken : (FIRCLSDataCollectionToken *)dataCollectionToken {
112
169
[self .operationQueue addOperationWithBlock: ^{
113
170
[self .reportUploader prepareAndSubmitReport: report
114
171
dataCollectionToken: dataCollectionToken
@@ -117,61 +174,17 @@ - (void)submitReport:(FIRCLSInternalReport *)report
117
174
}];
118
175
}
119
176
120
- // This is the side-effect of calling deleteUnsentReports, or collect_reports setting
121
- // being false
122
- - (void )deleteUnsentReportsWithPreexisting : (NSArray *)preexistingReportPaths {
123
- [self removeExistingReportPaths: preexistingReportPaths];
124
- [self removeExistingReportPaths: self .fileManager.processingPathContents];
125
- [self removeExistingReportPaths: self .fileManager.preparedPathContents];
126
- }
177
+ - (void )deleteUnsentReports {
178
+ NSArray <NSString *> *reportPaths = @[];
179
+ reportPaths = [reportPaths arrayByAddingObjectsFromArray: self .existingUnemptyActiveReportPaths];
180
+ reportPaths = [reportPaths arrayByAddingObjectsFromArray: self .processingReportPaths];
181
+ reportPaths = [reportPaths arrayByAddingObjectsFromArray: self .preparedReportPaths];
127
182
128
- - (void )removeExistingReportPaths : (NSArray *)reportPaths {
129
183
[self .operationQueue addOperationWithBlock: ^{
130
184
for (NSString *path in reportPaths) {
131
185
[self .fileManager removeItemAtPath: path];
132
186
}
133
187
}];
134
188
}
135
189
136
- - (void )handleContentsInOtherReportingDirectoriesWithToken : (FIRCLSDataCollectionToken *)token {
137
- [self handleExistingFilesInProcessingWithToken: token];
138
- [self handleExistingFilesInPreparedWithToken: token];
139
- }
140
-
141
- - (void )handleExistingFilesInProcessingWithToken : (FIRCLSDataCollectionToken *)token {
142
- NSArray *processingPaths = _fileManager.processingPathContents ;
143
-
144
- // deal with stuff in processing more carefully - do not process again
145
- [self .operationQueue addOperationWithBlock: ^{
146
- for (NSString *path in processingPaths) {
147
- FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath: path];
148
- [self .reportUploader prepareAndSubmitReport: report
149
- dataCollectionToken: token
150
- asUrgent: NO
151
- withProcessing: NO ];
152
- }
153
- }];
154
- }
155
-
156
- - (void )handleExistingFilesInPreparedWithToken : (FIRCLSDataCollectionToken *)token {
157
- NSArray *preparedPaths = self.fileManager .preparedPathContents ;
158
- [self .operationQueue addOperationWithBlock: ^{
159
- [self uploadPreexistingFiles: preparedPaths withToken: token];
160
- }];
161
- }
162
-
163
- - (void )uploadPreexistingFiles : (NSArray *)files withToken : (FIRCLSDataCollectionToken *)token {
164
- // Because this could happen quite a bit after the inital set of files was
165
- // captured, some could be completed (deleted). So, just double-check to make sure
166
- // the file still exists.
167
-
168
- for (NSString *path in files) {
169
- if (![[_fileManager underlyingFileManager ] fileExistsAtPath: path]) {
170
- continue ;
171
- }
172
-
173
- [self .reportUploader uploadPackagedReportAtPath: path dataCollectionToken: token asUrgent: NO ];
174
- }
175
- }
176
-
177
190
@end
0 commit comments