Skip to content

Commit e66c912

Browse files
committed
Clean up generated code.
1 parent 5c40559 commit e66c912

File tree

2 files changed

+121
-47
lines changed

2 files changed

+121
-47
lines changed

analytics/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ set(ios_SRCS
7878
set(stub_SRCS
7979
src/analytics_stub.cc)
8080

81+
# Source files used by the stub implementation.
82+
set(desktop_SRCS
83+
src/analytics_desktop.cc
84+
src/windows/analytics_dynamic.c)
85+
8186
if(ANDROID)
8287
set(analytics_platform_SRCS
8388
"${android_SRCS}")
@@ -86,7 +91,7 @@ elseif(IOS)
8691
"${ios_SRCS}")
8792
else()
8893
set(analytics_platform_SRCS
89-
"${stub_SRCS}")
94+
"${desktop_SRCS}")
9095
endif()
9196

9297
add_library(firebase_analytics STATIC

analytics/src/analytics_desktop.cc

Lines changed: 115 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,48 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include "analytics/src/windows/analytics_windows.h"
15+
#include "analytics/src/windows/analytics_dynamic.h"
1616
#include "app/src/include/firebase/app.h"
1717
#include "analytics/src/include/firebase/analytics.h"
18-
#include "analytics/src/common/analytics_common.h"
19-
#include "common/src/include/firebase/variant.h"
18+
#include "analytics/src/analytics_common.h"
19+
#include "app/src/include/firebase/variant.h"
2020
#include "app/src/include/firebase/future.h"
2121
#include "app/src/include/firebase/log.h"
2222
#include "app/src/future_manager.h" // For FutureData
2323

2424
#include <vector>
2525
#include <string>
2626
#include <map>
27+
#include <sstream>
28+
29+
#if defined(_WIN32)
30+
#include <windows.h>
31+
#endif // defined(_WIN32)
2732

2833
namespace firebase {
2934
namespace analytics {
3035

36+
#if defined(_WIN32)
37+
#define ANALYTICS_DLL_DEFAULT_FILENAME "analytics_win.dll"
38+
const char *g_analytics_dll_filename = nullptr;
39+
static HMODULE g_analytics_dll = 0;
40+
41+
void SetAnalyticsLibraryPath(const char* path) {
42+
if (g_analytics_dll_filename) {
43+
delete g_analytics_dll_filename;
44+
g_analytics_dll_filename = nullptr;
45+
}
46+
if (path) {
47+
g_analytics_dll_filename = new char[strlen(path)+1];
48+
strcpy(g_analytics_dll_filename, path);
49+
}
50+
}
51+
#endif
52+
3153
// Future data for analytics.
3254
// This is initialized in `Initialize()` and cleaned up in `Terminate()`.
33-
static FutureData* g_future_data = nullptr;
55+
static bool g_initialized = false;
56+
static int g_fake_instance_id = 0;
3457

3558
// Initializes the Analytics desktop API.
3659
// This function must be called before any other Analytics methods.
@@ -40,22 +63,48 @@ void Initialize(const App& app) {
4063
// with other Firebase platforms.
4164
(void)app;
4265

43-
if (g_future_data) {
44-
LogWarning("Analytics: Initialize() called when already initialized.");
45-
} else {
46-
g_future_data = new FutureData(internal::kAnalyticsFnCount);
66+
g_initialized = true;
67+
internal::RegisterTerminateOnDefaultAppDestroy();
68+
internal::FutureData::Create();
69+
g_fake_instance_id = 0;
70+
71+
#if defined(_WIN32)
72+
if (!g_analytics_dll) {
73+
const char* dll_filename = g_analytics_dll_filename;
74+
if (!dll_filename) dll_filename = ANALYTICS_DLL_DEFAULT_FILENAME;
75+
auto wFilename = toUtf16(dll_filename);
76+
g_analytics_dll = LoadLibraryW(wFilename);
77+
if (g_analytics_dll) {
78+
LogInfo("Successfully loaded Analytics DLL %s", g_analytics_dll_filename);
79+
} else {
80+
LogError("Failed to load Analytics DLL %s", g_analytics_dll_filename);
81+
}
4782
}
83+
FirebaseAnalytics_LoadAnalyticsFunctions(g_analytics_dll);
84+
#endif
4885
}
4986

87+
namespace internal {
88+
89+
// Determine whether the analytics module is initialized.
90+
bool IsInitialized() { return g_initialized; }
91+
92+
} // namespace internal
93+
5094
// Terminates the Analytics desktop API.
5195
// Call this function when Analytics is no longer needed to free up resources.
5296
void Terminate() {
53-
if (g_future_data) {
54-
delete g_future_data;
55-
g_future_data = nullptr;
56-
} else {
57-
LogWarning("Analytics: Terminate() called when not initialized or already terminated.");
97+
#if defined(_WIN32)
98+
FirebaseAnalytics_UnloadAnalyticsFunctions();
99+
if (g_analytics_dll) {
100+
FreeLibrary(g_analytics_dll);
101+
g_analytics_dll = 0;
58102
}
103+
#endif
104+
105+
internal::FutureData::Destroy();
106+
internal::UnregisterTerminateOnDefaultAppDestroy();
107+
g_initialized = false;
59108
}
60109

61110
static void ConvertParametersToGAParams(
@@ -95,8 +144,8 @@ static void ConvertParametersToGAParams(
95144
// is set as the property's value.
96145
// All these GoogleAnalytics_Items are then bundled into a single
97146
// GoogleAnalytics_ItemVector, which is associated with the original parameter's name.
98-
const std::map<std::string, firebase::Variant>& user_map =
99-
param.value.map_value();
147+
const std::map<firebase::Variant, firebase::Variant>& user_map =
148+
param.value.map();
100149
if (user_map.empty()) {
101150
LogWarning("Analytics: Parameter '%s' is an empty map. Skipping.", param.name);
102151
continue; // Skip this parameter
@@ -111,7 +160,12 @@ static void ConvertParametersToGAParams(
111160

112161
bool item_vector_populated = false;
113162
for (const auto& entry : user_map) {
114-
const std::string& key_from_map = entry.first;
163+
const firebase::Variant& key_variant = entry.first;
164+
if (!key_variant.is_string()) {
165+
LogError("Analytics: Non-string map key found. Skipping.");
166+
continue;
167+
}
168+
const std::string& key_from_map = key_variant.mutable_string();
115169
const firebase::Variant& value_from_map = entry.second;
116170

117171
GoogleAnalytics_Item* c_item = GoogleAnalytics_Item_Create();
@@ -164,6 +218,8 @@ static void ConvertParametersToGAParams(
164218
void LogEvent(const char* name,
165219
const Parameter* parameters,
166220
size_t number_of_parameters) {
221+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
222+
167223
if (name == nullptr || name[0] == '\0') {
168224
LogError("Analytics: Event name cannot be null or empty.");
169225
return;
@@ -196,6 +252,8 @@ void LogEvent(const char* name,
196252
// characters long. Setting the value to `nullptr` or an empty string will
197253
// clear the user property. Must be UTF-8 encoded if not nullptr.
198254
void SetUserProperty(const char* name, const char* property) {
255+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
256+
199257
if (name == nullptr || name[0] == '\0') {
200258
LogError("Analytics: User property name cannot be null or empty.");
201259
return;
@@ -216,6 +274,7 @@ void SetUserProperty(const char* name, const char* property) {
216274
// characters long, and UTF-8 encoded. Setting user_id to `nullptr` removes
217275
// the user ID.
218276
void SetUserId(const char* user_id) {
277+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
219278
// The C API GoogleAnalytics_SetUserId allows user_id to be nullptr to clear the user ID.
220279
// The C API documentation also mentions: "The user ID must be non-empty and
221280
// no more than 256 characters long".
@@ -235,18 +294,24 @@ void SetUserId(const char* user_id) {
235294
//
236295
// @param[in] enabled A flag that enables or disables Analytics collection.
237296
void SetAnalyticsCollectionEnabled(bool enabled) {
297+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
298+
238299
GoogleAnalytics_SetAnalyticsCollectionEnabled(enabled);
239300
}
240301

241302
// Clears all analytics data for this app from the device and resets the app
242303
// instance ID.
243304
void ResetAnalyticsData() {
305+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
306+
244307
GoogleAnalytics_ResetAnalyticsData();
245308
}
246309

247310
// --- Stub Implementations for Unsupported Features ---
248311

249312
void SetConsent(const std::map<ConsentType, ConsentStatus>& consent_settings) {
313+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
314+
250315
// Not supported by the Windows C API.
251316
(void)consent_settings; // Mark as unused
252317
LogWarning("Analytics: SetConsent() is not supported and has no effect on Desktop.");
@@ -298,75 +363,79 @@ void LogEvent(const char* name, const char* parameter_name,
298363

299364
void InitiateOnDeviceConversionMeasurementWithEmailAddress(
300365
const char* email_address) {
366+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
301367
(void)email_address;
302368
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithEmailAddress() is not supported and has no effect on Desktop.");
303369
}
304370

305371
void InitiateOnDeviceConversionMeasurementWithPhoneNumber(
306372
const char* phone_number) {
373+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
307374
(void)phone_number;
308375
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithPhoneNumber() is not supported and has no effect on Desktop.");
309376
}
310377

311378
void InitiateOnDeviceConversionMeasurementWithHashedEmailAddress(
312379
std::vector<unsigned char> hashed_email_address) {
380+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
313381
(void)hashed_email_address;
314382
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithHashedEmailAddress() is not supported and has no effect on Desktop.");
315383
}
316384

317385
void InitiateOnDeviceConversionMeasurementWithHashedPhoneNumber(
318386
std::vector<unsigned char> hashed_phone_number) {
387+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
319388
(void)hashed_phone_number;
320389
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithHashedPhoneNumber() is not supported and has no effect on Desktop.");
321390
}
322391

323392
void SetSessionTimeoutDuration(int64_t milliseconds) {
393+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
324394
(void)milliseconds;
325395
LogWarning("Analytics: SetSessionTimeoutDuration() is not supported and has no effect on Desktop.");
326396
}
327397

328398
Future<std::string> GetAnalyticsInstanceId() {
329-
LogWarning("Analytics: GetAnalyticsInstanceId() is not supported on Desktop.");
330-
if (!g_future_data) {
331-
LogError("Analytics: API not initialized; call Initialize() first.");
332-
static firebase::Future<std::string> invalid_future; // Default invalid
333-
if (!g_future_data) return invalid_future; // Or some other error future
399+
FIREBASE_ASSERT_RETURN(Future<std::string>(), internal::IsInitialized());
400+
auto* api = internal::FutureData::Get()->api();
401+
const auto future_handle =
402+
api->SafeAlloc<std::string>(internal::kAnalyticsFnGetAnalyticsInstanceId);
403+
std::string instance_id = std::string("FakeAnalyticsInstanceId");
404+
{
405+
std::stringstream ss;
406+
ss << g_fake_instance_id;
407+
instance_id += ss.str();
334408
}
335-
const auto handle =
336-
g_future_data->CreateFuture(internal::kAnalyticsFn_GetAnalyticsInstanceId, nullptr);
337-
g_future_data->CompleteFuture(handle, 0 /* error_code */, nullptr /* error_message_string */);
338-
return g_future_data->GetFuture<std::string>(handle);
409+
api->CompleteWithResult(future_handle, 0, "", instance_id);
410+
LogWarning("Analytics: GetAnalyticsInstanceId() is not supported on Desktop.");
411+
return Future<std::string>(api, future_handle.get());
339412
}
340413

341414
Future<std::string> GetAnalyticsInstanceIdLastResult() {
342-
if (!g_future_data) {
343-
LogError("Analytics: API not initialized; call Initialize() first.");
344-
static firebase::Future<std::string> invalid_future;
345-
return invalid_future;
346-
}
347-
return g_future_data->LastResult<std::string>(internal::kAnalyticsFn_GetAnalyticsInstanceId);
415+
FIREBASE_ASSERT_RETURN(Future<std::string>(), internal::IsInitialized());
416+
LogWarning("Analytics: GetAnalyticsInstanceIdLastResult() is not supported on Desktop.");
417+
return static_cast<const Future<std::string>&>(
418+
internal::FutureData::Get()->api()->LastResult(
419+
internal::kAnalyticsFnGetAnalyticsInstanceId));
348420
}
349421

350422
Future<int64_t> GetSessionId() {
423+
FIREBASE_ASSERT_RETURN(Future<int64_t>(), internal::IsInitialized());
424+
auto* api = internal::FutureData::Get()->api();
425+
const auto future_handle =
426+
api->SafeAlloc<int64_t>(internal::kAnalyticsFnGetSessionId);
427+
int64_t session_id = 0x5E5510171D570BL; // "SESSIONIDSTUB", kinda
428+
api->CompleteWithResult(future_handle, 0, "", session_id);
351429
LogWarning("Analytics: GetSessionId() is not supported on Desktop.");
352-
if (!g_future_data) {
353-
LogError("Analytics: API not initialized; call Initialize() first.");
354-
static firebase::Future<int64_t> invalid_future;
355-
return invalid_future;
356-
}
357-
const auto handle =
358-
g_future_data->CreateFuture(internal::kAnalyticsFn_GetSessionId, nullptr);
359-
g_future_data->CompleteFuture(handle, 0 /* error_code */, nullptr /* error_message_string */);
360-
return g_future_data->GetFuture<int64_t>(handle);
430+
return Future<int64_t>(api, future_handle.get());
361431
}
362432

363433
Future<int64_t> GetSessionIdLastResult() {
364-
if (!g_future_data) {
365-
LogError("Analytics: API not initialized; call Initialize() first.");
366-
static firebase::Future<int64_t> invalid_future;
367-
return invalid_future;
368-
}
369-
return g_future_data->LastResult<int64_t>(internal::kAnalyticsFn_GetSessionId);
434+
FIREBASE_ASSERT_RETURN(Future<int64_t>(), internal::IsInitialized());
435+
LogWarning("Analytics: GetSessionIdLastResult() is not supported on Desktop.");
436+
return static_cast<const Future<int64_t>&>(
437+
internal::FutureData::Get()->api()->LastResult(
438+
internal::kAnalyticsFnGetSessionId));
370439
}
371440

372441
} // namespace analytics

0 commit comments

Comments
 (0)