2 * Copyright 2017 Google
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #import "FIRMessagingUtilities.h"
19 #import "Protos/GtalkCore.pbobjc.h"
21 #import "FIRMessagingLogger.h"
23 #import <GoogleUtilities/GULAppEnvironmentUtil.h>
25 // Convert the macro to a string
26 #define STR_EXPAND(x) #x
27 #define STR(x) STR_EXPAND(x)
29 static const uint64_t kBytesToMegabytesDivisor = 1024 * 1024LL;
31 #pragma mark - Protocol Buffers
33 FIRMessagingProtoTag FIRMessagingGetTagForProto(GPBMessage *proto) {
34 if ([proto isKindOfClass:[GtalkHeartbeatPing class]]) {
35 return kFIRMessagingProtoTagHeartbeatPing;
36 } else if ([proto isKindOfClass:[GtalkHeartbeatAck class]]) {
37 return kFIRMessagingProtoTagHeartbeatAck;
38 } else if ([proto isKindOfClass:[GtalkLoginRequest class]]) {
39 return kFIRMessagingProtoTagLoginRequest;
40 } else if ([proto isKindOfClass:[GtalkLoginResponse class]]) {
41 return kFIRMessagingProtoTagLoginResponse;
42 } else if ([proto isKindOfClass:[GtalkClose class]]) {
43 return kFIRMessagingProtoTagClose;
44 } else if ([proto isKindOfClass:[GtalkIqStanza class]]) {
45 return kFIRMessagingProtoTagIqStanza;
46 } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) {
47 return kFIRMessagingProtoTagDataMessageStanza;
49 return kFIRMessagingProtoTagInvalid;
52 Class FIRMessagingGetClassForTag(FIRMessagingProtoTag tag) {
54 case kFIRMessagingProtoTagHeartbeatPing:
55 return GtalkHeartbeatPing.class;
56 case kFIRMessagingProtoTagHeartbeatAck:
57 return GtalkHeartbeatAck.class;
58 case kFIRMessagingProtoTagLoginRequest:
59 return GtalkLoginRequest.class;
60 case kFIRMessagingProtoTagLoginResponse:
61 return GtalkLoginResponse.class;
62 case kFIRMessagingProtoTagClose:
63 return GtalkClose.class;
64 case kFIRMessagingProtoTagIqStanza:
65 return GtalkIqStanza.class;
66 case kFIRMessagingProtoTagDataMessageStanza:
67 return GtalkDataMessageStanza.class;
68 case kFIRMessagingProtoTagInvalid:
76 NSString *FIRMessagingGetRmq2Id(GPBMessage *proto) {
77 if ([proto isKindOfClass:[GtalkIqStanza class]]) {
78 if (((GtalkIqStanza *)proto).hasPersistentId) {
79 return ((GtalkIqStanza *)proto).persistentId;
81 } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) {
82 if (((GtalkDataMessageStanza *)proto).hasPersistentId) {
83 return ((GtalkDataMessageStanza *)proto).persistentId;
89 void FIRMessagingSetRmq2Id(GPBMessage *proto, NSString *pID) {
90 if ([proto isKindOfClass:[GtalkIqStanza class]]) {
91 ((GtalkIqStanza *)proto).persistentId = pID;
92 } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) {
93 ((GtalkDataMessageStanza *)proto).persistentId = pID;
97 int FIRMessagingGetLastStreamId(GPBMessage *proto) {
98 if ([proto isKindOfClass:[GtalkIqStanza class]]) {
99 if (((GtalkIqStanza *)proto).hasLastStreamIdReceived) {
100 return ((GtalkIqStanza *)proto).lastStreamIdReceived;
102 } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) {
103 if (((GtalkDataMessageStanza *)proto).hasLastStreamIdReceived) {
104 return ((GtalkDataMessageStanza *)proto).lastStreamIdReceived;
106 } else if ([proto isKindOfClass:[GtalkHeartbeatPing class]]) {
107 if (((GtalkHeartbeatPing *)proto).hasLastStreamIdReceived) {
108 return ((GtalkHeartbeatPing *)proto).lastStreamIdReceived;
110 } else if ([proto isKindOfClass:[GtalkHeartbeatAck class]]) {
111 if (((GtalkHeartbeatAck *)proto).hasLastStreamIdReceived) {
112 return ((GtalkHeartbeatAck *)proto).lastStreamIdReceived;
118 void FIRMessagingSetLastStreamId(GPBMessage *proto, int sid) {
119 if ([proto isKindOfClass:[GtalkIqStanza class]]) {
120 ((GtalkIqStanza *)proto).lastStreamIdReceived = sid;
121 } else if ([proto isKindOfClass:[GtalkDataMessageStanza class]]) {
122 ((GtalkDataMessageStanza *)proto).lastStreamIdReceived = sid;
123 } else if ([proto isKindOfClass:[GtalkHeartbeatPing class]]) {
124 ((GtalkHeartbeatPing *)proto).lastStreamIdReceived = sid;
125 } else if ([proto isKindOfClass:[GtalkHeartbeatAck class]]) {
126 ((GtalkHeartbeatAck *)proto).lastStreamIdReceived = sid;
132 int64_t FIRMessagingCurrentTimestampInSeconds(void) {
133 return (int64_t)[[NSDate date] timeIntervalSince1970];
136 int64_t FIRMessagingCurrentTimestampInMilliseconds(void) {
137 return (int64_t)(FIRMessagingCurrentTimestampInSeconds() * 1000.0);
140 #pragma mark - App Info
142 NSString *FIRMessagingCurrentAppVersion(void) {
143 NSString *version = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"];
144 if (![version length]) {
145 FIRMessagingLoggerError(kFIRMessagingMessageCodeUtilities000,
146 @"Could not find current app version");
152 NSString *FIRMessagingAppIdentifier(void) {
153 return [[NSBundle mainBundle] bundleIdentifier];
156 uint64_t FIRMessagingGetFreeDiskSpaceInMB(void) {
158 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
160 NSDictionary *attributesMap =
161 [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject]
164 uint64_t totalSizeInBytes __unused = [attributesMap[NSFileSystemSize] longLongValue];
165 uint64_t freeSizeInBytes = [attributesMap[NSFileSystemFreeSize] longLongValue];
166 FIRMessagingLoggerDebug(
167 kFIRMessagingMessageCodeUtilities001, @"Device has capacity %llu MB with %llu MB free.",
168 totalSizeInBytes / kBytesToMegabytesDivisor, freeSizeInBytes / kBytesToMegabytesDivisor);
169 return ((double)freeSizeInBytes) / kBytesToMegabytesDivisor;
171 FIRMessagingLoggerError(kFIRMessagingMessageCodeUtilities002,
172 @"Error in retreiving device's free memory %@", error);
177 UIApplication *FIRMessagingUIApplication(void) {
178 static Class applicationClass = nil;
179 // iOS App extensions should not call [UIApplication sharedApplication], even if UIApplication
181 if (![GULAppEnvironmentUtil isAppExtension]) {
182 Class cls = NSClassFromString(@"UIApplication");
183 if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) {
184 applicationClass = cls;
187 return [applicationClass sharedApplication];